diff --git a/google-beta/bootstrap_utils_test.go b/google-beta/bootstrap_utils_test.go index 28c5319e98..fcab7f2e1f 100644 --- a/google-beta/bootstrap_utils_test.go +++ b/google-beta/bootstrap_utils_test.go @@ -1,6 +1,7 @@ package google import ( + "context" "fmt" "log" "os" @@ -73,7 +74,7 @@ func BootstrapKMSKeyWithPurposeInLocation(t *testing.T, purpose, locationID stri ConfigureBasePaths(config) - if err := config.LoadAndValidate(); err != nil { + if err := config.LoadAndValidate(context.Background()); err != nil { t.Errorf("Unable to bootstrap KMS key: %s", err) } @@ -213,7 +214,7 @@ func BootstrapServiceAccount(t *testing.T, project, testRunner string) string { ConfigureBasePaths(config) - if err := config.LoadAndValidate(); err != nil { + if err := config.LoadAndValidate(context.Background()); err != nil { t.Fatalf("Bootstrapping failed. Unable to load test config: %s", err) } diff --git a/google-beta/config.go b/google-beta/config.go index 5f35a1ea7f..d225e4abe1 100644 --- a/google-beta/config.go +++ b/google-beta/config.go @@ -68,6 +68,7 @@ type Config struct { RequestTimeout time.Duration client *http.Client + context context.Context terraformVersion string userAgent string @@ -260,7 +261,7 @@ var defaultClientScopes = []string{ "https://www.googleapis.com/auth/userinfo.email", } -func (c *Config) LoadAndValidate() error { +func (c *Config) LoadAndValidate(ctx context.Context) error { if len(c.Scopes) == 0 { c.Scopes = defaultClientScopes } @@ -281,10 +282,9 @@ func (c *Config) LoadAndValidate() error { userAgent := fmt.Sprintf("%s %s", tfUserAgent, providerVersion) c.client = client + c.context = ctx c.userAgent = userAgent - context := context.Background() - // This base path and some others below need the version and possibly more of the path // set on them. The client libraries are inconsistent about which values they need; // while most only want the host URL, some older ones also want the version and some @@ -292,7 +292,7 @@ func (c *Config) LoadAndValidate() error { // the basePath value in the client library file. computeClientBasePath := c.ComputeBasePath + "projects/" log.Printf("[INFO] Instantiating GCE client for path %s", computeClientBasePath) - c.clientCompute, err = compute.NewService(context, option.WithHTTPClient(client)) + c.clientCompute, err = compute.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -301,7 +301,7 @@ func (c *Config) LoadAndValidate() error { computeBetaClientBasePath := c.ComputeBetaBasePath + "projects/" log.Printf("[INFO] Instantiating GCE Beta client for path %s", computeBetaClientBasePath) - c.clientComputeBeta, err = computeBeta.NewService(context, option.WithHTTPClient(client)) + c.clientComputeBeta, err = computeBeta.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -310,7 +310,7 @@ func (c *Config) LoadAndValidate() error { containerClientBasePath := removeBasePathVersion(c.ContainerBasePath) log.Printf("[INFO] Instantiating GKE client for path %s", containerClientBasePath) - c.clientContainer, err = container.NewService(context, option.WithHTTPClient(client)) + c.clientContainer, err = container.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -319,7 +319,7 @@ func (c *Config) LoadAndValidate() error { containerBetaClientBasePath := removeBasePathVersion(c.ContainerBetaBasePath) log.Printf("[INFO] Instantiating GKE Beta client for path %s", containerBetaClientBasePath) - c.clientContainerBeta, err = containerBeta.NewService(context, option.WithHTTPClient(client)) + c.clientContainerBeta, err = containerBeta.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -328,7 +328,7 @@ func (c *Config) LoadAndValidate() error { dnsClientBasePath := c.DNSBasePath + "projects/" log.Printf("[INFO] Instantiating Google Cloud DNS client for path %s", dnsClientBasePath) - c.clientDns, err = dns.NewService(context, option.WithHTTPClient(client)) + c.clientDns, err = dns.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -337,7 +337,7 @@ func (c *Config) LoadAndValidate() error { dnsBetaClientBasePath := c.DnsBetaBasePath + "projects/" log.Printf("[INFO] Instantiating Google Cloud DNS Beta client for path %s", dnsBetaClientBasePath) - c.clientDnsBeta, err = dnsBeta.NewService(context, option.WithHTTPClient(client)) + c.clientDnsBeta, err = dnsBeta.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -346,7 +346,7 @@ func (c *Config) LoadAndValidate() error { kmsClientBasePath := removeBasePathVersion(c.KMSBasePath) log.Printf("[INFO] Instantiating Google Cloud KMS client for path %s", kmsClientBasePath) - c.clientKms, err = cloudkms.NewService(context, option.WithHTTPClient(client)) + c.clientKms, err = cloudkms.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -355,7 +355,7 @@ func (c *Config) LoadAndValidate() error { loggingClientBasePath := removeBasePathVersion(c.LoggingBasePath) log.Printf("[INFO] Instantiating Google Stackdriver Logging client for path %s", loggingClientBasePath) - c.clientLogging, err = cloudlogging.NewService(context, option.WithHTTPClient(client)) + c.clientLogging, err = cloudlogging.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -364,7 +364,7 @@ func (c *Config) LoadAndValidate() error { storageClientBasePath := c.StorageBasePath log.Printf("[INFO] Instantiating Google Storage client for path %s", storageClientBasePath) - c.clientStorage, err = storage.NewService(context, option.WithHTTPClient(client)) + c.clientStorage, err = storage.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -373,7 +373,7 @@ func (c *Config) LoadAndValidate() error { sqlClientBasePath := c.SQLBasePath log.Printf("[INFO] Instantiating Google SqlAdmin client for path %s", sqlClientBasePath) - c.clientSqlAdmin, err = sqladmin.NewService(context, option.WithHTTPClient(client)) + c.clientSqlAdmin, err = sqladmin.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -382,7 +382,7 @@ func (c *Config) LoadAndValidate() error { pubsubClientBasePath := removeBasePathVersion(c.PubsubBasePath) log.Printf("[INFO] Instantiating Google Pubsub client for path %s", pubsubClientBasePath) - c.clientPubsub, err = pubsub.NewService(context, option.WithHTTPClient(client)) + c.clientPubsub, err = pubsub.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -391,7 +391,7 @@ func (c *Config) LoadAndValidate() error { dataflowClientBasePath := removeBasePathVersion(c.DataflowBasePath) log.Printf("[INFO] Instantiating Google Dataflow client for path %s", dataflowClientBasePath) - c.clientDataflow, err = dataflow.NewService(context, option.WithHTTPClient(client)) + c.clientDataflow, err = dataflow.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -400,7 +400,7 @@ func (c *Config) LoadAndValidate() error { resourceManagerBasePath := removeBasePathVersion(c.ResourceManagerBasePath) log.Printf("[INFO] Instantiating Google Cloud ResourceManager client for path %s", resourceManagerBasePath) - c.clientResourceManager, err = cloudresourcemanager.NewService(context, option.WithHTTPClient(client)) + c.clientResourceManager, err = cloudresourcemanager.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -409,7 +409,7 @@ func (c *Config) LoadAndValidate() error { resourceManagerV2Beta1BasePath := removeBasePathVersion(c.ResourceManagerV2Beta1BasePath) log.Printf("[INFO] Instantiating Google Cloud ResourceManager V client for path %s", resourceManagerV2Beta1BasePath) - c.clientResourceManagerV2Beta1, err = resourceManagerV2Beta1.NewService(context, option.WithHTTPClient(client)) + c.clientResourceManagerV2Beta1, err = resourceManagerV2Beta1.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -418,7 +418,7 @@ func (c *Config) LoadAndValidate() error { runtimeConfigClientBasePath := removeBasePathVersion(c.RuntimeConfigBasePath) log.Printf("[INFO] Instantiating Google Cloud Runtimeconfig client for path %s", runtimeConfigClientBasePath) - c.clientRuntimeconfig, err = runtimeconfig.NewService(context, option.WithHTTPClient(client)) + c.clientRuntimeconfig, err = runtimeconfig.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -427,7 +427,7 @@ func (c *Config) LoadAndValidate() error { iamClientBasePath := removeBasePathVersion(c.IAMBasePath) log.Printf("[INFO] Instantiating Google Cloud IAM client for path %s", iamClientBasePath) - c.clientIAM, err = iam.NewService(context, option.WithHTTPClient(client)) + c.clientIAM, err = iam.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -436,7 +436,7 @@ func (c *Config) LoadAndValidate() error { iamCredentialsClientBasePath := removeBasePathVersion(c.IamCredentialsBasePath) log.Printf("[INFO] Instantiating Google Cloud IAMCredentials client for path %s", iamCredentialsClientBasePath) - c.clientIamCredentials, err = iamcredentials.NewService(context, option.WithHTTPClient(client)) + c.clientIamCredentials, err = iamcredentials.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -445,7 +445,7 @@ func (c *Config) LoadAndValidate() error { iapClientBasePath := removeBasePathVersion(c.IAPBasePath) log.Printf("[INFO] Instantiating IAP client for path %s", iapClientBasePath) - c.clientIAP, err = iap.NewService(context, option.WithHTTPClient(client)) + c.clientIAP, err = iap.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -454,7 +454,7 @@ func (c *Config) LoadAndValidate() error { serviceManagementClientBasePath := removeBasePathVersion(c.ServiceManagementBasePath) log.Printf("[INFO] Instantiating Google Cloud Service Management client for path %s", serviceManagementClientBasePath) - c.clientServiceMan, err = servicemanagement.NewService(context, option.WithHTTPClient(client)) + c.clientServiceMan, err = servicemanagement.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -463,7 +463,7 @@ func (c *Config) LoadAndValidate() error { serviceUsageClientBasePath := removeBasePathVersion(c.ServiceUsageBasePath) log.Printf("[INFO] Instantiating Google Cloud Service Usage client for path %s", serviceUsageClientBasePath) - c.clientServiceUsage, err = serviceusage.NewService(context, option.WithHTTPClient(client)) + c.clientServiceUsage, err = serviceusage.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -472,7 +472,7 @@ func (c *Config) LoadAndValidate() error { cloudBillingClientBasePath := removeBasePathVersion(c.CloudBillingBasePath) log.Printf("[INFO] Instantiating Google Cloud Billing client for path %s", cloudBillingClientBasePath) - c.clientBilling, err = cloudbilling.NewService(context, option.WithHTTPClient(client)) + c.clientBilling, err = cloudbilling.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -481,7 +481,7 @@ func (c *Config) LoadAndValidate() error { cloudBuildClientBasePath := removeBasePathVersion(c.CloudBuildBasePath) log.Printf("[INFO] Instantiating Google Cloud Build client for path %s", cloudBuildClientBasePath) - c.clientBuild, err = cloudbuild.NewService(context, option.WithHTTPClient(client)) + c.clientBuild, err = cloudbuild.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -490,7 +490,7 @@ func (c *Config) LoadAndValidate() error { bigQueryClientBasePath := c.BigQueryBasePath log.Printf("[INFO] Instantiating Google Cloud BigQuery client for path %s", bigQueryClientBasePath) - c.clientBigQuery, err = bigquery.NewService(context, option.WithHTTPClient(client)) + c.clientBigQuery, err = bigquery.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -499,7 +499,7 @@ func (c *Config) LoadAndValidate() error { cloudFunctionsClientBasePath := removeBasePathVersion(c.CloudFunctionsBasePath) log.Printf("[INFO] Instantiating Google Cloud CloudFunctions Client for path %s", cloudFunctionsClientBasePath) - c.clientCloudFunctions, err = cloudfunctions.NewService(context, option.WithHTTPClient(client)) + c.clientCloudFunctions, err = cloudfunctions.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -514,7 +514,7 @@ func (c *Config) LoadAndValidate() error { bigtableAdminBasePath := removeBasePathVersion(c.BigtableAdminBasePath) log.Printf("[INFO] Instantiating Google Cloud BigtableAdmin for path %s", bigtableAdminBasePath) - clientBigtable, err := bigtableadmin.NewService(context, option.WithHTTPClient(client)) + clientBigtable, err := bigtableadmin.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -524,7 +524,7 @@ func (c *Config) LoadAndValidate() error { sourceRepoClientBasePath := removeBasePathVersion(c.SourceRepoBasePath) log.Printf("[INFO] Instantiating Google Cloud Source Repo client for path %s", sourceRepoClientBasePath) - c.clientSourceRepo, err = sourcerepo.NewService(context, option.WithHTTPClient(client)) + c.clientSourceRepo, err = sourcerepo.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -533,7 +533,7 @@ func (c *Config) LoadAndValidate() error { spannerClientBasePath := removeBasePathVersion(c.SpannerBasePath) log.Printf("[INFO] Instantiating Google Cloud Spanner client for path %s", spannerClientBasePath) - c.clientSpanner, err = spanner.NewService(context, option.WithHTTPClient(client)) + c.clientSpanner, err = spanner.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -542,7 +542,7 @@ func (c *Config) LoadAndValidate() error { dataprocClientBasePath := removeBasePathVersion(c.DataprocBasePath) log.Printf("[INFO] Instantiating Google Cloud Dataproc client for path %s", dataprocClientBasePath) - c.clientDataproc, err = dataproc.NewService(context, option.WithHTTPClient(client)) + c.clientDataproc, err = dataproc.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -551,7 +551,7 @@ func (c *Config) LoadAndValidate() error { dataprocBetaClientBasePath := removeBasePathVersion(c.DataprocBetaBasePath) log.Printf("[INFO] Instantiating Google Cloud Dataproc Beta client for path %s", dataprocBetaClientBasePath) - c.clientDataprocBeta, err = dataprocBeta.NewService(context, option.WithHTTPClient(client)) + c.clientDataprocBeta, err = dataprocBeta.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -560,7 +560,7 @@ func (c *Config) LoadAndValidate() error { filestoreClientBasePath := removeBasePathVersion(c.FilestoreBasePath) log.Printf("[INFO] Instantiating Filestore client for path %s", filestoreClientBasePath) - c.clientFilestore, err = file.NewService(context, option.WithHTTPClient(client)) + c.clientFilestore, err = file.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -569,7 +569,7 @@ func (c *Config) LoadAndValidate() error { cloudIoTClientBasePath := removeBasePathVersion(c.CloudIoTBasePath) log.Printf("[INFO] Instantiating Google Cloud IoT Core client for path %s", cloudIoTClientBasePath) - c.clientCloudIoT, err = cloudiot.NewService(context, option.WithHTTPClient(client)) + c.clientCloudIoT, err = cloudiot.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -578,7 +578,7 @@ func (c *Config) LoadAndValidate() error { appEngineClientBasePath := removeBasePathVersion(c.AppEngineBasePath) log.Printf("[INFO] Instantiating App Engine client for path %s", appEngineClientBasePath) - c.clientAppEngine, err = appengine.NewService(context, option.WithHTTPClient(client)) + c.clientAppEngine, err = appengine.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -587,7 +587,7 @@ func (c *Config) LoadAndValidate() error { composerClientBasePath := removeBasePathVersion(c.ComposerBasePath) log.Printf("[INFO] Instantiating Cloud Composer client for path %s", composerClientBasePath) - c.clientComposer, err = composer.NewService(context, option.WithHTTPClient(client)) + c.clientComposer, err = composer.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -596,7 +596,7 @@ func (c *Config) LoadAndValidate() error { serviceNetworkingClientBasePath := removeBasePathVersion(c.ServiceNetworkingBasePath) log.Printf("[INFO] Instantiating Service Networking client for path %s", serviceNetworkingClientBasePath) - c.clientServiceNetworking, err = servicenetworking.NewService(context, option.WithHTTPClient(client)) + c.clientServiceNetworking, err = servicenetworking.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -605,7 +605,7 @@ func (c *Config) LoadAndValidate() error { storageTransferClientBasePath := removeBasePathVersion(c.StorageTransferBasePath) log.Printf("[INFO] Instantiating Google Cloud Storage Transfer client for path %s", storageTransferClientBasePath) - c.clientStorageTransfer, err = storagetransfer.NewService(context, option.WithHTTPClient(client)) + c.clientStorageTransfer, err = storagetransfer.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -615,7 +615,7 @@ func (c *Config) LoadAndValidate() error { healthcareClientBasePath := removeBasePathVersion(c.HealthcareBasePath) log.Printf("[INFO] Instantiating Google Cloud Healthcare client for path %s", healthcareClientBasePath) - c.clientHealthcare, err = healthcare.NewService(context, option.WithHTTPClient(client)) + c.clientHealthcare, err = healthcare.NewService(ctx, option.WithHTTPClient(client)) if err != nil { return err } @@ -624,8 +624,8 @@ func (c *Config) LoadAndValidate() error { c.Region = GetRegionFromRegionSelfLink(c.Region) - c.requestBatcherServiceUsage = NewRequestBatcher("Service Usage", context, c.BatchingConfig) - c.requestBatcherIam = NewRequestBatcher("IAM", context, c.BatchingConfig) + c.requestBatcherServiceUsage = NewRequestBatcher("Service Usage", ctx, c.BatchingConfig) + c.requestBatcherIam = NewRequestBatcher("IAM", ctx, c.BatchingConfig) return nil } diff --git a/google-beta/config_test.go b/google-beta/config_test.go index ae47412e9b..44dbe40922 100644 --- a/google-beta/config_test.go +++ b/google-beta/config_test.go @@ -24,7 +24,7 @@ func TestConfigLoadAndValidate_accountFilePath(t *testing.T) { ConfigureBasePaths(config) - err := config.LoadAndValidate() + err := config.LoadAndValidate(context.Background()) if err != nil { t.Fatalf("error: %v", err) } @@ -43,7 +43,7 @@ func TestConfigLoadAndValidate_accountFileJSON(t *testing.T) { ConfigureBasePaths(config) - err = config.LoadAndValidate() + err = config.LoadAndValidate(context.Background()) if err != nil { t.Fatalf("error: %v", err) } @@ -58,7 +58,7 @@ func TestConfigLoadAndValidate_accountFileJSONInvalid(t *testing.T) { ConfigureBasePaths(config) - if config.LoadAndValidate() == nil { + if config.LoadAndValidate(context.Background()) == nil { t.Fatalf("expected error, but got nil") } } @@ -80,7 +80,7 @@ func TestAccConfigLoadValidate_credentials(t *testing.T) { ConfigureBasePaths(config) - err := config.LoadAndValidate() + err := config.LoadAndValidate(context.Background()) if err != nil { t.Fatalf("error: %v", err) } @@ -118,7 +118,7 @@ func TestAccConfigLoadValidate_accessToken(t *testing.T) { ConfigureBasePaths(config) - err = config.LoadAndValidate() + err = config.LoadAndValidate(context.Background()) if err != nil { t.Fatalf("error: %v", err) } @@ -139,7 +139,7 @@ func TestConfigLoadAndValidate_customScopes(t *testing.T) { ConfigureBasePaths(config) - err := config.LoadAndValidate() + err := config.LoadAndValidate(context.Background()) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -165,7 +165,7 @@ func TestConfigLoadAndValidate_defaultBatchingConfig(t *testing.T) { BatchingConfig: batchCfg, } - err = config.LoadAndValidate() + err = config.LoadAndValidate(context.Background()) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -202,7 +202,7 @@ func TestConfigLoadAndValidate_customBatchingConfig(t *testing.T) { BatchingConfig: batchCfg, } - err = config.LoadAndValidate() + err = config.LoadAndValidate(context.Background()) if err != nil { t.Fatalf("unexpected error: %v", err) } diff --git a/google-beta/container_operation.go b/google-beta/container_operation.go index 99984f0f53..0cffb0d33b 100644 --- a/google-beta/container_operation.go +++ b/google-beta/container_operation.go @@ -1,13 +1,17 @@ package google import ( + "context" + "errors" "fmt" + "log" container "google.golang.org/api/container/v1beta1" ) type ContainerOperationWaiter struct { Service *container.Service + Context context.Context Op *container.Operation Project string Location string @@ -62,6 +66,13 @@ func (w *ContainerOperationWaiter) QueryOp() (interface{}, error) { w.Project, w.Location, w.Op.Name) var op *container.Operation + select { + case <-w.Context.Done(): + log.Println("[WARN] request has been cancelled early") + return op, errors.New("unable to finish polling, context has been cancelled") + default: + // default must be here to keep the previous case from blocking + } err := retryTimeDuration(func() (opErr error) { op, opErr = w.Service.Projects.Locations.Operations.Get(name).Do() return opErr @@ -88,6 +99,7 @@ func (w *ContainerOperationWaiter) TargetStates() []string { func containerOperationWait(config *Config, op *container.Operation, project, location, activity string, timeoutMinutes int) error { w := &ContainerOperationWaiter{ Service: config.clientContainerBeta, + Context: config.context, Op: op, Project: project, Location: location, diff --git a/google-beta/provider.go b/google-beta/provider.go index ec3c55ca6e..b5e5afbd65 100644 --- a/google-beta/provider.go +++ b/google-beta/provider.go @@ -506,7 +506,7 @@ func Provider() terraform.ResourceProvider { // We can therefore assume that if it's missing it's 0.10 or 0.11 terraformVersion = "0.11+compatible" } - return providerConfigure(d, terraformVersion) + return providerConfigure(d, provider, terraformVersion) } return provider @@ -796,7 +796,7 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) { ) } -func providerConfigure(d *schema.ResourceData, terraformVersion string) (interface{}, error) { +func providerConfigure(d *schema.ResourceData, p *schema.Provider, terraformVersion string) (interface{}, error) { config := Config{ Project: d.Get("project").(string), Region: d.Get("region").(string), @@ -895,7 +895,7 @@ func providerConfigure(d *schema.ResourceData, terraformVersion string) (interfa config.StorageTransferBasePath = d.Get(StorageTransferCustomEndpointEntryKey).(string) config.BigtableAdminBasePath = d.Get(BigtableAdminCustomEndpointEntryKey).(string) - if err := config.LoadAndValidate(); err != nil { + if err := config.LoadAndValidate(p.StopContext()); err != nil { return nil, err } diff --git a/google-beta/resource_composer_environment_test.go b/google-beta/resource_composer_environment_test.go index 2d8ff87412..7e40f0fda7 100644 --- a/google-beta/resource_composer_environment_test.go +++ b/google-beta/resource_composer_environment_test.go @@ -1,6 +1,7 @@ package google import ( + "context" "fmt" "testing" @@ -551,7 +552,7 @@ func testSweepComposerResources(region string) error { return fmt.Errorf("error getting shared config for region: %s", err) } - err = config.LoadAndValidate() + err = config.LoadAndValidate(context.Background()) if err != nil { log.Fatalf("error loading: %s", err) } diff --git a/google-beta/resource_compute_instance_migrate_test.go b/google-beta/resource_compute_instance_migrate_test.go index 36aebf40f4..3f04f42d5a 100644 --- a/google-beta/resource_compute_instance_migrate_test.go +++ b/google-beta/resource_compute_instance_migrate_test.go @@ -1,6 +1,7 @@ package google import ( + "context" "fmt" "log" "os" @@ -941,7 +942,7 @@ func getInitializedConfig(t *testing.T) *Config { ConfigureBasePaths(config) - err := config.LoadAndValidate() + err := config.LoadAndValidate(context.Background()) if err != nil { t.Fatal(err) } diff --git a/google-beta/resource_container_cluster.go b/google-beta/resource_container_cluster.go index ad8dab9acc..a7f6bacaa8 100644 --- a/google-beta/resource_container_cluster.go +++ b/google-beta/resource_container_cluster.go @@ -132,6 +132,11 @@ func resourceContainerCluster() *schema.Resource { }, }, + "operation": { + Type: schema.TypeString, + Computed: true, + }, + "location": { Type: schema.TypeString, Optional: true, @@ -1131,6 +1136,18 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er timeoutInMinutes := int(d.Timeout(schema.TimeoutCreate).Minutes()) waitErr := containerOperationWait(config, op, project, location, "creating GKE cluster", timeoutInMinutes) if waitErr != nil { + // Check if the create operation failed because Terraform was prematurely terminated. If it was we can persist the + // operation id to state so that a subsequent refresh of this resource will wait until the operation has terminated + // before attempting to Read the state of the cluster. This allows a graceful resumption of a Create that was killed + // by the upstream Terraform process exiting early such as a sigterm. + select { + case <-config.context.Done(): + log.Printf("[DEBUG] Persisting %s so this operation can be resumed \n", op.Name) + d.Set("operation", op.Name) + return nil + default: + // leaving default case to ensure this is non blocking + } // Try a GET on the cluster so we can see the state in debug logs. This will help classify error states. _, getErr := config.clientContainerBeta.Projects.Locations.Clusters.Get(containerClusterFullName(project, location, clusterName)).Do() if getErr != nil { @@ -1189,6 +1206,19 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro return err } + operation := d.Get("operation").(string) + if operation != "" { + log.Printf("[DEBUG] in progress operation detected at %v, attempting to resume", operation) + op := &containerBeta.Operation{ + Name: operation, + } + d.Set("operation", "") + waitErr := containerOperationWait(config, op, project, location, "resuming GKE cluster", int(d.Timeout(schema.TimeoutCreate).Minutes())) + if waitErr != nil { + return waitErr + } + } + clusterName := d.Get("name").(string) name := containerClusterFullName(project, location, clusterName) cluster, err := config.clientContainerBeta.Projects.Locations.Clusters.Get(name).Do() diff --git a/google-beta/resource_container_cluster_test.go b/google-beta/resource_container_cluster_test.go index f867f17c30..f65ed709fb 100644 --- a/google-beta/resource_container_cluster_test.go +++ b/google-beta/resource_container_cluster_test.go @@ -2,6 +2,7 @@ package google import ( "bytes" + "context" "fmt" "log" "regexp" @@ -27,7 +28,7 @@ func testSweepContainerClusters(region string) error { log.Fatalf("error getting shared config for region: %s", err) } - err = config.LoadAndValidate() + err = config.LoadAndValidate(context.Background()) if err != nil { log.Fatalf("error loading: %s", err) } diff --git a/google-beta/resource_monitoring_group_test.go b/google-beta/resource_monitoring_group_test.go index bd0ff75e5b..25284379fe 100644 --- a/google-beta/resource_monitoring_group_test.go +++ b/google-beta/resource_monitoring_group_test.go @@ -1,6 +1,7 @@ package google import ( + "context" "fmt" "log" "strings" @@ -23,7 +24,7 @@ func testSweepMonitoringGroups(region string) error { log.Fatalf("error getting shared config for region: %s", err) } - err = config.LoadAndValidate() + err = config.LoadAndValidate(context.Background()) if err != nil { log.Fatalf("error loading: %s", err) } diff --git a/google-beta/resource_sql_database_instance_test.go b/google-beta/resource_sql_database_instance_test.go index a2d60ce2bd..5ac15dea3d 100644 --- a/google-beta/resource_sql_database_instance_test.go +++ b/google-beta/resource_sql_database_instance_test.go @@ -1,6 +1,7 @@ package google import ( + "context" "fmt" "log" "strings" @@ -40,7 +41,7 @@ func testSweepDatabases(region string) error { return fmt.Errorf("error getting shared config for region: %s", err) } - err = config.LoadAndValidate() + err = config.LoadAndValidate(context.Background()) if err != nil { log.Fatalf("error loading: %s", err) }