<commit_before>package google

import (
	"bytes"
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/hashicorp/terraform/helper/resource"

	computeBeta "google.golang.org/api/compute/v0.beta"
	"google.golang.org/api/compute/v1"
)

type ComputeOperationWaiter struct {
	Service *compute.Service
	Op      *compute.Operation
	Project string
}

func (w *ComputeOperationWaiter) RefreshFunc() resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		var op *compute.Operation
		var err error

		if w.Op.Zone != "" {
			zoneURLParts := strings.Split(w.Op.Zone, "/")
			zone := zoneURLParts[len(zoneURLParts)-1]
			op, err = w.Service.ZoneOperations.Get(w.Project, zone, w.Op.Name).Do()
		} else if w.Op.Region != "" {
			regionURLParts := strings.Split(w.Op.Region, "/")
			region := regionURLParts[len(regionURLParts)-1]
			op, err = w.Service.RegionOperations.Get(w.Project, region, w.Op.Name).Do()
		} else {
			op, err = w.Service.GlobalOperations.Get(w.Project, w.Op.Name).Do()
		}
		if err != nil {
			return nil, "", err
		}

		log.Printf("[DEBUG] Got %q when asking for operation %q", op.Status, w.Op.Name)
		return op, op.Status, nil
	}
}

func (w *ComputeOperationWaiter) Conf() *resource.StateChangeConf {
	return &resource.StateChangeConf{
		Pending: []string{"PENDING", "RUNNING"},
		Target:  []string{"DONE"},
		Refresh: w.RefreshFunc(),
	}
}

// ComputeOperationError wraps compute.OperationError and implements the
// error interface so it can be returned.
type ComputeOperationError compute.OperationError

func (e ComputeOperationError) Error() string {
	var buf bytes.Buffer
	for _, err := range e.Errors {
		buf.WriteString(err.Message + "\n")
	}

	return buf.String()
}

func computeOperationWait(config *Config, op *compute.Operation, project, activity string) error {
	return computeOperationWaitTime(config, op, project, activity, 4)
}

func computeOperationWaitTime(config *Config, op *compute.Operation, project, activity string, timeoutMin int) error {
	w := &ComputeOperationWaiter{
		Service: config.clientCompute,
		Op:      op,
		Project: project,
	}

	state := w.Conf()
	state.Delay = 10 * time.Second
	state.Timeout = time.Duration(timeoutMin) * time.Minute
	state.MinTimeout = 2 * time.Second
	opRaw, err := state.WaitForState()
	if err != nil {
		return fmt.Errorf("Error waiting for %s: %s", activity, err)
	}

	resultOp := opRaw.(*compute.Operation)
	if resultOp.Error != nil {
		return ComputeOperationError(*resultOp.Error)
	}

	return nil
}

func computeBetaOperationWaitTime(config *Config, op *computeBeta.Operation, project, activity string, timeoutMin int) error {
	opV1 := &compute.Operation{}
	err := Convert(op, opV1)
	if err != nil {
		return err
	}

	return computeOperationWaitTime(config, opV1, project, activity, 4)
}<commit_msg>computeBetaOperationWaitTime doesn't use the timeoutMin properly (#425)<commit_after>package google

import (
	"bytes"
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/hashicorp/terraform/helper/resource"

	computeBeta "google.golang.org/api/compute/v0.beta"
	"google.golang.org/api/compute/v1"
)

type ComputeOperationWaiter struct {
	Service *compute.Service
	Op      *compute.Operation
	Project string
}

func (w *ComputeOperationWaiter) RefreshFunc() resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		var op *compute.Operation
		var err error

		if w.Op.Zone != "" {
			zoneURLParts := strings.Split(w.Op.Zone, "/")
			zone := zoneURLParts[len(zoneURLParts)-1]
			op, err = w.Service.ZoneOperations.Get(w.Project, zone, w.Op.Name).Do()
		} else if w.Op.Region != "" {
			regionURLParts := strings.Split(w.Op.Region, "/")
			region := regionURLParts[len(regionURLParts)-1]
			op, err = w.Service.RegionOperations.Get(w.Project, region, w.Op.Name).Do()
		} else {
			op, err = w.Service.GlobalOperations.Get(w.Project, w.Op.Name).Do()
		}
		if err != nil {
			return nil, "", err
		}

		log.Printf("[DEBUG] Got %q when asking for operation %q", op.Status, w.Op.Name)
		return op, op.Status, nil
	}
}

func (w *ComputeOperationWaiter) Conf() *resource.StateChangeConf {
	return &resource.StateChangeConf{
		Pending: []string{"PENDING", "RUNNING"},
		Target:  []string{"DONE"},
		Refresh: w.RefreshFunc(),
	}
}

// ComputeOperationError wraps compute.OperationError and implements the
// error interface so it can be returned.
type ComputeOperationError compute.OperationError

func (e ComputeOperationError) Error() string {
	var buf bytes.Buffer
	for _, err := range e.Errors {
		buf.WriteString(err.Message + "\n")
	}

	return buf.String()
}

func computeOperationWait(config *Config, op *compute.Operation, project, activity string) error {
	return computeOperationWaitTime(config, op, project, activity, 4)
}

func computeOperationWaitTime(config *Config, op *compute.Operation, project, activity string, timeoutMin int) error {
	w := &ComputeOperationWaiter{
		Service: config.clientCompute,
		Op:      op,
		Project: project,
	}

	state := w.Conf()
	state.Delay = 10 * time.Second
	state.Timeout = time.Duration(timeoutMin) * time.Minute
	state.MinTimeout = 2 * time.Second
	opRaw, err := state.WaitForState()
	if err != nil {
		return fmt.Errorf("Error waiting for %s: %s", activity, err)
	}

	resultOp := opRaw.(*compute.Operation)
	if resultOp.Error != nil {
		return ComputeOperationError(*resultOp.Error)
	}

	return nil
}

func computeBetaOperationWaitTime(config *Config, op *computeBeta.Operation, project, activity string, timeoutMin int) error {
	opV1 := &compute.Operation{}
	err := Convert(op, opV1)
	if err != nil {
		return err
	}

	return computeOperationWaitTime(config, opV1, project, activity, timeoutMin)
}
{'fraction_non_alphanumeric': 0.13569530558015944, 'fraction_numerical': 0.004605845881310895, 'mean_word_length': 4.372026641294005, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1524320', 'n_tokens_mistral': 1966, 'n_tokens_neox': 1866, 'n_words': 458}