From 124dd0e33a5d934bf27cd2764db835fa7791e4fd Mon Sep 17 00:00:00 2001 From: Luca Prete Date: Mon, 11 Mar 2024 18:32:13 +0100 Subject: [PATCH 01/59] [#15779] Add google_network_security_firewall_endpoint_association resource (#9815) * [#15779] Add google_network_security_firewall_endpoint_association resource * Fixing tests * Fixes * Add test for update --------- Co-authored-by: Luca Prete --- .../FirewallEndpointAssociation.yaml | 122 ++++++++++++++ ...firewall_endpoint_association_basic.tf.erb | 21 +++ ..._firewall_endpoint_association_test.go.erb | 154 ++++++++++++++++++ 3 files changed, 297 insertions(+) create mode 100644 mmv1/products/networksecurity/FirewallEndpointAssociation.yaml create mode 100644 mmv1/templates/terraform/examples/network_security_firewall_endpoint_association_basic.tf.erb create mode 100644 mmv1/third_party/terraform/services/networksecurity/resource_network_security_firewall_endpoint_association_test.go.erb diff --git a/mmv1/products/networksecurity/FirewallEndpointAssociation.yaml b/mmv1/products/networksecurity/FirewallEndpointAssociation.yaml new file mode 100644 index 000000000000..9a49eb7496fb --- /dev/null +++ b/mmv1/products/networksecurity/FirewallEndpointAssociation.yaml @@ -0,0 +1,122 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the 'License'); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an 'AS IS' BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +name: 'FirewallEndpointAssociation' +base_url: '{{parent}}/locations/{{location}}/firewallEndpointAssociations' +create_url: '{{parent}}/locations/{{location}}/firewallEndpointAssociations?firewallEndpointId={{name}}' +self_link: '{{parent}}/locations/{{location}}/firewallEndpointAssociations/{{name}}' +min_version: beta +update_verb: :PATCH +update_mask: true +description: | + Firewall endpoint association links a firewall endpoint to a VPC network in + the same zone. After you define this association, Cloud Firewall forwards the + zonal workload traffic in your VPC network that requires layer 7 inspection to + the attached firewall endpoint. +references: + !ruby/object:Api::Resource::ReferenceLinks + api: 'https://cloud.google.com/firewall/docs/reference/network-security/rest/v1beta1/projects.locations.firewallEndpointAssociations#FirewallEndpointAssociation' + guides: + 'Firewall endpoint overview': 'https://cloud.google.com/firewall/docs/about-firewall-endpoints' + 'Create and associate firewall endpoints': 'https://cloud.google.com/firewall/docs/configure-firewall-endpoints' +async: !ruby/object:Api::OpAsync + include_project: true + operation: !ruby/object:Api::OpAsync::Operation + base_url: '{{op_id}}' + result: !ruby/object:Api::OpAsync::Result + resource_inside_response: true +import_format: [ + '{{%parent}}/locations/{{location}}/firewallEndpointAssociations/{{name}}' +] +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'network_security_firewall_endpoint_association_basic' + primary_resource_id: 'default' + # Handwritten test will take care of creates and updates. + # Firewall endpoint association creation is subjet to firewall endpoint creation which is long and expensive. + skip_test: true + min_version: beta + vars: + resource_name_prefix: 'my-firewall-endpoint' + test_env_vars: + org_id: :ORG_ID + project: :PROJECT_NAME +parameters: + - !ruby/object:Api::Type::String + name: 'name' + required: true + immutable: true + url_param_only: true + description: | + The name of the firewall endpoint association resource. + - !ruby/object:Api::Type::String + name: 'location' + required: true + immutable: true + description: | + The location (zone) of the firewall endpoint association. + url_param_only: true + - !ruby/object:Api::Type::String + name: 'parent' + description: | + The name of the parent this firewall endpoint association belongs to. + Format: projects/{project_id}. + immutable: true + url_param_only: true +properties: + - !ruby/object:Api::Type::String + name: 'firewallEndpoint' + required: true + description: | + The URL of the firewall endpoint that is being associated. + - !ruby/object:Api::Type::String + name: 'network' + required: true + description: | + The URL of the network that is being associated. + - !ruby/object:Api::Type::String + name: 'tlsInspectionPolicy' + description: | + The URL of the TlsInspectionPolicy that is being associated. + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' + description: | + A map of key/value label pairs to assign to the resource. + - !ruby/object:Api::Type::String + name: 'selfLink' + description: | + Server-defined URL of this resource. + output: true + - !ruby/object:Api::Type::Time + name: 'createTime' + description: Time the firewall endpoint was created in UTC. + output: true + - !ruby/object:Api::Type::Time + name: 'updateTime' + description: Time the firewall endpoint was updated in UTC. + output: true + - !ruby/object:Api::Type::Boolean + name: 'reconciling' + description: | + Whether reconciling is in progress, recommended per https://google.aip.dev/128. + output: true + - !ruby/object:Api::Type::Enum + name: 'state' + description: The current state of the endpoint. + output: true + values: + - :ACTIVE + - :CREATING + - :DELETING + - :INACTIVE diff --git a/mmv1/templates/terraform/examples/network_security_firewall_endpoint_association_basic.tf.erb b/mmv1/templates/terraform/examples/network_security_firewall_endpoint_association_basic.tf.erb new file mode 100644 index 000000000000..ce6b59347058 --- /dev/null +++ b/mmv1/templates/terraform/examples/network_security_firewall_endpoint_association_basic.tf.erb @@ -0,0 +1,21 @@ +resource "google_network_security_firewall_endpoint" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + name = "<%= ctx[:vars]['resource_name_prefix'] %>" + parent = "organizations/<%= ctx[:test_env_vars]['org_id'] %>" + location = "us-central1-a" + + labels = { + foo = "bar" + } +} + +resource "google_network_security_firewall_endpoint_association" "<%= ctx[:primary_resource_id] %>_association" { + provider = google-beta + name = "<%= ctx[:vars]['resource_name_prefix'] %>-association" + parent = "projects/<%= ctx[:test_env_vars]['project'] %>" + location = "us-central1-a" + + labels = { + foo = "bar" + } +} diff --git a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_firewall_endpoint_association_test.go.erb b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_firewall_endpoint_association_test.go.erb new file mode 100644 index 000000000000..e10e75113914 --- /dev/null +++ b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_firewall_endpoint_association_test.go.erb @@ -0,0 +1,154 @@ +<% autogen_exception -%> +package networksecurity_test +<% unless version == 'ga' -%> + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" +) + +func TestAccNetworkSecurityFirewallEndpointAssociations_basic(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + orgId := envvar.GetTestOrgFromEnv(t) + randomSuffix := acctest.RandString(t, 10) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckNetworkSecurityFirewallEndpointDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkSecurityFirewallEndpointAssociation_basic(randomSuffix, orgId, ), + }, + { + ResourceName: "google_network_security_firewall_endpoint_association.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccNetworkSecurityFirewallEndpointAssociation_update(randomSuffix, orgId, ), + }, + { + ResourceName: "google_network_security_firewall_endpoint_association.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccNetworkSecurityFirewallEndpointAssociation_basic(randomSuffix string, orgId string) string { + return fmt.Sprintf(` +resource "google_compute_network" "foobar" { + provider = google-beta + name = "tf-test-my-vpc%s" + auto_create_subnetworks = false +} + +resource "google_network_security_firewall_endpoint" "foobar" { + provider = google-beta + name = "tf-test-my-firewall-endpoint%s" + parent = "organizations/%s" + location = "us-central1-a" +} + +# TODO: add tlsInspectionPolicy once resource is ready +resource "google_network_security_firewall_endpoint_association" "foobar" { + provider = google-beta + name = "tf-test-my-firewall-endpoint%s" + parent = "organizations/%s" + location = "us-central1-a" + firewall_endpoint = google_network_security_firewall_endpoint.foobar.id + network = google_compute_network.foobar.id + + labels = { + foo = "bar" + } +} +`, randomSuffix, randomSuffix, orgId, randomSuffix, orgId) +} + +func testAccNetworkSecurityFirewallEndpointAssociation_update(randomSuffix string, orgId string) string { + return fmt.Sprintf(` +resource "google_compute_network" "foobar" { + provider = google-beta + name = "tf-test-my-vpc%s" + auto_create_subnetworks = false +} + +resource "google_network_security_firewall_endpoint" "foobar" { + provider = google-beta + name = "tf-test-my-firewall-endpoint%s" + parent = "organizations/%s" + location = "us-central1-a" +} + +# TODO: add tlsInspectionPolicy once resource is ready +resource "google_network_security_firewall_endpoint_association" "foobar" { + provider = google-beta + name = "tf-test-my-firewall-endpoint%s" + parent = "organizations/%s" + location = "us-central1-a" + firewall_endpoint = google_network_security_firewall_endpoint.foobar.id + network = google_compute_network.foobar.id + + labels = { + foo = "bar-updated" + } +} +`, randomSuffix, randomSuffix, orgId, randomSuffix, orgId) +} + +func testAccCheckNetworkSecurityFirewallEndpointAssociationDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "google_network_security_firewall_endpoint_association" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{NetworkSecurityBasePath}}{{parent}}/locations/{{location}}/firewallEndpointAssociations/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: config.UserAgent, + }) + if err == nil { + return fmt.Errorf("NetworkSecurityFirewallEndpointAssociation still exists at %s", url) + } + } + + return nil + } +} + +<% end -%> From b16ca4a132078fb83a5b7f74239bce06f8376d92 Mon Sep 17 00:00:00 2001 From: Mauricio Alvarez Leon <65101411+BBBmau@users.noreply.github.com> Date: Mon, 11 Mar 2024 10:48:34 -0700 Subject: [PATCH 02/59] update teamcity diff check to run every monday morning also (#10159) --- .github/workflows/teamcity-services-diff-check-weekly.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/teamcity-services-diff-check-weekly.yml b/.github/workflows/teamcity-services-diff-check-weekly.yml index 5d857f0eda90..1d0bf90820c5 100644 --- a/.github/workflows/teamcity-services-diff-check-weekly.yml +++ b/.github/workflows/teamcity-services-diff-check-weekly.yml @@ -7,8 +7,8 @@ on: # Scheduled checks to catch edge cases schedule: - # Every Tuesday morning - - cron: '0 4 * * 2' + # Every Monday and Tuesday morning + - cron: '0 4 * * 1-2' jobs: terraform-provider-google: From 3907a64071e2aece0d26ef2e637e401a85ad1411 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Mon, 11 Mar 2024 12:47:19 -0700 Subject: [PATCH 03/59] Add DisplayName to Product struct (#10161) --- mmv1/api/async.go | 2 +- mmv1/api/product.go | 20 ++++--- mmv1/google/string_utils.go | 111 ++++++++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+), 10 deletions(-) create mode 100644 mmv1/google/string_utils.go diff --git a/mmv1/api/async.go b/mmv1/api/async.go index 55d756fa8312..dc4090fe7663 100644 --- a/mmv1/api/async.go +++ b/mmv1/api/async.go @@ -66,7 +66,7 @@ type Result struct { // Contains information about the result of an Operation - ResourceInsideResponse bool + ResourceInsideResponse bool `yaml:"resource_inside_response"` } // def validate diff --git a/mmv1/api/product.go b/mmv1/api/product.go index d56edeefb9be..bfaed3a19869 100644 --- a/mmv1/api/product.go +++ b/mmv1/api/product.go @@ -15,6 +15,7 @@ package api import ( "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" "golang.org/x/exp/slices" ) @@ -38,6 +39,7 @@ type Product struct { // Name string // Display Name: The full name of the GCP product; eg "Cloud Bigtable" + DisplayName string `yaml:"display_name"` Objects []*Resource @@ -108,15 +110,15 @@ func (p *Product) Validate() { // name.downcase // end -// // The product full name is the "display name" in string form intended for -// // users to read in documentation; "Google Compute Engine", "Cloud Bigtable" -// def display_name -// if @display_name.nil? -// name.space_separated -// else -// @display_name -// end -// end +// The product full name is the "display name" in string form intended for +// users to read in documentation; "Google Compute Engine", "Cloud Bigtable" +func (p Product) GetDisplayName() string { + if p.DisplayName == "" { + return google.SpaceSeparated(p.Name) + } + + return p.DisplayName +} // // Most general version that exists for the product // // If GA is present, use that, else beta, else alpha diff --git a/mmv1/google/string_utils.go b/mmv1/google/string_utils.go new file mode 100644 index 000000000000..264f031893c6 --- /dev/null +++ b/mmv1/google/string_utils.go @@ -0,0 +1,111 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package google + +import ( + "regexp" + "strings" +) + +// // Helper class to process and mutate strings. +// class StringUtils +// // Converts string from camel case to underscore +// def self.underscore(source) +// source.gsub(/::/, '/') +// .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2') +// .gsub(/([a-z\d])([A-Z])/, '\1_\2') +// .tr('-', '_') +// .tr('.', '_') +// .downcase +// end + +// // Converts from PascalCase to Space Separated +// def self.space_separated(source) +// tmp = source.gsub(/([A-Z]+)([A-Z][a-z])/, '\1 \2') +// .gsub(/([a-z\d])([A-Z])/, '\1 \2') +// .downcase +// tmp[0].upcase.concat(tmp[1..]) +// end + +// Converts from PascalCase to Space Separated +// For example, converts "AccessApproval" to "Access Approval" +func SpaceSeparated(source string) string { + tmp := regexp.MustCompile(`([A-Z]+)([A-Z][a-z])`).ReplaceAllString(source, "${1} ${2}") + tmp = regexp.MustCompile(`([a-z\d])([A-Z])`).ReplaceAllString(tmp, "${1} ${2}") + tmp = strings.ToLower(tmp) + tmp = strings.Title(tmp) + return tmp +} + +// // Converts a string to space-separated capitalized words +// def self.title(source) +// ss = space_separated(source) +// ss.gsub(/\b(? policies +// // indices -> indices +// return source if source.end_with?('ies') || source.end_with?('es') + +// // index -> indices +// return "//{source.gsub(/ex$/, '')}ices" if source.end_with?('ex') + +// // mesh -> meshes +// return "//{source}es" if source.end_with?('esh') + +// // key -> keys +// // gateway -> gateways +// return "//{source}s" if source.end_with?('ey') || source.end_with?('ay') + +// // policy -> policies +// return "//{source.gsub(/y$/, '')}ies" if source.end_with?('y') + +// "//{source}s" +// end + +// // Slimmed down version of ActiveSupport::Inflector code +// def self.camelize(term, uppercase_first_letter) +// acronyms_camelize_regex = /^(?:(?=a)b(?=\b|[A-Z_])|\w)/ + +// string = term.to_s +// string = if uppercase_first_letter +// string.sub(/^[a-z\d]*/) { |match| match.capitalize! || match } +// else +// string.sub(acronyms_camelize_regex) { |match| match.downcase! || match } +// end +// // handle snake case +// string.gsub!(/(?:_)([a-z\d]*)/i) do +// word = ::Regexp.last_match(1) +// word.capitalize! || word +// end +// string +// end +// end From 922cc703a5cc9d371a1396bec930869be9d890e9 Mon Sep 17 00:00:00 2001 From: gurankitt <161278508+gurankitt@users.noreply.github.com> Date: Tue, 12 Mar 2024 19:46:38 +0530 Subject: [PATCH 04/59] Add data source for apphub discovered service (#10105) * Add data source for apphub discovered service * Add data source for apphub discovered service' * Add data source for apphub discovered service * resolved comments * retry logic added * add tests and documentation * Corrected tests and added project field in the data source * changed id field * Added random_suffix for the resources created and enabled iam policy and compute api * modified retry logic * Modified schema for the data source, and tests * Removed IAM permission blocks * Add dependency for compute api * Resolve merge conflict * Add time sleep * Modified test function name * Shorten service project name * Add billing account * corrected get env variable function call * Modified project id * Combined time delay * Resolving comments * Remove retry logic and add time sleep for resource ingestion --- .../provider/provider_mmv1_resources.go.erb | 1 + .../data_source_apphub_discovered_service.go | 171 ++++++++++++++++++ ...a_source_apphub_discovered_service_test.go | 128 +++++++++++++ .../d/apphub_discovered_service.html.markdown | 52 ++++++ 4 files changed, 352 insertions(+) create mode 100644 mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_service.go create mode 100644 mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_service_test.go create mode 100644 mmv1/third_party/terraform/website/docs/d/apphub_discovered_service.html.markdown diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb index 33109889347c..0b2bd157e154 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -28,6 +28,7 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_alloydb_supported_database_flags": alloydb.DataSourceAlloydbSupportedDatabaseFlags(), "google_artifact_registry_repository": artifactregistry.DataSourceArtifactRegistryRepository(), "google_app_engine_default_service_account": appengine.DataSourceGoogleAppEngineDefaultServiceAccount(), + "google_apphub_discovered_service": apphub.DataSourceApphubDiscoveredService(), <% unless version == 'ga' -%> "google_backup_dr_management_server": backupdr.DataSourceGoogleCloudBackupDRService(), <% end -%> diff --git a/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_service.go b/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_service.go new file mode 100644 index 000000000000..3efee7c6b6ae --- /dev/null +++ b/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_service.go @@ -0,0 +1,171 @@ +package apphub + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func DataSourceApphubDiscoveredService() *schema.Resource { + return &schema.Resource{ + Read: dataSourceApphubDiscoveredServiceRead, + Schema: map[string]*schema.Schema{ + "project": { + Type: schema.TypeString, + Optional: true, + }, + "location": { + Type: schema.TypeString, + Required: true, + }, + "service_uri": { + Type: schema.TypeString, + Required: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "service_reference": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "uri": { + Type: schema.TypeString, + Computed: true, + }, + "path": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "service_properties": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "gcp_project": { + Type: schema.TypeString, + Computed: true, + }, + "location": { + Type: schema.TypeString, + Computed: true, + }, + "zone": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func dataSourceApphubDiscoveredServiceRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + url, err := tpgresource.ReplaceVars(d, config, "{{ApphubBasePath}}projects/{{project}}/locations/{{location}}/discoveredServices:lookup?uri={{service_uri}}") + if err != nil { + return err + } + + billingProject := "" + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + }) + + if err != nil { + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("ApphubDiscoveredService %q", d.Id()), url) + } + + if err := d.Set("name", flattenApphubDiscoveredServiceName(res["discoveredService"].(map[string]interface{})["name"], d, config)); err != nil { + return fmt.Errorf("Error setting service name: %s", err) + } + + if err := d.Set("service_reference", flattenApphubDiscoveredServiceReference(res["discoveredService"].(map[string]interface{})["serviceReference"], d, config)); err != nil { + return fmt.Errorf("Error setting service reference: %s", err) + } + + if err := d.Set("service_properties", flattenApphubDiscoveredServiceProperties(res["discoveredService"].(map[string]interface{})["serviceProperties"], d, config)); err != nil { + return fmt.Errorf("Error setting service properties: %s", err) + } + + d.SetId(res["discoveredService"].(map[string]interface{})["name"].(string)) + + return nil + +} + +func flattenApphubDiscoveredServiceReference(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["uri"] = flattenApphubDiscoveredServiceDataUri(original["uri"], d, config) + transformed["path"] = flattenApphubDiscoveredServiceDataPath(original["path"], d, config) + return []interface{}{transformed} +} + +func flattenApphubDiscoveredServiceProperties(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["gcp_project"] = flattenApphubDiscoveredServiceDataGcpProject(original["gcpProject"], d, config) + transformed["location"] = flattenApphubDiscoveredServiceDataLocation(original["location"], d, config) + transformed["zone"] = flattenApphubDiscoveredServiceDataZone(original["zone"], d, config) + return []interface{}{transformed} +} + +func flattenApphubDiscoveredServiceName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenApphubDiscoveredServiceDataUri(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenApphubDiscoveredServiceDataPath(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenApphubDiscoveredServiceDataGcpProject(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenApphubDiscoveredServiceDataLocation(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenApphubDiscoveredServiceDataZone(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} diff --git a/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_service_test.go b/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_service_test.go new file mode 100644 index 000000000000..6aaeabd5b908 --- /dev/null +++ b/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_service_test.go @@ -0,0 +1,128 @@ +package apphub_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccDataSourceApphubDiscoveredService_basic(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + "billing_account": envvar.GetTestBillingAccountFromEnv(t), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, + Steps: []resource.TestStep{ + { + Config: testDataSourceApphubDiscoveredService_basic(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.google_apphub_discovered_service.catalog-service", "name"), + ), + }, + }, + }) +} + +func testDataSourceApphubDiscoveredService_basic(context map[string]interface{}) string { + return acctest.Nprintf( + ` +resource "google_project" "service_project" { + project_id ="tf-test-ah-%{random_suffix}" + name = "Service Project" + org_id = "%{org_id}" + billing_account = "%{billing_account}" +} + +# Enable Compute API +resource "google_project_service" "compute_service_project" { + project = google_project.service_project.project_id + service = "compute.googleapis.com" +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_project_service.compute_service_project] + create_duration = "120s" +} + +resource "google_apphub_service_project_attachment" "service_project_attachment" { + service_project_attachment_id = google_project.service_project.project_id + depends_on = [time_sleep.wait_120s] +} + +# discovered service block +data "google_apphub_discovered_service" "catalog-service" { + location = "us-central1" + # ServiceReference | Application Hub | Google Cloud + # Using this reference means that this resource will not be provisioned until the forwarding rule is fully created + service_uri = "//compute.googleapis.com/${google_compute_forwarding_rule.forwarding_rule.id}" + depends_on = [time_sleep.wait_120s_for_resource_ingestion] +} + +# VPC network +resource "google_compute_network" "ilb_network" { + name = "ilb-network-%{random_suffix}" + project = google_project.service_project.project_id + auto_create_subnetworks = false + depends_on = [time_sleep.wait_120s] +} + +# backend subnet +resource "google_compute_subnetwork" "ilb_subnet" { + name = "ilb-subnet-%{random_suffix}" + project = google_project.service_project.project_id + ip_cidr_range = "10.0.1.0/24" + region = "us-central1" + network = google_compute_network.ilb_network.id +} + +# forwarding rule +resource "google_compute_forwarding_rule" "forwarding_rule" { + name = "forwarding-rule-%{random_suffix}" + project = google_project.service_project.project_id + region = "us-central1" + ip_version = "IPV4" + load_balancing_scheme = "INTERNAL" + all_ports = true + backend_service = google_compute_region_backend_service.backend.id + network = google_compute_network.ilb_network.id + subnetwork = google_compute_subnetwork.ilb_subnet.id +} + +resource "time_sleep" "wait_120s_for_resource_ingestion" { + depends_on = [google_compute_forwarding_rule.forwarding_rule] + create_duration = "120s" +} + +# backend service +resource "google_compute_region_backend_service" "backend" { + name = "backend-service-%{random_suffix}" + project = google_project.service_project.project_id + region = "us-central1" + health_checks = [google_compute_health_check.default.id] +} + +# health check +resource "google_compute_health_check" "default" { + name = "health-check-%{random_suffix}" + project = google_project.service_project.project_id + check_interval_sec = 1 + timeout_sec = 1 + + tcp_health_check { + port = "80" + } + depends_on = [time_sleep.wait_120s] +} +`, context) +} diff --git a/mmv1/third_party/terraform/website/docs/d/apphub_discovered_service.html.markdown b/mmv1/third_party/terraform/website/docs/d/apphub_discovered_service.html.markdown new file mode 100644 index 000000000000..272491b8d089 --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/apphub_discovered_service.html.markdown @@ -0,0 +1,52 @@ +--- +subcategory: "Apphub" +description: |- + Get information about a discovered service. +--- + +# google\_apphub\_discovered_service + +Get information about a discovered service from its uri. + + +## Example Usage + + +```hcl +data "google_apphub_discovered_service" "my-service" { + location = "my-location" + service_uri = "my-service-uri" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `project` - The host project of the discovered service. +* `service_uri` - (Required) The uri of the service. +* `location` - (Required) The location of the discovered service. + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `name` - Resource name of a Service. Format: "projects/{host-project-id}/locations/{location}/applications/{application-id}/services/{service-id}". + +* `service_reference` - Reference to an underlying networking resource that can comprise a Service. Structure is [documented below](#nested_service_reference) + +A `service_reference` object would contain the following fields: + +* `uri` - The underlying resource URI. + +* `path` - Additional path under the resource URI. + +* `service_properties` - Properties of an underlying compute resource that can comprise a Service. Structure is [documented below](#nested_service_properties) + +A `service_properties` object would contain the following fields: + +* `gcp_project` - The service project identifier that the underlying cloud resource resides in. + +* `location` - The location that the underlying resource resides in. + +* `zone` - The location that the underlying resource resides in if it is zonal. \ No newline at end of file From dd27044950e3806f23f260a14c04eada189880a0 Mon Sep 17 00:00:00 2001 From: Antoni Zawodny Date: Tue, 12 Mar 2024 15:33:21 +0100 Subject: [PATCH 05/59] Graduate support of GKE Queued Provisioning to GA (#10053) --- .../services/container/resource_container_node_pool.go.erb | 6 ------ .../container/resource_container_node_pool_test.go.erb | 2 -- .../website/docs/r/container_node_pool.html.markdown | 2 +- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.erb b/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.erb index 025ed420fdde..99126aceb3bf 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.erb @@ -207,7 +207,6 @@ var schemaNodePool = map[string]*schema.Schema{ }, }, -<% unless version == 'ga' -%> "queued_provisioning": { Type: schema.TypeList, Optional: true, @@ -225,7 +224,6 @@ var schemaNodePool = map[string]*schema.Schema{ }, }, }, -<% end -%> "max_pods_per_node": &schema.Schema{ Type: schema.TypeInt, @@ -988,7 +986,6 @@ func expandNodePool(d *schema.ResourceData, prefix string) (*container.NodePool, } } -<% unless version == 'ga' -%> if v, ok := d.GetOk(prefix + "queued_provisioning"); ok { if v.([]interface{}) != nil && v.([]interface{})[0] != nil { queued_provisioning := v.([]interface{})[0].(map[string]interface{}) @@ -997,7 +994,6 @@ func expandNodePool(d *schema.ResourceData, prefix string) (*container.NodePool, } } } -<% end -%> if v, ok := d.GetOk(prefix + "max_pods_per_node"); ok { np.MaxPodsConstraint = &container.MaxPodsConstraint{ @@ -1192,7 +1188,6 @@ func flattenNodePool(d *schema.ResourceData, config *transport_tpg.Config, np *c } } -<% unless version == 'ga' -%> if np.QueuedProvisioning != nil { nodePool["queued_provisioning"] = []map[string]interface{}{ { @@ -1200,7 +1195,6 @@ func flattenNodePool(d *schema.ResourceData, config *transport_tpg.Config, np *c }, } } -<% end -%> if np.MaxPodsConstraint != nil { nodePool["max_pods_per_node"] = np.MaxPodsConstraint.MaxPodsPerNode diff --git a/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb b/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb index ec3e852d8ce6..ac04e9501c21 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb @@ -1950,7 +1950,6 @@ resource "google_container_node_pool" "np" { `, cluster, networkName, subnetworkName, policyName, np) } -<% unless version == 'ga' -%> func TestAccContainerNodePool_enableQueuedProvisioning(t *testing.T) { t.Parallel() @@ -2022,7 +2021,6 @@ resource "google_container_node_pool" "np" { } `, cluster, networkName, subnetworkName, np, enabled) } -<% end -%> func TestAccContainerNodePool_threadsPerCore(t *testing.T) { t.Parallel() diff --git a/mmv1/third_party/terraform/website/docs/r/container_node_pool.html.markdown b/mmv1/third_party/terraform/website/docs/r/container_node_pool.html.markdown index 3649ce923de7..cbe26898c6e3 100644 --- a/mmv1/third_party/terraform/website/docs/r/container_node_pool.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/container_node_pool.html.markdown @@ -172,7 +172,7 @@ cluster. * `placement_policy` - (Optional) Specifies a custom placement policy for the nodes. -* `queued_provisioning` - (Optional, Beta) Specifies node pool-level settings of queued provisioning. +* `queued_provisioning` - (Optional) Specifies node pool-level settings of queued provisioning. Structure is [documented below](#nested_queued_provisioning). The `autoscaling` block supports (either total or per zone limits are required): From b24ef479852be21f400329a60156c6e1b6b727f2 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Tue, 12 Mar 2024 14:53:39 +0000 Subject: [PATCH 06/59] Update index page of documentation to link to issue templates for Bugs and FRs (#10160) * Update index page of documentation to link to issue templates for Bugs and FRs * Remove unused param from URL * Remove other unused parameter from URL --- mmv1/third_party/terraform/website/docs/index.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mmv1/third_party/terraform/website/docs/index.html.markdown b/mmv1/third_party/terraform/website/docs/index.html.markdown index fee57ac9c426..d240af80b2cc 100644 --- a/mmv1/third_party/terraform/website/docs/index.html.markdown +++ b/mmv1/third_party/terraform/website/docs/index.html.markdown @@ -91,9 +91,9 @@ experience for you using the Google provider. If you have a bug or feature request without an existing issue -* and an existing resource or field is working in an unexpected way, [file a bug](https://github.com/hashicorp/terraform-provider-google/issues/new?template=bug.md). +* and an existing resource or field is working in an unexpected way, [file a bug](https://github.com/hashicorp/terraform-provider-google/issues/new?labels=bug&template=00_bug.yml). -* and you'd like the provider to support a new resource or field, [file an enhancement/feature request](https://github.com/hashicorp/terraform-provider-google/issues/new?template=enhancement.md). +* and you'd like the provider to support a new resource or field, [file an enhancement/feature request](https://github.com/hashicorp/terraform-provider-google/issues/new?labels=enhancement&template=01_enhancement.yml). The provider maintainers will often use the assignee field on an issue to mark who is working on it. From a6ceb9e3c35210af4ecfaee801958eb7b79ac377 Mon Sep 17 00:00:00 2001 From: praseedhaPK <161299686+praseedhaPK@users.noreply.github.com> Date: Tue, 12 Mar 2024 22:36:36 +0530 Subject: [PATCH 07/59] Add data source for AppHub discovered workload (#10107) * Add data source for Apphub discovered workload * Add data source for Apphub discovered workload * Add data source for Apphub Discovered Workload * Resolved comments * Resolved comments * Resolved comments * Resolved comments * Add tests and documentation for data source discovered workload * Resolved comments and added tests * Resolved comments * Added modifications in tests, data source and documentation * Added modifications in tests, data source and documentation * Added modifications in tests, data source and documentation * Verified tests * Tests Verification * Tests Verification * Updated logic to obtain workload_uri * Updated logic to obtain workload_uri * Resolved comments * Resolved comments * Add billing account and shorten service project name * Add header * Change the project name to start with tf-test * Resolved comments * Lint changes * Removing two sleeps * Removing two sleeps * Modifying documentation * Resolved tests * Resolved comments * Resolved comments * logic modification * Update Retry logic * Update Retry logic * Resolved tests * Adding workload_uri description * Adding workload_uri description --- .../provider/provider_mmv1_resources.go.erb | 1 + .../data_source_apphub_discovered_workload.go | 162 ++++++++++++++++++ ..._source_apphub_discovered_workload_test.go | 145 ++++++++++++++++ .../apphub_discovered_workload.html.markdown | 50 ++++++ 4 files changed, 358 insertions(+) create mode 100644 mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_workload.go create mode 100644 mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_workload_test.go create mode 100644 mmv1/third_party/terraform/website/docs/d/apphub_discovered_workload.html.markdown diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb index 0b2bd157e154..cf84c8032b16 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -27,6 +27,7 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_alloydb_locations": alloydb.DataSourceAlloydbLocations(), "google_alloydb_supported_database_flags": alloydb.DataSourceAlloydbSupportedDatabaseFlags(), "google_artifact_registry_repository": artifactregistry.DataSourceArtifactRegistryRepository(), + "google_apphub_discovered_workload": apphub.DataSourceApphubDiscoveredWorkload(), "google_app_engine_default_service_account": appengine.DataSourceGoogleAppEngineDefaultServiceAccount(), "google_apphub_discovered_service": apphub.DataSourceApphubDiscoveredService(), <% unless version == 'ga' -%> diff --git a/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_workload.go b/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_workload.go new file mode 100644 index 000000000000..1221ddc2c71e --- /dev/null +++ b/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_workload.go @@ -0,0 +1,162 @@ +package apphub + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func DataSourceApphubDiscoveredWorkload() *schema.Resource { + return &schema.Resource{ + Read: dataSourceApphubDiscoveredWorkloadRead, + Schema: map[string]*schema.Schema{ + "project": { + Type: schema.TypeString, + Optional: true, + }, + "location": { + Type: schema.TypeString, + Required: true, + }, + "workload_uri": { + Type: schema.TypeString, + Required: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "workload_reference": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "uri": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "workload_properties": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "gcp_project": { + Type: schema.TypeString, + Computed: true, + }, + "location": { + Type: schema.TypeString, + Computed: true, + }, + "zone": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func dataSourceApphubDiscoveredWorkloadRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + url, err := tpgresource.ReplaceVars(d, config, fmt.Sprintf("{{ApphubBasePath}}projects/{{project}}/locations/{{location}}/discoveredWorkloads:lookup?uri={{workload_uri}}")) + if err != nil { + return err + } + + billingProject := "" + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + }) + + if err != nil { + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("ApphubDiscoveredWorkload %q", d.Id()), url) + } + + if err := d.Set("name", flattenApphubDiscoveredWorkloadName(res["discoveredWorkload"].(map[string]interface{})["name"], d, config)); err != nil { + return fmt.Errorf("Error setting workload name: %s", err) + } + + if err := d.Set("workload_reference", flattenApphubDiscoveredWorkloadReference(res["discoveredWorkload"].(map[string]interface{})["workloadReference"], d, config)); err != nil { + return fmt.Errorf("Error setting service reference: %s", err) + } + + if err := d.Set("workload_properties", flattenApphubDiscoveredWorkloadProperties(res["discoveredWorkload"].(map[string]interface{})["workloadProperties"], d, config)); err != nil { + return fmt.Errorf("Error setting workload properties: %s", err) + } + + d.SetId(res["discoveredWorkload"].(map[string]interface{})["name"].(string)) + + return nil + +} + +func flattenApphubDiscoveredWorkloadReference(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["uri"] = flattenApphubDiscoveredWorkloadDataUri(original["uri"], d, config) + return []interface{}{transformed} +} + +func flattenApphubDiscoveredWorkloadProperties(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["gcp_project"] = flattenApphubDiscoveredWorkloadDataGcpProject(original["gcpProject"], d, config) + transformed["location"] = flattenApphubDiscoveredWorkloadDataLocation(original["location"], d, config) + transformed["zone"] = flattenApphubDiscoveredWorkloadDataZone(original["zone"], d, config) + return []interface{}{transformed} +} + +func flattenApphubDiscoveredWorkloadName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenApphubDiscoveredWorkloadDataUri(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenApphubDiscoveredWorkloadDataGcpProject(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenApphubDiscoveredWorkloadDataLocation(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenApphubDiscoveredWorkloadDataZone(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} diff --git a/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_workload_test.go b/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_workload_test.go new file mode 100644 index 000000000000..c305079251a0 --- /dev/null +++ b/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_workload_test.go @@ -0,0 +1,145 @@ +package apphub_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccDataSourceApphubDiscoveredWorkload_basic(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + "billing_account": envvar.GetTestBillingAccountFromEnv(t), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, + Steps: []resource.TestStep{ + { + Config: testDataSourceApphubDiscoveredWorkload_basic(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.google_apphub_discovered_workload.catalog-workload", "name"), + ), + }, + }, + }) +} + +func testDataSourceApphubDiscoveredWorkload_basic(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_project" "service_project" { + project_id ="tf-test-ah-%{random_suffix}" + name = "Service Project" + org_id = "%{org_id}" + billing_account = "%{billing_account}" +} + +# Enable Compute API +resource "google_project_service" "compute_service_project" { + project = google_project.service_project.project_id + service = "compute.googleapis.com" +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_project_service.compute_service_project] + create_duration = "120s" +} + +resource "google_apphub_service_project_attachment" "service_project_attachment" { + service_project_attachment_id = google_project.service_project.project_id + depends_on = [time_sleep.wait_120s] +} + +data "google_apphub_discovered_workload" "catalog-workload" { + location = "us-central1" + workload_uri = "${replace(google_compute_region_instance_group_manager.mig.instance_group, "https://www.googleapis.com/compute/v1", "//compute.googleapis.com")}" + depends_on = [time_sleep.wait_120s_for_resource_ingestion] +} + +# VPC network +resource "google_compute_network" "ilb_network" { + name = "l7-ilb-network-%{random_suffix}" + project = google_project.service_project.project_id + auto_create_subnetworks = false + depends_on = [time_sleep.wait_120s] +} + +# backend subnet +resource "google_compute_subnetwork" "ilb_subnet" { + name = "l7-ilb-subnetwork-%{random_suffix}" + project = google_project.service_project.project_id + ip_cidr_range = "10.0.1.0/24" + region = "us-central1" + network = google_compute_network.ilb_network.id +} + +resource "time_sleep" "wait_120s_for_resource_ingestion" { + depends_on = [google_compute_region_instance_group_manager.mig] + create_duration = "120s" +} + +# instance template +resource "google_compute_instance_template" "instance_template" { + name = "l7-ilb-mig-template-%{random_suffix}" + project = google_project.service_project.project_id + machine_type = "e2-small" + tags = ["http-server"] + network_interface { + network = google_compute_network.ilb_network.id + subnetwork = google_compute_subnetwork.ilb_subnet.id + access_config { + # add external ip to fetch packages + } + } + disk { + source_image = "debian-cloud/debian-10" + auto_delete = true + boot = true + } + # install nginx and serve a simple web page + metadata = { + startup-script = <<-EOF1 + #! /bin/bash + set -euo pipefail + export DEBIAN_FRONTEND=noninteractive + apt-get update + apt-get install -y nginx-light jq + NAME=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/hostname") + IP=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip") + METADATA=$(curl -f -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/attributes/?recursive=True" | jq 'del(.["startup-script"])') + cat < /var/www/html/index.html +
+      Name: $NAME
+      IP: $IP
+      Metadata: $METADATA
+      
+ EOF + EOF1 + } + lifecycle { + create_before_destroy = true + } +} + +resource "google_compute_region_instance_group_manager" "mig" { + name = "l7-ilb-mig1-%{random_suffix}" + project = google_project.service_project.project_id + region = "us-central1" + version { + instance_template = google_compute_instance_template.instance_template.id + name = "primary" + } + base_instance_name = "vm" + target_size = 2 +} +`, context) +} diff --git a/mmv1/third_party/terraform/website/docs/d/apphub_discovered_workload.html.markdown b/mmv1/third_party/terraform/website/docs/d/apphub_discovered_workload.html.markdown new file mode 100644 index 000000000000..d9fc574eaff0 --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/apphub_discovered_workload.html.markdown @@ -0,0 +1,50 @@ +--- +subcategory: "Apphub" +description: |- + Get information about a discovered workload. +--- + +# google\_apphub\_discovered_workload + +Get information about a discovered workload from its uri. + + +## Example Usage + + +```hcl +data "google_apphub_discovered_workload" "my-workload" { + location = "us-central1" + workload_uri = "my-workload-uri" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `project` - The host project of the discovered workload. +* `workload_uri` - (Required) The uri of the workload (instance group managed by the Instance Group Manager). Example: "//compute.googleapis.com/projects/1/regions/us-east1/instanceGroups/id1" +* `location` - (Required) The location of the discovered workload. + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `name` - Resource name of a Workload. Format: "projects/{host-project-id}/locations/{location}/applications/{application-id}/workloads/{workload-id}". + +* `workload_reference` - Reference to an underlying networking resource that can comprise a Workload. Structure is [documented below](#nested_workload_reference) + +The `workload_reference` block supports: + +* `uri` - The underlying resource URI. + +* `workload_properties` - Properties of an underlying compute resource that can comprise a Workload. Structure is [documented below](#nested_workload_properties) + +The `workload_properties` block supports: + +* `gcp_project` - The service project identifier that the underlying cloud resource resides in. + +* `location` - The location that the underlying resource resides in. + +* `zone` - The location that the underlying resource resides in if it is zonal. From f72682f39d30f1eb3263acf8a6b4c3603ba4acdd Mon Sep 17 00:00:00 2001 From: Charles Leon Date: Tue, 12 Mar 2024 14:24:19 -0700 Subject: [PATCH 08/59] Update Documentation for ACM Service Perimeter resources to reflect Granular Controls group support (#10087) groups Co-authored-by: Charles Leon --- .../ServicePerimeter.yaml | 31 ++++++---- .../ServicePerimeterEgressPolicy.yaml | 4 +- .../ServicePerimeterIngressPolicy.yaml | 6 +- .../ServicePerimeters.yaml | 28 +++++---- ...service_perimeter_granular_controls.tf.erb | 59 +++++++++++++++++++ 5 files changed, 99 insertions(+), 29 deletions(-) create mode 100644 mmv1/templates/terraform/examples/access_context_manager_service_perimeter_granular_controls.tf.erb diff --git a/mmv1/products/accesscontextmanager/ServicePerimeter.yaml b/mmv1/products/accesscontextmanager/ServicePerimeter.yaml index b79c83c666cf..d6b02a13d48d 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeter.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeter.yaml @@ -71,6 +71,9 @@ examples: primary_resource_id: 'service-perimeter' vars: service_perimeter_name: 'restrict_bigquery_dryrun_storage' + - !ruby/object:Provider::Terraform::Examples + name: 'access_context_manager_service_perimeter_granular_controls' + skip_test: true custom_code: !ruby/object:Provider::Terraform::CustomCode encoder: templates/terraform/encoders/access_level_never_send_parent.go.erb custom_import: templates/terraform/custom_import/set_access_policy_parent_from_self_link.go.erb @@ -240,9 +243,10 @@ properties: item_type: Api::Type::String is_set: true description: | - A list of identities that are allowed access through this ingress policy. - Should be in the format of email address. The email address should represent - individual user or service account only. + 'A list of identities that are allowed access through this `IngressPolicy`. + To specify an identity or identity group, use the IAM v1 + format specified [here](https://cloud.google.com/iam/docs/principal-identifiers.md#v1). + The following prefixes are supprted: user, group, serviceAccount, principal, and principalSet.' - !ruby/object:Api::Type::Array name: 'sources' description: | @@ -364,9 +368,10 @@ properties: - !ruby/object:Api::Type::Array name: 'identities' description: | - A list of identities that are allowed access through this `EgressPolicy`. - Should be in the format of email address. The email address should - represent individual user or service account only. + 'A list of identities that are allowed access through this `EgressPolicy`. + To specify an identity or identity group, use the IAM v1 + format specified [here](https://cloud.google.com/iam/docs/principal-identifiers.md#v1). + The following prefixes are supprted: user, group, serviceAccount, principal, and principalSet.' is_set: true item_type: Api::Type::String - !ruby/object:Api::Type::NestedObject @@ -528,9 +533,10 @@ properties: item_type: Api::Type::String is_set: true description: | - A list of identities that are allowed access through this ingress policy. - Should be in the format of email address. The email address should represent - individual user or service account only. + 'A list of identities that are allowed access through this `IngressPolicy`. + To specify an identity or identity group, use the IAM v1 + format specified [here](https://cloud.google.com/iam/docs/principal-identifiers.md#v1). + The following prefixes are supprted: user, group, serviceAccount, principal, and principalSet.' - !ruby/object:Api::Type::Array name: 'sources' description: | @@ -652,9 +658,10 @@ properties: - !ruby/object:Api::Type::Array name: 'identities' description: | - A list of identities that are allowed access through this `EgressPolicy`. - Should be in the format of email address. The email address should - represent individual user or service account only. + 'A list of identities that are allowed access through this `EgressPolicy`. + To specify an identity or identity group, use the IAM v1 + format specified [here](https://cloud.google.com/iam/docs/principal-identifiers.md#v1). + The following prefixes are supprted: user, group, serviceAccount, principal, and principalSet.' item_type: Api::Type::String is_set: true - !ruby/object:Api::Type::NestedObject diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml index 5e46e6770c0d..738ceefd98bd 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml @@ -76,8 +76,8 @@ properties: name: 'identities' description: | A list of identities that are allowed access through this `EgressPolicy`. - Should be in the format of email address. The email address should - represent individual user or service account only. + Should be in the format of an email address. The email address should + represent an individual user, service account, or Google group. item_type: Api::Type::String - !ruby/object:Api::Type::Array name: 'sources' diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml index 8e671e4096ee..195b87db9bfa 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml @@ -78,9 +78,9 @@ properties: name: 'identities' item_type: Api::Type::String description: | - A list of identities that are allowed access through this ingress policy. - Should be in the format of email address. The email address should represent - individual user or service account only. + A list of identities that are allowed access through this `IngressPolicy`. + Should be in the format of an email address. The email address should represent + an individual user, service account, or Google group. - !ruby/object:Api::Type::Array name: 'sources' description: | diff --git a/mmv1/products/accesscontextmanager/ServicePerimeters.yaml b/mmv1/products/accesscontextmanager/ServicePerimeters.yaml index 2b941289d41a..655c3545a2e6 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeters.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeters.yaml @@ -220,9 +220,10 @@ properties: is_set: true item_type: Api::Type::String description: | - A list of identities that are allowed access through this ingress policy. - Should be in the format of email address. The email address should represent - individual user or service account only. + 'A list of identities that are allowed access through this `IngressPolicy`. + To specify an identity or identity group, use the IAM v1 format + specified [here](https://cloud.google.com/iam/docs/principal-identifiers.md#v1). + The following prefixes are supprted: user, group, serviceAccount, principal, and principalSet.' - !ruby/object:Api::Type::Array name: 'sources' description: | @@ -329,9 +330,10 @@ properties: - !ruby/object:Api::Type::Array name: 'identities' description: | - A list of identities that are allowed access through this `EgressPolicy`. - Should be in the format of email address. The email address should - represent individual user or service account only. + 'A list of identities that are allowed access through this `EgressPolicy`. + To specify an identity or identity group, use the IAM v1 format + specified [here](https://cloud.google.com/iam/docs/principal-identifiers.md#v1). + The following prefixes are supprted: user, group, serviceAccount, principal, and principalSet.' is_set: true item_type: Api::Type::String - !ruby/object:Api::Type::Array @@ -514,9 +516,10 @@ properties: is_set: true item_type: Api::Type::String description: | - A list of identities that are allowed access through this ingress policy. - Should be in the format of email address. The email address should represent - individual user or service account only. + 'A list of identities that are allowed access through this `IngressPolicy`. + To specify an identity or identity group, use the IAM v1 format + specified [here](https://cloud.google.com/iam/docs/principal-identifiers.md#v1). + The following prefixes are supprted: user, group, serviceAccount, principal, and principalSet.' - !ruby/object:Api::Type::Array name: 'sources' description: | @@ -623,9 +626,10 @@ properties: - !ruby/object:Api::Type::Array name: 'identities' description: | - A list of identities that are allowed access through this `EgressPolicy`. - Should be in the format of email address. The email address should - represent individual user or service account only. + 'A list of identities that are allowed access through this `EgressPolicy`. + To specify an identity or identity group, use the IAM v1 format + specified [here](https://cloud.google.com/iam/docs/principal-identifiers.md#v1). + The following prefixes are supprted: user, group, serviceAccount, principal, and principalSet.' item_type: Api::Type::String is_set: true - !ruby/object:Api::Type::Array diff --git a/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_granular_controls.tf.erb b/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_granular_controls.tf.erb new file mode 100644 index 000000000000..728b3a87ca83 --- /dev/null +++ b/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_granular_controls.tf.erb @@ -0,0 +1,59 @@ +resource "google_access_context_manager_access_policy" "access-policy" { + parent = "organizations/123456789" + title = "Policy with Granular Controls Group Support" +} + +resource "google_access_context_manager_service_perimeter" "test-access" { + parent = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}" + name = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}/servicePerimeters/%s" + title = "%s" + perimeter_type = "PERIMETER_TYPE_REGULAR" + status { + restricted_services = ["bigquery.googleapis.com", "storage.googleapis.com"] + + vpc_accessible_services { + enable_restriction = true + allowed_services = ["bigquery.googleapis.com", "storage.googleapis.com"] + } + + ingress_policies { + ingress_from { + sources { + access_level = google_access_context_manager_access_level.test-access.name + } + identities = ["group:database-admins@google.com"] + identities = ["principal://iam.googleapis.com/locations/global/workforcePools/1234/subject/janedoe"] + identities = ["principalSet://iam.googleapis.com/locations/global/workforcePools/1234/*"] + } + + ingress_to { + resources = [ "*" ] + operations { + service_name = "storage.googleapis.com" + + method_selectors { + method = "google.storage.objects.create" + } + } + } + } + + egress_policies { + egress_from { + identities = ["group:database-admins@google.com"] + identities = ["principal://iam.googleapis.com/locations/global/workforcePools/1234/subject/janedoe"] + identities = ["principalSet://iam.googleapis.com/locations/global/workforcePools/1234/*"] + } + egress_to { + resources = [ "*" ] + operations { + service_name = "storage.googleapis.com" + + method_selectors { + method = "google.storage.objects.create" + } + } + } + } + } +} From aba1d05f1ea4bd7e93a485044fa19870bd887ddd Mon Sep 17 00:00:00 2001 From: bcreddy-gcp <123543489+bcreddy-gcp@users.noreply.github.com> Date: Wed, 13 Mar 2024 03:51:15 +0530 Subject: [PATCH 09/59] fix tags cause notebooks instances to recreate (#10179) * add labels to runtime update test * Add labels to ImportStateVerifyIgnore * fix indentation * fix tags cause notebooks instances to create --- mmv1/products/notebooks/Instance.yaml | 1 + .../terraform/constants/notebooks_instance.go | 18 ++++++++++++++++-- .../examples/notebook_instance_full.tf.erb | 3 +++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/mmv1/products/notebooks/Instance.yaml b/mmv1/products/notebooks/Instance.yaml index b5fb92b0c1b1..613c50d70fab 100644 --- a/mmv1/products/notebooks/Instance.yaml +++ b/mmv1/products/notebooks/Instance.yaml @@ -393,6 +393,7 @@ properties: The Compute Engine tags to add to instance. item_type: Api::Type::String default_from_api: true + diff_suppress_func: NotebooksInstanceTagsDiffSuppress - !ruby/object:Api::Type::KeyValuePairs name: 'metadata' description: | diff --git a/mmv1/templates/terraform/constants/notebooks_instance.go b/mmv1/templates/terraform/constants/notebooks_instance.go index 230d2aece282..b1c47a704ffa 100644 --- a/mmv1/templates/terraform/constants/notebooks_instance.go +++ b/mmv1/templates/terraform/constants/notebooks_instance.go @@ -3,8 +3,22 @@ var NotebooksInstanceProvidedScopes = []string{ "https://www.googleapis.com/auth/userinfo.email", } +var NotebooksInstanceProvidedTags = []string{ + "deeplearning-vm", + "notebook-instance", +} + func NotebooksInstanceScopesDiffSuppress(_, _, _ string, d *schema.ResourceData) bool { - old, new := d.GetChange("service_account_scopes") + return NotebooksDiffSuppressTemplate("service_account_scopes", NotebooksInstanceProvidedScopes, d) +} + +func NotebooksInstanceTagsDiffSuppress(_, _, _ string, d *schema.ResourceData) bool { + return NotebooksDiffSuppressTemplate("tags", NotebooksInstanceProvidedTags, d) +} + +func NotebooksDiffSuppressTemplate(field string, defaults []string, d *schema.ResourceData) bool { + old, new := d.GetChange(field) + oldValue := old.([]interface{}) newValue := new.([]interface{}) oldValueList := []string{} @@ -17,7 +31,7 @@ func NotebooksInstanceScopesDiffSuppress(_, _, _ string, d *schema.ResourceData) for _, item := range newValue { newValueList = append(newValueList,item.(string)) } - newValueList= append(newValueList,NotebooksInstanceProvidedScopes...) + newValueList= append(newValueList,defaults...) sort.Strings(oldValueList) sort.Strings(newValueList) diff --git a/mmv1/templates/terraform/examples/notebook_instance_full.tf.erb b/mmv1/templates/terraform/examples/notebook_instance_full.tf.erb index 31f2af55ca3c..31de347bb0c6 100644 --- a/mmv1/templates/terraform/examples/notebook_instance_full.tf.erb +++ b/mmv1/templates/terraform/examples/notebook_instance_full.tf.erb @@ -34,6 +34,9 @@ resource "google_notebooks_instance" "<%= ctx[:primary_resource_id] %>" { "https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/userinfo.email" ] + + tags = ["foo", "bar"] + disk_encryption = "CMEK" kms_key = "<%= ctx[:vars]['key_name'] %>" desired_state = "ACTIVE" From 9779afc017103e7986c2458f5efc77deeb581c2e Mon Sep 17 00:00:00 2001 From: Andrew Grasso Date: Tue, 12 Mar 2024 18:22:53 -0400 Subject: [PATCH 10/59] Documentation Fix compute_security_policy (#9732) Fix mixed up descriptions between request_uri and request_query_param. --- .../website/docs/r/compute_security_policy.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mmv1/third_party/terraform/website/docs/r/compute_security_policy.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_security_policy.html.markdown index 92d2b5ab5b4f..2cf421900b64 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_security_policy.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_security_policy.html.markdown @@ -280,9 +280,9 @@ The following arguments are supported: * `request_cookie` - (Optional) Request cookie whose value will be excluded from inspection during preconfigured WAF evaluation. Structure is [documented below](#nested_field_params). -* `request_uri` - (Optional) Request query parameter whose value will be excluded from inspection during preconfigured WAF evaluation. Note that the parameter can be in the query string or in the POST body. Structure is [documented below](#nested_field_params). +* `request_uri` - (Optional) Request URI from the request line to be excluded from inspection during preconfigured WAF evaluation. When specifying this field, the query or fragment part should be excluded. Structure is [documented below](#nested_field_params). -* `request_query_param` - (Optional) Request URI from the request line to be excluded from inspection during preconfigured WAF evaluation. When specifying this field, the query or fragment part should be excluded. Structure is [documented below](#nested_field_params). +* `request_query_param` - (Optional) Request query parameter whose value will be excluded from inspection during preconfigured WAF evaluation. Note that the parameter can be in the query string or in the POST body. Structure is [documented below](#nested_field_params). * `target_rule_set` - (Required) Target WAF rule set to apply the preconfigured WAF exclusion. From ca62aed93eb3f92e915a5041fb0ab5c32ff99475 Mon Sep 17 00:00:00 2001 From: Esha Goel Date: Wed, 13 Mar 2024 04:43:38 +0530 Subject: [PATCH 11/59] Add new resource Workload for Apphub (#10155) * Add new resource Workload for Apphub * Fix lint error * Add billing account * Remove extra delay from test * Resolve comments * Add handwritten update test * Fix lint error * Add data source changes * Remove merged changes * Remove merged changes * Batch all update tests into one step to make test fast * Add a delay between discovered resource fetch and managed instance group manager creation * Add back org_id * Update region from us-east1 to us-central1 * Use standard diff suppress function --------- Co-authored-by: praseedhaPK <161299686+praseedhaPK@users.noreply.github.com> Co-authored-by: Krishnan Gopal --- mmv1/products/apphub/Workload.yaml | 228 ++++++++++++++++++ .../examples/apphub_workload_basic.tf.erb | 126 ++++++++++ .../examples/apphub_workload_full.tf.erb | 147 +++++++++++ .../apphub/resource_apphub_workload_test.go | 180 ++++++++++++++ 4 files changed, 681 insertions(+) create mode 100644 mmv1/products/apphub/Workload.yaml create mode 100644 mmv1/templates/terraform/examples/apphub_workload_basic.tf.erb create mode 100644 mmv1/templates/terraform/examples/apphub_workload_full.tf.erb create mode 100644 mmv1/third_party/terraform/services/apphub/resource_apphub_workload_test.go diff --git a/mmv1/products/apphub/Workload.yaml b/mmv1/products/apphub/Workload.yaml new file mode 100644 index 000000000000..b0c3466bb2d9 --- /dev/null +++ b/mmv1/products/apphub/Workload.yaml @@ -0,0 +1,228 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +base_url: projects/{{project}}/locations/{{location}}/applications/{{application_id}}/workloads +create_url: projects/{{project}}/locations/{{location}}/applications/{{application_id}}/workloads?workloadId={{workload_id}} +self_link: projects/{{project}}/locations/{{location}}/applications/{{application_id}}/workloads/{{workload_id}} +id_format: projects/{{project}}/locations/{{location}}/applications/{{application_id}}/workloads/{{workload_id}} +import_format: + - projects/{{project}}/locations/{{location}}/applications/{{application_id}}/workloads/{{workload_id}} +name: Workload +description: 'Workload represents a binary deployment (such as Managed Instance Groups (MIGs), GKE deployments, etc.) that performs the smallest logical subset of business functionality. + It registers identified workload to the Application.' +autogen_async: true +examples: + - !ruby/object:Provider::Terraform::Examples + name: "apphub_workload_basic" + pull_external: true + primary_resource_id: "example" + vars: + application_id: "example-application-1" + service_project_attachment_id: "project-1" + ilb_network: "l7-ilb-network" + ilb_subnet: "l7-ilb-subnet" + instance_template: "l7-ilb-mig-template" + mig: "l7-ilb-mig1" + test_env_vars: + org_id: :ORG_ID + billing_account: :BILLING_ACCT + - !ruby/object:Provider::Terraform::Examples + name: "apphub_workload_full" + pull_external: true + primary_resource_id: "example" + vars: + application_id: "example-application-1" + service_project_attachment_id: "project-1" + display_name: "Example Service Full" + description: "Register service for testing" + business_name: "Alice" + business_email: "alice@google.com" + developer_name: "Bob" + developer_email: "bob@google.com" + operator_name: "Charlie" + operator_email: "charlie@google.com" + ilb_network: "l7-ilb-network" + ilb_subnet: "l7-ilb-subnet" + instance_template: "l7-ilb-mig-template" + mig: "l7-ilb-mig1" + test_env_vars: + org_id: :ORG_ID + billing_account: :BILLING_ACCT +async: !ruby/object:Api::OpAsync + operation: !ruby/object:Api::OpAsync::Operation + path: name + base_url: "{{op_id}}" + wait_ms: 1000 + timeouts: + result: !ruby/object:Api::OpAsync::Result + path: response + resource_inside_response: true + status: !ruby/object:Api::OpAsync::Status + path: done + complete: true + allowed: + - true + - false + error: !ruby/object:Api::OpAsync::Error + path: error + message: message +update_verb: :PATCH +update_mask: true +parameters: + - !ruby/object:Api::Type::String + name: location + description: 'Part of `parent`. Full resource name of a parent Application. Example: projects/{HOST_PROJECT_ID}/locations/{LOCATION}/applications/{APPLICATION_ID} ' + url_param_only: true + required: true + immutable: true + - !ruby/object:Api::Type::String + name: applicationId + description: 'Part of `parent`. Full resource name of a parent Application. Example: projects/{HOST_PROJECT_ID}/locations/{LOCATION}/applications/{APPLICATION_ID}' + url_param_only: true + required: true + immutable: true + - !ruby/object:Api::Type::String + name: workloadId + description: 'The Workload identifier. ' + url_param_only: true + required: true + immutable: true +properties: + - !ruby/object:Api::Type::String + name: name + output: true + description: "Identifier. The resource name of the Workload. Format:\"projects/{host-project-id}/locations/{location}/applications/{application-id}/workloads/{workload-id}\" " + - !ruby/object:Api::Type::String + name: displayName + description: 'User-defined name for the Workload. ' + - !ruby/object:Api::Type::String + name: description + description: 'User-defined description of a Workload. ' + - !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: uri + description: 'Output only. The underlying compute resource uri. ' + output: true + output: true + name: workloadReference + description: 'Reference of an underlying compute resource represented by the Workload. ' + - !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: gcpProject + description: "Output only. The service project identifier that the underlying + cloud resource resides in. Empty for non cloud resources. " + output: true + - !ruby/object:Api::Type::String + name: location + description: "Output only. The location that the underlying compute resource resides + in (e.g us-west1). " + output: true + - !ruby/object:Api::Type::String + name: zone + description: "Output only. The location that the underlying compute resource resides + in if it is zonal (e.g us-west1-a). " + output: true + output: true + name: workloadProperties + description: 'Properties of an underlying compute resource represented by the Workload. ' + - !ruby/object:Api::Type::String + name: discoveredWorkload + diff_suppress_func: 'tpgresource.ProjectNumberDiffSuppress' + description: 'Immutable. The resource name of the original discovered workload. ' + required: true + immutable: true + - !ruby/object:Api::Type::NestedObject + name: attributes + description: 'Consumer provided attributes. ' + properties: + - !ruby/object:Api::Type::NestedObject + name: criticality + description: 'Criticality of the Application, Service, or Workload ' + properties: + - !ruby/object:Api::Type::Enum + name: type + description: 'Criticality type. ' + required: true + values: + - :MISSION_CRITICAL + - :HIGH + - :MEDIUM + - :LOW + - !ruby/object:Api::Type::NestedObject + name: environment + description: 'Environment of the Application, Service, or Workload ' + properties: + - !ruby/object:Api::Type::Enum + name: type + description: 'Environment type. ' + required: true + values: + - :PRODUCTION + - :STAGING + - :TEST + - :DEVELOPMENT + - !ruby/object:Api::Type::Array + name: developerOwners + description: 'Developer team that owns development and coding. ' + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: displayName + description: 'Contact''s name. ' + - !ruby/object:Api::Type::String + name: email + description: 'Email address of the contacts. ' + required: true + - !ruby/object:Api::Type::Array + name: operatorOwners + description: 'Operator team that ensures runtime and operations. ' + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: displayName + description: 'Contact''s name. ' + - !ruby/object:Api::Type::String + name: email + description: 'Email address of the contacts. ' + required: true + - !ruby/object:Api::Type::Array + name: businessOwners + description: 'Business team that ensures user needs are met and value is delivered ' + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: displayName + description: 'Contact''s name. ' + - !ruby/object:Api::Type::String + name: email + description: 'Email address of the contacts. ' + required: true + - !ruby/object:Api::Type::String + name: createTime + description: 'Output only. Create time. ' + output: true + - !ruby/object:Api::Type::String + name: updateTime + description: 'Output only. Update time. ' + output: true + - !ruby/object:Api::Type::String + name: uid + description: "Output only. A universally unique identifier (UUID) for the `Workload` in the UUID4 format. " + output: true + - !ruby/object:Api::Type::String + name: state + description: "Output only. Workload state. Possible values: STATE_UNSPECIFIED CREATING ACTIVE DELETING DETACHED" + output: true diff --git a/mmv1/templates/terraform/examples/apphub_workload_basic.tf.erb b/mmv1/templates/terraform/examples/apphub_workload_basic.tf.erb new file mode 100644 index 000000000000..0c9a57b3ce94 --- /dev/null +++ b/mmv1/templates/terraform/examples/apphub_workload_basic.tf.erb @@ -0,0 +1,126 @@ +resource "google_apphub_application" "application" { + location = "us-central1" + application_id = "<%= ctx[:vars]['application_id'] %>" + scope { + type = "REGIONAL" + } +} + +resource "google_project" "service_project" { + project_id ="<%= ctx[:vars]['service_project_attachment_id'] %>" + name = "Service Project" + org_id = "<%= ctx[:test_env_vars]['org_id'] %>" + billing_account = "<%= ctx[:test_env_vars]['billing_account'] %>" +} + +# Enable Compute API +resource "google_project_service" "compute_service_project" { + project = google_project.service_project.project_id + service = "compute.googleapis.com" +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_project_service.compute_service_project] + + create_duration = "120s" +} + +resource "google_apphub_service_project_attachment" "service_project_attachment" { + service_project_attachment_id = google_project.service_project.project_id + depends_on = [time_sleep.wait_120s] +} + + +# Discovered workload +data "google_apphub_discovered_workload" "catalog-workload" { + location = "us-central1" + workload_uri = "${replace(google_compute_region_instance_group_manager.mig.instance_group, "https://www.googleapis.com/compute/v1", "//compute.googleapis.com")}" + depends_on = [time_sleep.wait_120s_for_resource_ingestion] +} + +resource "time_sleep" "wait_120s_for_resource_ingestion" { + depends_on = [google_compute_region_instance_group_manager.mig] + create_duration = "120s" +} + +resource "google_apphub_workload" "<%= ctx[:primary_resource_id] %>" { + location = "us-central1" + application_id = google_apphub_application.application.application_id + workload_id = google_compute_region_instance_group_manager.mig.name + discovered_workload = data.google_apphub_discovered_workload.catalog-workload.name +} + +#Workload creation + + +# VPC network +resource "google_compute_network" "ilb_network" { + name = "<%= ctx[:vars]['ilb_network'] %>" + project = google_project.service_project.project_id + auto_create_subnetworks = false + depends_on = [time_sleep.wait_120s] +} + +# backend subnet +resource "google_compute_subnetwork" "ilb_subnet" { + name = "<%= ctx[:vars]['ilb_subnet'] %>" + project = google_project.service_project.project_id + ip_cidr_range = "10.0.1.0/24" + region = "us-central1" + network = google_compute_network.ilb_network.id +} + +# instance template +resource "google_compute_instance_template" "instance_template" { + name = "<%= ctx[:vars]['instance_template'] %>" + project = google_project.service_project.project_id + machine_type = "e2-small" + tags = ["http-server"] + network_interface { + network = google_compute_network.ilb_network.id + subnetwork = google_compute_subnetwork.ilb_subnet.id + access_config { + # add external ip to fetch packages + } + } + disk { + source_image = "debian-cloud/debian-10" + auto_delete = true + boot = true + } + # install nginx and serve a simple web page + metadata = { + startup-script = <<-EOF1 + #! /bin/bash + set -euo pipefail + export DEBIAN_FRONTEND=noninteractive + apt-get update + apt-get install -y nginx-light jq + NAME=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/hostname") + IP=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip") + METADATA=$(curl -f -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/attributes/?recursive=True" | jq 'del(.["startup-script"])') + cat < /var/www/html/index.html +
+      Name: $NAME
+      IP: $IP
+      Metadata: $METADATA
+      
+ EOF + EOF1 + } + lifecycle { + create_before_destroy = true + } +} + +resource "google_compute_region_instance_group_manager" "mig" { + name = "<%= ctx[:vars]['mig'] %>" + project = google_project.service_project.project_id + region = "us-central1" + version { + instance_template = google_compute_instance_template.instance_template.id + name = "primary" + } + base_instance_name = "vm" + target_size = 2 +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/apphub_workload_full.tf.erb b/mmv1/templates/terraform/examples/apphub_workload_full.tf.erb new file mode 100644 index 000000000000..a81dd6326175 --- /dev/null +++ b/mmv1/templates/terraform/examples/apphub_workload_full.tf.erb @@ -0,0 +1,147 @@ +resource "google_apphub_application" "application" { + location = "us-central1" + application_id = "<%= ctx[:vars]['application_id'] %>" + scope { + type = "REGIONAL" + } +} + +resource "google_project" "service_project" { + project_id ="<%= ctx[:vars]['service_project_attachment_id'] %>" + name = "Service Project" + org_id = "<%= ctx[:test_env_vars]['org_id'] %>" + billing_account = "<%= ctx[:test_env_vars]['billing_account'] %>" +} + +# Enable Compute API +resource "google_project_service" "compute_service_project" { + project = google_project.service_project.project_id + service = "compute.googleapis.com" +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_project_service.compute_service_project] + + create_duration = "120s" +} + +resource "google_apphub_service_project_attachment" "service_project_attachment" { + service_project_attachment_id = google_project.service_project.project_id + depends_on = [time_sleep.wait_120s] +} + +# Discovered workload +data "google_apphub_discovered_workload" "catalog-workload" { + location = "us-central1" + workload_uri = "${replace(google_compute_region_instance_group_manager.mig.instance_group, "https://www.googleapis.com/compute/v1", "//compute.googleapis.com")}" + depends_on = [time_sleep.wait_120s_for_resource_ingestion] +} + +resource "time_sleep" "wait_120s_for_resource_ingestion" { + depends_on = [google_compute_region_instance_group_manager.mig] + create_duration = "120s" +} + +resource "google_apphub_workload" "<%= ctx[:primary_resource_id] %>" { + location = "us-central1" + application_id = google_apphub_application.application.application_id + workload_id = google_compute_region_instance_group_manager.mig.name + discovered_workload = data.google_apphub_discovered_workload.catalog-workload.name + display_name = "<%= ctx[:vars]['display_name'] %>" + description = "<%= ctx[:vars]['description'] %>" + attributes { + environment { + type = "STAGING" + } + criticality { + type = "MISSION_CRITICAL" + } + business_owners { + display_name = "<%= ctx[:vars]['business_name'] %>" + email = "<%= ctx[:vars]['business_email'] %>" + } + developer_owners { + display_name = "<%= ctx[:vars]['developer_name'] %>" + email = "<%= ctx[:vars]['developer_email'] %>" + } + operator_owners { + display_name = "<%= ctx[:vars]['operator_name'] %>" + email = "<%= ctx[:vars]['operator_email'] %>" + } + } +} + +#Workload creation + + +# VPC network +resource "google_compute_network" "ilb_network" { + name = "<%= ctx[:vars]['ilb_network'] %>" + project = google_project.service_project.project_id + auto_create_subnetworks = false + depends_on = [time_sleep.wait_120s] +} + +# backend subnet +resource "google_compute_subnetwork" "ilb_subnet" { + name = "<%= ctx[:vars]['ilb_subnet'] %>" + project = google_project.service_project.project_id + ip_cidr_range = "10.0.1.0/24" + region = "us-central1" + network = google_compute_network.ilb_network.id +} + +# instance template +resource "google_compute_instance_template" "instance_template" { + name = "<%= ctx[:vars]['instance_template'] %>" + project = google_project.service_project.project_id + machine_type = "e2-small" + tags = ["http-server"] + network_interface { + network = google_compute_network.ilb_network.id + subnetwork = google_compute_subnetwork.ilb_subnet.id + access_config { + # add external ip to fetch packages + } + } + disk { + source_image = "debian-cloud/debian-10" + auto_delete = true + boot = true + } + # install nginx and serve a simple web page + metadata = { + startup-script = <<-EOF1 + #! /bin/bash + set -euo pipefail + export DEBIAN_FRONTEND=noninteractive + apt-get update + apt-get install -y nginx-light jq + NAME=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/hostname") + IP=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip") + METADATA=$(curl -f -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/attributes/?recursive=True" | jq 'del(.["startup-script"])') + cat < /var/www/html/index.html +
+      Name: $NAME
+      IP: $IP
+      Metadata: $METADATA
+      
+ EOF + EOF1 + } + lifecycle { + create_before_destroy = true + } +} + +resource "google_compute_region_instance_group_manager" "mig" { + name = "<%= ctx[:vars]['mig'] %>" + project = google_project.service_project.project_id + region = "us-central1" + version { + instance_template = google_compute_instance_template.instance_template.id + name = "primary" + } + base_instance_name = "vm" + target_size = 2 +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/apphub/resource_apphub_workload_test.go b/mmv1/third_party/terraform/services/apphub/resource_apphub_workload_test.go new file mode 100644 index 000000000000..2897307d1a93 --- /dev/null +++ b/mmv1/third_party/terraform/services/apphub/resource_apphub_workload_test.go @@ -0,0 +1,180 @@ +package apphub_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccApphubWorkload_apphubWorkloadUpdate(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "billing_account": envvar.GetTestBillingAccountFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "random": {}, + "time": {}, + }, + CheckDestroy: testAccCheckApphubWorkloadDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccApphubWorkload_apphubWorkloadFullExample(context), + }, + { + ResourceName: "google_apphub_workload.example", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "application_id", "workload_id"}, + }, + { + Config: testAccApphubWorkload_apphubWorkloadUpdate(context), + }, + { + ResourceName: "google_apphub_workload.example", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "application_id", "workload_id"}, + }, + }, + }) +} + +func testAccApphubWorkload_apphubWorkloadUpdate(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_apphub_application" "application" { + location = "us-central1" + application_id = "tf-test-example-application-1%{random_suffix}" + scope { + type = "REGIONAL" + } +} + +resource "google_project" "service_project" { + project_id ="tf-test-project-1%{random_suffix}" + name = "Service Project" + org_id = "%{org_id}" + billing_account = "%{billing_account}" +} + +# Enable Compute API +resource "google_project_service" "compute_service_project" { + project = google_project.service_project.project_id + service = "compute.googleapis.com" +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_project_service.compute_service_project] + + create_duration = "120s" +} + +resource "google_apphub_service_project_attachment" "service_project_attachment" { + service_project_attachment_id = google_project.service_project.project_id + depends_on = [time_sleep.wait_120s] +} + +# Discovered workload +data "google_apphub_discovered_workload" "catalog-workload" { + location = "us-central1" + workload_uri = "${replace(google_compute_region_instance_group_manager.mig.instance_group, "https://www.googleapis.com/compute/v1", "//compute.googleapis.com")}" + depends_on = [time_sleep.wait_120s_for_resource_ingestion] +} + +resource "time_sleep" "wait_120s_for_resource_ingestion" { + depends_on = [google_compute_region_instance_group_manager.mig] + create_duration = "120s" +} + +resource "google_apphub_workload" "example" { + location = "us-central1" + application_id = google_apphub_application.application.application_id + workload_id = google_compute_region_instance_group_manager.mig.name + discovered_workload = data.google_apphub_discovered_workload.catalog-workload.name +} + +#Workload creation + + +# VPC network +resource "google_compute_network" "ilb_network" { + name = "tf-test-l7-ilb-network%{random_suffix}" + project = google_project.service_project.project_id + auto_create_subnetworks = false + depends_on = [time_sleep.wait_120s] +} + +# backend subnet +resource "google_compute_subnetwork" "ilb_subnet" { + name = "tf-test-l7-ilb-subnet%{random_suffix}" + project = google_project.service_project.project_id + ip_cidr_range = "10.0.1.0/24" + region = "us-central1" + network = google_compute_network.ilb_network.id +} + +# instance template +resource "google_compute_instance_template" "instance_template" { + name = "tf-test-l7-ilb-mig-template%{random_suffix}" + project = google_project.service_project.project_id + machine_type = "e2-small" + tags = ["http-server"] + network_interface { + network = google_compute_network.ilb_network.id + subnetwork = google_compute_subnetwork.ilb_subnet.id + access_config { + # add external ip to fetch packages + } + } + disk { + source_image = "debian-cloud/debian-10" + auto_delete = true + boot = true + } + # install nginx and serve a simple web page + metadata = { + startup-script = <<-EOF1 + #! /bin/bash + set -euo pipefail + export DEBIAN_FRONTEND=noninteractive + apt-get update + apt-get install -y nginx-light jq + NAME=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/hostname") + IP=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip") + METADATA=$(curl -f -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/attributes/?recursive=True" | jq 'del(.["startup-script"])') + cat < /var/www/html/index.html +
+      Name: $NAME
+      IP: $IP
+      Metadata: $METADATA
+      
+ EOF + EOF1 + } + lifecycle { + create_before_destroy = true + } +} + +resource "google_compute_region_instance_group_manager" "mig" { + name = "tf-test-l7-ilb-mig1%{random_suffix}" + project = google_project.service_project.project_id + region = "us-central1" + version { + instance_template = google_compute_instance_template.instance_template.id + name = "primary" + } + base_instance_name = "vm" + target_size = 2 +} +`, context) +} From 8bd772e43e95185514d5e325a93f6d499ddc5b5d Mon Sep 17 00:00:00 2001 From: shijeesh-ns <92889532+shijeesh-ns@users.noreply.github.com> Date: Tue, 12 Mar 2024 16:23:16 -0700 Subject: [PATCH 12/59] Fix for PrivateNat test failures (#10174) --- .../services/compute/resource_compute_router_nat_test.go.erb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_router_nat_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_router_nat_test.go.erb index b1c17157506f..7436c9ccfa45 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_router_nat_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_router_nat_test.go.erb @@ -1679,6 +1679,9 @@ resource "google_compute_router" "foobar" { name = "%s" region = google_compute_subnetwork.subnet1.region network = google_compute_network.foobar.self_link + depends_on = [ + google_network_connectivity_spoke.primary + ] } `, routerName, routerName, routerName, routerName, routerName, hubName, routerName, routerName) } @@ -1793,4 +1796,4 @@ resource "google_compute_router_nat" "foobar" { `, testAccComputeRouterNatBaseResourcesWithPrivateNatSubnetworks(routerName, hubName), routerName, ruleNumber, ruleDescription, match) } -<% end -%> \ No newline at end of file +<% end -%> From 4fa7f7c5c43d93b9813acd33ecf232f6cd6151ed Mon Sep 17 00:00:00 2001 From: Esha Goel Date: Wed, 13 Mar 2024 04:53:57 +0530 Subject: [PATCH 13/59] Add new resource Service for Apphub (#10132) * Add new resource for Service Project for Apphub FIXES https://github.com/hashicorp/terraform-provider-google/issues/17405 * Add new resource for Service Project for Apphub FIXES https://github.com/hashicorp/terraform-provider-google/issues/17405 * Add new resource for Service Project Attachment for Apphub FIXES https://github.com/hashicorp/terraform-provider-google/issues/17405 * Add new resource for Service Project Attachment for Apphub FIXES https://github.com/hashicorp/terraform-provider-google/issues/17405 * Add new resource for Service Project Attachment for Apphub FIXES https://github.com/hashicorp/terraform-provider-google/issues/17405 * Add new resource for Application for Apphub * Add new resource for Application for Apphub * Enable Apphub API in test cases * Add new resource for Service Project Attachment for Apphub FIXES https://github.com/hashicorp/terraform-provider-google/issues/17405 * Enable apphub API in test cases * Fix precheck error * Fix precheck error * Fix precheck error * Fix precheck error * Resolve comments * Fix lint error * Fix errors * Add new resource for Service for Apphub * Fix examples * Add test * Fix tests * Add IAM permissions * Add IAM permission * Fix IAM issues * Remove merged changes * Add billing account * Remove extra delay from tests * Add handwritten update test * Remove merged changes * Make changes to yaml file incorporating comments from https://github.com/GoogleCloudPlatform/magic-modules/pull/10155 * Fix lint errors in Service YAML definition * Add a delay between discovered resource fetch and forwarding rule creation * Add a delay between discovered resource fetch and forwarding rule creation * Add a delay between discovered resource fetch and forwarding rule creation * Batch update tests to improve speed * Use standard diff suppress function * Update region from us-east1 to us-central1 --------- Co-authored-by: Krishnan Gopal Co-authored-by: praseedhaPK <161299686+praseedhaPK@users.noreply.github.com> --- mmv1/products/apphub/Service.yaml | 235 ++++++++++++++++++ .../examples/apphub_service_basic.tf.erb | 110 ++++++++ .../examples/apphub_service_full.tf.erb | 132 ++++++++++ .../apphub/resource_apphub_service_test.go | 163 ++++++++++++ 4 files changed, 640 insertions(+) create mode 100644 mmv1/products/apphub/Service.yaml create mode 100644 mmv1/templates/terraform/examples/apphub_service_basic.tf.erb create mode 100644 mmv1/templates/terraform/examples/apphub_service_full.tf.erb create mode 100644 mmv1/third_party/terraform/services/apphub/resource_apphub_service_test.go diff --git a/mmv1/products/apphub/Service.yaml b/mmv1/products/apphub/Service.yaml new file mode 100644 index 000000000000..7558666e9582 --- /dev/null +++ b/mmv1/products/apphub/Service.yaml @@ -0,0 +1,235 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +base_url: projects/{{project}}/locations/{{location}}/applications/{{application_id}}/services +create_url: projects/{{project}}/locations/{{location}}/applications/{{application_id}}/services?serviceId={{service_id}} +self_link: projects/{{project}}/locations/{{location}}/applications/{{application_id}}/services/{{service_id}} +id_format: projects/{{project}}/locations/{{location}}/applications/{{application_id}}/services/{{service_id}} +import_format: + - projects/{{project}}/locations/{{location}}/applications/{{application_id}}/services/{{service_id}} +name: Service +description: 'Service is a network/api interface that exposes some functionality to clients for consumption over the network. + Service typically has one or more Workloads behind it. It registers identified service to the Application.' +autogen_async: true +examples: + - !ruby/object:Provider::Terraform::Examples + name: "apphub_service_basic" + pull_external: true + primary_resource_id: "example" + vars: + application_id: "example-application-1" + service_project_attachment_id: "project-1" + ilb_network: "l7-ilb-network" + ilb_subnet: "l7-ilb-subnet" + forwarding_rule: "l7-ilb-forwarding-rule" + backend_service: "l7-ilb-backend-subnet" + health_check: "l7-ilb-hc" + test_env_vars: + org_id: :ORG_ID + billing_account: :BILLING_ACCT + - !ruby/object:Provider::Terraform::Examples + name: "apphub_service_full" + pull_external: true + primary_resource_id: "example" + vars: + application_id: "example-application-1" + service_project_attachment_id: "project-1" + display_name: "Example Service Full" + description: "Register service for testing" + business_name: "Alice" + business_email: "alice@google.com" + developer_name: "Bob" + developer_email: "bob@google.com" + operator_name: "Charlie" + operator_email: "charlie@google.com" + ilb_network: "l7-ilb-network" + ilb_subnet: "l7-ilb-subnet" + forwarding_rule: "l7-ilb-forwarding-rule" + backend_service: "l7-ilb-backend-subnet" + health_check: "l7-ilb-hc" + test_env_vars: + org_id: :ORG_ID + billing_account: :BILLING_ACCT +async: !ruby/object:Api::OpAsync + operation: !ruby/object:Api::OpAsync::Operation + path: name + base_url: "{{op_id}}" + wait_ms: 1000 + timeouts: + result: !ruby/object:Api::OpAsync::Result + path: response + resource_inside_response: true + status: !ruby/object:Api::OpAsync::Status + path: done + complete: true + allowed: + - true + - false + error: !ruby/object:Api::OpAsync::Error + path: error + message: message +update_verb: :PATCH +update_mask: true +parameters: + - !ruby/object:Api::Type::String + name: location + description: 'Part of `parent`. Full resource name of a parent Application. Example: projects/{HOST_PROJECT_ID}/locations/{LOCATION}/applications/{APPLICATION_ID} ' + url_param_only: true + required: true + immutable: true + - !ruby/object:Api::Type::String + name: applicationId + description: 'Part of `parent`. Full resource name of a parent Application. Example: projects/{HOST_PROJECT_ID}/locations/{LOCATION}/applications/{APPLICATION_ID}' + url_param_only: true + required: true + immutable: true + - !ruby/object:Api::Type::String + name: serviceId + description: 'The Service identifier. ' + url_param_only: true + required: true + immutable: true +properties: + - !ruby/object:Api::Type::String + name: name + output: true + description: "Identifier. The resource name of a Service. Format:\n\"projects/{host-project-id}/locations/{location}/applications/{application-id}/services/{service-id}\" " + - !ruby/object:Api::Type::String + name: displayName + description: 'User-defined name for the Service. ' + - !ruby/object:Api::Type::String + name: description + description: 'User-defined description of a Service. ' + - !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: uri + description: "Output only. The underlying resource URI (For example, URI of Forwarding + Rule, URL Map,\nand Backend Service). " + output: true + output: true + name: serviceReference + description: 'Reference to an underlying networking resource that can comprise a + Service. ' + - !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: gcpProject + description: "Output only. The service project identifier that the underlying + cloud resource resides in. " + output: true + - !ruby/object:Api::Type::String + name: location + description: "Output only. The location that the underlying resource resides in, + for example, us-west1. " + output: true + - !ruby/object:Api::Type::String + name: zone + description: "Output only. The location that the underlying resource resides in + if it is zonal, for example, us-west1-a). " + output: true + output: true + name: serviceProperties + description: 'Properties of an underlying cloud resource that can comprise a Service. ' + - !ruby/object:Api::Type::NestedObject + name: attributes + description: 'Consumer provided attributes. ' + properties: + - !ruby/object:Api::Type::NestedObject + name: criticality + description: 'Criticality of the Application, Service, or Workload ' + properties: + - !ruby/object:Api::Type::Enum + name: type + description: 'Criticality type. ' + required: true + values: + - :MISSION_CRITICAL + - :HIGH + - :MEDIUM + - :LOW + - !ruby/object:Api::Type::NestedObject + name: environment + description: 'Environment of the Application, Service, or Workload ' + properties: + - !ruby/object:Api::Type::Enum + name: type + description: 'Environment type. ' + required: true + values: + - :PRODUCTION + - :STAGING + - :TEST + - :DEVELOPMENT + - !ruby/object:Api::Type::Array + name: developerOwners + description: 'Developer team that owns development and coding. ' + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: displayName + description: 'Contact''s name. ' + - !ruby/object:Api::Type::String + name: email + description: 'Required. Email address of the contacts. ' + required: true + - !ruby/object:Api::Type::Array + name: operatorOwners + description: 'Operator team that ensures runtime and operations. ' + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: displayName + description: 'Contact''s name. ' + - !ruby/object:Api::Type::String + name: email + description: 'Required. Email address of the contacts. ' + required: true + - !ruby/object:Api::Type::Array + name: businessOwners + description: 'Business team that ensures user needs are met and value + is delivered ' + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: displayName + description: 'Contact''s name. ' + - !ruby/object:Api::Type::String + name: email + description: 'Required. Email address of the contacts. ' + required: true + - !ruby/object:Api::Type::String + name: discoveredService + diff_suppress_func: 'tpgresource.ProjectNumberDiffSuppress' + description: 'Immutable. The resource name of the original discovered + service. ' + required: true + immutable: true + - !ruby/object:Api::Type::String + name: createTime + description: 'Output only. Create time. ' + output: true + - !ruby/object:Api::Type::String + name: updateTime + description: 'Output only. Update time. ' + output: true + - !ruby/object:Api::Type::String + name: uid + description: "Output only. A universally unique identifier (UUID) for the `Service` + in the UUID4\nformat. " + output: true + - !ruby/object:Api::Type::String + name: state + description: "Output only. Service state. Possible values: STATE_UNSPECIFIED CREATING ACTIVE DELETING DETACHED" + output: true diff --git a/mmv1/templates/terraform/examples/apphub_service_basic.tf.erb b/mmv1/templates/terraform/examples/apphub_service_basic.tf.erb new file mode 100644 index 000000000000..f62288859da8 --- /dev/null +++ b/mmv1/templates/terraform/examples/apphub_service_basic.tf.erb @@ -0,0 +1,110 @@ +resource "google_apphub_application" "application" { + location = "us-central1" + application_id = "<%= ctx[:vars]['application_id'] %>" + scope { + type = "REGIONAL" + } +} + +resource "google_project" "service_project" { + project_id ="<%= ctx[:vars]['service_project_attachment_id'] %>" + name = "Service Project" + org_id = "<%= ctx[:test_env_vars]['org_id'] %>" + billing_account = "<%= ctx[:test_env_vars]['billing_account'] %>" +} + +# Enable Compute API +resource "google_project_service" "compute_service_project" { + project = google_project.service_project.project_id + service = "compute.googleapis.com" +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_project_service.compute_service_project] + + create_duration = "120s" +} + +resource "google_apphub_service_project_attachment" "service_project_attachment" { + service_project_attachment_id = google_project.service_project.project_id + depends_on = [time_sleep.wait_120s] +} + +# discovered service block +data "google_apphub_discovered_service" "catalog-service" { + provider = google + location = "us-central1" + service_uri = "//compute.googleapis.com/${google_compute_forwarding_rule.forwarding_rule.id}" + depends_on = [google_apphub_service_project_attachment.service_project_attachment, time_sleep.wait_120s_for_resource_ingestion] +} + +resource "time_sleep" "wait_120s_for_resource_ingestion" { + depends_on = [google_compute_forwarding_rule.forwarding_rule] + create_duration = "120s" +} + +resource "google_apphub_service" "<%= ctx[:primary_resource_id] %>" { + location = "us-central1" + application_id = google_apphub_application.application.application_id + service_id = google_compute_forwarding_rule.forwarding_rule.name + discovered_service = data.google_apphub_discovered_service.catalog-service.name +} + + +#creates service + + +# VPC network +resource "google_compute_network" "ilb_network" { + name = "<%= ctx[:vars]['ilb_network'] %>" + project = google_project.service_project.project_id + auto_create_subnetworks = false + depends_on = [time_sleep.wait_120s] +} + + +# backend subnet +resource "google_compute_subnetwork" "ilb_subnet" { + name = "<%= ctx[:vars]['ilb_subnet'] %>" + project = google_project.service_project.project_id + ip_cidr_range = "10.0.1.0/24" + region = "us-central1" + network = google_compute_network.ilb_network.id +} + +# forwarding rule +resource "google_compute_forwarding_rule" "forwarding_rule" { + name ="<%= ctx[:vars]['forwarding_rule'] %>" + project = google_project.service_project.project_id + region = "us-central1" + ip_version = "IPV4" + load_balancing_scheme = "INTERNAL" + all_ports = true + backend_service = google_compute_region_backend_service.backend.id + network = google_compute_network.ilb_network.id + subnetwork = google_compute_subnetwork.ilb_subnet.id +} + + + +# backend service +resource "google_compute_region_backend_service" "backend" { + name = "<%= ctx[:vars]['backend_service'] %>" + project = google_project.service_project.project_id + region = "us-central1" + health_checks = [google_compute_health_check.default.id] +} + +# health check +resource "google_compute_health_check" "default" { + name = "<%= ctx[:vars]['health_check'] %>" + project = google_project.service_project.project_id + check_interval_sec = 1 + timeout_sec = 1 + tcp_health_check { + port = "80" + } + depends_on = [time_sleep.wait_120s] +} + + diff --git a/mmv1/templates/terraform/examples/apphub_service_full.tf.erb b/mmv1/templates/terraform/examples/apphub_service_full.tf.erb new file mode 100644 index 000000000000..2a0bdde9ed19 --- /dev/null +++ b/mmv1/templates/terraform/examples/apphub_service_full.tf.erb @@ -0,0 +1,132 @@ +resource "google_apphub_application" "application" { + location = "us-central1" + application_id = "<%= ctx[:vars]['application_id'] %>" + scope { + type = "REGIONAL" + } +} + +resource "google_project" "service_project" { + project_id ="<%= ctx[:vars]['service_project_attachment_id'] %>" + name = "Service Project" + org_id = "<%= ctx[:test_env_vars]['org_id'] %>" + billing_account = "<%= ctx[:test_env_vars]['billing_account'] %>" +} + +# Enable Compute API +resource "google_project_service" "compute_service_project" { + project = google_project.service_project.project_id + service = "compute.googleapis.com" +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_project_service.compute_service_project] + + create_duration = "120s" +} + +resource "google_apphub_service_project_attachment" "service_project_attachment" { + service_project_attachment_id = google_project.service_project.project_id + depends_on = [time_sleep.wait_120s] +} + +# discovered service block +data "google_apphub_discovered_service" "catalog-service" { + provider = google + location = "us-central1" + service_uri = "//compute.googleapis.com/${google_compute_forwarding_rule.forwarding_rule.id}" + depends_on = [google_apphub_service_project_attachment.service_project_attachment, time_sleep.wait_120s_for_resource_ingestion] +} + +resource "time_sleep" "wait_120s_for_resource_ingestion" { + depends_on = [google_compute_forwarding_rule.forwarding_rule] + create_duration = "120s" +} + +resource "google_apphub_service" "<%= ctx[:primary_resource_id] %>" { + location = "us-central1" + application_id = google_apphub_application.application.application_id + service_id = google_compute_forwarding_rule.forwarding_rule.name + discovered_service = data.google_apphub_discovered_service.catalog-service.name + display_name = "<%= ctx[:vars]['display_name'] %>" + description = "<%= ctx[:vars]['description'] %>" + attributes { + environment { + type = "STAGING" + } + criticality { + type = "MISSION_CRITICAL" + } + business_owners { + display_name = "<%= ctx[:vars]['business_name'] %>" + email = "<%= ctx[:vars]['business_email'] %>" + } + developer_owners { + display_name = "<%= ctx[:vars]['developer_name'] %>" + email = "<%= ctx[:vars]['developer_email'] %>" + } + operator_owners { + display_name = "<%= ctx[:vars]['operator_name'] %>" + email = "<%= ctx[:vars]['operator_email'] %>" + } + } +} + + +#creates service + + +# VPC network +resource "google_compute_network" "ilb_network" { + name = "<%= ctx[:vars]['ilb_network'] %>" + project = google_project.service_project.project_id + auto_create_subnetworks = false + depends_on = [time_sleep.wait_120s] +} + + +# backend subnet +resource "google_compute_subnetwork" "ilb_subnet" { + name = "<%= ctx[:vars]['ilb_subnet'] %>" + project = google_project.service_project.project_id + ip_cidr_range = "10.0.1.0/24" + region = "us-central1" + network = google_compute_network.ilb_network.id +} + +# forwarding rule +resource "google_compute_forwarding_rule" "forwarding_rule" { + name ="<%= ctx[:vars]['forwarding_rule'] %>" + project = google_project.service_project.project_id + region = "us-central1" + ip_version = "IPV4" + load_balancing_scheme = "INTERNAL" + all_ports = true + backend_service = google_compute_region_backend_service.backend.id + network = google_compute_network.ilb_network.id + subnetwork = google_compute_subnetwork.ilb_subnet.id +} + + + +# backend service +resource "google_compute_region_backend_service" "backend" { + name = "<%= ctx[:vars]['backend_service'] %>" + project = google_project.service_project.project_id + region = "us-central1" + health_checks = [google_compute_health_check.default.id] +} + +# health check +resource "google_compute_health_check" "default" { + name = "<%= ctx[:vars]['health_check'] %>" + project = google_project.service_project.project_id + check_interval_sec = 1 + timeout_sec = 1 + tcp_health_check { + port = "80" + } + depends_on = [time_sleep.wait_120s] +} + + diff --git a/mmv1/third_party/terraform/services/apphub/resource_apphub_service_test.go b/mmv1/third_party/terraform/services/apphub/resource_apphub_service_test.go new file mode 100644 index 000000000000..0ea290f3992e --- /dev/null +++ b/mmv1/third_party/terraform/services/apphub/resource_apphub_service_test.go @@ -0,0 +1,163 @@ +package apphub_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccApphubService_serviceUpdate(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "billing_account": envvar.GetTestBillingAccountFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "random": {}, + "time": {}, + }, + CheckDestroy: testAccCheckApphubServiceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccApphubService_apphubServiceFullExample(context), + }, + { + ResourceName: "google_apphub_service.example", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "application_id", "service_id"}, + }, + { + Config: testAccApphubService_apphubServiceUpdate(context), + }, + { + ResourceName: "google_apphub_service.example", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "application_id", "service_id"}, + }, + }, + }) +} + +func testAccApphubService_apphubServiceUpdate(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_apphub_application" "application" { + location = "us-central1" + application_id = "tf-test-example-application-1%{random_suffix}" + scope { + type = "REGIONAL" + } +} + +resource "google_project" "service_project" { + project_id ="tf-test-project-1%{random_suffix}" + name = "Service Project" + org_id = "%{org_id}" + billing_account = "%{billing_account}" +} + +# Enable Compute API +resource "google_project_service" "compute_service_project" { + project = google_project.service_project.project_id + service = "compute.googleapis.com" +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_project_service.compute_service_project] + + create_duration = "120s" +} + +resource "google_apphub_service_project_attachment" "service_project_attachment" { + service_project_attachment_id = google_project.service_project.project_id + depends_on = [time_sleep.wait_120s] +} + +# discovered service block +data "google_apphub_discovered_service" "catalog-service" { + provider = google + location = "us-central1" + service_uri = "//compute.googleapis.com/${google_compute_forwarding_rule.forwarding_rule.id}" + depends_on = [google_apphub_service_project_attachment.service_project_attachment, time_sleep.wait_120s_for_resource_ingestion] +} + +resource "time_sleep" "wait_120s_for_resource_ingestion" { + depends_on = [google_compute_forwarding_rule.forwarding_rule] + create_duration = "120s" +} + +resource "google_apphub_service" "example" { + location = "us-central1" + application_id = google_apphub_application.application.application_id + service_id = google_compute_forwarding_rule.forwarding_rule.name + discovered_service = data.google_apphub_discovered_service.catalog-service.name +} + + +#creates service + + +# VPC network +resource "google_compute_network" "ilb_network" { + name = "tf-test-l7-ilb-network%{random_suffix}" + project = google_project.service_project.project_id + auto_create_subnetworks = false + depends_on = [time_sleep.wait_120s] +} + + +# backend subnet +resource "google_compute_subnetwork" "ilb_subnet" { + name = "tf-test-l7-ilb-subnet%{random_suffix}" + project = google_project.service_project.project_id + ip_cidr_range = "10.0.1.0/24" + region = "us-central1" + network = google_compute_network.ilb_network.id +} + +# forwarding rule +resource "google_compute_forwarding_rule" "forwarding_rule" { + name ="tf-test-l7-ilb-forwarding-rule%{random_suffix}" + project = google_project.service_project.project_id + region = "us-central1" + ip_version = "IPV4" + load_balancing_scheme = "INTERNAL" + all_ports = true + backend_service = google_compute_region_backend_service.backend.id + network = google_compute_network.ilb_network.id + subnetwork = google_compute_subnetwork.ilb_subnet.id +} + + + +# backend service +resource "google_compute_region_backend_service" "backend" { + name = "tf-test-l7-ilb-backend-subnet%{random_suffix}" + project = google_project.service_project.project_id + region = "us-central1" + health_checks = [google_compute_health_check.default.id] +} + +# health check +resource "google_compute_health_check" "default" { + name = "tf-test-l7-ilb-hc%{random_suffix}" + project = google_project.service_project.project_id + check_interval_sec = 1 + timeout_sec = 1 + tcp_health_check { + port = "80" + } + depends_on = [time_sleep.wait_120s] +} +`, context) +} From 4555c3364bb74d340fb13db281fc79bd8f862249 Mon Sep 17 00:00:00 2001 From: kumailkermalli-datatonic <108349674+kumailkermalli-datatonic@users.noreply.github.com> Date: Tue, 12 Mar 2024 23:33:51 +0000 Subject: [PATCH 14/59] feat: add credentials_secret field in azure blob storage block for google storage transfer job resource (#9278) * feat: add `credentials_secret` in `azure_blob_storage_data` source config * feat: add version guard for `credentials_secret` as in preview * docs: add documentation on `credentials_secret` --- ...o => resource_storage_transfer_job.go.erb} | 53 +++++++++++++++---- .../docs/r/storage_transfer_job.html.markdown | 4 +- 2 files changed, 45 insertions(+), 12 deletions(-) rename mmv1/third_party/terraform/services/storagetransfer/{resource_storage_transfer_job.go => resource_storage_transfer_job.go.erb} (96%) diff --git a/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job.go b/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job.go.erb similarity index 96% rename from mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job.go rename to mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job.go.erb index 148ab8c0af82..0a955d9f11b3 100644 --- a/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job.go +++ b/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job.go.erb @@ -1,3 +1,4 @@ +<% autogen_exception -%> package storagetransfer import ( @@ -50,6 +51,12 @@ var ( "transfer_spec.0.aws_s3_data_source.0.aws_access_key", "transfer_spec.0.aws_s3_data_source.0.role_arn", } + <% unless version == 'ga' -%> + azureOptionCredentials = []string{ + "transfer_spec.0.azure_blob_storage_data_source.0.azure_credentials", + "transfer_spec.0.azure_blob_storage_data_source.0.credentials_secret", + } + <% end -%> ) func ResourceStorageTransferJob() *schema.Resource { @@ -559,9 +566,14 @@ func azureBlobStorageDataSchema() *schema.Resource { Description: `Root path to transfer objects. Must be an empty string or full path name that ends with a '/'. This field is treated as an object prefix. As such, it should generally not begin with a '/'.`, }, "azure_credentials": { - Type: schema.TypeList, - Required: true, - MaxItems: 1, + Type: schema.TypeList, + <% unless version == 'ga' -%> + Optional: true, + ExactlyOneOf: azureOptionCredentials, + <% else -%> + Required: true, + <% end -%> + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "sas_token": { @@ -574,6 +586,14 @@ func azureBlobStorageDataSchema() *schema.Resource { }, Description: ` Credentials used to authenticate API requests to Azure.`, }, + <% unless version == 'ga' -%> + "credentials_secret": { + Optional: true, + Type: schema.TypeString, + Description: `The Resource name of a secret in Secret Manager containing SAS Credentials in JSON form. Service Agent must have permissions to access secret. If credentials_secret is specified, do not specify azure_credentials.`, + ExactlyOneOf: azureOptionCredentials, + }, + <% end -%> }, } } @@ -1099,6 +1119,11 @@ func expandAzureCredentials(azureCredentials []interface{}) *storagetransfer.Azu } func flattenAzureCredentials(d *schema.ResourceData) []map[string]interface{} { + <% unless version == 'ga' -%> + if d.Get("transfer_spec.0.azure_blob_storage_data_source.0.azure_credentials.0.sas_token") == "" { + return []map[string]interface{}{} + } + <% end -%> data := map[string]interface{}{ "sas_token": d.Get("transfer_spec.0.azure_blob_storage_data_source.0.azure_credentials.0.sas_token"), } @@ -1114,19 +1139,25 @@ func expandAzureBlobStorageData(azureBlobStorageDatas []interface{}) *storagetra azureBlobStorageData := azureBlobStorageDatas[0].(map[string]interface{}) return &storagetransfer.AzureBlobStorageData{ - Container: azureBlobStorageData["container"].(string), - Path: azureBlobStorageData["path"].(string), - StorageAccount: azureBlobStorageData["storage_account"].(string), - AzureCredentials: expandAzureCredentials(azureBlobStorageData["azure_credentials"].([]interface{})), + Container: azureBlobStorageData["container"].(string), + Path: azureBlobStorageData["path"].(string), + StorageAccount: azureBlobStorageData["storage_account"].(string), + AzureCredentials: expandAzureCredentials(azureBlobStorageData["azure_credentials"].([]interface{})), + <% unless version == 'ga' -%> + CredentialsSecret: azureBlobStorageData["credentials_secret"].(string), + <% end -%> } } func flattenAzureBlobStorageData(azureBlobStorageData *storagetransfer.AzureBlobStorageData, d *schema.ResourceData) []map[string]interface{} { data := map[string]interface{}{ - "container": azureBlobStorageData.Container, - "path": azureBlobStorageData.Path, - "storage_account": azureBlobStorageData.StorageAccount, - "azure_credentials": flattenAzureCredentials(d), + "container": azureBlobStorageData.Container, + "path": azureBlobStorageData.Path, + "storage_account": azureBlobStorageData.StorageAccount, + "azure_credentials": flattenAzureCredentials(d), + <% unless version == 'ga' -%> + "credentials_secret": azureBlobStorageData.CredentialsSecret, + <% end -%> } return []map[string]interface{}{data} diff --git a/mmv1/third_party/terraform/website/docs/r/storage_transfer_job.html.markdown b/mmv1/third_party/terraform/website/docs/r/storage_transfer_job.html.markdown index c354672672d2..2f2d4ecb5d83 100644 --- a/mmv1/third_party/terraform/website/docs/r/storage_transfer_job.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/storage_transfer_job.html.markdown @@ -247,7 +247,9 @@ The `aws_access_key` block supports: * `path` - (Required) Root path to transfer objects. Must be an empty string or full path name that ends with a '/'. This field is treated as an object prefix. As such, it should generally not begin with a '/'. -* `azure_credentials` - (Required) Credentials used to authenticate API requests to Azure block. +* `credentials_secret` - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) Full Resource name of a secret in Secret Manager containing [SAS Credentials in JSON form](https://cloud.google.com/storage-transfer/docs/reference/rest/v1/TransferSpec#azureblobstoragedata:~:text=begin%20with%20a%20%27/%27.-,credentialsSecret,-string). Service Agent for Storage Transfer must have permissions to access secret. If credentials_secret is specified, do not specify azure_credentials.`, + +* `azure_credentials` - (Required in GA, Optional in [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) Credentials used to authenticate API requests to Azure block. The `azure_credentials` block supports: From e3a06e371bbcd7ccd50dd832b96f4108d27d97bc Mon Sep 17 00:00:00 2001 From: Xuran Liu Date: Tue, 12 Mar 2024 17:03:36 -0700 Subject: [PATCH 15/59] Added CloudQuotas service and Create QuotaInfo Datasource (#10071) * add quota info data source * add test and documention for quota_info data source * fix lint error * clean up * update test * manually import cloudquotas to terraform provider * Update mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb Co-authored-by: Riley Karson * Update mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb Co-authored-by: Riley Karson --------- Co-authored-by: Riley Karson --- mmv1/products/cloudquotas/product.yaml | 22 ++ .../components/inputs/services_beta.kt | 7 +- .../components/inputs/services_ga.kt | 7 +- .../provider/provider_mmv1_resources.go.erb | 4 + ...a_source_google_cloud_quotas_quota_info.go | 247 ++++++++++++++++++ ...rce_google_cloud_quotas_quota_info_test.go | 61 +++++ .../d/cloud_quotas_quota_info.html.markdown | 61 +++++ 7 files changed, 407 insertions(+), 2 deletions(-) create mode 100644 mmv1/products/cloudquotas/product.yaml create mode 100644 mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_info.go create mode 100644 mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_info_test.go create mode 100644 mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_info.html.markdown diff --git a/mmv1/products/cloudquotas/product.yaml b/mmv1/products/cloudquotas/product.yaml new file mode 100644 index 000000000000..53c82344b0d2 --- /dev/null +++ b/mmv1/products/cloudquotas/product.yaml @@ -0,0 +1,22 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Product +name: CloudQuotas +display_name: Cloud Quotas +versions: + - !ruby/object:Api::Product::Version + name: ga + base_url: https://cloudquotas.googleapis.com/v1/ +scopes: + - https://www.googleapis.com/auth/cloud-platform diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt index 443987885a6f..e8beb038983d 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt @@ -178,6 +178,11 @@ var ServicesListBeta = mapOf( "displayName" to "Cloudids", "path" to "./google-beta/services/cloudids" ), + "cloudquotas" to mapOf( + "name" to "cloudquotas", + "displayName" to "Cloudquotas", + "path" to "./google-beta/services/cloudquotas" + ), "cloudrun" to mapOf( "name" to "cloudrun", "displayName" to "Cloudrun", @@ -693,4 +698,4 @@ var ServicesListBeta = mapOf( "displayName" to "Workstations", "path" to "./google-beta/services/workstations" ) -) \ No newline at end of file +) diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt index 08ce6c2ee82f..071ea16ec879 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt @@ -178,6 +178,11 @@ var ServicesListGa = mapOf( "displayName" to "Cloudids", "path" to "./google/services/cloudids" ), + "cloudquotas" to mapOf( + "name" to "cloudquotas", + "displayName" to "Cloudquotas", + "path" to "./google/services/cloudquotas" + ), "cloudrun" to mapOf( "name" to "cloudrun", "displayName" to "Cloudrun", @@ -688,4 +693,4 @@ var ServicesListGa = mapOf( "displayName" to "Workstations", "path" to "./google/services/workstations" ) -) \ No newline at end of file +) diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb index cf84c8032b16..f58f2b57e660 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -15,6 +15,9 @@ import ( "github.com/hashicorp/terraform-provider-google/google/services/dataflow" "github.com/hashicorp/terraform-provider-google/google/services/servicenetworking" "github.com/hashicorp/terraform-provider-google/google/tpgiamresource" + <% if version == 'ga' -%> // https://github.com/hashicorp/terraform-provider-google/issues/15633 for details + "github.com/hashicorp/terraform-provider-google/google/services/cloudquotas" + <% end -%> ) // Datasources @@ -49,6 +52,7 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_cloud_identity_groups": cloudidentity.DataSourceGoogleCloudIdentityGroups(), "google_cloud_identity_group_memberships": cloudidentity.DataSourceGoogleCloudIdentityGroupMemberships(), "google_cloud_identity_group_lookup": cloudidentity.DataSourceGoogleCloudIdentityGroupLookup(), + "google_cloud_quotas_quota_info": cloudquotas.DataSourceGoogleCloudQuotasQuotaInfo(), "google_cloud_run_locations": cloudrun.DataSourceGoogleCloudRunLocations(), "google_cloud_run_service": cloudrun.DataSourceGoogleCloudRunService(), "google_cloud_run_v2_job": cloudrunv2.DataSourceGoogleCloudRunV2Job(), diff --git a/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_info.go b/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_info.go new file mode 100644 index 000000000000..e2ac85a5a99e --- /dev/null +++ b/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_info.go @@ -0,0 +1,247 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 +package cloudquotas + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func DataSourceGoogleCloudQuotasQuotaInfo() *schema.Resource { + return &schema.Resource{ + Read: dataSourceGoogleCloudQuotasQuotaInfoRead, + + Schema: map[string]*schema.Schema{ + "parent": { + Type: schema.TypeString, + Required: true, + }, + "service": { + Type: schema.TypeString, + Required: true, + }, + "quota_id": { + Type: schema.TypeString, + Required: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "metric": { + Type: schema.TypeString, + Computed: true, + }, + "is_precise": { + Type: schema.TypeBool, + Computed: true, + }, + "refresh_interval": { + Type: schema.TypeString, + Computed: true, + }, + "container_type": { + Type: schema.TypeString, + Computed: true, + }, + "dimensions": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "metric_display_name": { + Type: schema.TypeString, + Computed: true, + }, + "quota_display_name": { + Type: schema.TypeString, + Computed: true, + }, + "metric_unit": { + Type: schema.TypeString, + Computed: true, + }, + "quota_increase_eligibility": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "is_eligible": { + Type: schema.TypeBool, + Computed: true, + }, + "ineligibility_reason": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "is_fixed": { + Type: schema.TypeBool, + Computed: true, + }, + "dimensions_infos": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dimensions": { + Type: schema.TypeMap, + Computed: true, + }, + "details": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "value": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "applicable_locations": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "is_concurrent": { + Type: schema.TypeBool, + Computed: true, + }, + "service_request_quota_uri": { + Type: schema.TypeString, + Computed: true, + }, + }, + UseJSONNumber: true, + } +} + +func dataSourceGoogleCloudQuotasQuotaInfoRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + url, err := tpgresource.ReplaceVars(d, config, "{{CloudQuotasBasePath}}{{parent}}/locations/global/services/{{service}}/quotaInfos/{{quota_id}}") + if err != nil { + return fmt.Errorf("error setting api endpoint") + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + RawURL: url, + UserAgent: userAgent, + }) + + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("CloudQuotasQuotaInfo %q", d.Id())) + } + + if err := d.Set("name", res["name"]); err != nil { + return fmt.Errorf("error reading QuotaInfo name: %s", err) + } + if err := d.Set("quota_id", res["quotaId"]); err != nil { + return fmt.Errorf("error reading QuotaInfo quota_id: %s", err) + } + if err := d.Set("metric", res["metric"]); err != nil { + return fmt.Errorf("error reading QuotaInfo metric: %s", err) + } + if err := d.Set("service", res["service"]); err != nil { + return fmt.Errorf("error reading QuotaInfo service: %s", err) + } + if err := d.Set("is_precise", res["isPrecise"]); err != nil { + return fmt.Errorf("error reading QuotaInfo is_precise: %s", err) + } + if err := d.Set("refresh_interval", res["refreshInterval"]); err != nil { + return fmt.Errorf("error reading QuotaInfo refresh_interval: %s", err) + } + if err := d.Set("container_type", res["containerType"]); err != nil { + return fmt.Errorf("error reading QuotaInfo container_type: %s", err) + } + if err := d.Set("dimensions", res["dimensions"]); err != nil { + return fmt.Errorf("error reading QuotaInfo dimensions: %s", err) + } + if err := d.Set("metric_display_name", res["metricDisplayName"]); err != nil { + return fmt.Errorf("error reading QuotaInfo metric_display_name: %s", err) + } + if err := d.Set("quota_display_name", res["quotaDisplayName"]); err != nil { + return fmt.Errorf("error reading QuotaInfo quota_display_name: %s", err) + } + if err := d.Set("metric_unit", res["metricUnit"]); err != nil { + return fmt.Errorf("error reading QuotaInfo metric_unit: %s", err) + } + if err := d.Set("quota_increase_eligibility", flattenCloudQuotasQuotaInfoQuotaIncreaseEligibility(res["quotaIncreaseEligibility"], d, config)); err != nil { + return fmt.Errorf("error reading QuotaInfo quota_increase_eligibility: %s", err) + } + if err := d.Set("is_fixed", res["isFixed"]); err != nil { + return fmt.Errorf("error reading QuotaInfo is_fixed: %s", err) + } + if err := d.Set("dimensions_infos", flattenCloudQuotasQuotaInfoDimensionsInfos(res["dimensionsInfos"], d, config)); err != nil { + return fmt.Errorf("error reading QuotaInfo dimensions_infos: %s", err) + } + if err := d.Set("is_concurrent", res["isConcurrent"]); err != nil { + return fmt.Errorf("error reading QuotaInfo is_concurrent: %s", err) + } + if err := d.Set("service_request_quota_uri", res["serviceRequestQuotaUri"]); err != nil { + return fmt.Errorf("error reading QuotaInfo service_request_quota_uri: %s", err) + } + + d.SetId(res["name"].(string)) + return nil +} + +func flattenCloudQuotasQuotaInfoQuotaIncreaseEligibility(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["is_eligible"] = original["is_eligible"] + transformed["ineligibility_reason"] = original["ineligibility_reason"] + return []interface{}{transformed} +} + +func flattenCloudQuotasQuotaInfoDimensionsInfos(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) []interface{} { + if v == nil { + return make([]interface{}, 0) + } + + original := v.([]interface{}) + dimensionsInfos := make([]interface{}, 0, len(original)) + + for _, raw := range original { + data := make(map[string]interface{}) + data["details"] = flattenCloudQuotasQuotaInfoDetails(raw.(map[string]interface{})["details"], d, config) + data["applicable_locations"] = raw.(map[string]interface{})["applicableLocations"] + data["dimensions"] = raw.(map[string]interface{})["dimensions"] + + dimensionsInfos = append(dimensionsInfos, data) + } + return dimensionsInfos +} + +func flattenCloudQuotasQuotaInfoDetails(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + original, ok := v.(map[string]interface{}) + if !ok || len(original) == 0 { + return nil + } + + return []interface{}{ + map[string]interface{}{"value": original["value"]}, + } +} diff --git a/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_info_test.go b/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_info_test.go new file mode 100644 index 000000000000..9a4ff979b47d --- /dev/null +++ b/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_info_test.go @@ -0,0 +1,61 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 +package cloudquotas_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccDataSourceGoogleQuotaInfo_basic(t *testing.T) { + t.Parallel() + + resourceName := "data.google_cloud_quotas_quota_info.my_quota_info" + service := "compute.googleapis.com" + quotaId := "CPUS-per-project-region" + + context := map[string]interface{}{ + "project": envvar.GetTestProjectFromEnv(), + "service": service, + "quota_id": quotaId, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccDataSourceGoogleQuotaInfo_basic(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(resourceName, "name"), + resource.TestCheckResourceAttr(resourceName, "quota_id", quotaId), + resource.TestCheckResourceAttr(resourceName, "metric", "compute.googleapis.com/cpus"), + resource.TestCheckResourceAttr(resourceName, "service", service), + resource.TestCheckResourceAttrSet(resourceName, "is_precise"), + resource.TestCheckResourceAttr(resourceName, "container_type", "PROJECT"), + resource.TestCheckResourceAttr(resourceName, "dimensions.0", "region"), + resource.TestCheckResourceAttr(resourceName, "metric_display_name", "CPUs"), + resource.TestCheckResourceAttr(resourceName, "quota_display_name", "CPUs"), + resource.TestCheckResourceAttrSet(resourceName, "metric_unit"), + resource.TestCheckResourceAttrSet(resourceName, "quota_increase_eligibility.0.is_eligible"), + resource.TestCheckResourceAttrSet(resourceName, "dimensions_infos.0.dimensions.region"), + resource.TestCheckResourceAttrSet(resourceName, "dimensions_infos.0.details.0.value"), + resource.TestCheckResourceAttrSet(resourceName, "dimensions_infos.0.applicable_locations.0"), + ), + }, + }, + }) +} + +func testAccDataSourceGoogleQuotaInfo_basic(context map[string]interface{}) string { + return acctest.Nprintf(` + data "google_cloud_quotas_quota_info" "my_quota_info" { + parent = "projects/%{project}" + quota_id = "%{quota_id}" + service = "%{service}" + } + `, context) +} diff --git a/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_info.html.markdown b/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_info.html.markdown new file mode 100644 index 000000000000..77e97d36489c --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_info.html.markdown @@ -0,0 +1,61 @@ +--- +subcategory: "Cloud Quotas" +--- + +# google\_cloud\_quotas\_quota\_info + +Provides information about a particular quota for a given project, folder or organization. + +## Example Usage + +```hcl +data "google_cloud_quotas_quota_info" "my_quota_info" { + parent = "projects/my-project" + service = "compute.googleapis.com" + quota_id = "CPUS-per-project-region" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `parent` - (Required) The parent of the quota info. Allowed parents are "projects/[project-id / number]" or "folders/[folder-id / number]" or "organizations/[org-id / number]. + +* `quota_id` - (Required) The id of the quota, which is unique within the service. + +* `service` - (Required) The name of the service in which the quota is defined. + +## Attributes Reference + +The following attributes are exported: + +* `name` - (Output) Resource name of this QuotaInfo, for example: `projects/123/locations/global/services/compute.googleapis.com/quotaInfos/CpusPerProjectPerRegion`. +* `metric` - (Output) The metric of the quota. It specifies the resources consumption the quota is defined for, for example: `compute.googleapis.com/cpus`. +* `is_precise` - (Output) Whether this is a precise quota. A precise quota is tracked with absolute precision. In contrast, an imprecise quota is not tracked with precision. +* `refresh_interval` - (Output) The reset time interval for the quota. Refresh interval applies to rate quota only. Example: "minute" for per minute, "day" for per day, or "10 seconds" for every 10 seconds. +* `container_type` - (Output) The container type of the QuotaInfo. +* `dimensions` - (Output) The dimensions the quota is defined on. +* `metric_display_name` - (Output) The display name of the quota metric. +* `quota_display_name` - (Output) The display name of the quota. +* `metric_unit` - (Output) The unit in which the metric value is reported, e.g., `MByte`. +* `quota_increase_eligibility` - (Output) Whether it is eligible to request a higher quota value for this quota. +* `is_fixed` - (Output) Whether the quota value is fixed or adjustable. +* `dimensions_infos` - (Output) The collection of dimensions info ordered by their dimensions from more specific ones to less specific ones. +* `is_concurrent` - (Output) Whether the quota is a concurrent quota. Concurrent quotas are enforced on the total number of concurrent operations in flight at any given time. +* `service_request_quota_uri` - (Output) URI to the page where users can request more quota for the cloud service, for example: `https://console.cloud.google.com/iam-admin/quotas`. + + The `quota_increase_eligibility` block supports: + +* `is_eligible` - Whether a higher quota value can be requested for the quota. +* `ineligibility_reason` - The enumeration of reasons when it is ineligible to request increase adjustment. + + The `dimensions_infos` block supports: +* `dimensions` - The map of dimensions for this dimensions info. The key of a map entry is "region", "zone" or the name of a service specific dimension, and the value of a map entry is the value of the dimension. If a dimension does not appear in the map of dimensions, the dimensions info applies to all the dimension values except for those that have another DimenisonInfo instance configured for the specific value. Example: {"provider" : "Foo Inc"} where "provider" is a service specific dimension of a quota. + + An object containing a list of "key": value pairs, for example: `{ "name": "wrench", "mass": "1.3kg", "count": "3" }`. +* `details` - The quota details for a map of dimensions. +* `applicable_locations` - The applicable regions or zones of this dimensions info. The field will be set to `['global']` for quotas that are not per region or per zone. Otherwise, it will be set to the list of locations this dimension info is applicable to. + + The `details` block supports: +* `value` - The value currently in effect and being enforced. From f23cbbedada43f94bfa7032005c6d41055ed3444 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Wed, 13 Mar 2024 10:24:03 +0000 Subject: [PATCH 16/59] Update comments in .teamcity/ files for clarity (#10149) * Make warning about files being controlled by MM more explicit * Add guidance to the input files about how to update them, and when --- .../builds/build_configuration_per_package.kt | 2 +- .../components/builds/build_configuration_sweepers.kt | 2 +- .../builds/build_configuration_vcr_recording.kt | 2 +- .../.teamcity/components/builds/build_features.kt | 2 +- .../.teamcity/components/builds/build_parameters.kt | 2 +- .../.teamcity/components/builds/build_steps.kt | 2 +- .../.teamcity/components/builds/build_triggers.kt | 2 +- .../.teamcity/components/builds/vcr_build_steps.kt | 2 +- .../terraform/.teamcity/components/constants.kt | 2 +- .../terraform/.teamcity/components/inputs/packages.kt | 10 +++++++++- .../components/inputs/per_service_parallelism.kt | 2 +- .../.teamcity/components/inputs/services_beta.kt | 10 +++++++++- .../.teamcity/components/inputs/services_ga.kt | 10 +++++++++- .../FEATURE-BRANCH-provider-functions.kt | 2 +- .../components/projects/google_beta_subproject.kt | 2 +- .../components/projects/google_ga_subproject.kt | 2 +- .../components/projects/project_sweeper_project.kt | 2 +- .../components/projects/reused/mm_upstream.kt | 2 +- .../components/projects/reused/nightly_tests.kt | 2 +- .../components/projects/reused/vcr_recording.kt | 2 +- .../.teamcity/components/projects/root_project.kt | 2 +- .../terraform/.teamcity/components/unique_id.kt | 2 +- .../.teamcity/components/vcs_roots/vcs_roots.kt | 2 +- mmv1/third_party/terraform/.teamcity/settings.kts | 2 +- .../.teamcity/tests/build_configuration_features.kt | 2 +- .../terraform/.teamcity/tests/context_parameters.kt | 2 +- .../terraform/.teamcity/tests/nightly_tests_project.kt | 2 +- mmv1/third_party/terraform/.teamcity/tests/sweepers.kt | 2 +- .../terraform/.teamcity/tests/test_utils.kt | 2 +- .../third_party/terraform/.teamcity/tests/vcs_roots.kt | 2 +- 30 files changed, 54 insertions(+), 30 deletions(-) diff --git a/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_per_package.kt b/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_per_package.kt index 395dc4da4a9c..f9be546f7eec 100644 --- a/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_per_package.kt +++ b/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_per_package.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package builds diff --git a/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_sweepers.kt b/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_sweepers.kt index 5d31f45db4bf..28ff7b99cdd0 100644 --- a/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_sweepers.kt +++ b/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_sweepers.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package builds diff --git a/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_vcr_recording.kt b/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_vcr_recording.kt index d647e3294737..134070d909ae 100644 --- a/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_vcr_recording.kt +++ b/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_vcr_recording.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package builds diff --git a/mmv1/third_party/terraform/.teamcity/components/builds/build_features.kt b/mmv1/third_party/terraform/.teamcity/components/builds/build_features.kt index 50734428b55f..ab2195c5111f 100644 --- a/mmv1/third_party/terraform/.teamcity/components/builds/build_features.kt +++ b/mmv1/third_party/terraform/.teamcity/components/builds/build_features.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package builds diff --git a/mmv1/third_party/terraform/.teamcity/components/builds/build_parameters.kt b/mmv1/third_party/terraform/.teamcity/components/builds/build_parameters.kt index 7641bc858592..9786a95a44b4 100644 --- a/mmv1/third_party/terraform/.teamcity/components/builds/build_parameters.kt +++ b/mmv1/third_party/terraform/.teamcity/components/builds/build_parameters.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package builds diff --git a/mmv1/third_party/terraform/.teamcity/components/builds/build_steps.kt b/mmv1/third_party/terraform/.teamcity/components/builds/build_steps.kt index 4682f1240eb9..7286b2b82f7c 100644 --- a/mmv1/third_party/terraform/.teamcity/components/builds/build_steps.kt +++ b/mmv1/third_party/terraform/.teamcity/components/builds/build_steps.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package builds diff --git a/mmv1/third_party/terraform/.teamcity/components/builds/build_triggers.kt b/mmv1/third_party/terraform/.teamcity/components/builds/build_triggers.kt index 95127f85e439..c7a119b0a158 100644 --- a/mmv1/third_party/terraform/.teamcity/components/builds/build_triggers.kt +++ b/mmv1/third_party/terraform/.teamcity/components/builds/build_triggers.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package builds diff --git a/mmv1/third_party/terraform/.teamcity/components/builds/vcr_build_steps.kt b/mmv1/third_party/terraform/.teamcity/components/builds/vcr_build_steps.kt index 4453c4fd73a8..05bcb261e901 100644 --- a/mmv1/third_party/terraform/.teamcity/components/builds/vcr_build_steps.kt +++ b/mmv1/third_party/terraform/.teamcity/components/builds/vcr_build_steps.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package builds diff --git a/mmv1/third_party/terraform/.teamcity/components/constants.kt b/mmv1/third_party/terraform/.teamcity/components/constants.kt index 7ecf16baa052..ba1cd010f3ab 100644 --- a/mmv1/third_party/terraform/.teamcity/components/constants.kt +++ b/mmv1/third_party/terraform/.teamcity/components/constants.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. // Provider name that matches the name in the Registry const val ProviderNameGa = "google" diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/packages.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/packages.kt index 2e4b11ffb516..8c5cdb3d4970 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/packages.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/packages.kt @@ -3,7 +3,15 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. + +/* + NOTE: This file is manually curated - any new packages added to the provider codebase will need to be accompanied with a change in this file. + When adding new entires make sure to ensure the path value is correct for TPG or TPGB + e.g. "path" to "./google/envvar" + versus + "path" to "./google-beta/envvar" +*/ package generated diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/per_service_parallelism.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/per_service_parallelism.kt index a57270c35250..175b063f26ac 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/per_service_parallelism.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/per_service_parallelism.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package generated diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt index e8beb038983d..13510630f136 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt @@ -3,7 +3,15 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. + +/* + NOTE: This file is manually curated - any new service packages added to the provider codebase will need to be accompanied with a change in this file. + When adding new entires make sure to ensure the path value is correct for TPG or TPGB + + For this file, services_beta.kt, please ensure paths are like: + "./google-beta/services/accessapproval" +*/ package generated diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt index 071ea16ec879..f4b303eccc69 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt @@ -3,7 +3,15 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. + +/* + NOTE: This file is manually curated - any new service packages added to the provider codebase will need to be accompanied with a change in this file. + When adding new entires make sure to ensure the path value is correct for TPG or TPGB + + For this file, services_ga.kt, please ensure paths are like: + "./google/services/accessapproval" +*/ package generated diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-provider-functions.kt b/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-provider-functions.kt index 3c1752e227f7..a795ef342fb4 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-provider-functions.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-provider-functions.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package projects.feature_branches diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/google_beta_subproject.kt b/mmv1/third_party/terraform/.teamcity/components/projects/google_beta_subproject.kt index 3824dcbfa97d..72233a701534 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/google_beta_subproject.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/google_beta_subproject.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package projects diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/google_ga_subproject.kt b/mmv1/third_party/terraform/.teamcity/components/projects/google_ga_subproject.kt index da23e7767c9e..19b4395d1c29 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/google_ga_subproject.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/google_ga_subproject.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package projects diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/project_sweeper_project.kt b/mmv1/third_party/terraform/.teamcity/components/projects/project_sweeper_project.kt index 732822a52ff6..2a484f583f9b 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/project_sweeper_project.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/project_sweeper_project.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package projects diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/reused/mm_upstream.kt b/mmv1/third_party/terraform/.teamcity/components/projects/reused/mm_upstream.kt index c26ed498edd4..9ca0a89b446a 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/reused/mm_upstream.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/reused/mm_upstream.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package projects.reused diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/reused/nightly_tests.kt b/mmv1/third_party/terraform/.teamcity/components/projects/reused/nightly_tests.kt index 6fda2b7b7ab1..cb6455e5f752 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/reused/nightly_tests.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/reused/nightly_tests.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package projects.reused diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/reused/vcr_recording.kt b/mmv1/third_party/terraform/.teamcity/components/projects/reused/vcr_recording.kt index c9916b27a722..8df65299015f 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/reused/vcr_recording.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/reused/vcr_recording.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package projects.reused diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/root_project.kt b/mmv1/third_party/terraform/.teamcity/components/projects/root_project.kt index a78260dfe650..a05e236a5a36 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/root_project.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/root_project.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package projects diff --git a/mmv1/third_party/terraform/.teamcity/components/unique_id.kt b/mmv1/third_party/terraform/.teamcity/components/unique_id.kt index 00635a8f783c..b9a56d762186 100644 --- a/mmv1/third_party/terraform/.teamcity/components/unique_id.kt +++ b/mmv1/third_party/terraform/.teamcity/components/unique_id.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. fun replaceCharsId(id: String): String{ var newId = id.replace("-", "") diff --git a/mmv1/third_party/terraform/.teamcity/components/vcs_roots/vcs_roots.kt b/mmv1/third_party/terraform/.teamcity/components/vcs_roots/vcs_roots.kt index 3ee70f25f1ef..0e696f91fd2f 100644 --- a/mmv1/third_party/terraform/.teamcity/components/vcs_roots/vcs_roots.kt +++ b/mmv1/third_party/terraform/.teamcity/components/vcs_roots/vcs_roots.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package vcs_roots diff --git a/mmv1/third_party/terraform/.teamcity/settings.kts b/mmv1/third_party/terraform/.teamcity/settings.kts index 7e748003d8f7..4e49b4abccb8 100644 --- a/mmv1/third_party/terraform/.teamcity/settings.kts +++ b/mmv1/third_party/terraform/.teamcity/settings.kts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. import projects.googleCloudRootProject import builds.AllContextParameters diff --git a/mmv1/third_party/terraform/.teamcity/tests/build_configuration_features.kt b/mmv1/third_party/terraform/.teamcity/tests/build_configuration_features.kt index ffde72f5ae79..7e3cc5b6ff58 100644 --- a/mmv1/third_party/terraform/.teamcity/tests/build_configuration_features.kt +++ b/mmv1/third_party/terraform/.teamcity/tests/build_configuration_features.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package tests diff --git a/mmv1/third_party/terraform/.teamcity/tests/context_parameters.kt b/mmv1/third_party/terraform/.teamcity/tests/context_parameters.kt index c9f373786be8..373ad78e29fe 100644 --- a/mmv1/third_party/terraform/.teamcity/tests/context_parameters.kt +++ b/mmv1/third_party/terraform/.teamcity/tests/context_parameters.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package tests diff --git a/mmv1/third_party/terraform/.teamcity/tests/nightly_tests_project.kt b/mmv1/third_party/terraform/.teamcity/tests/nightly_tests_project.kt index af3d7b8a9b24..fbdb4d9bd6d3 100644 --- a/mmv1/third_party/terraform/.teamcity/tests/nightly_tests_project.kt +++ b/mmv1/third_party/terraform/.teamcity/tests/nightly_tests_project.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package tests diff --git a/mmv1/third_party/terraform/.teamcity/tests/sweepers.kt b/mmv1/third_party/terraform/.teamcity/tests/sweepers.kt index b05e38573e96..67940004bc68 100644 --- a/mmv1/third_party/terraform/.teamcity/tests/sweepers.kt +++ b/mmv1/third_party/terraform/.teamcity/tests/sweepers.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package tests diff --git a/mmv1/third_party/terraform/.teamcity/tests/test_utils.kt b/mmv1/third_party/terraform/.teamcity/tests/test_utils.kt index 576e4b735c02..162a38eccf5c 100644 --- a/mmv1/third_party/terraform/.teamcity/tests/test_utils.kt +++ b/mmv1/third_party/terraform/.teamcity/tests/test_utils.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package tests diff --git a/mmv1/third_party/terraform/.teamcity/tests/vcs_roots.kt b/mmv1/third_party/terraform/.teamcity/tests/vcs_roots.kt index a46abc0a89af..ae56484af86e 100644 --- a/mmv1/third_party/terraform/.teamcity/tests/vcs_roots.kt +++ b/mmv1/third_party/terraform/.teamcity/tests/vcs_roots.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package tests From 48d346d562b56f53668e2b34e1eab4a536ba097a Mon Sep 17 00:00:00 2001 From: Rostislav Bobrovsky Date: Wed, 13 Mar 2024 14:48:22 +0100 Subject: [PATCH 17/59] Add fields pathTemplateMatch and pathTemplateRewrite to resource google_compute_region_url_map (#10157) --- mmv1/products/compute/RegionUrlMap.yaml | 38 ++++++++ .../region_url_map_path_template_match.tf.erb | 90 +++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 mmv1/templates/terraform/examples/region_url_map_path_template_match.tf.erb diff --git a/mmv1/products/compute/RegionUrlMap.yaml b/mmv1/products/compute/RegionUrlMap.yaml index 69d8e8fcb7ae..2d2645f08398 100644 --- a/mmv1/products/compute/RegionUrlMap.yaml +++ b/mmv1/products/compute/RegionUrlMap.yaml @@ -130,6 +130,15 @@ examples: skip_docs: true skip_test: true # Similar to other samples min_version: beta + - !ruby/object:Provider::Terraform::Examples + name: "region_url_map_path_template_match" + primary_resource_id: "urlmap" + vars: + url_map_name: "urlmap" + home_backend_service_name: "home-service" + cart_backend_service_name: "cart-service" + user_backend_service_name: "user-service" + health_check_name: "health-check" parameters: - !ruby/object:Api::Type::ResourceRef name: 'region' @@ -558,6 +567,18 @@ properties: and anchor supplied with the original URL. For regular expression grammar please see en.cppreference.com/w/cpp/regex/ecmascript Only one of prefixMatch, fullPathMatch or regexMatch must be specified. + - !ruby/object:Api::Type::String + name: 'pathTemplateMatch' + description: | + For satisfying the matchRule condition, the path of the request + must match the wildcard pattern specified in pathTemplateMatch + after removing any query parameters and anchor that may be part + of the original URL. + + pathTemplateMatch must be between 1 and 255 characters + (inclusive). The pattern specified by pathTemplateMatch may + have at most 5 wildcard operators and at most 5 variable + captures in total. - !ruby/object:Api::Type::NestedObject name: 'routeAction' description: | @@ -784,6 +805,23 @@ properties: Prior to forwarding the request to the selected backend service, the matching portion of the request's path is replaced by pathPrefixRewrite. The value must be between 1 and 1024 characters. + - !ruby/object:Api::Type::String + name: 'pathTemplateRewrite' + description: | + Prior to forwarding the request to the selected origin, if the + request matched a pathTemplateMatch, the matching portion of the + request's path is replaced re-written using the pattern specified + by pathTemplateRewrite. + + pathTemplateRewrite must be between 1 and 255 characters + (inclusive), must start with a '/', and must only use variables + captured by the route's pathTemplate matchers. + + pathTemplateRewrite may only be used when all of a route's + MatchRules specify pathTemplate. + + Only one of pathPrefixRewrite and pathTemplateRewrite may be + specified. - !ruby/object:Api::Type::Array name: 'weightedBackendServices' description: | diff --git a/mmv1/templates/terraform/examples/region_url_map_path_template_match.tf.erb b/mmv1/templates/terraform/examples/region_url_map_path_template_match.tf.erb new file mode 100644 index 000000000000..5a7008e1b80b --- /dev/null +++ b/mmv1/templates/terraform/examples/region_url_map_path_template_match.tf.erb @@ -0,0 +1,90 @@ +# [START cloudloadbalancing_url_map_path_template_match] +resource "google_compute_region_url_map" "<%= ctx[:primary_resource_id] %>" { + region = "us-central1" + + name = "<%= ctx[:vars]['url_map_name'] %>" + description = "a description" + + default_service = google_compute_region_backend_service.home-backend.id + + host_rule { + hosts = ["mysite.com"] + path_matcher = "mysite" + } + + path_matcher { + name = "mysite" + default_service = google_compute_region_backend_service.home-backend.id + + route_rules { + match_rules { + path_template_match = "/xyzwebservices/v2/xyz/users/{username=*}/carts/{cartid=**}" + } + service = google_compute_region_backend_service.cart-backend.id + priority = 1 + route_action { + url_rewrite { + path_template_rewrite = "/{username}-{cartid}/" + } + } + } + + route_rules { + match_rules { + path_template_match = "/xyzwebservices/v2/xyz/users/*/accountinfo/*" + } + service = google_compute_region_backend_service.user-backend.id + priority = 2 + } + } +} + +resource "google_compute_region_backend_service" "home-backend" { + region = "us-central1" + + name = "<%= ctx[:vars]['home_backend_service_name'] %>" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + load_balancing_scheme = "EXTERNAL_MANAGED" + + health_checks = [google_compute_region_health_check.default.id] +} + +resource "google_compute_region_backend_service" "cart-backend" { + region = "us-central1" + + name = "<%= ctx[:vars]['cart_backend_service_name'] %>" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + load_balancing_scheme = "EXTERNAL_MANAGED" + + health_checks = [google_compute_region_health_check.default.id] +} + +resource "google_compute_region_backend_service" "user-backend" { + region = "us-central1" + + name = "<%= ctx[:vars]['user_backend_service_name'] %>" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + load_balancing_scheme = "EXTERNAL_MANAGED" + + health_checks = [google_compute_region_health_check.default.id] +} + +resource "google_compute_region_health_check" "default" { + region = "us-central1" + + name = "<%= ctx[:vars]['health_check_name'] %>" + check_interval_sec = 1 + timeout_sec = 1 + http_health_check { + port = 80 + request_path = "/" + } +} + +# [END cloudloadbalancing_url_map_path_template_match] From 6fc834e51978806baacac87ecd978efc9dfc8dc8 Mon Sep 17 00:00:00 2001 From: Mauricio Alvarez Leon <65101411+BBBmau@users.noreply.github.com> Date: Wed, 13 Mar 2024 07:14:18 -0700 Subject: [PATCH 18/59] Refactor TeamCity Services Diff Check to run as one job (#10158) --- .github/actions/build-downstream/action.yml | 105 ++++++++++++++++++ .../teamcity-services-diff-check-weekly.yml | 86 ++++++-------- .../teamcity-services-diff-check.yml | 80 +++++-------- 3 files changed, 166 insertions(+), 105 deletions(-) create mode 100644 .github/actions/build-downstream/action.yml diff --git a/.github/actions/build-downstream/action.yml b/.github/actions/build-downstream/action.yml new file mode 100644 index 000000000000..012248b10862 --- /dev/null +++ b/.github/actions/build-downstream/action.yml @@ -0,0 +1,105 @@ +name: build +description: Generates given downstream Magic Modules Repository from `repo` input +inputs: + repo: + description: "provider repo" + required: true + token: + description: "github token" + required: true + +runs: + using: "composite" + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Ruby + uses: ruby/setup-ruby@036ef458ddccddb148a2b9fb67e95a22fdbf728b # v1.160.0 + with: + ruby-version: '3.1' + + - name: Cache Bundler gems + uses: actions/cache@v3 + with: + path: mmv1/vendor/bundle + key: ${{ runner.os }}-gems-${{ hashFiles('mmv1/**/Gemfile.lock') }} + restore-keys: | + ${{ runner.os }}-gems- + + - name: Install Ruby dependencies + shell: bash + run: | + bundle config path mmv1/vendor/bundle + bundle install + working-directory: mmv1 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: '^1.20' + + # Cache Go modules + - name: Cache Go modules + uses: actions/cache@v3 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - run: go install golang.org/x/tools/cmd/goimports@latest + shell: bash + - name: Build ${{ inputs.repo }} + shell: bash + env: + BASE_BRANCH: ${{ github.event.pull_request.base.ref || github.ref_name }} + GITHUB_TOKEN: ${{ inputs.token }} + run: | + set -e + set -x + # Set GOPATH to a directory the runner user has access to + export GOPATH=~/go + + function clone_repo() { + export OUTPUT_PATH=$GOPATH/src/github.com/$UPSTREAM_OWNER/$GH_REPO + echo "OUTPUT_PATH=$OUTPUT_PATH" >> $GITHUB_ENV + GITHUB_PATH=https://x-access-token:$GITHUB_TOKEN@github.com/$UPSTREAM_OWNER/$GH_REPO + mkdir -p "$(dirname $OUTPUT_PATH)" + git clone $GITHUB_PATH $OUTPUT_PATH --branch $BASE_BRANCH + } + + GH_REPO="${{ inputs.repo }}" + if [ "$GH_REPO" == "docs-examples" ] && [ "$BASE_BRANCH" == "main" ]; then + BASE_BRANCH="master" + fi + + GITHUB_PATH=https://x-access-token:$GITHUB_TOKEN@github.com/$UPSTREAM_OWNER/$GH_REPO + + if [[ "$GH_REPO" == terraform-provider-google* ]]; then + UPSTREAM_OWNER=hashicorp + clone_repo + if [ "$GH_REPO" == "terraform-provider-google" ]; then + export VERSION=ga + else + export VERSION=beta + fi + make clean-provider + make provider + elif [ "$GH_REPO" == "terraform-google-conversion" ]; then + UPSTREAM_OWNER=GoogleCloudPlatform + clone_repo + make clean-tgc + make tgc + elif [ "$GH_REPO" == "docs-examples" ]; then + UPSTREAM_OWNER=terraform-google-modules + clone_repo + make tf-oics + else + echo "case not supported" + exit 1 + fi + + (current_dir=$(pwd) && cd $OUTPUT_PATH && zip -r "$current_dir/output.zip" .) \ No newline at end of file diff --git a/.github/workflows/teamcity-services-diff-check-weekly.yml b/.github/workflows/teamcity-services-diff-check-weekly.yml index 1d0bf90820c5..355501e14d51 100644 --- a/.github/workflows/teamcity-services-diff-check-weekly.yml +++ b/.github/workflows/teamcity-services-diff-check-weekly.yml @@ -11,57 +11,37 @@ on: - cron: '0 4 * * 1-2' jobs: - terraform-provider-google: - uses: ./.github/workflows/build-downstream.yml - with: - repo: 'terraform-provider-google' - - terraform-provider-google-beta: - uses: ./.github/workflows/build-downstream.yml - with: - repo: 'terraform-provider-google-beta' - teamcity-services-diff-check: - needs: [terraform-provider-google, terraform-provider-google-beta] - runs-on: ubuntu-22.04 - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - - name: Setup Go - uses: actions/setup-go@v4 - with: - go-version: '^1.20' - - - name: Download built artifacts - GA provider - uses: actions/download-artifact@v2 - with: - name: artifact-terraform-provider-google - path: artifacts - - - name: Unzip the artifacts and delete the zip - run: | - unzip -o artifacts/output.zip -d ./provider - rm artifacts/output.zip - - - name: Download built artifacts - Beta provider - uses: actions/download-artifact@v2 - with: - name: artifact-terraform-provider-google-beta - path: artifacts - - - name: Unzip the artifacts and delete the zip - run: | - unzip -o artifacts/output.zip -d ./provider - rm artifacts/output.zip - - - name: Check that new services have been added to the TeamCity configuration code - run: | - # Create lists of service packages in providers - ls provider/google/services > tools/teamcity-diff-check/services_ga.txt - ls provider/google-beta/services > tools/teamcity-diff-check/services_beta.txt - - # Run tool to compare service packages in the providers vs those listed in TeamCity config files - cd tools/teamcity-diff-check - go run main.go -service_file=services_ga - go run main.go -service_file=services_beta + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + runs-on: ubuntu-22.04 + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + - name: TeamCity Google Provider Generate + uses: ./.github/actions/build-downstream + with: + repo: 'terraform-provider-google' + token: '$GITHUB_TOKEN' + # The path where GA/Beta providers are generated is grabbed from the OUTPUT_PATH that's set in build_downstream.yaml + # export OUTPUT_PATH=$GOPATH/src/github.com/$UPSTREAM_OWNER/$GH_REPO + # OUTPUT_PATH changes after each generate (GA/beta) + - name: Set GOOGLE_REPO_PATH to path where GA provider was generated + run: echo "GOOGLE_REPO_PATH=${{ env.OUTPUT_PATH}}" >> $GITHUB_ENV + - name: TeamCity Google Beta Provider Generate + uses: ./.github/actions/build-downstream + with: + repo: 'terraform-provider-google-beta' + token: '$GITHUB_TOKEN' + - name: Set GOOGLE_BETA_REPO_PATH to path where beta provider was generated + run: echo "GOOGLE_BETA_REPO_PATH=${{ env.OUTPUT_PATH}}" >> $GITHUB_ENV + - name: Check that new services have been added to the TeamCity configuration code + run: | + # Create lists of service packages in providers + ls ${{env.GOOGLE_REPO_PATH}}/google/services > tools/teamcity-diff-check/services_ga.txt + ls ${{env.GOOGLE_BETA_REPO_PATH}}/google-beta/services > tools/teamcity-diff-check/services_beta.txt + + # Run tool to compare service packages in the providers vs those listed in TeamCity config files + cd tools/teamcity-diff-check + go run main.go -service_file=services_ga + go run main.go -service_file=services_beta diff --git a/.github/workflows/teamcity-services-diff-check.yml b/.github/workflows/teamcity-services-diff-check.yml index 37dd8e218554..9ffee2130bdb 100644 --- a/.github/workflows/teamcity-services-diff-check.yml +++ b/.github/workflows/teamcity-services-diff-check.yml @@ -9,10 +9,10 @@ on: - 'mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt' - 'mmv1/products/**' jobs: - check-pr: + teamcity-services-diff-check: + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} runs-on: ubuntu-22.04 - outputs: - services: ${{steps.services.outputs.services}} steps: - name: Checkout Repository uses: actions/checkout@v4 @@ -24,61 +24,37 @@ jobs: newServices=$(($(git diff --name-only --diff-filter=A origin/main HEAD | grep -P "mmv1/products/.*/product.yaml" | wc -l))) echo "services=$newServices" >> "${GITHUB_OUTPUT}" if [ "$newServices" = "0" ];then - echo "No new service found." + echo "No new service found." fi - terraform-provider-google: - if: ${{needs.check-pr.outputs.services != '0'}} - needs: check-pr - uses: ./.github/workflows/build-downstream.yml - with: - repo: 'terraform-provider-google' - - terraform-provider-google-beta: - if: ${{needs.check-pr.outputs.services != '0'}} - needs: check-pr - uses: ./.github/workflows/build-downstream.yml - with: - repo: 'terraform-provider-google-beta' - - teamcity-services-diff-check: - needs: [terraform-provider-google, terraform-provider-google-beta] - runs-on: ubuntu-22.04 - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - - name: Setup Go - uses: actions/setup-go@v4 + - name: TeamCity Google Provider Generate + id: generate + if: ${{steps.services.outputs.services != '0'}} + uses: ./.github/actions/build-downstream with: - go-version: '^1.20' - - - name: Download built artifacts - GA provider - uses: actions/download-artifact@v2 + repo: 'terraform-provider-google' + token: '$GITHUB_TOKEN' + # The path where GA/Beta providers are generated is grabbed from the OUTPUT_PATH that's set in build_downstream.yaml + # export OUTPUT_PATH=$GOPATH/src/github.com/$UPSTREAM_OWNER/$GH_REPO + # OUTPUT_PATH changes after each generate (GA/beta) + - name: Set GOOGLE_REPO_PATH to path where GA provider was generated + run: echo "GOOGLE_REPO_PATH=${{ env.OUTPUT_PATH}}" >> $GITHUB_ENV + - name: TeamCity Google Beta Provider Generate + if: steps.generate.outcome == 'success' + uses: ./.github/actions/build-downstream with: - name: artifact-terraform-provider-google - path: artifacts - - - name: Unzip the artifacts and delete the zip - run: | - unzip -o artifacts/output.zip -d ./provider - rm artifacts/output.zip - - - name: Download built artifacts - Beta provider - uses: actions/download-artifact@v2 - with: - name: artifact-terraform-provider-google-beta - path: artifacts - - - name: Unzip the artifacts and delete the zip - run: | - unzip -o artifacts/output.zip -d ./provider - rm artifacts/output.zip - + repo: 'terraform-provider-google-beta' + token: '$GITHUB_TOKEN' + - name: Set GOOGLE_BETA_REPO_PATH to path where beta provider was generated + run: echo "GOOGLE_BETA_REPO_PATH=${{ env.OUTPUT_PATH}}" >> $GITHUB_ENV + - name: Checkout Repository + if: steps.generate.outcome == 'success' + uses: actions/checkout@v4 - name: Check that new services have been added to the TeamCity configuration code + if: steps.generate.outcome == 'success' run: | # Create lists of service packages in providers - ls provider/google/services > tools/teamcity-diff-check/services_ga.txt - ls provider/google-beta/services > tools/teamcity-diff-check/services_beta.txt + ls ${{env.GOOGLE_REPO_PATH}}/google/services > tools/teamcity-diff-check/services_ga.txt + ls ${{env.GOOGLE_BETA_REPO_PATH}}/google-beta/services > tools/teamcity-diff-check/services_beta.txt # Run tool to compare service packages in the providers vs those listed in TeamCity config files cd tools/teamcity-diff-check From ec1164c823f43e0d962467a791c3bff0b27c7c4a Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Wed, 13 Mar 2024 15:50:37 +0000 Subject: [PATCH 19/59] Add explicity dependency on IAM in PubSub acc test config (#9921) --- .../pubsub/resource_pubsub_subscription_test.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/mmv1/third_party/terraform/services/pubsub/resource_pubsub_subscription_test.go b/mmv1/third_party/terraform/services/pubsub/resource_pubsub_subscription_test.go index 11f8b050283d..25529a550cc2 100644 --- a/mmv1/third_party/terraform/services/pubsub/resource_pubsub_subscription_test.go +++ b/mmv1/third_party/terraform/services/pubsub/resource_pubsub_subscription_test.go @@ -446,10 +446,15 @@ resource "google_pubsub_subscription" "foo" { name = "%s" topic = google_pubsub_topic.foo.id - bigquery_config { - table = "${google_bigquery_table.test.project}.${google_bigquery_table.test.dataset_id}.${google_bigquery_table.test.table_id}" - use_table_schema = %t - } + bigquery_config { + table = "${google_bigquery_table.test.project}.${google_bigquery_table.test.dataset_id}.${google_bigquery_table.test.table_id}" + use_table_schema = %t + } + + depends_on = [ + google_project_iam_member.viewer, + google_project_iam_member.editor + ] } `, dataset, table, topic, subscription, useTableSchema) } From ab93c2fa8e1bfa0bb4292a9296d0052899be3ae0 Mon Sep 17 00:00:00 2001 From: Ryan Oaks Date: Wed, 13 Mar 2024 13:20:33 -0400 Subject: [PATCH 20/59] Improve the error messages when mmv1 compilation fails (#10191) --- mmv1/compiler.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mmv1/compiler.rb b/mmv1/compiler.rb index 2e4bc8b5b3ce..0f61a8eb4ccc 100755 --- a/mmv1/compiler.rb +++ b/mmv1/compiler.rb @@ -192,6 +192,9 @@ ) resource.validate resources.push(resource) + rescue StandardError => e + Google::LOGGER.error "Failed to compile #{file_path}: #{e}" + raise e end if override_dir @@ -221,6 +224,9 @@ ) resource.validate resources.push(resource) + rescue StandardError => e + Google::LOGGER.error "Failed to compile using override #{override_path}: #{e}" + raise e end end resources = resources.sort_by(&:name) From ab05386925a64c265787f3014486b797bae335f4 Mon Sep 17 00:00:00 2001 From: Ryan Oaks Date: Wed, 13 Mar 2024 14:41:54 -0400 Subject: [PATCH 21/59] Update enrolled teams (#10192) --- tools/issue-labeler/labeler/enrolled_teams.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/issue-labeler/labeler/enrolled_teams.yml b/tools/issue-labeler/labeler/enrolled_teams.yml index f2d88536d0c8..8da24bb5c517 100755 --- a/tools/issue-labeler/labeler/enrolled_teams.yml +++ b/tools/issue-labeler/labeler/enrolled_teams.yml @@ -327,6 +327,7 @@ service/filestore: resources: - google_filestore_.* service/firebase: + team: firebase-terraform resources: - google_firebase_.* - google_firebaserules_.* @@ -529,6 +530,7 @@ service/redis-instance: resources: - google_redis_instance service/run: + team: cloud-run-control-plane resources: - google_cloud_run_.* - google_cloud_run_v2_.* From ab811636776f9e49966a52deb44ea44cf1431ee3 Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Wed, 13 Mar 2024 13:15:38 -0700 Subject: [PATCH 22/59] Fix generate comment diff processor build failure (#10164) * Refactored generate_comment to continue in the face of errors Also switched to go template for comment formatting * Moved to structured data for diffs Also added error formatting into comment * Added basic tests for comment formatting * Skipped missing tests and breaking changes if repo failed to clone * Force generation * Breaking change * Fixed error display in diff comment * Marked diff-processor targets as not being real files * Added PATH to diffProcessorEnv * Fixed formatting for error sections * Cleaned up passthrough env var usage * Made exec.sh exit 1 if there are any errors running the magician * Don't error on initial build of the magician binary * Added missing env var for diff processor build * Force generation of tf-oics * Revert "Force generation of tf-oics" This reverts commit fcb65f121cbb0f7040a6b40c635eae3b318d936d. * Revert "Force generation" This reverts commit 596d1eb5afb10d36ab934411e0f1c47aa8b363e9. * Revert "Breaking change" This reverts commit fb04ad401e1d4ee93ef767297a2a59af7d2acffa. * Force missing test run * force missing tests to run - take 2 * Revert "force missing tests to run - take 2" This reverts commit 34f7d16a8442f09aa4a52e0ceafb8dae73f89b08. * Revert "Force missing test run" This reverts commit 90e664a935c4645314c3aabf1f48836e4547fc68. --- .ci/magician/cmd/DIFF_COMMENT.md | 36 ++ .ci/magician/cmd/generate_comment.go | 466 ++++++++++++---------- .ci/magician/cmd/generate_comment_test.go | 192 +++++++-- .ci/magician/cmd/mock_runner_test.go | 53 +-- .ci/magician/source/repo.go | 2 +- .ci/scripts/go-plus/magician/exec.sh | 2 + tools/diff-processor/GNUmakefile | 2 + 7 files changed, 488 insertions(+), 265 deletions(-) create mode 100644 .ci/magician/cmd/DIFF_COMMENT.md diff --git a/.ci/magician/cmd/DIFF_COMMENT.md b/.ci/magician/cmd/DIFF_COMMENT.md new file mode 100644 index 000000000000..b2c44b960823 --- /dev/null +++ b/.ci/magician/cmd/DIFF_COMMENT.md @@ -0,0 +1,36 @@ +Hi there, I'm the Modular magician. I've detected the following information about your changes: + +## Diff report +{{ $diffsLength := len .Diffs }}{{if eq $diffsLength 0 }} +Your PR hasn't generated any diffs, but I'll let you know if a future commit does. +{{else}} +Your PR generated some diffs in downstreams - here they are. + +{{range .Diffs -}} +{{.Title}}: [Diff](https://github.com/modular-magician/{{.Repo}}/compare/auto-pr-{{$.PrNumber}}-old..auto-pr-{{$.PrNumber}}) ({{.DiffStats}}) +{{end -}} +{{end -}} + +{{- $breakingChangesLength := len .BreakingChanges }} +{{- if gt $breakingChangesLength 0}} +## Breaking Change(s) Detected + +The following breaking change(s) were detected within your pull request. + +{{- range .BreakingChanges}} +- {{.}}{{end}} + +If you believe this detection to be incorrect please raise the concern with your reviewer. +If you intend to make this change you will need to wait for a [major release](https://www.terraform.io/plugin/sdkv2/best-practices/versioning#example-major-number-increments) window. +An `override-breaking-change` label can be added to allow merging. +{{end}} +{{.MissingTests}} +{{- $errorsLength := len .Errors}} +{{- if gt $errorsLength 0}} +## Errors +{{range .Errors}} +{{.Title}}: +{{- range .Errors}} +- {{.}}{{end}} +{{end}} +{{- end -}} \ No newline at end of file diff --git a/.ci/magician/cmd/generate_comment.go b/.ci/magician/cmd/generate_comment.go index b78bbf35fd3c..d1d5cd2936b4 100644 --- a/.ci/magician/cmd/generate_comment.go +++ b/.ci/magician/cmd/generate_comment.go @@ -23,12 +23,41 @@ import ( "magician/source" "os" "path/filepath" - "regexp" + "sort" + "strconv" "strings" + "text/template" "github.com/spf13/cobra" + "golang.org/x/exp/maps" + + _ "embed" +) + +var ( + //go:embed DIFF_COMMENT.md + diffComment string ) +type Diff struct { + Title string + Repo string + DiffStats string +} + +type Errors struct { + Title string + Errors []string +} + +type diffCommentData struct { + PrNumber int + Diffs []Diff + BreakingChanges []string + MissingTests string + Errors []Errors +} + const allowBreakingChangesLabel = "override-breaking-change" var gcEnvironmentVariables = [...]string{ @@ -84,7 +113,22 @@ var generateCommentCmd = &cobra.Command{ os.Exit(1) } ctlr := source.NewController(filepath.Join("workspace", "go"), "modular-magician", env["GITHUB_TOKEN_DOWNSTREAMS"], rnr) - execGenerateComment(env, gh, rnr, ctlr) + prNumber, err := strconv.Atoi(env["PR_NUMBER"]) + if err != nil { + fmt.Println("Error parsing PR_NUMBER: ", err) + os.Exit(1) + } + execGenerateComment( + prNumber, + env["GITHUB_TOKEN_MAGIC_MODULES"], + env["BUILD_ID"], + env["BUILD_STEP"], + env["PROJECT_ID"], + env["COMMIT_SHA"], + gh, + rnr, + ctlr, + ) }, } @@ -96,196 +140,219 @@ func listGCEnvironmentVariables() string { return result } -func execGenerateComment(env map[string]string, gh GithubClient, rnr ExecRunner, ctlr *source.Controller) { - newBranch := "auto-pr-" + env["PR_NUMBER"] - oldBranch := "auto-pr-" + env["PR_NUMBER"] + "-old" +func execGenerateComment(prNumber int, ghTokenMagicModules, buildId, buildStep, projectId, commitSha string, gh GithubClient, rnr ExecRunner, ctlr *source.Controller) { + newBranch := fmt.Sprintf("auto-pr-%d", prNumber) + oldBranch := fmt.Sprintf("auto-pr-%d-old", prNumber) wd := rnr.GetCWD() mmLocalPath := filepath.Join(wd, "..", "..") - tpgRepoName := "terraform-provider-google" - tpgLocalPath := filepath.Join(mmLocalPath, "..", "tpg") - tpgbRepoName := "terraform-provider-google-beta" - tpgbLocalPath := filepath.Join(mmLocalPath, "..", "tpgb") - tfoicsRepoName := "docs-examples" - tfoicsLocalPath := filepath.Join(mmLocalPath, "..", "tfoics") - // For backwards compatibility until at least Nov 15 2021 - tfcRepoName := "terraform-google-conversion" - tfcLocalPath := filepath.Join(mmLocalPath, "..", "tfc") - - var diffs string - for _, repo := range []*source.Repo{ - { - Name: tpgRepoName, - Title: "Terraform GA", - Path: tpgLocalPath, - }, - { - Name: tpgbRepoName, - Title: "Terraform Beta", - Path: tpgbLocalPath, - }, - { - Name: tfcRepoName, - Title: "TF Conversion", - Path: tfcLocalPath, - DiffCanFail: true, - }, - { - Name: tfoicsRepoName, - Title: "TF OiCS", - Path: tfoicsLocalPath, - }, - } { - // TPG/TPGB difference - repoDiffs, err := cloneAndDiff(repo, oldBranch, newBranch, ctlr) + + tpgRepo := source.Repo{ + Name: "terraform-provider-google", + Title: "`google` provider", + Path: filepath.Join(mmLocalPath, "..", "tpg"), + Version: provider.GA, + } + tpgbRepo := source.Repo{ + Name: "terraform-provider-google-beta", + Title: "`google-beta` provider", + Path: filepath.Join(mmLocalPath, "..", "tpgb"), + Version: provider.Beta, + } + tgcRepo := source.Repo{ + Name: "terraform-google-conversion", + Title: "`terraform-google-conversion`", + Path: filepath.Join(mmLocalPath, "..", "tgc"), + Version: provider.Beta, + } + tfoicsRepo := source.Repo{ + Name: "docs-examples", + Title: "Open in Cloud Shell", + Path: filepath.Join(mmLocalPath, "..", "tfoics"), + } + + // Initialize repos + data := diffCommentData{ + PrNumber: prNumber, + } + errors := map[string][]string{"Other": []string{}} + var err error + for _, repo := range []*source.Repo{&tpgRepo, &tpgbRepo, &tgcRepo, &tfoicsRepo} { + errors[repo.Title] = []string{} + repo.Branch = newBranch + if err := ctlr.Clone(repo); err != nil { + fmt.Println("Failed to clone repo: ", err) + errors[repo.Title] = append(errors[repo.Title], "Failed to clone repo") + } else { + repo.Cloned = true + } + } + + diffs := []Diff{} + for _, repo := range []source.Repo{tpgRepo, tpgbRepo, tgcRepo, tfoicsRepo} { + if !repo.Cloned { + fmt.Println("Skipping diff; repo failed to clone: ", repo.Name) + continue + } + diffStats, err := computeDiff(&repo, oldBranch, ctlr) if err != nil { - fmt.Printf("Error cloning and diffing tpg repo: %v\n", err) - if !repo.DiffCanFail { - os.Exit(1) - } + fmt.Println("diffing repo: ", err) + errors[repo.Title] = append(errors[repo.Title], "Failed to compute repo diff stats") } - if repoDiffs != "" { - diffs += "\n" + repoDiffs + if diffStats != "" { + diffs = append(diffs, Diff{ + Title: repo.Title, + Repo: repo.Name, + DiffStats: diffStats, + }) } } + data.Diffs = diffs - var showBreakingChangesFailed bool - var err error + // The breaking changes are unique across both provider versions + uniqueBreakingChanges := map[string]struct{}{} diffProcessorPath := filepath.Join(mmLocalPath, "tools", "diff-processor") - // versionedBreakingChanges is a map of breaking change output by provider version. - versionedBreakingChanges := make(map[provider.Version]string, 2) - - env["OLD_REF"] = oldBranch - env["NEW_REF"] = newBranch - for _, repo := range []*source.Repo{ - { - Title: "TPG", - Path: tpgLocalPath, - Version: provider.GA, - }, - { - Title: "TPGB", - Path: tpgbLocalPath, - Version: provider.Beta, - }, - } { - // TPG(B) diff processor - err = buildDiffProcessor(diffProcessorPath, repo.Path, env, rnr) + diffProcessorEnv := map[string]string{ + "OLD_REF": oldBranch, + "NEW_REF": newBranch, + // Passthrough vars required for a valid build environment. + "PATH": os.Getenv("PATH"), + "GOPATH": os.Getenv("GOPATH"), + "HOME": os.Getenv("HOME"), + } + for _, repo := range []source.Repo{tpgRepo, tpgbRepo} { + if !repo.Cloned { + fmt.Println("Skipping breaking changes; repo failed to clone: ", repo.Name) + continue + } + err = buildDiffProcessor(diffProcessorPath, repo.Path, diffProcessorEnv, rnr) if err != nil { - fmt.Println(err) - os.Exit(1) + fmt.Println("building diff processor: ", err) + errors[repo.Title] = append(errors[repo.Title], "The diff processor failed to build. This is usually due to the downstream provider failing to compile.") + continue } - output, err := computeBreakingChanges(diffProcessorPath, rnr) + + breakingChanges, err := computeBreakingChanges(diffProcessorPath, rnr) if err != nil { - fmt.Println("Error computing TPG breaking changes: ", err) - showBreakingChangesFailed = true + fmt.Println("computing breaking changes: ", err) + errors[repo.Title] = append(errors[repo.Title], "The diff processor crashed while computing breaking changes. This is usually due to the downstream provider failing to compile.") + } + for _, breakingChange := range breakingChanges { + uniqueBreakingChanges[breakingChange] = struct{}{} } - versionedBreakingChanges[repo.Version] = strings.TrimSuffix(output, "\n") - err = addLabels(diffProcessorPath, env, rnr) + + addLabelsEnv := map[string]string{ + "GITHUB_TOKEN_MAGIC_MODULES": ghTokenMagicModules, + } + err = addLabels(prNumber, diffProcessorPath, addLabelsEnv, rnr) if err != nil { - fmt.Println("Error adding TPG labels to PR: ", err) + fmt.Println("adding service labels: ", err) + errors[repo.Title] = append(errors[repo.Title], "The diff processor crashed while adding labels.") } err = cleanDiffProcessor(diffProcessorPath, rnr) if err != nil { - fmt.Println("Error cleaning up diff processor: ", err) - os.Exit(1) + fmt.Println("cleaning up diff processor: ", err) + errors[repo.Title] = append(errors[repo.Title], "The diff processor failed to clean up properly.") } } + breakingChangesSlice := maps.Keys(uniqueBreakingChanges) + sort.Strings(breakingChangesSlice) + data.BreakingChanges = breakingChangesSlice - var breakingChanges string - if showBreakingChangesFailed { - breakingChanges = `## Breaking Change Detection Failed -The breaking change detector crashed during execution. This is usually due to the downstream provider(s) failing to compile. Please investigate or follow up with your reviewer.` - } else { - breakingChanges = combineBreakingChanges(versionedBreakingChanges[provider.GA], versionedBreakingChanges[provider.Beta]) - } - - // Missing test detector - missingTests, err := detectMissingTests(mmLocalPath, tpgbLocalPath, oldBranch, rnr) - if err != nil { - fmt.Println("Error setting up missing test detector: ", err) - os.Exit(1) - } - - message := "Hi there, I'm the Modular magician. I've detected the following information about your changes:\n\n" + // Update breaking changes status on PR breakingState := "success" - if breakingChanges != "" { - message += breakingChanges + "\n\n" + if len(uniqueBreakingChanges) > 0 { + breakingState = "failure" - pullRequest, err := gh.GetPullRequest(env["PR_NUMBER"]) + pullRequest, err := gh.GetPullRequest(strconv.Itoa(prNumber)) if err != nil { fmt.Printf("Error getting pull request: %v\n", err) - os.Exit(1) - } - - breakingChangesAllowed := false - for _, label := range pullRequest.Labels { - if label.Name == allowBreakingChangesLabel { - breakingChangesAllowed = true - break + errors["Other"] = append(errors["Other"], "Failed to check for `override-breaking-change` label") + } else { + for _, label := range pullRequest.Labels { + if label.Name == allowBreakingChangesLabel { + breakingState = "success" + break + } } } - if !breakingChangesAllowed { - breakingState = "failure" - } } - - if diffs == "" { - message += "## Diff report\nYour PR hasn't generated any diffs, but I'll let you know if a future commit does." - } else { - message += "## Diff report\nYour PR generated some diffs in downstreams - here they are.\n" + diffs + "\n" - if missingTests != "" { - message += "\n" + missingTests + "\n" - } + targetURL := fmt.Sprintf("https://console.cloud.google.com/cloud-build/builds;region=global/%s;step=%s?project=%s", buildId, buildStep, projectId) + if err = gh.PostBuildStatus(strconv.Itoa(prNumber), "terraform-provider-breaking-change-test", breakingState, targetURL, commitSha); err != nil { + fmt.Printf("Error posting build status for pr %d commit %s: %v\n", prNumber, commitSha, err) + errors["Other"] = append(errors["Other"], "Failed to update breaking-change status check with state: "+breakingState) } - if err := gh.PostComment(env["PR_NUMBER"], message); err != nil { - fmt.Printf("Error posting comment to PR %s: %v\n", env["PR_NUMBER"], err) + // Run missing test detector (currently only for beta) + missingTestsPath := mmLocalPath + for _, repo := range []source.Repo{tpgbRepo} { + if !repo.Cloned { + fmt.Println("Skipping missing tests; repo failed to clone: ", repo.Name) + continue + } + missingTests, err := detectMissingTests(missingTestsPath, repo.Path, oldBranch, rnr) + if err != nil { + fmt.Println("Error running missing test detector: ", err) + errors[repo.Title] = append(errors[repo.Title], "The missing test detector failed to run.") + } + data.MissingTests = missingTests + } + + // Run unit tests for missing test detector + if err = runMissingTestUnitTests( + mmLocalPath, + tpgbRepo.Path, + targetURL, + commitSha, + prNumber, + gh, + rnr, + ); err != nil { + fmt.Println("Error running missing test detector unit tests: ", err) + errors["Other"] = append(errors["Other"], "Missing test detector unit tests failed to run.") + } + + // Add errors to data as an ordered list + errorsList := []Errors{} + for _, repo := range []source.Repo{tpgRepo, tpgbRepo, tgcRepo, tfoicsRepo} { + if len(errors[repo.Title]) > 0 { + errorsList = append(errorsList, Errors{ + Title: repo.Title, + Errors: errors[repo.Title], + }) + } } - - targetURL := fmt.Sprintf("https://console.cloud.google.com/cloud-build/builds;region=global/%s;step=%s?project=%s", env["BUILD_ID"], env["BUILD_STEP"], env["PROJECT_ID"]) - if err := gh.PostBuildStatus(env["PR_NUMBER"], "terraform-provider-breaking-change-test", breakingState, targetURL, env["COMMIT_SHA"]); err != nil { - fmt.Printf("Error posting build status for pr %s commit %s: %v\n", env["PR_NUMBER"], env["COMMIT_SHA"], err) - os.Exit(1) + if len(errors["Other"]) > 0 { + errorsList = append(errorsList, Errors{ + Title: "Other", + Errors: errors["Other"], + }) } + data.Errors = errorsList - if err := rnr.PushDir(mmLocalPath); err != nil { - fmt.Println(err) + // Post diff comment + message, err := formatDiffComment(data) + if err != nil { + fmt.Println("Error formatting message: ", err) + fmt.Printf("Data: %v\n", data) os.Exit(1) } - if diffs := rnr.MustRun("git", []string{"diff", "HEAD", "origin/main", "tools/missing-test-detector"}, nil); diffs != "" { - fmt.Printf("Found diffs in missing test detector:\n%s\nRunning tests.\n", diffs) - if err := testTools(mmLocalPath, tpgbLocalPath, env, gh, rnr); err != nil { - fmt.Printf("Error testing tools in %s: %v\n", mmLocalPath, err) - os.Exit(1) - } - } - if err := rnr.PopDir(); err != nil { - fmt.Println(err) + if err := gh.PostComment(strconv.Itoa(prNumber), message); err != nil { + fmt.Printf("Error posting comment to PR %d: %v\n", prNumber, err) + fmt.Println("Comment: ", message) os.Exit(1) } } -func cloneAndDiff(repo *source.Repo, oldBranch, newBranch string, ctlr *source.Controller) (string, error) { - // Clone the repo to the desired repo.Path. - repo.Branch = newBranch - if err := ctlr.Clone(repo); err != nil { - return "", fmt.Errorf("error cloning %s: %v\n", repo.Name, err) - } - +func computeDiff(repo *source.Repo, oldBranch string, ctlr *source.Controller) (string, error) { if err := ctlr.Fetch(repo, oldBranch); err != nil { return "", err } - - // Return summary, if any. - diffs, err := ctlr.Diff(repo, oldBranch, newBranch) + // Get shortstat summary of the diff + diff, err := ctlr.Diff(repo, oldBranch, repo.Branch) if err != nil { return "", err } - if diffs == "" { - return "", nil - } - diffs = strings.TrimSuffix(diffs, "\n") - return fmt.Sprintf("%s: [Diff](https://github.com/modular-magician/%s/compare/%s..%s) (%s)", repo.Title, repo.Name, oldBranch, newBranch, diffs), nil + return strings.TrimSuffix(diff, "\n"), nil } // Build the diff processor for tpg or tpgb @@ -304,22 +371,27 @@ func buildDiffProcessor(diffProcessorPath, providerLocalPath string, env map[str return rnr.PopDir() } -func computeBreakingChanges(diffProcessorPath string, rnr ExecRunner) (string, error) { +func computeBreakingChanges(diffProcessorPath string, rnr ExecRunner) ([]string, error) { if err := rnr.PushDir(diffProcessorPath); err != nil { - return "", err + return nil, err } - breakingChanges, err := rnr.Run("bin/diff-processor", []string{"breaking-changes"}, nil) + output, err := rnr.Run("bin/diff-processor", []string{"breaking-changes"}, nil) if err != nil { - return "", err + return nil, err + } + + if output == "" { + return nil, nil } - return breakingChanges, rnr.PopDir() + + return strings.Split(strings.TrimSuffix(output, "\n"), "\n"), rnr.PopDir() } -func addLabels(diffProcessorPath string, env map[string]string, rnr ExecRunner) error { +func addLabels(prNumber int, diffProcessorPath string, env map[string]string, rnr ExecRunner) error { if err := rnr.PushDir(diffProcessorPath); err != nil { return err } - output, err := rnr.Run("bin/diff-processor", []string{"add-labels", env["PR_NUMBER"]}, env) + output, err := rnr.Run("bin/diff-processor", []string{"add-labels", strconv.Itoa(prNumber)}, env) fmt.Println(output) if err != nil { return err @@ -336,48 +408,6 @@ func cleanDiffProcessor(diffProcessorPath string, rnr ExecRunner) error { return nil } -// Get the breaking change message including the unique tpg messages and all tpgb messages. -func combineBreakingChanges(tpgBreaking, tpgbBreaking string) string { - var allMessages []string - if tpgBreaking == "" { - if tpgbBreaking == "" { - return "" - } - allMessages = strings.Split(tpgbBreaking, "\n") - } else if tpgbBreaking == "" { - allMessages = strings.Split(tpgBreaking, "\n") - } else { - dashExp := regexp.MustCompile("-.*") - tpgMessages := strings.Split(tpgBreaking, "\n") - tpgbMessages := strings.Split(tpgbBreaking, "\n") - tpgbSet := make(map[string]struct{}, len(tpgbMessages)) - var tpgUnique []string - for _, message := range tpgbMessages { - simple := dashExp.ReplaceAllString(message, "") - tpgbSet[simple] = struct{}{} - } - for _, message := range tpgMessages { - simple := dashExp.ReplaceAllString(message, "") - if _, ok := tpgbSet[simple]; !ok { - tpgUnique = append(tpgUnique, message) - } - } - allMessages = append(tpgUnique, tpgbMessages...) - } - if len(allMessages) > 0 { - return `## Breaking Change(s) Detected -The following breaking change(s) were detected within your pull request. - -* ` + strings.Join(allMessages, "\n* ") + ` - -If you believe this detection to be incorrect please raise the concern with your reviewer. -If you intend to make this change you will need to wait for a [major release](https://www.terraform.io/plugin/sdkv2/best-practices/versioning#example-major-number-increments) window. -An ` + "`override-breaking-change`" + ` label can be added to allow merging. -` - } - return "" -} - // Run the missing test detector and return the results. // Returns an empty string unless there are missing tests. // Error will be nil unless an error occurs during setup. @@ -449,9 +479,24 @@ func updatePackageName(name, path string, rnr ExecRunner) error { return rnr.PopDir() } -// Run unit tests for the missing test detector and diff processor. +// Run unit tests for the missing test detector. // Report results using Github API. -func testTools(mmLocalPath, tpgbLocalPath string, env map[string]string, gh GithubClient, rnr ExecRunner) error { +func runMissingTestUnitTests(mmLocalPath, tpgbLocalPath, targetURL, commitSha string, prNumber int, gh GithubClient, rnr ExecRunner) error { + if err := rnr.PushDir(mmLocalPath); err != nil { + return err + } + + diffs, err := rnr.Run("git", []string{"diff", "HEAD", "origin/main", "tools/missing-test-detector"}, nil) + if err != nil { + return err + } + if diffs == "" { + // Short-circuit if there are no changes to the missing test detector + return rnr.PopDir() + } + + fmt.Printf("Found diffs in missing test detector:\n%s\nRunning tests.\n", diffs) + missingTestDetectorPath := filepath.Join(mmLocalPath, "tools", "missing-test-detector") rnr.PushDir(missingTestDetectorPath) if _, err := rnr.Run("go", []string{"mod", "tidy"}, nil); err != nil { @@ -460,20 +505,33 @@ func testTools(mmLocalPath, tpgbLocalPath string, env map[string]string, gh Gith servicesDir := filepath.Join(tpgbLocalPath, "google-beta", "services") state := "success" if _, err := rnr.Run("go", []string{"test"}, map[string]string{ - "GOPATH": env["GOPATH"], - "HOME": env["HOME"], "SERVICES_DIR": servicesDir, + // Passthrough vars required for a valid build environment. + "GOPATH": os.Getenv("GOPATH"), + "HOME": os.Getenv("HOME"), }); err != nil { fmt.Printf("error from running go test in %s: %v\n", missingTestDetectorPath, err) state = "failure" } - targetURL := fmt.Sprintf("https://console.cloud.google.com/cloud-build/builds;region=global/%s;step=%s?project=%s", env["BUILD_ID"], env["BUILD_STEP"], env["PROJECT_ID"]) - if err := gh.PostBuildStatus(env["PR_NUMBER"], "unit-tests-missing-test-detector", state, targetURL, env["COMMIT_SHA"]); err != nil { + if err := gh.PostBuildStatus(strconv.Itoa(prNumber), "unit-tests-missing-test-detector", state, targetURL, commitSha); err != nil { return err } return rnr.PopDir() } +func formatDiffComment(data diffCommentData) (string, error) { + tmpl, err := template.New("DIFF_COMMENT.md").Parse(diffComment) + if err != nil { + panic(fmt.Sprintf("Unable to parse DIFF_COMMENT.md: %s", err)) + } + sb := new(strings.Builder) + err = tmpl.Execute(sb, data) + if err != nil { + return "", err + } + return sb.String(), nil +} + func init() { rootCmd.AddCommand(generateCommentCmd) } diff --git a/.ci/magician/cmd/generate_comment_test.go b/.ci/magician/cmd/generate_comment_test.go index c8a1c14ed487..456267619bb8 100644 --- a/.ci/magician/cmd/generate_comment_test.go +++ b/.ci/magician/cmd/generate_comment_test.go @@ -16,9 +16,12 @@ package cmd import ( - "magician/source" + "os" "reflect" "testing" + + "github.com/stretchr/testify/assert" + "magician/source" ) func TestExecGenerateComment(t *testing.T) { @@ -27,25 +30,27 @@ func TestExecGenerateComment(t *testing.T) { calledMethods: make(map[string][][]any), } ctlr := source.NewController("/mock/dir/go", "modular-magician", "*******", mr) - env := map[string]string{ - "BUILD_ID": "build1", - "BUILD_STEP": "17", - "COMMIT_SHA": "sha1", - "GITHUB_TOKEN_MAGIC_MODULES": "*******", - "PR_NUMBER": "pr1", - "PROJECT_ID": "project1", - } diffProcessorEnv := map[string]string{ - "BUILD_ID": "build1", - "BUILD_STEP": "17", - "COMMIT_SHA": "sha1", + "NEW_REF": "auto-pr-123456", + "OLD_REF": "auto-pr-123456-old", + "PATH": os.Getenv("PATH"), + "GOPATH": os.Getenv("GOPATH"), + "HOME": os.Getenv("HOME"), + } + addLabelsEnv := map[string]string{ "GITHUB_TOKEN_MAGIC_MODULES": "*******", - "NEW_REF": "auto-pr-pr1", - "OLD_REF": "auto-pr-pr1-old", - "PR_NUMBER": "pr1", - "PROJECT_ID": "project1", } - execGenerateComment(env, gh, mr, ctlr) + execGenerateComment( + 123456, + "*******", + "build1", + "17", + "project1", + "sha1", + gh, + mr, + ctlr, + ) for method, expectedCalls := range map[string][]ParameterList{ "Copy": { @@ -64,25 +69,25 @@ func TestExecGenerateComment(t *testing.T) { {"/mock/dir/magic-modules/tools/diff-processor/bin"}, }, "Run": { - {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-pr1", "https://modular-magician:*******@github.com/modular-magician/terraform-provider-google", "/mock/dir/tpg"}, map[string]string(nil)}, - {"/mock/dir/tpg", "git", []string{"fetch", "origin", "auto-pr-pr1-old"}, map[string]string(nil)}, - {"/mock/dir/tpg", "git", []string{"diff", "origin/auto-pr-pr1-old", "origin/auto-pr-pr1", "--shortstat"}, map[string]string(nil)}, - {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-pr1", "https://modular-magician:*******@github.com/modular-magician/terraform-provider-google-beta", "/mock/dir/tpgb"}, map[string]string(nil)}, - {"/mock/dir/tpgb", "git", []string{"fetch", "origin", "auto-pr-pr1-old"}, map[string]string(nil)}, - {"/mock/dir/tpgb", "git", []string{"diff", "origin/auto-pr-pr1-old", "origin/auto-pr-pr1", "--shortstat"}, map[string]string(nil)}, - {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-pr1", "https://modular-magician:*******@github.com/modular-magician/terraform-google-conversion", "/mock/dir/tfc"}, map[string]string(nil)}, - {"/mock/dir/tfc", "git", []string{"fetch", "origin", "auto-pr-pr1-old"}, map[string]string(nil)}, - {"/mock/dir/tfc", "git", []string{"diff", "origin/auto-pr-pr1-old", "origin/auto-pr-pr1", "--shortstat"}, map[string]string(nil)}, - {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-pr1", "https://modular-magician:*******@github.com/modular-magician/docs-examples", "/mock/dir/tfoics"}, map[string]string(nil)}, - {"/mock/dir/tfoics", "git", []string{"fetch", "origin", "auto-pr-pr1-old"}, map[string]string(nil)}, - {"/mock/dir/tfoics", "git", []string{"diff", "origin/auto-pr-pr1-old", "origin/auto-pr-pr1", "--shortstat"}, map[string]string(nil)}, + {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-123456", "https://modular-magician:*******@github.com/modular-magician/terraform-provider-google", "/mock/dir/tpg"}, map[string]string(nil)}, + {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-123456", "https://modular-magician:*******@github.com/modular-magician/terraform-provider-google-beta", "/mock/dir/tpgb"}, map[string]string(nil)}, + {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-123456", "https://modular-magician:*******@github.com/modular-magician/terraform-google-conversion", "/mock/dir/tgc"}, map[string]string(nil)}, + {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-123456", "https://modular-magician:*******@github.com/modular-magician/docs-examples", "/mock/dir/tfoics"}, map[string]string(nil)}, + {"/mock/dir/tpg", "git", []string{"fetch", "origin", "auto-pr-123456-old"}, map[string]string(nil)}, + {"/mock/dir/tpg", "git", []string{"diff", "origin/auto-pr-123456-old", "origin/auto-pr-123456", "--shortstat"}, map[string]string(nil)}, + {"/mock/dir/tpgb", "git", []string{"fetch", "origin", "auto-pr-123456-old"}, map[string]string(nil)}, + {"/mock/dir/tpgb", "git", []string{"diff", "origin/auto-pr-123456-old", "origin/auto-pr-123456", "--shortstat"}, map[string]string(nil)}, + {"/mock/dir/tgc", "git", []string{"fetch", "origin", "auto-pr-123456-old"}, map[string]string(nil)}, + {"/mock/dir/tgc", "git", []string{"diff", "origin/auto-pr-123456-old", "origin/auto-pr-123456", "--shortstat"}, map[string]string(nil)}, + {"/mock/dir/tfoics", "git", []string{"fetch", "origin", "auto-pr-123456-old"}, map[string]string(nil)}, + {"/mock/dir/tfoics", "git", []string{"diff", "origin/auto-pr-123456-old", "origin/auto-pr-123456", "--shortstat"}, map[string]string(nil)}, {"/mock/dir/magic-modules/tools/diff-processor", "make", []string{"build"}, diffProcessorEnv}, {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"breaking-changes"}, map[string]string(nil)}, - {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"add-labels", "pr1"}, diffProcessorEnv}, + {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"add-labels", "123456"}, addLabelsEnv}, {"/mock/dir/magic-modules/tools/diff-processor", "make", []string{"build"}, diffProcessorEnv}, {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"breaking-changes"}, map[string]string(nil)}, - {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"add-labels", "pr1"}, diffProcessorEnv}, - {"/mock/dir/tpgbold", "git", []string{"checkout", "origin/auto-pr-pr1-old"}, map[string]string(nil)}, + {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"add-labels", "123456"}, addLabelsEnv}, + {"/mock/dir/tpgbold", "git", []string{"checkout", "origin/auto-pr-123456-old"}, map[string]string(nil)}, {"/mock/dir/tpgbold", "find", []string{".", "-type", "f", "-name", "*.go", "-exec", "sed", "-i.bak", "s~github.com/hashicorp/terraform-provider-google-beta~google/provider/old~g", "{}", "+"}, map[string]string(nil)}, {"/mock/dir/tpgbold", "sed", []string{"-i.bak", "s|github.com/hashicorp/terraform-provider-google-beta|google/provider/old|g", "go.mod"}, map[string]string(nil)}, {"/mock/dir/tpgbold", "sed", []string{"-i.bak", "s|github.com/hashicorp/terraform-provider-google-beta|google/provider/old|g", "go.sum"}, map[string]string(nil)}, @@ -110,8 +115,8 @@ func TestExecGenerateComment(t *testing.T) { } for method, expectedCalls := range map[string][][]any{ - "PostBuildStatus": {{"pr1", "terraform-provider-breaking-change-test", "success", "https://console.cloud.google.com/cloud-build/builds;region=global/build1;step=17?project=project1", "sha1"}}, - "PostComment": {{"pr1", "Hi there, I'm the Modular magician. I've detected the following information about your changes:\n\n## Diff report\nYour PR generated some diffs in downstreams - here they are.\n\nTerraform GA: [Diff](https://github.com/modular-magician/terraform-provider-google/compare/auto-pr-pr1-old..auto-pr-pr1) ( 2 files changed, 40 insertions(+))\nTerraform Beta: [Diff](https://github.com/modular-magician/terraform-provider-google-beta/compare/auto-pr-pr1-old..auto-pr-pr1) ( 2 files changed, 40 insertions(+))\nTF Conversion: [Diff](https://github.com/modular-magician/terraform-google-conversion/compare/auto-pr-pr1-old..auto-pr-pr1) ( 1 file changed, 10 insertions(+))\n\n## Missing test report\nYour PR includes resource fields which are not covered by any test.\n\nResource: `google_folder_access_approval_settings` (3 total tests)\nPlease add an acceptance test which includes these fields. The test should include the following:\n\n```hcl\nresource \"google_folder_access_approval_settings\" \"primary\" {\n uncovered_field = # value needed\n}\n\n```\n\n"}}, + "PostBuildStatus": {{"123456", "terraform-provider-breaking-change-test", "success", "https://console.cloud.google.com/cloud-build/builds;region=global/build1;step=17?project=project1", "sha1"}}, + "PostComment": {{"123456", "Hi there, I'm the Modular magician. I've detected the following information about your changes:\n\n## Diff report\n\nYour PR generated some diffs in downstreams - here they are.\n\n`google` provider: [Diff](https://github.com/modular-magician/terraform-provider-google/compare/auto-pr-123456-old..auto-pr-123456) ( 2 files changed, 40 insertions(+))\n`google-beta` provider: [Diff](https://github.com/modular-magician/terraform-provider-google-beta/compare/auto-pr-123456-old..auto-pr-123456) ( 2 files changed, 40 insertions(+))\n`terraform-google-conversion`: [Diff](https://github.com/modular-magician/terraform-google-conversion/compare/auto-pr-123456-old..auto-pr-123456) ( 1 file changed, 10 insertions(+))\n\n## Missing test report\nYour PR includes resource fields which are not covered by any test.\n\nResource: `google_folder_access_approval_settings` (3 total tests)\nPlease add an acceptance test which includes these fields. The test should include the following:\n\n```hcl\nresource \"google_folder_access_approval_settings\" \"primary\" {\n uncovered_field = # value needed\n}\n\n```\n"}}, } { if actualCalls, ok := gh.calledMethods[method]; !ok { t.Fatalf("Found no calls for %s", method) @@ -126,3 +131,122 @@ func TestExecGenerateComment(t *testing.T) { } } } + +func TestFormatDiffComment(t *testing.T) { + cases := map[string]struct { + data diffCommentData + expectedStrings []string + notExpectedStrings []string + }{ + "basic message": { + data: diffCommentData{}, + expectedStrings: []string{"## Diff report", "hasn't generated any diffs"}, + notExpectedStrings: []string{ + "generated some diffs", + "## Breaking Change(s) Detected", + "## Errors", + "## Missing test report", + }, + }, + "errors are displayed": { + data: diffCommentData{ + Errors: []Errors{ + { + Title: "`google` provider", + Errors: []string{"Provider 1"}, + }, + { + Title: "Other", + Errors: []string{"Error 1", "Error 2"}, + }, + }, + }, + expectedStrings: []string{"## Diff report", "## Errors", "`google` provider:\n- Provider 1\n\nOther:\n- Error 1\n- Error 2\n"}, + notExpectedStrings: []string{ + "generated some diffs", + "## Breaking Change(s) Detected", + "## Missing test report", + }, + }, + "diffs are displayed": { + data: diffCommentData{ + PrNumber: 1234567890, + Diffs: []Diff{ + { + Title: "Repo 1", + Repo: "repo-1", + DiffStats: "+1 added, -1 removed", + }, + { + Title: "Repo 2", + Repo: "repo-2", + DiffStats: "+2 added, -2 removed", + }, + }, + }, + expectedStrings: []string{ + "## Diff report", + "generated some diffs", + "Repo 1: [Diff](https://github.com/modular-magician/repo-1/compare/auto-pr-1234567890-old..auto-pr-1234567890) (+1 added, -1 removed)\nRepo 2: [Diff](https://github.com/modular-magician/repo-2/compare/auto-pr-1234567890-old..auto-pr-1234567890) (+2 added, -2 removed)", + }, + notExpectedStrings: []string{ + "hasn't generated any diffs", + "## Breaking Change(s) Detected", + "## Errors", + "## Missing test report", + }, + }, + "breaking changes are displayed": { + data: diffCommentData{ + BreakingChanges: []string{ + "Breaking change 1", + "Breaking change 2", + }, + }, + expectedStrings: []string{ + "## Diff report", + "## Breaking Change(s) Detected", + "major release", + "`override-breaking-change`", + "- Breaking change 1\n- Breaking change 2\n", + }, + notExpectedStrings: []string{ + "generated some diffs", + "## Errors", + "## Missing test report", + }, + }, + "missing tests are displayed": { + data: diffCommentData{ + MissingTests: "## Missing test report", + }, + expectedStrings: []string{ + "## Diff report", + "## Missing test report", + }, + notExpectedStrings: []string{ + "generated some diffs", + "## Breaking Change(s) Detected", + "## Errors", + }, + }, + } + + for tn, tc := range cases { + tc := tc + t.Run(tn, func(t *testing.T) { + t.Parallel() + + comment, err := formatDiffComment(tc.data) + assert.Nil(t, err) + + for _, s := range tc.expectedStrings { + assert.Contains(t, comment, s) + } + + for _, s := range tc.notExpectedStrings { + assert.NotContains(t, comment, s) + } + }) + } +} diff --git a/.ci/magician/cmd/mock_runner_test.go b/.ci/magician/cmd/mock_runner_test.go index 5789d9878a3f..bc470b13d685 100644 --- a/.ci/magician/cmd/mock_runner_test.go +++ b/.ci/magician/cmd/mock_runner_test.go @@ -41,32 +41,33 @@ func NewMockRunner() MockRunner { return &mockRunner{ calledMethods: make(map[string][]ParameterList), cmdResults: map[string]string{ - "/mock/dir/tfc git [clone -b auto-pr-pr1 https://modular-magician:*******@github.com/modular-magician/docs-examples /mock/dir/tfoics] map[]": "", - "/mock/dir/tpgb git [clone -b auto-pr-pr1 https://modular-magician:*******@github.com/modular-magician/terraform-google-conversion /mock/dir/tfc] map[]": "", - " git [clone -b auto-pr-pr1 https://modular-magician:*******@github.com/modular-magician/terraform-provider-google /mock/dir/tpg] map[]": "", - "/mock/dir/tpg git [clone -b auto-pr-pr1 https://modular-magician:*******@github.com/modular-magician/terraform-provider-google-beta /mock/dir/tpgb] map[]": "", - "/mock/dir/magic-modules git [diff HEAD origin/main tools/missing-test-detector] map[]": "", - "/mock/dir/magic-modules/tools/diff-processor bin/diff-processor [breaking-changes] map[]": "", - "/mock/dir/magic-modules/tools/diff-processor make [build] map[OLD_REF:auto-pr-pr1-old NEW_REF:auto-pr-pr1]": "", - "/mock/dir/magic-modules/tools/missing-test-detector go [mod edit -replace google/provider/new=/mock/dir/tpgb] map[]": "", - "/mock/dir/magic-modules/tools/missing-test-detector go [mod edit -replace google/provider/old=/mock/dir/tpgbold] map[]": "", - "/mock/dir/magic-modules/tools/missing-test-detector go [mod tidy] map[]": "", - "/mock/dir/magic-modules/tools/missing-test-detector go [run . -services-dir=/mock/dir/tpgb/google-beta/services] map[]": "## Missing test report\nYour PR includes resource fields which are not covered by any test.\n\nResource: `google_folder_access_approval_settings` (3 total tests)\nPlease add an acceptance test which includes these fields. The test should include the following:\n\n```hcl\nresource \"google_folder_access_approval_settings\" \"primary\" {\n uncovered_field = # value needed\n}\n\n```\n", - "/mock/dir/tfc git [diff origin/auto-pr-pr1-old origin/auto-pr-pr1 --shortstat] map[]": " 1 file changed, 10 insertions(+)\n", - "/mock/dir/tfc git [fetch origin auto-pr-pr1-old] map[]": "", - "/mock/dir/tfoics git [diff origin/auto-pr-pr1-old origin/auto-pr-pr1 --shortstat] map[]": "", - "/mock/dir/tfoics git [fetch origin auto-pr-pr1-old] map[]": "", - "/mock/dir/tpg git [diff origin/auto-pr-pr1-old origin/auto-pr-pr1 --shortstat] map[]": " 2 files changed, 40 insertions(+)\n", - "/mock/dir/tpg git [fetch origin auto-pr-pr1-old] map[]": "", - "/mock/dir/tpgb find [. -type f -name *.go -exec sed -i.bak s~github.com/hashicorp/terraform-provider-google-beta~google/provider/new~g {} +] map[]": "", - "/mock/dir/tpgb git [diff origin/auto-pr-pr1-old origin/auto-pr-pr1 --shortstat] map[]": " 2 files changed, 40 insertions(+)\n", - "/mock/dir/tpgb git [fetch origin auto-pr-pr1-old] map[]": "", - "/mock/dir/tpgb sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/new|g go.mod] map[]": "", - "/mock/dir/tpgb sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/new|g go.sum] map[]": "", - "/mock/dir/tpgbold find [. -type f -name *.go -exec sed -i.bak s~github.com/hashicorp/terraform-provider-google-beta~google/provider/old~g {} +] map[]": "", - "/mock/dir/tpgbold git [checkout origin/auto-pr-pr1-old] map[]": "", - "/mock/dir/tpgbold sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/old|g go.mod] map[]": "", - "/mock/dir/tpgbold sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/old|g go.sum] map[]": "", + "/mock/dir/magic-modules/.ci/magician git [clone -b auto-pr-123456 https://modular-magician:*******@github.com/modular-magician/docs-examples /mock/dir/tfoics] map[]": "", + "/mock/dir/magic-modules/.ci/magician git [clone -b auto-pr-123456 https://modular-magician:*******@github.com/modular-magician/terraform-google-conversion /mock/dir/tgc] map[]": "", + "/mock/dir/magic-modules/.ci/magician git [clone -b auto-pr-123456 https://modular-magician:*******@github.com/modular-magician/terraform-provider-google /mock/dir/tpg] map[]": "", + "/mock/dir/magic-modules/.ci/magician git [clone -b auto-pr-123456 https://modular-magician:*******@github.com/modular-magician/terraform-provider-google-beta /mock/dir/tpgb] map[]": "", + "/mock/dir/magic-modules git [diff HEAD origin/main tools/missing-test-detector] map[]": "", + "/mock/dir/magic-modules/tools/diff-processor bin/diff-processor [breaking-changes] map[]": "", + "/mock/dir/magic-modules/tools/diff-processor make [build] map[NEW_REF:auto-pr-123456 OLD_REF:auto-pr-123456-old]": "", + "/mock/dir/magic-modules/tools/diff-processor bin/diff-processor [add-labels 123456] map[GITHUB_TOKEN_MAGIC_MODULES:*******]": "", + "/mock/dir/magic-modules/tools/missing-test-detector go [mod edit -replace google/provider/new=/mock/dir/tpgb] map[]": "", + "/mock/dir/magic-modules/tools/missing-test-detector go [mod edit -replace google/provider/old=/mock/dir/tpgbold] map[]": "", + "/mock/dir/magic-modules/tools/missing-test-detector go [mod tidy] map[]": "", + "/mock/dir/magic-modules/tools/missing-test-detector go [run . -services-dir=/mock/dir/tpgb/google-beta/services] map[]": "## Missing test report\nYour PR includes resource fields which are not covered by any test.\n\nResource: `google_folder_access_approval_settings` (3 total tests)\nPlease add an acceptance test which includes these fields. The test should include the following:\n\n```hcl\nresource \"google_folder_access_approval_settings\" \"primary\" {\n uncovered_field = # value needed\n}\n\n```\n", + "/mock/dir/tgc git [diff origin/auto-pr-123456-old origin/auto-pr-123456 --shortstat] map[]": " 1 file changed, 10 insertions(+)\n", + "/mock/dir/tgc git [fetch origin auto-pr-123456-old] map[]": "", + "/mock/dir/tfoics git [diff origin/auto-pr-123456-old origin/auto-pr-123456 --shortstat] map[]": "", + "/mock/dir/tfoics git [fetch origin auto-pr-123456-old] map[]": "", + "/mock/dir/tpg git [diff origin/auto-pr-123456-old origin/auto-pr-123456 --shortstat] map[]": " 2 files changed, 40 insertions(+)\n", + "/mock/dir/tpg git [fetch origin auto-pr-123456-old] map[]": "", + "/mock/dir/tpgb find [. -type f -name *.go -exec sed -i.bak s~github.com/hashicorp/terraform-provider-google-beta~google/provider/new~g {} +] map[]": "", + "/mock/dir/tpgb git [diff origin/auto-pr-123456-old origin/auto-pr-123456 --shortstat] map[]": " 2 files changed, 40 insertions(+)\n", + "/mock/dir/tpgb git [fetch origin auto-pr-123456-old] map[]": "", + "/mock/dir/tpgb sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/new|g go.mod] map[]": "", + "/mock/dir/tpgb sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/new|g go.sum] map[]": "", + "/mock/dir/tpgbold find [. -type f -name *.go -exec sed -i.bak s~github.com/hashicorp/terraform-provider-google-beta~google/provider/old~g {} +] map[]": "", + "/mock/dir/tpgbold git [checkout origin/auto-pr-123456-old] map[]": "", + "/mock/dir/tpgbold sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/old|g go.mod] map[]": "", + "/mock/dir/tpgbold sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/old|g go.sum] map[]": "", }, cwd: "/mock/dir/magic-modules/.ci/magician", dirStack: list.New(), diff --git a/.ci/magician/source/repo.go b/.ci/magician/source/repo.go index 2d62d531431f..529cf97200ee 100644 --- a/.ci/magician/source/repo.go +++ b/.ci/magician/source/repo.go @@ -14,7 +14,7 @@ type Repo struct { Owner string // Owner of repo, optional Path string // local Path once cloned, including Name Version provider.Version - DiffCanFail bool // whether to allow the command to continue if cloning or diffing the repo fails + Cloned bool } type Controller struct { diff --git a/.ci/scripts/go-plus/magician/exec.sh b/.ci/scripts/go-plus/magician/exec.sh index a0cb4078e6b6..c438fb69cb22 100755 --- a/.ci/scripts/go-plus/magician/exec.sh +++ b/.ci/scripts/go-plus/magician/exec.sh @@ -1,5 +1,7 @@ #!/bin/bash +set -e + # Get the directory of the current script DIR="$(dirname $(realpath $0))" diff --git a/tools/diff-processor/GNUmakefile b/tools/diff-processor/GNUmakefile index 8e4f18ba9b05..c9e336230d17 100644 --- a/tools/diff-processor/GNUmakefile +++ b/tools/diff-processor/GNUmakefile @@ -56,3 +56,5 @@ endif go mod tidy mkdir -p bin/ go build -o ./bin/ . + +.PHONY: clone clean build From 6c7c0fb58933099b137bdbb7ac1771cc3b609cbd Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Wed, 13 Mar 2024 13:25:05 -0700 Subject: [PATCH 23/59] Rewrite versions related functions (#10181) --- mmv1/api/product.go | 136 ++++++++++++----------- mmv1/api/product/version.go | 8 ++ mmv1/api/product_test.go | 129 ++++++++++++++++++++++ mmv1/api/resource.go | 38 +++++++ mmv1/api/resource_test.go | 145 ++++++++++++++++++++++++ mmv1/api/type.go | 43 +++++--- mmv1/api/type_test.go | 214 ++++++++++++++++++++++++++++++++++++ 7 files changed, 632 insertions(+), 81 deletions(-) create mode 100644 mmv1/api/product_test.go create mode 100644 mmv1/api/resource_test.go create mode 100644 mmv1/api/type_test.go diff --git a/mmv1/api/product.go b/mmv1/api/product.go index bfaed3a19869..5c5b718d8767 100644 --- a/mmv1/api/product.go +++ b/mmv1/api/product.go @@ -14,6 +14,9 @@ package api import ( + "log" + "strings" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" "golang.org/x/exp/slices" @@ -50,7 +53,7 @@ type Product struct { // The API versions of this product - Versions []product.Version + Versions []*product.Version // The base URL for the service API endpoint // For example: `https://www.googleapis.com/compute/v1/` @@ -77,6 +80,9 @@ func (p *Product) Validate() { for _, o := range p.Objects { o.ProductMetadata = p } + + p.SetApiName() + p.SetDisplayName() } // def validate @@ -101,73 +107,82 @@ func (p *Product) Validate() { // check :versions, type: Array, item_type: Api::Product::Version, required: true // end -// // ==================== -// // Custom Getters -// // ==================== +// ==================== +// Custom Setters +// ==================== -// // The name of the product's API; "compute", "accesscontextmanager" -// def api_name -// name.downcase -// end +func (p *Product) SetApiName() { + // The name of the product's API; "compute", "accesscontextmanager" + p.ApiName = strings.ToLower(p.Name) +} // The product full name is the "display name" in string form intended for // users to read in documentation; "Google Compute Engine", "Cloud Bigtable" -func (p Product) GetDisplayName() string { +func (p *Product) SetDisplayName() { if p.DisplayName == "" { - return google.SpaceSeparated(p.Name) + p.DisplayName = google.SpaceSeparated(p.Name) } - - return p.DisplayName } -// // Most general version that exists for the product -// // If GA is present, use that, else beta, else alpha -// def lowest_version -// Version::ORDER.each do |ordered_version_name| -// @versions.each do |product_version| -// return product_version if ordered_version_name == product_version.name -// end -// end -// raise "Unable to find lowest version for product //{display_name}" -// end - -// def version_obj(name) -// @versions.each do |v| -// return v if v.name == name -// end +// ==================== +// Version-related methods +// ==================== + +// Most general version that exists for the product +// If GA is present, use that, else beta, else alpha +func (p Product) lowestVersion() *product.Version { + for _, orderedVersionName := range product.ORDER { + for _, productVersion := range p.Versions { + if orderedVersionName == productVersion.Name { + return productVersion + } + } + } -// raise "API version '//{name}' does not exist for product '//{@name}'" -// end + log.Fatalf("Unable to find lowest version for product %s", p.DisplayName) + return nil +} -// // Get the version of the object specified by the version given if present -// // Or else fall back to the closest version in the chain defined by Version::ORDER -// def version_obj_or_closest(name) -// return version_obj(name) if exists_at_version(name) +func (p Product) versionObj(name string) *product.Version { + for _, v := range p.Versions { + if v.Name == name { + return v + } + } -// // versions should fall back to the closest version to them that exists -// name ||= Version::ORDER[0] -// lower_versions = Version::ORDER[0..Version::ORDER.index(name)] + log.Fatalf("API version '%s' does not exist for product '%s'", name, p.Name) + return nil +} -// lower_versions.reverse_each do |version| -// return version_obj(version) if exists_at_version(version) -// end +// Get the version of the object specified by the version given if present +// Or else fall back to the closest version in the chain defined by product.ORDER +func (p Product) VersionObjOrClosest(name string) *product.Version { + if p.ExistsAtVersion(name) { + return p.versionObj(name) + } -// raise "Could not find object for version //{name} and product //{display_name}" -// end + // versions should fall back to the closest version to them that exists + if name == "" { + name = product.ORDER[0] + } -// def exists_at_version_or_lower(name) -// // Versions aren't normally going to be empty since products need a -// // base_url. This nil check exists for atypical products, like _bundle. -// return true if @versions.nil? + lowerVersions := make([]string, 0) + for _, v := range product.ORDER { + lowerVersions = append(lowerVersions, v) + if v == name { + break + } + } -// name ||= Version::ORDER[0] -// return false unless Version::ORDER.include?(name) + for i := len(lowerVersions) - 1; i >= 0; i-- { + if p.ExistsAtVersion(lowerVersions[i]) { + return p.versionObj(lowerVersions[i]) + } + } -// (0..Version::ORDER.index(name)).each do |i| -// return true if exists_at_version(Version::ORDER[i]) -// end -// false -// end + log.Fatalf("Could not find object for version %s and product %s", name, p.DisplayName) + return nil +} func (p *Product) ExistsAtVersionOrLower(name string) bool { if !slices.Contains(product.ORDER, name) { @@ -192,20 +207,9 @@ func (p *Product) ExistsAtVersion(name string) bool { return false } -// def exists_at_version(name) -// // Versions aren't normally going to be empty since products need a -// // base_url. This nil check exists for atypical products, like _bundle. -// return true if @versions.nil? - -// @versions.any? { |v| v.name == name } -// end - -// // Not a conventional setter, so ignore rubocop's warning -// // rubocop:disable Naming/AccessorMethodName -// def set_properties_based_on_version(version) -// @base_url = version.base_url -// end -// // rubocop:enable Naming/AccessorMethodName +func (p *Product) SetPropertiesBasedOnVersion(version *product.Version) { + p.BaseUrl = version.BaseUrl +} // // ==================== // // Debugging Methods diff --git a/mmv1/api/product/version.go b/mmv1/api/product/version.go index 3c2ef6a670c0..aa5bdd335c10 100644 --- a/mmv1/api/product/version.go +++ b/mmv1/api/product/version.go @@ -13,6 +13,10 @@ package product +import ( + "golang.org/x/exp/slices" +) + // require 'api/object' var ORDER = []string{"ga", "beta", "alpha", "private"} @@ -50,3 +54,7 @@ type Version struct { // def <=>(other) // ORDER.index(name) <=> ORDER.index(other.name) if other.is_a?(Version) // end + +func (v *Version) CompareTo(other *Version) int { + return slices.Index(ORDER, v.Name) - slices.Index(ORDER, other.Name) +} diff --git a/mmv1/api/product_test.go b/mmv1/api/product_test.go new file mode 100644 index 000000000000..682cd7b6a784 --- /dev/null +++ b/mmv1/api/product_test.go @@ -0,0 +1,129 @@ +package api + +import ( + "reflect" + "testing" + + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" +) + +func TestProductLowestVersion(t *testing.T) { + t.Parallel() + + cases := []struct { + description string + obj Product + expected string + }{ + { + description: "lowest version is ga", + obj: Product{ + Versions: []*product.Version{ + &product.Version{ + Name: "beta", + BaseUrl: "beta_url", + }, + &product.Version{ + Name: "ga", + BaseUrl: "ga_url", + }, + &product.Version{ + Name: "alpha", + BaseUrl: "alpha_url", + }, + }, + }, + expected: "ga", + }, + { + description: "lowest version is ga", + obj: Product{ + Versions: []*product.Version{ + &product.Version{ + Name: "beta", + BaseUrl: "beta_url", + }, + &product.Version{ + Name: "alpha", + BaseUrl: "alpha_url", + }, + }, + }, + expected: "beta", + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + versionObj := tc.obj.lowestVersion() + + if got, want := versionObj.Name, tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} + +func TestProductVersionObjOrClosest(t *testing.T) { + t.Parallel() + + cases := []struct { + description string + obj Product + input string + expected string + }{ + { + description: "closest version object to ga", + obj: Product{ + Versions: []*product.Version{ + &product.Version{ + Name: "beta", + BaseUrl: "beta_url", + }, + &product.Version{ + Name: "ga", + BaseUrl: "ga_url", + }, + }, + }, + input: "ga", + expected: "ga", + }, + { + description: "closest version object to alpha", + obj: Product{ + Versions: []*product.Version{ + &product.Version{ + Name: "beta", + BaseUrl: "beta_url", + }, + &product.Version{ + Name: "ga", + BaseUrl: "ga_url", + }, + }, + }, + input: "alpha", + expected: "beta", + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + versionObj := tc.obj.VersionObjOrClosest(tc.input) + + if got, want := versionObj.Name, tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go index 894850e765c1..069c935af0d8 100644 --- a/mmv1/api/resource.go +++ b/mmv1/api/resource.go @@ -13,6 +13,7 @@ package api import ( + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/resource" "github.com/GoogleCloudPlatform/magic-modules/mmv1/provider/terraform" ) @@ -292,3 +293,40 @@ func (r *Resource) setResourceMetada(properties []*Type) { property.ResourceMetadata = r } } + +// ==================== +// Version-related methods +// ==================== + +func (r Resource) MinVersionObj() *product.Version { + if r.MinVersion != "" { + return r.ProductMetadata.versionObj(r.MinVersion) + } else { + return r.ProductMetadata.lowestVersion() + } +} + +func (r Resource) NotInVersion(version *product.Version) bool { + return version.CompareTo(r.MinVersionObj()) < 0 +} + +// Recurses through all nested properties and parameters and changes their +// 'exclude' instance variable if the property is at a version below the +// one that is passed in. +func (r *Resource) ExcludeIfNotInVersion(version *product.Version) { + if !r.Exclude { + r.Exclude = r.NotInVersion(version) + } + + if r.Properties != nil { + for _, p := range r.Properties { + p.ExcludeIfNotInVersion(version) + } + } + + if r.Parameters != nil { + for _, p := range r.Parameters { + p.ExcludeIfNotInVersion(version) + } + } +} diff --git a/mmv1/api/resource_test.go b/mmv1/api/resource_test.go new file mode 100644 index 000000000000..a9cb0c3c4a65 --- /dev/null +++ b/mmv1/api/resource_test.go @@ -0,0 +1,145 @@ +package api + +import ( + "reflect" + "testing" + + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" +) + +func TestResourceMinVersionObj(t *testing.T) { + t.Parallel() + p := Product{ + NamedObject: NamedObject{ + Name: "test", + }, + Versions: []*product.Version{ + &product.Version{ + Name: "beta", + BaseUrl: "beta_url", + }, + &product.Version{ + Name: "ga", + BaseUrl: "ga_url", + }, + &product.Version{ + Name: "alpha", + BaseUrl: "alpha_url", + }, + }, + } + + cases := []struct { + description string + obj Resource + expected string + }{ + { + description: "resource minVersion is empty", + obj: Resource{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "", + ProductMetadata: &p, + }, + expected: "ga", + }, + { + description: "resource minVersion is not empty", + obj: Resource{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "beta", + ProductMetadata: &p, + }, + expected: "beta", + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + versionObj := tc.obj.MinVersionObj() + + if got, want := versionObj.Name, tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} + +func TestResourceNotInVersion(t *testing.T) { + t.Parallel() + p := Product{ + NamedObject: NamedObject{ + Name: "test", + }, + Versions: []*product.Version{ + &product.Version{ + Name: "beta", + BaseUrl: "beta_url", + }, + &product.Version{ + Name: "ga", + BaseUrl: "ga_url", + }, + &product.Version{ + Name: "alpha", + BaseUrl: "alpha_url", + }, + }, + } + + cases := []struct { + description string + obj Resource + input *product.Version + expected bool + }{ + { + description: "ga is in version if MinVersion is empty", + obj: Resource{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "", + ProductMetadata: &p, + }, + input: &product.Version{ + Name: "ga", + }, + expected: false, + }, + { + description: "ga is not in version if MinVersion is beta", + obj: Resource{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "beta", + ProductMetadata: &p, + }, + input: &product.Version{ + Name: "ga", + }, + expected: true, + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + if got, want := tc.obj.NotInVersion(tc.input), tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} diff --git a/mmv1/api/type.go b/mmv1/api/type.go index 0fe6f165e6dd..f80777231810 100644 --- a/mmv1/api/type.go +++ b/mmv1/api/type.go @@ -13,6 +13,10 @@ package api +import ( + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" +) + // require 'api/object' // require 'google/string_utils' // require 'provider/terraform/validation' @@ -441,24 +445,33 @@ const MAX_NAME = 20 // // @__parent // } -// func (t *Type) min_version() { -// // if @min_version.nil? -// // @__resource.min_version -// // else -// // @__resource.__product.version_obj(@min_version) -// // end -// } +func (t *Type) MinVersionObj() *product.Version { + if t.MinVersion != "" { + return t.ResourceMetadata.ProductMetadata.versionObj(t.MinVersion) + } else { + return t.ResourceMetadata.MinVersionObj() + } +} -// func (t *Type) exact_version() { -// // return nil if @exact_version.nil? || @exact_version.empty? +func (t *Type) exactVersionObj() *product.Version { + if t.ExactVersion == "" { + return nil + } -// // @__resource.__product.version_obj(@exact_version) -// } + return t.ResourceMetadata.ProductMetadata.versionObj(t.ExactVersion) +} -// func (t *Type) exclude_if_not_in_version!(version) { -// // @exclude ||= exact_version != version unless exact_version.nil? -// // @exclude ||= version < min_version -// } +func (t *Type) ExcludeIfNotInVersion(version *product.Version) { + if !t.Exclude { + if versionObj := t.exactVersionObj(); versionObj != nil { + t.Exclude = versionObj.CompareTo(version) != 0 + } + + if !t.Exclude { + t.Exclude = version.CompareTo(t.MinVersionObj()) < 0 + } + } +} // // Overriding is_a? to enable class overrides. // // Ruby does not let you natively change types, so this is the next best diff --git a/mmv1/api/type_test.go b/mmv1/api/type_test.go new file mode 100644 index 000000000000..86c3e2e57b1e --- /dev/null +++ b/mmv1/api/type_test.go @@ -0,0 +1,214 @@ +package api + +import ( + "reflect" + "testing" + + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" +) + +func TestTypeMinVersionObj(t *testing.T) { + t.Parallel() + + p := Product{ + NamedObject: NamedObject{ + Name: "test", + }, + Versions: []*product.Version{ + &product.Version{ + Name: "beta", + BaseUrl: "beta_url", + }, + &product.Version{ + Name: "ga", + BaseUrl: "ga_url", + }, + &product.Version{ + Name: "alpha", + BaseUrl: "alpha_url", + }, + }, + } + + cases := []struct { + description string + obj Type + expected string + }{ + { + description: "type minVersion is empty and resource minVersion is empty", + obj: Type{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "", + ResourceMetadata: &Resource{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "", + ProductMetadata: &p, + }, + }, + expected: "ga", + }, + { + description: "type minVersion is empty and resource minVersion is beta", + obj: Type{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "", + ResourceMetadata: &Resource{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "beta", + ProductMetadata: &p, + }, + }, + expected: "beta", + }, + { + description: "type minVersion is not empty", + obj: Type{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "beta", + ResourceMetadata: &Resource{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "", + ProductMetadata: &p, + }, + }, + expected: "beta", + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + versionObj := tc.obj.MinVersionObj() + + if got, want := versionObj.Name, tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} + +func TestTypeExcludeIfNotInVersion(t *testing.T) { + t.Parallel() + + p := Product{ + NamedObject: NamedObject{ + Name: "test", + }, + Versions: []*product.Version{ + &product.Version{ + Name: "beta", + BaseUrl: "beta_url", + }, + &product.Version{ + Name: "ga", + BaseUrl: "ga_url", + }, + &product.Version{ + Name: "alpha", + BaseUrl: "alpha_url", + }, + }, + } + + cases := []struct { + description string + obj Type + input *product.Version + expected bool + }{ + { + description: "type has Exclude true", + obj: Type{ + NamedObject: NamedObject{ + Name: "test", + }, + Exclude: true, + MinVersion: "", + ResourceMetadata: &Resource{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "", + ProductMetadata: &p, + }, + }, + input: &product.Version{ + Name: "ga", + }, + expected: true, + }, + { + description: "type has Exclude false and not empty ExactVersion", + obj: Type{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "", + Exclude: false, + ExactVersion: "beta", + ResourceMetadata: &Resource{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "beta", + ProductMetadata: &p, + }, + }, + input: &product.Version{ + Name: "ga", + }, + expected: true, + }, + { + description: "type has Exclude false and empty ExactVersion", + obj: Type{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "beta", + Exclude: false, + ExactVersion: "", + ResourceMetadata: &Resource{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "", + ProductMetadata: &p, + }, + }, + input: &product.Version{ + Name: "ga", + }, + expected: true, + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + tc.obj.ExcludeIfNotInVersion(tc.input) + if got, want := tc.obj.Exclude, tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} From 7fa597482534e1a969520e28f330d7421b25f3ae Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Wed, 13 Mar 2024 20:40:59 +0000 Subject: [PATCH 24/59] Update Dockerfiles to Go 1.21 (#10175) --- .ci/containers/build-environment/Dockerfile | 4 ++-- .ci/containers/go-plus/Dockerfile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.ci/containers/build-environment/Dockerfile b/.ci/containers/build-environment/Dockerfile index 2f2dcb85ecf5..d2f11e881954 100644 --- a/.ci/containers/build-environment/Dockerfile +++ b/.ci/containers/build-environment/Dockerfile @@ -1,5 +1,5 @@ # Stage 1: Building Go dependencies -FROM golang:1.20-bullseye AS builder +FROM golang:1.21-bullseye AS builder # Set working directory WORKDIR /app @@ -15,7 +15,7 @@ RUN go mod download FROM ruby:3.1-bullseye # golang -COPY --from=golang:1.20-bullseye /usr/local/go /usr/local/go +COPY --from=golang:1.21-bullseye /usr/local/go /usr/local/go ENV GOPATH /go ENV PATH /usr/local/go/bin:$PATH ENV PATH $GOPATH/bin:$PATH diff --git a/.ci/containers/go-plus/Dockerfile b/.ci/containers/go-plus/Dockerfile index 655f976726bf..b37e5ee8b996 100644 --- a/.ci/containers/go-plus/Dockerfile +++ b/.ci/containers/go-plus/Dockerfile @@ -1,5 +1,5 @@ # Stage 1: Download go module cache for builds -FROM golang:1.20-bullseye AS builder +FROM golang:1.21-bullseye AS builder ENV GOCACHE=/go/cache RUN apt-get update && apt-get install -y unzip @@ -12,7 +12,7 @@ WORKDIR /app1/magic-modules-main/.ci/magician RUN go build -o /dev/null . # Stage 2: Creating the final image -FROM golang:1.20-bullseye +FROM golang:1.21-bullseye SHELL ["/bin/bash", "-c"] ENV GOCACHE=/go/cache From 7b1ac65bae60038f8cb41a217174040f82183c6d Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Wed, 13 Mar 2024 13:41:48 -0700 Subject: [PATCH 25/59] Add an override for generating long form tests (#10162) --- tpgtools/override.go | 1 + tpgtools/property.go | 20 ++++++++++++++------ tpgtools/resource.go | 23 +++++++++++++++++++++++ tpgtools/sample.go | 9 ++++++--- tpgtools/serialization.go.base | 2 +- tpgtools/templates/serialization.go.tmpl | 16 ++++++++++++---- 6 files changed, 57 insertions(+), 14 deletions(-) diff --git a/tpgtools/override.go b/tpgtools/override.go index 5ce55962733c..53bd465818be 100644 --- a/tpgtools/override.go +++ b/tpgtools/override.go @@ -55,6 +55,7 @@ const ( TerraformProductName = "CUSTOM_TERRAFORM_PRODUCT_NAME" CustomTimeout = "CUSTOM_TIMEOUT" StateUpgrade = "STATE_UPGRADE" + GenerateLongFormTests = "GENERATE_LONG_FORM_TESTS" ) // Field-level Overrides diff --git a/tpgtools/property.go b/tpgtools/property.go index 62e5aa4fa51c..813b89e719ae 100644 --- a/tpgtools/property.go +++ b/tpgtools/property.go @@ -95,6 +95,11 @@ type Property struct { // the field being unset and being set to false. EnumBool bool + // Whether this field is only used as a url parameter + Parameter bool + // Whether this field has long form behavior in the DCL + HasLongForm bool + // An IdentityGetter is a function to retrieve the value of an "identity" field // from state. Identity fields will sometimes allow retrieval from multiple // fields or from the user's environment variables. @@ -210,7 +215,7 @@ func (t Type) IsSet() bool { } // Complex map is for maps of string --> object that are supported in DCL but -// not in Terraform. We handle this by adding a field in the Terraform schema +// not in Terraform. We handle this by adding a field in the Terraform schema // for the key in the map. This must be added via a COMPLEX_MAP_KEY_NAME // override func (t Type) IsComplexMap() bool { @@ -618,6 +623,9 @@ func createPropertiesFromSchema(schema *openapi.Schema, typeFetcher *TypeFetcher } } + p.Parameter, _ = v.Extension["x-dcl-parameter"].(bool) + p.HasLongForm, _ = v.Extension["x-dcl-has-long-form"].(bool) + // Handle object properties if len(v.Properties) > 0 { props, err := createPropertiesFromSchema(v, typeFetcher, overrides, resource, &p, location) @@ -691,11 +699,11 @@ func createPropertiesFromSchema(schema *openapi.Schema, typeFetcher *TypeFetcher return nil, fmt.Errorf("failed to find complex map key name for map named: %s", p.Name()) } keyProp := Property{ - title: cm.KeyName, - Type: Type{&openapi.Schema{Type: "string"}}, - resource: resource, - parent: &p, - Required: true, + title: cm.KeyName, + Type: Type{&openapi.Schema{Type: "string"}}, + resource: resource, + parent: &p, + Required: true, Description: "The name for the key in the map for which this object is mapped to in the API", } props = append([]Property{keyProp}, props...) diff --git a/tpgtools/resource.go b/tpgtools/resource.go index 5ceda2b47bb5..c7916dd303a1 100644 --- a/tpgtools/resource.go +++ b/tpgtools/resource.go @@ -178,6 +178,9 @@ type Resource struct { SchemaVersion int // The schema versions from 0 to the current schema version SchemaVersions []int + + // Whether to generate long form versions of resource sample tests + GenerateLongFormTests bool } type Link struct { @@ -711,6 +714,10 @@ func createResource(schema *openapi.Schema, info *openapi.Info, typeFetcher *Typ } } + if overrides.ResourceOverride(GenerateLongFormTests, location) { + res.GenerateLongFormTests = true + } + res.Samples = res.loadSamples() return &res, nil @@ -977,7 +984,23 @@ func (r *Resource) loadDCLSamples() []Sample { sample.IgnoreRead = append(sample.IgnoreRead, "annotations") } + if r.GenerateLongFormTests { + longFormSample := sample + longFormSample.LongForm = true + var longFormDependencies []Dependency + mainResourceLongForm := longFormSample.generateSampleDependencyWithName(primaryResource, "primary") + longFormDependencies = append(longFormDependencies, mainResourceLongForm) + for _, dFileName := range longFormSample.DependencyFileNames { + longFormDependency := sample.generateSampleDependency(dFileName) + longFormDependencies = append(longFormDependencies, longFormDependency) + } + longFormSample.DependencyList = longFormDependencies + longFormSample.TestSlug += "LongForm" + samples = append(samples, longFormSample) + } + samples = append(samples, sample) + } return samples diff --git a/tpgtools/sample.go b/tpgtools/sample.go index 057b74dfa518..c934575ea8bd 100644 --- a/tpgtools/sample.go +++ b/tpgtools/sample.go @@ -46,6 +46,9 @@ type Sample struct { // in the testcase. (if the test doesn't have a ga version of the test) HasGAEquivalent bool + // LongForm is whether this sample is a copy with long form fields expanded to include `/` + LongForm bool + // SamplesPath is the path to the directory where the original sample data is stored SamplesPath Filepath @@ -165,7 +168,7 @@ func findDCLReferencePackage(product SnakeCaseProductName) (DCLPackageName, erro } // BuildDependency produces a Dependency using a file and filename -func BuildDependency(fileName string, product SnakeCaseProductName, localname, version string, hasGAEquivalent bool, b []byte) (*Dependency, error) { +func BuildDependency(fileName string, product SnakeCaseProductName, localname, version string, hasGAEquivalent, makeLongForm bool, b []byte) (*Dependency, error) { // Miscellaneous name rather than "resource name" because this is the name in the sample json file - which might not match the TF name! // we have to account for that. var resourceName miscellaneousNameSnakeCase @@ -194,7 +197,7 @@ func BuildDependency(fileName string, product SnakeCaseProductName, localname, v return nil, fmt.Errorf("Error generating sample dependency reference %s: %s", fileName, err) } - block, err := ConvertSampleJSONToHCL(packageName, resourceName, version, hasGAEquivalent, b) + block, err := ConvertSampleJSONToHCL(packageName, resourceName, version, hasGAEquivalent, makeLongForm, b) if err != nil { glog.Errorf("failed to convert %q", fileName) return nil, fmt.Errorf("Error generating sample dependency %s: %s", fileName, err) @@ -223,7 +226,7 @@ func (s *Sample) generateSampleDependencyWithName(fileName, localname string) De dependencyBytes, err := ioutil.ReadFile(path.Join(string(s.SamplesPath), fileName)) version := s.resourceReference.versionMetadata.V product := s.resourceReference.productMetadata.ProductName - d, err := BuildDependency(fileName, product, localname, version, s.HasGAEquivalent, dependencyBytes) + d, err := BuildDependency(fileName, product, localname, version, s.HasGAEquivalent, s.LongForm, dependencyBytes) if err != nil { glog.Exit(err) } diff --git a/tpgtools/serialization.go.base b/tpgtools/serialization.go.base index 58f01e79d9ba..d29fea9ab9fd 100644 --- a/tpgtools/serialization.go.base +++ b/tpgtools/serialization.go.base @@ -8,7 +8,7 @@ func DCLToTerraformReference(product DCLPackageName, resource miscellaneousNameS return "", fmt.Errorf("unimplemented - did you run `make serialize`?") } -func ConvertSampleJSONToHCL(product DCLPackageName, resource miscellaneousNameSnakeCase, version string, hasGAEquivalent bool, b []byte) (string, error) { +func ConvertSampleJSONToHCL(product DCLPackageName, resource miscellaneousNameSnakeCase, version string, hasGAEquivalent, makeLongForm bool, b []byte) (string, error) { return "", fmt.Errorf("unimplemented - did you run `make serialize`?") } diff --git a/tpgtools/templates/serialization.go.tmpl b/tpgtools/templates/serialization.go.tmpl index faba0a38cdfc..c1c46b76f030 100644 --- a/tpgtools/templates/serialization.go.tmpl +++ b/tpgtools/templates/serialization.go.tmpl @@ -72,7 +72,7 @@ func DCLToTerraformReference(product DCLPackageName, resource miscellaneousNameS } // ConvertSampleJSONToHCL unmarshals json to an HCL string. -func ConvertSampleJSONToHCL(product DCLPackageName, resource miscellaneousNameSnakeCase, version string, hasGAEquivalent bool, b []byte) (string, error) { +func ConvertSampleJSONToHCL(product DCLPackageName, resource miscellaneousNameSnakeCase, version string, hasGAEquivalent, makeLongForm bool, b []byte) (string, error) { {{- range $version, $resList := $.Resources }} {{- if not (eq $version.V "ga") }} if version == "{{$version.V}}" { @@ -86,7 +86,7 @@ func ConvertSampleJSONToHCL(product DCLPackageName, resource miscellaneousNameSn {{- if $res.CustomSerializer }} return {{$res.CustomSerializer}}(*r, hasGAEquivalent) {{- else }} - return {{$res.TitleCaseFullName}}{{$version.SerializationSuffix}}AsHCL(*r, hasGAEquivalent) + return {{$res.TitleCaseFullName}}{{$version.SerializationSuffix}}AsHCL(*r, hasGAEquivalent, makeLongForm) {{- end }} {{- end }} } @@ -103,7 +103,7 @@ func ConvertSampleJSONToHCL(product DCLPackageName, resource miscellaneousNameSn {{- if $res.CustomSerializer }} return {{$res.CustomSerializer}}(*r, hasGAEquivalent) {{- else }} - return {{$res.TitleCaseFullName}}{{$version.SerializationSuffix}}AsHCL(*r, hasGAEquivalent) + return {{$res.TitleCaseFullName}}{{$version.SerializationSuffix}}AsHCL(*r, hasGAEquivalent, makeLongForm) {{- end }} {{- end }} default: @@ -123,7 +123,7 @@ func ConvertSampleJSONToHCL(product DCLPackageName, resource miscellaneousNameSn // the crucial point is that `terraform import; terraform apply` will not produce // any changes. We do not validate that the resource specified will pass terraform // validation unless is an object returned from the API after an Apply. -func {{ $res.TitleCaseFullName }}{{$version.SerializationSuffix}}AsHCL(r {{$res.Package}}{{$version.SerializationSuffix}}.{{$res.DCLStructName}}, hasGAEquivalent bool) (string, error) { +func {{ $res.TitleCaseFullName }}{{$version.SerializationSuffix}}AsHCL(r {{$res.Package}}{{$version.SerializationSuffix}}.{{$res.DCLStructName}}, hasGAEquivalent, makeLongForm bool) (string, error) { outputConfig := "resource \"{{$res.TerraformName}}\" \"output\" {\n" {{- range $field := $res.Properties}} {{- if $field.ShouldShowUpInSamples }} @@ -138,7 +138,15 @@ func {{ $res.TitleCaseFullName }}{{$version.SerializationSuffix}}AsHCL(r {{$res. } {{- else }} if r.{{$field.PackageName}} != nil { + {{- if or $field.Parameter $field.HasLongForm }} + if makeLongForm { + outputConfig += fmt.Sprintf("\t{{$field.Name}} = %#v\n", "long/form/" + *r.{{$field.PackageName}}) + } else { + outputConfig += fmt.Sprintf("\t{{$field.Name}} = %#v\n", *r.{{$field.PackageName}}) + } + {{- else }} outputConfig += fmt.Sprintf("\t{{$field.Name}} = %#v\n", *r.{{$field.PackageName}}) + {{- end }} } {{- end}} {{- else if $field.Type.IsObject }} From 67e2505f1821f00aeee54dac5f666a3ac913a71f Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Wed, 13 Mar 2024 20:48:41 +0000 Subject: [PATCH 26/59] Update to go 1.21 (#10169) * Update .go-version file in TPG and TPGB repos * Update go.mod used to generate TPG/TPGB and run `go mod tidy` * Update go.mod in mmv1/third_party/terraform/scripts * Update go.mod in mmv1 * Update go.mod in docs * Update go.mod in tools/go-changelog and run `go mod tidy` * Update go.mod in tools/missing-test-detector and run `go mod tidy` * Update go.mod in tools/diff-processor * Update go.mod in tools/issue-labeler * Update go.mod in tools/teamcity-generator * Update go.mod in tpgtools and run `go mod tidy` * Update doctor script to ensure developers use Go 1.21 locally * Update GHA workflows to use Go 1.21 * Add missing update to GHA --- .ci/magician/go.mod | 2 +- .../gcb-membership-checker-test.yml | 2 +- .github/workflows/build-downstream.yml | 2 +- .github/workflows/membership-checker.yml | 2 +- .github/workflows/request-reviewer.yml | 2 +- .github/workflows/test-tgc.yml | 2 +- .github/workflows/test-tpg.yml | 2 +- .github/workflows/unit-test-tgc.yml | 2 +- .github/workflows/unit-test-tpg.yml | 2 +- .../workflows/unit-tests-diff-processor.yml | 2 +- docs/go.mod | 2 +- mmv1/go.mod | 2 +- mmv1/third_party/terraform/.go-version | 2 +- mmv1/third_party/terraform/go.mod.erb | 2 +- mmv1/third_party/terraform/go.sum | 29 +- mmv1/third_party/terraform/scripts/go.mod | 2 +- scripts/doctor | 4 +- tools/diff-processor/go.mod | 2 +- tools/go-changelog/go.mod | 1 - tools/go-changelog/go.sum | 18 -- tools/issue-labeler/go.mod | 8 +- tools/missing-test-detector/go.mod | 56 +--- tools/missing-test-detector/go.sum | 306 +----------------- tools/teamcity-generator/go.mod | 2 +- tpgtools/go.mod | 2 +- tpgtools/go.sum | 1 + 26 files changed, 59 insertions(+), 400 deletions(-) diff --git a/.ci/magician/go.mod b/.ci/magician/go.mod index 95f0b951ab1c..4f089f20df4f 100644 --- a/.ci/magician/go.mod +++ b/.ci/magician/go.mod @@ -1,6 +1,6 @@ module magician -go 1.20 +go 1.21 replace github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler => ../../tools/issue-labeler diff --git a/.ci/unit-tests/gcb-membership-checker-test.yml b/.ci/unit-tests/gcb-membership-checker-test.yml index 1c0c63636ba2..a77f10fc1f48 100644 --- a/.ci/unit-tests/gcb-membership-checker-test.yml +++ b/.ci/unit-tests/gcb-membership-checker-test.yml @@ -1,6 +1,6 @@ --- steps: - - name: 'golang:1.20' + - name: 'golang:1.21' args: - '-c' - | diff --git a/.github/workflows/build-downstream.yml b/.github/workflows/build-downstream.yml index 91f33499bd10..10fcc1c768da 100644 --- a/.github/workflows/build-downstream.yml +++ b/.github/workflows/build-downstream.yml @@ -47,7 +47,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: '^1.20' + go-version: '^1.21' # Cache Go modules - name: Cache Go modules diff --git a/.github/workflows/membership-checker.yml b/.github/workflows/membership-checker.yml index 7a206b519eaa..6650f101acc2 100644 --- a/.github/workflows/membership-checker.yml +++ b/.github/workflows/membership-checker.yml @@ -15,7 +15,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: '^1.20.1' + go-version: '^1.21' - name: Run membership checker unit tests run: | cd .ci/magician diff --git a/.github/workflows/request-reviewer.yml b/.github/workflows/request-reviewer.yml index 2831ec975caa..de54d2e2f353 100644 --- a/.github/workflows/request-reviewer.yml +++ b/.github/workflows/request-reviewer.yml @@ -28,7 +28,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: '^1.20' + go-version: '^1.21' # Disable caching for now due to issues with large provider dependency caches cache: false - name: Build magician diff --git a/.github/workflows/test-tgc.yml b/.github/workflows/test-tgc.yml index 190bb6ae68c0..1edfa5b9399a 100644 --- a/.github/workflows/test-tgc.yml +++ b/.github/workflows/test-tgc.yml @@ -80,7 +80,7 @@ jobs: if: ${{ !failure() && steps.pull_request.outputs.has_changes == 'true' }} uses: actions/setup-go@v4 with: - go-version: '^1.20' + go-version: '^1.21' - name: Build Terraform Google Conversion if: ${{ !failure() && steps.pull_request.outputs.has_changes == 'true' }} run: | diff --git a/.github/workflows/test-tpg.yml b/.github/workflows/test-tpg.yml index 9edca790e1ec..c59f4355f19d 100644 --- a/.github/workflows/test-tpg.yml +++ b/.github/workflows/test-tpg.yml @@ -70,7 +70,7 @@ jobs: if: ${{ !failure() && steps.pull_request.outputs.has_changes == 'true' }} uses: actions/setup-go@v4 with: - go-version: '^1.20' + go-version: '^1.21' - name: Build Provider if: ${{ !failure() && steps.pull_request.outputs.has_changes == 'true' }} run: | diff --git a/.github/workflows/unit-test-tgc.yml b/.github/workflows/unit-test-tgc.yml index f254f91240db..34011a802bed 100644 --- a/.github/workflows/unit-test-tgc.yml +++ b/.github/workflows/unit-test-tgc.yml @@ -30,7 +30,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: '^1.20' + go-version: '^1.21' - name: Cache Go modules and build cache uses: actions/cache@v3 diff --git a/.github/workflows/unit-test-tpg.yml b/.github/workflows/unit-test-tpg.yml index ac925a0fe621..e394fd9ab8d4 100644 --- a/.github/workflows/unit-test-tpg.yml +++ b/.github/workflows/unit-test-tpg.yml @@ -28,7 +28,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: '^1.20' + go-version: '^1.21' - name: Build Provider run: | diff --git a/.github/workflows/unit-tests-diff-processor.yml b/.github/workflows/unit-tests-diff-processor.yml index 91d081716ab3..8718b49b7e61 100644 --- a/.github/workflows/unit-tests-diff-processor.yml +++ b/.github/workflows/unit-tests-diff-processor.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: '^1.20.1' + go-version: '^1.21.0' - name: Build run: | diff --git a/docs/go.mod b/docs/go.mod index 35af46f9dda9..8d0779b9cb98 100644 --- a/docs/go.mod +++ b/docs/go.mod @@ -1,6 +1,6 @@ module github.com/GoogleCloudPlatform/magic-modules/docs -go 1.20 +go 1.21 require ( github.com/alex-shpak/hugo-book v0.0.0-20230424134111-d86d5e70c7c0 // indirect diff --git a/mmv1/go.mod b/mmv1/go.mod index 24d9a6c630d1..58a9d896cd1a 100644 --- a/mmv1/go.mod +++ b/mmv1/go.mod @@ -1,6 +1,6 @@ module github.com/GoogleCloudPlatform/magic-modules/mmv1 -go 1.20 +go 1.21 require ( golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 diff --git a/mmv1/third_party/terraform/.go-version b/mmv1/third_party/terraform/.go-version index 5fb5a6b4f547..d2ab029d32c6 100644 --- a/mmv1/third_party/terraform/.go-version +++ b/mmv1/third_party/terraform/.go-version @@ -1 +1 @@ -1.20 +1.21 diff --git a/mmv1/third_party/terraform/go.mod.erb b/mmv1/third_party/terraform/go.mod.erb index fa30a092113d..812e2da3e939 100644 --- a/mmv1/third_party/terraform/go.mod.erb +++ b/mmv1/third_party/terraform/go.mod.erb @@ -1,7 +1,7 @@ <% autogen_exception -%> module github.com/hashicorp/terraform-provider-google -go 1.20 +go 1.21 require ( cloud.google.com/go/bigtable v1.19.0 diff --git a/mmv1/third_party/terraform/go.sum b/mmv1/third_party/terraform/go.sum index 63d8188cf48c..1cfc99eed33f 100644 --- a/mmv1/third_party/terraform/go.sum +++ b/mmv1/third_party/terraform/go.sum @@ -14,10 +14,12 @@ cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWO cloud.google.com/go/longrunning v0.5.5 h1:GOE6pZFdSrTb4KAiKnXsJBtlE6mEyaW44oKyMILWnOg= cloud.google.com/go/longrunning v0.5.5/go.mod h1:WV2LAxD8/rg5Z1cNW6FJ/ZpX4E4VnDnoTk0yawPBB7s= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.62.0 h1:s4Y6r6RrYLBnqosGXLwR0h1Gqr0VT3wgd6rqvHsD9OE= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.62.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.0 h1:eSOBYPZVnU2fZul9sAJFGLVCgv6stNVKkmsogKF7UeY= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= @@ -28,6 +30,7 @@ github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJE github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= +github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= @@ -47,12 +50,14 @@ github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbi github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/creachadair/staticfile v0.1.2/go.mod h1:a3qySzCIXEprDGxk6tSxSI+dBBdLzqeBOMhZ+o2d3pM= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= +github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -70,8 +75,11 @@ github.com/gammazero/deque v0.0.0-20180920172122-f6adf94963e4/go.mod h1:GeIq9qoE github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92 h1:EipXK6U05IQ2wtuFRn4k3h0+2lXypzItoXGVyf4r9Io= github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92/go.mod h1:w9RqFVO2BM3xwWEcAB8Fwp0OviTBBEiRmSBDfbXnd3w= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= github.com/go-git/go-git/v5 v5.10.1 h1:tu8/D8i+TWxgKpzQ3Vc43e+kkhXqtsZCKI/egajKnxk= +github.com/go-git/go-git/v5 v5.10.1/go.mod h1:uEuHjxkHap8kAl//V5F/nNWwqIYtP/402ddd05mp0wg= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -81,6 +89,7 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= +github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -106,6 +115,7 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= +github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -177,8 +187,11 @@ github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv2 github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= +github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -214,15 +227,18 @@ github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= +github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -234,6 +250,7 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= @@ -242,6 +259,7 @@ github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21 github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -258,6 +276,7 @@ go.opentelemetry.io/otel v1.23.0/go.mod h1:YCycw9ZeKhcJFrb34iVSkyT0iczq/zYDtZYFu go.opentelemetry.io/otel/metric v1.23.0 h1:pazkx7ss4LFVVYSxYew7L5I6qvLXHA0Ap2pwV+9Cnpo= go.opentelemetry.io/otel/metric v1.23.0/go.mod h1:MqUW2X2a6Q8RN96E2/nqNoT+z9BSms20Jb7Bbp+HiTo= go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= go.opentelemetry.io/otel/trace v1.23.0 h1:37Ik5Ib7xfYVb4V1UtnT97T1jI+AoIYkJyPkuL4iJgI= go.opentelemetry.io/otel/trace v1.23.0/go.mod h1:GSGTbIClEsuZrGIzoEHqsVfxgn5UkggkflQwDScNUsk= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -336,6 +355,7 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -359,6 +379,7 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -404,6 +425,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= @@ -413,5 +435,4 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.0 h1:eSOBYPZVnU2fZul9sAJFGLVCgv6stNVKkmsogKF7UeY= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/mmv1/third_party/terraform/scripts/go.mod b/mmv1/third_party/terraform/scripts/go.mod index 8db8f05e9c85..0265d3bcb20a 100644 --- a/mmv1/third_party/terraform/scripts/go.mod +++ b/mmv1/third_party/terraform/scripts/go.mod @@ -1,3 +1,3 @@ module github.com/hashicorp/terraform-provider-google/scripts -go 1.20 +go 1.21 diff --git a/scripts/doctor b/scripts/doctor index ce131165d7f6..6a39b637e35c 100755 --- a/scripts/doctor +++ b/scripts/doctor @@ -48,9 +48,9 @@ if [ $found -eq 0 ]; then else version=($(go version)) version=${version[2]} - if [[ "$version" < "go1.20.0" ]]; then + if [[ "$version" < "go1.21.0" ]]; then exitcode=1 - warn "yel" " $version is installed, but go 1.20 or later is required. See https://golang.org/doc/install for information on installing it." + warn "yel" " $version is installed, but go 1.21 or later is required. See https://golang.org/doc/install for information on installing it." fi if [[ -z "${GOPATH}" ]]; then exitcode=1 diff --git a/tools/diff-processor/go.mod b/tools/diff-processor/go.mod index 78da81c6aeaa..f740f857b9cf 100644 --- a/tools/diff-processor/go.mod +++ b/tools/diff-processor/go.mod @@ -1,6 +1,6 @@ module github.com/GoogleCloudPlatform/magic-modules/tools/diff-processor -go 1.20 +go 1.21 replace google/provider/old => ./old diff --git a/tools/go-changelog/go.mod b/tools/go-changelog/go.mod index 1dcdd361463b..3a898fd8dcdd 100644 --- a/tools/go-changelog/go.mod +++ b/tools/go-changelog/go.mod @@ -7,7 +7,6 @@ require ( github.com/go-git/go-git/v5 v5.4.2 github.com/google/go-github v17.0.0+incompatible github.com/google/go-querystring v1.0.0 // indirect - github.com/manifoldco/promptui v0.8.0 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d golang.org/x/sync v0.0.0-20190423024810-112230192c58 ) diff --git a/tools/go-changelog/go.sum b/tools/go-changelog/go.sum index f15669f53a7b..ffa6cde2ab37 100644 --- a/tools/go-changelog/go.sum +++ b/tools/go-changelog/go.sum @@ -10,12 +10,6 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -47,8 +41,6 @@ github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= -github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU= -github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -59,16 +51,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw= -github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= -github.com/manifoldco/promptui v0.8.0 h1:R95mMF+McvXZQ7j1g8ucVZE1gLP3Sv6j9vlF9kyRqQo= -github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ= github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= -github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= @@ -103,7 +87,6 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -121,7 +104,6 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= diff --git a/tools/issue-labeler/go.mod b/tools/issue-labeler/go.mod index a1fcbec43647..658e2f70955f 100644 --- a/tools/issue-labeler/go.mod +++ b/tools/issue-labeler/go.mod @@ -1,13 +1,11 @@ module github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler -go 1.20 +go 1.21 require ( github.com/golang/glog v1.1.1 + golang.org/x/exp v0.0.0-20230810033253-352e893a4cad gopkg.in/yaml.v2 v2.4.0 ) -require ( - golang.org/x/exp v0.0.0-20230810033253-352e893a4cad // indirect - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect -) +require gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect diff --git a/tools/missing-test-detector/go.mod b/tools/missing-test-detector/go.mod index a074a5d1b471..e5d9ede9b28b 100644 --- a/tools/missing-test-detector/go.mod +++ b/tools/missing-test-detector/go.mod @@ -1,6 +1,6 @@ module github.com/GoogleCloudPlatform/magic-modules/tools/missing-test-detector -go 1.20 +go 1.21 replace google/provider/old => github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20230302220542-203a52c6e3e1 @@ -11,85 +11,41 @@ require ( github.com/hashicorp/hcl/v2 v2.14.1 github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0 github.com/zclconf/go-cty v1.11.0 - google/provider/new v0.0.0-00010101000000-000000000000 - google/provider/old v0.0.0-00010101000000-000000000000 ) require ( - bitbucket.org/creachadair/stringset v0.0.8 // indirect - cloud.google.com/go v0.105.0 // indirect - cloud.google.com/go/bigtable v1.17.0 // indirect - cloud.google.com/go/compute v1.13.0 // indirect - cloud.google.com/go/compute/metadata v0.2.2 // indirect - cloud.google.com/go/iam v0.8.0 // indirect - cloud.google.com/go/longrunning v0.3.0 // indirect - github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0 // indirect github.com/agext/levenshtein v1.2.2 // indirect - github.com/apparentlymart/go-cidr v1.1.0 // indirect github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect - github.com/cenkalti/backoff v2.2.1+incompatible // indirect - github.com/census-instrumentation/opencensus-proto v0.2.1 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect - github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 // indirect - github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 // indirect - github.com/envoyproxy/protoc-gen-validate v0.1.0 // indirect github.com/fatih/color v1.13.0 // indirect - github.com/gammazero/deque v0.0.0-20180920172122-f6adf94963e4 // indirect - github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92 // indirect - github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/go-cpy v0.0.0-20211218193943-a9c933c06932 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect - github.com/googleapis/gax-go/v2 v2.7.0 // indirect - github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect - github.com/hashicorp/go-checkpoint v0.5.0 // indirect - github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect github.com/hashicorp/go-hclog v1.2.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.4.4 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/hc-install v0.4.0 // indirect github.com/hashicorp/logutils v1.0.0 // indirect - github.com/hashicorp/terraform-exec v0.17.3 // indirect - github.com/hashicorp/terraform-json v0.14.0 // indirect github.com/hashicorp/terraform-plugin-go v0.14.0 // indirect github.com/hashicorp/terraform-plugin-log v0.7.0 // indirect - github.com/hashicorp/terraform-provider-google-beta v1.20.0 // indirect - github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c // indirect - github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 // indirect - github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect - github.com/kylelemons/godebug v1.1.0 // indirect + github.com/kr/pretty v0.2.1 // indirect + github.com/kr/text v0.2.0 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/go-wordwrap v1.0.0 // indirect - github.com/mitchellh/hashstructure v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect - github.com/oklog/run v1.0.0 // indirect - github.com/sirupsen/logrus v1.8.1 // indirect + github.com/sergi/go-diff v1.2.0 // indirect + github.com/stretchr/testify v1.8.1 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect github.com/vmihailenco/tagparser v0.1.1 // indirect - go.opencensus.io v0.24.0 // indirect - golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167 // indirect golang.org/x/net v0.7.0 // indirect - golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect golang.org/x/sys v0.5.0 // indirect golang.org/x/text v0.7.0 // indirect - golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.105.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20221206210731-b1a01be3a5f6 // indirect - google.golang.org/grpc v1.51.0 // indirect google.golang.org/protobuf v1.28.1 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect ) diff --git a/tools/missing-test-detector/go.sum b/tools/missing-test-detector/go.sum index 9200a80bcd61..0adca9eb9012 100644 --- a/tools/missing-test-detector/go.sum +++ b/tools/missing-test-detector/go.sum @@ -1,204 +1,52 @@ -bitbucket.org/creachadair/stringset v0.0.8 h1:gQqe4vs8XWgMyijfyKE6K8o4TcyGGrRXe0JvHgx5H+M= -bitbucket.org/creachadair/stringset v0.0.8/go.mod h1:AgthVMyMxC/6FK1KBJ2ALdqkZObGN8hOetgpwXyMn34= -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y= -cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= -cloud.google.com/go/bigtable v1.17.0 h1:8t48YTxxFsYKy+AWuHdoePgAr4J2gEtntbdWclbEbco= -cloud.google.com/go/bigtable v1.17.0/go.mod h1:wtf7lFV1Wa5ay6aKa/gv/T2Ci7J6qXpBX8Ofij2z5mo= -cloud.google.com/go/compute v1.13.0 h1:AYrLkB8NPdDRslNp4Jxmzrhdr03fUAIDbiGFjLWowoU= -cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= -cloud.google.com/go/compute/metadata v0.2.2 h1:aWKAjYaBaOSrpKl57+jnS/3fJRQnxL7TvR/u1VVbt6k= -cloud.google.com/go/compute/metadata v0.2.2/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= -cloud.google.com/go/iam v0.8.0 h1:E2osAkZzxI/+8pZcxVLcDtAQx/u+hZXVryUaYQ5O0Kk= -cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= -cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= -cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0 h1:YhWTPhOf6gVpA9mSfnLOuL8Y6j8W5pzmHE7flXjTke4= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ= -github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= -github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= -github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apparentlymart/go-cidr v1.1.0 h1:2mAhrMoF+nhXqxTzSZMUzDHkLjmIHC+Zzn4tdgBZjnU= -github.com/apparentlymart/go-cidr v1.1.0/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0 h1:MzVXffFUye+ZcSR6opIgz9Co7WcDx6ZcY+RjfFHoA0I= -github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= +github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= -github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 h1:hzAQntlaYRkVSFEfj9OTWlVV1H155FMD8BTKktLv0QI= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 h1:zH8ljVhhq7yC0MIeUL/IviMtY8hx2mK8cN9wEYb8ggw= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/creachadair/staticfile v0.1.2/go.mod h1:a3qySzCIXEprDGxk6tSxSI+dBBdLzqeBOMhZ+o2d3pM= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY= -github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= -github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 h1:xvqufLtNVwAhN8NMyWklVgxnWohi+wtMGQMhtxexlm0= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= -github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/gammazero/deque v0.0.0-20180920172122-f6adf94963e4 h1:R+19WKQClnfMXS60cP5BmMe1wjZ4u0evY2p2Ar0ZTXo= -github.com/gammazero/deque v0.0.0-20180920172122-f6adf94963e4/go.mod h1:GeIq9qoE43YdGnDXURnmKTnGg15pQz4mYkXSTChbneI= -github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92 h1:EipXK6U05IQ2wtuFRn4k3h0+2lXypzItoXGVyf4r9Io= -github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92/go.mod h1:w9RqFVO2BM3xwWEcAB8Fwp0OviTBBEiRmSBDfbXnd3w= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= -github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= -github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34= -github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0= -github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4= -github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cpy v0.0.0-20211218193943-a9c933c06932 h1:5/4TSDzpDnHQ8rKEEQBjRlYx77mHOvXu08oGchxej7o= -github.com/google/go-cpy v0.0.0-20211218193943-a9c933c06932/go.mod h1:cC6EdPbj/17GFCPDK39NRarlMI+kt+O60S12cNB5J9Y= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs= -github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= -github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU= -github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg= -github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= -github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI= github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs= github.com/hashicorp/go-hclog v1.2.1 h1:YQsLlGDJgwhXFpucSPyVbCBviQtjlHv3jLTlp8YmtEw= github.com/hashicorp/go-hclog v1.2.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-plugin v1.4.4 h1:NVdrSdFRt3SkZtNckJ6tog7gbpRrcbOjQi/rgF7JYWQ= -github.com/hashicorp/go-plugin v1.4.4/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.5.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/hc-install v0.4.0 h1:cZkRFr1WVa0Ty6x5fTvL1TuO1flul231rWkGH92oYYk= -github.com/hashicorp/hc-install v0.4.0/go.mod h1:5d155H8EC5ewegao9A4PUTMNPZaq+TbOzkJJZ4vrXeI= github.com/hashicorp/hcl/v2 v2.14.1 h1:x0BpjfZ+CYdbiz+8yZTQ+gdLO7IXvOut7Da+XJayx34= github.com/hashicorp/hcl/v2 v2.14.1/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0= github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/terraform-exec v0.17.3 h1:MX14Kvnka/oWGmIkyuyvL6POx25ZmKrjlaclkx3eErU= -github.com/hashicorp/terraform-exec v0.17.3/go.mod h1:+NELG0EqQekJzhvikkeQsOAZpsw0cv/03rbeQJqscAI= -github.com/hashicorp/terraform-json v0.14.0 h1:sh9iZ1Y8IFJLx+xQiKHGud6/TSUCM0N8e17dKDpqV7s= -github.com/hashicorp/terraform-json v0.14.0/go.mod h1:5A9HIWPkk4e5aeeXIBbkcOvaZbIYnAIkEyqP2pNSckM= github.com/hashicorp/terraform-plugin-go v0.14.0 h1:ttnSlS8bz3ZPYbMb84DpcPhY4F5DsQtcAS7cHo8uvP4= github.com/hashicorp/terraform-plugin-go v0.14.0/go.mod h1:2nNCBeRLaenyQEi78xrGrs9hMbulveqG/zDMQSvVJTE= github.com/hashicorp/terraform-plugin-log v0.7.0 h1:SDxJUyT8TwN4l5b5/VkiTIaQgY6R+Y2BQ0sRZftGKQs= github.com/hashicorp/terraform-plugin-log v0.7.0/go.mod h1:p4R1jWBXRTvL4odmEkFfDdhUjHf9zcs/BCoNHAc7IK4= github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0 h1:FtCLTiTcykdsURXPt/ku7fYXm3y19nbzbZcUxHx9RbI= github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0/go.mod h1:80wf5oad1tW+oLnbXS4UTYmDCrl7BuN1Q+IA91X1a4Y= -github.com/hashicorp/terraform-provider-google-beta v1.20.0 h1:rxZwjTPOQgmSaBINGCRhGTf9svsFU3n1iaF5i3rYIbo= -github.com/hashicorp/terraform-provider-google-beta v1.20.0/go.mod h1:t8+8q1zjjAREhGZHvwPU35evEHk9FqNvCpP8+HwJ3Cw= -github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20230302220542-203a52c6e3e1 h1:SQt8Fqd3Gn3/kztAZP66iPeAZWc0sSI8BuAInGlz7fY= -github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20230302220542-203a52c6e3e1/go.mod h1:t2+a8diaNw8ijSr89vu1SXw8xaHPZ6xSHnNEnRHNfvk= -github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20230303123138-8194a951d003 h1:JKikj+wm7GTMmjN27QJHiQpngOW/5JE7Az58Gk4YNcs= -github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20230303123138-8194a951d003/go.mod h1:t2+a8diaNw8ijSr89vu1SXw8xaHPZ6xSHnNEnRHNfvk= -github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c h1:D8aRO6+mTqHfLsK/BC3j5OAoogv1WLRWzY1AaTo3rBg= -github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c/go.mod h1:Wn3Na71knbXc1G8Lh+yu/dQWWJeFQEpDeJMtWMtlmNI= -github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 h1:HKLsbzeOsfXmKNpr3GiT18XAblV0BjCbzL8KQAMZGa0= -github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734/go.mod h1:kNDNcF7sN4DocDLBkQYz73HGKwN1ANB1blq4lIYLYvg= -github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ= -github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= -github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= -github.com/jhump/protoreflect v1.6.1 h1:4/2yi5LyDPP7nN+Hiird1SAJ6YoxUm13/oxHGRnbPd8= -github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= -github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -206,10 +54,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= @@ -218,45 +64,24 @@ github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/hashstructure v1.1.0 h1:P6P1hdjqAAknpY/M1CGipelZgp+4y9ja9kmUZPXP+H0= -github.com/mitchellh/hashstructure v1.1.0/go.mod h1:xUDAozZz0Wmdiufv0uyhnHkUTN6/6d8ulp4AwfLKrmA= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce h1:RPclfga2SEJmgMmz2k+Mg7cowZ8yv4Trqw9UsJby758= -github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce/go.mod h1:uFMI8w+ref4v2r9jz+c9i1IfIttS/OkmLfrk1jne5hs= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -269,167 +94,44 @@ github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvC github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37wVyIuWY= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= -github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= -github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= -github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= -github.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= github.com/zclconf/go-cty v1.11.0 h1:726SxLdi2SDnjY+BStqB9J1hNp4+2WlzyXLuimibIe0= github.com/zclconf/go-cty v1.11.0/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA= -github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167 h1:O8uGbHCqlTp2P6QJSLmCojM4mN6UemYv8K+dCnmHmu0= -golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191009170851-d66e71096ffb/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/api v0.105.0 h1:t6P9Jj+6XTn4U9I2wycQai6Q/Kz7iOT+QzjJ3G2V4x8= -google.golang.org/api v0.105.0/go.mod h1:qh7eD5FJks5+BcE+cjBIm6Gz8vioK7EHvnlniqXBnqI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20221206210731-b1a01be3a5f6 h1:AGXp12e/9rItf6/4QymU7WsAUwCf+ICW75cuR91nJIc= -google.golang.org/genproto v0.0.0-20221206210731-b1a01be3a5f6/go.mod h1:1dOng4TWOomJrDGhpXjfCD35wQC6jnC7HpRmOFRqEV0= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= -google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= diff --git a/tools/teamcity-generator/go.mod b/tools/teamcity-generator/go.mod index 3f998f908e09..52feebc78ba3 100644 --- a/tools/teamcity-generator/go.mod +++ b/tools/teamcity-generator/go.mod @@ -1,5 +1,5 @@ module github.com/GoogleCloudPlatform/magic-modules/tools/teamcity-generator -go 1.20 +go 1.21 require golang.org/x/text v0.11.0 diff --git a/tpgtools/go.mod b/tpgtools/go.mod index 90f55b270e1e..370f45a397b2 100644 --- a/tpgtools/go.mod +++ b/tpgtools/go.mod @@ -1,6 +1,6 @@ module github.com/GoogleCloudPlatform/magic-modules/tpgtools -go 1.20 +go 1.21 require ( bitbucket.org/creachadair/stringset v0.0.11 diff --git a/tpgtools/go.sum b/tpgtools/go.sum index 30d683a7cf40..93cccba40a06 100644 --- a/tpgtools/go.sum +++ b/tpgtools/go.sum @@ -108,6 +108,7 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= From 5114e38e93aa6bb80ef4d3040d1e06ff96023caf Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Wed, 13 Mar 2024 22:28:26 +0000 Subject: [PATCH 27/59] Add note about permissions (#10195) --- .../terraform/.teamcity/USE_CONFIG_WITH_TEAMCITY.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mmv1/third_party/terraform/.teamcity/USE_CONFIG_WITH_TEAMCITY.md b/mmv1/third_party/terraform/.teamcity/USE_CONFIG_WITH_TEAMCITY.md index 08bf66acb3a3..ee0d3c3a0cef 100644 --- a/mmv1/third_party/terraform/.teamcity/USE_CONFIG_WITH_TEAMCITY.md +++ b/mmv1/third_party/terraform/.teamcity/USE_CONFIG_WITH_TEAMCITY.md @@ -8,6 +8,10 @@ Contents: * [Editing configuration files](#editing-configuration-files) * [Pushing configuration changes to TeamCity](#pushing-configuration-changes-to-teamcity) +## Permissions + +Actions in this file require Project Administrator permissions - ask for these if you are unsure if you have them. + ## Using configuration files for the first time in a project From ca2bf3fb16fac2bc518da50d5d8c241207b4732f Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Wed, 13 Mar 2024 16:14:37 -0700 Subject: [PATCH 28/59] Fix the bug for computed labels and annotations (#10182) --- .../resource_bigquery_dataset_test.go | 70 +++++++++++++++++++ ...esource_cloudbuild_worker_pool_test.go.erb | 63 +++++++++++++++++ .../terraform/tpgresource/annotations.go | 9 +++ .../terraform/tpgresource/labels.go | 13 ++++ 4 files changed, 155 insertions(+) diff --git a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_dataset_test.go b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_dataset_test.go index f4c23fd09306..eec2a3a37c56 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_dataset_test.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_dataset_test.go @@ -98,6 +98,55 @@ func TestAccBigQueryDataset_basic(t *testing.T) { }) } +func TestAccBigQueryDataset_withComputedLabels(t *testing.T) { + // Skip it in VCR test because of the randomness of uuid in "labels" field + // which causes the replaying mode after recording mode failing in VCR test + acctest.SkipIfVcr(t) + t.Parallel() + + datasetID := fmt.Sprintf("tf_test_%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "random": {}, + }, + CheckDestroy: testAccCheckBigQueryDatasetDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigQueryDataset(datasetID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "labels.%", "2"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "labels.env", "foo"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "labels.default_table_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "effective_labels.%", "2"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "effective_labels.env", "foo"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "effective_labels.default_table_expiration_ms", "3600000"), + ), + }, + { + ResourceName: "google_bigquery_dataset.test", + ImportState: true, + ImportStateVerify: true, + // The labels field in the state is decided by the configuration. + // During importing, the configuration is unavailable, so the labels field in the state after importing is empty. + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccBigQueryDatasetUpdated_withComputedLabels(datasetID), + }, + { + ResourceName: "google_bigquery_dataset.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + }, + }) +} + func TestAccBigQueryDataset_withProvider5(t *testing.T) { acctest.SkipIfVcr(t) t.Parallel() @@ -493,6 +542,27 @@ resource "google_bigquery_dataset" "test" { `, datasetID) } +func testAccBigQueryDatasetUpdated_withComputedLabels(datasetID string) string { + return fmt.Sprintf(` +resource "random_uuid" "test" { +} + +resource "google_bigquery_dataset" "test" { + dataset_id = "%s" + # friendly_name = "bar" + description = "This is a bar description" + location = "EU" + default_partition_expiration_ms = 7200000 + default_table_expiration_ms = 7200000 + + labels = { + env = "${random_uuid.test.result}" + default_table_expiration_ms = 7200000 + } +} +`, datasetID) +} + func testAccBigQueryDatasetDeleteContents(datasetID string) string { return fmt.Sprintf(` resource "google_bigquery_dataset" "contents_test" { diff --git a/mmv1/third_party/terraform/services/cloudbuild/resource_cloudbuild_worker_pool_test.go.erb b/mmv1/third_party/terraform/services/cloudbuild/resource_cloudbuild_worker_pool_test.go.erb index 2954e203a654..73d952177b0b 100644 --- a/mmv1/third_party/terraform/services/cloudbuild/resource_cloudbuild_worker_pool_test.go.erb +++ b/mmv1/third_party/terraform/services/cloudbuild/resource_cloudbuild_worker_pool_test.go.erb @@ -14,6 +14,47 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" ) +func TestAccCloudbuildWorkerPool_withComputedAnnotations(t *testing.T) { + // Skip it in VCR test because of the randomness of uuid in "annotations" field + // which causes the replaying mode after recording mode failing in VCR test + acctest.SkipIfVcr(t) + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "project": envvar.GetTestProjectFromEnv(), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "random": {}, + }, + CheckDestroy: funcAccTestCloudbuildWorkerPoolCheckDestroy(t), + Steps: []resource.TestStep{ + { + Config: testAccCloudbuildWorkerPool_updated(context), + }, + { + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations"}, + ResourceName: "google_cloudbuild_worker_pool.pool", + }, + { + Config: testAccCloudbuildWorkerPool_withComputedAnnotations(context), + }, + { + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations"}, + ResourceName: "google_cloudbuild_worker_pool.pool", + }, + }, + }) +} + func TestAccCloudbuildWorkerPool_basic(t *testing.T) { t.Parallel() @@ -89,6 +130,28 @@ resource "google_cloudbuild_worker_pool" "pool" { `, context) } +func testAccCloudbuildWorkerPool_withComputedAnnotations(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "random_uuid" "test" { +} + +resource "google_cloudbuild_worker_pool" "pool" { + name = "pool%{random_suffix}" + location = "europe-west1" + worker_config { + disk_size_gb = 101 + machine_type = "e2-standard-4" + no_external_ip = false + } + + annotations = { + env = "${random_uuid.test.result}" + default_expiration_ms = 3600000 + } +} +`, context) +} + func testAccCloudbuildWorkerPool_noWorkerConfig(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_cloudbuild_worker_pool" "pool" { diff --git a/mmv1/third_party/terraform/tpgresource/annotations.go b/mmv1/third_party/terraform/tpgresource/annotations.go index 410fbd2355d4..d43d608d16de 100644 --- a/mmv1/third_party/terraform/tpgresource/annotations.go +++ b/mmv1/third_party/terraform/tpgresource/annotations.go @@ -17,6 +17,15 @@ func SetAnnotationsDiff(_ context.Context, d *schema.ResourceDiff, meta interfac return fmt.Errorf("`effective_annotations` field is not present in the resource schema.") } + // If "annotations" field is computed, set "effective_annotations" to computed. + // https://github.com/hashicorp/terraform-provider-google/issues/16217 + if !d.GetRawPlan().GetAttr("annotations").IsWhollyKnown() { + if err := d.SetNewComputed("effective_annotations"); err != nil { + return fmt.Errorf("error setting effective_annotations to computed: %w", err) + } + return nil + } + o, n := d.GetChange("annotations") effectiveAnnotations := d.Get("effective_annotations").(map[string]interface{}) diff --git a/mmv1/third_party/terraform/tpgresource/labels.go b/mmv1/third_party/terraform/tpgresource/labels.go index 0465456e254a..5cfaa93ef41a 100644 --- a/mmv1/third_party/terraform/tpgresource/labels.go +++ b/mmv1/third_party/terraform/tpgresource/labels.go @@ -69,6 +69,19 @@ func SetLabelsDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) return fmt.Errorf("`effective_labels` field is not present in the resource schema.") } + // If "labels" field is computed, set "terraform_labels" and "effective_labels" to computed. + // https://github.com/hashicorp/terraform-provider-google/issues/16217 + if !d.GetRawPlan().GetAttr("labels").IsWhollyKnown() { + if err := d.SetNewComputed("terraform_labels"); err != nil { + return fmt.Errorf("error setting terraform_labels to computed: %w", err) + } + + if err := d.SetNewComputed("effective_labels"); err != nil { + return fmt.Errorf("error setting effective_labels to computed: %w", err) + } + return nil + } + config := meta.(*transport_tpg.Config) // Merge provider default labels with the user defined labels in the resource to get terraform managed labels From 1e3a728a0e161678338b385ee04d4a92b4603c57 Mon Sep 17 00:00:00 2001 From: Lingkai Shen Date: Thu, 14 Mar 2024 11:27:35 -0400 Subject: [PATCH 29/59] AndroidApp package_name should be immutable & required (#10194) --- mmv1/products/firebase/AndroidApp.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mmv1/products/firebase/AndroidApp.yaml b/mmv1/products/firebase/AndroidApp.yaml index 3e58993f5e98..47b74005bd5c 100644 --- a/mmv1/products/firebase/AndroidApp.yaml +++ b/mmv1/products/firebase/AndroidApp.yaml @@ -122,8 +122,10 @@ properties: This identifier should be treated as an opaque token, as the data format is not specified. - !ruby/object:Api::Type::String name: packageName + immutable: true + required: true description: | - Immutable. The canonical package name of the Android app as would appear in the Google Play + The canonical package name of the Android app as would appear in the Google Play Developer Console. - !ruby/object:Api::Type::Array name: sha1Hashes From 10f99b700278026de23a26bc1475783d300a411c Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Thu, 14 Mar 2024 11:41:51 -0700 Subject: [PATCH 30/59] Fix service team reviews (#10200) * Corrected unknown command messge to clean up stderr * Made tests throw error if team name is empty * Fixed handling of unset github_team name --- .ci/magician/cmd/mock_github_test.go | 9 ++++++- .ci/magician/cmd/mock_runner_test.go | 26 +++++++++++++++++-- .ci/magician/cmd/request_service_reviewers.go | 2 +- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/.ci/magician/cmd/mock_github_test.go b/.ci/magician/cmd/mock_github_test.go index 69eb80eee99f..5a836ff602f0 100644 --- a/.ci/magician/cmd/mock_github_test.go +++ b/.ci/magician/cmd/mock_github_test.go @@ -15,7 +15,11 @@ */ package cmd -import "magician/github" +import ( + "errors" + + "magician/github" +) type mockGithub struct { pullRequest github.PullRequest @@ -53,6 +57,9 @@ func (m *mockGithub) GetPullRequestPreviousReviewers(prNumber string) ([]github. func (m *mockGithub) GetTeamMembers(organization, team string) ([]github.User, error) { m.calledMethods["GetTeamMembers"] = append(m.calledMethods["GetTeamMembers"], []any{organization, team}) + if team == "" { + return nil, errors.New("No team members set") + } return m.teamMembers[team], nil } diff --git a/.ci/magician/cmd/mock_runner_test.go b/.ci/magician/cmd/mock_runner_test.go index bc470b13d685..72587c26b418 100644 --- a/.ci/magician/cmd/mock_runner_test.go +++ b/.ci/magician/cmd/mock_runner_test.go @@ -20,7 +20,12 @@ import ( "errors" "fmt" "log" + "os" "path/filepath" + "sort" + "strings" + + "golang.org/x/exp/maps" ) type ParameterList []any @@ -37,7 +42,24 @@ type mockRunner struct { dirStack *list.List } +func sortedEnvString(env map[string]string) string { + keys := maps.Keys(env) + sort.Strings(keys) + kvs := make([]string, len(keys)) + for i, k := range keys { + kvs[i] = fmt.Sprintf("%s:%s", k, env[k]) + } + return fmt.Sprintf("map[%s]", strings.Join(kvs, " ")) +} + func NewMockRunner() MockRunner { + diffProcessorEnv := map[string]string{ + "NEW_REF": "auto-pr-123456", + "OLD_REF": "auto-pr-123456-old", + "PATH": os.Getenv("PATH"), + "GOPATH": os.Getenv("GOPATH"), + "HOME": os.Getenv("HOME"), + } return &mockRunner{ calledMethods: make(map[string][]ParameterList), cmdResults: map[string]string{ @@ -47,7 +69,7 @@ func NewMockRunner() MockRunner { "/mock/dir/magic-modules/.ci/magician git [clone -b auto-pr-123456 https://modular-magician:*******@github.com/modular-magician/terraform-provider-google-beta /mock/dir/tpgb] map[]": "", "/mock/dir/magic-modules git [diff HEAD origin/main tools/missing-test-detector] map[]": "", "/mock/dir/magic-modules/tools/diff-processor bin/diff-processor [breaking-changes] map[]": "", - "/mock/dir/magic-modules/tools/diff-processor make [build] map[NEW_REF:auto-pr-123456 OLD_REF:auto-pr-123456-old]": "", + "/mock/dir/magic-modules/tools/diff-processor make [build] " + sortedEnvString(diffProcessorEnv): "", "/mock/dir/magic-modules/tools/diff-processor bin/diff-processor [add-labels 123456] map[GITHUB_TOKEN_MAGIC_MODULES:*******]": "", "/mock/dir/magic-modules/tools/missing-test-detector go [mod edit -replace google/provider/new=/mock/dir/tpgb] map[]": "", "/mock/dir/magic-modules/tools/missing-test-detector go [mod edit -replace google/provider/old=/mock/dir/tpgbold] map[]": "", @@ -128,7 +150,7 @@ func (mr *mockRunner) PopDir() error { func (mr *mockRunner) Run(name string, args []string, env map[string]string) (string, error) { mr.calledMethods["Run"] = append(mr.calledMethods["Run"], ParameterList{mr.cwd, name, args, env}) - cmd := fmt.Sprintf("%s %s %v %v", mr.cwd, name, args, env) + cmd := fmt.Sprintf("%s %s %v %s", mr.cwd, name, args, sortedEnvString(env)) if result, ok := mr.cmdResults[cmd]; ok { return result, nil } diff --git a/.ci/magician/cmd/request_service_reviewers.go b/.ci/magician/cmd/request_service_reviewers.go index 6ef80c5283c0..70343946ee34 100644 --- a/.ci/magician/cmd/request_service_reviewers.go +++ b/.ci/magician/cmd/request_service_reviewers.go @@ -89,7 +89,7 @@ func execRequestServiceReviewers(prNumber string, gh GithubClient, enrolledTeams continue } teamCount += 1 - if labelData, ok := enrolledTeams[label.Name]; ok { + if labelData, ok := enrolledTeams[label.Name]; ok && labelData.Team != "" { githubTeamsSet[labelData.Team] = struct{}{} } } From 16d4f0faa68159cdeffa19bb1cc1df810d191d73 Mon Sep 17 00:00:00 2001 From: Benjamin Kaplan <58792807+bskaplan@users.noreply.github.com> Date: Thu, 14 Mar 2024 12:30:19 -0700 Subject: [PATCH 31/59] Add gcs volume type to Cloud Run v2 beta provider (#9746) * Add gcs volume type to Cloud Run v2 beta provider * update gcs v2 docs to specify required launch stage and execution environment * merge changes with upstream --- mmv1/products/cloudrunv2/Job.yaml | 23 ++++ mmv1/products/cloudrunv2/Service.yaml | 12 +- ... => resource_cloud_run_v2_job_test.go.erb} | 89 +++++++++++++++ .../resource_cloud_run_v2_service_test.go.erb | 103 +++++++++++++++++- 4 files changed, 224 insertions(+), 3 deletions(-) rename mmv1/third_party/terraform/services/cloudrunv2/{resource_cloud_run_v2_job_test.go => resource_cloud_run_v2_job_test.go.erb} (77%) diff --git a/mmv1/products/cloudrunv2/Job.yaml b/mmv1/products/cloudrunv2/Job.yaml index 176c056e5715..4daa40450fc6 100644 --- a/mmv1/products/cloudrunv2/Job.yaml +++ b/mmv1/products/cloudrunv2/Job.yaml @@ -399,6 +399,7 @@ properties: # - template.0.template.0.volumes.0.secret # - template.0.template.0.volumes.0.cloudSqlInstance # - template.0.template.0.volumes.0.emptyDir + # - template.0.volumes.0.gcs properties: - !ruby/object:Api::Type::String name: 'secret' @@ -437,6 +438,7 @@ properties: # - template.0.template.0.volumes.0.secret # - template.0.template.0.volumes.0.cloudSqlInstance # - template.0.template.0.volumes.0.emptyDir + # - template.0.volumes.0.gcs properties: - !ruby/object:Api::Type::Array name: 'instances' @@ -452,6 +454,7 @@ properties: # - template.0.template.0.volumes.0.secret # - template.0.template.0.volumes.0.cloudSqlInstance # - template.0.template.0.volumes.0.emptyDir + # - template.0.volumes.0.gcs properties: - !ruby/object:Api::Type::Enum name: 'medium' @@ -464,6 +467,26 @@ properties: name: 'sizeLimit' description: |- Limit on the storage usable by this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. This field's values are of the 'Quantity' k8s type: https://kubernetes.io/docs/reference/kubernetes-api/common-definitions/quantity/. The default is nil which means that the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir. + - !ruby/object:Api::Type::NestedObject + name: 'gcs' + description: |- + Cloud Storage bucket mounted as a volume using GCSFuse. This feature requires the launch stage to be set to ALPHA or BETA. + min_version: beta + # exactly_one_of: + # - template.0.volumes.0.secret + # - template.0.volumes.0.cloudSqlInstance + # - template.0.volumes.0.emptyDir + # - template.0.volumes.0.gcs + properties: + - !ruby/object:Api::Type::String + name: 'bucket' + required: true + description: |- + Name of the cloud storage bucket to back the volume. The resource service account must have permission to access the bucket. + - !ruby/object:Api::Type::Boolean + name: 'readOnly' + description: |- + If true, mount this volume as read-only in all mounts. If false, mount this volume as read-write. - !ruby/object:Api::Type::String name: 'timeout' description: |- diff --git a/mmv1/products/cloudrunv2/Service.yaml b/mmv1/products/cloudrunv2/Service.yaml index bbedcc2cf10c..909b454786a6 100644 --- a/mmv1/products/cloudrunv2/Service.yaml +++ b/mmv1/products/cloudrunv2/Service.yaml @@ -741,6 +741,7 @@ properties: # - template.0.volumes.0.secret # - template.0.volumes.0.cloudSqlInstance # - template.0.volumes.0.emptyDir + # - template.0.volumes.0.gcs properties: - !ruby/object:Api::Type::Array name: 'instances' @@ -757,6 +758,7 @@ properties: # - template.0.volumes.0.secret # - template.0.volumes.0.cloudSqlInstance # - template.0.volumes.0.emptyDir + # - template.0.volumes.0.gcs properties: - !ruby/object:Api::Type::Enum name: 'medium' @@ -770,8 +772,14 @@ properties: description: |- Limit on the storage usable by this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. This field's values are of the 'Quantity' k8s type: https://kubernetes.io/docs/reference/kubernetes-api/common-definitions/quantity/. The default is nil which means that the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir. - !ruby/object:Api::Type::NestedObject - name: gcs - description: Represents a GCS Bucket mounted as a volume. + name: 'gcs' + description: |- + Cloud Storage bucket mounted as a volume using GCSFuse. This feature is only supported in the gen2 execution environment and requires launch-stage to be set to ALPHA or BETA. + # exactly_one_of: + # - template.0.volumes.0.secret + # - template.0.volumes.0.cloudSqlInstance + # - template.0.volumes.0.emptyDir + # - template.0.volumes.0.gcs properties: - !ruby/object:Api::Type::String name: bucket diff --git a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go.erb similarity index 77% rename from mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go rename to mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go.erb index e2cbbba9a30a..feca32ee81e7 100644 --- a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go +++ b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go.erb @@ -1,3 +1,4 @@ +<% autogen_exception -%> package cloudrunv2_test import ( @@ -298,3 +299,91 @@ func testAccCloudRunV2Job_cloudrunv2JobWithDirectVPCUpdate(context map[string]in } `, context) } + +<% unless version == 'ga' -%> +func TestAccCloudRunV2Job_cloudrunv2JobWithGcsUpdate(t *testing.T) { + t.Parallel() + + jobName := fmt.Sprintf("tf-test-cloudrun-service%s", acctest.RandString(t, 10)) + context := map[string]interface{}{ + "job_name": jobName, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckCloudRunV2JobDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccCloudRunV2Job_cloudrunv2JobWithNoVolume(context), + }, + { + ResourceName: "google_cloud_run_v2_job.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "launch_stage"}, + }, + { + Config: testAccCloudRunV2Job_cloudrunv2JobWithGcsVolume(context), + }, + { + ResourceName: "google_cloud_run_v2_job.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "launch_stage"}, + }, + }, + }) +} + +func testAccCloudRunV2Job_cloudrunv2JobWithNoVolume(context map[string]interface{}) string { + return acctest.Nprintf(` + resource "google_cloud_run_v2_job" "default" { + name = "%{job_name}" + location = "us-central1" + launch_stage = "BETA" + template { + template { + containers { + image = "us-docker.pkg.dev/cloudrun/container/job" + } + } + } + + lifecycle { + ignore_changes = [ + launch_stage, + ] + } + } +`, context) +} + +func testAccCloudRunV2Job_cloudrunv2JobWithGcsVolume(context map[string]interface{}) string { + return acctest.Nprintf(` + resource "google_cloud_run_v2_job" "default" { + name = "%{job_name}" + location = "us-central1" + launch_stage = "BETA" + template { + template { + containers { + image = "us-docker.pkg.dev/cloudrun/container/job" + volume_mounts { + name = "gcs" + mount_path = "/mnt/gcs" + } + } + volumes { + name = "gcs" + gcs { + bucket = "gcp-public-data-landsat" + read_only = true + } + } + } + } + } +`, context) +} +<% end -%> diff --git a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go.erb b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go.erb index bacaa401b2d6..b4f3b6ad5a9a 100644 --- a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go.erb +++ b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go.erb @@ -46,6 +46,7 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceFullUpdate(t *testing.T) { }) } + func testAccCloudRunV2Service_cloudrunv2ServiceFull(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_cloud_run_v2_service" "default" { @@ -109,7 +110,6 @@ resource "google_service_account" "service_account" { } `, context) } - func testAccCloudRunV2Service_cloudrunv2ServiceFullUpdate(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_cloud_run_v2_service" "default" { @@ -208,7 +208,108 @@ resource "google_compute_network" "custom_test" { } `, context) } +<% unless version == 'ga' -%> +func TestAccCloudRunV2Service_cloudrunv2ServiceGcsVolume(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckCloudRunV2ServiceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccCloudRunV2Service_cloudrunv2ServiceGcsVolume(context), + }, + { + ResourceName: "google_cloud_run_v2_service.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location", "annotations", "labels", "terraform_labels", "launch_stage"}, + }, + }, + }) +} + +func testAccCloudRunV2Service_cloudrunv2ServiceGcsVolume(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_cloud_run_v2_service" "default" { + name = "tf-test-cloudrun-service%{random_suffix}" + description = "description creating" + location = "us-central1" + launch_stage = "BETA" + annotations = { + generated-by = "magic-modules" + } + ingress = "INGRESS_TRAFFIC_ALL" + labels = { + label-1 = "value-1" + } + client = "client-1" + client_version = "client-version-1" + template { + labels = { + label-1 = "value-1" + } + timeout = "300s" + service_account = google_service_account.service_account.email + execution_environment = "EXECUTION_ENVIRONMENT_GEN2" + scaling { + max_instance_count = 3 + min_instance_count = 1 + } + annotations = { + generated-by = "magic-modules" + } + volumes { + name = "gcs" + gcs { + bucket = "gcp-public-data-landsat" + read_only = true + } + } + containers { + name = "container-1" + image = "us-docker.pkg.dev/cloudrun/container/hello" + env { + name = "SOURCE" + value = "remote" + } + env { + name = "TARGET" + value = "home" + } + ports { + name = "h2c" + container_port = 8080 + } + volume_mounts { + name = "gcs" + mount_path = "/mnt/landsat" + } + resources { + cpu_idle = true + startup_cpu_boost = true + limits = { + cpu = "4" + memory = "2Gi" + } + } + } + session_affinity = false + } +} +resource "google_service_account" "service_account" { + account_id = "tf-test-my-account%{random_suffix}" + display_name = "Test Service Account" +} +`, context) +} +<%end -%> func TestAccCloudRunV2Service_cloudrunv2ServiceTCPProbesUpdate(t *testing.T) { t.Parallel() From 219ab589aaafa919c7011967def03305f56c8462 Mon Sep 17 00:00:00 2001 From: Ali Ebrahim Date: Thu, 14 Mar 2024 13:36:33 -0700 Subject: [PATCH 32/59] cloudrunv2: Validate number of ports specified restricting to 1. (#10173) * cloudrunv2: Validate number of ports specified restricting to 1. * Update mmv1/products/cloudrunv2/Service.yaml --- mmv1/products/cloudrunv2/Service.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/mmv1/products/cloudrunv2/Service.yaml b/mmv1/products/cloudrunv2/Service.yaml index 909b454786a6..2568620c8fc7 100644 --- a/mmv1/products/cloudrunv2/Service.yaml +++ b/mmv1/products/cloudrunv2/Service.yaml @@ -448,6 +448,7 @@ properties: Determines whether CPU should be boosted on startup of a new container instance above the requested CPU threshold, this can help reduce cold-start latency. - !ruby/object:Api::Type::Array name: 'ports' + max_size: 1 description: |- List of ports to expose from the container. Only a single port can be specified. The specified ports must be listening on all interfaces (0.0.0.0) within the container to be accessible. From fab4b93a978a4cb74f7d4726c4102ac500961a1e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 15:15:54 -0700 Subject: [PATCH 33/59] Bump google.golang.org/protobuf from 1.28.1 to 1.33.0 in /.ci/magician (#10196) Bumps google.golang.org/protobuf from 1.28.1 to 1.33.0. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .ci/magician/go.mod | 11 +++++++---- .ci/magician/go.sum | 21 +++++++++++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/.ci/magician/go.mod b/.ci/magician/go.mod index 4f089f20df4f..165526d48c67 100644 --- a/.ci/magician/go.mod +++ b/.ci/magician/go.mod @@ -13,7 +13,11 @@ require ( google.golang.org/api v0.112.0 ) -require github.com/otiai10/copy v1.12.0 +require ( + github.com/otiai10/copy v1.12.0 + github.com/stretchr/testify v1.8.4 + gopkg.in/yaml.v2 v2.4.0 +) require ( cloud.google.com/go/compute v1.18.0 // indirect @@ -25,8 +29,8 @@ require ( github.com/google/uuid v1.3.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect github.com/googleapis/gax-go/v2 v2.7.0 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/stretchr/testify v1.8.4 // indirect go.opencensus.io v0.24.0 // indirect golang.org/x/net v0.15.0 // indirect golang.org/x/oauth2 v0.6.0 // indirect @@ -35,7 +39,6 @@ require ( google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488 // indirect google.golang.org/grpc v1.53.0 // indirect - google.golang.org/protobuf v1.28.1 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/.ci/magician/go.sum b/.ci/magician/go.sum index cc6550f565aa..7fc76449804d 100644 --- a/.ci/magician/go.sum +++ b/.ci/magician/go.sum @@ -5,13 +5,13 @@ cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOV cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= +cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler v0.0.0-20231219215713-49252d7a95dc h1:EhpDpfqwRHmrIgDJQkdNOMhm374ylpVuR1sN7EdgVr4= -github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler v0.0.0-20231219215713-49252d7a95dc/go.mod h1:mqTMlyCznI9dA2Mf8oVdRuCArfCwfHE+5vpe3wEQ7qI= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -47,6 +47,7 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -56,12 +57,20 @@ github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1Yu github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/otiai10/copy v1.12.0 h1:cLMgSQnXBs1eehF0Wy/FAGsgDTDmAqFR7rQylBb1nDY= github.com/otiai10/copy v1.12.0/go.mod h1:rSaLseMUsZFFbsFGc7wCJnnkTAvdc5L6VWxPE4308Ww= github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= +github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= @@ -80,8 +89,6 @@ go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20230314191032-db074128a8ec h1:pAv+d8BM2JNnNctsLJ6nnZ6NqXT8N4+eauvZSb3P0I0= -golang.org/x/exp v0.0.0-20230314191032-db074128a8ec/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/exp v0.0.0-20230810033253-352e893a4cad h1:g0bG7Z4uG+OgH2QDODnjp6ggkk1bJDsINcuWmJN1iJU= golang.org/x/exp v0.0.0-20230810033253-352e893a4cad/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -148,9 +155,11 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 944450cac1644467f78fbcde4ed870ccbd07ba6f Mon Sep 17 00:00:00 2001 From: askubis Date: Thu, 14 Mar 2024 23:18:59 +0100 Subject: [PATCH 34/59] attempt at fixing the (R)IGM.status output message (#10188) * attempt at fixing the (R)IGM.status output message * Fix plural of instances * Fix plural of instances * Fix plural of instances * Fix plural of instances --- ...urce_compute_instance_group_manager.go.erb | 22 ++++++++++++------- ...mpute_region_instance_group_manager.go.erb | 7 +++++- ...mpute_instance_group_manager.html.markdown | 12 ++++++++-- ...egion_instance_group_manager.html.markdown | 12 ++++++++-- 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb index 97baae34251f..7ee2ac2bbb18 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb @@ -459,13 +459,18 @@ func ResourceComputeInstanceGroupManager() *schema.Resource { Computed: true, Description: `Status of all-instances configuration on the group.`, Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "effective": { - Type: schema.TypeBool, - Computed: true, - Description: `A bit indicating whether this configuration has been applied to all managed instances in the group.`, - }, - }, + Schema: map[string]*schema.Schema{ + "effective": { + Type: schema.TypeBool, + Computed: true, + Description: `A bit indicating whether this configuration has been applied to all managed instances in the group.`, + }, + "current_revision": { + Type: schema.TypeString, + Computed: true, + Description: `Current all-instances configuration revision. This value is in RFC3339 text format.`, + }, + }, }, }, "stateful": { @@ -482,7 +487,7 @@ func ResourceComputeInstanceGroupManager() *schema.Resource { "per_instance_configs": { Type: schema.TypeList, Computed: true, - Description: `Status of per-instance configs on the instance.`, + Description: `Status of per-instance configs on the instances.`, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "all_effective": { @@ -1492,6 +1497,7 @@ func flattenStatusAllInstancesConfig(allInstancesConfig *compute.InstanceGroupMa results := []map[string]interface{}{} data := map[string]interface{}{ "effective": allInstancesConfig.Effective, + "current_revision": allInstancesConfig.CurrentRevision, } results = append(results, data) return results diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb index 8c756656264c..9a380f05eaf5 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb @@ -492,6 +492,11 @@ func ResourceComputeRegionInstanceGroupManager() *schema.Resource { Computed: true, Description: `A bit indicating whether this configuration has been applied to all managed instances in the group.`, }, + "current_revision": { + Type: schema.TypeString, + Computed: true, + Description: `Current all-instances configuration revision. This value is in RFC3339 text format.`, + }, }, }, }, @@ -509,7 +514,7 @@ func ResourceComputeRegionInstanceGroupManager() *schema.Resource { "per_instance_configs": { Type: schema.TypeList, Computed: true, - Description: `Status of per-instance configs on the instance.`, + Description: `Status of per-instance configs on the instances.`, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "all_effective": { diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown index 04f576cb43cf..b76ff773958b 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown @@ -329,17 +329,25 @@ The `status` block holds: * `version_target` - A status of consistency of Instances' versions with their target version specified by version field on Instance Group Manager. +* `all_instances_config` - Status of all-instances configuration on the group. + +* `stateful` - Stateful status of the given Instance Group Manager. + The `version_target` block holds: * `version_target` - A bit indicating whether version target has been reached in this managed instance group, i.e. all instances are in their target version. Instances' target version are specified by version field on Instance Group Manager. -* `stateful` - Stateful status of the given Instance Group Manager. +The `all_instances_config` block holds: + +* `effective` - A bit indicating whether this configuration has been applied to all managed instances in the group. + +* `current_revision` - Current all-instances configuration revision. This value is in RFC3339 text format. The `stateful` block holds: * `has_stateful_config` - A bit indicating whether the managed instance group has stateful configuration, that is, if you have configured any items in a stateful policy or in per-instance configs. The group might report that it has no stateful config even when there is still some preserved state on a managed instance, for example, if you have deleted all PICs but not yet applied those deletions. -* `per_instance_configs` - Status of per-instance configs on the instance. +* `per_instance_configs` - Status of per-instance configs on the instances. The `per_instance_configs` block holds: diff --git a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown index eeab84344718..052747cdee7f 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown @@ -336,19 +336,27 @@ The `status` block holds: * `is_stable` - A bit indicating whether the managed instance group is in a stable state. A stable state means that: none of the instances in the managed instance group is currently undergoing any type of change (for example, creation, restart, or deletion); no future changes are scheduled for instances in the managed instance group; and the managed instance group itself is not being modified. +* `all_instances_config` - Status of all-instances configuration on the group. + +* `stateful` - Stateful status of the given Instance Group Manager. + * `version_target` - A status of consistency of Instances' versions with their target version specified by version field on Instance Group Manager. The `version_target` block holds: * `version_target` - A bit indicating whether version target has been reached in this managed instance group, i.e. all instances are in their target version. Instances' target version are specified by version field on Instance Group Manager. -* `stateful` - Stateful status of the given Instance Group Manager. +The `all_instances_config` block holds: + +* `effective` - A bit indicating whether this configuration has been applied to all managed instances in the group. + +* `current_revision` - Current all-instances configuration revision. This value is in RFC3339 text format. The `stateful` block holds: * `has_stateful_config` - A bit indicating whether the managed instance group has stateful configuration, that is, if you have configured any items in a stateful policy or in per-instance configs. The group might report that it has no stateful config even when there is still some preserved state on a managed instance, for example, if you have deleted all PICs but not yet applied those deletions. -* `per_instance_configs` - Status of per-instance configs on the instance. +* `per_instance_configs` - Status of per-instance configs on the instances. The `per_instance_configs` block holds: From 7f8a73595635f1ddd917fd6b33ce9a6d1bcf2c97 Mon Sep 17 00:00:00 2001 From: Charles Leon Date: Thu, 14 Mar 2024 15:21:16 -0700 Subject: [PATCH 35/59] Access Context Manager - make ingress and egress rules immutable (#10147) * Access Context Manager - make ingress and egress rules immutable * Move immutable state to top level resource --------- Co-authored-by: Charles Leon --- .../ServicePerimeterEgressPolicy.yaml | 10 ++++- .../ServicePerimeterIngressPolicy.yaml | 10 ++++- ...ger_service_perimeter_egress_policy.tf.erb | 36 +++++++++++++++++ ...er_service_perimeter_ingress_policy.tf.erb | 39 +++++++++++++++++++ 4 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 mmv1/templates/terraform/examples/access_context_manager_service_perimeter_egress_policy.tf.erb create mode 100644 mmv1/templates/terraform/examples/access_context_manager_service_perimeter_ingress_policy.tf.erb diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml index 738ceefd98bd..5c26b6c85bc8 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml @@ -18,6 +18,7 @@ self_link: '{{perimeter}}' create_verb: :PATCH delete_verb: :PATCH update_mask: true +immutable: true identity: - egressFrom - egressTo @@ -37,6 +38,14 @@ description: | within the ServicePerimeter to access a defined set of projects outside the perimeter in certain contexts (e.g. to read data from a Cloud Storage bucket or query against a BigQuery dataset). + + ~> **Note:** By default, updates to this resource will remove the EgressPolicy from the + from the perimeter and add it back in a non-atomic manner. To ensure that the new EgressPolicy + is added before the old one is removed, add a `lifecycle` block with `create_before_destroy = true` to this resource. +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'access_context_manager_service_perimeter_egress_policy' + skip_test: true autogen_async: true exclude_tgc: true # Skipping the sweeper due to the non-standard base_url and because this is fine-grained under ServicePerimeter @@ -54,7 +63,6 @@ parameters: description: | The name of the Service Perimeter to add this resource to. required: true - immutable: true url_param_only: true properties: - !ruby/object:Api::Type::NestedObject diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml index 195b87db9bfa..c17f8a3e0471 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml @@ -18,6 +18,7 @@ self_link: '{{perimeter}}' create_verb: :PATCH delete_verb: :PATCH update_mask: true +immutable: true identity: - ingressFrom - ingressTo @@ -38,6 +39,14 @@ description: | For access from private networks, using the project of the hosting network is required. Individual ingress policies can be limited by restricting which services and/ or actions they match using the ingressTo field. + + ~> **Note:** By default, updates to this resource will remove the IngressPolicy from the + from the perimeter and add it back in a non-atomic manner. To ensure that the new IngressPolicy + is added before the old one is removed, add a `lifecycle` block with `create_before_destroy = true` to this resource. +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'access_context_manager_service_perimeter_ingress_policy' + skip_test: true autogen_async: true exclude_tgc: true # Skipping the sweeper due to the non-standard base_url and because this is fine-grained under ServicePerimeter @@ -55,7 +64,6 @@ parameters: description: | The name of the Service Perimeter to add this resource to. required: true - immutable: true url_param_only: true properties: - !ruby/object:Api::Type::NestedObject diff --git a/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_egress_policy.tf.erb b/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_egress_policy.tf.erb new file mode 100644 index 000000000000..7ea39e59976f --- /dev/null +++ b/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_egress_policy.tf.erb @@ -0,0 +1,36 @@ +resource "google_access_context_manager_service_perimeter" "storage-perimeter" { + parent = "accesspolicies/${google_access_context_manager_access_policy.access-policy.name}" + name = "accesspolicies/${google_access_context_manager_access_policy.access-policy.name}/serviceperimeters/storage-perimeter" + title = "Storage Perimeter" + status { + restricted_services = ["storage.googleapis.com"] + } + lifecycle { + ignore_changes = [status[0].resources] + } +} + +resource "google_access_context_manager_service_perimeter_egress_policy" "egress_policy" { + perimeter = "${google_access_context_manager_service_perimeter.storage-perimeter.name}" + egress_from { + identity_type = "ANY_IDENTITY" + } + egress_to { + resources = ["*"] + operations { + service_name = "bigquery.googleapis.com" + method_selectors { + method = "*" + } + } + } + lifecycle { + create_before_destroy = true + } +} + + +resource "google_access_context_manager_access_policy" "access-policy" { + parent = "organizations/123456789" + title = "Storage Policy" +} diff --git a/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_ingress_policy.tf.erb b/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_ingress_policy.tf.erb new file mode 100644 index 000000000000..b54c62bcc207 --- /dev/null +++ b/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_ingress_policy.tf.erb @@ -0,0 +1,39 @@ +resource "google_access_context_manager_service_perimeter" "storage-perimeter" { + parent = "accesspolicies/${google_access_context_manager_access_policy.access-policy.name}" + name = "accesspolicies/${google_access_context_manager_access_policy.access-policy.name}/serviceperimeters/storage-perimeter" + title = "Storage Perimeter" + status { + restricted_services = ["storage.googleapis.com"] + } + lifecycle { + ignore_changes = [status[0].resources] + } +} + +resource "google_access_context_manager_service_perimeter_ingress_policy" "ingress_policy" { + perimeter = "${google_access_context_manager_service_perimeter.storage-perimeter.name}" + ingress_from { + identity_type = "any_identity" + sources { + access_level = "*" + } + } + ingress_to { + resources = ["*"] + operations { + service_name = "bigquery.googleapis.com" + method_selectors { + method = "*" + } + } + } + lifecycle { + create_before_destroy = true + } +} + + +resource "google_access_context_manager_access_policy" "access-policy" { + parent = "organizations/123456789" + title = "Storage Policy" +} From 809bb4d0ff12d871736ef450986894512b57f394 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 15:54:00 -0700 Subject: [PATCH 36/59] Bump golang.org/x/net from 0.10.0 to 0.17.0 in /.ci/magician (#9243) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.10.0 to 0.17.0. - [Commits](https://github.com/golang/net/compare/v0.10.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .ci/magician/go.mod | 4 ++-- .ci/magician/go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.ci/magician/go.mod b/.ci/magician/go.mod index 165526d48c67..9c2971179e9f 100644 --- a/.ci/magician/go.mod +++ b/.ci/magician/go.mod @@ -32,9 +32,9 @@ require ( github.com/kr/pretty v0.3.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect go.opencensus.io v0.24.0 // indirect - golang.org/x/net v0.15.0 // indirect + golang.org/x/net v0.17.0 // indirect golang.org/x/oauth2 v0.6.0 // indirect - golang.org/x/sys v0.12.0 // indirect + golang.org/x/sys v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488 // indirect diff --git a/.ci/magician/go.sum b/.ci/magician/go.sum index 7fc76449804d..ce55618fb1c3 100644 --- a/.ci/magician/go.sum +++ b/.ci/magician/go.sum @@ -101,8 +101,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= @@ -113,8 +113,8 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= From 3218971e9a3a93c444b05f761bfaa89568044a48 Mon Sep 17 00:00:00 2001 From: Shuya Ma <87669292+shuyama1@users.noreply.github.com> Date: Thu, 14 Mar 2024 16:08:34 -0700 Subject: [PATCH 37/59] fix datastream private connection sweeper (#10201) * fix datastream private connection sweeper * update * run gofmt --- .../datastream/PrivateConnection.yaml | 2 + ...e_datastream_private_connection_sweeper.go | 126 ++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 mmv1/third_party/terraform/services/datastream/resource_datastream_private_connection_sweeper.go diff --git a/mmv1/products/datastream/PrivateConnection.yaml b/mmv1/products/datastream/PrivateConnection.yaml index f2bc7884d1db..4d38f0b9fe56 100644 --- a/mmv1/products/datastream/PrivateConnection.yaml +++ b/mmv1/products/datastream/PrivateConnection.yaml @@ -25,6 +25,8 @@ description: | immutable: true schema_version: 1 state_upgraders: true +# Skipping the sweeper since the resource needs force-deletion +skip_sweeper: true id_format: projects/{{project}}/locations/{{location}}/privateConnections/{{private_connection_id}} import_format: [ diff --git a/mmv1/third_party/terraform/services/datastream/resource_datastream_private_connection_sweeper.go b/mmv1/third_party/terraform/services/datastream/resource_datastream_private_connection_sweeper.go new file mode 100644 index 000000000000..81150729a74b --- /dev/null +++ b/mmv1/third_party/terraform/services/datastream/resource_datastream_private_connection_sweeper.go @@ -0,0 +1,126 @@ +package datastream + +import ( + "context" + "log" + "strings" + "testing" + + "github.com/hashicorp/terraform-provider-google/google/envvar" + "github.com/hashicorp/terraform-provider-google/google/sweeper" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func init() { + sweeper.AddTestSweepers("DatastreamPrivateConnection", testSweepDatastreamPrivateConnection) +} + +// At the time of writing, the CI only passes us-central1 as the region +func testSweepDatastreamPrivateConnection(region string) error { + resourceName := "DatastreamPrivateConnection" + log.Printf("[INFO][SWEEPER_LOG] Starting sweeper for %s", resourceName) + + config, err := sweeper.SharedConfigForRegion(region) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error getting shared config for region: %s", err) + return err + } + + err = config.LoadAndValidate(context.Background()) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error loading: %s", err) + return err + } + + t := &testing.T{} + billingId := envvar.GetTestBillingAccountFromEnv(t) + + // Setup variables to replace in list template + d := &tpgresource.ResourceDataMock{ + FieldsInSchema: map[string]interface{}{ + "project": config.Project, + "region": region, + "location": region, + "zone": "-", + "billing_account": billingId, + }, + } + + listTemplate := strings.Split("https://datastream.googleapis.com/v1/projects/{{project}}/locations/{{location}}/privateConnections", "?")[0] + listUrl, err := tpgresource.ReplaceVars(d, config, listTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err) + return nil + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: config.Project, + RawURL: listUrl, + UserAgent: config.UserAgent, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error in response from request %s: %s", listUrl, err) + return nil + } + + resourceList, ok := res["privateConnections"] + if !ok { + log.Printf("[INFO][SWEEPER_LOG] Nothing found in response.") + return nil + } + + rl := resourceList.([]interface{}) + + log.Printf("[INFO][SWEEPER_LOG] Found %d items in %s list response.", len(rl), resourceName) + // Keep count of items that aren't sweepable for logging. + nonPrefixCount := 0 + for _, ri := range rl { + obj := ri.(map[string]interface{}) + var name string + // Id detected in the delete URL, attempt to use id. + if obj["id"] != nil { + name = tpgresource.GetResourceNameFromSelfLink(obj["id"].(string)) + } else if obj["name"] != nil { + name = tpgresource.GetResourceNameFromSelfLink(obj["name"].(string)) + } else { + log.Printf("[INFO][SWEEPER_LOG] %s resource name and id were nil", resourceName) + return nil + } + // Skip resources that shouldn't be sweeped + if !sweeper.IsSweepableTestResource(name) { + nonPrefixCount++ + continue + } + + deleteTemplate := "https://datastream.googleapis.com/v1/projects/{{project}}/locations/{{location}}/privateConnections/{{private_connection_id}}" + deleteUrl, err := tpgresource.ReplaceVars(d, config, deleteTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing delete url: %s", err) + return nil + } + deleteUrl = deleteUrl + name + "?force=true" + + // Don't wait on operations as we may have a lot to delete + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "DELETE", + Project: config.Project, + RawURL: deleteUrl, + UserAgent: config.UserAgent, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error deleting for url %s : %s", deleteUrl, err) + } else { + log.Printf("[INFO][SWEEPER_LOG] Sent delete request for %s resource: %s", resourceName, name) + } + } + + if nonPrefixCount > 0 { + log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonPrefixCount) + } + + return nil +} From 0152b9d97c10ace81f1e4c12d5152398d6e94482 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Fri, 15 Mar 2024 14:46:45 +0000 Subject: [PATCH 38/59] Add SarahFrench to on vacation list (#10189) --- .ci/magician/github/membership.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.ci/magician/github/membership.go b/.ci/magician/github/membership.go index 908970d1b08f..112388d4a75a 100644 --- a/.ci/magician/github/membership.go +++ b/.ci/magician/github/membership.go @@ -46,7 +46,9 @@ var ( trustedContributors = []string{} // This is for reviewers who are "on vacation": will not receive new review assignments but will still receive re-requests for assigned PRs. - onVacationReviewers = []string{} + onVacationReviewers = []string{ + "SarahFrench", + } ) type UserType int64 From 28c58f90bcb46bac2fc699812130ccc775902f28 Mon Sep 17 00:00:00 2001 From: Ryan Oaks Date: Fri, 15 Mar 2024 10:59:43 -0400 Subject: [PATCH 39/59] Modify issue labeler to skip linked issues (#10199) * Modify issue labeler to skip linked issues * Update tests --- tools/issue-labeler/labeler/backfill.go | 8 ++++++++ tools/issue-labeler/labeler/backfill_test.go | 12 +++--------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/tools/issue-labeler/labeler/backfill.go b/tools/issue-labeler/labeler/backfill.go index 12db0cc04238..89eed2d58077 100644 --- a/tools/issue-labeler/labeler/backfill.go +++ b/tools/issue-labeler/labeler/backfill.go @@ -98,6 +98,14 @@ func ComputeIssueUpdates(issues []Issue, regexpLabels []RegexpLabel) []IssueUpda continue } + // Decision was made to no longer add new service labels to linked tickets, because it is + // more difficult to know which teams have received those tickets and which haven't. + // Forwarding a ticket to a different service team should involve removing the old service + // label and `linked` label. + if linked { + continue + } + var issueUpdate IssueUpdate for label := range desired { issueUpdate.OldLabels = append(issueUpdate.OldLabels, label) diff --git a/tools/issue-labeler/labeler/backfill_test.go b/tools/issue-labeler/labeler/backfill_test.go index c58e7f14b8e6..36ffa8defee3 100644 --- a/tools/issue-labeler/labeler/backfill_test.go +++ b/tools/issue-labeler/labeler/backfill_test.go @@ -136,7 +136,7 @@ func TestComputeIssueUpdates(t *testing.T) { }, }, }, - "add missing service labels even if already linked": { + "don't add missing service labels if already linked": { issues: []Issue{ { Number: 1, @@ -145,14 +145,8 @@ func TestComputeIssueUpdates(t *testing.T) { PullRequest: map[string]any{}, }, }, - regexpLabels: defaultRegexpLabels, - expectedIssueUpdates: []IssueUpdate{ - { - Number: 1, - Labels: []string{"forward/linked", "service/service1", "service/service2-subteam1"}, - OldLabels: []string{"service/service2-subteam1", "forward/linked"}, - }, - }, + regexpLabels: defaultRegexpLabels, + expectedIssueUpdates: []IssueUpdate{}, }, } From 4c432c6d4d96c2537b7818afdbef4387d8894733 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Fri, 15 Mar 2024 15:57:19 +0000 Subject: [PATCH 40/59] Remove misleading examples from docs for `google_dataform_repository`, add new example (#10187) * Remove misleading examples from docs for `google_dataform_repository`, add new example * Remove unusued var from new example * Fix typo * Fix other instances of typo --- mmv1/products/dataform/Repository.yaml | 27 ++++++++++-- .../examples/dataform_repository.tf.erb | 7 +-- ...rm_repository_with_cloudsource_repo.tf.erb | 43 +++++++++++++++++++ ...tory_with_cloudsource_repo_and_ssh.tf.erb} | 0 .../resource_dataform_repository_test.go.erb | 8 ++-- 5 files changed, 72 insertions(+), 13 deletions(-) create mode 100644 mmv1/templates/terraform/examples/dataform_repository_with_cloudsource_repo.tf.erb rename mmv1/templates/terraform/examples/{dataform_repository_ssh.tf.erb => dataform_repository_with_cloudsource_repo_and_ssh.tf.erb} (100%) diff --git a/mmv1/products/dataform/Repository.yaml b/mmv1/products/dataform/Repository.yaml index 1d99d98c8fb7..41c8bfd4e289 100644 --- a/mmv1/products/dataform/Repository.yaml +++ b/mmv1/products/dataform/Repository.yaml @@ -34,7 +34,24 @@ import_format: examples: - !ruby/object:Provider::Terraform::Examples name: 'dataform_repository' - primary_resource_id: dataform_respository + # This example is used in the docs to address this issue + # See : https://github.com/hashicorp/terraform-provider-google/issues/17335 + skip_test: true + primary_resource_id: dataform_repository + primary_resource_name: + 'fmt.Sprintf("tf_test_dataform_repository%s", context["random_suffix"])' + min_version: beta + vars: + dataform_repository_name: 'dataform_repository' + data: secret-data + secret_name: my-secret + - !ruby/object:Provider::Terraform::Examples + name: 'dataform_repository_with_cloudsource_repo' + # Although the Terraform config can be applied without error, the connection between Dataform and the SourceRepo aren't yet functional + # See : https://github.com/hashicorp/terraform-provider-google/issues/17335 + # See : https://issuetracker.google.com/issues/287850319 + skip_docs: true + primary_resource_id: dataform_repository primary_resource_name: 'fmt.Sprintf("tf_test_dataform_repository%s", context["random_suffix"])' min_version: beta @@ -44,8 +61,12 @@ examples: data: secret-data secret_name: my-secret - !ruby/object:Provider::Terraform::Examples - name: 'dataform_repository_ssh' - primary_resource_id: dataform_respository + name: 'dataform_repository_with_cloudsource_repo_and_ssh' + # Although the Terraform config can be applied without error, the connection between Dataform and the SourceRepo aren't yet functional + # See : https://github.com/hashicorp/terraform-provider-google/issues/17335 + # See : https://issuetracker.google.com/issues/287850319 + skip_docs: true + primary_resource_id: dataform_repository min_version: beta vars: git_repository_name: 'my/repository' diff --git a/mmv1/templates/terraform/examples/dataform_repository.tf.erb b/mmv1/templates/terraform/examples/dataform_repository.tf.erb index 1e76e9133b1e..ff237f57c15c 100644 --- a/mmv1/templates/terraform/examples/dataform_repository.tf.erb +++ b/mmv1/templates/terraform/examples/dataform_repository.tf.erb @@ -1,8 +1,3 @@ -resource "google_sourcerepo_repository" "git_repository" { - provider = google-beta - name = "<%= ctx[:vars]['git_repository_name'] %>" -} - resource "google_secret_manager_secret" "secret" { provider = google-beta secret_id = "<%= ctx[:vars]['secret_name'] %>" @@ -30,7 +25,7 @@ resource "google_dataform_repository" "<%= ctx[:primary_resource_id] %>" { } git_remote_settings { - url = google_sourcerepo_repository.git_repository.url + url = "https://github.com/OWNER/REPOSITORY.git" default_branch = "main" authentication_token_secret_version = google_secret_manager_secret_version.secret_version.id } diff --git a/mmv1/templates/terraform/examples/dataform_repository_with_cloudsource_repo.tf.erb b/mmv1/templates/terraform/examples/dataform_repository_with_cloudsource_repo.tf.erb new file mode 100644 index 000000000000..1e76e9133b1e --- /dev/null +++ b/mmv1/templates/terraform/examples/dataform_repository_with_cloudsource_repo.tf.erb @@ -0,0 +1,43 @@ +resource "google_sourcerepo_repository" "git_repository" { + provider = google-beta + name = "<%= ctx[:vars]['git_repository_name'] %>" +} + +resource "google_secret_manager_secret" "secret" { + provider = google-beta + secret_id = "<%= ctx[:vars]['secret_name'] %>" + + replication { + auto {} + } +} + +resource "google_secret_manager_secret_version" "secret_version" { + provider = google-beta + secret = google_secret_manager_secret.secret.id + + secret_data = "<%= ctx[:vars]['data'] %>" +} + +resource "google_dataform_repository" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + name = "<%= ctx[:vars]['dataform_repository_name'] %>" + display_name = "<%= ctx[:vars]['dataform_repository_name'] %>" + npmrc_environment_variables_secret_version = google_secret_manager_secret_version.secret_version.id + + labels = { + label_foo1 = "label-bar1" + } + + git_remote_settings { + url = google_sourcerepo_repository.git_repository.url + default_branch = "main" + authentication_token_secret_version = google_secret_manager_secret_version.secret_version.id + } + + workspace_compilation_overrides { + default_database = "database" + schema_suffix = "_suffix" + table_prefix = "prefix_" + } +} diff --git a/mmv1/templates/terraform/examples/dataform_repository_ssh.tf.erb b/mmv1/templates/terraform/examples/dataform_repository_with_cloudsource_repo_and_ssh.tf.erb similarity index 100% rename from mmv1/templates/terraform/examples/dataform_repository_ssh.tf.erb rename to mmv1/templates/terraform/examples/dataform_repository_with_cloudsource_repo_and_ssh.tf.erb diff --git a/mmv1/third_party/terraform/services/dataform/resource_dataform_repository_test.go.erb b/mmv1/third_party/terraform/services/dataform/resource_dataform_repository_test.go.erb index fd24afe43b3f..396a5703a77a 100644 --- a/mmv1/third_party/terraform/services/dataform/resource_dataform_repository_test.go.erb +++ b/mmv1/third_party/terraform/services/dataform/resource_dataform_repository_test.go.erb @@ -26,7 +26,7 @@ func TestAccDataformRepository_updated(t *testing.T) { Config: testAccDataformRepository_basic(context), }, { - ResourceName: "google_dataform_repository.dataform_respository", + ResourceName: "google_dataform_repository.dataform_repository", ImportState: true, ImportStateVerify: true, ImportStateVerifyIgnore: []string{"region"}, @@ -35,7 +35,7 @@ func TestAccDataformRepository_updated(t *testing.T) { Config: testAccDataformRepository_updated(context), }, { - ResourceName: "google_dataform_repository.dataform_respository", + ResourceName: "google_dataform_repository.dataform_repository", ImportState: true, ImportStateVerify: true, ImportStateVerifyIgnore: []string{"region"}, @@ -67,7 +67,7 @@ resource "google_secret_manager_secret_version" "secret_version" { secret_data = "tf-test-secret-data%{random_suffix}" } -resource "google_dataform_repository" "dataform_respository" { +resource "google_dataform_repository" "dataform_repository" { provider = google-beta name = "tf_test_dataform_repository%{random_suffix}" @@ -109,7 +109,7 @@ resource "google_secret_manager_secret_version" "secret_version" { secret_data = "tf-test-secret-data%{random_suffix}" } -resource "google_dataform_repository" "dataform_respository" { +resource "google_dataform_repository" "dataform_repository" { provider = google-beta name = "tf_test_dataform_repository%{random_suffix}" From fdafe53d72b626ee367c769efb5bca6d70429cac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Mar 2024 10:20:20 -0700 Subject: [PATCH 41/59] Bump google.golang.org/grpc from 1.53.0 to 1.56.3 in /.ci/magician (#9366) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.53.0 to 1.56.3. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.53.0...v1.56.3) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .ci/magician/go.mod | 14 +++++++------- .ci/magician/go.sum | 28 ++++++++++++++-------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.ci/magician/go.mod b/.ci/magician/go.mod index 9c2971179e9f..3ac92fda1f95 100644 --- a/.ci/magician/go.mod +++ b/.ci/magician/go.mod @@ -10,7 +10,7 @@ require ( github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 // indirect golang.org/x/exp v0.0.0-20230810033253-352e893a4cad - google.golang.org/api v0.112.0 + google.golang.org/api v0.114.0 ) require ( @@ -20,25 +20,25 @@ require ( ) require ( - cloud.google.com/go/compute v1.18.0 // indirect + cloud.google.com/go/compute v1.19.1 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/golang/glog v1.1.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/google/uuid v1.3.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect - github.com/googleapis/gax-go/v2 v2.7.0 // indirect + github.com/googleapis/gax-go/v2 v2.7.1 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect go.opencensus.io v0.24.0 // indirect golang.org/x/net v0.17.0 // indirect - golang.org/x/oauth2 v0.6.0 // indirect + golang.org/x/oauth2 v0.7.0 // indirect golang.org/x/sys v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488 // indirect - google.golang.org/grpc v1.53.0 // indirect + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect + google.golang.org/grpc v1.56.3 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/.ci/magician/go.sum b/.ci/magician/go.sum index ce55618fb1c3..d63fb6058429 100644 --- a/.ci/magician/go.sum +++ b/.ci/magician/go.sum @@ -1,7 +1,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= -cloud.google.com/go/compute v1.18.0 h1:FEigFqoDbys2cvFkZ9Fjq4gnHBP55anJ0yQyau2f9oY= -cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= +cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY= +cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= @@ -37,8 +37,8 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -53,8 +53,8 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= +github.com/googleapis/gax-go/v2 v2.7.1 h1:gF4c0zjUP2H/s/hEGyLA3I0fA2ZWjzYiONAD6cvPr8A= +github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -104,8 +104,8 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= -golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= +golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g= +golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -126,8 +126,8 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.112.0 h1:iDmzvZ4C086R3+en4nSyIf07HlQKMOX1Xx2dmia/+KQ= -google.golang.org/api v0.112.0/go.mod h1:737UfWHNsOq4F3REUTmb+GN9pugkgNLCayLTfoIKpPc= +google.golang.org/api v0.114.0 h1:1xQPji6cO2E2vLiI+C/XiFAnsn1WV3mjaEwGLhi3grE= +google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= @@ -135,15 +135,15 @@ google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488 h1:QQF+HdiI4iocoxUjjpLgvTYDHKm99C/VtTBFnfiCJos= -google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= -google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= +google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= +google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From 77816ee766a56cf2b09c332b9b9fbc3bd6d50cea Mon Sep 17 00:00:00 2001 From: roop2 <161707562+roop2@users.noreply.github.com> Date: Fri, 15 Mar 2024 23:24:19 +0530 Subject: [PATCH 42/59] Moving the netapp kmsconfig resource update test to a different region to avoid conflict with create test (#10185) --- .../netapp/resource_netapp_kmsconfig_test.go | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/mmv1/third_party/terraform/services/netapp/resource_netapp_kmsconfig_test.go b/mmv1/third_party/terraform/services/netapp/resource_netapp_kmsconfig_test.go index 0f309e3f5a8d..5bd73fde3264 100644 --- a/mmv1/third_party/terraform/services/netapp/resource_netapp_kmsconfig_test.go +++ b/mmv1/third_party/terraform/services/netapp/resource_netapp_kmsconfig_test.go @@ -1,20 +1,6 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -// ---------------------------------------------------------------------------- -// -// *** AUTO GENERATED CODE *** Type: MMv1 *** -// -// ---------------------------------------------------------------------------- -// -// 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 netapp_test import ( @@ -63,7 +49,7 @@ func testAccNetappkmsconfig_kmsConfigCreateExample_Full(context map[string]inter return acctest.Nprintf(` resource "google_kms_key_ring" "keyring" { name = "tf-test-key-ring%{random_suffix}" - location = "us-central1" + location = "us-east4" } resource "google_kms_crypto_key" "crypto_key" { @@ -75,7 +61,7 @@ func testAccNetappkmsconfig_kmsConfigCreateExample_Full(context map[string]inter name = "tf-test-kms-test%{random_suffix}" description="this is a test description" crypto_key_name=google_kms_crypto_key.crypto_key.id - location="us-central1" + location="us-east4" } `, context) } @@ -84,7 +70,7 @@ func testAccNetappkmsconfig_kmsConfigCreateExample_Update(context map[string]int return acctest.Nprintf(` resource "google_kms_key_ring" "keyring" { name = "tf-test-key-ring%{random_suffix}" - location = "us-central1" + location = "us-east4" } resource "google_kms_crypto_key" "crypto_key" { @@ -96,7 +82,7 @@ func testAccNetappkmsconfig_kmsConfigCreateExample_Update(context map[string]int name = "tf-test-kms-test%{random_suffix}" description="kmsconfig update" crypto_key_name=google_kms_crypto_key.crypto_key.id - location="us-central1" + location="us-east4" labels = { "foo": "bar", } From 6dfce95e0728bdfc9ca43d3f616c1759d54b3341 Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Fri, 15 Mar 2024 11:11:28 -0700 Subject: [PATCH 43/59] Only run mmv1 rake tests and yaml linting if relevant files have changed (#10207) * Only run mmv1 rake tests and yaml linting if relevant files have changed * fix path for rb files Co-authored-by: Sarah French <15078782+SarahFrench@users.noreply.github.com> --------- Co-authored-by: Sarah French <15078782+SarahFrench@users.noreply.github.com> --- ...modules.yml => mmv1-lint-product-yaml.yml} | 33 ++-------------- .github/workflows/mmv1-rake-tests.yml | 39 +++++++++++++++++++ 2 files changed, 42 insertions(+), 30 deletions(-) rename .github/workflows/{magic-modules.yml => mmv1-lint-product-yaml.yml} (56%) create mode 100644 .github/workflows/mmv1-rake-tests.yml diff --git a/.github/workflows/magic-modules.yml b/.github/workflows/mmv1-lint-product-yaml.yml similarity index 56% rename from .github/workflows/magic-modules.yml rename to .github/workflows/mmv1-lint-product-yaml.yml index d92e666e2b60..7a732c6c7402 100644 --- a/.github/workflows/magic-modules.yml +++ b/.github/workflows/mmv1-lint-product-yaml.yml @@ -1,9 +1,11 @@ -name: magic-modules +name: mmv1-lint-product-yaml permissions: read-all on: pull_request: + paths: + - 'mmv1/products/**' jobs: lint-yaml: @@ -32,32 +34,3 @@ jobs: - name: Lint YAML files if: ${{ !failure() && steps.pull_request.outputs.yamlfiles != '' }} run: yamllint -c repo/.yamllint ${{steps.pull_request.outputs.yamlfiles}} - rake-tests: - runs-on: ubuntu-22.04 - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - with: - path: repo - fetch-depth: 2 - - name: Merge base branch - id: pull_request - run: | - cd repo - git config user.name "modular-magician" - git config user.email "magic-modules@google.com" - git fetch origin ${{ github.base_ref }} # Fetch the base branch - git merge --no-ff origin/${{ github.base_ref }} # Merge with the base branch - - name: Set up Ruby - uses: ruby/setup-ruby@036ef458ddccddb148a2b9fb67e95a22fdbf728b # v1.160.0 - with: - ruby-version: '3.1' - - name: Install dependencies - run: | - cd repo/mmv1 - bundle install - - name: Run rake tests - run: | - cd repo/mmv1 - bundle exec rake test - diff --git a/.github/workflows/mmv1-rake-tests.yml b/.github/workflows/mmv1-rake-tests.yml new file mode 100644 index 000000000000..e6d1ecb5ea1f --- /dev/null +++ b/.github/workflows/mmv1-rake-tests.yml @@ -0,0 +1,39 @@ +name: mmv1-rake-tests + +permissions: read-all + +on: + pull_request: + paths: + - 'mmv1/**/*.rb' + +jobs: + rake-tests: + runs-on: ubuntu-22.04 + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + path: repo + fetch-depth: 2 + - name: Merge base branch + id: pull_request + run: | + cd repo + git config user.name "modular-magician" + git config user.email "magic-modules@google.com" + git fetch origin ${{ github.base_ref }} # Fetch the base branch + git merge --no-ff origin/${{ github.base_ref }} # Merge with the base branch + - name: Set up Ruby + uses: ruby/setup-ruby@036ef458ddccddb148a2b9fb67e95a22fdbf728b # v1.160.0 + with: + ruby-version: '3.1' + - name: Install dependencies + run: | + cd repo/mmv1 + bundle install + - name: Run rake tests + run: | + cd repo/mmv1 + bundle exec rake test + From 64b712308bdcc40f68f7d17d05a2c476e902298b Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Fri, 15 Mar 2024 13:06:49 -0700 Subject: [PATCH 44/59] Clean up functions and add slice utility functions (#10210) * Clean up function all_resourcerefs * Add slice utility functions * Change sensitive_props as resource method --- mmv1/api/resource.rb | 45 +----- mmv1/google/slice_utils.go | 41 ++++++ mmv1/google/slice_utils_test.go | 138 ++++++++++++++++++ .../terraform/resource.html.markdown.erb | 5 +- 4 files changed, 185 insertions(+), 44 deletions(-) create mode 100644 mmv1/google/slice_utils.go create mode 100644 mmv1/google/slice_utils_test.go diff --git a/mmv1/api/resource.rb b/mmv1/api/resource.rb index 7ff67c56035a..a3036a3c6d79 100644 --- a/mmv1/api/resource.rb +++ b/mmv1/api/resource.rb @@ -389,11 +389,6 @@ def all_nested_properties(props) nested end - # Returns all resourcerefs at any depth - def all_resourcerefs - resourcerefs_for_properties(all_user_properties, self) - end - # All settable properties in the resource. # Fingerprints aren't *really" settable properties, but they behave like one. # At Create, they have no value but they can just be read in anyways, and after a Read @@ -425,6 +420,10 @@ def root_properties end end + def sensitive_props + all_nested_properties(root_properties).select(&:sensitive) + end + # Return the product-level async object, or the resource-specific one # if one exists. def async @@ -770,41 +769,5 @@ def validate_identity if all_user_properties.select { |p| p.name == i }.empty? end end - - # Given an array of properties, return all ResourceRefs contained within - # Requires: - # props- a list of props - # original_object - the original object containing props. This is to - # avoid self-referencing objects. - def resourcerefs_for_properties(props, original_obj) - rrefs = [] - props.each do |p| - # We need to recurse on ResourceRefs to get all levels - # We do not want to recurse on resourcerefs of type self to avoid - # infinite loop. - if p.is_a? Api::Type::ResourceRef - # We want to avoid a circular reference - # This reference may be the next reference or have some number of refs - # in between it. - next if p.resource_ref == original_obj - next if p.resource_ref == p.__resource - - rrefs << p - rrefs.concat(resourcerefs_for_properties(p.resource_ref - .required_properties, - original_obj)) - elsif !p.nested_properties.nil? - rrefs.concat(resourcerefs_for_properties(p.nested_properties, original_obj)) - elsif p.is_a? Api::Type::Array - if p.item_type.is_a? Api::Type::ResourceRef - rrefs << p.item_type - rrefs.concat(resourcerefs_for_properties(p.item_type.resource_ref - .required_properties, - original_obj)) - end - end - end - rrefs.uniq - end end end diff --git a/mmv1/google/slice_utils.go b/mmv1/google/slice_utils.go new file mode 100644 index 000000000000..75ad22de3b7d --- /dev/null +++ b/mmv1/google/slice_utils.go @@ -0,0 +1,41 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package google + +// Returns a new slice containing all of the elements +// for which the test function returns true in the original slice +func Select[T any](S []T, test func(T) bool) (ret []T) { + for _, s := range S { + if test(s) { + ret = append(ret, s) + } + } + return +} + +// Returns a new slice containing all of the elements +// for which the test function returns false in the original slice +func Reject[T any](S []T, test func(T) bool) (ret []T) { + for _, s := range S { + if !test(s) { + ret = append(ret, s) + } + } + return +} + +// Concat two slices +func Concat[T any](S1 []T, S2 []T) (ret []T) { + return append(S1, S2...) +} diff --git a/mmv1/google/slice_utils_test.go b/mmv1/google/slice_utils_test.go new file mode 100644 index 000000000000..98532795f8b0 --- /dev/null +++ b/mmv1/google/slice_utils_test.go @@ -0,0 +1,138 @@ +package google + +import ( + "reflect" + "testing" +) + +func TestSliceSelect(t *testing.T) { + t.Parallel() + + cases := []struct { + description string + S []int + testFun func(int) bool + expected int + }{ + { + description: "interger slice selects even numbers", + S: []int{0, 1, 2}, + testFun: func(n int) bool { + return n%2 == 0 + }, + expected: 2, + }, + { + description: "empty slice", + S: make([]int, 0), + testFun: func(n int) bool { + return n%2 == 0 + }, + expected: 0, + }, + { + description: "nil slice", + S: nil, + testFun: func(n int) bool { + return n%2 == 0 + }, + expected: 0, + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + if got, want := len(Select(tc.S, tc.testFun)), tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} + +func TestSliceReject(t *testing.T) { + t.Parallel() + + cases := []struct { + description string + S []int + testFun func(int) bool + expected int + }{ + { + description: "interger slice rejects even numbers", + S: []int{0, 1, 2}, + testFun: func(n int) bool { + return n%2 == 0 + }, + expected: 1, + }, + { + description: "empty slice", + S: make([]int, 0), + testFun: func(n int) bool { + return n%2 == 0 + }, + expected: 0, + }, + { + description: "nil slice", + S: nil, + testFun: func(n int) bool { + return n%2 == 0 + }, + expected: 0, + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + if got, want := len(Reject(tc.S, tc.testFun)), tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} + +func TestSliceConcat(t *testing.T) { + t.Parallel() + + cases := []struct { + description string + S1 []int + S2 []int + expected int + }{ + { + description: "interger slice rejects even numbers", + S1: []int{0, 1, 2}, + S2: []int{3, 4}, + expected: 5, + }, + { + description: "empty slice", + S1: nil, + S2: make([]int, 0), + expected: 0, + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + if got, want := len(Concat(tc.S1, tc.S2)), tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} diff --git a/mmv1/templates/terraform/resource.html.markdown.erb b/mmv1/templates/terraform/resource.html.markdown.erb index bc03202abe3d..f411914debeb 100644 --- a/mmv1/templates/terraform/resource.html.markdown.erb +++ b/mmv1/templates/terraform/resource.html.markdown.erb @@ -40,7 +40,6 @@ tf_subcategory = (object.__product.display_name) terraform_name = object.legacy_name || "google_#{tf_product}_#{object.name.underscore}" properties = object.all_user_properties - sensitive_props = object.all_nested_properties(object.root_properties).select(&:sensitive) # In order of preference, use TF override, # general defined timeouts, or default Timeouts timeouts = object.timeouts @@ -87,9 +86,9 @@ To get more information about <%= object.name -%>, see: ~> **Note:** <%= object.docs.note -%> <%- end -%> -<%- if !sensitive_props.empty? -%> +<%- if !object.sensitive_props.empty? -%> <%- - sense_props = sensitive_props.map! {|prop| "`"+prop.lineage+"`"}.join(', ') + sense_props = object.sensitive_props.map! {|prop| "`"+prop.lineage+"`"}.join(', ') -%> ~> **Warning:** All arguments including the following potentially sensitive From 1b2c21428b470c523ac42c47ddecb9bfd84d3331 Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Fri, 15 Mar 2024 13:18:29 -0700 Subject: [PATCH 45/59] Removed github-differ bash scripts (#10208) --- .../github-differ/compare_breaking_changes.sh | 59 ----- .../go-plus/github-differ/generate_comment.sh | 221 ------------------ .../go-plus/github-differ/test_tools.sh | 39 ---- .ci/scripts/go-plus/github-differ/utils.sh | 15 -- 4 files changed, 334 deletions(-) delete mode 100755 .ci/scripts/go-plus/github-differ/compare_breaking_changes.sh delete mode 100755 .ci/scripts/go-plus/github-differ/generate_comment.sh delete mode 100755 .ci/scripts/go-plus/github-differ/test_tools.sh delete mode 100755 .ci/scripts/go-plus/github-differ/utils.sh diff --git a/.ci/scripts/go-plus/github-differ/compare_breaking_changes.sh b/.ci/scripts/go-plus/github-differ/compare_breaking_changes.sh deleted file mode 100755 index 921554908999..000000000000 --- a/.ci/scripts/go-plus/github-differ/compare_breaking_changes.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/bash -# input: two environment variables -# TPG_BREAKING - results of runing breaking change detector -# against tpg -# TPGB_BREAKING - results of runing breaking change detector -# against tpgb -# output: echo to console -# message section cotaining: a header, -# tpg's unique messages, and all of tpgb's messages - -tpgUnique="" -newline=$'\n' - -# This while loop itterates over each individual -# line of TPG_BREAKING. The input to the while loop -# is through the <<< at the conclusion of the loop. -while read -r tpgi; do - simpleTPG=$(sed 's/-.*//' <<< "$tpgi") - found="false" - while read -r tpgbi; do - simpleTPGB=$(sed 's/-.*//' <<< "$tpgbi") - if [ "$simpleTPG" == "$simpleTPGB" ]; then - found="true" - fi - done <<< "$TPGB_BREAKING" - if [ "$found" != "true" ]; then - if [ "$tpgUnique" == "" ]; then - tpgUnique="${tpgi}" - else - tpgUnique="${tpgUnique}${newline}${tpgi}" - fi - fi -done <<< "$TPG_BREAKING" - - -breakingchanges="" -if [ "$tpgUnique" != "" ]; then - tpgUnique=$(sed 's/^/\* /' <<< "$tpgUnique") - breakingchanges="${breakingchanges}${tpgUnique}${newline}" -fi - -if [ "$TPGB_BREAKING" != "" ]; then - tpgbBreaking=$(sed 's/^/\* /' <<< "$TPGB_BREAKING") - breakingchanges="${breakingchanges}${tpgbBreaking}${newline}" -fi - -if [ "$breakingchanges" != "" ]; then -message="## Breaking Change(s) Detected -The following breaking change(s) were detected within your pull request. - -${breakingchanges} - -If you believe this detection to be incorrect please raise the concern with your reviewer. If you intend to make this change you will need to wait for a [major release](https://www.terraform.io/plugin/sdkv2/best-practices/versioning#example-major-number-increments) window. An \`override-breaking-change\` label can be added to allow merging. -" -fi - -echo "$message" - - diff --git a/.ci/scripts/go-plus/github-differ/generate_comment.sh b/.ci/scripts/go-plus/github-differ/generate_comment.sh deleted file mode 100755 index 191dde497fb4..000000000000 --- a/.ci/scripts/go-plus/github-differ/generate_comment.sh +++ /dev/null @@ -1,221 +0,0 @@ -#! /bin/bash - -set -e - -if [ $# -lt 1 ]; then - echo "Usage: $0 pr-number" - exit 1 -fi -if [ -z "$GITHUB_TOKEN" ]; then - echo "Did not provide GITHUB_TOKEN environment variable." - exit 1 -fi - -# Get the directory of the current script -script_dir=$(dirname "$0") - -# make utility functions avalible -source "$script_dir/utils.sh" - -PR_NUMBER=$1 -NEW_BRANCH=auto-pr-$PR_NUMBER -OLD_BRANCH=auto-pr-$PR_NUMBER-old -MM_LOCAL_PATH=$PWD -TPG_SCRATCH_PATH=https://modular-magician:$GITHUB_TOKEN@github.com/modular-magician/terraform-provider-google -TPG_LOCAL_PATH=$PWD/../tpg -TPGB_SCRATCH_PATH=https://modular-magician:$GITHUB_TOKEN@github.com/modular-magician/terraform-provider-google-beta -TPGB_LOCAL_PATH=$PWD/../tpgb -TFOICS_SCRATCH_PATH=https://modular-magician:$GITHUB_TOKEN@github.com/modular-magician/docs-examples -TFOICS_LOCAL_PATH=$PWD/../tfoics -BREAKING_CHANGE_BUILD_FAILURE=0 - -# For backwards compatibility until at least Nov 15 2021 -TFC_SCRATCH_PATH=https://modular-magician:$GITHUB_TOKEN@github.com/modular-magician/terraform-google-conversion -TFC_LOCAL_PATH=$PWD/../tfc - -DIFFS="" -NEWLINE=$'\n' - -# TPG/TPGB difference -mkdir -p $TPG_LOCAL_PATH -git clone -b $NEW_BRANCH $TPG_SCRATCH_PATH $TPG_LOCAL_PATH -pushd $TPG_LOCAL_PATH -git fetch origin $OLD_BRANCH -if ! git diff --exit-code origin/$OLD_BRANCH origin/$NEW_BRANCH; then - SUMMARY=`git diff origin/$OLD_BRANCH origin/$NEW_BRANCH --shortstat` - DIFFS="${DIFFS}${NEWLINE}Terraform GA: [Diff](https://github.com/modular-magician/terraform-provider-google/compare/$OLD_BRANCH..$NEW_BRANCH) ($SUMMARY)" -fi -popd - -mkdir -p $TPGB_LOCAL_PATH -git clone -b $NEW_BRANCH $TPGB_SCRATCH_PATH $TPGB_LOCAL_PATH -pushd $TPGB_LOCAL_PATH -git fetch origin $OLD_BRANCH -if ! git diff --exit-code origin/$OLD_BRANCH origin/$NEW_BRANCH; then - SUMMARY=`git diff origin/$OLD_BRANCH origin/$NEW_BRANCH --shortstat` - DIFFS="${DIFFS}${NEWLINE}Terraform Beta: [Diff](https://github.com/modular-magician/terraform-provider-google-beta/compare/$OLD_BRANCH..$NEW_BRANCH) ($SUMMARY)" -fi -popd - -## Diff processor - TPG -set +e -pushd $MM_LOCAL_PATH/tools/diff-processor -cp -r $TPG_LOCAL_PATH old/ -cp -r $TPG_LOCAL_PATH new/ -make build OLD_REF=$OLD_BRANCH NEW_REF=$NEW_BRANCH - -### Breaking changes -TPG_BREAKING="$(bin/diff-processor breaking-changes)" -retVal=$? -if [ $retVal -ne 0 ]; then - TPG_BREAKING="" - BREAKING_CHANGE_BUILD_FAILURE=1 -fi - -### Add labels -GITHUB_TOKEN=$GITHUB_TOKEN $MM_LOCAL_PATH/tools/diff-processor/bin/diff-processor add-labels $PR_NUMBER -rm -rf ./old/ ./new/ ./bin/ -popd -set -e - -## Diff processor - TPGB -set +e -pushd $MM_LOCAL_PATH/tools/diff-processor -cp -r $TPGB_LOCAL_PATH old/ -cp -r $TPGB_LOCAL_PATH new/ -make build OLD_REF=$OLD_BRANCH NEW_REF=$NEW_BRANCH - -### Breaking changes -TPGB_BREAKING="$(bin/diff-processor breaking-changes)" -retVal=$? -if [ $retVal -ne 0 ]; then - TPGB_BREAKING="" - BREAKING_CHANGE_BUILD_FAILURE=1 -fi - -### Add labels -GITHUB_TOKEN=$GITHUB_TOKEN $MM_LOCAL_PATH/tools/diff-processor/bin/diff-processor add-labels $PR_NUMBER -rm -rf ./old/ ./new/ ./bin/ -popd -set -e - -## Report breaking change failures -set +e -if [ $BREAKING_CHANGE_BUILD_FAILURE -eq 0 ]; then - echo "Breaking changes succeeded" - # Export variables here so that they can be used in compare_breaking_changes - # exporting earlier would cause the retvals to not be calculated properly. - export TPG_BREAKING=$TPG_BREAKING - export TPGB_BREAKING=$TPGB_BREAKING - BREAKINGCHANGES="$($script_dir/compare_breaking_changes.sh)" -else - echo "Breaking changes failed" - BREAKINGCHANGES="## Breaking Change Detection Failed${NEWLINE}The breaking change detector crashed during execution. This is usually due to the downstream provider(s) failing to compile. Please investigate or follow up with your reviewer." -fi -set -e - -## Missing test setup and execution -TPGB_LOCAL_PATH_OLD="${TPGB_LOCAL_PATH}old" -mkdir -p $TPGB_LOCAL_PATH_OLD -cp -r $TPGB_LOCAL_PATH/. $TPGB_LOCAL_PATH_OLD - -pushd $TPGB_LOCAL_PATH -git checkout origin/$NEW_BRANCH -update_package_name "github.com/hashicorp/terraform-provider-google-beta" "google/provider/new" -popd - -pushd $TPGB_LOCAL_PATH_OLD -git checkout origin/$OLD_BRANCH -update_package_name "github.com/hashicorp/terraform-provider-google-beta" "google/provider/old" -popd - -set +e -pushd $MM_LOCAL_PATH/tools/missing-test-detector -go mod edit -replace google/provider/new=$(realpath $TPGB_LOCAL_PATH) -go mod edit -replace google/provider/old=$(realpath $TPGB_LOCAL_PATH_OLD) -go mod tidy -MISSINGTESTS="$(go run . -services-dir=$TPGB_LOCAL_PATH/google-beta/services)" -retVal=$? -if [ $retVal -ne 0 ]; then - MISSINGTESTS="" -fi -set -e -popd - -# TF Conversion - for compatibility until at least Nov 15 2021 -mkdir -p $TFC_LOCAL_PATH -# allow this to fail for compatibility during tfv/tgc transition phase -if git clone -b $NEW_BRANCH $TFC_SCRATCH_PATH $TFC_LOCAL_PATH; then - pushd $TFC_LOCAL_PATH - git fetch origin $OLD_BRANCH - if ! git diff --exit-code origin/$OLD_BRANCH origin/$NEW_BRANCH; then - SUMMARY=`git diff origin/$OLD_BRANCH origin/$NEW_BRANCH --shortstat` - DIFFS="${DIFFS}${NEWLINE}TF Conversion: [Diff](https://github.com/modular-magician/terraform-google-conversion/compare/$OLD_BRANCH..$NEW_BRANCH) ($SUMMARY)" - fi - popd -fi - -# TF OICS -mkdir -p $TFOICS_LOCAL_PATH -git clone -b $NEW_BRANCH $TFOICS_SCRATCH_PATH $TFOICS_LOCAL_PATH -pushd $TFOICS_LOCAL_PATH -git fetch origin $OLD_BRANCH -if ! git diff --exit-code --quiet origin/$OLD_BRANCH origin/$NEW_BRANCH; then - SUMMARY="$(git diff origin/$OLD_BRANCH origin/$NEW_BRANCH --shortstat)" - DIFFS="${DIFFS}${NEWLINE}TF OiCS: [Diff](https://github.com/modular-magician/docs-examples/compare/$OLD_BRANCH..$NEW_BRANCH) ($SUMMARY)" -fi -popd - -MESSAGE="Hi there, I'm the Modular magician. I've detected the following information about your changes:${NEWLINE}${NEWLINE}" - -BREAKINGSTATE="success" -if [ -n "$BREAKINGCHANGES" ]; then - MESSAGE="${MESSAGE}${BREAKINGCHANGES}${NEWLINE}${NEWLINE}" - - BREAKINGCHANGE_OVERRIDE=$(curl \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer $GITHUB_TOKEN" \ - "https://api.github.com/repos/GoogleCloudPlatform/magic-modules/pulls/$PR_NUMBER"\ - | jq ".labels|any(.id==4598495472)") - - if [ "${BREAKINGCHANGE_OVERRIDE}" == "true" ]; then - BREAKINGSTATE="success" - else - BREAKINGSTATE="failure" - fi -fi - - -if [ -z "$DIFFS" ]; then - MESSAGE="${MESSAGE}## Diff report ${NEWLINE}Your PR hasn't generated any diffs, but I'll let you know if a future commit does." -else - MESSAGE="${MESSAGE}## Diff report ${NEWLINE}Your PR generated some diffs in downstreams - here they are.${NEWLINE}${DIFFS}" - if [ -n "$MISSINGTESTS" ]; then - MESSAGE="${MESSAGE}${NEWLINE}${MISSINGTESTS}${NEWLINE}" - fi -fi - - - -#;region=global/${BUILD_ID};step=19?project=${PROJECT_ID}" -BREAKINGSTATE_BODY=$( jq -n \ - --arg context "terraform-provider-breaking-change-test" \ - --arg target_url "https://console.cloud.google.com/cloud-build/builds;region=global/${BUILD_ID};step=${BUILD_STEP}?project=${PROJECT_ID}" \ - --arg breakingstate "${BREAKINGSTATE}" \ - '{context: $context, target_url: $target_url, state: $breakingstate}') - -curl \ - -X POST \ - -u "$github_username:$GITHUB_TOKEN" \ - -H "Accept: application/vnd.github.v3+json" \ - "https://api.github.com/repos/GoogleCloudPlatform/magic-modules/statuses/$COMMIT_SHA" \ - -d "$BREAKINGSTATE_BODY" - -curl -H "Authorization: token ${GITHUB_TOKEN}" \ - -d "$(jq -r --arg diffs "$MESSAGE" -n "{body: \$diffs}")" \ - "https://api.github.com/repos/GoogleCloudPlatform/magic-modules/issues/${PR_NUMBER}/comments" - -if ! git diff --exit-code origin/main tools; then - ## Run unit tests for breaking change and missing test detector. - "$script_dir/test_tools.sh" "$MM_LOCAL_PATH" "$TPGB_LOCAL_PATH" "$COMMIT_SHA" "$BUILD_ID" "$BUILD_STEP" "$PROJECT_ID" -fi diff --git a/.ci/scripts/go-plus/github-differ/test_tools.sh b/.ci/scripts/go-plus/github-differ/test_tools.sh deleted file mode 100755 index 5f47c0408d68..000000000000 --- a/.ci/scripts/go-plus/github-differ/test_tools.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash - -MM_LOCAL_PATH=$1 -TPGB_LOCAL_PATH=$2 -mm_commit_sha=$3 -build_id=$4 -build_step=$5 -project_id=$6 - -github_username=modular-magician - -set +e -pushd $MM_LOCAL_PATH/tools/missing-test-detector -go mod tidy -SERVICES_DIR=$TPGB_LOCAL_PATH/google-beta/services go test -exit_code=$? -popd -set -e - - -if [ $exit_code -ne 0 ]; then - state="failure" -else - state="success" -fi - -post_body=$( jq -n \ - --arg context "unit-tests-missing-test-detector" \ - --arg target_url "https://console.cloud.google.com/cloud-build/builds;region=global/${build_id};step=${build_step}?project=${project_id}" \ - --arg state "${state}" \ - '{context: $context, target_url: $target_url, state: $state}') - -curl \ - -X POST \ - -u "$github_username:$GITHUB_TOKEN" \ - -H "Accept: application/vnd.github.v3+json" \ - "https://api.github.com/repos/GoogleCloudPlatform/magic-modules/statuses/$mm_commit_sha" \ - -d "$post_body" - diff --git a/.ci/scripts/go-plus/github-differ/utils.sh b/.ci/scripts/go-plus/github-differ/utils.sh deleted file mode 100755 index 9a4329a6ad84..000000000000 --- a/.ci/scripts/go-plus/github-differ/utils.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -update_package_name() { - old_package_name="$1" - new_package_name="$2" - - # Update import statements and references within files - find . -type f -name "*.go" -exec sed -i.bak "s~$old_package_name~$new_package_name~g" {} + - - # Update go.mod file - sed -i.bak "s|$old_package_name|$new_package_name|g" go.mod - - # Optional: Update go.sum file - sed -i.bak "s|$old_package_name|$new_package_name|g" go.sum -} From 046681494d8e99d6517c273e0a806513fc8afbe6 Mon Sep 17 00:00:00 2001 From: fayssalmartanigcp <73672393+fayssalmartanigcp@users.noreply.github.com> Date: Fri, 15 Mar 2024 17:44:11 -0400 Subject: [PATCH 46/59] Add ingestion settings to `google_pubsub_topic` (#9985) * Add ingestion settings to `google_pubsub_topic` * Add ingestion settings to `google_pubsub_topic` * Add create/update tests for `google_pubsub_topic` ingestion settings * Update topic ingestion settings test --- mmv1/products/pubsub/Topic.yaml | 42 ++++++++++++ .../pubsub_topic_ingestion_kinesis.tf.erb | 13 ++++ .../pubsub/resource_pubsub_topic_test.go | 68 +++++++++++++++++++ 3 files changed, 123 insertions(+) create mode 100644 mmv1/templates/terraform/examples/pubsub_topic_ingestion_kinesis.tf.erb diff --git a/mmv1/products/pubsub/Topic.yaml b/mmv1/products/pubsub/Topic.yaml index 95bb9563576f..275da6ceabca 100644 --- a/mmv1/products/pubsub/Topic.yaml +++ b/mmv1/products/pubsub/Topic.yaml @@ -72,6 +72,11 @@ examples: schema_name: 'example' test_env_vars: project_name: :PROJECT_NAME + - !ruby/object:Provider::Terraform::Examples + name: 'pubsub_topic_ingestion_kinesis' + primary_resource_id: 'example' + vars: + topic_name: 'example-topic' custom_code: !ruby/object:Provider::Terraform::CustomCode encoder: templates/terraform/encoders/no_send_name.go.erb update_encoder: templates/terraform/update_encoder/pubsub_topic.erb @@ -149,3 +154,40 @@ properties: set, message retention is controlled by settings on individual subscriptions. The rotation period has the format of a decimal number, followed by the letter `s` (seconds). Cannot be more than 31 days or less than 10 minutes. + - !ruby/object:Api::Type::NestedObject + name: 'ingestionDataSourceSettings' + description: | + Settings for ingestion from a data source into this topic. + properties: + - !ruby/object:Api::Type::NestedObject + name: 'awsKinesis' + description: | + Settings for ingestion from Amazon Kinesis Data Streams. + properties: + - !ruby/object:Api::Type::String + name: 'streamArn' + description: | + The Kinesis stream ARN to ingest data from. + required: true + - !ruby/object:Api::Type::String + name: 'consumerArn' + description: | + The Kinesis consumer ARN to used for ingestion in + Enhanced Fan-Out mode. The consumer must be already + created and ready to be used. + required: true + - !ruby/object:Api::Type::String + name: 'awsRoleArn' + description: | + AWS role ARN to be used for Federated Identity authentication with + Kinesis. Check the Pub/Sub docs for how to set up this role and the + required permissions that need to be attached to it. + required: true + - !ruby/object:Api::Type::String + name: 'gcpServiceAccount' + description: | + The GCP service account to be used for Federated Identity authentication + with Kinesis (via a `AssumeRoleWithWebIdentity` call for the provided + role). The `awsRoleArn` must be set up with `accounts.google.com:sub` + equals to this service account number. + required: true diff --git a/mmv1/templates/terraform/examples/pubsub_topic_ingestion_kinesis.tf.erb b/mmv1/templates/terraform/examples/pubsub_topic_ingestion_kinesis.tf.erb new file mode 100644 index 000000000000..b47c80e8a9fa --- /dev/null +++ b/mmv1/templates/terraform/examples/pubsub_topic_ingestion_kinesis.tf.erb @@ -0,0 +1,13 @@ +resource "google_pubsub_topic" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['topic_name'] %>" + + # Outside of automated terraform-provider-google CI tests, these values must be of actual AWS resources for the test to pass. + ingestion_data_source_settings { + aws_kinesis { + stream_arn = "arn:aws:kinesis:us-west-2:111111111111:stream/fake-stream-name" + consumer_arn = "arn:aws:kinesis:us-west-2:111111111111:stream/fake-stream-name/consumer/consumer-1:1111111111" + aws_role_arn = "arn:aws:iam::111111111111:role/fake-role-name" + gcp_service_account = "fake-service-account@fake-gcp-project.iam.gserviceaccount.com" + } + } +} diff --git a/mmv1/third_party/terraform/services/pubsub/resource_pubsub_topic_test.go b/mmv1/third_party/terraform/services/pubsub/resource_pubsub_topic_test.go index b5f13d882c1f..7a944302ea21 100644 --- a/mmv1/third_party/terraform/services/pubsub/resource_pubsub_topic_test.go +++ b/mmv1/third_party/terraform/services/pubsub/resource_pubsub_topic_test.go @@ -140,6 +140,38 @@ func TestAccPubsubTopic_migration(t *testing.T) { }) } +func TestAccPubsubTopic_kinesisIngestionUpdate(t *testing.T) { + t.Parallel() + + topic := fmt.Sprintf("tf-test-topic-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckPubsubTopicDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccPubsubTopic_updateWithKinesisIngestionSettings(topic), + }, + { + ResourceName: "google_pubsub_topic.foo", + ImportStateId: topic, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccPubsubTopic_updateWithUpdatedKinesisIngestionSettings(topic), + }, + { + ResourceName: "google_pubsub_topic.foo", + ImportStateId: topic, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccPubsubTopic_update(topic, key, value string) string { return fmt.Sprintf(` resource "google_pubsub_topic" "foo" { @@ -212,3 +244,39 @@ resource "google_pubsub_topic" "bar" { } `, schema, topic) } + +func testAccPubsubTopic_updateWithKinesisIngestionSettings(topic string) string { + return fmt.Sprintf(` +resource "google_pubsub_topic" "foo" { + name = "%s" + + # Outside of automated terraform-provider-google CI tests, these values must be of actual AWS resources for the test to pass. + ingestion_data_source_settings { + aws_kinesis { + stream_arn = "arn:aws:kinesis:us-west-2:111111111111:stream/fake-stream-name" + consumer_arn = "arn:aws:kinesis:us-west-2:111111111111:stream/fake-stream-name/consumer/consumer-1:1111111111" + aws_role_arn = "arn:aws:iam::111111111111:role/fake-role-name" + gcp_service_account = "fake-service-account@fake-gcp-project.iam.gserviceaccount.com" + } + } +} +`, topic) +} + +func testAccPubsubTopic_updateWithUpdatedKinesisIngestionSettings(topic string) string { + return fmt.Sprintf(` +resource "google_pubsub_topic" "foo" { + name = "%s" + + # Outside of automated terraform-provider-google CI tests, these values must be of actual AWS resources for the test to pass. + ingestion_data_source_settings { + aws_kinesis { + stream_arn = "arn:aws:kinesis:us-west-2:111111111111:stream/updated-fake-stream-name" + consumer_arn = "arn:aws:kinesis:us-west-2:111111111111:stream/updated-fake-stream-name/consumer/consumer-1:1111111111" + aws_role_arn = "arn:aws:iam::111111111111:role/updated-fake-role-name" + gcp_service_account = "updated-fake-service-account@fake-gcp-project.iam.gserviceaccount.com" + } + } +} +`, topic) +} From 7c0a51c93476181d4bd8864fb132d511b2b18995 Mon Sep 17 00:00:00 2001 From: Patrick Costello Date: Mon, 18 Mar 2024 12:40:56 -0700 Subject: [PATCH 47/59] Run Firestore index tests in fresh databases. (#10168) * Run Firestore index tests in fresh databases. This removes the index dependency on creating a document, as creating indexes on a non-existent collection is a valid operation in Firestore. This removes the dependency on a fixed (default) database, which should deflake tests. Fixes #17393. * Move project_id to test_env_vars. * Move project_id to test_env_vars for datastore_mode example. --- mmv1/products/firestore/Index.yaml | 11 +++-- .../examples/firestore_index_basic.tf.erb | 41 +++---------------- .../firestore_index_datastore_mode.tf.erb | 16 ++++++-- 3 files changed, 24 insertions(+), 44 deletions(-) diff --git a/mmv1/products/firestore/Index.yaml b/mmv1/products/firestore/Index.yaml index 06a76d2af452..d96f36e65f9c 100644 --- a/mmv1/products/firestore/Index.yaml +++ b/mmv1/products/firestore/Index.yaml @@ -60,19 +60,18 @@ examples: primary_resource_id: 'my-index' vars: - project_id: "project-id" + database_id: "database-id" test_env_vars: - org_id: :ORG_ID + project_id: :PROJECT_NAME pull_external: true - !ruby/object:Provider::Terraform::Examples name: 'firestore_index_datastore_mode' primary_resource_id: 'my-index' + vars: + database_id: "database-id-dm" test_env_vars: - # This example relies on a well-known collection having been created and - # Firestore being enabled on the project. We can't do that automatically - # for Datastore mode so we need a pre-created project. - project_id: :FIRESTORE_PROJECT_NAME + project_id: :PROJECT_NAME custom_code: !ruby/object:Provider::Terraform::CustomCode custom_import: templates/terraform/custom_import/index_self_link_as_name_set_project.go.erb encoder: templates/terraform/encoders/index.go.erb diff --git a/mmv1/templates/terraform/examples/firestore_index_basic.tf.erb b/mmv1/templates/terraform/examples/firestore_index_basic.tf.erb index 0b3c2cd71548..b706e3be2817 100644 --- a/mmv1/templates/terraform/examples/firestore_index_basic.tf.erb +++ b/mmv1/templates/terraform/examples/firestore_index_basic.tf.erb @@ -1,45 +1,17 @@ -resource "google_project" "project" { - project_id = "<%= ctx[:vars]['project_id'] %>" - name = "<%= ctx[:vars]['project_id'] %>" - org_id = "<%= ctx[:test_env_vars]['org_id'] %>" -} - -resource "time_sleep" "wait_60_seconds" { - depends_on = [google_project.project] - - create_duration = "60s" -} - -resource "google_project_service" "firestore" { - project = google_project.project.project_id - service = "firestore.googleapis.com" - - # Needed for CI tests for permissions to propagate, should not be needed for actual usage - depends_on = [time_sleep.wait_60_seconds] -} - resource "google_firestore_database" "database" { - project = google_project.project.project_id - name = "(default)" + project = "<%= ctx[:test_env_vars]['project_id'] %>" + name = "<%= ctx[:vars]['database_id'] %>" location_id = "nam5" type = "FIRESTORE_NATIVE" - depends_on = [google_project_service.firestore] -} - -# Creating a document also creates its collection -resource "google_firestore_document" "document" { - project = google_project.project.project_id - database = google_firestore_database.database.name - collection = "somenewcollection" - document_id = "<%= ctx[:vars]['document_id'] %>" - fields = "{\"something\":{\"mapValue\":{\"fields\":{\"akey\":{\"stringValue\":\"avalue\"}}}}}" + delete_protection_state = "DELETE_PROTECTION_DISABLED" + deletion_policy = "DELETE" } resource "google_firestore_index" "<%= ctx[:primary_resource_id] %>" { - project = google_project.project.project_id + project = "<%= ctx[:test_env_vars]['project_id'] %>" database = google_firestore_database.database.name - collection = google_firestore_document.document.collection + collection = "atestcollection" fields { field_path = "name" @@ -50,5 +22,4 @@ resource "google_firestore_index" "<%= ctx[:primary_resource_id] %>" { field_path = "description" order = "DESCENDING" } - } diff --git a/mmv1/templates/terraform/examples/firestore_index_datastore_mode.tf.erb b/mmv1/templates/terraform/examples/firestore_index_datastore_mode.tf.erb index bc944770c839..4ec2fc640954 100644 --- a/mmv1/templates/terraform/examples/firestore_index_datastore_mode.tf.erb +++ b/mmv1/templates/terraform/examples/firestore_index_datastore_mode.tf.erb @@ -1,7 +1,17 @@ +resource "google_firestore_database" "database" { + project = "<%= ctx[:test_env_vars]['project_id'] %>" + name = "<%= ctx[:vars]['database_id'] %>" + location_id = "nam5" + type = "DATASTORE_MODE" + + delete_protection_state = "DELETE_PROTECTION_DISABLED" + deletion_policy = "DELETE" +} + resource "google_firestore_index" "<%= ctx[:primary_resource_id] %>" { - project = "<%= ctx[:test_env_vars]['project_id'] %>" - database = "(default)" - collection = "chatrooms" + project = "<%= ctx[:test_env_vars]['project_id'] %>" + database = google_firestore_database.database.name + collection = "atestcollection" query_scope = "COLLECTION_RECURSIVE" api_scope = "DATASTORE_MODE_API" From 5b99a9a281b329b84b6a12d3947dcd31896b0a30 Mon Sep 17 00:00:00 2001 From: Charles Leon Date: Mon, 18 Mar 2024 15:42:34 -0700 Subject: [PATCH 48/59] AccessContextManager - Add dry run service perimeter resource (#10145) Co-authored-by: Charlesleonius --- .../ServicePerimeterDryRunResource.yaml | 89 +++++++++++ .../ServicePerimeterResource.yaml | 3 +- ...ce_perimeter_dry_run_resource_basic.tf.erb | 22 +++ ..._service_perimeter_dry_run_resource.go.erb | 1 + ..._context_manager_access_policy_test.go.erb | 31 ++-- ...service_perimeter_dry_run_resource_test.go | 139 ++++++++++++++++++ 6 files changed, 269 insertions(+), 16 deletions(-) create mode 100644 mmv1/products/accesscontextmanager/ServicePerimeterDryRunResource.yaml create mode 100644 mmv1/templates/terraform/examples/access_context_manager_service_perimeter_dry_run_resource_basic.tf.erb create mode 100644 mmv1/templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb create mode 100644 mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_dry_run_resource_test.go diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunResource.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunResource.yaml new file mode 100644 index 000000000000..9b39f873b779 --- /dev/null +++ b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunResource.yaml @@ -0,0 +1,89 @@ +# Copyright 2018 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +name: 'ServicePerimeterDryRunResource' +create_url: '{{perimeter_name}}' +base_url: '' +self_link: '{{perimeter_name}}' +create_verb: :PATCH +delete_verb: :PATCH +immutable: true +update_mask: true +identity: + - resource +nested_query: !ruby/object:Api::Resource::NestedQuery + modify_by_patch: true + is_list_of_ids: true + keys: + - spec + - resources +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Service Perimeter Quickstart': 'https://cloud.google.com/vpc-service-controls/docs/quickstart' + api: 'https://cloud.google.com/access-context-manager/docs/reference/rest/v1/accessPolicies.servicePerimeters' +description: | + Allows configuring a single GCP resource that should be inside of the `spec` block of a dry run service perimeter. + This resource is intended to be used in cases where it is not possible to compile a full list + of projects to include in a `google_access_context_manager_service_perimeter` resource, + to enable them to be added separately. + If your perimeter is NOT in dry-run mode use `google_access_context_manager_service_perimeter_resource` instead. + + ~> **Note:** If this resource is used alongside a `google_access_context_manager_service_perimeter` resource, + the service perimeter resource must have a `lifecycle` block with `ignore_changes = [spec[0].resources]` so + they don't fight over which resources should be in the policy. +docs: !ruby/object:Provider::Terraform::Docs + warning: | + If you are using User ADCs (Application Default Credentials) with this resource, + you must specify a `billing_project` and set `user_project_override` to true + in the provider configuration. Otherwise the ACM API will return a 403 error. + Your account must have the `serviceusage.services.use` permission on the + `billing_project` you defined. +autogen_async: true +exclude_tgc: true +# Skipping the sweeper due to the non-standard base_url and because this is fine-grained under ServicePerimeter +skip_sweeper: true +id_format: '{{perimeter_name}}/{{resource}}' +import_format: ['{{perimeter_name}}/{{resource}}'] +mutex: '{{perimeter_name}}' +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'access_context_manager_service_perimeter_dry_run_resource_basic' + skip_test: true + primary_resource_id: 'service-perimeter-dry-run-resource' + vars: + service_perimeter_name: 'restrict_all' +custom_code: !ruby/object:Provider::Terraform::CustomCode + custom_import: templates/terraform/custom_import/access_context_manager_service_perimeter_resource.go.erb + pre_update: templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb + pre_create: templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb + pre_delete: templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb +parameters: + - !ruby/object:Api::Type::ResourceRef + name: 'perimeterName' + resource: 'ServicePerimeter' + imports: 'name' + description: | + The name of the Service Perimeter to add this resource to. + required: true + immutable: true + url_param_only: true +properties: + - !ruby/object:Api::Type::String + name: 'resource' + description: | + A GCP resource that is inside of the service perimeter. + Currently only projects are allowed. + Format: projects/{project_number} + required: true + immutable: true diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterResource.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterResource.yaml index b5264b1dadda..298b2bad26d7 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterResource.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterResource.yaml @@ -33,10 +33,11 @@ references: !ruby/object:Api::Resource::ReferenceLinks 'Service Perimeter Quickstart': 'https://cloud.google.com/vpc-service-controls/docs/quickstart' api: 'https://cloud.google.com/access-context-manager/docs/reference/rest/v1/accessPolicies.servicePerimeters' description: | - Allows configuring a single GCP resource that should be inside of a service perimeter. + Allows configuring a single GCP resource that should be inside the `status` block of a service perimeter. This resource is intended to be used in cases where it is not possible to compile a full list of projects to include in a `google_access_context_manager_service_perimeter` resource, to enable them to be added separately. + If your perimeter is in dry-run mode use `google_access_context_manager_service_perimeter_dry_run_resource` instead. ~> **Note:** If this resource is used alongside a `google_access_context_manager_service_perimeter` resource, the service perimeter resource must have a `lifecycle` block with `ignore_changes = [status[0].resources]` so diff --git a/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_dry_run_resource_basic.tf.erb b/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_dry_run_resource_basic.tf.erb new file mode 100644 index 000000000000..04b6ebfbb10e --- /dev/null +++ b/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_dry_run_resource_basic.tf.erb @@ -0,0 +1,22 @@ +resource "google_access_context_manager_service_perimeter_dry_run_resource" "<%= ctx[:primary_resource_id] %>" { + perimeter_name = google_access_context_manager_service_perimeter.<%= ctx[:primary_resource_id] %>.name + resource = "projects/987654321" +} + +resource "google_access_context_manager_service_perimeter" "<%= ctx[:primary_resource_id] %>" { + parent = "accessPolicies/${google_access_context_manager_access_policy.access-policy.name}" + name = "accessPolicies/${google_access_context_manager_access_policy.access-policy.name}/servicePerimeters/<%= ctx[:vars]['service_perimeter_name'] %>" + title = "<%= ctx[:vars]['service_perimeter_name'] %>" + spec { + restricted_services = ["storage.googleapis.com"] + } + use_explicit_dry_run_spec = true + lifecycle { + ignore_changes = [spec[0].resources] + } +} + +resource "google_access_context_manager_access_policy" "access-policy" { + parent = "organizations/123456789" + title = "my policy" +} diff --git a/mmv1/templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb b/mmv1/templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb new file mode 100644 index 000000000000..7e9f036c027b --- /dev/null +++ b/mmv1/templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb @@ -0,0 +1 @@ +obj["use_explicit_dry_run_spec"] = true diff --git a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_access_policy_test.go.erb b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_access_policy_test.go.erb index 944066fd5ed2..76ea6244cbfd 100644 --- a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_access_policy_test.go.erb +++ b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_access_policy_test.go.erb @@ -17,21 +17,22 @@ import ( // can exist, they need to be run serially func TestAccAccessContextManager(t *testing.T) { testCases := map[string]func(t *testing.T){ - "access_policy": testAccAccessContextManagerAccessPolicy_basicTest, - "access_policy_scoped": testAccAccessContextManagerAccessPolicy_scopedTest, - "service_perimeter": testAccAccessContextManagerServicePerimeter_basicTest, - "service_perimeter_update": testAccAccessContextManagerServicePerimeter_updateTest, - "service_perimeter_resource": testAccAccessContextManagerServicePerimeterResource_basicTest, - "access_level": testAccAccessContextManagerAccessLevel_basicTest, - "access_level_full": testAccAccessContextManagerAccessLevel_fullTest, - "access_level_custom": testAccAccessContextManagerAccessLevel_customTest, - "access_levels": testAccAccessContextManagerAccessLevels_basicTest, - "access_level_condition": testAccAccessContextManagerAccessLevelCondition_basicTest, - "service_perimeter_egress_policy": testAccAccessContextManagerServicePerimeterEgressPolicy_basicTest, - "service_perimeter_ingress_policy": testAccAccessContextManagerServicePerimeterIngressPolicy_basicTest, - "service_perimeters": testAccAccessContextManagerServicePerimeters_basicTest, - "gcp_user_access_binding": testAccAccessContextManagerGcpUserAccessBinding_basicTest, - "authorized_orgs_desc": testAccAccessContextManagerAuthorizedOrgsDesc_basicTest, + "access_policy": testAccAccessContextManagerAccessPolicy_basicTest, + "access_policy_scoped": testAccAccessContextManagerAccessPolicy_scopedTest, + "service_perimeter": testAccAccessContextManagerServicePerimeter_basicTest, + "service_perimeter_update": testAccAccessContextManagerServicePerimeter_updateTest, + "service_perimeter_resource": testAccAccessContextManagerServicePerimeterResource_basicTest, + "service_perimeter_dry_run_resource": testAccAccessContextManagerServicePerimeterResource_basicTest, + "access_level": testAccAccessContextManagerAccessLevel_basicTest, + "access_level_full": testAccAccessContextManagerAccessLevel_fullTest, + "access_level_custom": testAccAccessContextManagerAccessLevel_customTest, + "access_levels": testAccAccessContextManagerAccessLevels_basicTest, + "access_level_condition": testAccAccessContextManagerAccessLevelCondition_basicTest, + "service_perimeter_egress_policy": testAccAccessContextManagerServicePerimeterEgressPolicy_basicTest, + "service_perimeter_ingress_policy": testAccAccessContextManagerServicePerimeterIngressPolicy_basicTest, + "service_perimeters": testAccAccessContextManagerServicePerimeters_basicTest, + "gcp_user_access_binding": testAccAccessContextManagerGcpUserAccessBinding_basicTest, + "authorized_orgs_desc": testAccAccessContextManagerAuthorizedOrgsDesc_basicTest, } for name, tc := range testCases { diff --git a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_dry_run_resource_test.go b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_dry_run_resource_test.go new file mode 100644 index 000000000000..3c240fdd5d85 --- /dev/null +++ b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_dry_run_resource_test.go @@ -0,0 +1,139 @@ +package accesscontextmanager_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +// Since each test here is acting on the same organization and only one AccessPolicy +// can exist, they need to be run serially. See AccessPolicy for the test runner. + +func testAccAccessContextManagerServicePerimeterDryRunResource_basicTest(t *testing.T) { + // Multiple fine-grained resources + acctest.SkipIfVcr(t) + org := envvar.GetTestOrgFromEnv(t) + projects := acctest.BootstrapServicePerimeterProjects(t, 2) + policyTitle := "my policy" + perimeterTitle := "perimeter" + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccAccessContextManagerServicePerimeterDryRunResource_basic(org, policyTitle, perimeterTitle, projects[0].ProjectNumber, projects[1].ProjectNumber), + }, + { + ResourceName: "google_access_context_manager_service_perimeter_dry_run_resource.test-access1", + ImportState: true, + ImportStateVerify: true, + }, + { + ResourceName: "google_access_context_manager_service_perimeter_dry_run_resource.test-access2", + ImportState: true, + ImportStateVerify: true, + }, + // Use a separate TestStep rather than a CheckDestroy because we need the service perimeter to still exist + { + Config: testAccAccessContextManagerServicePerimeterDryRunResource_destroy(org, policyTitle, perimeterTitle), + Check: testAccCheckAccessContextManagerServicePerimeterDryRunResourceDestroyProducer(t), + }, + }, + }) +} + +func testAccCheckAccessContextManagerServicePerimeterDryRunResourceDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "google_access_context_manager_service_perimeter_dry_run_resource" { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{AccessContextManagerBasePath}}{{perimeter_name}}") + if err != nil { + return err + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + RawURL: url, + UserAgent: config.UserAgent, + }) + if err != nil { + return err + } + + v, ok := res["spec"] + if !ok || v == nil { + return nil + } + + res = v.(map[string]interface{}) + v, ok = res["resources"] + if !ok || v == nil { + return nil + } + + resources := v.([]interface{}) + if len(resources) == 0 { + return nil + } + + return fmt.Errorf("expected 0 resources in perimeter, found %d: %v", len(resources), resources) + } + + return nil + } +} + +func testAccAccessContextManagerServicePerimeterDryRunResource_basic(org, policyTitle, perimeterTitleName string, projectNumber1, projectNumber2 int64) string { + return fmt.Sprintf(` +%s + +resource "google_access_context_manager_service_perimeter_dry_run_resource" "test-access1" { + perimeter_name = google_access_context_manager_service_perimeter.test-access.name + resource = "projects/%d" +} + +resource "google_access_context_manager_service_perimeter_dry_run_resource" "test-access2" { + perimeter_name = google_access_context_manager_service_perimeter.test-access.name + resource = "projects/%d" +} +`, testAccAccessContextManagerServicePerimeterDryRunResource_destroy(org, policyTitle, perimeterTitleName), projectNumber1, projectNumber2) +} + +func testAccAccessContextManagerServicePerimeterDryRunResource_destroy(org, policyTitle, perimeterTitleName string) string { + return fmt.Sprintf(` +resource "google_access_context_manager_access_policy" "test-access" { + parent = "organizations/%s" + title = "%s" +} + +resource "google_access_context_manager_service_perimeter" "test-access" { + parent = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}" + name = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}/servicePerimeters/%s" + title = "%s" + perimeter_type = "PERIMETER_TYPE_REGULAR" + status { + restricted_services = ["storage.googleapis.com"] + } + spec { + restricted_services = ["storage.googleapis.com"] + } + use_explicit_dry_run_spec = true + lifecycle { + ignore_changes = [spec[0].resources] + } +} +`, org, policyTitle, perimeterTitleName, perimeterTitleName) +} From 55deca52e291505ba1692b3fea275116b2adfe85 Mon Sep 17 00:00:00 2001 From: Xuran Liu Date: Tue, 19 Mar 2024 06:59:44 -0700 Subject: [PATCH 49/59] Create quota infos datasource (#10074) * add quota info data source * add test and documention for quota_info data source * fix lint error * add quota infos datasource * update read test * remove duplicate import * update formatting and documentation * remove pagination parameters, concat and return all qualified entries * remove specific check for number of entries --- .../provider/provider_mmv1_resources.go.erb | 1 + ..._source_google_cloud_quotas_quota_infos.go | 215 ++++++++++++++++++ ...ce_google_cloud_quotas_quota_infos_test.go | 51 +++++ .../d/cloud_quotas_quota_info.html.markdown | 1 - .../d/cloud_quotas_quota_infos.html.markdown | 62 +++++ 5 files changed, 329 insertions(+), 1 deletion(-) create mode 100644 mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos.go create mode 100644 mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos_test.go create mode 100644 mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_infos.html.markdown diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb index f58f2b57e660..f828b8c13ff2 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -53,6 +53,7 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_cloud_identity_group_memberships": cloudidentity.DataSourceGoogleCloudIdentityGroupMemberships(), "google_cloud_identity_group_lookup": cloudidentity.DataSourceGoogleCloudIdentityGroupLookup(), "google_cloud_quotas_quota_info": cloudquotas.DataSourceGoogleCloudQuotasQuotaInfo(), + "google_cloud_quotas_quota_infos": cloudquotas.DataSourceGoogleCloudQuotasQuotaInfos(), "google_cloud_run_locations": cloudrun.DataSourceGoogleCloudRunLocations(), "google_cloud_run_service": cloudrun.DataSourceGoogleCloudRunService(), "google_cloud_run_v2_job": cloudrunv2.DataSourceGoogleCloudRunV2Job(), diff --git a/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos.go b/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos.go new file mode 100644 index 000000000000..5b0c90afd9f8 --- /dev/null +++ b/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos.go @@ -0,0 +1,215 @@ +package cloudquotas + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func DataSourceGoogleCloudQuotasQuotaInfos() *schema.Resource { + return &schema.Resource{ + Read: dataSourceGoogleCloudQuotasQuotaInfosRead, + + Schema: map[string]*schema.Schema{ + "parent": { + Type: schema.TypeString, + Required: true, + }, + "service": { + Type: schema.TypeString, + Required: true, + }, + "quota_infos": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "service": { + Type: schema.TypeString, + Computed: true, + }, + "quota_id": { + Type: schema.TypeString, + Computed: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "metric": { + Type: schema.TypeString, + Computed: true, + }, + "is_precise": { + Type: schema.TypeBool, + Computed: true, + }, + "refresh_interval": { + Type: schema.TypeString, + Computed: true, + }, + "container_type": { + Type: schema.TypeString, + Computed: true, + }, + "dimensions": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "metric_display_name": { + Type: schema.TypeString, + Computed: true, + }, + "quota_display_name": { + Type: schema.TypeString, + Computed: true, + }, + "metric_unit": { + Type: schema.TypeString, + Computed: true, + }, + "quota_increase_eligibility": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "is_eligible": { + Type: schema.TypeBool, + Computed: true, + }, + "ineligibility_reason": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "is_fixed": { + Type: schema.TypeBool, + Computed: true, + }, + "dimensions_infos": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dimensions": { + Type: schema.TypeMap, + Computed: true, + }, + "details": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "value": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "applicable_locations": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "is_concurrent": { + Type: schema.TypeBool, + Computed: true, + }, + "service_request_quota_uri": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + UseJSONNumber: true, + } +} + +func dataSourceGoogleCloudQuotasQuotaInfosRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + url, err := tpgresource.ReplaceVars(d, config, "{{CloudQuotasBasePath}}{{parent}}/locations/global/services/{{service}}/quotaInfos") + if err != nil { + return fmt.Errorf("error setting api endpoint") + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + RawURL: url, + UserAgent: userAgent, + }) + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("CloudQuotasQuotaInfo %q", d.Id())) + } + + var quotaInfos []map[string]interface{} + for { + fetchedQuotaInfos := res["quotaInfos"].([]interface{}) + for _, rawQuotaInfo := range fetchedQuotaInfos { + quotaInfos = append(quotaInfos, flattenCloudQuotasQuotaInfo(rawQuotaInfo.(map[string]interface{}), d, config)) + } + + if res["nextPageToken"] == nil || res["nextPageToken"].(string) == "" { + break + } + url, err = tpgresource.ReplaceVars(d, config, "{{CloudQuotasBasePath}}{{parent}}/locations/global/services/{{service}}/quotaInfos?pageToken="+res["nextPageToken"].(string)) + if err != nil { + return fmt.Errorf("error setting api endpoint") + } + res, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + RawURL: url, + UserAgent: userAgent, + }) + if err != nil { + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("CloudQuotasQuotaInfo %q", d.Id()), url) + } + } + + if err := d.Set("quota_infos", quotaInfos); err != nil { + return fmt.Errorf("error reading quota infos : %s", err) + } + + d.SetId(url) + return nil +} + +func flattenCloudQuotasQuotaInfo(rawQuotaInfo map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config) map[string]interface{} { + quotaInfo := make(map[string]interface{}) + + quotaInfo["name"] = rawQuotaInfo["name"] + quotaInfo["quota_id"] = rawQuotaInfo["quotaId"] + quotaInfo["metric"] = rawQuotaInfo["metric"] + quotaInfo["service"] = rawQuotaInfo["service"] + quotaInfo["is_precise"] = rawQuotaInfo["isPrecise"] + quotaInfo["refresh_interval"] = rawQuotaInfo["refreshInterval"] + quotaInfo["container_type"] = rawQuotaInfo["containerType"] + quotaInfo["dimensions"] = rawQuotaInfo["dimensions"] + quotaInfo["metric_display_name"] = rawQuotaInfo["metricDisplayName"] + quotaInfo["quota_display_name"] = rawQuotaInfo["quotaDisplayName"] + quotaInfo["metric_unit"] = rawQuotaInfo["metricUnit"] + quotaInfo["quota_increase_eligibility"] = flattenCloudQuotasQuotaInfoQuotaIncreaseEligibility(rawQuotaInfo["quotaIncreaseEligibility"], d, config) + quotaInfo["is_fixed"] = rawQuotaInfo["isFixed"] + quotaInfo["dimensions_infos"] = flattenCloudQuotasQuotaInfoDimensionsInfos(rawQuotaInfo["dimensionsInfos"], d, config) + quotaInfo["is_concurrent"] = rawQuotaInfo["isConcurrent"] + quotaInfo["service_request_quota_uri"] = rawQuotaInfo["serviceRequestQuotaUri"] + + return quotaInfo +} diff --git a/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos_test.go b/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos_test.go new file mode 100644 index 000000000000..99db75f58074 --- /dev/null +++ b/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos_test.go @@ -0,0 +1,51 @@ +package cloudquotas_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccDataSourceGoogleQuotaInfos_basic(t *testing.T) { + t.Parallel() + + resourceName := "data.google_cloud_quotas_quota_infos.my_quota_infos" + service := "compute.googleapis.com" + + context := map[string]interface{}{ + "project": envvar.GetTestProjectFromEnv(), + "service": service, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccDataSourceGoogleQuotaInfos_basic(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.name"), + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.quota_id"), + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.metric"), + resource.TestCheckResourceAttr(resourceName, "quota_infos.0.service", service), + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.is_precise"), + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.container_type"), + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.quota_increase_eligibility.0.is_eligible"), + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.dimensions_infos.0.details.0.value"), + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.dimensions_infos.0.applicable_locations.0"), + ), + }, + }, + }) +} + +func testAccDataSourceGoogleQuotaInfos_basic(context map[string]interface{}) string { + return acctest.Nprintf(` + data "google_cloud_quotas_quota_infos" "my_quota_infos" { + parent = "projects/%{project}" + service = "%{service}" + } + `, context) +} diff --git a/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_info.html.markdown b/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_info.html.markdown index 77e97d36489c..2f88f3c3abdc 100644 --- a/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_info.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_info.html.markdown @@ -53,7 +53,6 @@ The following attributes are exported: The `dimensions_infos` block supports: * `dimensions` - The map of dimensions for this dimensions info. The key of a map entry is "region", "zone" or the name of a service specific dimension, and the value of a map entry is the value of the dimension. If a dimension does not appear in the map of dimensions, the dimensions info applies to all the dimension values except for those that have another DimenisonInfo instance configured for the specific value. Example: {"provider" : "Foo Inc"} where "provider" is a service specific dimension of a quota. - An object containing a list of "key": value pairs, for example: `{ "name": "wrench", "mass": "1.3kg", "count": "3" }`. * `details` - The quota details for a map of dimensions. * `applicable_locations` - The applicable regions or zones of this dimensions info. The field will be set to `['global']` for quotas that are not per region or per zone. Otherwise, it will be set to the list of locations this dimension info is applicable to. diff --git a/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_infos.html.markdown b/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_infos.html.markdown new file mode 100644 index 000000000000..b160791ce1ca --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_infos.html.markdown @@ -0,0 +1,62 @@ +--- +subcategory: "Cloud Quotas" +--- + +# google\_cloud\_quotas\_quota\_infos + +Provides information about all quotas for a given project, folder or organization. + +## Example Usage + +```hcl +data "google_cloud_quotas_quota_infos" "my_quota_infos" { + parent = "projects/my-project" + service = "compute.googleapis.com" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `parent` - (Required) Parent value of QuotaInfo resources. Listing across different resource containers (such as 'projects/-') is not allowed. Allowed parents are "projects/[project-id / number]" or "folders/[folder-id / number]" or "organizations/[org-id / number]. + +* `service` - (Required) The name of the service in which the quotas are defined. + + +## Attributes Reference + +The following attributes are exported: + +* `quota_infos` - (Output) The list of QuotaInfo. + + The `quota_infos` block supports: + +* `name` - (Output) Resource name of this QuotaInfo, for example: `projects/123/locations/global/services/compute.googleapis.com/quotaInfos/CpusPerProjectPerRegion`. +* `metric` - (Output) The metric of the quota. It specifies the resources consumption the quota is defined for, for example: `compute.googleapis.com/cpus`. +* `is_precise` - (Output) Whether this is a precise quota. A precise quota is tracked with absolute precision. In contrast, an imprecise quota is not tracked with precision. +* `refresh_interval` - (Output) The reset time interval for the quota. Refresh interval applies to rate quota only. Example: "minute" for per minute, "day" for per day, or "10 seconds" for every 10 seconds. +* `container_type` - (Output) The container type of the QuotaInfo. +* `dimensions` - (Output) The dimensions the quota is defined on. +* `metric_display_name` - (Output) The display name of the quota metric. +* `quota_display_name` - (Output) The display name of the quota. +* `metric_unit` - (Output) The unit in which the metric value is reported, e.g., `MByte`. +* `quota_increase_eligibility` - (Output) Whether it is eligible to request a higher quota value for this quota. +* `is_fixed` - (Output) Whether the quota value is fixed or adjustable. +* `dimensions_infos` - (Output) The collection of dimensions info ordered by their dimensions from more specific ones to less specific ones. +* `is_concurrent` - (Output) Whether the quota is a concurrent quota. Concurrent quotas are enforced on the total number of concurrent operations in flight at any given time. +* `service_request_quota_uri` - (Output) URI to the page where users can request more quota for the cloud service, for example: `https://console.cloud.google.com/iam-admin/quotas`. + + The `quota_increase_eligibility` block supports: + +* `is_eligible` - Whether a higher quota value can be requested for the quota. +* `ineligibility_reason` - The enumeration of reasons when it is ineligible to request increase adjustment. + + The `dimensions_infos` block supports: +* `dimensions` - The map of dimensions for this dimensions info. The key of a map entry is "region", "zone" or the name of a service specific dimension, and the value of a map entry is the value of the dimension. If a dimension does not appear in the map of dimensions, the dimensions info applies to all the dimension values except for those that have another DimenisonInfo instance configured for the specific value. Example: {"provider" : "Foo Inc"} where "provider" is a service specific dimension of a quota. + +* `details` - The quota details for a map of dimensions. +* `applicable_locations` - The applicable regions or zones of this dimensions info. The field will be set to `['global']` for quotas that are not per region or per zone. Otherwise, it will be set to the list of locations this dimension info is applicable to. + + The `details` block supports: +* `value` - The value currently in effect and being enforced. From 5e5b8d75bfb2d2e98d048a3616a10302b6515493 Mon Sep 17 00:00:00 2001 From: rahul2393 Date: Tue, 19 Mar 2024 20:49:03 +0530 Subject: [PATCH 50/59] fix(spanner): remove validation on version retention period on spanner database (#10184) * fix(spanner): remove validation on version retention period on spanner database * fix build --- mmv1/products/spanner/Database.yaml | 2 - .../constants/spanner_database.go.erb | 38 ---------- .../resource_spanner_database_test.go.erb | 72 ------------------- 3 files changed, 112 deletions(-) diff --git a/mmv1/products/spanner/Database.yaml b/mmv1/products/spanner/Database.yaml index ea33c9ad211c..bcb1c3c21033 100644 --- a/mmv1/products/spanner/Database.yaml +++ b/mmv1/products/spanner/Database.yaml @@ -120,8 +120,6 @@ properties: the values 1d, 24h, 1440m, and 86400s are equivalent. Default value is 1h. If this property is used, you must avoid adding new DDL statements to `ddl` that update the database's version_retention_period. - validation: !ruby/object:Provider::Terraform::Validation - function: ValidateDatabaseRetentionPeriod default_from_api: true - !ruby/object:Api::Type::Array name: 'ddl' diff --git a/mmv1/templates/terraform/constants/spanner_database.go.erb b/mmv1/templates/terraform/constants/spanner_database.go.erb index bc2c1ae45088..926488ac8c68 100644 --- a/mmv1/templates/terraform/constants/spanner_database.go.erb +++ b/mmv1/templates/terraform/constants/spanner_database.go.erb @@ -44,44 +44,6 @@ func resourceSpannerDBDdlCustomDiff(_ context.Context, diff *schema.ResourceDiff return resourceSpannerDBDdlCustomDiffFunc(diff) } -func ValidateDatabaseRetentionPeriod(v interface{}, k string) (ws []string, errors []error) { - value := v.(string) - valueError := fmt.Errorf("version_retention_period should be in range [1h, 7d], in a format resembling 1d, 24h, 1440m, or 86400s") - - r := regexp.MustCompile("^(\\d{1}d|\\d{1,3}h|\\d{2,5}m|\\d{4,6}s)$") - if !r.MatchString(value) { - errors = append(errors, valueError) - return - } - - unit := value[len(value)-1:] - multiple := value[:len(value)-1] - num, err := strconv.Atoi(multiple) - if err != nil { - errors = append(errors, valueError) - return - } - - if unit == "d" && (num < 1 || num > 7) { - errors = append(errors, valueError) - return - } - if unit == "h" && (num < 1 || num > 7*24) { - errors = append(errors, valueError) - return - } - if unit == "m" && (num < 1*60 || num > 7*24*60) { - errors = append(errors, valueError) - return - } - if unit == "s" && (num < 1*60*60 || num > 7*24*60*60) { - errors = append(errors, valueError) - return - } - - return -} - func resourceSpannerDBVirtualUpdate(d *schema.ResourceData, resourceSchema map[string]*schema.Schema) bool { // deletion_protection is the only virtual field if d.HasChange("deletion_protection") { diff --git a/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.erb b/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.erb index 3eb94e373be8..75f625c37217 100644 --- a/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.erb +++ b/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.erb @@ -9,7 +9,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-provider-google/google/acctest" "github.com/hashicorp/terraform-provider-google/google/envvar" - "github.com/hashicorp/terraform-provider-google/google/services/spanner" ) func TestAccSpannerDatabase_basic(t *testing.T) { @@ -466,77 +465,6 @@ resource "google_spanner_database" "basic" { `, instanceName, instanceName, databaseName) } -// Unit Tests for validation of retention period argument -func TestValidateDatabaseRetentionPeriod(t *testing.T) { - t.Parallel() - testCases := map[string]struct { - input string - expectError bool - }{ - // Not valid input - "empty_string": { - input: "", - expectError: true, - }, - "number_with_no_unit": { - input: "1", - expectError: true, - }, - "less_than_1h": { - input: "59m", - expectError: true, - }, - "more_than_7days": { - input: "8d", - expectError: true, - }, - // Valid input - "1_hour_in_secs": { - input: "3600s", - expectError: false, - }, - "1_hour_in_mins": { - input: "60m", - expectError: false, - }, - "1_hour_in_hours": { - input: "1h", - expectError: false, - }, - "7_days_in_secs": { - input: fmt.Sprintf("%ds", 7*24*60*60), - expectError: false, - }, - "7_days_in_mins": { - input: fmt.Sprintf("%dm", 7*24*60), - expectError: false, - }, - "7_days_in_hours": { - input: fmt.Sprintf("%dh", 7*24), - expectError: false, - }, - "7_days_in_days": { - input: "7d", - expectError: false, - }, - } - - for tn, tc := range testCases { - t.Run(tn, func(t *testing.T) { - _, errs := spanner.ValidateDatabaseRetentionPeriod(tc.input, "foobar") - var wantErrCount string - if tc.expectError { - wantErrCount = "1+" - } else { - wantErrCount = "0" - } - if (len(errs) > 0 && tc.expectError == false) || (len(errs) == 0 && tc.expectError == true) { - t.Errorf("failed, expected `%s` test case validation to have %s errors", tn, wantErrCount) - } - }) - } -} - func TestAccSpannerDatabase_deletionProtection(t *testing.T) { acctest.SkipIfVcr(t) t.Parallel() From 974267d4ade60c1ca9eab3e4efea058f2e95c792 Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Tue, 19 Mar 2024 12:54:44 -0500 Subject: [PATCH 51/59] initial mmv1 go templating and flags (#10219) --- mmv1/go.mod | 2 + mmv1/go.sum | 2 + mmv1/google/string_utils.go | 26 +- mmv1/main.go | 35 ++- mmv1/provider/template_data.go | 195 ++++++++++++ mmv1/provider/terraform.go | 290 +++++++++--------- mmv1/templates/terraform/resource.go.tmpl | 31 ++ .../terraform/resource.html.markdown.tmpl | 30 ++ 8 files changed, 437 insertions(+), 174 deletions(-) create mode 100644 mmv1/provider/template_data.go create mode 100644 mmv1/templates/terraform/resource.go.tmpl create mode 100644 mmv1/templates/terraform/resource.html.markdown.tmpl diff --git a/mmv1/go.mod b/mmv1/go.mod index 58a9d896cd1a..b297c2158ba6 100644 --- a/mmv1/go.mod +++ b/mmv1/go.mod @@ -6,3 +6,5 @@ require ( golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 gopkg.in/yaml.v2 v2.4.0 ) + +require github.com/golang/glog v1.2.0 // indirect diff --git a/mmv1/go.sum b/mmv1/go.sum index b8ec4cc09d5a..3e041fb75ba4 100644 --- a/mmv1/go.sum +++ b/mmv1/go.sum @@ -1,3 +1,5 @@ +github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= +github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= diff --git a/mmv1/google/string_utils.go b/mmv1/google/string_utils.go index 264f031893c6..a9e4fb0db978 100644 --- a/mmv1/google/string_utils.go +++ b/mmv1/google/string_utils.go @@ -20,23 +20,15 @@ import ( // // Helper class to process and mutate strings. // class StringUtils -// // Converts string from camel case to underscore -// def self.underscore(source) -// source.gsub(/::/, '/') -// .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2') -// .gsub(/([a-z\d])([A-Z])/, '\1_\2') -// .tr('-', '_') -// .tr('.', '_') -// .downcase -// end - -// // Converts from PascalCase to Space Separated -// def self.space_separated(source) -// tmp = source.gsub(/([A-Z]+)([A-Z][a-z])/, '\1 \2') -// .gsub(/([a-z\d])([A-Z])/, '\1 \2') -// .downcase -// tmp[0].upcase.concat(tmp[1..]) -// end +// Converts string from camel case to underscore +func Underscore(source string) string { + tmp := regexp.MustCompile(`([A-Z]+)([A-Z][a-z])`).ReplaceAllString(source, "${1}_${2}") + tmp = regexp.MustCompile(`([a-z\d])([A-Z])`).ReplaceAllString(tmp, "${1}_${2}") + tmp = strings.Replace(tmp, "-", "_", 1) + tmp = strings.Replace(tmp, ".", "_", 1) + tmp = strings.ToLower(tmp) + return tmp +} // Converts from PascalCase to Space Separated // For example, converts "AccessApproval" to "Access Approval" diff --git a/mmv1/main.go b/mmv1/main.go index b01aad864eaf..11f04126cc44 100644 --- a/mmv1/main.go +++ b/mmv1/main.go @@ -1,6 +1,7 @@ package main import ( + "flag" "fmt" "log" "os" @@ -16,14 +17,26 @@ import ( "github.com/GoogleCloudPlatform/magic-modules/mmv1/provider" ) +// TODO Q2: additional flags + +// Example usage: --output $GOPATH/src/github.com/terraform-providers/terraform-provider-google-beta +var outputPath = flag.String("output", "", "path to output generated files to") + +// Example usage: --version beta +var version = flag.String("version", "", "optional version name. If specified, this version is preferred for resource generation when applicable") + func main() { - // TODO Q2: parse flags - var version = "beta" - var outputPath = "." + flag.Parse() var generateCode = true var generateDocs = true - log.Printf("Initiating go MM compiler") + if outputPath == nil || *outputPath == "" { + log.Fatalf("No output path specified") + } + + if version == nil || *version == "" { + log.Fatalf("No version specified") + } // TODO Q1: allow specifying one product (flag or hardcoded) // var productsToGenerate []string @@ -51,8 +64,8 @@ func main() { log.Fatalf("No product.yaml file found.") } - log.Printf("Generating MM output to '%s'", outputPath) - log.Printf("Using %s version", version) + log.Printf("Generating MM output to '%s'", *outputPath) + log.Printf("Using %s version", *version) // Building compute takes a long time and can't be parallelized within the product // so lets build it first @@ -93,8 +106,8 @@ func main() { // prod, _ := json.Marshal(productApi) // log.Printf("prod %s", string(prod)) - if !productApi.ExistsAtVersionOrLower(version) { - log.Printf("%s does not have a '%s' version, skipping", productName, version) + if !productApi.ExistsAtVersionOrLower(*version) { + log.Printf("%s does not have a '%s' version, skipping", productName, *version) continue } @@ -132,7 +145,7 @@ func main() { } // TODO Q2: override resources - log.Printf("resources before sorting %#v", resources) + // log.Printf("resources before sorting %#v", resources) // Sort resources by name sort.Slice(resources, func(i, j int) bool { @@ -143,7 +156,7 @@ func main() { productApi.Validate() // TODO Q2: set other providers via flag - providerToGenerate := provider.NewTerraform(productApi) + providerToGenerate := provider.NewTerraform(productApi, *version) if !slices.Contains(productsToGenerate, productName) { log.Printf("%s not specified, skipping generation", productName) @@ -151,7 +164,7 @@ func main() { } log.Printf("%s: Generating files", productName) - providerToGenerate.Generate(outputPath, productName, generateCode, generateDocs) + providerToGenerate.Generate(*outputPath, productName, generateCode, generateDocs) } // TODO Q2: copy common files diff --git a/mmv1/provider/template_data.go b/mmv1/provider/template_data.go new file mode 100644 index 000000000000..23ee5ebffd12 --- /dev/null +++ b/mmv1/provider/template_data.go @@ -0,0 +1,195 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package provider + +import ( + "bytes" + "fmt" + "go/format" + "log" + "os" + "strings" + + "text/template" + + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" + "github.com/golang/glog" +) + +type TemplateData struct { + // include Compile::Core + + OutputFolder string + Version product.Version + + TerraformResourceDirectory string + TerraformProviderModule string + + // TODO Q2: is this needed? + // # Information about the local environment + // # (which formatters are enabled, start-time) + // attr_accessor :env +} + +var TemplateFunctions = template.FuncMap{ + "title": strings.Title, + // "patternToRegex": PatternToRegex, + "replace": strings.Replace, + // "isLastIndex": isLastIndex, + // "escapeDescription": escapeDescription, + // "shouldAllowForwardSlashInFormat": shouldAllowForwardSlashInFormat, +} + +var GA_VERSION = "ga" +var BETA_VERSION = "beta" +var ALPHA_VERSION = "alpha" + +func NewTemplateData(outputFolder string, version product.Version) *TemplateData { + td := TemplateData{OutputFolder: outputFolder, Version: version} + + if version.Name == GA_VERSION { + td.TerraformResourceDirectory = "google" + td.TerraformProviderModule = "github.com/hashicorp/terraform-provider-google/google" + } else if version.Name == ALPHA_VERSION { + td.TerraformResourceDirectory = "google-private" + td.TerraformProviderModule = "internal/terraform-next" + } else { + td.TerraformResourceDirectory = "google-beta" + td.TerraformProviderModule = "github.com/hashicorp/terraform-provider-google-beta" + } + + return &td +} + +func (td *TemplateData) GenerateResourceFile(filePath string, resource api.Resource) { + + log.Printf("Generating %s", filePath) + + tmpl, err := template.New("resource.go.tmpl").Funcs(TemplateFunctions).ParseFiles( + "templates/terraform/resource.go.tmpl", + ) + if err != nil { + glog.Exit(err) + } + + contents := bytes.Buffer{} + if err = tmpl.ExecuteTemplate(&contents, "resource.go.tmpl", resource); err != nil { + glog.Exit(err) + } + + if err != nil { + glog.Exit(err) + } + + formatted, err := td.FormatSource(&contents) + if err != nil { + glog.Error(fmt.Errorf("error formatting %s", filePath)) + } + + err = os.WriteFile(filePath, formatted, 0644) + if err != nil { + glog.Exit(err) + } +} + +func (td *TemplateData) GenerateDocumentationFile(filePath string, resource api.Resource) { + +} + +// # path is the output name of the file +// # template is used to determine metadata about the file based on how it is +// # generated +// def format_output_file(path, template) +// return unless path.end_with?('.go') && @env[:goformat_enabled] + +// run_formatter("gofmt -w -s #{path}") +// run_formatter("goimports -w #{path}") unless template.include?('third_party/terraform') +// end + +// def run_formatter(command) +// output = %x(#{command} 2>&1) +// Google::LOGGER.error output unless $CHILD_STATUS.to_i.zero? +// end + +// def relative_path(target, base) +// Pathname.new(target).relative_path_from(Pathname.new(base)) +// end +// end + +// # Responsible for compiling provider-level files, rather than product-specific ones +// class ProviderFileTemplate < Provider::FileTemplate +// # All the products that are being compiled with the provider on this run +// attr_accessor :products + +// # Optional path to the directory where overrides reside. Used to locate files +// # outside of the MM root directory +// attr_accessor :override_path + +// def initialize(output_folder, version, env, products, override_path = nil) +// super() + +// @output_folder = output_folder +// @version = version +// @env = env +// @products = products +// @override_path = override_path +// end +// end + +// # Responsible for generating a file in the context of a product +// # with a given set of parameters. +// class ProductFileTemplate < Provider::FileTemplate +// # The name of the resource +// attr_accessor :name +// # The resource itself. +// attr_accessor :object +// # The entire API object. +// attr_accessor :product + +// class << self +// # Construct a new ProductFileTemplate based on a resource object +// def file_for_resource(output_folder, object, version, env) +// file_template = new(output_folder, object.name, object.__product, version, env) +// file_template.object = object +// file_template +// end +// end + +// def initialize(output_folder, name, product, version, env) +// super() + +// @name = name +// @product = product +// @output_folder = output_folder +// @version = version +// @env = env +// end +// end +// end + +func (td *TemplateData) FormatSource(source *bytes.Buffer) ([]byte, error) { + sourceByte := source.Bytes() + // Replace import path based on version (beta/alpha) + if td.TerraformResourceDirectory != "google" { + sourceByte = bytes.Replace(sourceByte, []byte("github.com/hashicorp/terraform-provider-google/google"), []byte(td.TerraformProviderModule+"/"+td.TerraformResourceDirectory), -1) + } + + output, err := format.Source(sourceByte) + if err != nil { + return []byte(source.String()), err + } + + return output, nil +} diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index fb620c1ddce5..54a91b38f208 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -14,9 +14,15 @@ package provider import ( + "fmt" "log" + "os" + "path" + "strings" "github.com/GoogleCloudPlatform/magic-modules/mmv1/api" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" ) const TERRAFORM_PROVIDER_GA = "github.com/hashicorp/terraform-provider-google" @@ -32,52 +38,159 @@ type Terraform struct { IAMResourceCount int ResourcesForVersion []api.Resource + + TargetVersionName string + + Version product.Version + + Product api.Product } -func NewTerraform(product *api.Product) *Terraform { - t := Terraform{ResourceCount: 0, IAMResourceCount: 0} +func NewTerraform(product *api.Product, versionName string) *Terraform { + t := Terraform{ + ResourceCount: 0, + IAMResourceCount: 0, + Product: *product, + TargetVersionName: versionName, + Version: *product.VersionObjOrClosest(versionName)} - // TODO Q1 - // @target_version_name = version_name - // - // @version = @api.version_obj_or_closest(version_name) - // @api.set_properties_based_on_version(@version) + t.Product.SetPropertiesBasedOnVersion(&t.Version) return &t } -// -// # Main entry point for generation. -// def generate(output_folder, types, product_path, dump_yaml, generate_code, generate_docs) +func (t *Terraform) Generate(outputFolder, productPath string, generateCode, generateDocs bool) { + if err := os.MkdirAll(outputFolder, os.ModePerm); err != nil { + log.Println(fmt.Errorf("error creating output directory %v: %v", outputFolder, err)) + } -// end + t.GenerateObjects(outputFolder, generateCode, generateDocs) -func (t *Terraform) Generate(outputFolder, productPath string, generateCode, generateDocs bool) { - log.Printf("Generate function called with %s %s %t %t", outputFolder, productPath, generateCode, generateDocs) + if generateCode { + t.GenerateOperation(outputFolder) + } +} + +func (t *Terraform) GenerateObjects(outputFolder string, generateCode, generateDocs bool) { + for _, object := range t.Product.Objects { + // TODO Q2: Exclude objects + // if !types.empty? && !types.include?(object.name) + // Google::LOGGER.info "Excluding #{object.name} per user request" + // elsif types.empty? && object.exclude + // Google::LOGGER.info "Excluding #{object.name} per API catalog" + // elsif types.empty? && object.not_in_version?(@version) + // Google::LOGGER.info "Excluding #{object.name} per API version" + // else + // Google::LOGGER.info "Generating #{object.name}" + // # exclude_if_not_in_version must be called in order to filter out + // # beta properties that are nested within GA resources + // object.exclude_if_not_in_version!(@version) + // + // # Make object immutable. + // object.freeze + // object.all_user_properties.each(&:freeze) - // TODO Q1 - // generate_objects(output_folder, types, generate_code, generate_docs) + t.GenerateObject(*object, outputFolder, t.TargetVersionName, generateCode, generateDocs) + } +} + +func (t *Terraform) GenerateObject(object api.Resource, outputFolder, productPath string, generateCode, generateDocs bool) { + + templateData := NewTemplateData(outputFolder, t.Version) + + if !object.ExcludeResource { + log.Printf("Generating %s resource", object.Name) + t.GenerateResource(object, *templateData, outputFolder, generateCode, generateDocs) + + if generateCode { + log.Printf("Generating %s tests", object.Name) + // TODO Q2 + // generate_resource_tests(pwd, data.clone) + // generate_resource_sweepers(pwd, data.clone) + } + } + + // TODO Q2 + // # if iam_policy is not defined or excluded, don't generate it + // return if object.iam_policy.nil? || object.iam_policy.exclude // - // FileUtils.mkpath output_folder - // pwd = Dir.pwd - // if generate_code - // Dir.chdir output_folder + // FileUtils.mkpath output_folder + // Dir.chdir output_folder + // Google::LOGGER.debug "Generating #{object.name} IAM policy" + // generate_iam_policy(pwd, data.clone, generate_code, generate_docs) + // Dir.chdir pwd // - // generate_operation(pwd, output_folder, types) - // Dir.chdir pwd - // end + // end +} + +func (t *Terraform) GenerateResource(object api.Resource, templateData TemplateData, outputFolder string, generateCode, generateDocs bool) { + if generateCode { + productName := t.Product.ApiName + targetFolder := path.Join(outputFolder, t.FolderName(), "services", productName) + + if err := os.MkdirAll(targetFolder, os.ModePerm); err != nil { + log.Println(fmt.Errorf("error creating parent directory %v: %v", targetFolder, err)) + } + + targetFilePath := path.Join(targetFolder, fmt.Sprintf("resource_%s.go", t.FullResourceName(object))) + + templateData.GenerateResourceFile(targetFilePath, object) + } + + if generateDocs { + templateData.GenerateDocumentationFile(outputFolder, object) + } +} + +func (t *Terraform) GenerateOperation(outputFolder string) { + + // TODO Q2 + // def generate_operation(pwd, output_folder, _types) + // return if @api.objects.select(&:autogen_async).empty? // - // # Write a file with the final version of the api, after overrides - // # have been applied. - // return unless dump_yaml + // product_name = @api.api_name + // product_name_underscore = @api.name.underscore + // data = build_object_data(pwd, @api.objects.first, output_folder, @target_version_name) // - // raise 'Path to output the final yaml was not specified.' \ - // if product_path.nil? || product_path == '' + // data.object = @api.objects.select(&:autogen_async).first // - // File.open("#{product_path}/final_api.yaml", 'w') do |file| - // file.write("# This is a generated file, its contents will be overwritten.\n") - // file.write(YAML.dump(@api)) - // end + // data.async = data.object.async + // target_folder = File.join(folder_name(data.version), 'services', product_name) + // FileUtils.mkpath target_folder + // data.generate(pwd, + // 'templates/terraform/operation.go.erb', + // "#{target_folder}/#{product_name_underscore}_operation.go", + // self) + // end +} + +func (t *Terraform) FolderName() string { + if t.Version.Name == "ga" { + return "google" + } + return "google-beta" +} + +func (t *Terraform) FullResourceName(object api.Resource) string { + if object.LegacyName != "" { + return strings.Replace(object.LegacyName, "google_", "", 1) + } + + var name string + if object.FilenameOverride != "" { + name = object.FilenameOverride + } else { + name = google.Underscore(object.Name) + } + + var productName string + if t.Product.LegacyName != "" { + productName = t.Product.LegacyName + } else { + productName = google.Underscore(t.Product.Name) + } + + return fmt.Sprintf("%s_%s", productName, name) } // @@ -325,66 +438,6 @@ func (t *Terraform) Generate(outputFolder, productPath string, generateCode, gen // services // end // -// def generate_objects(output_folder, types, generate_code, generate_docs) -// (@api.objects || []).each do |object| -// if !types.empty? && !types.include?(object.name) -// Google::LOGGER.info "Excluding #{object.name} per user request" -// elsif types.empty? && object.exclude -// Google::LOGGER.info "Excluding #{object.name} per API catalog" -// elsif types.empty? && object.not_in_version?(@version) -// Google::LOGGER.info "Excluding #{object.name} per API version" -// else -// Google::LOGGER.info "Generating #{object.name}" -// # exclude_if_not_in_version must be called in order to filter out -// # beta properties that are nested within GA resources -// object.exclude_if_not_in_version!(@version) -// -// # Make object immutable. -// object.freeze -// object.all_user_properties.each(&:freeze) -// -// generate_object object, output_folder, @target_version_name, generate_code, generate_docs -// end -// # Uncomment for go YAML -// # generate_object_modified object, output_folder, @target_version_name -// end -// end -// -// def generate_object(object, output_folder, version_name, generate_code, generate_docs) -// pwd = Dir.pwd -// data = build_object_data(pwd, object, output_folder, version_name) -// unless object.exclude_resource -// FileUtils.mkpath output_folder -// Dir.chdir output_folder -// Google::LOGGER.debug "Generating #{object.name} resource" -// generate_resource(pwd, data.clone, generate_code, generate_docs) -// if generate_code -// Google::LOGGER.debug "Generating #{object.name} tests" -// generate_resource_tests(pwd, data.clone) -// generate_resource_sweepers(pwd, data.clone) -// end -// Dir.chdir pwd -// end -// # if iam_policy is not defined or excluded, don't generate it -// return if object.iam_policy.nil? || object.iam_policy.exclude -// -// FileUtils.mkpath output_folder -// Dir.chdir output_folder -// Google::LOGGER.debug "Generating #{object.name} IAM policy" -// generate_iam_policy(pwd, data.clone, generate_code, generate_docs) -// Dir.chdir pwd -// end -// -// def generate_object_modified(object, output_folder, version_name) -// pwd = Dir.pwd -// data = build_object_data(pwd, object, output_folder, version_name) -// FileUtils.mkpath output_folder -// Dir.chdir output_folder -// Google::LOGGER.debug "Generating #{object.name} rewrite yaml" -// generate_newyaml(pwd, data.clone) -// Dir.chdir pwd -// end -// // def generate_newyaml(pwd, data) // # @api.api_name is the service folder name // product_name = @api.api_name @@ -720,25 +773,6 @@ func (t *Terraform) Generate(outputFolder, productPath string, generateCode, gen // version == 'ga' ? 'google' : "google-#{version}" // end // -// # This function uses the resource.erb template to create one file -// # per resource. The resource.erb template forms the basis of a single -// # GCP Resource on Terraform. -// def generate_resource(pwd, data, generate_code, generate_docs) -// if generate_code -// # @api.api_name is the service folder name -// product_name = @api.api_name -// target_folder = File.join(folder_name(data.version), 'services', product_name) -// FileUtils.mkpath target_folder -// data.generate(pwd, -// '/templates/terraform/resource.erb', -// "#{target_folder}/resource_#{full_resource_name(data)}.go", -// self) -// end -// -// return unless generate_docs -// -// generate_documentation(pwd, data) -// end // // def generate_documentation(pwd, data) // target_folder = data.output_folder @@ -786,24 +820,6 @@ func (t *Terraform) Generate(outputFolder, productPath string, generateCode, gen // self) // end // -// def generate_operation(pwd, output_folder, _types) -// return if @api.objects.select(&:autogen_async).empty? -// -// product_name = @api.api_name -// product_name_underscore = @api.name.underscore -// data = build_object_data(pwd, @api.objects.first, output_folder, @target_version_name) -// -// data.object = @api.objects.select(&:autogen_async).first -// -// data.async = data.object.async -// target_folder = File.join(folder_name(data.version), 'services', product_name) -// FileUtils.mkpath target_folder -// data.generate(pwd, -// 'templates/terraform/operation.go.erb', -// "#{target_folder}/#{product_name_underscore}_operation.go", -// self) -// end -// // # Generate the IAM policy for this object. This is used to query and test // # IAM policies separately from the resource itself // def generate_iam_policy(pwd, data, generate_code, generate_docs) @@ -850,15 +866,6 @@ func (t *Terraform) Generate(outputFolder, productPath string, generateCode, gen // data.generate(pwd, 'templates/terraform/datasource_iam.html.markdown.erb', filepath, self) // end // -// def build_object_data(_pwd, object, output_folder, version) -// TerraformProductFileTemplate.file_for_resource( -// output_folder, -// object, -// version, -// build_env -// ) -// end -// // def extract_identifiers(url) // url.scan(/\{\{%?(\w+)\}\}/).flatten // end @@ -870,15 +877,6 @@ func (t *Terraform) Generate(outputFolder, productPath string, generateCode, gen // object.id_format || object.self_link_uri // end // -// def full_resource_name(data) -// if data.object.legacy_name -// data.object.legacy_name.sub(/^google_/, '') -// else -// name = data.object.filename_override || data.object.name.underscore -// product_name = data.product.legacy_name || data.product.name.underscore -// "#{product_name}_#{name}" -// end -// end // // # Returns the extension for DCL packages for the given version. This is needed // # as the DCL uses "alpha" for preview resources, while we use "private" diff --git a/mmv1/templates/terraform/resource.go.tmpl b/mmv1/templates/terraform/resource.go.tmpl new file mode 100644 index 000000000000..70ce7a03e4ea --- /dev/null +++ b/mmv1/templates/terraform/resource.go.tmpl @@ -0,0 +1,31 @@ +{{- /* Copyright 2024 Google LLC. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ -}} +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// 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. +// +// ---------------------------------------------------------------------------- + +// {{$.ProductMetadata.Name}} {{$.Name}} \ No newline at end of file diff --git a/mmv1/templates/terraform/resource.html.markdown.tmpl b/mmv1/templates/terraform/resource.html.markdown.tmpl new file mode 100644 index 000000000000..80a5c85d93dd --- /dev/null +++ b/mmv1/templates/terraform/resource.html.markdown.tmpl @@ -0,0 +1,30 @@ +{{- /* Copyright 2024 Google LLC. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ -}} +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** Type: MMv1 *** +# +# ---------------------------------------------------------------------------- +# +# 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. +# +# ---------------------------------------------------------------------------- + +{{$.ProductMetadata.Name}} {{$.Name}} +--- From 3b9c61bd50c271e769a6cb81dbd28d5ba7512c15 Mon Sep 17 00:00:00 2001 From: kautikdk <144651627+kautikdk@users.noreply.github.com> Date: Tue, 19 Mar 2024 18:04:35 +0000 Subject: [PATCH 52/59] Adds support for Soft Delete feature, which allows setting soft delete policy on 'google_storage_bucket' resource. (#10171) --- .../storage/resource_storage_bucket.go.erb | 63 +++++++++++++++- .../resource_storage_bucket_test.go.erb | 74 +++++++++++++++++++ .../docs/r/storage_bucket.html.markdown | 8 ++ 3 files changed, 144 insertions(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.erb b/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.erb index ed7422389d82..fc17d08790b8 100644 --- a/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.erb +++ b/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.erb @@ -482,6 +482,28 @@ func ResourceStorageBucket() *schema.Resource { Computed: true, Description: `Prevents public access to a bucket.`, }, + "soft_delete_policy": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: `The bucket's soft delete policy, which defines the period of time that soft-deleted objects will be retained, and cannot be permanently deleted. If it is not provided, by default Google Cloud Storage sets this to default soft delete policy`, + Elem : &schema.Resource{ + Schema: map[string]*schema.Schema{ + "retention_duration_seconds": { + Type: schema.TypeInt, + Default: 604800, + Optional: true, + Description: `The duration in seconds that soft-deleted objects in the bucket will be retained and cannot be permanently deleted. Default value is 604800.`, + }, + "effective_time": { + Type: schema.TypeString, + Computed: true, + Description: `Server-determined value that indicates the time from which the policy, or one with a greater retention, was effective. This value is in RFC 3339 format.`, + }, + }, + }, + }, }, UseJSONNumber: true, } @@ -612,6 +634,10 @@ func resourceStorageBucketCreate(d *schema.ResourceData, meta interface{}) error sb.Rpo = v.(string) } + if v, ok := d.GetOk("soft_delete_policy"); ok { + sb.SoftDeletePolicy = expandBucketSoftDeletePolicy(v.([]interface{})) + } + var res *storage.Bucket err = transport_tpg.Retry(transport_tpg.RetryOptions{ @@ -784,6 +810,12 @@ func resourceStorageBucketUpdate(d *schema.ResourceData, meta interface{}) error } } + if d.HasChange("soft_delete_policy") { + if v, ok := d.GetOk("soft_delete_policy"); ok { + sb.SoftDeletePolicy = expandBucketSoftDeletePolicy(v.([]interface{})) + } + } + res, err := config.NewStorageClient(userAgent).Buckets.Patch(d.Get("name").(string), sb).Do() if err != nil { return err @@ -1166,6 +1198,32 @@ func flattenBucketObjectRetention(bucketObjectRetention *storage.BucketObjectRet return false } +func expandBucketSoftDeletePolicy(configured interface{}) *storage.BucketSoftDeletePolicy{ + configuredSoftDeletePolicies := configured.([]interface{}) + if len(configuredSoftDeletePolicies) == 0 { + return nil + } + configuredSoftDeletePolicy := configuredSoftDeletePolicies[0].(map[string]interface{}) + softDeletePolicy := &storage.BucketSoftDeletePolicy{ + RetentionDurationSeconds: int64(configuredSoftDeletePolicy["retention_duration_seconds"].(int)), + } + softDeletePolicy.ForceSendFields=append(softDeletePolicy.ForceSendFields,"RetentionDurationSeconds") + return softDeletePolicy +} + +func flattenBucketSoftDeletePolicy(softDeletePolicy *storage.BucketSoftDeletePolicy) []map[string]interface{} { + policies := make([]map[string]interface{}, 0, 1) + if softDeletePolicy == nil { + return policies + } + policy := map[string]interface{}{ + "retention_duration_seconds": softDeletePolicy.RetentionDurationSeconds, + "effective_time": softDeletePolicy.EffectiveTime, + } + policies = append(policies, policy) + return policies +} + func expandBucketVersioning(configured interface{}) *storage.BucketVersioning { versionings := configured.([]interface{}) if len(versionings) == 0 { @@ -1689,7 +1747,7 @@ func setStorageBucket(d *schema.ResourceData, config *transport_tpg.Config, res } // lifecycle_rule contains terraform only variable no_age. // Passing config("d") to flattener function to set no_age separately. - if err := d.Set("lifecycle_rule", flattenBucketLifecycle(d,res.Lifecycle)); err != nil { + if err := d.Set("lifecycle_rule", flattenBucketLifecycle(d, res.Lifecycle)); err != nil { return fmt.Errorf("Error setting lifecycle_rule: %s", err) } if err := tpgresource.SetLabels(res.Labels, d, "labels"); err != nil { @@ -1717,6 +1775,9 @@ func setStorageBucket(d *schema.ResourceData, config *transport_tpg.Config, res return fmt.Errorf("Error setting RPO setting : %s", err) } } + if err := d.Set("soft_delete_policy", flattenBucketSoftDeletePolicy(res.SoftDeletePolicy)); err != nil { + return fmt.Errorf("Error setting soft_delete_policy: %s", err) + } if res.IamConfiguration != nil && res.IamConfiguration.UniformBucketLevelAccess != nil { if err := d.Set("uniform_bucket_level_access", res.IamConfiguration.UniformBucketLevelAccess.Enabled); err != nil { return fmt.Errorf("Error setting uniform_bucket_level_access: %s", err) diff --git a/mmv1/third_party/terraform/services/storage/resource_storage_bucket_test.go.erb b/mmv1/third_party/terraform/services/storage/resource_storage_bucket_test.go.erb index f62447cb399e..22ef2baecef6 100644 --- a/mmv1/third_party/terraform/services/storage/resource_storage_bucket_test.go.erb +++ b/mmv1/third_party/terraform/services/storage/resource_storage_bucket_test.go.erb @@ -1338,6 +1338,66 @@ func TestAccStorageBucket_retentionPolicyLocked(t *testing.T) { }) } +func TestAccStorageBucket_SoftDeletePolicy(t *testing.T) { + t.Parallel() + + var bucket storage.Bucket + bucketName := fmt.Sprintf("tf-test-acc-bucket-%d", acctest.RandInt(t)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccStorageBucketDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccStorageBucket_basic(bucketName), + Check: resource.ComposeTestCheckFunc( + testAccCheckStorageBucketExists( + t, "google_storage_bucket.bucket", bucketName, &bucket), + resource.TestCheckResourceAttr( + "google_storage_bucket.bucket", "soft_delete_policy.0.retention_duration_seconds", "604800"), + ), + }, + { + ResourceName: "google_storage_bucket.bucket", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy"}, + }, + { + Config: testAccStorageBucket_SoftDeletePolicy(bucketName,7776000), + Check: resource.ComposeTestCheckFunc( + testAccCheckStorageBucketExists( + t, "google_storage_bucket.bucket", bucketName, &bucket), + resource.TestCheckResourceAttr( + "google_storage_bucket.bucket", "soft_delete_policy.0.retention_duration_seconds", "7776000"), + ), + }, + { + ResourceName: "google_storage_bucket.bucket", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy"}, + }, + { + Config: testAccStorageBucket_SoftDeletePolicy(bucketName,0), + Check: resource.ComposeTestCheckFunc( + testAccCheckStorageBucketExists( + t, "google_storage_bucket.bucket", bucketName, &bucket), + resource.TestCheckResourceAttr( + "google_storage_bucket.bucket", "soft_delete_policy.0.retention_duration_seconds", "0"), + ), + }, + { + ResourceName: "google_storage_bucket.bucket", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy"}, + }, + }, + }) +} + func testAccCheckStorageBucketExists(t *testing.T, n string, bucketName string, bucket *storage.Bucket) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -2264,6 +2324,20 @@ resource "google_storage_bucket" "bucket" { `, bucketName) } +func testAccStorageBucket_SoftDeletePolicy(bucketName string, duration int) string { + return fmt.Sprintf(` +resource "google_storage_bucket" "bucket" { + name = "%s" + location = "US" + force_destroy = true + + soft_delete_policy { + retention_duration_seconds = %d + } +} +`, bucketName, duration) +} + func testAccStorageBucket_websiteNoAttributes(bucketName string) string { return fmt.Sprintf(` resource "google_storage_bucket" "website" { diff --git a/mmv1/third_party/terraform/website/docs/r/storage_bucket.html.markdown b/mmv1/third_party/terraform/website/docs/r/storage_bucket.html.markdown index 2389ac04bf55..58e1e1cf5056 100644 --- a/mmv1/third_party/terraform/website/docs/r/storage_bucket.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/storage_bucket.html.markdown @@ -133,6 +133,8 @@ The following arguments are supported: * `custom_placement_config` - (Optional) The bucket's custom location configuration, which specifies the individual regions that comprise a dual-region bucket. If the bucket is designated a single or multi-region, the parameters are empty. Structure is [documented below](#nested_custom_placement_config). +* `soft_delete_policy` - (Optional, Computed) The bucket's soft delete policy, which defines the period of time that soft-deleted objects will be retained, and cannot be permanently deleted. If the block is not provided, Server side value will be kept which means removal of block won't generate any terraform change. Structure is [documented below](#nested_soft_delete_policy). + The `lifecycle_rule` block supports: * `action` - (Required) The Lifecycle Rule's action configuration. A single block of this type is supported. Structure is [documented below](#nested_action). @@ -233,6 +235,12 @@ The following arguments are supported: * `data_locations` - (Required) The list of individual regions that comprise a dual-region bucket. See [Cloud Storage bucket locations](https://cloud.google.com/storage/docs/dual-regions#availability) for a list of acceptable regions. **Note**: If any of the data_locations changes, it will [recreate the bucket](https://cloud.google.com/storage/docs/locations#key-concepts). +The `soft_delete_policy` block supports: + +* `retention_duration_seconds` - (Optional, Default: 604800) The duration in seconds that soft-deleted objects in the bucket will be retained and cannot be permanently deleted. Default value is 604800. The value must be in between 604800(7 days) and 7776000(90 days). **Note**: To disable the soft delete policy on a bucket, This field must be set to 0. + +* `effective_time` - (Computed) Server-determined value that indicates the time from which the policy, or one with a greater retention, was effective. This value is in RFC 3339 format. + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are From f4abf45f154501fe04509c2da704ac0dc0d4400e Mon Sep 17 00:00:00 2001 From: Salome Papiashvili Date: Tue, 19 Mar 2024 19:35:34 +0100 Subject: [PATCH 53/59] Fixes and enhancements after the bug bash. (#10223) * remove float from documentation * change storage-gb type to int * Revert "change storage-gb type to int" This reverts commit 89795a80889287fb287497fbcbbfdbb365d40884. * add support for dag_processor count * fix int64 unpacking * add validation for composer internal ip range size * add upper limit for dag_prcessor.count --- .../resource_composer_environment.go.erb | 26 +++++++++++++++++++ .../resource_composer_environment_test.go.erb | 2 ++ .../docs/r/composer_environment.html.markdown | 4 +-- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.erb b/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.erb index e192b510fa65..2a2f0b545757 100644 --- a/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.erb +++ b/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.erb @@ -3,6 +3,7 @@ package composer import ( "fmt" + "net" "log" "regexp" "strings" @@ -390,6 +391,7 @@ func ResourceComposerEnvironment() *schema.Resource { Computed: true, Optional: true, ForceNew: true, + ValidateFunc: validateComposerInternalIpv4CidrBlock, Description: `IPv4 cidr range that will be used by Composer internal components.`, }, <% end -%> @@ -969,6 +971,14 @@ func ResourceComposerEnvironment() *schema.Resource { ValidateFunc: validation.FloatAtLeast(0), Description: `Storage (GB) request and limit for DAG processor.`, }, + "count": { + Type: schema.TypeInt, + Optional: true, + ForceNew: false, + Computed: true, + ValidateFunc: validation.IntBetween(0, 3), + Description: `Number of DAG processors.`, + }, }, }, }, @@ -1887,6 +1897,7 @@ func flattenComposerEnvironmentConfigWorkloadsConfig(workloadsConfig *composer.W transformedDagProcessor["cpu"] = wlCfgDagProcessor.Cpu transformedDagProcessor["memory_gb"] = wlCfgDagProcessor.MemoryGb transformedDagProcessor["storage_gb"] = wlCfgDagProcessor.StorageGb + transformedDagProcessor["count"] = wlCfgDagProcessor.Count } <% end -%> @@ -2398,6 +2409,7 @@ func expandComposerEnvironmentConfigWorkloadsConfig(v interface{}, d *schema.Res transformedDagProcessor.Cpu = originalDagProcessorRaw["cpu"].(float64) transformedDagProcessor.MemoryGb = originalDagProcessorRaw["memory_gb"].(float64) transformedDagProcessor.StorageGb = originalDagProcessorRaw["storage_gb"].(float64) + transformedDagProcessor.Count = int64(originalDagProcessorRaw["count"].(int)) transformed.DagProcessor = transformedDagProcessor } } @@ -3096,4 +3108,18 @@ func versionValidationCustomizeDiffFunc(ctx context.Context, d *schema.ResourceD } } return nil +} + +func validateComposerInternalIpv4CidrBlock(v any, k string) (warns []string, errs []error) { + cidr_range := v.(string) + _, ip_net, err := net.ParseCIDR(cidr_range) + if err != nil { + errs = append(errs, fmt.Errorf("Invalid CIDR range: %s", err)) + return + } + ones, _ := ip_net.Mask.Size() + if ones != 20 { + errs = append(errs, fmt.Errorf("Composer Internal IPv4 CIDR range must have size /20")) + } + return } \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb b/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb index bde25f487b1f..e2ee2668fb80 100644 --- a/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb +++ b/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb @@ -3159,6 +3159,7 @@ resource "google_composer_environment" "test" { cpu = 1 memory_gb = 2.5 storage_gb = 2 + count = 1 } } enable_private_environment = true @@ -3202,6 +3203,7 @@ resource "google_composer_environment" "test" { cpu = 2 memory_gb = 2 storage_gb = 1 + count = 2 } } enable_private_environment = false diff --git a/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown b/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown index 81865ec37908..e46ad1f6a9ed 100644 --- a/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown @@ -1371,7 +1371,7 @@ The `worker` block supports: (Optional) The amount of memory (GB) for a single Airflow worker. -* `float storage_gb` +* `storage_gb` (Optional) The amount of storage (GB) for a single Airflow worker. @@ -1396,7 +1396,7 @@ The `dag_processor` block supports: (Optional) Memory (GB) request and limit for DAG processor. -* `float storage_gb` +* `storage_gb` (Optional) Storage (GB) request and limit for DAG processor. From cbd78670f83239f1029a12684b856f5b0a0c63c6 Mon Sep 17 00:00:00 2001 From: Daniel Randell Date: Tue, 19 Mar 2024 19:00:25 +0000 Subject: [PATCH 54/59] google_monitoring_alert_policy periods doc update & dataproc doc update (#10226) * enable_http_port_access is a boolean not a string * add doc update to alert policy notification rate limit period --- mmv1/products/monitoring/AlertPolicy.yaml | 1 + .../services/dataproc/resource_dataproc_cluster_test.go.erb | 2 +- .../terraform/website/docs/r/dataproc_cluster.html.markdown | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mmv1/products/monitoring/AlertPolicy.yaml b/mmv1/products/monitoring/AlertPolicy.yaml index d968e2d4ea1c..52e00415e3c2 100644 --- a/mmv1/products/monitoring/AlertPolicy.yaml +++ b/mmv1/products/monitoring/AlertPolicy.yaml @@ -926,6 +926,7 @@ properties: name: period description: | Not more than one notification per period. + A duration in seconds with up to nine fractional digits, terminated by 's'. Example "60.5s". - !ruby/object:Api::Type::String name: autoClose description: | diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.erb b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.erb index 6c003db6e7b0..0a41895275ba 100644 --- a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.erb @@ -2127,7 +2127,7 @@ resource "google_dataproc_cluster" "with_endpoint_config" { } endpoint_config { - enable_http_port_access = "true" + enable_http_port_access = true } } } diff --git a/mmv1/third_party/terraform/website/docs/r/dataproc_cluster.html.markdown b/mmv1/third_party/terraform/website/docs/r/dataproc_cluster.html.markdown index a09753653a04..796a14b262f8 100644 --- a/mmv1/third_party/terraform/website/docs/r/dataproc_cluster.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/dataproc_cluster.html.markdown @@ -926,7 +926,7 @@ cluster_config { ```hcl cluster_config { endpoint_config { - enable_http_port_access = "true" + enable_http_port_access = true } } ``` From 676288eca33da129da405db05a0b02f6af61011b Mon Sep 17 00:00:00 2001 From: joelkattapuram <46967875+joelkattapuram@users.noreply.github.com> Date: Tue, 19 Mar 2024 12:22:01 -0700 Subject: [PATCH 55/59] Add support for boost configs in workstations configs (#10176) * add boostConfig workstationConfig * add boostConfig workstationConfig * link example * remove * update descriptions and add update test * update machine type * fix update test --- .../workstations/WorkstationConfig.yaml | 39 +++++++++ .../examples/workstation_config_boost.tf.erb | 56 +++++++++++++ ...orkstations_workstation_config_test.go.erb | 79 +++++++++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 mmv1/templates/terraform/examples/workstation_config_boost.tf.erb diff --git a/mmv1/products/workstations/WorkstationConfig.yaml b/mmv1/products/workstations/WorkstationConfig.yaml index 39fada27bca8..65a868209b9a 100644 --- a/mmv1/products/workstations/WorkstationConfig.yaml +++ b/mmv1/products/workstations/WorkstationConfig.yaml @@ -108,6 +108,13 @@ examples: vars: workstation_cluster_name: 'workstation-cluster' workstation_config_name: 'workstation-config' + - !ruby/object:Provider::Terraform::Examples + name: 'workstation_config_boost' + min_version: beta + primary_resource_id: 'default' + vars: + workstation_cluster_name: 'workstation-cluster' + workstation_config_name: 'workstation-config' - !ruby/object:Provider::Terraform::Examples name: 'workstation_config_encryption_key' min_version: beta @@ -213,6 +220,7 @@ properties: - 'host.gceInstance.shieldedInstanceConfig.enableIntegrityMonitoring' - 'host.gceInstance.confidentialInstanceConfig.enableConfidentialCompute' - 'host.gceInstance.accelerators' + - 'host.gceInstance.boostConfigs' - 'host.gceInstance.disableSsh' properties: - !ruby/object:Api::Type::NestedObject @@ -319,6 +327,37 @@ properties: description: | Number of accelerator cards exposed to the instance. required: true + - !ruby/object:Api::Type::Array + name: 'boostConfigs' + description: | + A list of the boost configurations that workstations created using this workstation configuration are allowed to use. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'id' + description: | + The id to be used for the boost config. + required: true + - !ruby/object:Api::Type::String + name: 'machineType' + description: | + The type of machine that boosted VM instances will use—for example, e2-standard-4. For more information about machine types that Cloud Workstations supports, see the list of available machine types https://cloud.google.com/workstations/docs/available-machine-types. Defaults to e2-standard-4. + - !ruby/object:Api::Type::Array + name: 'accelerators' + description: | + An accelerator card attached to the boost instance. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'type' + description: | + Type of accelerator resource to attach to the instance, for example, "nvidia-tesla-p100". + required: true + - !ruby/object:Api::Type::Integer + name: 'count' + description: | + Number of accelerator cards exposed to the instance. + required: true - !ruby/object:Api::Type::Array name: 'persistentDirectories' description: | diff --git a/mmv1/templates/terraform/examples/workstation_config_boost.tf.erb b/mmv1/templates/terraform/examples/workstation_config_boost.tf.erb new file mode 100644 index 000000000000..d498c3eb1281 --- /dev/null +++ b/mmv1/templates/terraform/examples/workstation_config_boost.tf.erb @@ -0,0 +1,56 @@ +resource "google_compute_network" "default" { + provider = google-beta + name = "<%= ctx[:vars]['workstation_cluster_name'] %>" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "default" { + provider = google-beta + name = "<%= ctx[:vars]['workstation_cluster_name'] %>" + ip_cidr_range = "10.0.0.0/24" + region = "us-central1" + network = google_compute_network.default.name +} + +resource "google_workstations_workstation_cluster" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + workstation_cluster_id = "<%= ctx[:vars]['workstation_cluster_name'] %>" + network = google_compute_network.default.id + subnetwork = google_compute_subnetwork.default.id + location = "us-central1" + + labels = { + "label" = "key" + } + + annotations = { + label-one = "value-one" + } +} + +resource "google_workstations_workstation_config" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + workstation_config_id = "<%= ctx[:vars]['workstation_config_name'] %>" + workstation_cluster_id = google_workstations_workstation_cluster.<%= ctx[:primary_resource_id] %>.workstation_cluster_id + location = "us-central1" + + host { + gce_instance { + machine_type = "e2-standard-4" + boot_disk_size_gb = 35 + disable_public_ip_addresses = true + boost_configs { + id = "boost-1" + machine_type = "n1-standard-2" + accelerators { + type = "nvidia-tesla-t4" + count = "1" + } + } + boost_configs { + id = "boost-1" + machine_type = "e2-standard-2" + } + } + } +} diff --git a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb index e29069d6ab11..10839661da72 100644 --- a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb +++ b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb @@ -476,6 +476,80 @@ func testAccWorkstationsWorkstationConfig_serviceAccount(context map[string]inte `, context) } +func TestAccWorkstationsWorkstationConfig_boost(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckWorkstationsWorkstationConfigDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccWorkstationsWorkstationConfig_boost(context), + }, + { + ResourceName: "google_workstations_workstation_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"etag"}, + }, + }, + }) +} + +func testAccWorkstationsWorkstationConfig_boost(context map[string]interface{}) string { + return acctest.Nprintf(` + resource "google_compute_network" "default" { + provider = google-beta + name = "tf-test-workstation-cluster%{random_suffix}" + auto_create_subnetworks = false + } + + resource "google_compute_subnetwork" "default" { + provider = google-beta + name = "tf-test-workstation-cluster%{random_suffix}" + ip_cidr_range = "10.0.0.0/24" + region = "us-central1" + network = google_compute_network.default.name + } + + resource "google_workstations_workstation_cluster" "default" { + provider = google-beta + workstation_cluster_id = "tf-test-workstation-cluster%{random_suffix}" + network = google_compute_network.default.id + subnetwork = google_compute_subnetwork.default.id + location = "us-central1" + } + + resource "google_workstations_workstation_config" "default" { + provider = google-beta + workstation_config_id = "tf-test-workstation-config%{random_suffix}" + workstation_cluster_id = google_workstations_workstation_cluster.default.workstation_cluster_id + location = "us-central1" + host { + gce_instance { + boost_configs { + id = "boost-1" + machine_type = "n1-standard-2" + accelerators { + type = "nvidia-tesla-t4" + count = 1 + } + } + boost_configs { + id = "boost-1" + machine_type = "e2-standard-2" + } + } + } + } +`, context) +} + func TestAccWorkstationsWorkstationConfig_disableTcpConnections(t *testing.T) { t.Parallel() @@ -886,6 +960,11 @@ resource "google_workstations_workstation_config" "default" { confidential_instance_config { enable_confidential_compute = true } + + boost_configs { + id = "boost-1" + machine_type = "n2d-standard-2" + } } } } From d58db7cbcd766462bc0be7d50cd467507fc34899 Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Tue, 19 Mar 2024 13:14:59 -0700 Subject: [PATCH 56/59] Add a rule for removing diff suppress functions (#10167) * Add a rule for removing diff suppress functions * Add rule link to docs --- .../breaking-changes/breaking-changes.md | 2 +- tools/diff-processor/rules/rules_field.go | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/docs/content/develop/breaking-changes/breaking-changes.md b/docs/content/develop/breaking-changes/breaking-changes.md index 0b17be06b890..6e2b93039bb6 100644 --- a/docs/content/develop/breaking-changes/breaking-changes.md +++ b/docs/content/develop/breaking-changes/breaking-changes.md @@ -79,7 +79,7 @@ For more information, see and modifying examples and modules may achieve the intended effect with a smaller blast radius. * Modifying how field data is stored in state * For example, changing the case of a value returned by the API in a flattener or decorder -* Removing diff suppression from a field. +* Removing diff suppression from a field. * For MMv1 resources, removing `diff_suppress_func` from a field. * For handwritten resources, removing `DiffSuppressFunc` from a field. * Removing update support from a field. diff --git a/tools/diff-processor/rules/rules_field.go b/tools/diff-processor/rules/rules_field.go index 1b5645571731..793a768fedf0 100644 --- a/tools/diff-processor/rules/rules_field.go +++ b/tools/diff-processor/rules/rules_field.go @@ -27,6 +27,7 @@ var FieldRules = []FieldRule{ fieldRule_DefaultModification, fieldRule_GrowingMin, fieldRule_ShrinkingMax, + fieldRule_RemovingDiffSuppress, fieldRule_ChangingFieldDataFormat, } @@ -211,6 +212,25 @@ func fieldRule_ShrinkingMax_func(old, new *schema.Schema, mc MessageContext) str return "" } +var fieldRule_RemovingDiffSuppress = FieldRule{ + name: "Removing Diff Suppress Function", + definition: "Diff suppress functions cannot be removed. Otherwise terraform configurations that previously had no diffs would show diffs.", + message: "Field {{field}} lost its diff suppress function", + identifier: "field-removing-diff-suppress", + isRuleBreak: fieldRule_RemovingDiffSuppress_func, +} + +func fieldRule_RemovingDiffSuppress_func(old, new *schema.Schema, mc MessageContext) string { + // ignore for added / removed fields + if old == nil || new == nil { + return "" + } + if old.DiffSuppressFunc != nil && new.DiffSuppressFunc == nil { + return populateMessageContext(mc.message, mc) + } + return "" +} + func fieldRulesToRuleArray(frs []FieldRule) []Rule { var rules []Rule for _, fr := range frs { From 5fddaec1797fd46f5f57241dc878642b5bcf60f2 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Tue, 19 Mar 2024 13:55:00 -0700 Subject: [PATCH 57/59] Rewrite Resource functions (#10228) --- mmv1/api/async.go | 8 +- mmv1/api/product.go | 20 +- mmv1/api/resource.go | 452 ++++++++++++++++++++++++++++++- mmv1/api/resource.rb | 20 -- mmv1/api/timeouts.go | 8 + mmv1/api/type.go | 123 +++++---- mmv1/google/string_utils.go | 51 ++-- mmv1/google/string_utils_test.go | 54 ++++ mmv1/provider/terraform.rb | 8 - 9 files changed, 629 insertions(+), 115 deletions(-) create mode 100644 mmv1/google/string_utils_test.go diff --git a/mmv1/api/async.go b/mmv1/api/async.go index dc4090fe7663..51a740aaffcd 100644 --- a/mmv1/api/async.go +++ b/mmv1/api/async.go @@ -26,7 +26,7 @@ type Async struct { google.YamlValidator // Describes an operation - Operation Operation + Operation *Operation // The list of methods where operations are used. Actions []string @@ -50,7 +50,7 @@ type Operation struct { // Contains information about an long-running operation, to make // requests for the state of an operation. - Timeouts Timeouts + Timeouts *Timeouts Result Result } @@ -79,7 +79,7 @@ type OpAsync struct { // TODO: Should embed Async or not? // < Async - Operation OpAsyncOperation + Operation *OpAsyncOperation Result OpAsyncResult @@ -127,7 +127,7 @@ type OpAsyncOperation struct { WaitMs int `yaml:"wait_ms"` - Timeouts Timeouts + Timeouts *Timeouts // Use this if the resource includes the full operation url. FullUrl string `yaml:"full_url"` diff --git a/mmv1/api/product.go b/mmv1/api/product.go index 5c5b718d8767..e3defe678c82 100644 --- a/mmv1/api/product.go +++ b/mmv1/api/product.go @@ -67,7 +67,7 @@ type Product struct { OperationRetry string `yaml:"operation_retry"` - Async OpAsync + Async *OpAsync LegacyName string `yaml:"legacy_name"` @@ -211,21 +211,21 @@ func (p *Product) SetPropertiesBasedOnVersion(version *product.Version) { p.BaseUrl = version.BaseUrl } -// // ==================== -// // Debugging Methods -// // ==================== +// ==================== +// Debugging Methods +// ==================== // def to_s // // relies on the custom to_json definitions // JSON.pretty_generate(self) // end -// // Prints a dot notation path to where the field is nested within the parent -// // object when called on a property. eg: parent.meta.label.foo -// // Redefined on Product to terminate the calls up the parent chain. -// def lineage -// name -// end +// Prints a dot notation path to where the field is nested within the parent +// object when called on a property. eg: parent.meta.label.foo +// Redefined on Product to terminate the calls up the parent chain. +func (p Product) Lineage() string { + return p.Name +} // def to_json(opts = nil) // json_out = {} diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go index 069c935af0d8..ad71a8eb23e8 100644 --- a/mmv1/api/resource.go +++ b/mmv1/api/resource.go @@ -13,9 +13,14 @@ package api import ( + "fmt" + "strings" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/resource" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" "github.com/GoogleCloudPlatform/magic-modules/mmv1/provider/terraform" + "golang.org/x/exp/slices" ) type Resource struct { @@ -64,13 +69,13 @@ type Resource struct { // ==================== // // [Optional] The "identity" URL of the resource. Defaults to: - // * base_url when the create_verb is :POST - // * self_link when the create_verb is :PUT or :PATCH + // * base_url when the create_verb is POST + // * self_link when the create_verb is PUT or PATCH SelfLink string `yaml:"self_link"` // [Optional] The URL used to creating the resource. Defaults to: - // * collection url when the create_verb is :POST - // * self_link when the create_verb is :PUT or :PATCH + // * collection url when the create_verb is POST + // * self_link when the create_verb is PUT or PATCH CreateUrl string `yaml:"create_url"` // [Optional] The URL used to delete the resource. Defaults to the self @@ -80,16 +85,16 @@ type Resource struct { // [Optional] The URL used to update the resource. Defaults to the self // link. UpdateUrl string `yaml:"update_url"` - // [Optional] The HTTP verb used during create. Defaults to :POST. + // [Optional] The HTTP verb used during create. Defaults to POST. CreateVerb string `yaml:"create_verb"` - // [Optional] The HTTP verb used during read. Defaults to :GET. + // [Optional] The HTTP verb used during read. Defaults to GET. ReadVerb string `yaml:"read_verb"` - // [Optional] The HTTP verb used during update. Defaults to :PUT. + // [Optional] The HTTP verb used during update. Defaults to PUT. UpdateVerb string `yaml:"update_verb"` - // [Optional] The HTTP verb used during delete. Defaults to :DELETE. + // [Optional] The HTTP verb used during delete. Defaults to DELETE. DeleteVerb string `yaml:"delete_verb"` // [Optional] Additional Query Parameters to append to GET. Defaults to "" @@ -204,7 +209,7 @@ type Resource struct { // If true, skip sweeper generation for this resource SkipSweeper bool `yaml:"skip_sweeper"` - Timeouts Timeouts + Timeouts *Timeouts // An array of function names that determine whether an error is retryable. ErrorRetryPredicates []string `yaml:"error_retry_predicates"` @@ -268,6 +273,8 @@ type Resource struct { // Add a deprecation message for a resource that's been deprecated in the API. DeprecationMessage string `yaml:"deprecation_message"` + Async *OpAsync + Properties []*Type Parameters []*Type @@ -294,10 +301,284 @@ func (r *Resource) setResourceMetada(properties []*Type) { } } +// ==================== +// Custom Getters and Setters +// ==================== + +// Returns all properties and parameters including the ones that are +// excluded. This is used for PropertyOverride validation + +// TODO: remove the ruby function name +// def all_properties +func (r Resource) AllProperties() []*Type { + return google.Concat(r.Properties, r.Parameters) +} + +// def properties_with_excluded +func (r Resource) PropertiesWithExcluded() []*Type { + return r.Properties +} + +// def properties +func (r Resource) UserProperites() []*Type { + return google.Reject(r.Properties, func(p *Type) bool { + return p.Exclude + }) +} + +// def parameters +func (r Resource) UserParameters() []*Type { + return google.Reject(r.Parameters, func(p *Type) bool { + return p.Exclude + }) +} + +// Return the user-facing properties in client tools; this ends up meaning +// both properties and parameters but without any that are excluded due to +// version mismatches or manual exclusion + +// def all_user_properties +func (r Resource) AllUserProperties() []*Type { + return google.Concat(r.UserProperites(), r.UserParameters()) +} + +// def required_properties +func (r Resource) RequiredProperties() []*Type { + return google.Select(r.AllUserProperties(), func(p *Type) bool { + return p.Required + }) +} + +// def all_nested_properties(props) +func allNestedProperties(props []*Type) []*Type { + nested := props + for _, prop := range props { + if nestedProperties := prop.NestedProperties(); !prop.FlattenObject && nestedProperties != nil { + nested = google.Concat(nested, allNestedProperties(nestedProperties)) + } + } + + return nested +} + +// sensitive_props +func (r Resource) SensitiveProps() []*Type { + props := allNestedProperties(r.RootProperties()) + return google.Select(props, func(p *Type) bool { + return p.Sensitive + }) +} + +// All settable properties in the resource. +// Fingerprints aren't *really" settable properties, but they behave like one. +// At Create, they have no value but they can just be read in anyways, and after a Read +// they will need to be set in every Update. + +// def settable_properties +func (r Resource) settableProperties() []*Type { + props := make([]*Type, 0) + + props = google.Reject(r.AllUserProperties(), func(v *Type) bool { + return v.Output && !v.IsA("Fingerprint") && !v.IsA("KeyValueEffectiveLabels") + }) + + props = google.Reject(props, func(v *Type) bool { + return v.UrlParamOnly + }) + + props = google.Reject(props, func(v *Type) bool { + return v.IsA("KeyValueLabels") || v.IsA("KeyValueAnnotations") + }) + + return props +} + +// Properties that will be returned in the API body + +// def gettable_properties +func (r Resource) GettableProperties() []*Type { + return google.Reject(r.AllUserProperties(), func(v *Type) bool { + return v.UrlParamOnly + }) +} + +// Returns the list of top-level properties once any nested objects with flatten_object +// set to true have been collapsed + +// def root_properties +func (r Resource) RootProperties() []*Type { + props := make([]*Type, 0) + + for _, p := range r.AllUserProperties() { + if p.FlattenObject { + props = google.Concat(props, p.RootProperties()) + } else { + props = append(props, p) + } + } + return props +} + +// Return the product-level async object, or the resource-specific one +// if one exists. + +// def async +func (r Resource) GetAsync() *OpAsync { + if r.Async != nil { + return r.Async + } + + return r.ProductMetadata.Async +} + +// Return the resource-specific identity properties, or a best guess of the +// `name` value for the resource. + +// def identity +func (r Resource) GetIdentity() []*Type { + props := r.AllUserProperties() + + if r.Identity != nil { + identities := google.Select(props, func(p *Type) bool { + return slices.Contains(r.Identity, p.Name) + }) + + slices.SortFunc(identities, func(a, b *Type) int { + return slices.Index(r.Identity, a.Name) - slices.Index(r.Identity, b.Name) + }) + + return identities + } + + return google.Select(props, func(p *Type) bool { + return p.Name == "name" + }) + +} + +// TODO Q1 +// def add_labels_related_fields(props, parent) +// props.each do |p| +// if p.is_a? Api::Type::KeyValueLabels +// add_labels_fields(props, parent, p) +// elsif p.is_a? Api::Type::KeyValueAnnotations +// add_annotations_fields(props, parent, p) +// elsif (p.is_a? Api::Type::NestedObject) && !p.all_properties.nil? +// p.properties = add_labels_related_fields(p.all_properties, p) +// end +// end +// props +// end + +// def add_labels_fields(props, parent, labels) +// @custom_diff ||= [] +// if parent.nil? || parent.flatten_object +// @custom_diff.append('tpgresource.SetLabelsDiff') +// elsif parent.name == 'metadata' +// @custom_diff.append('tpgresource.SetMetadataLabelsDiff') +// end + +// props << build_terraform_labels_field('labels', parent, labels) +// props << build_effective_labels_field('labels', labels) + +// // The effective_labels field is used to write to API, instead of the labels field. +// labels.ignore_write = true +// labels.description = "//{labels.description}\n\n//{get_labels_field_note(labels.name)}" +// return unless parent.nil? + +// labels.immutable = false +// end + +// def add_annotations_fields(props, parent, annotations) +// // The effective_annotations field is used to write to API, +// // instead of the annotations field. +// annotations.ignore_write = true +// note = get_labels_field_note(annotations.name) +// annotations.description = "//{annotations.description}\n\n//{note}" + +// @custom_diff ||= [] +// if parent.nil? +// @custom_diff.append('tpgresource.SetAnnotationsDiff') +// elsif parent.name == 'metadata' +// @custom_diff.append('tpgresource.SetMetadataAnnotationsDiff') +// end + +// props << build_effective_labels_field('annotations', annotations) +// end + +// def build_effective_labels_field(name, labels) +// description = "All of //{name} (key/value pairs)\ +// present on the resource in GCP, including the //{name} configured through Terraform,\ +// other clients and services." + +// Api::Type::KeyValueEffectiveLabels.new( +// name: "effective//{name.capitalize}", +// output: true, +// api_name: name, +// description:, +// min_version: labels.field_min_version, +// update_verb: labels.update_verb, +// update_url: labels.update_url, +// immutable: labels.immutable +// ) +// end + +// def build_terraform_labels_field(name, parent, labels) +// description = "The combination of //{name} configured directly on the resource +// and default //{name} configured on the provider." + +// immutable = if parent.nil? +// false +// else +// labels.immutable +// end + +// Api::Type::KeyValueTerraformLabels.new( +// name: "terraform//{name.capitalize}", +// output: true, +// api_name: name, +// description:, +// min_version: labels.field_min_version, +// ignore_write: true, +// update_url: labels.update_url, +// immutable: +// ) +// end + +// // Check if the resource has root "labels" field +// def root_labels? +// root_properties.each do |p| +// return true if p.is_a? Api::Type::KeyValueLabels +// end +// false +// end + +// // Return labels fields that should be added to ImportStateVerifyIgnore +// def ignore_read_labels_fields(props) +// fields = [] +// props.each do |p| +// if (p.is_a? Api::Type::KeyValueLabels) || +// (p.is_a? Api::Type::KeyValueTerraformLabels) || +// (p.is_a? Api::Type::KeyValueAnnotations) +// fields << p.terraform_lineage +// elsif (p.is_a? Api::Type::NestedObject) && !p.all_properties.nil? +// fields.concat(ignore_read_labels_fields(p.all_properties)) +// end +// end +// fields +// end + +// def get_labels_field_note(title) +// "**Note**: This field is non-authoritative, and will only manage the //{title} present " \ +// "in your configuration. +// Please refer to the field `effective_//{title}` for all of the //{title} present on the resource." +// end + // ==================== // Version-related methods // ==================== +// def min_version func (r Resource) MinVersionObj() *product.Version { if r.MinVersion != "" { return r.ProductMetadata.versionObj(r.MinVersion) @@ -306,6 +587,7 @@ func (r Resource) MinVersionObj() *product.Version { } } +// def not_in_version?(version) func (r Resource) NotInVersion(version *product.Version) bool { return version.CompareTo(r.MinVersionObj()) < 0 } @@ -313,6 +595,8 @@ func (r Resource) NotInVersion(version *product.Version) bool { // Recurses through all nested properties and parameters and changes their // 'exclude' instance variable if the property is at a version below the // one that is passed in. + +// def exclude_if_not_in_version!(version) func (r *Resource) ExcludeIfNotInVersion(version *product.Version) { if !r.Exclude { r.Exclude = r.NotInVersion(version) @@ -330,3 +614,153 @@ func (r *Resource) ExcludeIfNotInVersion(version *product.Version) { } } } + +// ==================== +// URL-related methods +// ==================== + +// Returns the "self_link_url" which is generally really the resource's GET +// URL. In older resources generally, this was the self_link value & was the +// product.base_url + resource.base_url + '/name' +// In newer resources there is much less standardisation in terms of value. +// Generally for them though, it's the product.base_url + resource.name + +// def self_link_url +func (r Resource) SelfLinkUrl() string { + s := []string{r.ProductMetadata.BaseUrl, r.SelfLinkUri()} + return strings.Join(s, "") +} + +// Returns the partial uri / relative path of a resource. In newer resources, +// this is the name. This fn is named self_link_uri for consistency, but +// could otherwise be considered to be "path" + +// def self_link_uri +func (r Resource) SelfLinkUri() string { + // If the terms in this are not snake-cased, this will require + // an override in Terraform. + if r.SelfLink != "" { + return r.SelfLink + } + + return strings.Join([]string{r.BaseUrl, "{{name}}"}, "/") +} + +// def collection_url +func (r Resource) CollectionUrl() string { + s := []string{r.ProductMetadata.BaseUrl, r.collectionUri()} + return strings.Join(s, "") +} + +// def collection_uri +func (r Resource) collectionUri() string { + return r.BaseUrl +} + +// def create_uri +func (r Resource) CreateUri() string { + if r.CreateUrl != "" { + return r.CreateUrl + } + + if r.CreateVerb == "" || r.CreateVerb == "POST" { + return r.collectionUri() + } + + return r.SelfLinkUri() +} + +// def delete_uri +func (r Resource) DeleteUri() string { + if r.DeleteUrl != "" { + return r.DeleteUrl + } + + return r.SelfLinkUri() +} + +// def resource_name +func (r Resource) ResourceName() string { + return fmt.Sprintf("%s%s", r.ProductMetadata.Name, r.Name) +} + +// Filter the properties to keep only the ones don't have custom update +// method and group them by update url & verb. + +// def properties_without_custom_update(properties) +func propertiesWithoutCustomUpdate(properties []*Type) []*Type { + return google.Select(properties, func(p *Type) bool { + return p.UpdateUrl == "" || p.UpdateVerb == "" || p.UpdateVerb == "NOOP" + }) +} + +// def update_body_properties +func (r Resource) UpdateBodyProperties() []*Type { + updateProp := propertiesWithoutCustomUpdate(r.settableProperties()) + if r.UpdateVerb == "PATCH" { + updateProp = google.Reject(updateProp, func(p *Type) bool { + return p.Immutable + }) + } + return updateProp +} + +// Handwritten TF Operation objects will be shaped like accessContextManager +// while the Google Go Client will have a name like accesscontextmanager + +// def client_name_pascal +func (r Resource) ClientNamePascal() string { + clientName := r.ProductMetadata.ClientName + if clientName == "" { + clientName = r.ProductMetadata.Name + } + + return google.Camelize(clientName, "upper") +} + +// In order of preference, use TF override, +// general defined timeouts, or default Timeouts + +// def timeouts +func (r Resource) GetTimeouts() *Timeouts { + timeoutsFiltered := r.Timeouts + if timeoutsFiltered == nil { + if async := r.GetAsync(); async != nil && async.Operation != nil { + timeoutsFiltered = async.Operation.Timeouts + } + + if timeoutsFiltered == nil { + timeoutsFiltered = NewTimeouts() + } + } + + return timeoutsFiltered +} + +// def project? +func (r Resource) HasProject() bool { + return strings.Contains(r.BaseUrl, "{{project}}") || strings.Contains(r.CreateUrl, "{{project}}") +} + +// def region? +func (r Resource) HasRegion() bool { + return strings.Contains(r.BaseUrl, "{{region}}") || strings.Contains(r.CreateUrl, "{{region}}") +} + +// def zone? +func (r Resource) HasZone() bool { + return strings.Contains(r.BaseUrl, "{{zone}}") || strings.Contains(r.CreateUrl, "{{zone}}") +} + +// ==================== +// Debugging Methods +// ==================== + +// Prints a dot notation path to where the field is nested within the parent +// object when called on a property. eg: parent.meta.label.foo +// Redefined on Resource to terminate the calls up the parent chain. + +// def lineage +func (r Resource) Lineage() string { + return r.Name +} diff --git a/mmv1/api/resource.rb b/mmv1/api/resource.rb index a3036a3c6d79..7e086ad13fd1 100644 --- a/mmv1/api/resource.rb +++ b/mmv1/api/resource.rb @@ -445,18 +445,6 @@ def identity end end - def kind? - !@kind.nil? - end - - def encoder? - !@transport&.encoder.nil? - end - - def decoder? - !@transport&.decoder.nil? - end - def add_labels_related_fields(props, parent) props.each do |p| if p.is_a? Api::Type::KeyValueLabels @@ -635,10 +623,6 @@ def collection_uri @base_url end - def full_create_url - [@__product.base_url, create_uri].flatten.join - end - def create_uri if @create_url.nil? if @create_verb.nil? || @create_verb == :POST @@ -651,10 +635,6 @@ def create_uri end end - def full_delete_url - [@__product.base_url, delete_uri].flatten.join - end - def delete_uri if @delete_url.nil? self_link_uri diff --git a/mmv1/api/timeouts.go b/mmv1/api/timeouts.go index 41134697a969..31d1e61b2f8f 100644 --- a/mmv1/api/timeouts.go +++ b/mmv1/api/timeouts.go @@ -42,6 +42,14 @@ type Timeouts struct { // validate // end +func NewTimeouts() *Timeouts { + return &Timeouts{ + InsertMinutes: DEFAULT_INSERT_TIMEOUT_MINUTES, + UpdateMinutes: DEFAULT_UPDATE_TIMEOUT_MINUTES, + DeleteMinutes: DEFAULT_DELETE_TIMEOUT_MINUTES, + } +} + // def validate // super diff --git a/mmv1/api/type.go b/mmv1/api/type.go index f80777231810..43afc0f77f8b 100644 --- a/mmv1/api/type.go +++ b/mmv1/api/type.go @@ -14,7 +14,12 @@ package api import ( + "fmt" + "log" + "reflect" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" ) // require 'api/object' @@ -120,19 +125,20 @@ type Type struct { RequiredWith []string `yaml:"required_with"` // Can only be overridden - we should never set this ourselves. - // TODO: set a specific type intead of interface{} - NewType interface{} + NewType string // A pattern that maps expected user input to expected API input. // TODO: remove? Pattern string - Properties []Type + Properties []*Type EnumValues []string `yaml:"enum_values"` ItemType string `yaml:"item_type"` + Resource string + // ==================== // Terraform Overrides // ==================== @@ -305,11 +311,15 @@ const MAX_NAME = 20 // object. eg: parent.meta.label.foo // The only intended purpose is to allow better error messages. Some objects // and at some points in the build this doesn't output a valid output. -// func (t *Type) lineage() { -// return name&.underscore if __parent.nil? -// "//{__parent.lineage}.//{name&.underscore}" -// } +// def lineage +func (t *Type) Lineage() string { + if t.ParentMetadata == nil { + return google.Underscore(t.Name) + } + + return fmt.Sprintf("%s.%s", t.ParentMetadata.Lineage(), google.Underscore(t.Name)) +} // Prints the access path of the field in the configration eg: metadata.0.labels // The only intended purpose is to get the value of the labes field by calling d.Get(). @@ -445,6 +455,7 @@ const MAX_NAME = 20 // // @__parent // } +// def min_version func (t *Type) MinVersionObj() *product.Version { if t.MinVersion != "" { return t.ResourceMetadata.ProductMetadata.versionObj(t.MinVersion) @@ -453,6 +464,7 @@ func (t *Type) MinVersionObj() *product.Version { } } +// def exact_version func (t *Type) exactVersionObj() *product.Version { if t.ExactVersion == "" { return nil @@ -461,6 +473,7 @@ func (t *Type) exactVersionObj() *product.Version { return t.ResourceMetadata.ProductMetadata.versionObj(t.ExactVersion) } +// def exclude_if_not_in_version!(version) func (t *Type) ExcludeIfNotInVersion(version *product.Version) { if !t.Exclude { if versionObj := t.exactVersionObj(); versionObj != nil { @@ -473,14 +486,24 @@ func (t *Type) ExcludeIfNotInVersion(version *product.Version) { } } -// // Overriding is_a? to enable class overrides. -// // Ruby does not let you natively change types, so this is the next best -// // thing. +// Overriding is_a? to enable class overrides. +// Ruby does not let you natively change types, so this is the next best +// thing. + +// TODO Q1: check the type of superclasses of property t // func (t *Type) is_a?(clazz) { -// // return Module.const_get(@new_type).new.is_a?(clazz) if @new_type +func (t *Type) IsA(clazz string) bool { + if clazz == "" { + log.Fatalf("class cannot be empty") + } -// // super(clazz) -// } + if t.NewType != "" { + return t.NewType == clazz + } + + return reflect.TypeOf(t).Name() == fmt.Sprintf("main.%s", clazz) + // super(clazz) +} // // Overriding class to enable class overrides. // // Ruby does not let you natively change types, so this is the next best @@ -491,11 +514,6 @@ func (t *Type) ExcludeIfNotInVersion(version *product.Version) { // // super // } -// // Returns nested properties for this property. -// func (t *Type) nested_properties() { -// // nil -// } - // func (t *Type) removed() { // // !(@removed_message.nil? || @removed_message == '') // } @@ -634,12 +652,12 @@ func (t *Type) ExcludeIfNotInVersion(version *product.Version) { // if @item_type.is_a? NestedObject // end -// func (t *Type) nested_properties -// return @item_type.nested_properties.reject(&:exclude) \ -// if @item_type.is_a?(Api::Type::NestedObject) +// func (t *Type) nested_properties +// return @item_type.nested_properties.reject(&:exclude) \ +// if @item_type.is_a?(Api::Type::NestedObject) -// super -// end +// super +// end // func (t *Type) item_type_class // return @item_type \ @@ -726,12 +744,15 @@ func (t *Type) ExcludeIfNotInVersion(version *product.Version) { // return props.first unless props.empty? // end -// func (t *Type) resource_ref -// product = @__resource.__product -// resources = product.objects.select { |obj| obj.name == @resource } +// func (t *Type) resource_ref +func (t *Type) ResourceRef() *Resource { + product := t.ResourceMetadata.ProductMetadata + resources := google.Select(product.Objects, func(obj *Resource) bool { + return obj.Name == t.Resource + }) -// resources[0] -// end + return resources[0] +} // func (t *Type) property_class // type = property_ns_prefix @@ -783,27 +804,37 @@ func (t *Type) ExcludeIfNotInVersion(version *product.Version) { // @properties // end -// func (t *Type) properties -// raise "Field '//{lineage}' properties are nil!" if @properties.nil? +// func (t *Type) properties +func (t *Type) UserProperties() []*Type { + if t.Properties == nil { + log.Fatalf("Field '{%s}' properties are nil!", t.Lineage()) + } -// @properties.reject(&:exclude) -// end + return google.Reject(t.Properties, func(p *Type) bool { + return p.Exclude + }) +} -// func (t *Type) nested_properties -// properties -// end +// func (t *Type) nested_properties +func (t *Type) NestedProperties() []*Type { + return t.UserProperties() +} -// // Returns the list of top-level properties once any nested objects with -// // flatten_object set to true have been collapsed -// func (t *Type) root_properties -// properties.flat_map do |p| -// if p.flatten_object -// p.root_properties -// else -// p -// end -// end -// end +// Returns the list of top-level properties once any nested objects with +// flatten_object set to true have been collapsed +// +// func (t *Type) root_properties +func (t *Type) RootProperties() []*Type { + props := make([]*Type, 0) + for _, p := range t.UserProperties() { + if p.FlattenObject { + props = google.Concat(props, p.RootProperties()) + } else { + props = append(props, p) + } + } + return props +} // func (t *Type) exclude_if_not_in_version!(version) // super diff --git a/mmv1/google/string_utils.go b/mmv1/google/string_utils.go index a9e4fb0db978..880460ee9ddb 100644 --- a/mmv1/google/string_utils.go +++ b/mmv1/google/string_utils.go @@ -14,8 +14,10 @@ package google import ( + "log" "regexp" "strings" + "unicode" ) // // Helper class to process and mutate strings. @@ -83,21 +85,34 @@ func SpaceSeparated(source string) string { // "//{source}s" // end -// // Slimmed down version of ActiveSupport::Inflector code -// def self.camelize(term, uppercase_first_letter) -// acronyms_camelize_regex = /^(?:(?=a)b(?=\b|[A-Z_])|\w)/ - -// string = term.to_s -// string = if uppercase_first_letter -// string.sub(/^[a-z\d]*/) { |match| match.capitalize! || match } -// else -// string.sub(acronyms_camelize_regex) { |match| match.downcase! || match } -// end -// // handle snake case -// string.gsub!(/(?:_)([a-z\d]*)/i) do -// word = ::Regexp.last_match(1) -// word.capitalize! || word -// end -// string -// end -// end +func Camelize(term string, firstLetter string) string { + if firstLetter != "upper" && firstLetter != "lower" { + log.Fatalf("Invalid option, use either upper or lower") + } + + res := term + if firstLetter == "upper" { + res = regexp.MustCompile(`^[a-z\d]*/`).ReplaceAllStringFunc(res, func(match string) string { + return strings.Title(match) + }) + } else { + // TODO: rewrite with the regular expression. Lookahead(?=) is not supported in Go + // acronymsCamelizeRegex := regexp.MustCompile(`^(?:(?=a)b(?=\b|[A-Z_])|\w)`) + // res = acronymsCamelizeRegex.ReplaceAllStringFunc(res, func(match string) string { + // return strings.ToLower(match) + // }) + if len(res) != 0 { + r := []rune(res) + r[0] = unicode.ToLower(r[0]) + res = string(r) + } + } + // handle snake case + re := regexp.MustCompile(`(?:_)([a-z\d]*)`) + res = re.ReplaceAllStringFunc(res, func(match string) string { + word := match[1:] + word = strings.Title(word) + return word + }) + return res +} diff --git a/mmv1/google/string_utils_test.go b/mmv1/google/string_utils_test.go new file mode 100644 index 000000000000..cde78a98d0dd --- /dev/null +++ b/mmv1/google/string_utils_test.go @@ -0,0 +1,54 @@ +package google + +import ( + "reflect" + "testing" +) + +func TestStringCamelize(t *testing.T) { + t.Parallel() + + cases := []struct { + description string + term string + firstLetter string + expected string + }{ + { + description: "Camelize string with lowercase first letter", + term: "AuthorizedOrgsDesc", + firstLetter: "lower", + expected: "authorizedOrgsDesc", + }, + { + description: "Camelize string with uppercase first letter", + term: "AuthorizedOrgsDesc", + firstLetter: "upper", + expected: "AuthorizedOrgsDesc", + }, + { + description: "Camelize snakecase string with lowercase first letter", + term: "Authorized_Orgs_Desc", + firstLetter: "lower", + expected: "authorizedOrgsDesc", + }, + { + description: "Camelize snakecase string with uppercase first letter", + term: "Authorized_Orgs_Desc", + firstLetter: "upper", + expected: "AuthorizedOrgsDesc", + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + if got, want := Camelize(tc.term, tc.firstLetter), tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} diff --git a/mmv1/provider/terraform.rb b/mmv1/provider/terraform.rb index 37fd2de9f525..cd781e5da8eb 100644 --- a/mmv1/provider/terraform.rb +++ b/mmv1/provider/terraform.rb @@ -466,14 +466,6 @@ def properties_by_custom_update(properties) end end - # Filter the properties to keep only the ones don't have custom update - # method and group them by update url & verb. - def properties_without_custom_update(properties) - properties.select do |p| - p.update_url.nil? || p.update_verb.nil? || p.update_verb == :NOOP - end - end - # Takes a update_url and returns the list of custom updatable properties # that can be updated at that URL. This allows flattened objects # to determine which parent property in the API should be updated with From cbcabf77af2a2a035338003ce717e5cfd73b0060 Mon Sep 17 00:00:00 2001 From: Harrison Powers Date: Tue, 19 Mar 2024 18:56:57 -0400 Subject: [PATCH 58/59] Add missing guest_os_features enumeration value (#10229) --- mmv1/products/compute/Disk.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/mmv1/products/compute/Disk.yaml b/mmv1/products/compute/Disk.yaml index 2097550860c1..9fdca5f907ee 100644 --- a/mmv1/products/compute/Disk.yaml +++ b/mmv1/products/compute/Disk.yaml @@ -500,6 +500,7 @@ properties: - :SEV_SNP_CAPABLE - :SUSPEND_RESUME_COMPATIBLE - :TDX_CAPABLE + - :SEV_LIVE_MIGRATABLE_V2 - !ruby/object:Api::Type::Array name: 'licenses' description: Any applicable license URI. From 8f3a9892f4cfeddbaf4dc8457849e30e6ac49b8e Mon Sep 17 00:00:00 2001 From: Max Portocarrero CI&T <105444618+maxi-cit@users.noreply.github.com> Date: Tue, 19 Mar 2024 20:51:00 -0500 Subject: [PATCH 59/59] add billing project id support to firewall endpoint resource (#10122) * add billing project support * removed description field due to API issue * test updated and fixed for ADC support * added ADC warning * removing ADC --- .../networksecurity/FirewallEndpoint.yaml | 12 +++++ ...ork_security_firewall_endpoint_test.go.erb | 49 ++++++++++--------- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/mmv1/products/networksecurity/FirewallEndpoint.yaml b/mmv1/products/networksecurity/FirewallEndpoint.yaml index bc53ec4fa5a5..a2118263106c 100644 --- a/mmv1/products/networksecurity/FirewallEndpoint.yaml +++ b/mmv1/products/networksecurity/FirewallEndpoint.yaml @@ -23,6 +23,13 @@ description: | A Firewall endpoint is a Cloud Firewall resource that enables layer 7 advanced protection capabilities, such as intrusion prevention, in your network. +docs: !ruby/object:Provider::Terraform::Docs + warning: | + If you are using User ADCs (Application Default Credentials) with this resource, + you must specify a `billing_project` and set `user_project_override` to true + in the provider configuration. Otherwise the ACM API will return a 403 error. + Your account must have the `serviceusage.services.use` permission on the + `billing_project` you defined. references: !ruby/object:Api::Resource::ReferenceLinks api: 'https://cloud.google.com/firewall/docs/reference/network-security/rest/v1beta1/organizations.locations.firewallEndpoints' @@ -110,3 +117,8 @@ properties: name: 'state' description: The current state of the endpoint. output: true + - !ruby/object:Api::Type::String + name: 'billingProjectId' + description: | + Project to bill on endpoint uptime usage. + required: true diff --git a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_firewall_endpoint_test.go.erb b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_firewall_endpoint_test.go.erb index 05413b1545ec..888d865f9fbb 100644 --- a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_firewall_endpoint_test.go.erb +++ b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_firewall_endpoint_test.go.erb @@ -20,6 +20,7 @@ func TestAccNetworkSecurityFirewallEndpoints_basic(t *testing.T) { acctest.SkipIfVcr(t) t.Parallel() + billingProjectId := envvar.GetTestProjectFromEnv() orgId := envvar.GetTestOrgFromEnv(t) randomSuffix := acctest.RandString(t, 10) @@ -29,7 +30,7 @@ func TestAccNetworkSecurityFirewallEndpoints_basic(t *testing.T) { CheckDestroy: testAccCheckNetworkSecurityFirewallEndpointDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccNetworkSecurityFirewallEndpoints_basic(orgId, randomSuffix), + Config: testAccNetworkSecurityFirewallEndpoints_basic(orgId, billingProjectId, randomSuffix), }, { ResourceName: "google_network_security_firewall_endpoint.foobar", @@ -38,7 +39,7 @@ func TestAccNetworkSecurityFirewallEndpoints_basic(t *testing.T) { ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { - Config: testAccNetworkSecurityFirewallEndpoints_update(orgId, randomSuffix), + Config: testAccNetworkSecurityFirewallEndpoints_update(orgId, billingProjectId, randomSuffix), }, { ResourceName: "google_network_security_firewall_endpoint.foobar", @@ -50,34 +51,38 @@ func TestAccNetworkSecurityFirewallEndpoints_basic(t *testing.T) { }) } -func testAccNetworkSecurityFirewallEndpoints_basic(orgId string, randomSuffix string) string { +func testAccNetworkSecurityFirewallEndpoints_basic(orgId string, billingProjectId string, randomSuffix string) string { return fmt.Sprintf(` resource "google_network_security_firewall_endpoint" "foobar" { - provider = google-beta - name = "tf-test-my-firewall-endpoint%s" - parent = "organizations/%s" - location = "us-central1-a" - - labels = { - foo = "bar" - } + provider = google-beta + + name = "tf-test-my-firewall-endpoint%[1]s" + parent = "organizations/%[2]s" + location = "us-central1-a" + billing_project_id = "%[3]s" + + labels = { + foo = "bar" + } } -`, randomSuffix, orgId) +`, randomSuffix, orgId, billingProjectId) } -func testAccNetworkSecurityFirewallEndpoints_update(orgId string, randomSuffix string) string { +func testAccNetworkSecurityFirewallEndpoints_update(orgId string, billingProjectId string, randomSuffix string) string { return fmt.Sprintf(` resource "google_network_security_firewall_endpoint" "foobar" { - provider = google-beta - name = "tf-test-my-firewall-endpoint%s" - parent = "organizations/%s" - location = "us-central1-a" - - labels = { - foo = "bar-updated" - } + provider = google-beta + + name = "tf-test-my-firewall-endpoint%[1]s" + parent = "organizations/%[2]s" + location = "us-central1-a" + billing_project_id = "%[3]s" + + labels = { + foo = "bar-updated" + } } -`, randomSuffix, orgId) +`, randomSuffix, orgId, billingProjectId) } func testAccCheckNetworkSecurityFirewallEndpointDestroyProducer(t *testing.T) func(s *terraform.State) error {