diff --git a/.changelog/3267.txt b/.changelog/3267.txt new file mode 100644 index 00000000000..57210743759 --- /dev/null +++ b/.changelog/3267.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +`google_service_usage_consumer_quota_override` +``` diff --git a/google/config.go b/google/config.go index ffa26e5b811..048cdee785f 100644 --- a/google/config.go +++ b/google/config.go @@ -108,6 +108,7 @@ type Config struct { RuntimeConfigBasePath string SecurityCenterBasePath string ServiceManagementBasePath string + ServiceUsageBasePath string SourceRepoBasePath string SpannerBasePath string SQLBasePath string @@ -178,8 +179,7 @@ type Config struct { clientServiceMan *servicemanagement.APIService - ServiceUsageBasePath string - clientServiceUsage *serviceusage.Service + clientServiceUsage *serviceusage.Service clientBigQuery *bigquery.Service @@ -242,6 +242,7 @@ var ResourceManagerDefaultBasePath = "https://cloudresourcemanager.googleapis.co var RuntimeConfigDefaultBasePath = "https://runtimeconfig.googleapis.com/v1beta1/" var SecurityCenterDefaultBasePath = "https://securitycenter.googleapis.com/v1/" var ServiceManagementDefaultBasePath = "https://servicemanagement.googleapis.com/v1/" +var ServiceUsageDefaultBasePath = "https://serviceusage.googleapis.com/v1/" var SourceRepoDefaultBasePath = "https://sourcerepo.googleapis.com/v1/" var SpannerDefaultBasePath = "https://spanner.googleapis.com/v1/" var SQLDefaultBasePath = "https://sqladmin.googleapis.com/sql/v1beta4/" @@ -740,6 +741,7 @@ func ConfigureBasePaths(c *Config) { c.RuntimeConfigBasePath = RuntimeConfigDefaultBasePath c.SecurityCenterBasePath = SecurityCenterDefaultBasePath c.ServiceManagementBasePath = ServiceManagementDefaultBasePath + c.ServiceUsageBasePath = ServiceUsageDefaultBasePath c.SourceRepoBasePath = SourceRepoDefaultBasePath c.SpannerBasePath = SpannerDefaultBasePath c.SQLBasePath = SQLDefaultBasePath @@ -760,7 +762,6 @@ func ConfigureBasePaths(c *Config) { c.ResourceManagerV2Beta1BasePath = ResourceManagerV2Beta1DefaultBasePath c.IAMBasePath = IAMDefaultBasePath c.ServiceNetworkingBasePath = ServiceNetworkingDefaultBasePath - c.ServiceUsageBasePath = ServiceUsageDefaultBasePath c.BigQueryBasePath = BigQueryDefaultBasePath c.CloudIoTBasePath = CloudIoTDefaultBasePath c.StorageTransferBasePath = StorageTransferDefaultBasePath diff --git a/google/provider.go b/google/provider.go index 45814b6b606..4c309398cbd 100644 --- a/google/provider.go +++ b/google/provider.go @@ -365,6 +365,14 @@ func Provider() terraform.ResourceProvider { "GOOGLE_SERVICE_MANAGEMENT_CUSTOM_ENDPOINT", }, ServiceManagementDefaultBasePath), }, + "service_usage_custom_endpoint": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateCustomEndpoint, + DefaultFunc: schema.MultiEnvDefaultFunc([]string{ + "GOOGLE_SERVICE_USAGE_CUSTOM_ENDPOINT", + }, ServiceUsageDefaultBasePath), + }, "source_repo_custom_endpoint": { Type: schema.TypeString, Optional: true, @@ -865,6 +873,7 @@ func providerConfigure(d *schema.ResourceData, p *schema.Provider, terraformVers config.RuntimeConfigBasePath = d.Get("runtime_config_custom_endpoint").(string) config.SecurityCenterBasePath = d.Get("security_center_custom_endpoint").(string) config.ServiceManagementBasePath = d.Get("service_management_custom_endpoint").(string) + config.ServiceUsageBasePath = d.Get("service_usage_custom_endpoint").(string) config.SourceRepoBasePath = d.Get("source_repo_custom_endpoint").(string) config.SpannerBasePath = d.Get("spanner_custom_endpoint").(string) config.SQLBasePath = d.Get("sql_custom_endpoint").(string) diff --git a/google/provider_handwritten_endpoint.go b/google/provider_handwritten_endpoint.go index f65b33c50ca..563efd444d1 100644 --- a/google/provider_handwritten_endpoint.go +++ b/google/provider_handwritten_endpoint.go @@ -160,7 +160,6 @@ var ServiceNetworkingCustomEndpointEntry = &schema.Schema{ }, ServiceNetworkingDefaultBasePath), } -var ServiceUsageDefaultBasePath = "https://serviceusage.googleapis.com/v1/" var ServiceUsageCustomEndpointEntryKey = "service_usage_custom_endpoint" var ServiceUsageCustomEndpointEntry = &schema.Schema{ Type: schema.TypeString, diff --git a/google/resource_access_context_manager_service_perimeter_resource.go b/google/resource_access_context_manager_service_perimeter_resource.go index 5ea18df90cc..aaa46ef4d2d 100644 --- a/google/resource_access_context_manager_service_perimeter_resource.go +++ b/google/resource_access_context_manager_service_perimeter_resource.go @@ -116,13 +116,15 @@ func resourceAccessContextManagerServicePerimeterResourceCreate(d *schema.Resour return fmt.Errorf("Error waiting to create ServicePerimeterResource: %s", err) } - opRes, err = flattenNestedAccessContextManagerServicePerimeterResource(d, meta, opRes) - if err != nil { - return fmt.Errorf("Error getting nested object from operation response: %s", err) - } - if opRes == nil { - // Object isn't there any more - remove it from the state. - return fmt.Errorf("Error decoding response from operation, could not find nested object") + if _, ok := opRes["status"]; ok { + opRes, err = flattenNestedAccessContextManagerServicePerimeterResource(d, meta, opRes) + if err != nil { + return fmt.Errorf("Error getting nested object from operation response: %s", err) + } + if opRes == nil { + // Object isn't there any more - remove it from the state. + return fmt.Errorf("Error decoding response from operation, could not find nested object") + } } if err := d.Set("resource", flattenAccessContextManagerServicePerimeterResourceResource(opRes["resource"], d, config)); err != nil { return err @@ -250,7 +252,9 @@ func flattenNestedAccessContextManagerServicePerimeterResource(d *schema.Resourc v, ok = res["resources"] if !ok || v == nil { - return nil, nil + // It's possible that there is only one of these resources and + // that res represents that resource. + v = res } switch v.(type) { diff --git a/google/resource_compute_backend_bucket_signed_url_key.go b/google/resource_compute_backend_bucket_signed_url_key.go index 411422ba45e..c3c49903f02 100644 --- a/google/resource_compute_backend_bucket_signed_url_key.go +++ b/google/resource_compute_backend_bucket_signed_url_key.go @@ -246,7 +246,9 @@ func flattenNestedComputeBackendBucketSignedUrlKey(d *schema.ResourceData, meta v, ok = res["signedUrlKeyNames"] if !ok || v == nil { - return nil, nil + // It's possible that there is only one of these resources and + // that res represents that resource. + v = res } switch v.(type) { diff --git a/google/resource_compute_backend_service_signed_url_key.go b/google/resource_compute_backend_service_signed_url_key.go index e0c88dff0e5..28030c576a6 100644 --- a/google/resource_compute_backend_service_signed_url_key.go +++ b/google/resource_compute_backend_service_signed_url_key.go @@ -246,7 +246,9 @@ func flattenNestedComputeBackendServiceSignedUrlKey(d *schema.ResourceData, meta v, ok = res["signedUrlKeyNames"] if !ok || v == nil { - return nil, nil + // It's possible that there is only one of these resources and + // that res represents that resource. + v = res } switch v.(type) { diff --git a/google/resource_compute_disk_resource_policy_attachment.go b/google/resource_compute_disk_resource_policy_attachment.go index 49a871d1b35..8e28046cb34 100644 --- a/google/resource_compute_disk_resource_policy_attachment.go +++ b/google/resource_compute_disk_resource_policy_attachment.go @@ -296,7 +296,9 @@ func flattenNestedComputeDiskResourcePolicyAttachment(d *schema.ResourceData, me v, ok = res["resourcePolicies"] if !ok || v == nil { - return nil, nil + // It's possible that there is only one of these resources and + // that res represents that resource. + v = res } switch v.(type) { diff --git a/google/resource_compute_instance_group_named_port.go b/google/resource_compute_instance_group_named_port.go index 6778419e0fe..1f5603faca7 100644 --- a/google/resource_compute_instance_group_named_port.go +++ b/google/resource_compute_instance_group_named_port.go @@ -308,7 +308,9 @@ func flattenNestedComputeInstanceGroupNamedPort(d *schema.ResourceData, meta int v, ok = res["namedPorts"] if !ok || v == nil { - return nil, nil + // It's possible that there is only one of these resources and + // that res represents that resource. + v = res } switch v.(type) { diff --git a/google/resource_compute_network_endpoint.go b/google/resource_compute_network_endpoint.go index c6742ec3c6c..4ffbbcd2851 100644 --- a/google/resource_compute_network_endpoint.go +++ b/google/resource_compute_network_endpoint.go @@ -347,7 +347,9 @@ func flattenNestedComputeNetworkEndpoint(d *schema.ResourceData, meta interface{ v, ok = res["items"] if !ok || v == nil { - return nil, nil + // It's possible that there is only one of these resources and + // that res represents that resource. + v = res } switch v.(type) { diff --git a/google/resource_compute_network_peering_routes_config.go b/google/resource_compute_network_peering_routes_config.go index 8859dc173ac..d3961092625 100644 --- a/google/resource_compute_network_peering_routes_config.go +++ b/google/resource_compute_network_peering_routes_config.go @@ -320,7 +320,9 @@ func flattenNestedComputeNetworkPeeringRoutesConfig(d *schema.ResourceData, meta v, ok = res["peerings"] if !ok || v == nil { - return nil, nil + // It's possible that there is only one of these resources and + // that res represents that resource. + v = res } switch v.(type) { diff --git a/google/resource_compute_region_disk_resource_policy_attachment.go b/google/resource_compute_region_disk_resource_policy_attachment.go index 9aa5b012207..54abf96ab1c 100644 --- a/google/resource_compute_region_disk_resource_policy_attachment.go +++ b/google/resource_compute_region_disk_resource_policy_attachment.go @@ -280,7 +280,9 @@ func flattenNestedComputeRegionDiskResourcePolicyAttachment(d *schema.ResourceDa v, ok = res["resourcePolicies"] if !ok || v == nil { - return nil, nil + // It's possible that there is only one of these resources and + // that res represents that resource. + v = res } switch v.(type) { diff --git a/google/resource_compute_router_bgp_peer.go b/google/resource_compute_router_bgp_peer.go index 20bba1101f6..a6594052fb8 100644 --- a/google/resource_compute_router_bgp_peer.go +++ b/google/resource_compute_router_bgp_peer.go @@ -634,7 +634,9 @@ func flattenNestedComputeRouterBgpPeer(d *schema.ResourceData, meta interface{}, v, ok = res["bgpPeers"] if !ok || v == nil { - return nil, nil + // It's possible that there is only one of these resources and + // that res represents that resource. + v = res } switch v.(type) { diff --git a/google/resource_compute_router_nat.go b/google/resource_compute_router_nat.go index 48e7539fd45..13eca45c03f 100644 --- a/google/resource_compute_router_nat.go +++ b/google/resource_compute_router_nat.go @@ -1000,7 +1000,9 @@ func flattenNestedComputeRouterNat(d *schema.ResourceData, meta interface{}, res v, ok = res["nats"] if !ok || v == nil { - return nil, nil + // It's possible that there is only one of these resources and + // that res represents that resource. + v = res } switch v.(type) { diff --git a/google/resource_google_project.go b/google/resource_google_project.go index 49f843f9b92..f1434177a19 100644 --- a/google/resource_google_project.go +++ b/google/resource_google_project.go @@ -561,7 +561,7 @@ func doEnableServicesRequest(services []string, project string, config *Config, return errwrap.Wrapf("failed to send enable services request: {{err}}", err) } // Poll for the API to return - waitErr := serviceUsageOperationWait(config, op, fmt.Sprintf("Enable Project %q Services: %+v", project, services)) + waitErr := serviceUsageOperationWait(config, op, project, fmt.Sprintf("Enable Project %q Services: %+v", project, services)) if waitErr != nil { return waitErr } diff --git a/google/resource_google_project_service.go b/google/resource_google_project_service.go index d1545826204..d015200f4c2 100644 --- a/google/resource_google_project_service.go +++ b/google/resource_google_project_service.go @@ -215,7 +215,7 @@ func disableServiceUsageProjectService(service, project string, d *schema.Resour return err } // Wait for the operation to complete - waitErr := serviceUsageOperationWait(config, sop, "api to disable") + waitErr := serviceUsageOperationWait(config, sop, project, "api to disable") if waitErr != nil { return waitErr } diff --git a/google/resource_resource_manager_lien.go b/google/resource_resource_manager_lien.go index 1f40107eafd..d3fc5c797d8 100644 --- a/google/resource_resource_manager_lien.go +++ b/google/resource_resource_manager_lien.go @@ -317,7 +317,9 @@ func flattenNestedResourceManagerLien(d *schema.ResourceData, meta interface{}, v, ok = res["liens"] if !ok || v == nil { - return nil, nil + // It's possible that there is only one of these resources and + // that res represents that resource. + v = res } switch v.(type) { diff --git a/google/resource_spanner_database.go b/google/resource_spanner_database.go index d4bfc917a2e..9072194231f 100644 --- a/google/resource_spanner_database.go +++ b/google/resource_spanner_database.go @@ -150,6 +150,7 @@ func resourceSpannerDatabaseCreate(d *schema.ResourceData, meta interface{}) err if opRes == nil { return fmt.Errorf("Error decoding response from operation, could not find object") } + if err := d.Set("name", flattenSpannerDatabaseName(opRes["name"], d, config)); err != nil { return err } diff --git a/google/resource_spanner_instance.go b/google/resource_spanner_instance.go index 0314254737f..405da655675 100644 --- a/google/resource_spanner_instance.go +++ b/google/resource_spanner_instance.go @@ -184,6 +184,7 @@ func resourceSpannerInstanceCreate(d *schema.ResourceData, meta interface{}) err if opRes == nil { return fmt.Errorf("Error decoding response from operation, could not find object") } + if err := d.Set("name", flattenSpannerInstanceName(opRes["name"], d, config)); err != nil { return err } diff --git a/google/resource_vpc_access_connector.go b/google/resource_vpc_access_connector.go index 84db3d73992..bed5147f2f5 100644 --- a/google/resource_vpc_access_connector.go +++ b/google/resource_vpc_access_connector.go @@ -182,6 +182,7 @@ func resourceVPCAccessConnectorCreate(d *schema.ResourceData, meta interface{}) if opRes == nil { return fmt.Errorf("Error decoding response from operation, could not find object") } + if err := d.Set("name", flattenVPCAccessConnectorName(opRes["name"], d, config)); err != nil { return err } diff --git a/google/service_usage_operation.go b/google/service_usage_operation.go new file mode 100644 index 00000000000..1ac2ce1d980 --- /dev/null +++ b/google/service_usage_operation.go @@ -0,0 +1,71 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- +package google + +import ( + "encoding/json" + "fmt" +) + +type ServiceUsageOperationWaiter struct { + Config *Config + Project string + CommonOperationWaiter +} + +func (w *ServiceUsageOperationWaiter) QueryOp() (interface{}, error) { + if w == nil { + return nil, fmt.Errorf("Cannot query operation, it's unset or nil.") + } + // Returns the proper get. + url := fmt.Sprintf("https://serviceusage.googleapis.com/v1/%s", w.CommonOperationWaiter.Op.Name) + return sendRequest(w.Config, "GET", w.Project, url, nil) +} + +func createServiceUsageWaiter(config *Config, op map[string]interface{}, project, activity string) (*ServiceUsageOperationWaiter, error) { + if val, ok := op["name"]; !ok || val == "" { + // This was a synchronous call - there is no operation to wait for. + return nil, nil + } + w := &ServiceUsageOperationWaiter{ + Config: config, + Project: project, + } + if err := w.CommonOperationWaiter.SetOp(op); err != nil { + return nil, err + } + return w, nil +} + +// nolint: deadcode,unused +func serviceUsageOperationWaitTimeWithResponse(config *Config, op map[string]interface{}, response *map[string]interface{}, project, activity string, timeoutMinutes int) error { + w, err := createServiceUsageWaiter(config, op, project, activity) + if err != nil || w == nil { + // If w is nil, the op was synchronous. + return err + } + if err := OperationWait(w, activity, timeoutMinutes, config.PollInterval); err != nil { + return err + } + return json.Unmarshal([]byte(w.CommonOperationWaiter.Op.Response), response) +} + +func serviceUsageOperationWaitTime(config *Config, op map[string]interface{}, project, activity string, timeoutMinutes int) error { + w, err := createServiceUsageWaiter(config, op, project, activity) + if err != nil || w == nil { + // If w is nil, the op was synchronous. + return err + } + return OperationWait(w, activity, timeoutMinutes, config.PollInterval) +} diff --git a/google/serviceusage_operation.go b/google/serviceusage_operation.go index 53ed57679d6..3f2bdf35f34 100644 --- a/google/serviceusage_operation.go +++ b/google/serviceusage_operation.go @@ -1,42 +1,24 @@ package google import ( - "fmt" + "encoding/json" "google.golang.org/api/googleapi" "google.golang.org/api/serviceusage/v1" ) -type ServiceUsageOperationWaiter struct { - Service *serviceusage.Service - CommonOperationWaiter -} - -func (w *ServiceUsageOperationWaiter) QueryOp() (interface{}, error) { - if w == nil { - return nil, fmt.Errorf("Cannot query operation, it's unset or nil.") - } - - var op *serviceusage.Operation - err := retryTimeDuration(func() (opErr error) { - op, opErr = w.Service.Operations.Get(w.Op.Name).Do() - return handleServiceUsageRetryableError(opErr) - }, DefaultRequestTimeout) - return op, err -} - -func serviceUsageOperationWait(config *Config, op *serviceusage.Operation, activity string) error { - return serviceUsageOperationWaitTime(config, op, activity, 10) -} - -func serviceUsageOperationWaitTime(config *Config, op *serviceusage.Operation, activity string, timeoutMinutes int) error { - w := &ServiceUsageOperationWaiter{ - Service: config.clientServiceUsage, +func serviceUsageOperationWait(config *Config, op *serviceusage.Operation, project, activity string) error { + // maintained for compatibility with old code that was written before the + // autogenerated waiters. + b, err := op.MarshalJSON() + if err != nil { + return err } - if err := w.SetOp(op); err != nil { + var m map[string]interface{} + if err := json.Unmarshal(b, &m); err != nil { return err } - return OperationWait(w, activity, timeoutMinutes, config.PollInterval) + return serviceUsageOperationWaitTime(config, m, project, activity, 10) } func handleServiceUsageRetryableError(err error) error {