From ccbd66997ec632905dd726015573a49dae2f2a45 Mon Sep 17 00:00:00 2001 From: wj-chen Date: Fri, 28 Jul 2023 14:05:13 -0700 Subject: [PATCH 01/67] Enhance BigQuery table schema input validation (#8460) * Enhance BigQuery table schema input validation * skip TestAccBigQueryTable_invalidSchemas in VCR test --- .../bigquery/resource_bigquery_table.go | 30 +++- .../tests/resource_bigquery_table_test.go | 134 ++++++++++++++++++ 2 files changed, 162 insertions(+), 2 deletions(-) diff --git a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go index dafd68aa86be..b95488961d3b 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go @@ -363,6 +363,32 @@ func resourceBigQueryTableSchemaCustomizeDiff(_ context.Context, d *schema.Resou return resourceBigQueryTableSchemaCustomizeDiffFunc(d) } +func validateBigQueryTableSchema(v interface{}, k string) (warnings []string, errs []error) { + if v == nil { + return + } + + if _, e := validation.StringIsJSON(v, k); e != nil { + errs = append(errs, e...) + return + } + + var jsonList []interface{} + if err := json.Unmarshal([]byte(v.(string)), &jsonList); err != nil { + errs = append(errs, fmt.Errorf("\"schema\" is not a JSON array: %s", err)) + return + } + + for _, v := range jsonList { + if v == nil { + errs = append(errs, errors.New("\"schema\" contains a nil element")) + return + } + } + + return +} + func ResourceBigQueryTable() *schema.Resource { return &schema.Resource{ Create: resourceBigQueryTableCreate, @@ -471,7 +497,7 @@ func ResourceBigQueryTable() *schema.Resource { Optional: true, Computed: true, ForceNew: true, - ValidateFunc: validation.StringIsJSON, + ValidateFunc: validateBigQueryTableSchema, StateFunc: func(v interface{}) string { json, _ := structure.NormalizeJsonString(v) return json @@ -739,7 +765,7 @@ func ResourceBigQueryTable() *schema.Resource { Type: schema.TypeString, Optional: true, Computed: true, - ValidateFunc: validation.StringIsJSON, + ValidateFunc: validateBigQueryTableSchema, StateFunc: func(v interface{}) string { json, _ := structure.NormalizeJsonString(v) return json diff --git a/mmv1/third_party/terraform/tests/resource_bigquery_table_test.go b/mmv1/third_party/terraform/tests/resource_bigquery_table_test.go index e3b2d380b937..229d32af49d3 100644 --- a/mmv1/third_party/terraform/tests/resource_bigquery_table_test.go +++ b/mmv1/third_party/terraform/tests/resource_bigquery_table_test.go @@ -586,6 +586,36 @@ func TestAccBigQueryExternalDataTable_CSV(t *testing.T) { }) } +func TestAccBigQueryExternalDataTable_CSV_WithSchema_InvalidSchemas(t *testing.T) { + t.Parallel() + + bucketName := testBucketName(t) + objectName := fmt.Sprintf("tf_test_%s.csv", RandString(t, 10)) + + datasetID := fmt.Sprintf("tf_test_%s", RandString(t, 10)) + tableID := fmt.Sprintf("tf_test_%s", RandString(t, 10)) + + VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckBigQueryTableDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigQueryTableFromGCSWithExternalDataConfigSchema(datasetID, tableID, bucketName, objectName, TEST_SIMPLE_CSV, TEST_INVALID_SCHEMA_NOT_JSON), + ExpectError: regexp.MustCompile("contains an invalid JSON"), + }, + { + Config: testAccBigQueryTableFromGCSWithExternalDataConfigSchema(datasetID, tableID, bucketName, objectName, TEST_SIMPLE_CSV, TEST_INVALID_SCHEMA_NOT_JSON_LIST), + ExpectError: regexp.MustCompile("\"schema\" is not a JSON array"), + }, + { + Config: testAccBigQueryTableFromGCSWithExternalDataConfigSchema(datasetID, tableID, bucketName, objectName, TEST_SIMPLE_CSV, TEST_INVALID_SCHEMA_JSON_LIST_WITH_NULL_ELEMENT), + ExpectError: regexp.MustCompile("\"schema\" contains a nil element"), + }, + }, + }) +} + func TestAccBigQueryExternalDataTable_CSV_WithSchemaAndConnectionID_UpdateNoConnectionID(t *testing.T) { t.Parallel() @@ -917,6 +947,35 @@ func TestAccBigQueryTable_emptySchema(t *testing.T) { }) } +func TestAccBigQueryTable_invalidSchemas(t *testing.T) { + t.Parallel() + // Not an acceptance test. + acctest.SkipIfVcr(t) + + datasetID := fmt.Sprintf("tf_test_%s", RandString(t, 10)) + tableID := fmt.Sprintf("tf_test_%s", RandString(t, 10)) + + VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckBigQueryTableDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigQueryTableWithSchema(datasetID, tableID, TEST_INVALID_SCHEMA_NOT_JSON), + ExpectError: regexp.MustCompile("contains an invalid JSON"), + }, + { + Config: testAccBigQueryTableWithSchema(datasetID, tableID, TEST_INVALID_SCHEMA_NOT_JSON_LIST), + ExpectError: regexp.MustCompile("\"schema\" is not a JSON array"), + }, + { + Config: testAccBigQueryTableWithSchema(datasetID, tableID, TEST_INVALID_SCHEMA_JSON_LIST_WITH_NULL_ELEMENT), + ExpectError: regexp.MustCompile("\"schema\" contains a nil element"), + }, + }, + }) +} + func testAccCheckBigQueryExtData(t *testing.T, expectedQuoteChar string) resource.TestCheckFunc { return func(s *terraform.State) error { for _, rs := range s.RootModule().Resources { @@ -1984,6 +2043,45 @@ resource "google_bigquery_table" "test" { `, datasetID, bucketName, objectName, content, tableID, schema) } +func testAccBigQueryTableFromGCSWithExternalDataConfigSchema(datasetID, tableID, bucketName, objectName, content, schema string) string { + return fmt.Sprintf(` +resource "google_bigquery_dataset" "test" { + dataset_id = "%s" +} +resource "google_storage_bucket" "test" { + name = "%s" + location = "US" + force_destroy = true +} +resource "google_storage_bucket_object" "test" { + name = "%s" + content = < Date: Fri, 4 Aug 2023 13:50:46 -0400 Subject: [PATCH 02/67] Breaking changes for Firebase apps deletion policy (#8458) --- mmv1/products/firebase/AndroidApp.yaml | 9 +-- mmv1/products/firebase/AppleApp.yaml | 10 ++-- mmv1/products/firebase/WebApp.yaml | 13 ++-- .../examples/firebase_web_app_basic.tf.erb | 22 +------ .../examples/firebasehosting_site_full.tf.erb | 1 - ...source_google_firebase_web_app_test.go.erb | 1 - ...resource_firebase_hosting_site_test.go.erb | 2 - .../resource_firebase_web_app_test.go.erb | 60 ++++++++----------- 8 files changed, 42 insertions(+), 76 deletions(-) diff --git a/mmv1/products/firebase/AndroidApp.yaml b/mmv1/products/firebase/AndroidApp.yaml index 17f46aeb37f2..03a5c194dfeb 100644 --- a/mmv1/products/firebase/AndroidApp.yaml +++ b/mmv1/products/firebase/AndroidApp.yaml @@ -64,7 +64,6 @@ examples: vars: display_name: 'Display Name Basic' test_env_vars: - org_id: :ORG_ID project_id: :PROJECT_NAME test_vars_overrides: package_name: '"android.package.app" + acctest.RandString(t, 4)' @@ -73,14 +72,16 @@ examples: - project - deletion_policy virtual_fields: - # TODO: make this an enum in a future major version. If using this field as a reference, look at PerInstanceConfig's minimal_action field for enum configuration. - - !ruby/object:Api::Type::String + - !ruby/object:Api::Type::Enum name: 'deletion_policy' description: | (Optional) Set to `ABANDON` to allow the AndroidApp to be untracked from terraform state rather than deleted upon `terraform destroy`. This is useful because the AndroidApp may be serving traffic. Set to `DELETE` to delete the AndroidApp. Defaults to `DELETE`. - default_value: DELETE + default_value: :DELETE + values: + - :DELETE + - :ABANDON custom_code: !ruby/object:Provider::Terraform::CustomCode custom_delete: templates/terraform/custom_delete/firebase_app_deletion_policy.erb properties: diff --git a/mmv1/products/firebase/AppleApp.yaml b/mmv1/products/firebase/AppleApp.yaml index 7653470da1c1..82079249edab 100644 --- a/mmv1/products/firebase/AppleApp.yaml +++ b/mmv1/products/firebase/AppleApp.yaml @@ -65,7 +65,6 @@ examples: display_name: 'Display Name Basic' bundle_id: 'apple.app.12345' test_env_vars: - org_id: :ORG_ID project_id: :PROJECT_NAME test_vars_overrides: display_name: '"tf-test Display Name Basic"' @@ -79,7 +78,6 @@ examples: app_store_id: '12345' team_id: '9987654321' # Has to be a 10-digit number. test_env_vars: - org_id: :ORG_ID project_id: :PROJECT_NAME test_vars_overrides: app_store_id: '12345' @@ -89,14 +87,16 @@ examples: - project - deletion_policy virtual_fields: - # TODO: make this an enum in a future major version. If using this field as a reference, look at PerInstanceConfig's minimal_action field for enum configuration. - - !ruby/object:Api::Type::String + - !ruby/object:Api::Type::Enum name: 'deletion_policy' description: | (Optional) Set to `ABANDON` to allow the Apple to be untracked from terraform state rather than deleted upon `terraform destroy`. This is useful because the Apple may be serving traffic. Set to `DELETE` to delete the Apple. Defaults to `DELETE`. - default_value: DELETE + default_value: :DELETE + values: + - :DELETE + - :ABANDON custom_code: !ruby/object:Provider::Terraform::CustomCode custom_delete: templates/terraform/custom_delete/firebase_app_deletion_policy.erb properties: diff --git a/mmv1/products/firebase/WebApp.yaml b/mmv1/products/firebase/WebApp.yaml index 5e11372645ac..df07eb5f9ca5 100644 --- a/mmv1/products/firebase/WebApp.yaml +++ b/mmv1/products/firebase/WebApp.yaml @@ -65,23 +65,24 @@ examples: vars: display_name: 'Display Name Basic' bucket_name: 'fb-webapp-' - project_name: "my-project" test_env_vars: - org_id: :ORG_ID + project_id: :PROJECT_NAME test_vars_overrides: display_name: '"tf-test Display Name Basic"' ignore_read_extra: - project - deletion_policy virtual_fields: - # TODO: make this an enum in a future major version. If using this field as a reference, look at PerInstanceConfig's minimal_action field for enum configuration. - - !ruby/object:Api::Type::String + - !ruby/object:Api::Type::Enum name: 'deletion_policy' description: | Set to `ABANDON` to allow the WebApp to be untracked from terraform state rather than deleted upon `terraform destroy`. This is useful becaue the WebApp may be - serving traffic. Set to `DELETE` to delete the WebApp. Default to `ABANDON` - default_value: ABANDON + serving traffic. Set to `DELETE` to delete the WebApp. Default to `DELETE` + default_value: :DELETE + values: + - :DELETE + - :ABANDON custom_code: !ruby/object:Provider::Terraform::CustomCode custom_delete: templates/terraform/custom_delete/firebase_app_deletion_policy.erb properties: diff --git a/mmv1/templates/terraform/examples/firebase_web_app_basic.tf.erb b/mmv1/templates/terraform/examples/firebase_web_app_basic.tf.erb index c75c49c821d6..46d98f831900 100644 --- a/mmv1/templates/terraform/examples/firebase_web_app_basic.tf.erb +++ b/mmv1/templates/terraform/examples/firebase_web_app_basic.tf.erb @@ -1,27 +1,7 @@ -resource "google_project" "default" { - provider = google-beta - - project_id = "<%= ctx[:vars]['project_name'] %>" - name = "<%= ctx[:vars]['project_name'] %>" - org_id = "<%= ctx[:test_env_vars]['org_id'] %>" - - labels = { - "firebase" = "enabled" - } -} - -resource "google_firebase_project" "default" { - provider = google-beta - project = google_project.default.project_id -} - resource "google_firebase_web_app" "<%= ctx[:primary_resource_id] %>" { provider = google-beta - project = google_project.default.project_id + project = "<%= ctx[:test_env_vars]['project_id'] %>" display_name = "<%= ctx[:vars]['display_name'] %>" - deletion_policy = "DELETE" - - depends_on = [google_firebase_project.default] } data "google_firebase_web_app_config" "basic" { diff --git a/mmv1/templates/terraform/examples/firebasehosting_site_full.tf.erb b/mmv1/templates/terraform/examples/firebasehosting_site_full.tf.erb index 57c88044615e..f436a7264428 100644 --- a/mmv1/templates/terraform/examples/firebasehosting_site_full.tf.erb +++ b/mmv1/templates/terraform/examples/firebasehosting_site_full.tf.erb @@ -2,7 +2,6 @@ resource "google_firebase_web_app" "default" { provider = google-beta project = "<%= ctx[:test_env_vars]['project_id'] %>" display_name = "<%= ctx[:vars]['display_name'] %>" - deletion_policy = "DELETE" } resource "google_firebase_hosting_site" "full" { diff --git a/mmv1/third_party/terraform/tests/data_source_google_firebase_web_app_test.go.erb b/mmv1/third_party/terraform/tests/data_source_google_firebase_web_app_test.go.erb index 55a476684a91..084e3b2004b9 100644 --- a/mmv1/third_party/terraform/tests/data_source_google_firebase_web_app_test.go.erb +++ b/mmv1/third_party/terraform/tests/data_source_google_firebase_web_app_test.go.erb @@ -44,7 +44,6 @@ func testAccDataSourceGoogleFirebaseWebApp(context map[string]interface{}) strin resource "google_firebase_web_app" "my_app" { project = "%{project_id}" display_name = "%{display_name}" - deletion_policy = "DELETE" } data "google_firebase_web_app" "my_app" { diff --git a/mmv1/third_party/terraform/tests/resource_firebase_hosting_site_test.go.erb b/mmv1/third_party/terraform/tests/resource_firebase_hosting_site_test.go.erb index 6647c063e5f4..e8b9097aa2e1 100644 --- a/mmv1/third_party/terraform/tests/resource_firebase_hosting_site_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_firebase_hosting_site_test.go.erb @@ -52,7 +52,6 @@ resource "google_firebase_web_app" "before" { provider = google-beta project = "%{project_id}" display_name = "tf-test Test web app before for Firebase Hosting" - deletion_policy = "DELETE" } resource "google_firebase_hosting_site" "update" { @@ -70,7 +69,6 @@ resource "google_firebase_web_app" "after" { provider = google-beta project = "%{project_id}" display_name = "tf-test Test web app after for Firebase Hosting" - deletion_policy = "DELETE" } resource "google_firebase_hosting_site" "update" { diff --git a/mmv1/third_party/terraform/tests/resource_firebase_web_app_test.go.erb b/mmv1/third_party/terraform/tests/resource_firebase_web_app_test.go.erb index 68ffd72efcd4..c1c87f6c1478 100644 --- a/mmv1/third_party/terraform/tests/resource_firebase_web_app_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_firebase_web_app_test.go.erb @@ -22,30 +22,19 @@ func TestAccFirebaseWebApp_firebaseWebAppFull(t *testing.T) { t.Parallel() context := map[string]interface{}{ - "org_id": envvar.GetTestOrgFromEnv(t), + "project_id": envvar.GetTestProjectFromEnv(), "random_suffix": acctest.RandString(t, 10), "display_name": "tf-test Display Name N", } acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), Steps: []resource.TestStep{ { - ExternalProviders: map[string]resource.ExternalProvider{ - "google": { - VersionConstraint: "4.58.0", - Source: "hashicorp/google<%= "-" + version unless version == 'ga' -%>", - }, - }, Config: testAccFirebaseWebApp_firebaseWebAppFull(context, ""), }, { - ExternalProviders: map[string]resource.ExternalProvider{ - "google": { - VersionConstraint: "4.58.0", - Source: "hashicorp/google<%= "-" + version unless version == 'ga' -%>", - }, - }, Config: testAccFirebaseWebApp_firebaseWebAppFull(context, "2"), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet("data.google_firebase_web_app_config.default", "api_key"), @@ -54,11 +43,9 @@ func TestAccFirebaseWebApp_firebaseWebAppFull(t *testing.T) { ), }, { - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), Config: testAccFirebaseWebApp_firebaseWebAppFull(context, ""), }, { - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), Config: testAccFirebaseWebApp_firebaseWebAppFull(context, "2"), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet("data.google_firebase_web_app_config.default", "api_key"), @@ -73,28 +60,11 @@ func TestAccFirebaseWebApp_firebaseWebAppFull(t *testing.T) { func testAccFirebaseWebApp_firebaseWebAppFull(context map[string]interface{}, update string) string { context["display_name"] = context["display_name"].(string) + update return acctest.Nprintf(` -resource "google_project" "default" { - provider = google-beta - - project_id = "tf-test%{random_suffix}" - name = "tf-test%{random_suffix}" - org_id = "%{org_id}" - labels = { - "firebase" = "enabled" - } -} - -resource "google_firebase_project" "default" { - provider = google-beta - project = google_project.default.project_id -} - resource "google_firebase_web_app" "default" { provider = google-beta - project = google_project.default.project_id + project = "%{project_id}" display_name = "%{display_name} %{random_suffix}" - - depends_on = [google_firebase_project.default] + deletion_policy = "DELETE" } data "google_firebase_web_app_config" "default" { @@ -108,7 +78,7 @@ func TestAccFirebaseWebApp_firebaseWebAppSkipDelete(t *testing.T) { t.Parallel() context := map[string]interface{}{ - "project_id": envvar.GetTestProjectFromEnv(), + "org_id": envvar.GetTestOrgFromEnv(t), "random_suffix": acctest.RandString(t, 10), "display_name": "tf-test Display Name N", } @@ -132,11 +102,29 @@ func TestAccFirebaseWebApp_firebaseWebAppSkipDelete(t *testing.T) { } func testAccFirebaseWebApp_firebaseWebAppSkipDelete(context map[string]interface{}, update string) string { + // Create a new project so we can clean up the project entirely return acctest.Nprintf(` +resource "google_project" "default" { + provider = google-beta + + project_id = "tf-test%{random_suffix}" + name = "tf-test%{random_suffix}" + org_id = "%{org_id}" + labels = { + "firebase" = "enabled" + } +} + +resource "google_firebase_project" "default" { + provider = google-beta + project = google_project.default.project_id +} + resource "google_firebase_web_app" "skip_delete" { provider = google-beta - project = "%{project_id}" + project = google_firebase_project.default.project display_name = "%{display_name} %{random_suffix}" + deletion_policy = "ABANDON" } `, context) } From a102bc63620dc24315001f228ba01190f1dbdba7 Mon Sep 17 00:00:00 2001 From: Yanwei Guo Date: Tue, 8 Aug 2023 09:30:45 -0700 Subject: [PATCH 03/67] remove deprecated (#8529) --- mmv1/products/cloudrunv2/Job.yaml | 158 -------------------------- mmv1/products/cloudrunv2/Service.yaml | 15 --- 2 files changed, 173 deletions(-) diff --git a/mmv1/products/cloudrunv2/Job.yaml b/mmv1/products/cloudrunv2/Job.yaml index 01f9e8499d64..f2361164420e 100644 --- a/mmv1/products/cloudrunv2/Job.yaml +++ b/mmv1/products/cloudrunv2/Job.yaml @@ -337,164 +337,6 @@ properties: name: 'workingDir' description: |- Container's working directory. If not specified, the container runtime's default will be used, which might be configured in the container image. - - !ruby/object:Api::Type::NestedObject - name: 'livenessProbe' - description: |- - Periodic probe of container liveness. Container will be restarted if the probe fails. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - This field is not supported in Cloud Run Job currently. - deprecation_message: - Cloud Run Job does not support liveness probe and - `liveness_probe` field will be removed in a future major - release. - properties: - - !ruby/object:Api::Type::Integer - name: 'initialDelaySeconds' - description: |- - Number of seconds after the container has started before the probe is initiated. Defaults to 0 seconds. Minimum value is 0. Maximum value for liveness probe is 3600. Maximum value for startup probe is 240. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - default_value: 0 - - !ruby/object:Api::Type::Integer - name: 'timeoutSeconds' - description: |- - Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. Maximum value is 3600. Must be smaller than periodSeconds. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - default_value: 1 - - !ruby/object:Api::Type::Integer - name: 'periodSeconds' - description: |- - How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. Maximum value for liveness probe is 3600. Maximum value for startup probe is 240. Must be greater or equal than timeoutSeconds - default_value: 10 - - !ruby/object:Api::Type::Integer - name: 'failureThreshold' - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. - default_value: 3 - - !ruby/object:Api::Type::NestedObject - name: 'httpGet' - description: |- - HTTPGet specifies the http request to perform. Exactly one of HTTPGet or TCPSocket must be specified. - send_empty_value: true - allow_empty_object: - true - # exactly_one_of: - # - template.0.template.0.containers.0.livenessProbe.0.httpGet - # - template.0.template.0.containers.0.livenessProbe.0.tcpSocket - properties: - - !ruby/object:Api::Type::String - name: 'path' - default_value: '/' - description: |- - Path to access on the HTTP server. Defaults to '/'. - - !ruby/object:Api::Type::Array - name: httpHeaders - description: |- - Custom headers to set in the request. HTTP allows repeated headers. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::String - name: name - required: true - description: |- - The header field name - - !ruby/object:Api::Type::String - name: value - description: |- - The header field value - default_value: '' - send_empty_value: true - - !ruby/object:Api::Type::NestedObject - name: 'tcpSocket' - description: |- - TCPSocket specifies an action involving a TCP port. Exactly one of HTTPGet or TCPSocket must be specified. - send_empty_value: true - allow_empty_object: - true - # exactly_one_of: - # - template.0.template.0.containers.0.livenessProbe.0.httpGet - # - template.0.template.0.containers.0.livenessProbe.0.tcpSocket - properties: - - !ruby/object:Api::Type::Integer - name: port - description: |- - Port number to access on the container. Must be in the range 1 to 65535. If not specified, defaults to 8080. - - !ruby/object:Api::Type::NestedObject - name: 'startupProbe' - description: |- - Startup probe of application within the container. All other probes are disabled if a startup probe is provided, until it succeeds. Container will not be added to service endpoints if the probe fails. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - This field is not supported in Cloud Run Job currently. - deprecation_message: - Cloud Run Job does not support startup probe and - `startup_probe` field will be removed in a future major - release. - default_from_api: true - properties: - - !ruby/object:Api::Type::Integer - name: 'initialDelaySeconds' - description: |- - Number of seconds after the container has started before the probe is initiated. Defaults to 0 seconds. Minimum value is 0. Maximum value for liveness probe is 3600. Maximum value for startup probe is 240. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - default_value: 0 - - !ruby/object:Api::Type::Integer - name: 'timeoutSeconds' - description: |- - Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. Maximum value is 3600. Must be smaller than periodSeconds. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - default_value: 1 - - !ruby/object:Api::Type::Integer - name: 'periodSeconds' - description: |- - How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. Maximum value for liveness probe is 3600. Maximum value for startup probe is 240. Must be greater or equal than timeoutSeconds - default_value: 10 - - !ruby/object:Api::Type::Integer - name: 'failureThreshold' - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. - default_value: 3 - - !ruby/object:Api::Type::NestedObject - name: 'httpGet' - description: |- - HTTPGet specifies the http request to perform. Exactly one of HTTPGet or TCPSocket must be specified. - send_empty_value: true - allow_empty_object: - true - # exactly_one_of: - # - template.0.template.0.containers.startupProbe.0.httpGet - # - template.0.template.0.containers.startupProbe.0.tcpSocket - properties: - - !ruby/object:Api::Type::String - name: 'path' - default_value: '/' - description: |- - Path to access on the HTTP server. Defaults to '/'. - - !ruby/object:Api::Type::Array - name: 'httpHeaders' - description: |- - Custom headers to set in the request. HTTP allows repeated headers. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::String - name: name - required: true - description: |- - The header field name - - !ruby/object:Api::Type::String - name: value - description: |- - The header field value - default_value: '' - send_empty_value: true - - !ruby/object:Api::Type::NestedObject - name: 'tcpSocket' - description: |- - TCPSocket specifies an action involving a TCP port. Exactly one of HTTPGet or TCPSocket must be specified. - send_empty_value: true - allow_empty_object: - true - # exactly_one_of: - # - template.0.template.0.containers.startupProbe.0.httpGet - # - template.0.template.0.containers.startupProbe.0.tcpSocket - properties: - - !ruby/object:Api::Type::Integer - name: port - description: |- - Port number to access on the container. Must be in the range 1 to 65535. If not specified, defaults to 8080. - default_from_api: true - !ruby/object:Api::Type::Array name: 'volumes' description: |- diff --git a/mmv1/products/cloudrunv2/Service.yaml b/mmv1/products/cloudrunv2/Service.yaml index 5ba508fc9b42..66953043edc3 100644 --- a/mmv1/products/cloudrunv2/Service.yaml +++ b/mmv1/products/cloudrunv2/Service.yaml @@ -466,21 +466,6 @@ properties: The header field value default_value: '' send_empty_value: true - - !ruby/object:Api::Type::NestedObject - name: 'tcpSocket' - description: |- - TCPSocket specifies an action involving a TCP port. This field is not supported in liveness probe currently. - deprecation_message: - Cloud Run does not support tcp socket in liveness probe and - `liveness_probe.tcp_socket` field will be removed in a - future major release. - send_empty_value: true - allow_empty_object: true - properties: - - !ruby/object:Api::Type::Integer - name: port - description: |- - Port number to access on the container. Must be in the range 1 to 65535. If not specified, defaults to 8080. - !ruby/object:Api::Type::NestedObject name: grpc description: |- From 87e4f293f0030189f8ee24f20a20d7fa57eb2cc8 Mon Sep 17 00:00:00 2001 From: wj-chen Date: Wed, 9 Aug 2023 10:30:22 -0700 Subject: [PATCH 04/67] Enforce mutual exclusivity among view, materialized view, and schema in BigQuery table config (#7973) * Enforce mutual exclusivity among view, materialized view, and schema in BigQuery table config * fix merge conflict * fix field specification and add a VCR skip for the new acceptance test * skip VCR for MaterializedView_WithView test too --- .../bigquery/resource_bigquery_table.go | 45 ++--- .../tests/resource_bigquery_table_test.go | 163 ++++++++++++++++-- 2 files changed, 159 insertions(+), 49 deletions(-) diff --git a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go index b95488961d3b..8048027c14e0 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go @@ -761,6 +761,7 @@ func ResourceBigQueryTable() *schema.Resource { }, // Schema: [Optional] Describes the schema of this table. + // Schema is mutually exclusive with View and Materialized View. "schema": { Type: schema.TypeString, Optional: true, @@ -772,8 +773,10 @@ func ResourceBigQueryTable() *schema.Resource { }, DiffSuppressFunc: bigQueryTableSchemaDiffSuppress, Description: `A JSON schema for the table.`, + ConflictsWith: []string{"view", "materialized_view"}, }, // View: [Optional] If specified, configures this table as a view. + // View is mutually exclusive with Schema and Materialized View. "view": { Type: schema.TypeList, Optional: true, @@ -800,9 +803,11 @@ func ResourceBigQueryTable() *schema.Resource { }, }, }, + ConflictsWith: []string{"schema", "materialized_view"}, }, // Materialized View: [Optional] If specified, configures this table as a materialized view. + // Materialized View is mutually exclusive with Schema and View. "materialized_view": { Type: schema.TypeList, Optional: true, @@ -839,6 +844,7 @@ func ResourceBigQueryTable() *schema.Resource { }, }, }, + ConflictsWith: []string{"schema", "view"}, }, // TimePartitioning: [Experimental] If specified, configures time-based @@ -1170,41 +1176,16 @@ func resourceBigQueryTableCreate(d *schema.ResourceData, meta interface{}) error datasetID := d.Get("dataset_id").(string) - if table.View != nil && table.Schema != nil { + log.Printf("[INFO] Creating BigQuery table: %s", table.TableReference.TableId) - log.Printf("[INFO] Removing schema from table definition because big query does not support setting schema on view creation") - schemaBack := table.Schema - table.Schema = nil - - log.Printf("[INFO] Creating BigQuery table: %s without schema", table.TableReference.TableId) - - res, err := config.NewBigQueryClient(userAgent).Tables.Insert(project, datasetID, table).Do() - if err != nil { - return err - } - - log.Printf("[INFO] BigQuery table %s has been created", res.Id) - d.SetId(fmt.Sprintf("projects/%s/datasets/%s/tables/%s", res.TableReference.ProjectId, res.TableReference.DatasetId, res.TableReference.TableId)) - - table.Schema = schemaBack - log.Printf("[INFO] Updating BigQuery table: %s with schema", table.TableReference.TableId) - if _, err = config.NewBigQueryClient(userAgent).Tables.Update(project, datasetID, res.TableReference.TableId, table).Do(); err != nil { - return err - } - - log.Printf("[INFO] BigQuery table %s has been update with schema", res.Id) - } else { - log.Printf("[INFO] Creating BigQuery table: %s", table.TableReference.TableId) - - res, err := config.NewBigQueryClient(userAgent).Tables.Insert(project, datasetID, table).Do() - if err != nil { - return err - } - - log.Printf("[INFO] BigQuery table %s has been created", res.Id) - d.SetId(fmt.Sprintf("projects/%s/datasets/%s/tables/%s", res.TableReference.ProjectId, res.TableReference.DatasetId, res.TableReference.TableId)) + res, err := config.NewBigQueryClient(userAgent).Tables.Insert(project, datasetID, table).Do() + if err != nil { + return err } + log.Printf("[INFO] BigQuery table %s has been created", res.Id) + d.SetId(fmt.Sprintf("projects/%s/datasets/%s/tables/%s", res.TableReference.ProjectId, res.TableReference.DatasetId, res.TableReference.TableId)) + return resourceBigQueryTableRead(d, meta) } diff --git a/mmv1/third_party/terraform/tests/resource_bigquery_table_test.go b/mmv1/third_party/terraform/tests/resource_bigquery_table_test.go index 229d32af49d3..85299b40fd33 100644 --- a/mmv1/third_party/terraform/tests/resource_bigquery_table_test.go +++ b/mmv1/third_party/terraform/tests/resource_bigquery_table_test.go @@ -367,22 +367,8 @@ func TestAccBigQueryTable_WithViewAndSchema(t *testing.T) { CheckDestroy: testAccCheckBigQueryTableDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccBigQueryTableWithViewAndSchema(datasetID, tableID, "table description1"), - }, - { - ResourceName: "google_bigquery_table.test", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"deletion_protection"}, - }, - { - Config: testAccBigQueryTableWithViewAndSchema(datasetID, tableID, "table description2"), - }, - { - ResourceName: "google_bigquery_table.test", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"deletion_protection"}, + Config: testAccBigQueryTableWithViewAndSchema(datasetID, tableID, "table description"), + ExpectError: regexp.MustCompile("\"view\": conflicts with schema"), }, }, }) @@ -487,6 +473,52 @@ func TestAccBigQueryTable_MaterializedView_DailyTimePartioning_Update(t *testing }) } +func TestAccBigQueryTable_MaterializedView_WithSchema(t *testing.T) { + t.Parallel() + // Pending VCR support in https://github.com/hashicorp/terraform-provider-google/issues/15427. + acctest.SkipIfVcr(t) + + datasetID := fmt.Sprintf("tf_test_%s", RandString(t, 10)) + tableID := fmt.Sprintf("tf_test_%s", RandString(t, 10)) + materializedViewID := fmt.Sprintf("tf_test_%s", RandString(t, 10)) + query := fmt.Sprintf("SELECT some_int FROM `%s.%s`", datasetID, tableID) + + VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckBigQueryTableDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigQueryTableWithMatViewAndSchema(datasetID, tableID, materializedViewID, query), + ExpectError: regexp.MustCompile("\"materialized_view\": conflicts with schema"), + }, + }, + }) +} + +func TestAccBigQueryTable_MaterializedView_WithView(t *testing.T) { + t.Parallel() + // Pending VCR support in https://github.com/hashicorp/terraform-provider-google/issues/15427. + acctest.SkipIfVcr(t) + + datasetID := fmt.Sprintf("tf_test_%s", RandString(t, 10)) + tableID := fmt.Sprintf("tf_test_%s", RandString(t, 10)) + materializedViewID := fmt.Sprintf("tf_test_%s", RandString(t, 10)) + query := fmt.Sprintf("SELECT some_int FROM `%s.%s`", datasetID, tableID) + + VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckBigQueryTableDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigQueryTableWithMatViewAndView(datasetID, tableID, materializedViewID, query), + ExpectError: regexp.MustCompile("\"materialized_view\": conflicts with view"), + }, + }, + }) +} + func TestAccBigQueryExternalDataTable_parquet(t *testing.T) { t.Parallel() @@ -949,7 +981,7 @@ func TestAccBigQueryTable_emptySchema(t *testing.T) { func TestAccBigQueryTable_invalidSchemas(t *testing.T) { t.Parallel() - // Not an acceptance test. + // Pending VCR support in https://github.com/hashicorp/terraform-provider-google/issues/15427. acctest.SkipIfVcr(t) datasetID := fmt.Sprintf("tf_test_%s", RandString(t, 10)) @@ -1554,6 +1586,103 @@ resource "google_bigquery_table" "mv_test" { `, datasetID, tableID, mViewID, enable_refresh, refresh_interval, query) } +func testAccBigQueryTableWithMatViewAndSchema(datasetID, tableID, mViewID, query string) string { + return fmt.Sprintf(` +resource "google_bigquery_dataset" "test" { + dataset_id = "%s" +} + +resource "google_bigquery_table" "test" { + deletion_protection = false + table_id = "%s" + dataset_id = google_bigquery_dataset.test.dataset_id + + schema = < Date: Fri, 11 Aug 2023 10:46:58 -0700 Subject: [PATCH 05/67] Bugfix: Use API's default value for enableEndpointIndependentMapping (#8600) Instead of using a hardcode default of `false` for `enableEndpointIndependentMapping`, use the default value from the API. --- mmv1/products/compute/RouterNat.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mmv1/products/compute/RouterNat.yaml b/mmv1/products/compute/RouterNat.yaml index 9585438f70b7..7f9689035c9b 100644 --- a/mmv1/products/compute/RouterNat.yaml +++ b/mmv1/products/compute/RouterNat.yaml @@ -371,7 +371,7 @@ properties: - !ruby/object:Api::Type::Boolean name: enableEndpointIndependentMapping description: | - Specifies if endpoint independent mapping is enabled. This is enabled by default. For more information - see the [official documentation](https://cloud.google.com/nat/docs/overview#specs-rfcs). - default_value: true + Enable endpoint independent mapping. + For more information see the [official documentation](https://cloud.google.com/nat/docs/overview#specs-rfcs). + default_from_api: true send_empty_value: true From 0fc437a08f8abd6a942d58a28abbe1ba24aae77f Mon Sep 17 00:00:00 2001 From: Saurabh Maurya Date: Tue, 15 Aug 2023 08:15:06 -0700 Subject: [PATCH 06/67] Remove dataprofileresult and dataqualityresult (#8583) --- mmv1/products/dataplex/Datascan.yaml | 381 --------------------------- 1 file changed, 381 deletions(-) diff --git a/mmv1/products/dataplex/Datascan.yaml b/mmv1/products/dataplex/Datascan.yaml index e788f3f39dbd..8c7062edc981 100644 --- a/mmv1/products/dataplex/Datascan.yaml +++ b/mmv1/products/dataplex/Datascan.yaml @@ -413,384 +413,3 @@ properties: name: 'rowFilter' description: | A filter applied to all rows in a single DataScan job. The filter needs to be a valid SQL expression for a WHERE clause in BigQuery standard SQL syntax. Example: col1 >= 0 AND col2 < 10 - - !ruby/object:Api::Type::NestedObject - name: 'dataQualityResult' - output: true - description: | - The result of the data quality scan. - properties: - - !ruby/object:Api::Type::Boolean - name: 'passed' - output: true - description: | - Overall data quality result -- true if all rules passed. - - !ruby/object:Api::Type::Array - name: 'dimensions' - description: | - A list of results at the dimension level. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::Boolean - name: 'passed' - description: | - Whether the dimension passed or failed. - - !ruby/object:Api::Type::Array - name: 'rules' - output: true - description: | - A list of all the rules in a job, and their results. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::NestedObject - name: 'rule' - output: true - description: | - The rule specified in the DataQualitySpec, as is. - properties: - - !ruby/object:Api::Type::String - name: 'column' - description: | - The unnested column which this rule is evaluated against. - - !ruby/object:Api::Type::Boolean - name: 'ignoreNull' - description: | - Rows with null values will automatically fail a rule, unless ignoreNull is true. In that case, such null rows are trivially considered passing. Only applicable to ColumnMap rules. - - !ruby/object:Api::Type::String - name: 'dimension' - description: | - The dimension a rule belongs to. Results are also aggregated at the dimension level. Supported dimensions are ["COMPLETENESS", "ACCURACY", "CONSISTENCY", "VALIDITY", "UNIQUENESS", "INTEGRITY"] - - !ruby/object:Api::Type::Integer - name: 'threshold' - description: | - The minimum ratio of passing_rows / total_rows required to pass this rule, with a range of [0.0, 1.0]. 0 indicates default value (i.e. 1.0). - - !ruby/object:Api::Type::NestedObject - name: 'rangeExpectation' - output: true - description: | - ColumnMap rule which evaluates whether each column value lies between a specified range. - properties: - - !ruby/object:Api::Type::String - name: 'minValue' - description: | - The minimum column value allowed for a row to pass this validation. At least one of minValue and maxValue need to be provided. - - !ruby/object:Api::Type::String - name: maxValue - description: | - The maximum column value allowed for a row to pass this validation. At least one of minValue and maxValue need to be provided. - - !ruby/object:Api::Type::Boolean - name: 'strictMinEnabled' - default_value: false - description: | - Whether each value needs to be strictly greater than ('>') the minimum, or if equality is allowed. - Only relevant if a minValue has been defined. Default = false. - - !ruby/object:Api::Type::Boolean - name: 'strictMaxEnabled' - default_value: false - description: | - Whether each value needs to be strictly lesser than ('<') the maximum, or if equality is allowed. - Only relevant if a maxValue has been defined. Default = false. - - !ruby/object:Api::Type::NestedObject - name: 'nonNullExpectation' - output: true - allow_empty_object: true - description: | - ColumnMap rule which evaluates whether each column value is null. - properties: [] - - !ruby/object:Api::Type::NestedObject - name: 'setExpectation' - output: true - description: | - ColumnMap rule which evaluates whether each column value is contained by a specified set. - properties: - - !ruby/object:Api::Type::Array - name: 'values' - description: | - Expected values for the column value. - item_type: Api::Type::String - - !ruby/object:Api::Type::NestedObject - name: 'regexExpectation' - output: true - description: | - ColumnMap rule which evaluates whether each column value matches a specified regex. - properties: - - !ruby/object:Api::Type::String - name: 'regex' - description: | - A regular expression the column value is expected to match. - - !ruby/object:Api::Type::NestedObject - name: 'uniquenessExpectation' - output: true - allow_empty_object: true - description: | - ColumnAggregate rule which evaluates whether the column has duplicates. - properties: [] - - !ruby/object:Api::Type::NestedObject - name: 'statisticRangeExpectation' - output: true - description: | - ColumnAggregate rule which evaluates whether the column aggregate statistic lies between a specified range. - properties: - - !ruby/object:Api::Type::Enum - name: 'statistic' - description: | - column statistics. - values: - - :STATISTIC_UNDEFINED - - :MEAN - - :MIN - - :MAX - - !ruby/object:Api::Type::String - name: 'minValue' - description: | - The minimum column statistic value allowed for a row to pass this validation. - At least one of minValue and maxValue need to be provided. - - !ruby/object:Api::Type::String - name: 'maxValue' - description: | - The maximum column statistic value allowed for a row to pass this validation. - At least one of minValue and maxValue need to be provided. - - !ruby/object:Api::Type::Boolean - name: 'strictMinEnabled' - description: | - Whether column statistic needs to be strictly greater than ('>') the minimum, or if equality is allowed. - Only relevant if a minValue has been defined. Default = false. - - !ruby/object:Api::Type::Boolean - name: 'strictMaxEnabled' - description: | - Whether column statistic needs to be strictly lesser than ('<') the maximum, or if equality is allowed. - Only relevant if a maxValue has been defined. Default = false. - - !ruby/object:Api::Type::NestedObject - name: 'rowConditionExpectation' - output: true - description: | - Table rule which evaluates whether each row passes the specified condition. - properties: - - !ruby/object:Api::Type::String - name: 'sqlExpression' - description: | - The SQL expression. - - !ruby/object:Api::Type::NestedObject - name: 'tableConditionExpectation' - output: true - description: | - Table rule which evaluates whether the provided expression is true. - properties: - - !ruby/object:Api::Type::String - name: 'sqlExpression' - description: | - The SQL expression. - - !ruby/object:Api::Type::Boolean - name: 'passed' - output: true - description: | - Whether the rule passed or failed. - - !ruby/object:Api::Type::String - name: 'evaluatedCount' - output: true - description: | - The number of rows a rule was evaluated against. This field is only valid for ColumnMap type rules. - Evaluated count can be configured to either - 1. include all rows (default) - with null rows automatically failing rule evaluation, or - 2. exclude null rows from the evaluatedCount, by setting ignore_nulls = true. - - !ruby/object:Api::Type::String - name: 'passedCount' - output: true - description: | - The number of rows which passed a rule evaluation. This field is only valid for ColumnMap type rules. - - !ruby/object:Api::Type::String - name: 'nullCount' - output: true - description: | - The number of rows with null values in the specified column. - - !ruby/object:Api::Type::Integer - name: 'passRatio' - output: true - description: | - The ratio of passedCount / evaluatedCount. This field is only valid for ColumnMap type rules. - - !ruby/object:Api::Type::String - name: 'failingRowsQuery' - output: true - description: | - The query to find rows that did not pass this rule. Only applies to ColumnMap and RowCondition rules. - - !ruby/object:Api::Type::String - name: 'rowCount' - output: true - description: | - The count of rows processed. - - !ruby/object:Api::Type::NestedObject - name: 'scannedData' - output: true - description: | - The data scanned for this result. - properties: - - !ruby/object:Api::Type::NestedObject - name: 'incrementalField' - description: | - The range denoted by values of an incremental field - properties: - - !ruby/object:Api::Type::String - name: 'field' - description: | - The field that contains values which monotonically increases over time (e.g. a timestamp column). - - !ruby/object:Api::Type::String - name: 'start' - description: | - Value that marks the start of the range. - - !ruby/object:Api::Type::String - name: 'end' - description: Value that marks the end of the range. - - !ruby/object:Api::Type::NestedObject - name: 'dataProfileResult' - output: true - description: | - The result of the data profile scan. - properties: - - !ruby/object:Api::Type::String - name: 'rowCount' - description: | - The count of rows scanned. - - !ruby/object:Api::Type::NestedObject - name: 'profile' - output: true - description: | - The profile information per field. - properties: - - !ruby/object:Api::Type::Array - name: 'fields' - description: | - List of fields with structural and profile information for each field. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::String - name: 'name' - description: | - The name of the field. - - !ruby/object:Api::Type::String - name: 'type' - description: | - The field data type. - - !ruby/object:Api::Type::String - name: 'mode' - description: | - The mode of the field. Possible values include: - 1. REQUIRED, if it is a required field. - 2. NULLABLE, if it is an optional field. - 3. REPEATED, if it is a repeated field. - - !ruby/object:Api::Type::NestedObject - name: 'profile' - description: | - Profile information for the corresponding field. - properties: - - !ruby/object:Api::Type::Integer - name: 'nullRatio' - output: true - description: | - Ratio of rows with null value against total scanned rows. - - !ruby/object:Api::Type::Integer - name: 'distinctRatio' - description: | - Ratio of rows with distinct values against total scanned rows. Not available for complex non-groupable field type RECORD and fields with REPEATABLE mode. - - !ruby/object:Api::Type::NestedObject - name: 'topNValues' - description: | - The list of top N non-null values and number of times they occur in the scanned data. N is 10 or equal to the number of distinct values in the field, whichever is smaller. Not available for complex non-groupable field type RECORD and fields with REPEATABLE mode. - properties: - - !ruby/object:Api::Type::String - name: 'value' - description: | - String value of a top N non-null value. - - !ruby/object:Api::Type::String - name: 'count' - description: | - Count of the corresponding value in the scanned data. - - !ruby/object:Api::Type::NestedObject - name: 'stringProfile' - output: true - description: | - String type field information. - properties: - - !ruby/object:Api::Type::String - name: 'minLength' - description: | - Minimum length of non-null values in the scanned data. - - !ruby/object:Api::Type::String - name: 'maxLength' - description: | - Maximum length of non-null values in the scanned data. - - !ruby/object:Api::Type::Integer - name: 'averageLength' - description: | - Average length of non-null values in the scanned data. - - !ruby/object:Api::Type::NestedObject - name: 'integerProfile' - output: true - description: | - Integer type field information. - properties: - - !ruby/object:Api::Type::Integer - name: 'average' - description: | - Average of non-null values in the scanned data. NaN, if the field has a NaN. - - !ruby/object:Api::Type::Integer - name: 'standardDeviation' - description: | - Standard deviation of non-null values in the scanned data. NaN, if the field has a NaN. - - !ruby/object:Api::Type::String - name: 'min' - description: | - Minimum of non-null values in the scanned data. NaN, if the field has a NaN. - - !ruby/object:Api::Type::String - name: 'quartiles' - description: | - A quartile divides the number of data points into four parts, or quarters, of more-or-less equal size. Three main quartiles used are: The first quartile (Q1) splits off the lowest 25% of data from the highest 75%. It is also known as the lower or 25th empirical quartile, as 25% of the data is below this point. The second quartile (Q2) is the median of a data set. So, 50% of the data lies below this point. The third quartile (Q3) splits off the highest 25% of data from the lowest 75%. It is known as the upper or 75th empirical quartile, as 75% of the data lies below this point. Here, the quartiles is provided as an ordered list of quartile values for the scanned data, occurring in order Q1, median, Q3. - - !ruby/object:Api::Type::String - name: 'max' - description: | - Maximum of non-null values in the scanned data. NaN, if the field has a NaN. - - !ruby/object:Api::Type::NestedObject - name: 'doubleProfile' - output: true - description: | - Double type field information. - properties: - - !ruby/object:Api::Type::Integer - name: 'average' - description: | - Average of non-null values in the scanned data. NaN, if the field has a NaN. - - !ruby/object:Api::Type::Integer - name: 'standardDeviation' - description: | - Standard deviation of non-null values in the scanned data. NaN, if the field has a NaN. - - !ruby/object:Api::Type::String - name: 'min' - description: | - Minimum of non-null values in the scanned data. NaN, if the field has a NaN. - - !ruby/object:Api::Type::String - name: 'quartiles' - description: | - A quartile divides the number of data points into four parts, or quarters, of more-or-less equal size. Three main quartiles used are: The first quartile (Q1) splits off the lowest 25% of data from the highest 75%. It is also known as the lower or 25th empirical quartile, as 25% of the data is below this point. The second quartile (Q2) is the median of a data set. So, 50% of the data lies below this point. The third quartile (Q3) splits off the highest 25% of data from the lowest 75%. It is known as the upper or 75th empirical quartile, as 75% of the data lies below this point. Here, the quartiles is provided as an ordered list of quartile values for the scanned data, occurring in order Q1, median, Q3. - - !ruby/object:Api::Type::String - name: 'max' - description: | - Maximum of non-null values in the scanned data. NaN, if the field has a NaN. - - !ruby/object:Api::Type::NestedObject - name: 'scannedData' - output: true - description: The data scanned for this result. - properties: - - !ruby/object:Api::Type::NestedObject - name: 'incrementalField' - description: | - The range denoted by values of an incremental field - properties: - - !ruby/object:Api::Type::String - name: 'field' - description: | - The field that contains values which monotonically increases over time (e.g. a timestamp column). - - !ruby/object:Api::Type::String - name: 'start' - description: | - Value that marks the start of the range. - - !ruby/object:Api::Type::String - name: 'end' - description: Value that marks the end of the range. From f390fc92e3760d6d0ed37be6c8c48a50721c85c9 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Tue, 15 Aug 2023 12:45:38 -0700 Subject: [PATCH 07/67] Add new types KeyValueLabels and KeyValueAnnotations (#8519) * Add new type KeyValueLabels * Use KeyValueLabels in resource google_compute_address * func access_path in type * Add new type KeyValueAnnotations * Add new type KeyValueAnnotations * Fix the syntax error * Modify descriptions for labels field * Fix tests * Only read labels fingerprint when set labels * Remove version check * Fix tgc * Refactor code * Remove logger * New function properities_with_excluded * Address comments * Revert the TGC changes * Fix rake syntax errors * Fix the bug to set labels in the state * Type transform --- mmv1/api/resource.rb | 32 +++ mmv1/api/type.rb | 56 ++++ mmv1/compiler.rb | 1 + mmv1/products/bigquery/Dataset.yaml | 6 +- mmv1/products/compute/Address.yaml | 5 +- mmv1/provider/terraform.rb | 2 + .../examples/base_configs/test_file.go.erb | 2 +- .../terraform/expand_property_method.erb | 2 + .../terraform/flatten_property_method.erb | 13 + .../terraform/post_create/labels.erb | 4 + .../tests/resource_big_query_dataset_test.go | 149 ++++++++-- .../tests/resource_compute_address_test.go | 112 -------- .../resource_compute_address_test.go.erb | 256 ++++++++++++++++++ 13 files changed, 503 insertions(+), 137 deletions(-) delete mode 100644 mmv1/third_party/terraform/tests/resource_compute_address_test.go create mode 100644 mmv1/third_party/terraform/tests/resource_compute_address_test.go.erb diff --git a/mmv1/api/resource.rb b/mmv1/api/resource.rb index 799420f2dd80..42766e6c9afc 100644 --- a/mmv1/api/resource.rb +++ b/mmv1/api/resource.rb @@ -338,6 +338,10 @@ def all_properties ((@properties || []) + (@parameters || [])) end + def properties_with_excluded + @properties || [] + end + def properties (@properties || []).reject(&:exclude) end @@ -435,6 +439,34 @@ def decoder? !@transport&.decoder.nil? end + def add_labels_related_fields(props) + props.each do |p| + if p.is_a? Api::Type::KeyValueLabels + props << build_effective_labels_field('labels', p.field_min_version) + elsif p.is_a? Api::Type::KeyValueAnnotations + props << build_effective_labels_field('annotations', p.field_min_version) + elsif (p.is_a? Api::Type::NestedObject) && !p.all_properties.nil? + p.properties = add_labels_related_fields(p.all_properties) + end + end + props + end + + def build_effective_labels_field(name, min_version) + 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::KeyValuePairs.new( + name: "effective_#{name}", + output: true, + api_name: name, + description:, + min_version:, + ignore_write: true + ) + end + # ==================== # Version-related methods # ==================== diff --git a/mmv1/api/type.rb b/mmv1/api/type.rb index 2d0900b1fd7d..d8b505199993 100644 --- a/mmv1/api/type.rb +++ b/mmv1/api/type.rb @@ -266,6 +266,14 @@ def lineage "#{__parent.lineage}.#{name&.underscore}" end + # 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(). + def terraform_lineage + return name&.underscore if __parent.nil? + + "#{__parent.terraform_lineage}.0.#{name&.underscore}" + end + def to_json(opts = nil) # ignore fields that will contain references to parent resources and # those which will be added later @@ -728,6 +736,8 @@ def properties @properties.reject(&:exclude) end + attr_writer :properties + def nested_properties properties end @@ -755,6 +765,52 @@ def exclude_if_not_in_version!(version) # simpler property to generate and means we can avoid conditional logic # in Map. class KeyValuePairs < Composite + # Ignore writing the "effective_labels" and "effective_annotations" fields to API. + attr_reader :ignore_write + + def initialize(name: nil, output: nil, api_name: nil, description: nil, min_version: nil, + ignore_write: nil) + super() + + @name = name + @output = output + @api_name = api_name + @description = description + @min_version = min_version + @ignore_write = ignore_write + end + + def validate + super + check :ignore_write, type: :boolean, default: false + end + + def field_min_version + @min_version + end + end + + # An array of string -> string key -> value pairs used specifically for the "labels" field. + # The field name with this type should be "labels" literally. + class KeyValueLabels < KeyValuePairs + def validate + super + return unless @name != 'labels' + + raise "The field #{name} has the type KeyValueLabels, but the field name is not 'labels'!" + end + end + + # An array of string -> string key -> value pairs used specifically for the "annotations" field. + # The field name with this type should be "annotations" literally. + class KeyValueAnnotations < KeyValuePairs + def validate + super + return unless @name != 'annotations' + + raise "The field #{name} has the type KeyValueAnnotations,\ + but the field name is not 'annotations'!" + end end # Map from string keys -> nested object entries diff --git a/mmv1/compiler.rb b/mmv1/compiler.rb index 00a414c0552a..0ca7dc22b610 100755 --- a/mmv1/compiler.rb +++ b/mmv1/compiler.rb @@ -223,6 +223,7 @@ end res_yaml = File.read(file_path) resource = Api::Compiler.new(res_yaml).run + resource.properties = resource.add_labels_related_fields(resource.properties_with_excluded) resource.validate resources.push(resource) end diff --git a/mmv1/products/bigquery/Dataset.yaml b/mmv1/products/bigquery/Dataset.yaml index 7cd95a4eb7f1..2fb36dfc2c06 100644 --- a/mmv1/products/bigquery/Dataset.yaml +++ b/mmv1/products/bigquery/Dataset.yaml @@ -290,12 +290,14 @@ properties: name: 'friendlyName' description: A descriptive name for the dataset send_empty_value: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | The labels associated with this dataset. You can use these to organize and group your datasets - default_from_api: true + + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field `effective_labels` for all of the labels present on the resource. - !ruby/object:Api::Type::Integer name: 'lastModifiedTime' description: | diff --git a/mmv1/products/compute/Address.yaml b/mmv1/products/compute/Address.yaml index 59a26cd3b1bd..cd80696c04ba 100644 --- a/mmv1/products/compute/Address.yaml +++ b/mmv1/products/compute/Address.yaml @@ -194,10 +194,13 @@ properties: description: 'The URLs of the resources that are using this address.' item_type: Api::Type::String output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels to apply to this address. A list of key->value pairs. + + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field `effective_labels` for all of the labels present on the resource. update_verb: :POST update_url: 'projects/{{project}}/regions/{{region}}/addresses/{{name}}/setLabels' min_version: beta diff --git a/mmv1/provider/terraform.rb b/mmv1/provider/terraform.rb index 220b52b62e23..753f1479f23c 100644 --- a/mmv1/provider/terraform.rb +++ b/mmv1/provider/terraform.rb @@ -91,6 +91,8 @@ def tf_types Api::Type::NestedObject => 'schema.TypeList', Api::Type::Array => 'schema.TypeList', Api::Type::KeyValuePairs => 'schema.TypeMap', + Api::Type::KeyValueLabels => 'schema.TypeMap', + Api::Type::KeyValueAnnotations => 'schema.TypeMap', Api::Type::Map => 'schema.TypeSet', Api::Type::Fingerprint => 'schema.TypeString' } diff --git a/mmv1/templates/terraform/examples/base_configs/test_file.go.erb b/mmv1/templates/terraform/examples/base_configs/test_file.go.erb index 967d78cb63c7..40eafa9afadc 100644 --- a/mmv1/templates/terraform/examples/base_configs/test_file.go.erb +++ b/mmv1/templates/terraform/examples/base_configs/test_file.go.erb @@ -44,7 +44,7 @@ object.examples test_slug = "#{resource_name}_#{example.name.camelize(:lower)}Example" ignore_read = object.all_user_properties - .select{|p| p.url_param_only || p.ignore_read || p.is_a?(Api::Type::ResourceRef) } + .select{|p| p.url_param_only || p.ignore_read || p.is_a?(Api::Type::ResourceRef) || p.is_a?(Api::Type::KeyValueLabels || p.is_a?(Api::Type::KeyValueAnnotations))} .map { |p| p.name.underscore } .concat(example.ignore_read_extra) diff --git a/mmv1/templates/terraform/expand_property_method.erb b/mmv1/templates/terraform/expand_property_method.erb index d3a034e84ca2..880242320bd5 100644 --- a/mmv1/templates/terraform/expand_property_method.erb +++ b/mmv1/templates/terraform/expand_property_method.erb @@ -130,6 +130,7 @@ func expand<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d t transformed := make(map[string]interface{}) <% property.nested_properties.each do |prop| -%> +<% next if prop.is_a?(Api::Type::KeyValuePairs) && prop.ignore_write -%> transformed<%= titlelize_property(prop) -%>, err := expand<%= prefix -%><%= titlelize_property(property) -%><%= titlelize_property(prop) -%>(original["<%= prop.name.underscore -%>"], d, config) if err != nil { return nil, err @@ -175,6 +176,7 @@ func expand<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d t <% if !property.nested_properties.nil? -%> <% property.nested_properties.each do |prop| -%> +<% next if prop.is_a?(Api::Type::KeyValuePairs) && prop.ignore_write -%> <%# Map is a map from {key -> object} in the API, but Terraform can't represent that so we treat the key as a property of the object in Terraform schema. %> <%= lines(build_expand_method(prefix + titlelize_property(property), prop, object, pwd), 1) -%> diff --git a/mmv1/templates/terraform/flatten_property_method.erb b/mmv1/templates/terraform/flatten_property_method.erb index ed6eda44afcc..5f8fdb875590 100644 --- a/mmv1/templates/terraform/flatten_property_method.erb +++ b/mmv1/templates/terraform/flatten_property_method.erb @@ -93,6 +93,19 @@ func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d <% end -%> }) } + return transformed +<% elsif (property.is_a?(Api::Type::KeyValueLabels)) || (property.is_a?(Api::Type::KeyValueAnnotations)) -%> + if v == nil { + return v + } + + transformed := make(map[string]interface{}) + if l, ok := d.GetOkExists("<%= property.terraform_lineage -%>"); ok { + for k := range l.(map[string]interface{}) { + transformed[k] = v.(map[string]interface{})[k] + } + } + return transformed <% elsif property.is_a?(Api::Type::Integer) -%> // Handles the string fixed64 format diff --git a/mmv1/templates/terraform/post_create/labels.erb b/mmv1/templates/terraform/post_create/labels.erb index 83c6dcea64a9..e725830eaabd 100644 --- a/mmv1/templates/terraform/post_create/labels.erb +++ b/mmv1/templates/terraform/post_create/labels.erb @@ -46,5 +46,9 @@ if v, ok := d.GetOkExists("labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v return err } + // Set back the labels field, as it is needed to decide the value of "labels" in the state in the read function. + if err := d.Set("labels", v); err != nil { + return fmt.Errorf("Error setting back labels: %s", err) + } } <% end -%> diff --git a/mmv1/third_party/terraform/tests/resource_big_query_dataset_test.go b/mmv1/third_party/terraform/tests/resource_big_query_dataset_test.go index 0c3ed02f1af1..c31e9b00b294 100644 --- a/mmv1/third_party/terraform/tests/resource_big_query_dataset_test.go +++ b/mmv1/third_party/terraform/tests/resource_big_query_dataset_test.go @@ -22,7 +22,11 @@ func TestAccBigQueryDataset_basic(t *testing.T) { CheckDestroy: testAccCheckBigQueryDatasetDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccBigQueryDataset(datasetID), + Config: testAccBigQueryDataset_withoutLabels(datasetID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckNoResourceAttr("google_bigquery_dataset.test", "labels.%"), + resource.TestCheckNoResourceAttr("google_bigquery_dataset.test", "effective_labels.%"), + ), }, { ResourceName: "google_bigquery_dataset.test", @@ -30,16 +34,59 @@ func TestAccBigQueryDataset_basic(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccBigQueryDatasetUpdated(datasetID), + 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"}, + }, + { + Config: testAccBigQueryDatasetUpdated(datasetID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "labels.%", "2"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "labels.env", "bar"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "labels.default_table_expiration_ms", "7200000"), + + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "effective_labels.%", "2"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "effective_labels.env", "bar"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "effective_labels.default_table_expiration_ms", "7200000"), + ), + }, + { + ResourceName: "google_bigquery_dataset.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels"}, }, { Config: testAccBigQueryDatasetUpdated2(datasetID), }, + { + ResourceName: "google_bigquery_dataset.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels"}, + }, + { + Config: testAccBigQueryDataset_withoutLabels(datasetID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckNoResourceAttr("google_bigquery_dataset.test", "labels.%"), + resource.TestCheckNoResourceAttr("google_bigquery_dataset.test", "effective_labels.%"), + ), + }, { ResourceName: "google_bigquery_dataset.test", ImportState: true, @@ -49,6 +96,47 @@ func TestAccBigQueryDataset_basic(t *testing.T) { }) } +func TestAccBigQueryDataset_withProvider5(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + datasetID := fmt.Sprintf("tf_test_%s", acctest.RandString(t, 10)) + oldVersion := map[string]resource.ExternalProvider{ + "google": { + VersionConstraint: "4.75.0", // a version that doesn't separate user defined labels and system labels + Source: "registry.terraform.io/hashicorp/google", + }, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + CheckDestroy: testAccCheckBigQueryDatasetDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigQueryDataset_withoutLabels(datasetID), + ExternalProviders: oldVersion, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckNoResourceAttr("google_bigquery_dataset.test", "labels.%"), + resource.TestCheckNoResourceAttr("google_bigquery_dataset.test", "effective_labels.%"), + ), + }, + { + Config: testAccBigQueryDataset(datasetID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + 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"), + ), + }, + }, + }) +} + func TestAccBigQueryDataset_datasetWithContents(t *testing.T) { t.Parallel() @@ -68,7 +156,7 @@ func TestAccBigQueryDataset_datasetWithContents(t *testing.T) { ResourceName: "google_bigquery_dataset.contents_test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"delete_contents_on_destroy"}, + ImportStateVerifyIgnore: []string{"delete_contents_on_destroy", "labels"}, }, }, }) @@ -90,33 +178,37 @@ func TestAccBigQueryDataset_access(t *testing.T) { Config: testAccBigQueryDatasetWithOneAccess(datasetID), }, { - ResourceName: "google_bigquery_dataset.access_test", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_bigquery_dataset.access_test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels"}, }, { Config: testAccBigQueryDatasetWithTwoAccess(datasetID), }, { - ResourceName: "google_bigquery_dataset.access_test", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_bigquery_dataset.access_test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels"}, }, { Config: testAccBigQueryDatasetWithOneAccess(datasetID), }, { - ResourceName: "google_bigquery_dataset.access_test", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_bigquery_dataset.access_test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels"}, }, { Config: testAccBigQueryDatasetWithViewAccess(datasetID, otherDatasetID, otherTableID), }, { - ResourceName: "google_bigquery_dataset.access_test", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_bigquery_dataset.access_test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels"}, }, }, }) @@ -136,9 +228,10 @@ func TestAccBigQueryDataset_regionalLocation(t *testing.T) { Config: testAccBigQueryRegionalDataset(datasetID1, "asia-south1"), }, { - ResourceName: "google_bigquery_dataset.test", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_bigquery_dataset.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels"}, }, }, }) @@ -181,9 +274,10 @@ func TestAccBigQueryDataset_storageBillModel(t *testing.T) { Config: testAccBigQueryDatasetStorageBillingModel(datasetID), }, { - ResourceName: "google_bigquery_dataset.test", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_bigquery_dataset.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels"}, }, }, }) @@ -208,6 +302,19 @@ func testAccAddTable(t *testing.T, datasetID string, tableID string) resource.Te } } +func testAccBigQueryDataset_withoutLabels(datasetID string) string { + return fmt.Sprintf(` +resource "google_bigquery_dataset" "test" { + dataset_id = "%s" + friendly_name = "foo" + description = "This is a foo description" + location = "EU" + default_partition_expiration_ms = 3600000 + default_table_expiration_ms = 3600000 +} +`, datasetID) +} + func testAccBigQueryDataset(datasetID string) string { return fmt.Sprintf(` resource "google_bigquery_dataset" "test" { diff --git a/mmv1/third_party/terraform/tests/resource_compute_address_test.go b/mmv1/third_party/terraform/tests/resource_compute_address_test.go deleted file mode 100644 index afab1990ba55..000000000000 --- a/mmv1/third_party/terraform/tests/resource_compute_address_test.go +++ /dev/null @@ -1,112 +0,0 @@ -package google - -import ( - "fmt" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" - "github.com/hashicorp/terraform-provider-google/google/acctest" -) - -func TestAccComputeAddress_networkTier(t *testing.T) { - t.Parallel() - - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckComputeAddressDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccComputeAddress_networkTier(acctest.RandString(t, 10)), - }, - { - ResourceName: "google_compute_address.foobar", - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func TestAccComputeAddress_internal(t *testing.T) { - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckComputeAddressDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccComputeAddress_internal(acctest.RandString(t, 10)), - }, - { - ResourceName: "google_compute_address.internal", - ImportState: true, - ImportStateVerify: true, - }, - - { - ResourceName: "google_compute_address.internal_with_subnet", - ImportState: true, - ImportStateVerify: true, - }, - - { - ResourceName: "google_compute_address.internal_with_subnet_and_address", - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func testAccComputeAddress_internal(i string) string { - return fmt.Sprintf(` -resource "google_compute_address" "internal" { - name = "tf-test-address-internal-%s" - address_type = "INTERNAL" - region = "us-east1" -} - -resource "google_compute_network" "default" { - name = "tf-test-network-test-%s" -} - -resource "google_compute_subnetwork" "foo" { - name = "subnetwork-test-%s" - ip_cidr_range = "10.0.0.0/16" - region = "us-east1" - network = google_compute_network.default.self_link -} - -resource "google_compute_address" "internal_with_subnet" { - name = "tf-test-address-internal-with-subnet-%s" - subnetwork = google_compute_subnetwork.foo.self_link - address_type = "INTERNAL" - region = "us-east1" -} - -// We can't test the address alone, because we don't know what IP range the -// default subnetwork uses. -resource "google_compute_address" "internal_with_subnet_and_address" { - name = "tf-test-address-internal-with-subnet-and-address-%s" - subnetwork = google_compute_subnetwork.foo.self_link - address_type = "INTERNAL" - address = "10.0.42.42" - region = "us-east1" -} -`, - i, // google_compute_address.internal name - i, // google_compute_network.default name - i, // google_compute_subnetwork.foo name - i, // google_compute_address.internal_with_subnet_name - i, // google_compute_address.internal_with_subnet_and_address name - ) -} - -func testAccComputeAddress_networkTier(i string) string { - return fmt.Sprintf(` -resource "google_compute_address" "foobar" { - name = "tf-test-address-%s" - network_tier = "STANDARD" -} -`, i) -} diff --git a/mmv1/third_party/terraform/tests/resource_compute_address_test.go.erb b/mmv1/third_party/terraform/tests/resource_compute_address_test.go.erb new file mode 100644 index 000000000000..11987ad189ab --- /dev/null +++ b/mmv1/third_party/terraform/tests/resource_compute_address_test.go.erb @@ -0,0 +1,256 @@ +<% autogen_exception -%> + +package google + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccComputeAddress_networkTier(t *testing.T) { + t.Parallel() + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeAddressDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeAddress_networkTier(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckNoResourceAttr("google_compute_address.foobar", "labels.%"), + resource.TestCheckNoResourceAttr("google_compute_address.foobar", "effective_labels.%"), + ), + }, + }, + }) +} + +func TestAccComputeAddress_internal(t *testing.T) { + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeAddressDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeAddress_internal(acctest.RandString(t, 10)), + }, + { + ResourceName: "google_compute_address.internal", + ImportState: true, + ImportStateVerify: true, + }, + + { + ResourceName: "google_compute_address.internal_with_subnet", + ImportState: true, + ImportStateVerify: true, + }, + + { + ResourceName: "google_compute_address.internal_with_subnet_and_address", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +<% unless version == "ga" -%> +func TestAccComputeAddress_networkTier_withLabels(t *testing.T) { + t.Parallel() + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeAddressDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeAddress_networkTier(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckNoResourceAttr("google_compute_address.foobar", "labels.%"), + resource.TestCheckNoResourceAttr("google_compute_address.foobar", "effective_labels.%"), + ), + }, + { + ResourceName: "google_compute_address.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeAddress_networkTier_withLabels(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.%", "2"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.env", "foo"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.%", "2"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.env", "foo"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.default_expiration_ms", "3600000"), + ), + }, + { + ResourceName: "google_compute_address.foobar", + 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"}, + }, + { + Config: testAccComputeAddress_networkTier_withLabelsUpdate(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.%", "2"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.env", "bar"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.default_expiration_ms", "7200000"), + + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.%", "2"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.env", "bar"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.default_expiration_ms", "7200000"), + ), + }, + { + ResourceName: "google_compute_address.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels"}, + }, + { + Config: testAccComputeAddress_networkTier(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckNoResourceAttr("google_compute_address.foobar", "labels.%"), + resource.TestCheckNoResourceAttr("google_compute_address.foobar", "effective_labels.%"), + ), + }, + { + ResourceName: "google_compute_address.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccComputeAddress_networkTier_withProvider5(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + oldVersion := map[string]resource.ExternalProvider{ + "google": { + VersionConstraint: "4.75.0", // a version that doesn't separate user defined labels and system labels + Source: "registry.terraform.io/hashicorp/google", + }, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + Steps: []resource.TestStep{ + { + Config: testAccComputeAddress_networkTier(acctest.RandString(t, 10)), + ExternalProviders: oldVersion, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckNoResourceAttr("google_compute_address.foobar", "labels.%"), + resource.TestCheckNoResourceAttr("google_compute_address.foobar", "effective_labels.%"), + ), + }, + { + Config: testAccComputeAddress_networkTier_withLabels(acctest.RandString(t, 10)), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.%", "2"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.env", "foo"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.%", "2"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.env", "foo"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.default_expiration_ms", "3600000"), + ), + }, + }, + }) +} + +func testAccComputeAddress_networkTier_withLabels(i string) string { + return fmt.Sprintf(` +resource "google_compute_address" "foobar" { + name = "tf-test-address-%s" + network_tier = "STANDARD" + + labels = { + env = "foo" + default_expiration_ms = 3600000 + } +} +`, i) +} + +func testAccComputeAddress_networkTier_withLabelsUpdate(i string) string { + return fmt.Sprintf(` +resource "google_compute_address" "foobar" { + name = "tf-test-address-%s" + network_tier = "STANDARD" + + labels = { + env = "bar" + default_expiration_ms = 7200000 + } +} +`, i) +} +<% end -%> + +func testAccComputeAddress_internal(i string) string { + return fmt.Sprintf(` +resource "google_compute_address" "internal" { + name = "tf-test-address-internal-%s" + address_type = "INTERNAL" + region = "us-east1" +} + +resource "google_compute_network" "default" { + name = "tf-test-network-test-%s" +} + +resource "google_compute_subnetwork" "foo" { + name = "subnetwork-test-%s" + ip_cidr_range = "10.0.0.0/16" + region = "us-east1" + network = google_compute_network.default.self_link +} + +resource "google_compute_address" "internal_with_subnet" { + name = "tf-test-address-internal-with-subnet-%s" + subnetwork = google_compute_subnetwork.foo.self_link + address_type = "INTERNAL" + region = "us-east1" +} + +// We can't test the address alone, because we don't know what IP range the +// default subnetwork uses. +resource "google_compute_address" "internal_with_subnet_and_address" { + name = "tf-test-address-internal-with-subnet-and-address-%s" + subnetwork = google_compute_subnetwork.foo.self_link + address_type = "INTERNAL" + address = "10.0.42.42" + region = "us-east1" +} +`, + i, // google_compute_address.internal name + i, // google_compute_network.default name + i, // google_compute_subnetwork.foo name + i, // google_compute_address.internal_with_subnet_name + i, // google_compute_address.internal_with_subnet_and_address name + ) +} + +func testAccComputeAddress_networkTier(i string) string { + return fmt.Sprintf(` +resource "google_compute_address" "foobar" { + name = "tf-test-address-%s" + network_tier = "STANDARD" +} +`, i) +} \ No newline at end of file From 1ac6933c3664f1afb8a4c5b4739fe09a416e318f Mon Sep 17 00:00:00 2001 From: wj-chen Date: Tue, 15 Aug 2023 14:35:18 -0700 Subject: [PATCH 08/67] make routineType required in the BigQuery Routine resource (#8573) --- mmv1/products/bigquery/Routine.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/mmv1/products/bigquery/Routine.yaml b/mmv1/products/bigquery/Routine.yaml index 054100c13ee9..7e57fd7dd1fb 100644 --- a/mmv1/products/bigquery/Routine.yaml +++ b/mmv1/products/bigquery/Routine.yaml @@ -76,6 +76,7 @@ properties: - !ruby/object:Api::Type::Enum name: 'routineType' immutable: true + required: true description: The type of routine. values: - :SCALAR_FUNCTION From 764e379a95749de51d9b23af52ff706338ae232d Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Tue, 15 Aug 2023 14:48:09 -0700 Subject: [PATCH 09/67] Add default value to metric.filter in the resource google_compute_autoscaler (#8327) --- mmv1/products/compute/Autoscaler.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/mmv1/products/compute/Autoscaler.yaml b/mmv1/products/compute/Autoscaler.yaml index e10212ef636b..8c66621727e9 100644 --- a/mmv1/products/compute/Autoscaler.yaml +++ b/mmv1/products/compute/Autoscaler.yaml @@ -367,6 +367,7 @@ properties: TimeSeries are returned upon the query execution, the autoscaler will sum their respective values to obtain its scaling value. min_version: beta + default_value: 'resource.type = gce_instance' - !ruby/object:Api::Type::NestedObject name: 'loadBalancingUtilization' description: | From 5de4e819d97f33c08b15a6329d82c9dbd290eb77 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Tue, 15 Aug 2023 14:59:49 -0700 Subject: [PATCH 10/67] Modify labels fields for DCL resources (#8563) * Modify labels fields * effective_labels filed is not optional * Add tests for labels * Append notes for lables description * Fix the notes --- ...esource_cloudbuild_worker_pool_test.go.erb | 6 +++ ...rce_dataproc_workflow_template_test.go.erb | 9 ++++ .../samples/asset/basic_asset.tf.tmpl | 6 +++ tpgtools/property.go | 39 ++++++++++++++++ tpgtools/resource.go | 44 +++++++++++++++++++ tpgtools/templates/resource.go.tmpl | 34 ++++++++++++++ 6 files changed, 138 insertions(+) diff --git a/mmv1/third_party/terraform/tests/resource_cloudbuild_worker_pool_test.go.erb b/mmv1/third_party/terraform/tests/resource_cloudbuild_worker_pool_test.go.erb index 8dc25191686e..acfef3e1978b 100644 --- a/mmv1/third_party/terraform/tests/resource_cloudbuild_worker_pool_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_cloudbuild_worker_pool_test.go.erb @@ -41,6 +41,7 @@ func TestAccCloudbuildWorkerPool_basic(t *testing.T) { { ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations"}, ResourceName: "google_cloudbuild_worker_pool.pool", }, { @@ -79,6 +80,11 @@ resource "google_cloudbuild_worker_pool" "pool" { machine_type = "e2-standard-4" no_external_ip = false } + + annotations = { + env = "foo" + default_expiration_ms = 3600000 + } } `, context) } diff --git a/mmv1/third_party/terraform/tests/resource_dataproc_workflow_template_test.go.erb b/mmv1/third_party/terraform/tests/resource_dataproc_workflow_template_test.go.erb index a277266a01a4..495e7d8e8f73 100644 --- a/mmv1/third_party/terraform/tests/resource_dataproc_workflow_template_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_dataproc_workflow_template_test.go.erb @@ -37,6 +37,10 @@ func TestAccDataprocWorkflowTemplate_basic(t *testing.T) { { ImportState: true, ImportStateVerify: true, + // The "labels" field in the state are decided by the configuration. + // During importing, as the configuration is unavailableafter, the "labels" field in the state will be empty. + // So add the "labels" to the ImportStateVerifyIgnore list. + ImportStateVerifyIgnore: []string{"labels"}, ResourceName: "google_dataproc_workflow_template.template", }, }, @@ -124,6 +128,11 @@ resource "google_dataproc_workflow_template" "template" { query_file_uri = "someuri" } } + + labels = { + env = "foo" + somekey = "somevalue" + } } `, context) } diff --git a/tpgtools/overrides/dataplex/samples/asset/basic_asset.tf.tmpl b/tpgtools/overrides/dataplex/samples/asset/basic_asset.tf.tmpl index 07c9141bb937..d3f18d1990dd 100644 --- a/tpgtools/overrides/dataplex/samples/asset/basic_asset.tf.tmpl +++ b/tpgtools/overrides/dataplex/samples/asset/basic_asset.tf.tmpl @@ -52,6 +52,12 @@ resource "google_dataplex_asset" "primary" { name = "projects/{{project}}/buckets/{{bucket}}" type = "STORAGE_BUCKET" } + + labels = { + env = "foo" + my-asset = "exists" + } + project = "{{project}}" depends_on = [ diff --git a/tpgtools/property.go b/tpgtools/property.go index 0ee26f2af299..0292c3124857 100644 --- a/tpgtools/property.go +++ b/tpgtools/property.go @@ -311,6 +311,10 @@ func (p Property) DefaultStateSetter() string { case SchemaTypeFloat: fallthrough case SchemaTypeMap: + if p.IsResourceLabels() || p.IsResourceAnnotations() { + return fmt.Sprintf("d.Set(%q, flatten%s%s(res.%s, d))", p.Name(), p.resource.PathType(), p.PackagePath(), p.PackageName) + } + return fmt.Sprintf("d.Set(%q, res.%s)", p.Name(), p.PackageName) case SchemaTypeList, SchemaTypeSet: if p.typ.Items != nil && ((p.typ.Items.Type == "string" && len(p.typ.Items.Enum) == 0) || p.typ.Items.Type == "integer") { @@ -440,6 +444,14 @@ func (p Property) Objects() (props []Property) { return props } +func (p Property) IsResourceLabels() bool { + return p.Name() == "labels" && p.parent == nil +} + +func (p Property) IsResourceAnnotations() bool { + return p.Name() == "annotations" && p.parent == nil +} + // collapsedProperties returns the input list of properties with nested objects collapsed if needed. func collapsedProperties(props []Property) (collapsed []Property) { for _, v := range props { @@ -878,6 +890,16 @@ func createPropertiesFromSchema(schema *openapi.Schema, typeFetcher *TypeFetcher resource.ReusedTypes = resource.RegisterReusedType(p) } + // Add the "effective_labels" property when the current property is top level "labels" or + // add the "effective_annotations" property when the current property is top level "annotations" + + if p.IsResourceLabels() || p.IsResourceAnnotations() { + note := "**Note**: This field is non-authoritative, and will only manage the labels present in your configuration. " + + "Please refer to the field `effective_labels` for all of the labels present on the resource." + p.Description = fmt.Sprintf("%s\n\n%s", p.Description, note) + props = append(props, build_effective_labels_field(p, resource, parent)) + } + props = append(props, p) } @@ -901,3 +923,20 @@ func createPropertiesFromSchema(schema *openapi.Schema, typeFetcher *TypeFetcher return props, nil } + +func build_effective_labels_field(p Property, resource *Resource, parent *Property) Property { + title := fmt.Sprintf("effective_%s", p.title) + description := fmt.Sprintf("All of %s (key/value pairs) present on the resource in GCP, including the %s configured through Terraform, other clients and services.", p.title, p.title) + stateSetter := fmt.Sprintf("d.Set(%q, res.%s)", title, p.PackageName) + + return Property{ + title: title, + Type: p.Type, + Description: description, + resource: resource, + parent: parent, + Optional: false, + Computed: true, + StateSetter: &stateSetter, + } +} diff --git a/tpgtools/resource.go b/tpgtools/resource.go index b65c2061f9f9..1e6f6e7a1498 100644 --- a/tpgtools/resource.go +++ b/tpgtools/resource.go @@ -381,6 +381,26 @@ func (r Resource) IDFunction() string { return "tpgresource.ReplaceVarsForId" } +// Check if the resource has the lables field for the resource +func (r Resource) HasLabels() bool { + for _, p := range r.Properties { + if p.IsResourceLabels() { + return true + } + } + return false +} + +// Check if the resource has the annotations field for the resource +func (r Resource) HasAnnotations() bool { + for _, p := range r.Properties { + if p.IsResourceAnnotations() { + return true + } + } + return false +} + // ResourceInput is a Resource along with additional generation metadata. type ResourceInput struct { Resource @@ -810,6 +830,18 @@ func (r *Resource) loadHandWrittenSamples() []Sample { sample.Name = &sampleName } sample.TestSlug = RenderedString(snakeToTitleCase(miscellaneousNameSnakeCase(sampleName)).titlecase() + "HandWritten") + + // The "labels" and "annotations" fields in the state are decided by the configuration. + // During importing, as the configuration is unavailableafter, the "labels" and "annotations" fields in the state will be empty. + // So add the "labels" and the "annotations" fields to the ImportStateVerifyIgnore list. + if r.HasLabels() { + sample.IgnoreRead = append(sample.IgnoreRead, "labels") + } + + if r.HasAnnotations() { + sample.IgnoreRead = append(sample.IgnoreRead, "annotations") + } + samples = append(samples, sample) } @@ -896,6 +928,18 @@ func (r *Resource) loadDCLSamples() []Sample { } sample.DependencyList = dependencies sample.TestSlug = RenderedString(sampleNameToTitleCase(*sample.Name).titlecase()) + + // The "labels" and "annotations" fields in the state are decided by the configuration. + // During importing, as the configuration is unavailableafter, the "labels" and "annotations" fields in the state will be empty. + // So add the "labels" and the "annotations" fields to the ImportStateVerifyIgnore list. + if r.HasLabels() { + sample.IgnoreRead = append(sample.IgnoreRead, "labels") + } + + if r.HasAnnotations() { + sample.IgnoreRead = append(sample.IgnoreRead, "annotations") + } + samples = append(samples, sample) } diff --git a/tpgtools/templates/resource.go.tmpl b/tpgtools/templates/resource.go.tmpl index 532dd4c4c75b..a3f10f2db10b 100644 --- a/tpgtools/templates/resource.go.tmpl +++ b/tpgtools/templates/resource.go.tmpl @@ -714,6 +714,40 @@ func flatten{{$.PathType}}{{$v.PackagePath}}(obj *{{$.Package}}.{{$v.ObjectType} } {{ end -}} +{{ if $.HasLabels }} +func flatten{{$.PathType}}Labels(v map[string]string, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + + transformed := make(map[string]interface{}) + if l, ok := d.Get("labels").(map[string]interface{}); ok { + for k, _ := range l { + transformed[k] = l[k] + } + } + + return transformed +} +{{ end }} + +{{ if $.HasAnnotations }} +func flatten{{$.PathType}}Annotations(v map[string]string, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + + transformed := make(map[string]interface{}) + if l, ok := d.Get("annotations").(map[string]interface{}); ok { + for k, _ := range l { + transformed[k] = l[k] + } + } + + return transformed +} +{{ end }} + {{ range $v := .EnumArrays -}} func flatten{{$.PathType}}{{$v.PackagePath}}Array(obj []{{$.Package}}.{{$v.ObjectType}}Enum) interface{} { if obj == nil { From f94c19dbf29fa8e1c4a50a69668c02d9e558ed74 Mon Sep 17 00:00:00 2001 From: gfxcc Date: Wed, 16 Aug 2023 14:27:38 -0700 Subject: [PATCH 11/67] remove deprecated fields (#8531) --- mmv1/products/privateca/Certificate.yaml | 132 ----------------------- 1 file changed, 132 deletions(-) diff --git a/mmv1/products/privateca/Certificate.yaml b/mmv1/products/privateca/Certificate.yaml index 2d8b63d41544..67f04352cd18 100644 --- a/mmv1/products/privateca/Certificate.yaml +++ b/mmv1/products/privateca/Certificate.yaml @@ -544,131 +544,6 @@ properties: leading period (like `.example.com`) output: true item_type: Api::Type::String - - !ruby/object:Api::Type::NestedObject - name: 'configValues' - deprecation_message: Deprecated in favor of `x509_description`. - output: true - description: | - Describes some of the technical fields in a certificate. - properties: - - !ruby/object:Api::Type::NestedObject - name: 'keyUsage' - output: true - description: | - Indicates the intended use for keys that correspond to a certificate. - properties: - - !ruby/object:Api::Type::NestedObject - name: 'baseKeyUsage' - output: true - description: | - Describes high-level ways in which a key may be used. - properties: - - !ruby/object:Api::Type::NestedObject - name: 'keyUsageOptions' - output: true - description: | - Describes high-level ways in which a key may be used. - properties: - - !ruby/object:Api::Type::Boolean - name: 'digitalSignature' - output: true - description: | - The key may be used for digital signatures. - - !ruby/object:Api::Type::Boolean - name: 'contentCommitment' - output: true - description: | - The key may be used for cryptographic commitments. Note that this may also be referred to as "non-repudiation". - - !ruby/object:Api::Type::Boolean - name: 'keyEncipherment' - output: true - description: | - The key may be used to encipher other keys. - - !ruby/object:Api::Type::Boolean - name: 'dataEncipherment' - output: true - description: | - The key may be used to encipher data. - - !ruby/object:Api::Type::Boolean - name: 'keyAgreement' - output: true - description: | - The key may be used in a key agreement protocol. - - !ruby/object:Api::Type::Boolean - name: 'certSign' - output: true - description: | - The key may be used to sign certificates. - - !ruby/object:Api::Type::Boolean - name: 'crlSign' - output: true - description: | - The key may be used sign certificate revocation lists. - - !ruby/object:Api::Type::Boolean - name: 'encipherOnly' - output: true - description: | - The key may be used to encipher only. - - !ruby/object:Api::Type::Boolean - name: 'decipherOnly' - output: true - description: | - The key may be used to decipher only. - - !ruby/object:Api::Type::NestedObject - name: 'extendedKeyUsage' - output: true - description: | - Describes high-level ways in which a key may be used. - properties: - - !ruby/object:Api::Type::Boolean - name: 'serverAuth' - output: true - description: | - Corresponds to OID 1.3.6.1.5.5.7.3.1. Officially described as "TLS WWW server authentication", though regularly used for non-WWW TLS. - - !ruby/object:Api::Type::Boolean - name: 'clientAuth' - output: true - description: | - Corresponds to OID 1.3.6.1.5.5.7.3.2. Officially described as "TLS WWW client authentication", though regularly used for non-WWW TLS. - - !ruby/object:Api::Type::Boolean - name: 'codeSigning' - output: true - description: | - Corresponds to OID 1.3.6.1.5.5.7.3.3. Officially described as "Signing of downloadable executable code client authentication". - - !ruby/object:Api::Type::Boolean - name: 'emailProtection' - output: true - description: | - Corresponds to OID 1.3.6.1.5.5.7.3.4. Officially described as "Email protection". - - !ruby/object:Api::Type::Boolean - name: 'timeStamping' - output: true - description: | - Corresponds to OID 1.3.6.1.5.5.7.3.8. Officially described as "Binding the hash of an object to a time". - - !ruby/object:Api::Type::Boolean - name: 'ocspSigning' - output: true - description: | - Corresponds to OID 1.3.6.1.5.5.7.3.9. Officially described as "Signing OCSP responses". - - !ruby/object:Api::Type::Array - name: 'unknownExtendedKeyUsages' - output: true - description: | - An ObjectId specifies an object identifier (OID). These provide context and describe types in ASN.1 messages. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::NestedObject - name: 'obectId' - output: true - description: | - Required. Describes how some of the technical fields in a certificate should be populated. - properties: - - !ruby/object:Api::Type::Array - name: 'objectIdPath' - output: true - item_type: Api::Type::Integer - description: | - An ObjectId specifies an object identifier (OID). These provide context and describe types in ASN.1 messages. - !ruby/object:Api::Type::NestedObject name: 'publicKey' output: true @@ -739,13 +614,6 @@ properties: description: | The chain that may be used to verify the X.509 certificate. Expected to be in issuer-to-root order according to RFC 5246. item_type: Api::Type::String - - !ruby/object:Api::Type::Array - name: 'pemCertificates' - deprecation_message: Deprecated in favor of `pem_certificate_chain`. - output: true - description: | - Required. Expected to be in leaf-to-root order according to RFC 5246. - item_type: Api::Type::String - !ruby/object:Api::Type::Time name: 'createTime' description: | From 74d45a2e896ff15481d548da5fb0ad8d9af5c153 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Thu, 17 Aug 2023 12:40:25 -0700 Subject: [PATCH 12/67] Modify labels field for some handwritten resources (#8579) * Modify lables field * Fix description * Fix tests * Ignore labels for import state verify * Ignore labels for import state verify --- .../bigquery/resource_bigquery_table.go | 19 +++++++++++++++---- .../bigtable/resource_bigtable_instance.go | 19 ++++++++++++++++--- .../resource_cloudfunctions_function.go | 17 +++++++++++++++-- .../resource_composer_environment.go.erb | 17 +++++++++++++++-- .../compute/resource_compute_instance.go.erb | 18 ++++++++++++++++-- .../resource_compute_instance_template.go.erb | 17 +++++++++++++++-- .../dataproc/resource_dataproc_job.go.erb | 17 +++++++++++++++-- .../resource_google_project.go | 19 ++++++++++++++++--- .../tests/resource_bigquery_table_test.go | 10 +++++----- .../tests/resource_bigtable_instance_test.go | 6 +++--- ...source_cloudfunctions_function_test.go.erb | 10 +++++----- .../resource_composer_environment_test.go.erb | 1 + ...urce_compute_instance_template_test.go.erb | 6 ++++++ .../resource_compute_instance_test.go.erb | 4 ++-- .../tests/resource_google_project_test.go | 2 +- .../terraform/tpgresource/lables.go | 19 +++++++++++++++++++ 16 files changed, 165 insertions(+), 36 deletions(-) create mode 100644 mmv1/third_party/terraform/tpgresource/lables.go diff --git a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go index 0a33024dafe0..33508cc6326a 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go @@ -767,12 +767,20 @@ func ResourceBigQueryTable() *schema.Resource { // start with a letter and each label in the list must have a different // key. "labels": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `A mapping of labels to assign to the resource. + + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field 'effective_labels' for all of the labels present on the resource.`, + }, + "effective_labels": { Type: schema.TypeMap, - Optional: true, + Computed: true, + Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, Elem: &schema.Schema{Type: schema.TypeString}, - Description: `A mapping of labels to assign to the resource.`, }, - // Schema: [Optional] Describes the schema of this table. // Schema is mutually exclusive with View and Materialized View. "schema": { @@ -1243,9 +1251,12 @@ func resourceBigQueryTableRead(d *schema.ResourceData, meta interface{}) error { if err := d.Set("max_staleness", res.MaxStaleness); err != nil { return fmt.Errorf("Error setting max_staleness: %s", err) } - if err := d.Set("labels", res.Labels); err != nil { + if err := d.Set("labels", tpgresource.FlattenLabels(res.Labels, d)); err != nil { return fmt.Errorf("Error setting labels: %s", err) } + if err := d.Set("effective_labels", res.Labels); err != nil { + return fmt.Errorf("Error setting effective_labels: %s", err) + } if err := d.Set("creation_time", res.CreationTime); err != nil { return fmt.Errorf("Error setting creation_time: %s", err) } diff --git a/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance.go b/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance.go index ecb97c65aa52..840e1be46e12 100644 --- a/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance.go +++ b/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance.go @@ -153,10 +153,20 @@ func ResourceBigtableInstance() *schema.Resource { }, "labels": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `A mapping of labels to assign to the resource. + + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field 'effective_labels' for all of the labels present on the resource.`, + }, + + "effective_labels": { Type: schema.TypeMap, - Optional: true, + Computed: true, + Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, Elem: &schema.Schema{Type: schema.TypeString}, - Description: `A mapping of labels to assign to the resource.`, }, "project": { @@ -301,9 +311,12 @@ func resourceBigtableInstanceRead(d *schema.ResourceData, meta interface{}) erro if err := d.Set("display_name", instance.DisplayName); err != nil { return fmt.Errorf("Error setting display_name: %s", err) } - if err := d.Set("labels", instance.Labels); err != nil { + if err := d.Set("labels", tpgresource.FlattenLabels(instance.Labels, d)); err != nil { return fmt.Errorf("Error setting labels: %s", err) } + if err := d.Set("effective_labels", instance.Labels); err != nil { + return fmt.Errorf("Error setting effective_labels: %s", err) + } // Don't set instance_type: we don't want to detect drift on it because it can // change under-the-hood. diff --git a/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function.go b/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function.go index 20d26544972a..3d27630c57d3 100644 --- a/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function.go +++ b/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function.go @@ -257,7 +257,17 @@ func ResourceCloudFunctionsFunction() *schema.Resource { Type: schema.TypeMap, ValidateFunc: labelKeyValidator, Optional: true, - Description: `A set of key/value label pairs to assign to the function. Label keys must follow the requirements at https://cloud.google.com/resource-manager/docs/creating-managing-labels#requirements.`, + Description: `A set of key/value label pairs to assign to the function. Label keys must follow the requirements at https://cloud.google.com/resource-manager/docs/creating-managing-labels#requirements. + + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field 'effective_labels' for all of the labels present on the resource.`, + }, + + "effective_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, + Elem: &schema.Schema{Type: schema.TypeString}, }, "runtime": { @@ -670,9 +680,12 @@ func resourceCloudFunctionsRead(d *schema.ResourceData, meta interface{}) error if err := d.Set("ingress_settings", function.IngressSettings); err != nil { return fmt.Errorf("Error setting ingress_settings: %s", err) } - if err := d.Set("labels", function.Labels); err != nil { + if err := d.Set("labels", tpgresource.FlattenLabels(function.Labels, d)); err != nil { return fmt.Errorf("Error setting labels: %s", err) } + if err := d.Set("effective_labels", function.Labels); err != nil { + return fmt.Errorf("Error setting effective_labels: %s", err) + } if err := d.Set("runtime", function.Runtime); err != nil { return fmt.Errorf("Error setting runtime: %s", err) } 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 82e7ea37ac2c..dc642a764e09 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 @@ -874,7 +874,17 @@ func ResourceComposerEnvironment() *schema.Resource { Type: schema.TypeMap, Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, - Description: `User-defined labels for this environment. The labels map can contain no more than 64 entries. Entries of the labels map are UTF8 strings that comply with the following restrictions: Label keys must be between 1 and 63 characters long and must conform to the following regular expression: [a-z]([-a-z0-9]*[a-z0-9])?. Label values must be between 0 and 63 characters long and must conform to the regular expression ([a-z]([-a-z0-9]*[a-z0-9])?)?. No more than 64 labels can be associated with a given environment. Both keys and values must be <= 128 bytes in size.`, + Description: `User-defined labels for this environment. The labels map can contain no more than 64 entries. Entries of the labels map are UTF8 strings that comply with the following restrictions: Label keys must be between 1 and 63 characters long and must conform to the following regular expression: [a-z]([-a-z0-9]*[a-z0-9])?. Label values must be between 0 and 63 characters long and must conform to the regular expression ([a-z]([-a-z0-9]*[a-z0-9])?)?. No more than 64 labels can be associated with a given environment. Both keys and values must be <= 128 bytes in size. + + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field 'effective_labels' for all of the labels present on the resource.`, + }, + + "effective_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, + Elem: &schema.Schema{Type: schema.TypeString}, }, }, UseJSONNumber: true, @@ -978,7 +988,10 @@ func resourceComposerEnvironmentRead(d *schema.ResourceData, meta interface{}) e if err := d.Set("config", flattenComposerEnvironmentConfig(res.Config)); err != nil { return fmt.Errorf("Error setting Environment: %s", err) } - if err := d.Set("labels", res.Labels); err != nil { + if err := d.Set("labels", tpgresource.FlattenLabels(res.Labels, d)); err != nil { + return fmt.Errorf("Error setting Environment: %s", err) + } + if err := d.Set("effective_labels", res.Labels); err != nil { return fmt.Errorf("Error setting Environment: %s", err) } return nil diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb index 59dcba8c061c..bf3f25aeb1a1 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb @@ -598,7 +598,17 @@ func ResourceComputeInstance() *schema.Resource { Type: schema.TypeMap, Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, - Description: `A set of key/value label pairs assigned to the instance.`, + Description: `A set of key/value label pairs assigned to the instance. + + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field 'effective_labels' for all of the labels present on the resource.`, + }, + + "effective_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, + Elem: &schema.Schema{Type: schema.TypeString}, }, "metadata": { @@ -1375,7 +1385,11 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error } } - if err := d.Set("labels", instance.Labels); err != nil { + if err := d.Set("labels", tpgresource.FlattenLabels(instance.Labels, d)); err != nil { + return err + } + + if err := d.Set("effective_labels", instance.Labels); err != nil { return err } diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb index ee619a6e4f36..3d991d545028 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb @@ -899,7 +899,17 @@ be from 0 to 999,999,999 inclusive.`, ForceNew: true, Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, - Description: `A set of key/value label pairs to assign to instances created from this template,`, + Description: `A set of key/value label pairs to assign to instances created from this template. + + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field 'effective_labels' for all of the labels present on the resource.`, + }, + + "effective_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, + Elem: &schema.Schema{Type: schema.TypeString}, }, "resource_policies": { @@ -1601,10 +1611,13 @@ func resourceComputeInstanceTemplateRead(d *schema.ResourceData, meta interface{ } } if instanceTemplate.Properties.Labels != nil { - if err := d.Set("labels", instanceTemplate.Properties.Labels); err != nil { + if err := d.Set("labels", tpgresource.FlattenLabels(instanceTemplate.Properties.Labels, d)); err != nil { return fmt.Errorf("Error setting labels: %s", err) } } + if err := d.Set("effective_labels", instanceTemplate.Properties.Labels); err != nil { + return fmt.Errorf("Error setting effective_labels: %s", err) + } if err = d.Set("self_link", instanceTemplate.SelfLink); err != nil { return fmt.Errorf("Error setting self_link: %s", err) } diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_job.go.erb b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_job.go.erb index 94cd75a6ed99..d1fcd5ceb4dd 100644 --- a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_job.go.erb +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_job.go.erb @@ -144,12 +144,22 @@ func ResourceDataprocJob() *schema.Resource { "labels": { Type: schema.TypeMap, - Description: "Optional. The labels to associate with this job.", + Description: `Optional. The labels to associate with this job. + + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field 'effective_labels' for all of the labels present on the resource.`, Optional: true, ForceNew: true, Elem: &schema.Schema{Type: schema.TypeString}, }, + "effective_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "scheduling": { Type: schema.TypeList, Description: "Optional. Job scheduling configuration.", @@ -311,9 +321,12 @@ func resourceDataprocJobRead(d *schema.ResourceData, meta interface{}) error { if err := d.Set("force_delete", d.Get("force_delete")); err != nil { return fmt.Errorf("Error setting force_delete: %s", err) } - if err := d.Set("labels", job.Labels); err != nil { + if err := d.Set("labels", tpgresource.FlattenLabels(job.Labels, d)); err != nil { return fmt.Errorf("Error setting labels: %s", err) } + if err := d.Set("effective_labels", job.Labels); err != nil { + return fmt.Errorf("Error setting effective_labels: %s", err) + } if err := d.Set("driver_output_resource_uri", job.DriverOutputResourceUri); err != nil { return fmt.Errorf("Error setting driver_output_resource_uri: %s", err) } diff --git a/mmv1/third_party/terraform/services/resourcemanager/resource_google_project.go b/mmv1/third_party/terraform/services/resourcemanager/resource_google_project.go index cb88fc4c14f8..629ab2b04c29 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/resource_google_project.go +++ b/mmv1/third_party/terraform/services/resourcemanager/resource_google_project.go @@ -103,10 +103,20 @@ func ResourceGoogleProject() *schema.Resource { Description: `The alphanumeric ID of the billing account this project belongs to. The user or service account performing this operation with Terraform must have Billing Account Administrator privileges (roles/billing.admin) in the organization. See Google Cloud Billing API Access Control for more details.`, }, "labels": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `A set of key/value label pairs to assign to the project. + + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field 'effective_labels' for all of the labels present on the resource.`, + }, + + "effective_labels": { Type: schema.TypeMap, - Optional: true, + Computed: true, + Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, Elem: &schema.Schema{Type: schema.TypeString}, - Description: `A set of key/value label pairs to assign to the project.`, }, }, UseJSONNumber: true, @@ -286,9 +296,12 @@ func resourceGoogleProjectRead(d *schema.ResourceData, meta interface{}) error { if err := d.Set("name", p.Name); err != nil { return fmt.Errorf("Error setting name: %s", err) } - if err := d.Set("labels", p.Labels); err != nil { + if err := d.Set("labels", tpgresource.FlattenLabels(p.Labels, d)); err != nil { return fmt.Errorf("Error setting labels: %s", err) } + if err := d.Set("effective_labels", p.Labels); err != nil { + return fmt.Errorf("Error setting effective_labels: %s", err) + } if p.Parent != nil { switch p.Parent.Type { diff --git a/mmv1/third_party/terraform/tests/resource_bigquery_table_test.go b/mmv1/third_party/terraform/tests/resource_bigquery_table_test.go index 8cce1b7beb8b..659062418985 100644 --- a/mmv1/third_party/terraform/tests/resource_bigquery_table_test.go +++ b/mmv1/third_party/terraform/tests/resource_bigquery_table_test.go @@ -912,7 +912,7 @@ func TestAccBigQueryDataTable_jsonEquivalency(t *testing.T) { ResourceName: "google_bigquery_table.test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection"}, + ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection", "labels"}, }, { Config: testAccBigQueryTable_jsonEqModeRemoved(datasetID, tableID), @@ -921,7 +921,7 @@ func TestAccBigQueryDataTable_jsonEquivalency(t *testing.T) { ResourceName: "google_bigquery_table.test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection"}, + ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection", "labels"}, }, }, }) @@ -971,7 +971,7 @@ func TestAccBigQueryDataTable_expandArray(t *testing.T) { ResourceName: "google_bigquery_table.test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection"}, + ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection", "labels"}, }, { Config: testAccBigQueryTable_arrayExpanded(datasetID, tableID), @@ -980,7 +980,7 @@ func TestAccBigQueryDataTable_expandArray(t *testing.T) { ResourceName: "google_bigquery_table.test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection"}, + ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection", "labels"}, }, }, }) @@ -1004,7 +1004,7 @@ func TestAccBigQueryTable_allowDestroy(t *testing.T) { ResourceName: "google_bigquery_table.test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"deletion_protection"}, + ImportStateVerifyIgnore: []string{"deletion_protection", "labels"}, }, { Config: testAccBigQueryTable_noAllowDestroy(datasetID, tableID), diff --git a/mmv1/third_party/terraform/tests/resource_bigtable_instance_test.go b/mmv1/third_party/terraform/tests/resource_bigtable_instance_test.go index 39bcb1391d60..baeb17c7d5f3 100644 --- a/mmv1/third_party/terraform/tests/resource_bigtable_instance_test.go +++ b/mmv1/third_party/terraform/tests/resource_bigtable_instance_test.go @@ -89,7 +89,7 @@ func TestAccBigtableInstance_cluster(t *testing.T) { ResourceName: "google_bigtable_instance.instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"deletion_protection", "instance_type", "cluster"}, // we don't read instance type back + ImportStateVerifyIgnore: []string{"deletion_protection", "instance_type", "cluster", "labels"}, // we don't read instance type back }, { Config: testAccBigtableInstance_clusterReordered(instanceName, 5), @@ -108,7 +108,7 @@ func TestAccBigtableInstance_cluster(t *testing.T) { ResourceName: "google_bigtable_instance.instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"deletion_protection", "instance_type", "cluster"}, // we don't read instance type back + ImportStateVerifyIgnore: []string{"deletion_protection", "instance_type", "cluster", "labels"}, // we don't read instance type back }, }, }) @@ -428,7 +428,7 @@ func TestAccBigtableInstance_MultipleClustersSameID(t *testing.T) { ResourceName: "google_bigtable_instance.instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"deletion_protection", "instance_type"}, // we don't read instance type back + ImportStateVerifyIgnore: []string{"deletion_protection", "instance_type", "labels"}, // we don't read instance type back }, { Config: testAccBigtableInstance_multipleClustersSameID(instanceName), diff --git a/mmv1/third_party/terraform/tests/resource_cloudfunctions_function_test.go.erb b/mmv1/third_party/terraform/tests/resource_cloudfunctions_function_test.go.erb index 1aa75635342f..47735f8ddc2c 100644 --- a/mmv1/third_party/terraform/tests/resource_cloudfunctions_function_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_cloudfunctions_function_test.go.erb @@ -84,7 +84,7 @@ func TestAccCloudFunctionsFunction_basic(t *testing.T) { ResourceName: funcResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"build_environment_variables"}, + ImportStateVerifyIgnore: []string{"build_environment_variables", "labels"}, }, }, }) @@ -121,7 +121,7 @@ func TestAccCloudFunctionsFunction_update(t *testing.T) { ResourceName: funcResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"build_environment_variables"}, + ImportStateVerifyIgnore: []string{"build_environment_variables", "labels"}, }, { Config: testAccCloudFunctionsFunction_updated(functionName, bucketName, zipFileUpdatePath, random_suffix), @@ -154,7 +154,7 @@ func TestAccCloudFunctionsFunction_update(t *testing.T) { ResourceName: funcResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"build_environment_variables"}, + ImportStateVerifyIgnore: []string{"build_environment_variables", "labels"}, }, }, }) @@ -429,7 +429,7 @@ func TestAccCloudFunctionsFunction_vpcConnector(t *testing.T) { ResourceName: funcResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"build_environment_variables"}, + ImportStateVerifyIgnore: []string{"build_environment_variables", "labels"}, }, { Config: testAccCloudFunctionsFunction_vpcConnector(projectNumber, networkName, functionName, bucketName, zipFilePath, "10.20.0.0/28", vpcConnectorName+"-update"), @@ -438,7 +438,7 @@ func TestAccCloudFunctionsFunction_vpcConnector(t *testing.T) { ResourceName: funcResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"build_environment_variables"}, + ImportStateVerifyIgnore: []string{"build_environment_variables", "labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/tests/resource_composer_environment_test.go.erb b/mmv1/third_party/terraform/tests/resource_composer_environment_test.go.erb index d5e7b74f618c..7a84fdb47bcc 100644 --- a/mmv1/third_party/terraform/tests/resource_composer_environment_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_composer_environment_test.go.erb @@ -100,6 +100,7 @@ func TestAccComposerEnvironment_update(t *testing.T) { ResourceName: "google_composer_environment.test", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels"}, }, // This is a terrible clean-up step in order to get destroy to succeed, // due to dangling firewall rules left by the Composer Environment blocking network deletion. diff --git a/mmv1/third_party/terraform/tests/resource_compute_instance_template_test.go.erb b/mmv1/third_party/terraform/tests/resource_compute_instance_template_test.go.erb index d239fcb6cc31..0d83ba1f93af 100644 --- a/mmv1/third_party/terraform/tests/resource_compute_instance_template_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_compute_instance_template_test.go.erb @@ -51,6 +51,7 @@ func TestAccComputeInstanceTemplate_basic(t *testing.T) { ResourceName: "google_compute_instance_template.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels"}, }, }, }) @@ -77,6 +78,7 @@ func TestAccComputeInstanceTemplate_imageShorthand(t *testing.T) { ResourceName: "google_compute_instance_template.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels"}, }, }, }) @@ -133,6 +135,7 @@ func TestAccComputeInstanceTemplate_maintenance_interval(t *testing.T) { ResourceName: "google_compute_instance_template.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels"}, }, { Config: testAccComputeInstanceTemplate_basic(acctest.RandString(t, 10)), @@ -589,6 +592,7 @@ func TestAccComputeInstanceTemplate_EncryptKMS(t *testing.T) { ResourceName: "google_compute_instance_template.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels"}, }, }, }) @@ -920,6 +924,7 @@ func TestAccComputeInstanceTemplate_diskResourcePolicies(t *testing.T) { ResourceName: "google_compute_instance_template.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels"}, }, }, }) @@ -997,6 +1002,7 @@ func TestAccComputeInstanceTemplate_managedEnvoy(t *testing.T) { ResourceName: "google_compute_instance_template.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/tests/resource_compute_instance_test.go.erb b/mmv1/third_party/terraform/tests/resource_compute_instance_test.go.erb index 938d0a17c864..3c5adc679b57 100644 --- a/mmv1/third_party/terraform/tests/resource_compute_instance_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_compute_instance_test.go.erb @@ -139,7 +139,7 @@ func TestAccComputeInstance_basic1(t *testing.T) { testAccCheckComputeInstanceHasConfiguredDeletionProtection(&instance, false), ), }, - computeInstanceImportStep("us-central1-a", instanceName, []string{"metadata.baz", "metadata.foo", "desired_status", "current_status"}), + computeInstanceImportStep("us-central1-a", instanceName, []string{"metadata.baz", "metadata.foo", "desired_status", "current_status", "labels"}), }, }) } @@ -1401,7 +1401,7 @@ func TestAccComputeInstance_forceChangeMachineTypeManually(t *testing.T) { ), ExpectNonEmptyPlan: true, }, - computeInstanceImportStep("us-central1-a", instanceName, []string{"metadata.baz", "metadata.foo", "desired_status", "current_status"}), + computeInstanceImportStep("us-central1-a", instanceName, []string{"metadata.baz", "metadata.foo", "desired_status", "current_status", "labels"}), }, }) } diff --git a/mmv1/third_party/terraform/tests/resource_google_project_test.go b/mmv1/third_party/terraform/tests/resource_google_project_test.go index 331002899d66..2a0f226537fe 100644 --- a/mmv1/third_party/terraform/tests/resource_google_project_test.go +++ b/mmv1/third_party/terraform/tests/resource_google_project_test.go @@ -135,7 +135,7 @@ func TestAccProject_labels(t *testing.T) { ResourceName: "google_project.acceptance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"skip_delete"}, + ImportStateVerifyIgnore: []string{"skip_delete", "labels"}, }, // update project with labels { diff --git a/mmv1/third_party/terraform/tpgresource/lables.go b/mmv1/third_party/terraform/tpgresource/lables.go new file mode 100644 index 000000000000..1e76a2aeb35c --- /dev/null +++ b/mmv1/third_party/terraform/tpgresource/lables.go @@ -0,0 +1,19 @@ +package tpgresource + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func FlattenLabels(labels map[string]string, d *schema.ResourceData) map[string]interface{} { + transformed := make(map[string]interface{}) + + if v, ok := d.GetOk("labels"); ok { + if labels != nil { + for k, _ := range v.(map[string]interface{}) { + transformed[k] = labels[k] + } + } + } + + return transformed +} From 5b240fd3536510936fba02e5c81a7a550e8d01cd Mon Sep 17 00:00:00 2001 From: hao-nan-li <100219545+hao-nan-li@users.noreply.github.com> Date: Fri, 18 Aug 2023 10:45:46 -0700 Subject: [PATCH 13/67] Remove Terraform support for game services (#8669) * Remove Terraform support for game services * Remove game_service from provider.go * Remove gameServices from ci file --- .ci/infra/terraform/main.tf | 1 - .../gameservices/GameServerCluster.yaml | 137 -------------- .../gameservices/GameServerConfig.yaml | 176 ------------------ .../gameservices/GameServerDeployment.yaml | 87 --------- .../GameServerDeploymentRollout.yaml | 106 ----------- mmv1/products/gameservices/Realm.yaml | 90 --------- mmv1/products/gameservices/product.yaml | 25 --- .../gameservice_rollout_create.go | 16 -- .../game_service_cluster_basic.tf.erb | 62 ------ .../examples/game_service_config_basic.tf.erb | 30 --- .../game_service_deployment_basic.tf.erb | 5 - ...me_service_deployment_rollout_basic.tf.erb | 23 --- .../examples/game_service_realm_basic.tf.erb | 8 - .../terraform/provider/provider.go.erb | 1 - ...services_game_server_deployment_rollout.go | 33 ---- ...me_server_deployment_rollout.html.markdown | 68 ------- 16 files changed, 868 deletions(-) delete mode 100644 mmv1/products/gameservices/GameServerCluster.yaml delete mode 100644 mmv1/products/gameservices/GameServerConfig.yaml delete mode 100644 mmv1/products/gameservices/GameServerDeployment.yaml delete mode 100644 mmv1/products/gameservices/GameServerDeploymentRollout.yaml delete mode 100644 mmv1/products/gameservices/Realm.yaml delete mode 100644 mmv1/products/gameservices/product.yaml delete mode 100644 mmv1/templates/terraform/custom_create/gameservice_rollout_create.go delete mode 100644 mmv1/templates/terraform/examples/game_service_cluster_basic.tf.erb delete mode 100644 mmv1/templates/terraform/examples/game_service_config_basic.tf.erb delete mode 100644 mmv1/templates/terraform/examples/game_service_deployment_basic.tf.erb delete mode 100644 mmv1/templates/terraform/examples/game_service_deployment_rollout_basic.tf.erb delete mode 100644 mmv1/templates/terraform/examples/game_service_realm_basic.tf.erb delete mode 100644 mmv1/third_party/terraform/services/gameservices/data_source_google_game_services_game_server_deployment_rollout.go delete mode 100644 mmv1/third_party/terraform/website/docs/d/game_services_game_server_deployment_rollout.html.markdown diff --git a/.ci/infra/terraform/main.tf b/.ci/infra/terraform/main.tf index fa6d3a584595..24380f7fbde8 100644 --- a/.ci/infra/terraform/main.tf +++ b/.ci/infra/terraform/main.tf @@ -241,7 +241,6 @@ module "project-services" { "firebasestorage.googleapis.com", "firestore.googleapis.com", "firestorekeyvisualizer.googleapis.com", - "gameservices.googleapis.com", "gkebackup.googleapis.com", "gkeconnect.googleapis.com", "gkehub.googleapis.com", diff --git a/mmv1/products/gameservices/GameServerCluster.yaml b/mmv1/products/gameservices/GameServerCluster.yaml deleted file mode 100644 index 8f768c02bfa6..000000000000 --- a/mmv1/products/gameservices/GameServerCluster.yaml +++ /dev/null @@ -1,137 +0,0 @@ -# Copyright 2023 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: GameServerCluster -references: !ruby/object:Api::Resource::ReferenceLinks - guides: - 'Official Documentation': 'https://cloud.google.com/game-servers/docs' - api: 'https://cloud.google.com/game-servers/docs/reference/rest/v1beta/projects.locations.realms.gameServerClusters' -update_verb: :PATCH -update_mask: true -base_url: projects/{{project}}/locations/{{location}}/realms/{{realm_id}}/gameServerClusters -create_url: projects/{{project}}/locations/{{location}}/realms/{{realm_id}}/gameServerClusters?gameServerClusterId={{cluster_id}} -self_link: projects/{{project}}/locations/{{location}}/realms/{{realm_id}}/gameServerClusters/{{cluster_id}} -description: A game server cluster resource. -async: !ruby/object:Api::OpAsync - operation: !ruby/object:Api::OpAsync::Operation - path: 'name' - base_url: '{{op_id}}' - wait_ms: 1000 - 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/errors' - message: 'message' -import_format: - [ - 'projects/{{project}}/locations/{{location}}/realms/{{realm_id}}/gameServerClusters/{{cluster_id}}', - ] -# Skipping the sweeper due to the non-standard base_url -skip_sweeper: true -examples: - - !ruby/object:Provider::Terraform::Examples - name: 'game_service_cluster_basic' - primary_resource_id: - 'default' - skip_test: true - vars: - realm_id: 'realm' - test_vars_overrides: - agones_cluster: '"bootstrapped-agones-cluster"' -custom_code: !ruby/object:Provider::Terraform::CustomCode - constants: 'templates/terraform/constants/gameserver_cluster_custom_diff.go' -properties: - - !ruby/object:Api::Type::String - immutable: true - name: clusterId - required: true - url_param_only: true - description: |- - Required. The resource name of the game server cluster - - !ruby/object:Api::Type::String - name: name - output: true - description: |- - The resource id of the game server cluster, eg: - - `projects/{project_id}/locations/{location}/realms/{realm_id}/gameServerClusters/{cluster_id}`. - For example, - - `projects/my-project/locations/{location}/realms/zanzibar/gameServerClusters/my-onprem-cluster`. - - !ruby/object:Api::Type::ResourceRef - name: realmId - url_param_only: true - resource: Realm - imports: name - required: true - description: |- - The realm id of the game server realm. - - !ruby/object:Api::Type::String - name: location - url_param_only: true - default_value: global - description: Location of the Cluster. - - !ruby/object:Api::Type::KeyValuePairs - name: labels - description: |- - The labels associated with this game server cluster. Each label is a - key-value pair. - - !ruby/object:Api::Type::NestedObject - name: connectionInfo - required: true - immutable: true - description: |- - Game server cluster connection information. This information is used to - manage game server clusters. - properties: - - !ruby/object:Api::Type::NestedObject - name: gkeClusterReference - required: true - immutable: true - description: - Reference of the GKE cluster where the game servers are installed. - properties: - - !ruby/object:Api::Type::String - name: cluster - required: true - immutable: true - description: |- - The full or partial name of a GKE cluster, using one of the following - forms: - - * `projects/{project_id}/locations/{location}/clusters/{cluster_id}` - * `locations/{location}/clusters/{cluster_id}` - * `{cluster_id}` - - If project and location are not specified, the project and location of the - GameServerCluster resource are used to generate the full name of the - GKE cluster. - diff_suppress_func: suppressSuffixDiff - - !ruby/object:Api::Type::String - name: namespace - required: true - description: |- - Namespace designated on the game server cluster where the game server - instances will be created. The namespace existence will be validated - during creation. - - !ruby/object:Api::Type::String - name: description - description: Human readable description of the cluster. diff --git a/mmv1/products/gameservices/GameServerConfig.yaml b/mmv1/products/gameservices/GameServerConfig.yaml deleted file mode 100644 index 75de43ab2eb0..000000000000 --- a/mmv1/products/gameservices/GameServerConfig.yaml +++ /dev/null @@ -1,176 +0,0 @@ -# Copyright 2023 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: GameServerConfig -references: !ruby/object:Api::Resource::ReferenceLinks - guides: - 'Official Documentation': 'https://cloud.google.com/game-servers/docs' - api: 'https://cloud.google.com/game-servers/docs/reference/rest/v1beta/projects.locations.gameServerDeployments.configs' -create_url: projects/{{project}}/locations/{{location}}/gameServerDeployments/{{deployment_id}}/configs?configId={{config_id}} -base_url: projects/{{project}}/locations/{{location}}/gameServerDeployments/{{deployment_id}}/configs -self_link: projects/{{project}}/locations/{{location}}/gameServerDeployments/{{deployment_id}}/configs/{{config_id}} -immutable: true -async: !ruby/object:Api::OpAsync - operation: !ruby/object:Api::OpAsync::Operation - path: 'name' - base_url: '{{op_id}}' - wait_ms: 1000 - 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/errors' - message: 'message' -description: A game server config resource. Configs are global and immutable. -autogen_async: true -import_format: - [ - 'projects/{{project}}/locations/{{location}}/gameServerDeployments/{{deployment_id}}/configs/{{config_id}}', - ] -examples: - - !ruby/object:Provider::Terraform::Examples - name: 'game_service_config_basic' - primary_resource_id: 'default' - skip_test: true - vars: - deployment_id: 'tf-test-deployment' - config_id: 'tf-test-config' -properties: - - !ruby/object:Api::Type::String - name: name - output: true - description: |- - The resource name of the game server config, in the form: - - `projects/{project_id}/locations/{location}/gameServerDeployments/{deployment_id}/configs/{config_id}`. - - !ruby/object:Api::Type::String - name: configId - immutable: true - required: true - url_param_only: true - description: | - A unique id for the deployment config. - - !ruby/object:Api::Type::String - name: location - # The only acceptable location currently is 'global' - # TODO - either hard code or set as computed - url_param_only: true - default_value: global - description: Location of the Deployment. - - !ruby/object:Api::Type::ResourceRef - name: deploymentId - resource: 'GameServerDeployment' - imports: 'deploymentId' - immutable: true - required: true - url_param_only: true - description: | - A unique id for the deployment. - - !ruby/object:Api::Type::String - name: description - description: The description of the game server config. - - !ruby/object:Api::Type::KeyValuePairs - name: labels - description: |- - The labels associated with this game server config. Each label is a - key-value pair. - - !ruby/object:Api::Type::Array - name: fleetConfigs - required: true - description: |- - The fleet config contains list of fleet specs. In the Single Cloud, there - will be only one. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::String - required: true - name: fleetSpec - description: | - The fleet spec, which is sent to Agones to configure fleet. - The spec can be passed as inline json but it is recommended to use a file reference - instead. File references can contain the json or yaml format of the fleet spec. Eg: - - * fleet_spec = jsonencode(yamldecode(file("fleet_configs.yaml"))) - * fleet_spec = file("fleet_configs.json") - - The format of the spec can be found : - `https://agones.dev/site/docs/reference/fleet/`. - - !ruby/object:Api::Type::String - name: name - required: true - description: The name of the FleetConfig. - default_from_api: true - - !ruby/object:Api::Type::Array - name: scalingConfigs - description: Optional. This contains the autoscaling settings. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::String - name: name - required: true - description: The name of the ScalingConfig - - !ruby/object:Api::Type::String - required: true - name: fleetAutoscalerSpec - description: |- - Fleet autoscaler spec, which is sent to Agones. - Example spec can be found : - https://agones.dev/site/docs/reference/fleetautoscaler/ - - !ruby/object:Api::Type::Array - name: selectors - description: |- - Labels used to identify the clusters to which this scaling config - applies. A cluster is subject to this scaling config if its labels match - any of the selector entries. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::KeyValuePairs - name: labels - description: Set of labels to group by. - - !ruby/object:Api::Type::Array - name: schedules - description: The schedules to which this scaling config applies. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::String - name: startTime - description: |- - The start time of the event. - - A timestamp in RFC3339 UTC "Zulu" format, accurate to nanoseconds. Example: "2014-10-02T15:01:23.045123456Z". - - !ruby/object:Api::Type::String - name: endTime - description: |- - The end time of the event. - - A timestamp in RFC3339 UTC "Zulu" format, accurate to nanoseconds. Example: "2014-10-02T15:01:23.045123456Z". - - !ruby/object:Api::Type::String - name: cronJobDuration - description: |- - The duration for the cron job event. The duration of the event is effective - after the cron job's start time. - - A duration in seconds with up to nine fractional digits, terminated by 's'. Example: "3.5s". - - !ruby/object:Api::Type::String - name: cronSpec - description: |- - The cron definition of the scheduled event. See - https://en.wikipedia.org/wiki/Cron. Cron spec specifies the local time as - defined by the realm. diff --git a/mmv1/products/gameservices/GameServerDeployment.yaml b/mmv1/products/gameservices/GameServerDeployment.yaml deleted file mode 100644 index 041d44def02e..000000000000 --- a/mmv1/products/gameservices/GameServerDeployment.yaml +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright 2023 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: GameServerDeployment -references: !ruby/object:Api::Resource::ReferenceLinks - guides: - 'Official Documentation': 'https://cloud.google.com/game-servers/docs' - api: 'https://cloud.google.com/game-servers/docs/reference/rest/v1beta/projects.locations.gameServerDeployments' -base_url: projects/{{project}}/locations/{{location}}/gameServerDeployments -create_url: projects/{{project}}/locations/{{location}}/gameServerDeployments?deploymentId={{deployment_id}} -self_link: projects/{{project}}/locations/{{location}}/gameServerDeployments/{{deployment_id}} -update_mask: true -update_verb: :PATCH -description: A game server deployment resource. -async: !ruby/object:Api::OpAsync - operation: !ruby/object:Api::OpAsync::Operation - path: 'name' - base_url: '{{op_id}}' - wait_ms: 1000 - 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/errors' - message: 'message' -autogen_async: true -import_format: - [ - 'projects/{{project}}/locations/{{location}}/gameServerDeployments/{{deployment_id}}', - ] -examples: - - !ruby/object:Provider::Terraform::Examples - name: 'game_service_deployment_basic' - primary_resource_id: 'default' - skip_test: true - vars: - deployment_id: 'tf-test-deployment' -properties: - - !ruby/object:Api::Type::String - name: name - output: true - description: |- - The resource id of the game server deployment, eg: - - `projects/{project_id}/locations/{location}/gameServerDeployments/{deployment_id}`. - For example, - - `projects/my-project/locations/{location}/gameServerDeployments/my-deployment`. - - !ruby/object:Api::Type::String - name: description - description: Human readable description of the game server deployment. - - !ruby/object:Api::Type::String - name: deploymentId - immutable: true - required: true - url_param_only: true - description: | - A unique id for the deployment. - - !ruby/object:Api::Type::String - name: location - # The only acceptable location currently is 'global' - # TODO - either hard code or set as computed - url_param_only: true - default_value: global - description: Location of the Deployment. - - !ruby/object:Api::Type::KeyValuePairs - name: labels - description: |- - The labels associated with this game server deployment. Each label is a - key-value pair. diff --git a/mmv1/products/gameservices/GameServerDeploymentRollout.yaml b/mmv1/products/gameservices/GameServerDeploymentRollout.yaml deleted file mode 100644 index 3b9cad5296de..000000000000 --- a/mmv1/products/gameservices/GameServerDeploymentRollout.yaml +++ /dev/null @@ -1,106 +0,0 @@ -# Copyright 2023 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: GameServerDeploymentRollout -references: !ruby/object:Api::Resource::ReferenceLinks - guides: - 'Official Documentation': 'https://cloud.google.com/game-servers/docs' - api: 'https://cloud.google.com/game-servers/docs/reference/rest/v1beta/GameServerDeploymentRollout' -create_url: projects/{{project}}/locations/global/gameServerDeployments/{{deployment_id}}/rollout -base_url: projects/{{project}}/locations/global/gameServerDeployments/{{deployment_id}}/rollout -update_url: projects/{{project}}/locations/global/gameServerDeployments/{{deployment_id}}/rollout -# Deleting a rollout is synonymous with removing the default game server config -delete_url: projects/{{project}}/locations/global/gameServerDeployments/{{deployment_id}}/rollout?updateMask=defaultGameServerConfig -update_verb: :PATCH -delete_verb: :PATCH -update_mask: true -self_link: projects/{{project}}/locations/global/gameServerDeployments/{{deployment_id}}/rollout -async: !ruby/object:Api::OpAsync - operation: !ruby/object:Api::OpAsync::Operation - path: 'name' - base_url: '{{op_id}}' - wait_ms: 1000 - 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/errors' - message: 'message' -description: |- - This represents the rollout state. This is part of the game server - deployment. -import_format: - [ - 'projects/{{project}}/locations/global/gameServerDeployments/{{deployment_id}}/rollout', - ] -examples: - - !ruby/object:Provider::Terraform::Examples - name: 'game_service_deployment_rollout_basic' - primary_resource_id: 'default' - skip_test: true - vars: - deployment_id: 'tf-test-deployment' - config_id: 'tf-test-config' -custom_code: !ruby/object:Provider::Terraform::CustomCode - custom_create: 'templates/terraform/custom_create/gameservice_rollout_create.go' -properties: - - !ruby/object:Api::Type::String - name: name - output: true - description: |- - The resource id of the game server deployment - - eg: `projects/my-project/locations/global/gameServerDeployments/my-deployment/rollout`. - - !ruby/object:Api::Type::ResourceRef - name: deploymentId - resource: GameServerDeployment - url_param_only: true - required: true - imports: name - description: | - The deployment to rollout the new config to. Only 1 rollout must be associated with each deployment. - - !ruby/object:Api::Type::String - name: defaultGameServerConfig - required: true - description: |- - This field points to the game server config that is - applied by default to all realms and clusters. For example, - - `projects/my-project/locations/global/gameServerDeployments/my-game/configs/my-config`. - - !ruby/object:Api::Type::Array - name: gameServerConfigOverrides - description: |- - The game_server_config_overrides contains the per game server config - overrides. The overrides are processed in the order they are listed. As - soon as a match is found for a cluster, the rest of the list is not - processed. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::NestedObject - name: realmsSelector - description: Selection by realms. - properties: - - !ruby/object:Api::Type::Array - name: realms - description: List of realms to match against. - item_type: Api::Type::String - - !ruby/object:Api::Type::String - name: configVersion - description: Version of the configuration. diff --git a/mmv1/products/gameservices/Realm.yaml b/mmv1/products/gameservices/Realm.yaml deleted file mode 100644 index 07a0f6f2c650..000000000000 --- a/mmv1/products/gameservices/Realm.yaml +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright 2023 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: Realm -references: !ruby/object:Api::Resource::ReferenceLinks - guides: - 'Official Documentation': 'https://cloud.google.com/game-servers/docs' - api: 'https://cloud.google.com/game-servers/docs/reference/rest/v1beta/projects.locations.realms' -create_url: projects/{{project}}/locations/{{location}}/realms?realmId={{realm_id}} -base_url: projects/{{project}}/locations/{{location}}/realms -self_link: projects/{{project}}/locations/{{location}}/realms/{{realm_id}} -update_verb: :PATCH -update_mask: true -description: A Realm resource. -async: !ruby/object:Api::OpAsync - operation: !ruby/object:Api::OpAsync::Operation - path: 'name' - base_url: '{{op_id}}' - wait_ms: 1000 - 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/errors' - message: 'message' -autogen_async: true -import_format: - ['projects/{{project}}/locations/{{location}}/realms/{{realm_id}}'] -examples: - - !ruby/object:Provider::Terraform::Examples - name: 'game_service_realm_basic' - primary_resource_id: 'default' - skip_test: true - vars: - realm_id: 'tf-test-realm' -parameters: - - !ruby/object:Api::Type::String - name: location - url_param_only: true - default_value: global - description: Location of the Realm. - - !ruby/object:Api::Type::String - name: realmId - immutable: true - url_param_only: true - required: true - description: GCP region of the Realm. -properties: - - !ruby/object:Api::Type::String - name: name - output: true - description: |- - The resource id of the realm, of the form: - `projects/{project_id}/locations/{location}/realms/{realm_id}`. For - example, `projects/my-project/locations/{location}/realms/my-realm`. - - !ruby/object:Api::Type::KeyValuePairs - name: labels - description: - The labels associated with this realm. Each label is a key-value pair. - - !ruby/object:Api::Type::String - name: timeZone - required: true - description: |- - Required. Time zone where all realm-specific policies are evaluated. The value of - this field must be from the IANA time zone database: - https://www.iana.org/time-zones. - - !ruby/object:Api::Type::String - name: etag - output: true - description: ETag of the resource. - - !ruby/object:Api::Type::String - name: description - description: Human readable description of the realm. diff --git a/mmv1/products/gameservices/product.yaml b/mmv1/products/gameservices/product.yaml deleted file mode 100644 index 45ddaf0b3d6d..000000000000 --- a/mmv1/products/gameservices/product.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2019 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: GameServices -display_name: Game Servers -scopes: - - https://www.googleapis.com/auth/compute -versions: - - !ruby/object:Api::Product::Version - name: ga - base_url: https://gameservices.googleapis.com/v1/ - - !ruby/object:Api::Product::Version - name: beta - base_url: https://gameservices.googleapis.com/v1beta/ diff --git a/mmv1/templates/terraform/custom_create/gameservice_rollout_create.go b/mmv1/templates/terraform/custom_create/gameservice_rollout_create.go deleted file mode 100644 index 85da871cd049..000000000000 --- a/mmv1/templates/terraform/custom_create/gameservice_rollout_create.go +++ /dev/null @@ -1,16 +0,0 @@ -// Store the ID now -id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/global/gameServerDeployments/{{deployment_id}}/rollout") -if err != nil { - return fmt.Errorf("Error constructing id: %s", err) -} -d.SetId(id) - -log.Printf("[DEBUG] Creating GameServerDeploymentRollout %q: ", d.Id()) - -err = resourceGameServicesGameServerDeploymentRolloutUpdate(d, meta) -if err != nil { - d.SetId("") - return fmt.Errorf("Error trying to create GameServerDeploymentRollout: %s", err) -} - -return nil diff --git a/mmv1/templates/terraform/examples/game_service_cluster_basic.tf.erb b/mmv1/templates/terraform/examples/game_service_cluster_basic.tf.erb deleted file mode 100644 index 19eb85571952..000000000000 --- a/mmv1/templates/terraform/examples/game_service_cluster_basic.tf.erb +++ /dev/null @@ -1,62 +0,0 @@ -resource "google_game_services_game_server_cluster" "<%= ctx[:primary_resource_id] %>" { - <%# depends_on = [google_project_iam_member.kubernetes_developer] -%> - <%# depends_on = [module.agones_cluster, module.helm_agones] -%> - - cluster_id = "<%= ctx[:vars]['agones_cluster'] %>" - realm_id = google_game_services_realm.default.realm_id - - connection_info { - gke_cluster_reference { - cluster = "locations/us-west1/clusters/%{agones_cluster}" - } - namespace = "default" - } -} - -resource "google_game_services_realm" "default" { - realm_id = "<%= ctx[:vars]["realm_id"] %>" - time_zone = "PST8PDT" - - description = "Test Game Realm" -} - - -<%# -This resource requires that a GKE cluster is already created with Agones provisioned -and configured correctly for this test to succeed. Since this setup requires a fair amount -of bootstrapping that is non-essential to testing that the resource works we've decided to -set up the cluster in advance and run the tests against it. The following Terraform config -was used to provision the cluster. Since it is a manual set up this config not guaranteed to -work out of the box. - -module "agones_cluster" { - source = "git::https://github.com/googleforgames/agones.git//install/terraform/modules/gke/?ref=release-1.4.0" - - cluster = { - "name" = var.name - "zone" = "us-west1" - "machineType" = "e2-standard-4" - "initialNodeCount" = 1 - "project" = "" - "network" = "default" - } -} - -// Install Agones via Helm -module "helm_agones" { - source = "git::https://github.com/googleforgames/agones.git//install/terraform/modules/helm/?ref=release-1.4.0" - - agones_version = "1.4.0" - values_file = "" - chart = "agones" - host = module.agones_cluster.host - token = module.agones_cluster.token - cluster_ca_certificate = module.agones_cluster.cluster_ca_certificate -} - -resource "google_project_iam_member" "agent_create" { - project = var.project - role = "roles/container.developer" - member = "serviceAccount:service-@gcp-sa-gameservices.iam.gserviceaccount.com" -} --%> \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/game_service_config_basic.tf.erb b/mmv1/templates/terraform/examples/game_service_config_basic.tf.erb deleted file mode 100644 index 6c89cbcf8f7c..000000000000 --- a/mmv1/templates/terraform/examples/game_service_config_basic.tf.erb +++ /dev/null @@ -1,30 +0,0 @@ -resource "google_game_services_game_server_deployment" "default" { - deployment_id = "<%= ctx[:vars]["deployment_id"] %>" - description = "a deployment description" -} - -resource "google_game_services_game_server_config" "<%= ctx[:primary_resource_id] %>" { - config_id = "<%= ctx[:vars]["config_id"] %>" - deployment_id = google_game_services_game_server_deployment.default.deployment_id - description = "a config description" - - fleet_configs { - name = "something-unique" - fleet_spec = jsonencode({ "replicas" : 1, "scheduling" : "Packed", "template" : { "metadata" : { "name" : "tf-test-game-server-template" }, "spec" : { "ports": [{"name": "default", "portPolicy": "Dynamic", "containerPort": 7654, "protocol": "UDP"}], "template" : { "spec" : { "containers" : [{ "name" : "simple-udp-server", "image" : "gcr.io/agones-images/udp-server:0.14" }] } } } } }) - } - - scaling_configs { - name = "scaling-config-name" - fleet_autoscaler_spec = jsonencode({"policy": {"type": "Webhook","webhook": {"service": {"name": "autoscaler-webhook-service","namespace": "default","path": "scale"}}}}) - selectors { - labels = { - "one" : "two" - } - } - - schedules { - cron_job_duration = "3.500s" - cron_spec = "0 0 * * 0" - } - } -} diff --git a/mmv1/templates/terraform/examples/game_service_deployment_basic.tf.erb b/mmv1/templates/terraform/examples/game_service_deployment_basic.tf.erb deleted file mode 100644 index 10e00ebc6ace..000000000000 --- a/mmv1/templates/terraform/examples/game_service_deployment_basic.tf.erb +++ /dev/null @@ -1,5 +0,0 @@ -resource "google_game_services_game_server_deployment" "<%= ctx[:primary_resource_id] %>" { - deployment_id = "<%= ctx[:vars]["deployment_id"] %>" - description = "a deployment description" -} - diff --git a/mmv1/templates/terraform/examples/game_service_deployment_rollout_basic.tf.erb b/mmv1/templates/terraform/examples/game_service_deployment_rollout_basic.tf.erb deleted file mode 100644 index 8d41a0ddd382..000000000000 --- a/mmv1/templates/terraform/examples/game_service_deployment_rollout_basic.tf.erb +++ /dev/null @@ -1,23 +0,0 @@ -resource "google_game_services_game_server_deployment" "default" { - deployment_id = "<%= ctx[:vars]["deployment_id"] %>" - description = "a deployment description" -} - -resource "google_game_services_game_server_config" "default" { - config_id = "<%= ctx[:vars]["config_id"] %>" - deployment_id = google_game_services_game_server_deployment.default.deployment_id - description = "a config description" - - fleet_configs { - name = "some-non-guid" - fleet_spec = jsonencode({ "replicas" : 1, "scheduling" : "Packed", "template" : { "metadata" : { "name" : "tf-test-game-server-template" }, "spec" : { "ports": [{"name": "default", "portPolicy": "Dynamic", "containerPort": 7654, "protocol": "UDP"}], "template" : { "spec" : { "containers" : [{ "name" : "simple-udp-server", "image" : "gcr.io/agones-images/udp-server:0.14" }] } } } } }) - - // Alternate usage: - // fleet_spec = file(fleet_configs.json) - } -} - -resource "google_game_services_game_server_deployment_rollout" "<%= ctx[:primary_resource_id] %>" { - deployment_id = google_game_services_game_server_deployment.default.deployment_id - default_game_server_config = google_game_services_game_server_config.default.name -} diff --git a/mmv1/templates/terraform/examples/game_service_realm_basic.tf.erb b/mmv1/templates/terraform/examples/game_service_realm_basic.tf.erb deleted file mode 100644 index 0385c37a6f2c..000000000000 --- a/mmv1/templates/terraform/examples/game_service_realm_basic.tf.erb +++ /dev/null @@ -1,8 +0,0 @@ -resource "google_game_services_realm" "<%= ctx[:primary_resource_id] %>" { - realm_id = "<%= ctx[:vars]["realm_id"] %>" - time_zone = "EST" - location = "global" - - description = "one of the nine" -} - diff --git a/mmv1/third_party/terraform/provider/provider.go.erb b/mmv1/third_party/terraform/provider/provider.go.erb index 7aa937faf4f3..851680b5ca35 100644 --- a/mmv1/third_party/terraform/provider/provider.go.erb +++ b/mmv1/third_party/terraform/provider/provider.go.erb @@ -274,7 +274,6 @@ func DatasourceMapWithErrors() (map[string]*schema.Resource, error) { "google_container_registry_repository": containeranalysis.DataSourceGoogleContainerRepo(), "google_dataproc_metastore_service": dataprocmetastore.DataSourceDataprocMetastoreService(), "google_datastream_static_ips": datastream.DataSourceGoogleDatastreamStaticIps(), - "google_game_services_game_server_deployment_rollout": gameservices.DataSourceGameServicesGameServerDeploymentRollout(), "google_iam_policy": resourcemanager.DataSourceGoogleIamPolicy(), "google_iam_role": resourcemanager.DataSourceGoogleIamRole(), "google_iam_testable_permissions": resourcemanager.DataSourceGoogleIamTestablePermissions(), diff --git a/mmv1/third_party/terraform/services/gameservices/data_source_google_game_services_game_server_deployment_rollout.go b/mmv1/third_party/terraform/services/gameservices/data_source_google_game_services_game_server_deployment_rollout.go deleted file mode 100644 index ab8d406cafdb..000000000000 --- a/mmv1/third_party/terraform/services/gameservices/data_source_google_game_services_game_server_deployment_rollout.go +++ /dev/null @@ -1,33 +0,0 @@ -package gameservices - -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 DataSourceGameServicesGameServerDeploymentRollout() *schema.Resource { - - dsSchema := tpgresource.DatasourceSchemaFromResourceSchema(ResourceGameServicesGameServerDeploymentRollout().Schema) - tpgresource.AddRequiredFieldsToSchema(dsSchema, "deployment_id") - - return &schema.Resource{ - Read: dataSourceGameServicesGameServerDeploymentRolloutRead, - Schema: dsSchema, - } -} - -func dataSourceGameServicesGameServerDeploymentRolloutRead(d *schema.ResourceData, meta interface{}) error { - config := meta.(*transport_tpg.Config) - - id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/global/gameServerDeployments/{{deployment_id}}/rollout") - if err != nil { - return fmt.Errorf("Error constructing id: %s", err) - } - - d.SetId(id) - - return resourceGameServicesGameServerDeploymentRolloutRead(d, meta) -} diff --git a/mmv1/third_party/terraform/website/docs/d/game_services_game_server_deployment_rollout.html.markdown b/mmv1/third_party/terraform/website/docs/d/game_services_game_server_deployment_rollout.html.markdown deleted file mode 100644 index 263c218a36da..000000000000 --- a/mmv1/third_party/terraform/website/docs/d/game_services_game_server_deployment_rollout.html.markdown +++ /dev/null @@ -1,68 +0,0 @@ ---- -subcategory: "Game Servers" -description: |- - Get the rollout state. ---- - -# google\_game\_services\_game\_server\_deployment\_rollout - -Use this data source to get the rollout state. - -https://cloud.google.com/game-servers/docs/reference/rest/v1beta/GameServerDeploymentRollout - -## Example Usage - - -```hcl -data "google_game_services_game_server_deployment_rollout" "qa" { - deployment_id = "tf-test-deployment-s8sn12jt2c" -} -``` - -## Argument Reference - -The following arguments are supported: - - -* `deployment_id` - (Required) - The deployment to get the rollout state from. Only 1 rollout must be associated with each deployment. - - -## Attributes Reference - -In addition to the arguments listed above, the following attributes are exported: - -* `default_game_server_config` - - This field points to the game server config that is - applied by default to all realms and clusters. For example, - `projects/my-project/locations/global/gameServerDeployments/my-game/configs/my-config`. - - -* `game_server_config_overrides` - - The game_server_config_overrides contains the per game server config - overrides. The overrides are processed in the order they are listed. As - soon as a match is found for a cluster, the rest of the list is not - processed. Structure is [documented below](#nested_game_server_config_overrides). - -* `project` - The ID of the project in which the resource belongs. - If it is not provided, the provider project is used. - - -The `game_server_config_overrides` block contains: - -* `realms_selector` - - Selection by realms. Structure is [documented below](#nested_realms_selector). - -* `config_version` - - Version of the configuration. - -The `realms_selector` block contains: - -* `realms` - - List of realms to match against. - -* `id` - an identifier for the resource with format `projects/{{project}}/locations/global/gameServerDeployments/{{deployment_id}}/rollout` - -* `name` - - The resource id of the game server deployment - eg: `projects/my-project/locations/global/gameServerDeployments/my-deployment/rollout`. From 7d4ce179b67cf52900bf989e0bc6d56a56bc3653 Mon Sep 17 00:00:00 2001 From: Scott Suarez Date: Wed, 23 Aug 2023 12:14:41 -0700 Subject: [PATCH 14/67] Use base branch for pre-build validation merge (#8748) --- .github/workflows/pre-build-validation-on-pr.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pre-build-validation-on-pr.yml b/.github/workflows/pre-build-validation-on-pr.yml index 93f845708c5f..d8741fd52cf2 100644 --- a/.github/workflows/pre-build-validation-on-pr.yml +++ b/.github/workflows/pre-build-validation-on-pr.yml @@ -20,8 +20,9 @@ jobs: cd repo git config user.name "modular-magician" git config user.email "magic-modules@google.com" - git merge --no-ff origin/main - yamlfiles=$(git diff --name-only origin/main -- mmv1/products) + git fetch origin ${{ github.base_ref }} # Fetch the base branch + git merge --no-ff origin/${{ github.base_ref }} # Merge with the base branch + yamlfiles=$(git diff --name-only origin/${{ github.base_ref }} -- mmv1/products) # Compare with the base branch if [ ! -z "$yamlfiles" ]; then echo "yamlfiles=repo/${yamlfiles//$'\n'/ repo/}" >> $GITHUB_OUTPUT fi From 91bbdc516cae8c86a16f476fb137f02ab99a76c5 Mon Sep 17 00:00:00 2001 From: Shuya Ma Date: Wed, 23 Aug 2023 13:15:11 -0700 Subject: [PATCH 15/67] fix yaml lint errors --- mmv1/products/compute/RegionSecurityPolicyRule.yaml | 2 +- mmv1/products/filestore/Instance.yaml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mmv1/products/compute/RegionSecurityPolicyRule.yaml b/mmv1/products/compute/RegionSecurityPolicyRule.yaml index 8580b3281d90..fecb3ca06c05 100644 --- a/mmv1/products/compute/RegionSecurityPolicyRule.yaml +++ b/mmv1/products/compute/RegionSecurityPolicyRule.yaml @@ -65,7 +65,7 @@ examples: - !ruby/object:Provider::Terraform::Examples name: 'region_security_policy_rule_with_network_match' # it needs to run synchronously because a region can have only one google_compute_network_edge_security_service. - # there is a robust handwritten test which covers this scenario. + # there is a robust handwritten test which covers this scenario. skip_test: true primary_resource_id: 'policy_rule_network_match' min_version: 'beta' diff --git a/mmv1/products/filestore/Instance.yaml b/mmv1/products/filestore/Instance.yaml index 12ca3ef1d256..2abe2a296123 100644 --- a/mmv1/products/filestore/Instance.yaml +++ b/mmv1/products/filestore/Instance.yaml @@ -44,7 +44,8 @@ examples: - !ruby/object:Provider::Terraform::Examples name: 'filestore_instance_enterprise' primary_resource_id: 'instance' - skip_test: true # https://github.com/GoogleCloudPlatform/magic-modules/pull/5875#discussion_r844285335 + # https://github.com/GoogleCloudPlatform/magic-modules/pull/5875#discussion_r844285335 + skip_test: true vars: instance_name: 'test-instance' custom_code: !ruby/object:Provider::Terraform::CustomCode From ac907790465771501b21daf315486f8994518126 Mon Sep 17 00:00:00 2001 From: Shuya Ma Date: Thu, 24 Aug 2023 00:42:27 -0700 Subject: [PATCH 16/67] added back Datascan changes --- mmv1/products/dataplex/Datascan.yaml | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/mmv1/products/dataplex/Datascan.yaml b/mmv1/products/dataplex/Datascan.yaml index 7178853c122a..eaababbcac5e 100644 --- a/mmv1/products/dataplex/Datascan.yaml +++ b/mmv1/products/dataplex/Datascan.yaml @@ -445,3 +445,44 @@ properties: name: 'rowFilter' description: | A filter applied to all rows in a single DataScan job. The filter needs to be a valid SQL expression for a WHERE clause in BigQuery standard SQL syntax. Example: col1 >= 0 AND col2 < 10 + - !ruby/object:Api::Type::NestedObject + name: 'postScanActions' + description: | + Actions to take upon job completion. + properties: + - !ruby/object:Api::Type::NestedObject + name: 'bigqueryExport' + description: | + If set, results will be exported to the provided BigQuery table. + properties: + - !ruby/object:Api::Type::String + name: 'resultsTable' + description: | + The BigQuery table to export DataProfileScan results to. + Format://bigquery.googleapis.com/projects/PROJECT_ID/datasets/DATASET_ID/tables/TABLE_ID + - !ruby/object:Api::Type::NestedObject + name: 'includeFields' + description: | + The fields to include in data profile. + If not specified, all fields at the time of profile scan job execution are included, except for ones listed in `exclude_fields`. + properties: + - !ruby/object:Api::Type::Array + name: 'fieldNames' + description: | + Expected input is a list of fully qualified names of fields as in the schema. + Only top-level field names for nested fields are supported. + For instance, if 'x' is of nested field type, listing 'x' is supported but 'x.y.z' is not supported. Here 'y' and 'y.z' are nested fields of 'x'. + item_type: Api::Type::String + - !ruby/object:Api::Type::NestedObject + name: 'excludeFields' + description: | + The fields to exclude from data profile. + If specified, the fields will be excluded from data profile, regardless of `include_fields` value. + properties: + - !ruby/object:Api::Type::Array + name: 'fieldNames' + description: | + Expected input is a list of fully qualified names of fields as in the schema. + Only top-level field names for nested fields are supported. + For instance, if 'x' is of nested field type, listing 'x' is supported but 'x.y.z' is not supported. Here 'y' and 'y.z' are nested fields of 'x'. + item_type: Api::Type::String From 086a67cdcb829a792e60b2f8858e3f4f71f6b278 Mon Sep 17 00:00:00 2001 From: Sean McGivern <27fv8yygye@snkmail.com> Date: Wed, 30 Aug 2023 16:22:00 +0100 Subject: [PATCH 17/67] Make SQL database flags a set (#8118) Co-authored-by: Cameron Thornton --- .../sql/resource_sql_database_instance.go.erb | 35 ++++----- .../resource_sql_database_instance_test.go | 72 +++++++++++++++++++ mmv1/third_party/tgc/sql_database_instance.go | 2 +- 3 files changed, 92 insertions(+), 17 deletions(-) diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.erb b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.erb index 28004b4c275d..90f7ef577212 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.erb +++ b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.erb @@ -46,6 +46,21 @@ var sqlDatabaseAuthorizedNetWorkSchemaElem *schema.Resource = &schema.Resource{ }, } +var sqlDatabaseFlagSchemaElem *schema.Resource = &schema.Resource{ + Schema: map[string]*schema.Schema{ + "value": { + Type: schema.TypeString, + Required: true, + Description: `Value of the flag.`, + }, + "name": { + Type: schema.TypeString, + Required: true, + Description: `Name of the flag.`, + }, + }, +} + var ( backupConfigurationKeys = []string{ "settings.0.backup_configuration.0.binary_log_enabled", @@ -362,22 +377,10 @@ is set to true. Defaults to ZONAL.`, Description: `The name of server instance collation.`, }, "database_flags": { - Type: schema.TypeList, + Type: schema.TypeSet, Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "value": { - Type: schema.TypeString, - Required: true, - Description: `Value of the flag.`, - }, - "name": { - Type: schema.TypeString, - Required: true, - Description: `Name of the flag.`, - }, - }, - }, + Set: schema.HashResource(sqlDatabaseFlagSchemaElem), + Elem: sqlDatabaseFlagSchemaElem, }, "disk_autoresize": { Type: schema.TypeBool, @@ -1261,7 +1264,7 @@ func expandSqlDatabaseInstanceSettings(configured []interface{}, databaseVersion DeletionProtectionEnabled: _settings["deletion_protection_enabled"].(bool), UserLabels: tpgresource.ConvertStringMap(_settings["user_labels"].(map[string]interface{})), BackupConfiguration: expandBackupConfiguration(_settings["backup_configuration"].([]interface{})), - DatabaseFlags: expandDatabaseFlags(_settings["database_flags"].([]interface{})), + DatabaseFlags: expandDatabaseFlags(_settings["database_flags"].(*schema.Set).List()), IpConfiguration: expandIpConfiguration(_settings["ip_configuration"].([]interface{}), databaseVersion), LocationPreference: expandLocationPreference(_settings["location_preference"].([]interface{})), MaintenanceWindow: expandMaintenanceWindow(_settings["maintenance_window"].([]interface{})), diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go index 7f43e53d8870..64607beb5cb0 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go @@ -1671,6 +1671,34 @@ func TestAccSqlDatabaseInstance_Timezone(t *testing.T) { }) } +func TestAccSqlDatabaseInstance_updateDifferentFlagOrder(t *testing.T) { + t.Parallel() + + instance := "tf-test-" + acctest.RandString(t, 10) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccSqlDatabaseInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testGoogleSqlDatabaseInstance_flags(instance), + }, + { + ResourceName: "google_sql_database_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + { + Config: testGoogleSqlDatabaseInstance_flags_update(instance), + PlanOnly: true, + ExpectNonEmptyPlan: false, + }, + }, + }) +} + func TestAccSqlDatabaseInstance_sqlMysqlInstancePvpExample(t *testing.T) { t.Parallel() @@ -3830,6 +3858,50 @@ func checkInstanceTypeIsPresent(resourceName string) func(*terraform.State) erro } } +func testGoogleSqlDatabaseInstance_flags(instance string) string { + return fmt.Sprintf(` +resource "google_sql_database_instance" "instance" { + name = "%s" + region = "us-central1" + database_version = "MYSQL_5_7" + deletion_protection = false + settings { + tier = "db-f1-micro" + + database_flags { + name = "character_set_server" + value = "utf8mb4" + } + database_flags { + name = "auto_increment_increment" + value = "2" + } + } +}`, instance) +} + +func testGoogleSqlDatabaseInstance_flags_update(instance string) string { + return fmt.Sprintf(` +resource "google_sql_database_instance" "instance" { + name = "%s" + region = "us-central1" + database_version = "MYSQL_5_7" + deletion_protection = false + settings { + tier = "db-f1-micro" + + database_flags { + name = "auto_increment_increment" + value = "2" + } + database_flags { + name = "character_set_server" + value = "utf8mb4" + } + } +}`, instance) +} + func testGoogleSqlDatabaseInstance_readReplica(instance string) string { return fmt.Sprintf(` resource "google_sql_database_instance" "master" { diff --git a/mmv1/third_party/tgc/sql_database_instance.go b/mmv1/third_party/tgc/sql_database_instance.go index 9eba9d623725..add0a43f459c 100644 --- a/mmv1/third_party/tgc/sql_database_instance.go +++ b/mmv1/third_party/tgc/sql_database_instance.go @@ -110,7 +110,7 @@ func expandSqlDatabaseInstanceSettings(configured []interface{}, secondGen bool) PricingPlan: _settings["pricing_plan"].(string), UserLabels: tpgresource.ConvertStringMap(_settings["user_labels"].(map[string]interface{})), BackupConfiguration: expandBackupConfiguration(_settings["backup_configuration"].([]interface{})), - DatabaseFlags: expandDatabaseFlags(_settings["database_flags"].([]interface{})), + DatabaseFlags: expandDatabaseFlags(_settings["database_flags"].(*schema.Set).List()), IpConfiguration: expandIpConfiguration(_settings["ip_configuration"].([]interface{})), LocationPreference: expandLocationPreference(_settings["location_preference"].([]interface{})), MaintenanceWindow: expandMaintenanceWindow(_settings["maintenance_window"].([]interface{})), From 415c90dfc305e52b79c5a4f78366760d6a9a3bc0 Mon Sep 17 00:00:00 2001 From: pengq-google Date: Wed, 30 Aug 2023 15:05:49 -0400 Subject: [PATCH 18/67] Mark `num_finite_buckets` required for cloud logging metric bucket_options (#8780) Co-authored-by: Cameron Thornton --- mmv1/products/logging/Metric.yaml | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/mmv1/products/logging/Metric.yaml b/mmv1/products/logging/Metric.yaml index 030758a8465d..98b154070d22 100644 --- a/mmv1/products/logging/Metric.yaml +++ b/mmv1/products/logging/Metric.yaml @@ -206,28 +206,19 @@ properties: properties: - !ruby/object:Api::Type::Integer name: numFiniteBuckets - at_least_one_of: - - bucket_options.0.linear_buckets.0.num_finite_buckets - - bucket_options.0.linear_buckets.0.width - - bucket_options.0.linear_buckets.0.offset description: | Must be greater than 0. + required: true - !ruby/object:Api::Type::Double name: width - at_least_one_of: - - bucket_options.0.linear_buckets.0.num_finite_buckets - - bucket_options.0.linear_buckets.0.width - - bucket_options.0.linear_buckets.0.offset description: | Must be greater than 0. + required: true - !ruby/object:Api::Type::Double name: offset - at_least_one_of: - - bucket_options.0.linear_buckets.0.num_finite_buckets - - bucket_options.0.linear_buckets.0.width - - bucket_options.0.linear_buckets.0.offset description: | Lower bound of the first bucket. + required: true - !ruby/object:Api::Type::NestedObject name: exponentialBuckets at_least_one_of: @@ -240,28 +231,19 @@ properties: properties: - !ruby/object:Api::Type::Integer name: numFiniteBuckets - at_least_one_of: - - bucket_options.0.exponential_buckets.0.num_finite_buckets - - bucket_options.0.exponential_buckets.0.growth_factor - - bucket_options.0.exponential_buckets.0.scale description: | Must be greater than 0. + required: true - !ruby/object:Api::Type::Double name: growthFactor - at_least_one_of: - - bucket_options.0.exponential_buckets.0.num_finite_buckets - - bucket_options.0.exponential_buckets.0.growth_factor - - bucket_options.0.exponential_buckets.0.scale description: | Must be greater than 1. + required: true - !ruby/object:Api::Type::Double name: scale - at_least_one_of: - - bucket_options.0.exponential_buckets.0.num_finite_buckets - - bucket_options.0.exponential_buckets.0.growth_factor - - bucket_options.0.exponential_buckets.0.scale description: | Must be greater than 0. + required: true - !ruby/object:Api::Type::NestedObject name: explicitBuckets at_least_one_of: From 2afc9e6d3881a4216be6da96c5f64ba3e75af067 Mon Sep 17 00:00:00 2001 From: hao-nan-li <100219545+hao-nan-li@users.noreply.github.com> Date: Wed, 30 Aug 2023 12:57:48 -0700 Subject: [PATCH 19/67] Remove default value for rule.rate_limit_options.encorce_on_key on resource google_compute_security_policy (#8804) --- .../services/compute/resource_compute_security_policy.go.erb | 1 - 1 file changed, 1 deletion(-) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_security_policy.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_security_policy.go.erb index a96ca1fe6a8e..4b82ac79182b 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_security_policy.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_security_policy.go.erb @@ -268,7 +268,6 @@ func ResourceComputeSecurityPolicy() *schema.Resource { "enforce_on_key": { Type: schema.TypeString, Optional: true, - Default: "ALL", Description: `Determines the key to enforce the rateLimitThreshold on`, ValidateFunc: validation.StringInSlice([]string{"ALL", "IP", "HTTP_HEADER", "XFF_IP", "HTTP_COOKIE", "HTTP_PATH", "SNI", "REGION_CODE", ""}, false), }, From ae21b64e00316f10680dc0ea77166be283f4b32d Mon Sep 17 00:00:00 2001 From: Nick Elliot Date: Fri, 1 Sep 2023 14:00:04 -0700 Subject: [PATCH 20/67] Display default provider values at plan-time (#8569) --- mmv1/api/resource.rb | 5 + mmv1/products/compute/Autoscaler.yaml | 1 + .../compute/DiskResourcePolicyAttachment.yaml | 1 + .../compute/NetworkEndpointGroup.yaml | 1 + mmv1/products/compute/PerInstanceConfig.yaml | 1 + mmv1/products/compute/RegionAutoscaler.yaml | 1 + mmv1/products/compute/ResourcePolicy.yaml | 1 + mmv1/products/compute/ServiceAttachment.yaml | 1 + mmv1/products/redis/Instance.yaml | 2 + mmv1/templates/terraform/resource.erb | 22 +- .../resource_app_engine_application.go | 1 + .../bigquery/resource_bigquery_table.go | 1 + .../bigtable/resource_bigtable_instance.go | 1 + .../bigtable/resource_bigtable_table.go | 4 + .../resource_cloudfunctions_function.go | 6 + .../resource_composer_environment.go.erb | 6 + .../resource_compute_attached_disk.go.erb | 6 + .../compute/resource_compute_instance.go.erb | 2 + ...urce_compute_instance_from_template.go.erb | 6 +- .../resource_compute_instance_group.go.erb | 6 + ...urce_compute_instance_group_manager.go.erb | 5 + .../resource_compute_instance_template.go.erb | 1 + ...ompute_project_default_network_tier.go.erb | 5 + .../resource_compute_project_metadata.go.erb | 5 + ...ource_compute_project_metadata_item.go.erb | 5 + ...mpute_region_instance_group_manager.go.erb | 6 + ...ce_compute_region_instance_template.go.erb | 2 + .../resource_compute_router_interface.go.erb | 6 + .../resource_compute_security_policy.go.erb | 6 +- ..._compute_shared_vpc_service_project.go.erb | 5 + .../resource_compute_target_pool.go.erb | 6 + .../resource_usage_export_bucket.go.erb | 5 + .../resource_container_node_pool.go.erb | 1 + .../resource_container_registry.go | 5 + .../dataproc/resource_dataproc_cluster.go.erb | 5 + .../dataproc/resource_dataproc_job.go.erb | 5 + .../resource_dialogflow_cx_environment.go | 5 + .../resource_dialogflow_cx_version.go | 5 + .../services/dns/resource_dns_record_set.go | 5 + .../logging/resource_logging_bucket_config.go | 4 + .../resource_monitoring_dashboard.go | 5 + ...resource_os_config_os_policy_assignment.go | 5 + ...resource_google_project_iam_custom_role.go | 5 + .../resource_google_project_service.go | 5 + .../resource_google_service_account.go | 4 + .../resource_project_service_identity.go.erb | 5 + .../resource_runtimeconfig_config.go.erb | 5 + .../resource_runtimeconfig_variable.go.erb | 5 + ...le_service_networking_peered_dns_domain.go | 5 + .../sql/resource_sql_database_instance.go.erb | 1 + .../services/sql/resource_sql_ssl_cert.go | 5 + .../services/sql/resource_sql_user.go | 5 + .../resource_storage_transfer_job.go | 5 + .../terraform/tpgresource/utils.go | 93 +++ .../provider_versionfive_upgrade_test.go.erb | 646 ++++++++++++++++++ tpgtools/overrides/apikeys/beta/key.yaml | 4 + tpgtools/overrides/apikeys/key.yaml | 4 + .../bigqueryreservation/assignment.yaml | 4 + .../bigqueryreservation/beta/assignment.yaml | 4 + .../cloudbuild/beta/worker_pool.yaml | 4 + .../overrides/cloudbuild/worker_pool.yaml | 4 + .../cloudbuildv2/beta/connection.yaml | 4 + .../cloudbuildv2/beta/repository.yaml | 4 + .../overrides/cloudbuildv2/connection.yaml | 4 + .../overrides/cloudbuildv2/repository.yaml | 4 + .../clouddeploy/beta/delivery_pipeline.yaml | 4 + .../overrides/clouddeploy/beta/target.yaml | 4 + .../clouddeploy/delivery_pipeline.yaml | 4 + tpgtools/overrides/clouddeploy/target.yaml | 4 + .../compute/beta/firewall_policy.yaml | 4 + .../beta/firewall_policy_association.yaml | 4 + .../compute/beta/firewall_policy_rule.yaml | 4 + .../compute/beta/network_firewall_policy.yaml | 5 + .../network_firewall_policy_association.yaml | 5 + .../beta/network_firewall_policy_rule.yaml | 5 + .../overrides/compute/firewall_policy.yaml | 4 + .../compute/firewall_policy_association.yaml | 4 + .../compute/firewall_policy_rule.yaml | 4 + .../compute/network_firewall_policy.yaml | 5 + .../network_firewall_policy_association.yaml | 5 + .../compute/network_firewall_policy_rule.yaml | 5 + .../overrides/containeraws/beta/cluster.yaml | 4 + .../containeraws/beta/node_pool.yaml | 4 + tpgtools/overrides/containeraws/cluster.yaml | 4 + .../overrides/containeraws/node_pool.yaml | 4 + .../containerazure/azure_client.yaml | 4 + .../containerazure/beta/azure_client.yaml | 4 + .../containerazure/beta/cluster.yaml | 6 +- .../containerazure/beta/node_pool.yaml | 4 + .../overrides/containerazure/cluster.yaml | 4 + .../overrides/containerazure/node_pool.yaml | 4 + tpgtools/overrides/dataplex/asset.yaml | 4 + tpgtools/overrides/dataplex/beta/asset.yaml | 4 + tpgtools/overrides/dataplex/beta/lake.yaml | 4 + tpgtools/overrides/dataplex/beta/zone.yaml | 4 + tpgtools/overrides/dataplex/lake.yaml | 4 + tpgtools/overrides/dataplex/zone.yaml | 4 + .../dataproc/beta/workflow_template.yaml | 4 + .../overrides/dataproc/workflow_template.yaml | 4 + tpgtools/overrides/eventarc/beta/channel.yaml | 4 + .../eventarc/beta/google_channel_config.yaml | 4 + tpgtools/overrides/eventarc/beta/trigger.yaml | 5 +- tpgtools/overrides/eventarc/channel.yaml | 4 + .../eventarc/google_channel_config.yaml | 4 + tpgtools/overrides/eventarc/trigger.yaml | 4 + .../overrides/firebaserules/beta/release.yaml | 4 + .../overrides/firebaserules/beta/ruleset.yaml | 4 + tpgtools/overrides/firebaserules/release.yaml | 4 + tpgtools/overrides/firebaserules/ruleset.yaml | 4 + .../gkehub/beta/feature_membership.yaml | 6 +- .../networkconnectivity/beta/hub.yaml | 4 + .../networkconnectivity/beta/spoke.yaml | 4 + .../overrides/networkconnectivity/hub.yaml | 4 + .../overrides/networkconnectivity/spoke.yaml | 4 + .../privateca/beta/certificate_template.yaml | 4 + .../privateca/certificate_template.yaml | 4 + .../recaptchaenterprise/beta/key.yaml | 4 + .../overrides/recaptchaenterprise/key.yaml | 4 + 118 files changed, 1223 insertions(+), 6 deletions(-) create mode 100644 mmv1/third_party/terraform/utils/provider_versionfive_upgrade_test.go.erb diff --git a/mmv1/api/resource.rb b/mmv1/api/resource.rb index 267b2d91115f..0321f88f89f5 100644 --- a/mmv1/api/resource.rb +++ b/mmv1/api/resource.rb @@ -217,6 +217,10 @@ module Properties # public ca external account keys attr_reader :skip_read + # Set to true for resources that wish to disable automatic generation of default provider + # value customdiff functions + attr_reader :skip_default_cdiff + # This enables resources that get their project via a reference to a different resource # instead of a project field to use User Project Overrides attr_reader :supports_indirect_user_project_override @@ -322,6 +326,7 @@ def validate check :migrate_state, type: String check :skip_delete, type: :boolean, default: false check :skip_read, type: :boolean, default: false + check :skip_default_cdiff, type: :boolean, default: false check :supports_indirect_user_project_override, type: :boolean, default: false check :legacy_long_form_project, type: :boolean, default: false check :read_error_transform, type: String diff --git a/mmv1/products/compute/Autoscaler.yaml b/mmv1/products/compute/Autoscaler.yaml index 8c66621727e9..e4480401284e 100644 --- a/mmv1/products/compute/Autoscaler.yaml +++ b/mmv1/products/compute/Autoscaler.yaml @@ -84,6 +84,7 @@ parameters: URL of the zone where the instance group resides. required: false immutable: true + ignore_read: true default_from_api: true custom_expand: 'templates/terraform/custom_expand/resourceref_with_validation.go.erb' properties: diff --git a/mmv1/products/compute/DiskResourcePolicyAttachment.yaml b/mmv1/products/compute/DiskResourcePolicyAttachment.yaml index c2cbb0524deb..0926037d8e30 100644 --- a/mmv1/products/compute/DiskResourcePolicyAttachment.yaml +++ b/mmv1/products/compute/DiskResourcePolicyAttachment.yaml @@ -77,6 +77,7 @@ parameters: description: 'A reference to the zone where the disk resides.' required: false url_param_only: true + ignore_read: true default_from_api: true properties: - !ruby/object:Api::Type::String diff --git a/mmv1/products/compute/NetworkEndpointGroup.yaml b/mmv1/products/compute/NetworkEndpointGroup.yaml index 9e849d2b3f76..529ebb2fab35 100644 --- a/mmv1/products/compute/NetworkEndpointGroup.yaml +++ b/mmv1/products/compute/NetworkEndpointGroup.yaml @@ -78,6 +78,7 @@ parameters: Zone where the network endpoint group is located. required: false default_from_api: true + ignore_read: true custom_expand: 'templates/terraform/custom_expand/resourceref_with_validation.go.erb' properties: - !ruby/object:Api::Type::String diff --git a/mmv1/products/compute/PerInstanceConfig.yaml b/mmv1/products/compute/PerInstanceConfig.yaml index 57c1b8bc3300..5ebfb93a4cfa 100644 --- a/mmv1/products/compute/PerInstanceConfig.yaml +++ b/mmv1/products/compute/PerInstanceConfig.yaml @@ -124,6 +124,7 @@ parameters: url_param_only: true immutable: true ignore_read: true + default_from_api: true - !ruby/object:Api::Type::ResourceRef name: 'instanceGroupManager' resource: 'InstanceGroupManager' diff --git a/mmv1/products/compute/RegionAutoscaler.yaml b/mmv1/products/compute/RegionAutoscaler.yaml index e68955cf3728..3783b308a3be 100644 --- a/mmv1/products/compute/RegionAutoscaler.yaml +++ b/mmv1/products/compute/RegionAutoscaler.yaml @@ -65,6 +65,7 @@ parameters: required: false immutable: true default_from_api: true + ignore_read: true custom_expand: 'templates/terraform/custom_expand/resourceref_with_validation.go.erb' properties: - !ruby/object:Api::Type::Time diff --git a/mmv1/products/compute/ResourcePolicy.yaml b/mmv1/products/compute/ResourcePolicy.yaml index 2fc5f561273e..8e645187a41e 100644 --- a/mmv1/products/compute/ResourcePolicy.yaml +++ b/mmv1/products/compute/ResourcePolicy.yaml @@ -85,6 +85,7 @@ parameters: description: Region where resource policy resides. immutable: true required: false + ignore_read: true default_from_api: true custom_expand: 'templates/terraform/custom_expand/resourceref_with_validation.go.erb' properties: diff --git a/mmv1/products/compute/ServiceAttachment.yaml b/mmv1/products/compute/ServiceAttachment.yaml index a795f7d97a98..427ef1eb1fc8 100644 --- a/mmv1/products/compute/ServiceAttachment.yaml +++ b/mmv1/products/compute/ServiceAttachment.yaml @@ -93,6 +93,7 @@ parameters: required: false immutable: true default_from_api: true + ignore_read: true custom_expand: 'templates/terraform/custom_expand/resourceref_with_validation.go.erb' properties: - !ruby/object:Api::Type::String diff --git a/mmv1/products/redis/Instance.yaml b/mmv1/products/redis/Instance.yaml index eaab27ffdb55..b232ae4e69bd 100644 --- a/mmv1/products/redis/Instance.yaml +++ b/mmv1/products/redis/Instance.yaml @@ -28,6 +28,7 @@ timeouts: !ruby/object:Api::Timeouts update_minutes: 20 delete_minutes: 20 autogen_async: true +skip_default_cdiff: true custom_code: !ruby/object:Provider::Terraform::CustomCode encoder: templates/terraform/encoders/redis_location_id_for_fallback_zone.go.erb decoder: templates/terraform/decoders/redis_instance.go.erb @@ -35,6 +36,7 @@ custom_code: !ruby/object:Provider::Terraform::CustomCode constants: templates/terraform/constants/redis_instance.go custom_diff: [ 'customdiff.ForceNewIfChange("redis_version", isRedisVersionDecreasing)', + 'tpgresource.DefaultProviderProject', ] examples: - !ruby/object:Provider::Terraform::Examples diff --git a/mmv1/templates/terraform/resource.erb b/mmv1/templates/terraform/resource.erb index 4306de057c7a..f24f763b02f3 100644 --- a/mmv1/templates/terraform/resource.erb +++ b/mmv1/templates/terraform/resource.erb @@ -65,6 +65,7 @@ import ( client_name_lower = client_name.downcase has_project = object.base_url.include?('{{project}}') || (object.create_url && object.create_url.include?('{{project}}')) has_region = object.base_url.include?('{{region}}') && object.parameters.any?{ |p| p.name == 'region' && p.ignore_read } + has_zone = object.base_url.include?('{{zone}}') && object.parameters.any?{ |p| p.name == 'zone' && p.ignore_read } # In order of preference, use TF override, # general defined timeouts, or default Timeouts timeouts = object.timeouts @@ -113,7 +114,7 @@ func Resource<%= resource_name -%>() *schema.Resource { <% end -%> }, <% end -%> -<% if object.custom_diff.any? || object.settable_properties.any? {|p| p.unordered_list}-%> +<% if ((has_project || has_region || has_zone) && !object.skip_default_cdiff) || object.custom_diff.any? || object.settable_properties.any? {|p| p.unordered_list}-%> CustomizeDiff: customdiff.All( <% if object.settable_properties.any? {|p| p.unordered_list} -%> <%= @@ -126,6 +127,15 @@ func Resource<%= resource_name -%>() *schema.Resource { <% for cdiff in object.custom_diff-%> <%= cdiff%>, <% end -%> +<% end -%> +<% if has_project && !object.skip_default_cdiff -%> + tpgresource.DefaultProviderProject, +<% end -%> +<% if has_region && !object.skip_default_cdiff -%> + tpgresource.DefaultProviderRegion, +<% end -%> +<% if has_zone && !object.skip_default_cdiff -%> + tpgresource.DefaultProviderZone, <% end -%> ), <% end -%> @@ -640,6 +650,16 @@ func resource<%= resource_name -%>Read(d *schema.ResourceData, meta interface{}) } <% end -%> +<% if has_zone -%> + zone, err := tpgresource.GetZone(d, config) + if err != nil { + return err + } + if err := d.Set("zone", zone); err != nil { + return fmt.Errorf("Error reading <%= object.name -%>: %s", err) + } +<% end -%> + <% object.gettable_properties.reject{|p| p.ignore_read }.each do |prop| -%> <% if prop.flatten_object -%> // Terraform must set the top level schema field, but since this object contains collapsed properties diff --git a/mmv1/third_party/terraform/services/appengine/resource_app_engine_application.go b/mmv1/third_party/terraform/services/appengine/resource_app_engine_application.go index 0ca799ade56d..c7d631e84806 100644 --- a/mmv1/third_party/terraform/services/appengine/resource_app_engine_application.go +++ b/mmv1/third_party/terraform/services/appengine/resource_app_engine_application.go @@ -32,6 +32,7 @@ func ResourceAppEngineApplication() *schema.Resource { }, CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, appEngineApplicationLocationIDCustomizeDiff, ), diff --git a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go index 99debcd4cdd5..8116bf8834ba 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go @@ -419,6 +419,7 @@ func ResourceBigQueryTable() *schema.Resource { State: resourceBigQueryTableImport, }, CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, resourceBigQueryTableSchemaCustomizeDiff, ), Schema: map[string]*schema.Schema{ diff --git a/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance.go b/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance.go index 840e1be46e12..1863b8f3e8c9 100644 --- a/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance.go +++ b/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance.go @@ -34,6 +34,7 @@ func ResourceBigtableInstance() *schema.Resource { }, CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, resourceBigtableInstanceClusterReorderTypeList, resourceBigtableInstanceUniqueClusterID, ), diff --git a/mmv1/third_party/terraform/services/bigtable/resource_bigtable_table.go b/mmv1/third_party/terraform/services/bigtable/resource_bigtable_table.go index cd5d4f334b70..22dfdb88c53f 100644 --- a/mmv1/third_party/terraform/services/bigtable/resource_bigtable_table.go +++ b/mmv1/third_party/terraform/services/bigtable/resource_bigtable_table.go @@ -7,6 +7,7 @@ import ( "time" "cloud.google.com/go/bigtable" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -32,6 +33,9 @@ func ResourceBigtableTable() *schema.Resource { Update: schema.DefaultTimeout(20 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), // ---------------------------------------------------------------------- // IMPORTANT: Do not add any additional ForceNew fields to this resource. // Destroying/recreating tables can lead to data loss for users. diff --git a/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function.go b/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function.go index 6519fa0444b5..6cf41e153ef4 100644 --- a/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function.go +++ b/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function.go @@ -3,6 +3,7 @@ package cloudfunctions import ( "regexp" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -141,6 +142,11 @@ func ResourceCloudFunctionsFunction() *schema.Resource { Delete: schema.DefaultTimeout(5 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.DefaultProviderRegion, + ), + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, 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 dc642a764e09..4dc1b2b86ce3 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 @@ -9,6 +9,7 @@ import ( "time" "github.com/hashicorp/go-version" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -156,6 +157,11 @@ func ResourceComposerEnvironment() *schema.Resource { Delete: schema.DefaultTimeout(30 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.DefaultProviderRegion, + ), + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_attached_disk.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_attached_disk.go.erb index cec13a19f1da..9725498a1f7a 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_attached_disk.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_attached_disk.go.erb @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -35,6 +36,11 @@ func ResourceComputeAttachedDisk() *schema.Resource { Delete: schema.DefaultTimeout(300 * time.Second), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.DefaultProviderZone, + ), + Schema: map[string]*schema.Schema{ "disk": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb index 5a7eca0f7514..fdbbdc29bef8 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb @@ -1044,6 +1044,8 @@ be from 0 to 999,999,999 inclusive.`, }, }, CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.DefaultProviderZone, customdiff.If( func(_ context.Context, d *schema.ResourceDiff, meta interface{}) bool { return d.HasChange("guest_accelerator") diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_template.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_template.go.erb index 5d624b4b797e..fc61dd0c02c5 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_template.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_template.go.erb @@ -7,6 +7,7 @@ import ( "log" "strings" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-google/google/tpgresource" @@ -32,7 +33,10 @@ func ResourceComputeInstanceFromTemplate() *schema.Resource { Timeouts: ResourceComputeInstance().Timeouts, Schema: computeInstanceFromTemplateSchema(), - CustomizeDiff: ResourceComputeInstance().CustomizeDiff, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ResourceComputeInstance().CustomizeDiff, + ), UseJSONNumber: true, } } diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group.go.erb index 856c24d3b6aa..e577bf497906 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group.go.erb @@ -12,6 +12,7 @@ import ( "google.golang.org/api/googleapi" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" <% if version == "ga" -%> @@ -36,6 +37,11 @@ func ResourceComputeInstanceGroup() *schema.Resource { Update: schema.DefaultTimeout(6 * time.Minute), Delete: schema.DefaultTimeout(6 * time.Minute), }, + + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.DefaultProviderZone, + ), SchemaVersion: 2, MigrateState: resourceComputeInstanceGroupMigrateState, 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 ca89eddea57c..75a142685a37 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 @@ -9,6 +9,7 @@ import ( "time" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -36,6 +37,10 @@ func ResourceComputeInstanceGroupManager() *schema.Resource { Update: schema.DefaultTimeout(15 * time.Minute), Delete: schema.DefaultTimeout(15 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.DefaultProviderZone, + ), Schema: map[string]*schema.Schema{ "base_instance_name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb index 1aa43d6df564..d44091b50ece 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb @@ -62,6 +62,7 @@ func ResourceComputeInstanceTemplate() *schema.Resource { }, SchemaVersion: 1, CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, resourceComputeInstanceTemplateSourceImageCustomizeDiff, resourceComputeInstanceTemplateScratchDiskCustomizeDiff, resourceComputeInstanceTemplateBootDiskCustomizeDiff, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_project_default_network_tier.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_project_default_network_tier.go.erb index 2b838cd1bcad..3f1830c4c210 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_project_default_network_tier.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_project_default_network_tier.go.erb @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" <% if version == "ga" -%> @@ -34,6 +35,10 @@ func ResourceComputeProjectDefaultNetworkTier() *schema.Resource { Create: schema.DefaultTimeout(4 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + SchemaVersion: 0, Schema: map[string]*schema.Schema{ diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_project_metadata.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_project_metadata.go.erb index 8186762eb938..8e8560b592f2 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_project_metadata.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_project_metadata.go.erb @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" <% if version == "ga" -%> @@ -33,6 +34,10 @@ func ResourceComputeProjectMetadata() *schema.Resource { Delete: schema.DefaultTimeout(4 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + SchemaVersion: 0, Schema: map[string]*schema.Schema{ diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_project_metadata_item.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_project_metadata_item.go.erb index 5cf62dc29590..957476bb24fb 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_project_metadata_item.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_project_metadata_item.go.erb @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" <% if version == "ga" -%> @@ -35,6 +36,10 @@ func ResourceComputeProjectMetadataItem() *schema.Resource { State: schema.ImportStatePassthrough, }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "key": { Type: schema.TypeString, 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 9ac36c5455a8..d95ed976e020 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 @@ -9,6 +9,7 @@ import ( "time" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -37,6 +38,11 @@ func ResourceComputeRegionInstanceGroupManager() *schema.Resource { Delete: schema.DefaultTimeout(15 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.DefaultProviderRegion, + ), + Schema: map[string]*schema.Schema{ "base_instance_name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.erb index 2050ede84d0c..ed8687a5271f 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.erb @@ -36,6 +36,8 @@ func ResourceComputeRegionInstanceTemplate() *schema.Resource { }, SchemaVersion: 1, CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.DefaultProviderRegion, resourceComputeInstanceTemplateSourceImageCustomizeDiff, resourceComputeInstanceTemplateScratchDiskCustomizeDiff, resourceComputeInstanceTemplateBootDiskCustomizeDiff, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_router_interface.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_router_interface.go.erb index b8f48d98cffc..807a9c443d4d 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_router_interface.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_router_interface.go.erb @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "google.golang.org/api/googleapi" @@ -35,6 +36,11 @@ func ResourceComputeRouterInterface() *schema.Resource { Delete: schema.DefaultTimeout(4 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.DefaultProviderRegion, + ), + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_security_policy.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_security_policy.go.erb index 4b82ac79182b..1d2c67fb7ab4 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_security_policy.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_security_policy.go.erb @@ -12,6 +12,7 @@ import ( "time" "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -35,7 +36,10 @@ func ResourceComputeSecurityPolicy() *schema.Resource { Importer: &schema.ResourceImporter{ State: resourceSecurityPolicyStateImporter, }, - CustomizeDiff: rulesCustomizeDiff, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + rulesCustomizeDiff, + ), Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(8 * time.Minute), diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_shared_vpc_service_project.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_shared_vpc_service_project.go.erb index 2ce95299eb93..3f5f9d7f74d2 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_shared_vpc_service_project.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_shared_vpc_service_project.go.erb @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "google.golang.org/api/googleapi" @@ -36,6 +37,10 @@ func ResourceComputeSharedVpcServiceProject() *schema.Resource { Delete: schema.DefaultTimeout(4 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "host_project": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_target_pool.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_target_pool.go.erb index 7a0bb638024f..ceb79c114082 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_target_pool.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_target_pool.go.erb @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "google.golang.org/api/googleapi" @@ -39,6 +40,11 @@ func ResourceComputeTargetPool() *schema.Resource { Delete: schema.DefaultTimeout(4 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.DefaultProviderRegion, + ), + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/compute/resource_usage_export_bucket.go.erb b/mmv1/third_party/terraform/services/compute/resource_usage_export_bucket.go.erb index e15258a3cc79..da1205fc1dca 100644 --- a/mmv1/third_party/terraform/services/compute/resource_usage_export_bucket.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_usage_export_bucket.go.erb @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" <% if version == "ga" -%> @@ -32,6 +33,10 @@ func ResourceProjectUsageBucket() *schema.Resource { Delete: schema.DefaultTimeout(4 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "bucket_name": { Type: schema.TypeString, 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 9d73c6ccb416..14d7e4419cfd 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 @@ -48,6 +48,7 @@ func ResourceContainerNodePool() *schema.Resource { }, CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, resourceNodeConfigEmptyGuestAccelerator, ), diff --git a/mmv1/third_party/terraform/services/containeranalysis/resource_container_registry.go b/mmv1/third_party/terraform/services/containeranalysis/resource_container_registry.go index f19e1389bd0b..d44bb07e105c 100644 --- a/mmv1/third_party/terraform/services/containeranalysis/resource_container_registry.go +++ b/mmv1/third_party/terraform/services/containeranalysis/resource_container_registry.go @@ -5,6 +5,7 @@ import ( "log" "strings" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "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" @@ -16,6 +17,10 @@ func ResourceContainerRegistry() *schema.Resource { Read: resourceContainerRegistryRead, Delete: resourceContainerRegistryDelete, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "location": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster.go.erb b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster.go.erb index 39c8bd221972..d66f2a3464f8 100644 --- a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster.go.erb +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster.go.erb @@ -10,6 +10,7 @@ import ( "strings" "time" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -162,6 +163,10 @@ func ResourceDataprocCluster() *schema.Resource { Delete: schema.DefaultTimeout(45 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_job.go.erb b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_job.go.erb index d1fcd5ceb4dd..fc6c576a08c3 100644 --- a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_job.go.erb +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_job.go.erb @@ -11,6 +11,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" "github.com/hashicorp/terraform-provider-google/google/verify" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "google.golang.org/api/dataproc/v1" @@ -30,6 +31,10 @@ func ResourceDataprocJob() *schema.Resource { Delete: schema.DefaultTimeout(20 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "project": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflow_cx_environment.go b/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflow_cx_environment.go index 086883aa0d4d..3953c21bb38d 100644 --- a/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflow_cx_environment.go +++ b/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflow_cx_environment.go @@ -8,6 +8,7 @@ import ( "strings" "time" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -32,6 +33,10 @@ func ResourceDialogflowCXEnvironment() *schema.Resource { Delete: schema.DefaultTimeout(20 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "display_name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflow_cx_version.go b/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflow_cx_version.go index 980387b9eb16..98d22ff459ed 100644 --- a/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflow_cx_version.go +++ b/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflow_cx_version.go @@ -8,6 +8,7 @@ import ( "strings" "time" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -33,6 +34,10 @@ func ResourceDialogflowCXVersion() *schema.Resource { Delete: schema.DefaultTimeout(20 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "display_name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/dns/resource_dns_record_set.go b/mmv1/third_party/terraform/services/dns/resource_dns_record_set.go index 38d53ebc4b39..4a4d90eaa5a0 100644 --- a/mmv1/third_party/terraform/services/dns/resource_dns_record_set.go +++ b/mmv1/third_party/terraform/services/dns/resource_dns_record_set.go @@ -8,6 +8,7 @@ import ( "net" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-google/google/tpgresource" @@ -81,6 +82,10 @@ func ResourceDnsRecordSet() *schema.Resource { State: resourceDnsRecordSetImportState, }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "managed_zone": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/logging/resource_logging_bucket_config.go b/mmv1/third_party/terraform/services/logging/resource_logging_bucket_config.go index 9ad5ebb08f29..923d253a74d0 100644 --- a/mmv1/third_party/terraform/services/logging/resource_logging_bucket_config.go +++ b/mmv1/third_party/terraform/services/logging/resource_logging_bucket_config.go @@ -6,6 +6,7 @@ import ( "regexp" "strings" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "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" @@ -105,6 +106,9 @@ func ResourceLoggingBucketConfig(parentType string, parentSpecificSchema map[str }, Schema: tpgresource.MergeSchemas(loggingBucketConfigSchema, parentSpecificSchema), UseJSONNumber: true, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), } } diff --git a/mmv1/third_party/terraform/services/monitoring/resource_monitoring_dashboard.go b/mmv1/third_party/terraform/services/monitoring/resource_monitoring_dashboard.go index b0a06770882d..aa8a0d57c5e3 100644 --- a/mmv1/third_party/terraform/services/monitoring/resource_monitoring_dashboard.go +++ b/mmv1/third_party/terraform/services/monitoring/resource_monitoring_dashboard.go @@ -8,6 +8,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -51,6 +52,10 @@ func ResourceMonitoringDashboard() *schema.Resource { Delete: schema.DefaultTimeout(4 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "dashboard_json": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/osconfig/resource_os_config_os_policy_assignment.go b/mmv1/third_party/terraform/services/osconfig/resource_os_config_os_policy_assignment.go index c3e8e143c89d..9ea349cdbce8 100644 --- a/mmv1/third_party/terraform/services/osconfig/resource_os_config_os_policy_assignment.go +++ b/mmv1/third_party/terraform/services/osconfig/resource_os_config_os_policy_assignment.go @@ -7,6 +7,7 @@ import ( "strings" "time" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "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" @@ -30,6 +31,10 @@ func ResourceOSConfigOSPolicyAssignment() *schema.Resource { Delete: schema.DefaultTimeout(20 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "instance_filter": { Type: schema.TypeList, diff --git a/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_iam_custom_role.go b/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_iam_custom_role.go index 121919258376..ef27f2aacb9a 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_iam_custom_role.go +++ b/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_iam_custom_role.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-google/google/tpgresource" @@ -23,6 +24,10 @@ func ResourceGoogleProjectIamCustomRole() *schema.Resource { State: resourceGoogleProjectIamCustomRoleImport, }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "role_id": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_service.go b/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_service.go index a24765e16f6d..94d5d4873e18 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_service.go +++ b/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_service.go @@ -6,6 +6,7 @@ import ( "strings" "time" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" tpgserviceusage "github.com/hashicorp/terraform-provider-google/google/services/serviceusage" @@ -93,6 +94,10 @@ func ResourceGoogleProjectService() *schema.Resource { Delete: schema.DefaultTimeout(20 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "service": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/resourcemanager/resource_google_service_account.go b/mmv1/third_party/terraform/services/resourcemanager/resource_google_service_account.go index ca67bda3b101..4ce623f56ad8 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/resource_google_service_account.go +++ b/mmv1/third_party/terraform/services/resourcemanager/resource_google_service_account.go @@ -9,6 +9,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" "github.com/hashicorp/terraform-provider-google/google/verify" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "google.golang.org/api/iam/v1" @@ -26,6 +27,9 @@ func ResourceGoogleServiceAccount() *schema.Resource { Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(5 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), Schema: map[string]*schema.Schema{ "email": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/resourcemanager/resource_project_service_identity.go.erb b/mmv1/third_party/terraform/services/resourcemanager/resource_project_service_identity.go.erb index 9a22928cca5f..351fa637401c 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/resource_project_service_identity.go.erb +++ b/mmv1/third_party/terraform/services/resourcemanager/resource_project_service_identity.go.erb @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -26,6 +27,10 @@ func ResourceProjectServiceIdentity() *schema.Resource { Delete: schema.DefaultTimeout(20 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "service": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/runtimeconfig/resource_runtimeconfig_config.go.erb b/mmv1/third_party/terraform/services/runtimeconfig/resource_runtimeconfig_config.go.erb index 273ec7dc010b..f0d1aa31a902 100644 --- a/mmv1/third_party/terraform/services/runtimeconfig/resource_runtimeconfig_config.go.erb +++ b/mmv1/third_party/terraform/services/runtimeconfig/resource_runtimeconfig_config.go.erb @@ -10,6 +10,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" "github.com/hashicorp/terraform-provider-google/google/verify" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" runtimeconfig "google.golang.org/api/runtimeconfig/v1beta1" ) @@ -27,6 +28,10 @@ func ResourceRuntimeconfigConfig() *schema.Resource { State: resourceRuntimeconfigConfigImport, }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/runtimeconfig/resource_runtimeconfig_variable.go.erb b/mmv1/third_party/terraform/services/runtimeconfig/resource_runtimeconfig_variable.go.erb index fbabc5d7ee00..01c98fc45724 100644 --- a/mmv1/third_party/terraform/services/runtimeconfig/resource_runtimeconfig_variable.go.erb +++ b/mmv1/third_party/terraform/services/runtimeconfig/resource_runtimeconfig_variable.go.erb @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" runtimeconfig "google.golang.org/api/runtimeconfig/v1beta1" ) @@ -24,6 +25,10 @@ func ResourceRuntimeconfigVariable() *schema.Resource { State: resourceRuntimeconfigVariableImport, }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/servicenetworking/resource_google_service_networking_peered_dns_domain.go b/mmv1/third_party/terraform/services/servicenetworking/resource_google_service_networking_peered_dns_domain.go index 108d5d343588..bb9aba314e34 100644 --- a/mmv1/third_party/terraform/services/servicenetworking/resource_google_service_networking_peered_dns_domain.go +++ b/mmv1/third_party/terraform/services/servicenetworking/resource_google_service_networking_peered_dns_domain.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "google.golang.org/api/servicenetworking/v1" ) @@ -30,6 +31,10 @@ func ResourceGoogleServiceNetworkingPeeredDNSDomain() *schema.Resource { Delete: schema.DefaultTimeout(20 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "project": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.erb b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.erb index 90f7ef577212..e8cbf9eab4b9 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.erb +++ b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.erb @@ -134,6 +134,7 @@ func ResourceSqlDatabaseInstance() *schema.Resource { }, CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, customdiff.ForceNewIfChange("settings.0.disk_size", compute.IsDiskShrinkage), customdiff.ForceNewIfChange("master_instance_name", isMasterInstanceNameSet), customdiff.IfValueChange("instance_type", isReplicaPromoteRequested, checkPromoteConfigurationsAndUpdateDiff), diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_ssl_cert.go b/mmv1/third_party/terraform/services/sql/resource_sql_ssl_cert.go index 116a9b682f86..374230343810 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_ssl_cert.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_ssl_cert.go @@ -8,6 +8,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" sqladmin "google.golang.org/api/sqladmin/v1beta4" ) @@ -25,6 +26,10 @@ func ResourceSqlSslCert() *schema.Resource { Delete: schema.DefaultTimeout(10 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "common_name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_user.go b/mmv1/third_party/terraform/services/sql/resource_sql_user.go index d0ee4d85bc0b..599e55df39f7 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_user.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_user.go @@ -10,6 +10,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" sqladmin "google.golang.org/api/sqladmin/v1beta4" @@ -56,6 +57,10 @@ func ResourceSqlUser() *schema.Resource { Delete: schema.DefaultTimeout(10 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + SchemaVersion: 1, MigrateState: resourceSqlUserMigrateState, 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 index 07b3c1dcc2b9..3e746270d10c 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 @@ -11,6 +11,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" "github.com/hashicorp/terraform-provider-google/google/verify" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -61,6 +62,10 @@ func ResourceStorageTransferJob() *schema.Resource { State: resourceStorageTransferJobStateImporter, }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/tpgresource/utils.go b/mmv1/third_party/terraform/tpgresource/utils.go index 3722678026c7..0d9310fafb8d 100644 --- a/mmv1/third_party/terraform/tpgresource/utils.go +++ b/mmv1/third_party/terraform/tpgresource/utils.go @@ -1,6 +1,7 @@ package tpgresource import ( + "context" "crypto/md5" "encoding/base64" "errors" @@ -18,6 +19,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" "github.com/hashicorp/errwrap" + "github.com/hashicorp/go-cty/cty" fwDiags "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -97,12 +99,49 @@ func GetProjectFromDiff(d *schema.ResourceDiff, config *transport_tpg.Config) (s if ok { return res.(string), nil } + if d.GetRawConfig().GetAttr("project") == cty.UnknownVal(cty.String) { + return res.(string), nil + } if config.Project != "" { return config.Project, nil } return "", fmt.Errorf("%s: required field is not set", "project") } +// getRegionFromDiff reads the "region" field from the given diff and falls +// back to the provider's value if not given. If the provider's value is not +// given, an error is returned. +func GetRegionFromDiff(d *schema.ResourceDiff, config *transport_tpg.Config) (string, error) { + res, ok := d.GetOk("region") + if ok { + return res.(string), nil + } + if d.GetRawConfig().GetAttr("region") == cty.UnknownVal(cty.String) { + return res.(string), nil + } + if config.Region != "" { + return config.Region, nil + } + return "", fmt.Errorf("%s: required field is not set", "region") +} + +// getZoneFromDiff reads the "zone" field from the given diff and falls +// back to the provider's value if not given. If the provider's value is not +// given, an error is returned. +func GetZoneFromDiff(d *schema.ResourceDiff, config *transport_tpg.Config) (string, error) { + res, ok := d.GetOk("zone") + if ok { + return res.(string), nil + } + if d.GetRawConfig().GetAttr("zone") == cty.UnknownVal(cty.String) { + return res.(string), nil + } + if config.Zone != "" { + return config.Zone, nil + } + return "", fmt.Errorf("%s: required field is not set", "zone") +} + func GetRouterLockName(region string, router string) string { return fmt.Sprintf("router/%s/%s", region, router) } @@ -702,3 +741,57 @@ func GetContentMd5Hash(content []byte) string { } return base64.StdEncoding.EncodeToString(h.Sum(nil)) } + +func DefaultProviderProject(_ context.Context, diff *schema.ResourceDiff, meta interface{}) error { + + config := meta.(*transport_tpg.Config) + + //project + if project := diff.Get("project"); project != nil { + project, err := GetProjectFromDiff(diff, config) + if err != nil { + return fmt.Errorf("Failed to retrieve project, pid: %s, err: %s", project, err) + } + err = diff.SetNew("project", project) + if err != nil { + return err + } + } + return nil +} + +func DefaultProviderRegion(_ context.Context, diff *schema.ResourceDiff, meta interface{}) error { + + config := meta.(*transport_tpg.Config) + //region + if region := diff.Get("region"); region != nil { + region, err := GetRegionFromDiff(diff, config) + if err != nil { + return fmt.Errorf("Failed to retrieve region, pid: %s, err: %s", region, err) + } + err = diff.SetNew("region", region) + if err != nil { + return err + } + } + + return nil +} + +func DefaultProviderZone(_ context.Context, diff *schema.ResourceDiff, meta interface{}) error { + + config := meta.(*transport_tpg.Config) + // zone + if zone := diff.Get("zone"); zone != nil { + zone, err := GetZoneFromDiff(diff, config) + if err != nil { + return fmt.Errorf("Failed to retrieve zone, pid: %s, err: %s", zone, err) + } + err = diff.SetNew("zone", zone) + if err != nil { + return err + } + } + + return nil +} diff --git a/mmv1/third_party/terraform/utils/provider_versionfive_upgrade_test.go.erb b/mmv1/third_party/terraform/utils/provider_versionfive_upgrade_test.go.erb new file mode 100644 index 000000000000..161ec6ccf34d --- /dev/null +++ b/mmv1/third_party/terraform/utils/provider_versionfive_upgrade_test.go.erb @@ -0,0 +1,646 @@ +<% autogen_exception -%> +package google + +import ( + "fmt" + "strings" + "testing" + + "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" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestProvider_versionfive_upgrade(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + org := envvar.GetTestOrgFromEnv(t) + billingId := envvar.GetTestBillingAccountFromEnv(t) + project := fmt.Sprintf("tf-test-%d", acctest.RandInt(t)) + + name1 := fmt.Sprintf("tf-test-%d", acctest.RandInt(t)) + name2 := fmt.Sprintf("tf-test-%d", acctest.RandInt(t)) + name3 := fmt.Sprintf("tf-test-%d", acctest.RandInt(t)) + name4 := fmt.Sprintf("tf-test-%d", acctest.RandInt(t)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + Steps: []resource.TestStep{ + { + ExternalProviders: map[string]resource.ExternalProvider{ + "google": { + VersionConstraint: "4.80.0", + Source: "hashicorp/google-beta", + }, + }, + Config: testProvider_versionfive_upgrades(project, org, billingId, name1, name2, name3, name4), + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Config: testProvider_versionfive_upgrades(project, org, billingId, name1, name2, name3, name4), + PlanOnly: true, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ResourceName: "google_data_fusion_instance.unset", + ImportState: true, + ImportStateVerify: true, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ResourceName: "google_data_fusion_instance.set", + ImportState: true, + ImportStateVerify: true, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ResourceName: "google_data_fusion_instance.reference", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestProvider_versionfive_ignorereads_upgrade(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + var itName = fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + var tpName = fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + var igmName = fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + var autoscalerName = fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + + diskName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + policyName := fmt.Sprintf("tf-test-policy-%s", acctest.RandString(t, 10)) + + endpointContext := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + var itNameRegion = fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + var tpNameRegion = fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + var igmNameRegion = fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + var autoscalerNameRegion = fmt.Sprintf("tf-test-region-autoscaler-%s", acctest.RandString(t, 10)) + + policyContext := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + attachmentContext := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + CheckDestroy: resource.ComposeTestCheckFunc(testAccCheckComputeResourcePolicyDestroyProducer(t), + testAccCheckComputeRegionAutoscalerDestroyProducer(t), + testAccCheckComputeNetworkEndpointGroupDestroyProducer(t), + testAccCheckComputeAutoscalerDestroyProducer(t), + ), + Steps: []resource.TestStep{ + { + ExternalProviders: map[string]resource.ExternalProvider{ + "google": { + VersionConstraint: "4.80.0", + Source: "hashicorp/google-beta", + }, + }, + Config: testProvider_versionfive_upgrades_ignorereads(itName, tpName, igmName, autoscalerName, diskName, policyName, + itNameRegion, tpNameRegion, igmNameRegion, autoscalerNameRegion, endpointContext, + policyContext, attachmentContext), + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Config: testProvider_versionfive_upgrades_ignorereads(itName, tpName, igmName, autoscalerName, diskName, policyName, + itNameRegion, tpNameRegion, igmNameRegion, autoscalerNameRegion, endpointContext, + policyContext, attachmentContext), + PlanOnly: true, + }, + }, + }) +} + +func testProvider_versionfive_upgrades(project, org, billing, name1, name2, name3, name4 string) string { + return fmt.Sprintf(` +resource "google_project" "host" { + project_id = "%s" + name = "%s" + org_id = "%s" + billing_account = "%s" +} + +resource "google_project_service" "dfapi" { + project = google_project.host.project_id + service = "datafusion.googleapis.com" + + disable_dependent_services = false +} + +resource "google_data_fusion_instance" "unset" { + name = "%s" + type = "BASIC" + options = { + prober_test_run = "true" + } +} + +resource "google_data_fusion_instance" "set" { + name = "%s" + region = "us-west1" + type = "BASIC" + options = { + prober_test_run = "true" + } +} + +resource "google_data_fusion_instance" "reference" { + project = google_project.host.project_id + name = "%s" + type = "DEVELOPER" + options = { + prober_test_run = "true" + } + zone = "us-west1-a" + depends_on = [ + google_project_service.dfapi + ] +} + +resource "google_redis_instance" "overridewithnonstandardlogic" { + name = "%s" + memory_size_gb = 1 + location_id = "us-south1-a" +} + + +`, project, project, org, billing, name1, name2, name3, name4) +} + +func testProvider_versionfive_upgrades_ignorereads(itName, tpName, igmName, autoscalerName, diskName, policyName, itNameRegion, tpNameRegion, igmNameRegion, autoscalerNameRegion string, endpointContext, policyContext, attachmentContext map[string]interface{}) string { + return testAccComputeAutoscaler_basic(itName, tpName, igmName, autoscalerName) + + testAccComputeDiskResourcePolicyAttachment_basic(diskName, policyName) + + testAccComputeNetworkEndpointGroup_networkEndpointGroup(endpointContext) + + testAccComputeRegionAutoscaler_basic(itNameRegion, tpNameRegion, igmNameRegion, autoscalerNameRegion) + + testAccComputeResourcePolicy_resourcePolicyBasicExample(policyContext) + + testAccComputeServiceAttachment_serviceAttachmentBasicExample(attachmentContext) +} + +// need to make copies of all the respective resource functions within here as *_test.go files can not be imported +// checkdestroys +func testAccCheckComputeResourcePolicyDestroyProducer(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_compute_resource_policy" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/resourcePolicies/{{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("ComputeResourcePolicy still exists at %s", url) + } + } + + return nil + } +} + +func testAccCheckComputeRegionAutoscalerDestroyProducer(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_compute_region_autoscaler" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/autoscalers/{{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("ComputeRegionAutoscaler still exists at %s", url) + } + } + + return nil + } +} + +func testAccCheckComputeNetworkEndpointGroupDestroyProducer(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_compute_network_endpoint_group" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{ComputeBasePath}}projects/{{project}}/zones/{{zone}}/networkEndpointGroups/{{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("ComputeNetworkEndpointGroup still exists at %s", url) + } + } + + return nil + } +} + +func testAccCheckComputeAutoscalerDestroyProducer(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_compute_autoscaler" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{ComputeBasePath}}projects/{{project}}/zones/{{zone}}/autoscalers/{{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("ComputeAutoscaler still exists at %s", url) + } + } + + return nil + } +} + +// tests +func testAccComputeAutoscaler_scaffolding(itName, tpName, igmName string) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image1" { + family = "debian-11" + project = "debian-cloud" +} + +resource "google_compute_instance_template" "foobar1" { + name = "%s" + machine_type = "e2-medium" + can_ip_forward = false + tags = ["foo", "bar"] + + disk { + source_image = data.google_compute_image.my_image1.self_link + auto_delete = true + boot = true + } + + network_interface { + network = "default" + } + + service_account { + scopes = ["userinfo-email", "compute-ro", "storage-ro"] + } +} + +resource "google_compute_target_pool" "foobar1" { + description = "Resource created for Terraform acceptance testing" + name = "%s" + session_affinity = "CLIENT_IP_PROTO" + region = "us-west1" +} + +resource "google_compute_instance_group_manager" "foobar1" { + description = "Terraform test instance group manager" + name = "%s" + version { + instance_template = google_compute_instance_template.foobar1.self_link + name = "primary" + } + target_pools = [google_compute_target_pool.foobar1.self_link] + base_instance_name = "foobar1" + zone = "us-west1-a" +} +`, itName, tpName, igmName) + +} + +func testAccComputeAutoscaler_basic(itName, tpName, igmName, autoscalerName string) string { + return testAccComputeAutoscaler_scaffolding(itName, tpName, igmName) + fmt.Sprintf(` +resource "google_compute_autoscaler" "foobar1" { + description = "Resource created for Terraform acceptance testing" + name = "%s" + zone = "us-west1-a" + target = google_compute_instance_group_manager.foobar1.self_link + autoscaling_policy { + max_replicas = 5 + min_replicas = 1 + cooldown_period = 60 + cpu_utilization { + target = 0.5 + } + } +} +`, autoscalerName) +} + +func testAccComputeDiskResourcePolicyAttachment_basic(diskName, policyName string) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image2" { + family = "debian-11" + project = "debian-cloud" +} + +resource "google_compute_disk" "foobar2" { + name = "%s" + image = data.google_compute_image.my_image2.self_link + size = 1000 + type = "pd-extreme" + zone = "us-west1-c" + labels = { + my-label = "my-label-value" + } + provisioned_iops = 90000 +} + +resource "google_compute_resource_policy" "foobar2" { + name = "%s" + region = "us-west1" + snapshot_schedule_policy { + schedule { + daily_schedule { + days_in_cycle = 1 + start_time = "04:00" + } + } + } +} + +resource "google_compute_disk_resource_policy_attachment" "foobar2" { + name = google_compute_resource_policy.foobar2.name + disk = google_compute_disk.foobar2.name + zone = "us-west1-c" +} +`, diskName, policyName) +} + +func testAccComputeNetworkEndpointGroup_networkEndpointGroup(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_network_endpoint_group" "neg3" { + name = "tf-test-my-lb-neg%{random_suffix}" + network = google_compute_network.default3.id + default_port = "90" + zone = "us-west1-a" +} + +resource "google_compute_network" "default3" { + name = "tf-test-neg-network%{random_suffix}" + auto_create_subnetworks = true +} +`, context) +} + +func testAccComputeRegionAutoscaler_scaffolding(itName, tpName, igmName string) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image4" { + family = "debian-11" + project = "debian-cloud" +} + +resource "google_compute_instance_template" "foobar4" { + name = "%s" + machine_type = "e2-medium" + can_ip_forward = false + tags = ["foo", "bar"] + + disk { + source_image = data.google_compute_image.my_image4.self_link + auto_delete = true + boot = true + } + + network_interface { + network = "default" + } + + service_account { + scopes = ["userinfo-email", "compute-ro", "storage-ro"] + } +} + +resource "google_compute_target_pool" "foobar4" { + description = "Resource created for Terraform acceptance testing" + name = "%s" + session_affinity = "CLIENT_IP_PROTO" + region = "us-west1" +} + +resource "google_compute_region_instance_group_manager" "foobar4" { + description = "Terraform test instance group manager" + name = "%s" + version { + instance_template = google_compute_instance_template.foobar4.self_link + name = "primary" + } + target_pools = [google_compute_target_pool.foobar4.self_link] + base_instance_name = "tf-test-foobar4" + region = "us-west1" +} + +`, itName, tpName, igmName) +} + +func testAccComputeRegionAutoscaler_basic(itName, tpName, igmName, autoscalerName string) string { + return testAccComputeRegionAutoscaler_scaffolding(itName, tpName, igmName) + fmt.Sprintf(` +resource "google_compute_region_autoscaler" "foobar4" { + description = "Resource created for Terraform acceptance testing" + name = "%s" + region = "us-west1" + target = google_compute_region_instance_group_manager.foobar4.self_link + autoscaling_policy { + max_replicas = 5 + min_replicas = 0 + cooldown_period = 60 + cpu_utilization { + target = 0.5 + } + } +} +`, autoscalerName) +} + +func testAccComputeResourcePolicy_resourcePolicyBasicExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_resource_policy" "foo5" { + name = "tf-test-gce-policy%{random_suffix}" + region = "us-west1" + snapshot_schedule_policy { + schedule { + daily_schedule { + days_in_cycle = 1 + start_time = "04:00" + } + } + } +} +`, context) +} + +func testAccComputeServiceAttachment_serviceAttachmentBasicExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_service_attachment" "psc_ilb_service_attachment6" { + name = "tf-test-my-psc-ilb%{random_suffix}" + region = "us-west2" + description = "A service attachment configured with Terraform" + + enable_proxy_protocol = true + connection_preference = "ACCEPT_AUTOMATIC" + nat_subnets = [google_compute_subnetwork.psc_ilb_nat6.id] + target_service = google_compute_forwarding_rule.psc_ilb_target_service6.id + reconcile_connections = true +} + +resource "google_compute_address" "psc_ilb_consumer_address6" { + name = "tf-test-psc-ilb-consumer-address%{random_suffix}" + region = "us-west2" + + subnetwork = "default" + address_type = "INTERNAL" +} + +resource "google_compute_forwarding_rule" "psc_ilb_consumer6" { + name = "tf-test-psc-ilb-consumer-forwarding-rule%{random_suffix}" + region = "us-west2" + + target = google_compute_service_attachment.psc_ilb_service_attachment6.id + load_balancing_scheme = "" # need to override EXTERNAL default when target is a service attachment + network = "default" + ip_address = google_compute_address.psc_ilb_consumer_address6.id +} + +resource "google_compute_forwarding_rule" "psc_ilb_target_service6" { + name = "tf-test-producer-forwarding-rule%{random_suffix}" + region = "us-west2" + + load_balancing_scheme = "INTERNAL" + backend_service = google_compute_region_backend_service.producer_service_backend6.id + all_ports = true + network = google_compute_network.psc_ilb_network6.name + subnetwork = google_compute_subnetwork.psc_ilb_producer_subnetwork6.name +} + +resource "google_compute_region_backend_service" "producer_service_backend6" { + name = "tf-test-producer-service%{random_suffix}" + region = "us-west2" + + health_checks = [google_compute_health_check.producer_service_health_check6.id] +} + +resource "google_compute_health_check" "producer_service_health_check6" { + name = "tf-test-producer-service-health-check%{random_suffix}" + + check_interval_sec = 1 + timeout_sec = 1 + tcp_health_check { + port = "80" + } +} + +resource "google_compute_network" "psc_ilb_network6" { + name = "tf-test-psc-ilb-network%{random_suffix}" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "psc_ilb_producer_subnetwork6" { + name = "tf-test-psc-ilb-producer-subnetwork%{random_suffix}" + region = "us-west2" + + network = google_compute_network.psc_ilb_network6.id + ip_cidr_range = "10.0.0.0/16" +} + +resource "google_compute_subnetwork" "psc_ilb_nat6" { + name = "tf-test-psc-ilb-nat%{random_suffix}" + region = "us-west2" + + network = google_compute_network.psc_ilb_network6.id + purpose = "PRIVATE_SERVICE_CONNECT" + ip_cidr_range = "10.1.0.0/16" +} +`, context) +} diff --git a/tpgtools/overrides/apikeys/beta/key.yaml b/tpgtools/overrides/apikeys/beta/key.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/apikeys/beta/key.yaml +++ b/tpgtools/overrides/apikeys/beta/key.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/apikeys/key.yaml b/tpgtools/overrides/apikeys/key.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/apikeys/key.yaml +++ b/tpgtools/overrides/apikeys/key.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/bigqueryreservation/assignment.yaml b/tpgtools/overrides/bigqueryreservation/assignment.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/bigqueryreservation/assignment.yaml +++ b/tpgtools/overrides/bigqueryreservation/assignment.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/bigqueryreservation/beta/assignment.yaml b/tpgtools/overrides/bigqueryreservation/beta/assignment.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/bigqueryreservation/beta/assignment.yaml +++ b/tpgtools/overrides/bigqueryreservation/beta/assignment.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/cloudbuild/beta/worker_pool.yaml b/tpgtools/overrides/cloudbuild/beta/worker_pool.yaml index 4deb00daaee1..8c8073b08ca5 100644 --- a/tpgtools/overrides/cloudbuild/beta/worker_pool.yaml +++ b/tpgtools/overrides/cloudbuild/beta/worker_pool.yaml @@ -4,3 +4,7 @@ diffsuppressfunc: tpgresource.CompareResourceNames - type: EXCLUDE field: etag +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/cloudbuild/worker_pool.yaml b/tpgtools/overrides/cloudbuild/worker_pool.yaml index 4deb00daaee1..8c8073b08ca5 100644 --- a/tpgtools/overrides/cloudbuild/worker_pool.yaml +++ b/tpgtools/overrides/cloudbuild/worker_pool.yaml @@ -4,3 +4,7 @@ diffsuppressfunc: tpgresource.CompareResourceNames - type: EXCLUDE field: etag +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/cloudbuildv2/beta/connection.yaml b/tpgtools/overrides/cloudbuildv2/beta/connection.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/cloudbuildv2/beta/connection.yaml +++ b/tpgtools/overrides/cloudbuildv2/beta/connection.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/cloudbuildv2/beta/repository.yaml b/tpgtools/overrides/cloudbuildv2/beta/repository.yaml index 01ea7c579c97..8de5a79b7fc7 100644 --- a/tpgtools/overrides/cloudbuildv2/beta/repository.yaml +++ b/tpgtools/overrides/cloudbuildv2/beta/repository.yaml @@ -16,3 +16,7 @@ required: false optional: true computed: true +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/cloudbuildv2/connection.yaml b/tpgtools/overrides/cloudbuildv2/connection.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/cloudbuildv2/connection.yaml +++ b/tpgtools/overrides/cloudbuildv2/connection.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/cloudbuildv2/repository.yaml b/tpgtools/overrides/cloudbuildv2/repository.yaml index 01ea7c579c97..8de5a79b7fc7 100644 --- a/tpgtools/overrides/cloudbuildv2/repository.yaml +++ b/tpgtools/overrides/cloudbuildv2/repository.yaml @@ -16,3 +16,7 @@ required: false optional: true computed: true +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/clouddeploy/beta/delivery_pipeline.yaml b/tpgtools/overrides/clouddeploy/beta/delivery_pipeline.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/clouddeploy/beta/delivery_pipeline.yaml +++ b/tpgtools/overrides/clouddeploy/beta/delivery_pipeline.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/clouddeploy/beta/target.yaml b/tpgtools/overrides/clouddeploy/beta/target.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/clouddeploy/beta/target.yaml +++ b/tpgtools/overrides/clouddeploy/beta/target.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/clouddeploy/delivery_pipeline.yaml b/tpgtools/overrides/clouddeploy/delivery_pipeline.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/clouddeploy/delivery_pipeline.yaml +++ b/tpgtools/overrides/clouddeploy/delivery_pipeline.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/clouddeploy/target.yaml b/tpgtools/overrides/clouddeploy/target.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/clouddeploy/target.yaml +++ b/tpgtools/overrides/clouddeploy/target.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/compute/beta/firewall_policy.yaml b/tpgtools/overrides/compute/beta/firewall_policy.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/compute/beta/firewall_policy.yaml +++ b/tpgtools/overrides/compute/beta/firewall_policy.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/compute/beta/firewall_policy_association.yaml b/tpgtools/overrides/compute/beta/firewall_policy_association.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/compute/beta/firewall_policy_association.yaml +++ b/tpgtools/overrides/compute/beta/firewall_policy_association.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/compute/beta/firewall_policy_rule.yaml b/tpgtools/overrides/compute/beta/firewall_policy_rule.yaml index e743d253be12..dc91e4f5a9d5 100644 --- a/tpgtools/overrides/compute/beta/firewall_policy_rule.yaml +++ b/tpgtools/overrides/compute/beta/firewall_policy_rule.yaml @@ -2,3 +2,7 @@ field: target_resources details: diffsuppressfunc: tpgresource.CompareSelfLinkOrResourceName +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/compute/beta/network_firewall_policy.yaml b/tpgtools/overrides/compute/beta/network_firewall_policy.yaml index ac4ed8505f0c..ea763ef1b90d 100644 --- a/tpgtools/overrides/compute/beta/network_firewall_policy.yaml +++ b/tpgtools/overrides/compute/beta/network_firewall_policy.yaml @@ -15,3 +15,8 @@ details: id: projects/{{project}}/regions/{{region}}/firewallPolicies/{{name}} location: region +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject + - tpgresource.DefaultProviderRegion diff --git a/tpgtools/overrides/compute/beta/network_firewall_policy_association.yaml b/tpgtools/overrides/compute/beta/network_firewall_policy_association.yaml index 8919dd2c7cf8..3260bc51a574 100644 --- a/tpgtools/overrides/compute/beta/network_firewall_policy_association.yaml +++ b/tpgtools/overrides/compute/beta/network_firewall_policy_association.yaml @@ -31,3 +31,8 @@ - "projects/{{project}}/global/firewallPolicies/{{firewall_policy}}/associations/{{name}}" - "{{project}}/{{firewall_policy}}/{{name}}" location: global +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject + - tpgresource.DefaultProviderRegion diff --git a/tpgtools/overrides/compute/beta/network_firewall_policy_rule.yaml b/tpgtools/overrides/compute/beta/network_firewall_policy_rule.yaml index 6c0153011095..4ad5ccbeee34 100644 --- a/tpgtools/overrides/compute/beta/network_firewall_policy_rule.yaml +++ b/tpgtools/overrides/compute/beta/network_firewall_policy_rule.yaml @@ -17,3 +17,8 @@ details: id: projects/{{project}}/regions/{{region}}/firewallPolicies/{{firewall_policy}}/{{priority}} location: region +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject + - tpgresource.DefaultProviderRegion diff --git a/tpgtools/overrides/compute/firewall_policy.yaml b/tpgtools/overrides/compute/firewall_policy.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/compute/firewall_policy.yaml +++ b/tpgtools/overrides/compute/firewall_policy.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/compute/firewall_policy_association.yaml b/tpgtools/overrides/compute/firewall_policy_association.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/compute/firewall_policy_association.yaml +++ b/tpgtools/overrides/compute/firewall_policy_association.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/compute/firewall_policy_rule.yaml b/tpgtools/overrides/compute/firewall_policy_rule.yaml index e743d253be12..dc91e4f5a9d5 100644 --- a/tpgtools/overrides/compute/firewall_policy_rule.yaml +++ b/tpgtools/overrides/compute/firewall_policy_rule.yaml @@ -2,3 +2,7 @@ field: target_resources details: diffsuppressfunc: tpgresource.CompareSelfLinkOrResourceName +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/compute/network_firewall_policy.yaml b/tpgtools/overrides/compute/network_firewall_policy.yaml index ac4ed8505f0c..ea763ef1b90d 100644 --- a/tpgtools/overrides/compute/network_firewall_policy.yaml +++ b/tpgtools/overrides/compute/network_firewall_policy.yaml @@ -15,3 +15,8 @@ details: id: projects/{{project}}/regions/{{region}}/firewallPolicies/{{name}} location: region +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject + - tpgresource.DefaultProviderRegion diff --git a/tpgtools/overrides/compute/network_firewall_policy_association.yaml b/tpgtools/overrides/compute/network_firewall_policy_association.yaml index 8919dd2c7cf8..3260bc51a574 100644 --- a/tpgtools/overrides/compute/network_firewall_policy_association.yaml +++ b/tpgtools/overrides/compute/network_firewall_policy_association.yaml @@ -31,3 +31,8 @@ - "projects/{{project}}/global/firewallPolicies/{{firewall_policy}}/associations/{{name}}" - "{{project}}/{{firewall_policy}}/{{name}}" location: global +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject + - tpgresource.DefaultProviderRegion diff --git a/tpgtools/overrides/compute/network_firewall_policy_rule.yaml b/tpgtools/overrides/compute/network_firewall_policy_rule.yaml index 6c0153011095..4ad5ccbeee34 100644 --- a/tpgtools/overrides/compute/network_firewall_policy_rule.yaml +++ b/tpgtools/overrides/compute/network_firewall_policy_rule.yaml @@ -17,3 +17,8 @@ details: id: projects/{{project}}/regions/{{region}}/firewallPolicies/{{firewall_policy}}/{{priority}} location: region +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject + - tpgresource.DefaultProviderRegion diff --git a/tpgtools/overrides/containeraws/beta/cluster.yaml b/tpgtools/overrides/containeraws/beta/cluster.yaml index 0c72806bc726..ad5e41a283d3 100644 --- a/tpgtools/overrides/containeraws/beta/cluster.yaml +++ b/tpgtools/overrides/containeraws/beta/cluster.yaml @@ -1,5 +1,9 @@ - type: EXCLUDE field: monitoring_config +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject - type: DIFF_SUPPRESS_FUNC field: control_plane.root_volume.volume_type details: diff --git a/tpgtools/overrides/containeraws/beta/node_pool.yaml b/tpgtools/overrides/containeraws/beta/node_pool.yaml index e16b502f32ef..60a274d2b3d9 100644 --- a/tpgtools/overrides/containeraws/beta/node_pool.yaml +++ b/tpgtools/overrides/containeraws/beta/node_pool.yaml @@ -1,3 +1,7 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject - type: DIFF_SUPPRESS_FUNC field: config.root_volume.volume_type details: diff --git a/tpgtools/overrides/containeraws/cluster.yaml b/tpgtools/overrides/containeraws/cluster.yaml index 793a89736e62..8485cd756c4e 100644 --- a/tpgtools/overrides/containeraws/cluster.yaml +++ b/tpgtools/overrides/containeraws/cluster.yaml @@ -1,3 +1,7 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject - type: DIFF_SUPPRESS_FUNC field: control_plane.root_volume.volume_type details: diff --git a/tpgtools/overrides/containeraws/node_pool.yaml b/tpgtools/overrides/containeraws/node_pool.yaml index 4f76c9df9c1e..a6b6f0589d85 100644 --- a/tpgtools/overrides/containeraws/node_pool.yaml +++ b/tpgtools/overrides/containeraws/node_pool.yaml @@ -1,3 +1,7 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject - type: DIFF_SUPPRESS_FUNC field: config.root_volume.volume_type details: diff --git a/tpgtools/overrides/containerazure/azure_client.yaml b/tpgtools/overrides/containerazure/azure_client.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/containerazure/azure_client.yaml +++ b/tpgtools/overrides/containerazure/azure_client.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/containerazure/beta/azure_client.yaml b/tpgtools/overrides/containerazure/beta/azure_client.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/containerazure/beta/azure_client.yaml +++ b/tpgtools/overrides/containerazure/beta/azure_client.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/containerazure/beta/cluster.yaml b/tpgtools/overrides/containerazure/beta/cluster.yaml index 4ff1c7c72378..9c36ab64d35b 100644 --- a/tpgtools/overrides/containerazure/beta/cluster.yaml +++ b/tpgtools/overrides/containerazure/beta/cluster.yaml @@ -1,6 +1,10 @@ - type: EXCLUDE field: monitoring_config +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject - type: DIFF_SUPPRESS_FUNC field: logging_config.component_config.enable_components details: - diffsuppressfunc: tpgresource.CompareCaseInsensitive \ No newline at end of file + diffsuppressfunc: tpgresource.CompareCaseInsensitive diff --git a/tpgtools/overrides/containerazure/beta/node_pool.yaml b/tpgtools/overrides/containerazure/beta/node_pool.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/containerazure/beta/node_pool.yaml +++ b/tpgtools/overrides/containerazure/beta/node_pool.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/containerazure/cluster.yaml b/tpgtools/overrides/containerazure/cluster.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/containerazure/cluster.yaml +++ b/tpgtools/overrides/containerazure/cluster.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/containerazure/node_pool.yaml b/tpgtools/overrides/containerazure/node_pool.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/containerazure/node_pool.yaml +++ b/tpgtools/overrides/containerazure/node_pool.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/dataplex/asset.yaml b/tpgtools/overrides/dataplex/asset.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/dataplex/asset.yaml +++ b/tpgtools/overrides/dataplex/asset.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/dataplex/beta/asset.yaml b/tpgtools/overrides/dataplex/beta/asset.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/dataplex/beta/asset.yaml +++ b/tpgtools/overrides/dataplex/beta/asset.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/dataplex/beta/lake.yaml b/tpgtools/overrides/dataplex/beta/lake.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/dataplex/beta/lake.yaml +++ b/tpgtools/overrides/dataplex/beta/lake.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/dataplex/beta/zone.yaml b/tpgtools/overrides/dataplex/beta/zone.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/dataplex/beta/zone.yaml +++ b/tpgtools/overrides/dataplex/beta/zone.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/dataplex/lake.yaml b/tpgtools/overrides/dataplex/lake.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/dataplex/lake.yaml +++ b/tpgtools/overrides/dataplex/lake.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/dataplex/zone.yaml b/tpgtools/overrides/dataplex/zone.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/dataplex/zone.yaml +++ b/tpgtools/overrides/dataplex/zone.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/dataproc/beta/workflow_template.yaml b/tpgtools/overrides/dataproc/beta/workflow_template.yaml index a0cea3403c87..da6b1fa0e6ad 100644 --- a/tpgtools/overrides/dataproc/beta/workflow_template.yaml +++ b/tpgtools/overrides/dataproc/beta/workflow_template.yaml @@ -9,3 +9,7 @@ details: message: >- version is not useful as a configurable field, and will be removed in the future. +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/dataproc/workflow_template.yaml b/tpgtools/overrides/dataproc/workflow_template.yaml index a0cea3403c87..da6b1fa0e6ad 100644 --- a/tpgtools/overrides/dataproc/workflow_template.yaml +++ b/tpgtools/overrides/dataproc/workflow_template.yaml @@ -9,3 +9,7 @@ details: message: >- version is not useful as a configurable field, and will be removed in the future. +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/eventarc/beta/channel.yaml b/tpgtools/overrides/eventarc/beta/channel.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/eventarc/beta/channel.yaml +++ b/tpgtools/overrides/eventarc/beta/channel.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/eventarc/beta/google_channel_config.yaml b/tpgtools/overrides/eventarc/beta/google_channel_config.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/eventarc/beta/google_channel_config.yaml +++ b/tpgtools/overrides/eventarc/beta/google_channel_config.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/eventarc/beta/trigger.yaml b/tpgtools/overrides/eventarc/beta/trigger.yaml index 2b02fd09b9ce..9014b1241575 100644 --- a/tpgtools/overrides/eventarc/beta/trigger.yaml +++ b/tpgtools/overrides/eventarc/beta/trigger.yaml @@ -11,4 +11,7 @@ # 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. - +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/eventarc/channel.yaml b/tpgtools/overrides/eventarc/channel.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/eventarc/channel.yaml +++ b/tpgtools/overrides/eventarc/channel.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/eventarc/google_channel_config.yaml b/tpgtools/overrides/eventarc/google_channel_config.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/eventarc/google_channel_config.yaml +++ b/tpgtools/overrides/eventarc/google_channel_config.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/eventarc/trigger.yaml b/tpgtools/overrides/eventarc/trigger.yaml index 13ed711e62fe..9014b1241575 100644 --- a/tpgtools/overrides/eventarc/trigger.yaml +++ b/tpgtools/overrides/eventarc/trigger.yaml @@ -11,3 +11,7 @@ # 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. +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/firebaserules/beta/release.yaml b/tpgtools/overrides/firebaserules/beta/release.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/firebaserules/beta/release.yaml +++ b/tpgtools/overrides/firebaserules/beta/release.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/firebaserules/beta/ruleset.yaml b/tpgtools/overrides/firebaserules/beta/ruleset.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/firebaserules/beta/ruleset.yaml +++ b/tpgtools/overrides/firebaserules/beta/ruleset.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/firebaserules/release.yaml b/tpgtools/overrides/firebaserules/release.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/firebaserules/release.yaml +++ b/tpgtools/overrides/firebaserules/release.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/firebaserules/ruleset.yaml b/tpgtools/overrides/firebaserules/ruleset.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/firebaserules/ruleset.yaml +++ b/tpgtools/overrides/firebaserules/ruleset.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/gkehub/beta/feature_membership.yaml b/tpgtools/overrides/gkehub/beta/feature_membership.yaml index 2e8b8f32503c..3eac7364e119 100644 --- a/tpgtools/overrides/gkehub/beta/feature_membership.yaml +++ b/tpgtools/overrides/gkehub/beta/feature_membership.yaml @@ -24,4 +24,8 @@ field: mesh.control_plane details: message: >- - Deprecated in favor of the `management` field \ No newline at end of file + Deprecated in favor of the `management` field +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/networkconnectivity/beta/hub.yaml b/tpgtools/overrides/networkconnectivity/beta/hub.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/networkconnectivity/beta/hub.yaml +++ b/tpgtools/overrides/networkconnectivity/beta/hub.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/networkconnectivity/beta/spoke.yaml b/tpgtools/overrides/networkconnectivity/beta/spoke.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/networkconnectivity/beta/spoke.yaml +++ b/tpgtools/overrides/networkconnectivity/beta/spoke.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/networkconnectivity/hub.yaml b/tpgtools/overrides/networkconnectivity/hub.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/networkconnectivity/hub.yaml +++ b/tpgtools/overrides/networkconnectivity/hub.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/networkconnectivity/spoke.yaml b/tpgtools/overrides/networkconnectivity/spoke.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/networkconnectivity/spoke.yaml +++ b/tpgtools/overrides/networkconnectivity/spoke.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/privateca/beta/certificate_template.yaml b/tpgtools/overrides/privateca/beta/certificate_template.yaml index 13ed711e62fe..9014b1241575 100644 --- a/tpgtools/overrides/privateca/beta/certificate_template.yaml +++ b/tpgtools/overrides/privateca/beta/certificate_template.yaml @@ -11,3 +11,7 @@ # 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. +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/privateca/certificate_template.yaml b/tpgtools/overrides/privateca/certificate_template.yaml index 13ed711e62fe..9014b1241575 100644 --- a/tpgtools/overrides/privateca/certificate_template.yaml +++ b/tpgtools/overrides/privateca/certificate_template.yaml @@ -11,3 +11,7 @@ # 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. +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/recaptchaenterprise/beta/key.yaml b/tpgtools/overrides/recaptchaenterprise/beta/key.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/recaptchaenterprise/beta/key.yaml +++ b/tpgtools/overrides/recaptchaenterprise/beta/key.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/recaptchaenterprise/key.yaml b/tpgtools/overrides/recaptchaenterprise/key.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/recaptchaenterprise/key.yaml +++ b/tpgtools/overrides/recaptchaenterprise/key.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject From 8fc61a4f616352c95ea5a4a5a20bfba9f7a6b658 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Wed, 6 Sep 2023 09:50:34 -0700 Subject: [PATCH 21/67] Remove cloud iot service (#8868) --- mmv1/products/cloudiot/Device.yaml | 241 ------------------ mmv1/products/cloudiot/DeviceRegistry.yaml | 172 ------------- mmv1/products/cloudiot/product.yaml | 24 -- .../terraform/constants/cloudiot.go.erb | 241 ------------------ .../decoders/cloudiot_device_registry.go.erb | 31 --- .../encoders/cloudiot_device_registry.go.erb | 43 ---- .../examples/cloudiot_device_basic.tf.erb | 8 - .../examples/cloudiot_device_full.tf.erb | 27 -- .../cloudiot_device_registry_basic.tf.erb | 3 - .../cloudiot_device_registry_full.tf.erb | 46 ---- ...y_single_event_notification_configs.tf.erb | 13 - .../cloudiot_device_registry.go.erb | 32 --- .../cloudiot_device_registry.go.erb | 35 --- ...source_cloudiot_device_registry_id_test.go | 33 --- .../resource_cloudiot_device_update_test.go | 104 -------- .../resource_cloudiot_registry_update_test.go | 110 -------- .../cloudiot/test-fixtures/rsa_cert.pem | 17 -- .../cloudiot/test-fixtures/rsa_public.pem | 14 - 18 files changed, 1194 deletions(-) delete mode 100644 mmv1/products/cloudiot/Device.yaml delete mode 100644 mmv1/products/cloudiot/DeviceRegistry.yaml delete mode 100644 mmv1/products/cloudiot/product.yaml delete mode 100644 mmv1/templates/terraform/constants/cloudiot.go.erb delete mode 100644 mmv1/templates/terraform/decoders/cloudiot_device_registry.go.erb delete mode 100644 mmv1/templates/terraform/encoders/cloudiot_device_registry.go.erb delete mode 100644 mmv1/templates/terraform/examples/cloudiot_device_basic.tf.erb delete mode 100644 mmv1/templates/terraform/examples/cloudiot_device_full.tf.erb delete mode 100644 mmv1/templates/terraform/examples/cloudiot_device_registry_basic.tf.erb delete mode 100644 mmv1/templates/terraform/examples/cloudiot_device_registry_full.tf.erb delete mode 100644 mmv1/templates/terraform/examples/cloudiot_device_registry_single_event_notification_configs.tf.erb delete mode 100644 mmv1/templates/terraform/extra_schema_entry/cloudiot_device_registry.go.erb delete mode 100644 mmv1/templates/terraform/pre_update/cloudiot_device_registry.go.erb delete mode 100644 mmv1/third_party/terraform/services/cloudiot/resource_cloudiot_device_registry_id_test.go delete mode 100644 mmv1/third_party/terraform/services/cloudiot/resource_cloudiot_device_update_test.go delete mode 100644 mmv1/third_party/terraform/services/cloudiot/resource_cloudiot_registry_update_test.go delete mode 100644 mmv1/third_party/terraform/services/cloudiot/test-fixtures/rsa_cert.pem delete mode 100644 mmv1/third_party/terraform/services/cloudiot/test-fixtures/rsa_public.pem diff --git a/mmv1/products/cloudiot/Device.yaml b/mmv1/products/cloudiot/Device.yaml deleted file mode 100644 index 162f73adecec..000000000000 --- a/mmv1/products/cloudiot/Device.yaml +++ /dev/null @@ -1,241 +0,0 @@ -# Copyright 2023 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: 'Device' -base_url: '{{registry}}/devices' -self_link: '{{registry}}/devices/{{name}}' -update_verb: :PATCH -update_mask: true -description: | - A Google Cloud IoT Core device. -references: !ruby/object:Api::Resource::ReferenceLinks - guides: - 'Official Documentation': 'https://cloud.google.com/iot/docs/' - api: 'https://cloud.google.com/iot/docs/reference/cloudiot/rest/' -import_format: ['{{%registry}}/devices/{{name}}'] -examples: - - !ruby/object:Provider::Terraform::Examples - name: 'cloudiot_device_basic' - primary_resource_id: 'test-device' - vars: - cloudiot_device_name: 'cloudiot-device' - cloudiot_device_registry_name: 'cloudiot-device-registry' - test_env_vars: - project: :PROJECT_NAME - region: :REGION - - !ruby/object:Provider::Terraform::Examples - name: 'cloudiot_device_full' - primary_resource_id: 'test-device' - vars: - cloudiot_device_name: 'cloudiot-device' - cloudiot_device_registry_name: 'cloudiot-device-registry' - test_env_vars: - project: :PROJECT_NAME - region: :REGION -parameters: - - !ruby/object:Api::Type::String - name: registry - immutable: true - url_param_only: true - required: true - description: | - The name of the device registry where this device should be created. -properties: - - !ruby/object:Api::Type::String - name: 'name' - immutable: true - required: true - description: | - A unique name for the resource. - api_name: 'id' - - !ruby/object:Api::Type::String - name: 'numId' - output: true - description: | - A server-defined unique numeric ID for the device. - This is a more compact way to identify devices, and it is globally unique. - - !ruby/object:Api::Type::Array - name: 'credentials' - description: | - The credentials used to authenticate this device. - max_size: 3 - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::Time - name: 'expirationTime' - description: | - The time at which this credential becomes invalid. - default_from_api: true - - !ruby/object:Api::Type::NestedObject - name: 'publicKey' - required: true - description: | - A public key used to verify the signature of JSON Web Tokens (JWTs). - properties: - - !ruby/object:Api::Type::Enum - name: 'format' - required: true - description: | - The format of the key. - values: - - :RSA_PEM - - :RSA_X509_PEM - - :ES256_PEM - - :ES256_X509_PEM - - !ruby/object:Api::Type::String - name: 'key' - required: true - description: | - The key data. - - !ruby/object:Api::Type::Time - name: 'lastHeartbeatTime' - output: true - description: | - The last time an MQTT PINGREQ was received. - - !ruby/object:Api::Type::Time - name: 'lastEventTime' - output: true - description: | - The last time a telemetry event was received. - - !ruby/object:Api::Type::Time - name: 'lastStateTime' - output: true - description: | - The last time a state event was received. - - !ruby/object:Api::Type::Time - name: 'lastConfigAckTime' - output: true - description: | - The last time a cloud-to-device config version acknowledgment was received from the device. - - !ruby/object:Api::Type::Time - name: 'lastConfigSendTime' - output: true - description: | - The last time a cloud-to-device config version was sent to the device. - - !ruby/object:Api::Type::Boolean - name: 'blocked' - description: | - If a device is blocked, connections or requests from this device will fail. - - !ruby/object:Api::Type::Time - name: 'lastErrorTime' - output: true - description: | - The time the most recent error occurred, such as a failure to publish to Cloud Pub/Sub. - - !ruby/object:Api::Type::NestedObject - name: 'lastErrorStatus' - output: true - description: | - The error message of the most recent error, such as a failure to publish to Cloud Pub/Sub. - properties: - - !ruby/object:Api::Type::Integer - name: 'number' - description: | - The status code, which should be an enum value of google.rpc.Code. - - !ruby/object:Api::Type::String - name: 'message' - description: | - A developer-facing error message, which should be in English. - - !ruby/object:Api::Type::Array - name: 'details' - description: | - A list of messages that carry the error details. - item_type: Api::Type::KeyValuePairs - - !ruby/object:Api::Type::NestedObject - name: 'config' - output: true - description: | - The most recent device configuration, which is eventually sent from Cloud IoT Core to the device. - properties: - - !ruby/object:Api::Type::String - name: 'version' - output: true - description: | - The version of this update. - - !ruby/object:Api::Type::String - name: 'cloudUpdateTime' - output: true - description: | - The time at which this configuration version was updated in Cloud IoT Core. - - !ruby/object:Api::Type::String - name: 'deviceAckTime' - output: true - description: | - The time at which Cloud IoT Core received the acknowledgment from the device, - indicating that the device has received this configuration version. - - !ruby/object:Api::Type::String - name: 'binaryData' - description: | - The device configuration data. - - !ruby/object:Api::Type::NestedObject - name: 'state' - output: true - description: | - The state most recently received from the device. - properties: - - !ruby/object:Api::Type::Time - name: 'updateTime' - description: | - The time at which this state version was updated in Cloud IoT Core. - - !ruby/object:Api::Type::String - name: 'binaryData' - description: | - The device state data. - - !ruby/object:Api::Type::Enum - name: 'logLevel' - allow_empty_object: true - description: | - The logging verbosity for device activity. - values: - - :NONE - - :ERROR - - :INFO - - :DEBUG - - !ruby/object:Api::Type::KeyValuePairs - name: 'metadata' - description: | - The metadata key-value pairs assigned to the device. - - !ruby/object:Api::Type::NestedObject - name: 'gatewayConfig' - description: | - Gateway-related configuration and state. - update_mask_fields: - - 'gateway_config.gateway_auth_method' - properties: - - !ruby/object:Api::Type::Enum - name: 'gatewayType' - default_value: :NON_GATEWAY - immutable: true - description: | - Indicates whether the device is a gateway. - values: - - :GATEWAY - - :NON_GATEWAY - - !ruby/object:Api::Type::Enum - name: 'gatewayAuthMethod' - description: | - Indicates whether the device is a gateway. - values: - - :ASSOCIATION_ONLY - - :DEVICE_AUTH_TOKEN_ONLY - - :ASSOCIATION_AND_DEVICE_AUTH_TOKEN - - !ruby/object:Api::Type::String - name: 'lastAccessedGatewayId' - output: true - description: | - The ID of the gateway the device accessed most recently. - - !ruby/object:Api::Type::Time - name: 'lastAccessedGatewayTime' - output: true - description: | - The most recent time at which the device accessed the gateway specified in last_accessed_gateway. diff --git a/mmv1/products/cloudiot/DeviceRegistry.yaml b/mmv1/products/cloudiot/DeviceRegistry.yaml deleted file mode 100644 index 044a5bf70436..000000000000 --- a/mmv1/products/cloudiot/DeviceRegistry.yaml +++ /dev/null @@ -1,172 +0,0 @@ -# Copyright 2023 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: 'DeviceRegistry' -base_url: 'projects/{{project}}/locations/{{region}}/registries' -self_link: 'projects/{{project}}/locations/{{region}}/registries/{{name}}' -update_verb: :PATCH -update_mask: true -description: | - A Google Cloud IoT Core device registry. -references: !ruby/object:Api::Resource::ReferenceLinks - guides: - 'Official Documentation': 'https://cloud.google.com/iot/docs/' - api: 'https://cloud.google.com/iot/docs/reference/cloudiot/rest/' -iam_policy: !ruby/object:Api::Resource::IamPolicy - method_name_separator: ':' - fetch_iam_policy_verb: :POST - parent_resource_attribute: 'name' - import_format: - [ - 'projects/{{project}}/locations/{{location}}/registries/{{name}}', - '{{name}}', - ] -legacy_name: 'google_cloudiot_registry' -import_format: ['{{project}}/locations/{{region}}/registries/{{name}}'] -id_format: 'projects/{{project}}/locations/{{region}}/registries/{{name}}' -custom_code: !ruby/object:Provider::Terraform::CustomCode - constants: templates/terraform/constants/cloudiot.go.erb - decoder: templates/terraform/decoders/cloudiot_device_registry.go.erb - encoder: templates/terraform/encoders/cloudiot_device_registry.go.erb - extra_schema_entry: templates/terraform/extra_schema_entry/cloudiot_device_registry.go.erb - pre_update: templates/terraform/pre_update/cloudiot_device_registry.go.erb -docs: !ruby/object:Provider::Terraform::Docs - optional_properties: | - * `state_notification_config` - A PubSub topic to publish device state updates. - The structure is documented below. - - * `mqtt_config` - Activate or deactivate MQTT. - The structure is documented below. - - * `http_config` - Activate or deactivate HTTP. - The structure is documented below. - - * `credentials` - List of public key certificates to authenticate devices. - The structure is documented below. - - The `state_notification_config` block supports: - - * `pubsub_topic_name` - PubSub topic name to publish device state updates. - - The `mqtt_config` block supports: - - * `mqtt_enabled_state` - The field allows `MQTT_ENABLED` or `MQTT_DISABLED`. - - The `http_config` block supports: - - * `http_enabled_state` - The field allows `HTTP_ENABLED` or `HTTP_DISABLED`. - - The `credentials` block supports: - - * `public_key_certificate` - A public key certificate format and data. - - The `public_key_certificate` block supports: - - * `format` - The field allows only `X509_CERTIFICATE_PEM`. - - * `certificate` - The certificate data. -examples: - - !ruby/object:Provider::Terraform::Examples - name: 'cloudiot_device_registry_basic' - primary_resource_id: 'test-registry' - primary_resource_name: "fmt.Sprintf(\"tf-test-cloudiot-registry%s\", - context[\"\ - random_suffix\"])" - vars: - cloudiot_registry_name: 'cloudiot-registry' - test_env_vars: - project: :PROJECT_NAME - region: :REGION - - !ruby/object:Provider::Terraform::Examples - name: 'cloudiot_device_registry_single_event_notification_configs' - primary_resource_id: 'test-registry' - vars: - cloudiot_registry_name: 'cloudiot-registry' - cloudiot_device_telemetry_topic_name: 'default-telemetry' - test_env_vars: - project: :PROJECT_NAME - region: :REGION - - !ruby/object:Provider::Terraform::Examples - name: 'cloudiot_device_registry_full' - primary_resource_id: 'test-registry' - vars: - cloudiot_registry_name: 'cloudiot-registry' - cloudiot_device_status_topic_name: 'default-devicestatus' - cloudiot_device_telemetry_topic_name: 'default-telemetry' - cloudiot_additional_device_telemetry_topic_name: 'additional-telemetry' - cloudiot_subfolder_matches_additional_device_telemetry_topic: 'test/path' - test_env_vars: - project: :PROJECT_NAME - region: :REGION -parameters: - - !ruby/object:Api::Type::String - name: region - immutable: true - url_param_only: true - required: false - description: | - The region in which the created registry should reside. - If it is not provided, the provider region is used. - ignore_read: true - default_from_api: true -properties: - - !ruby/object:Api::Type::String - name: 'name' - immutable: true - required: true - description: | - A unique name for the resource, required by device registry. - api_name: 'id' - validation: !ruby/object:Provider::Terraform::Validation - function: 'ValidateCloudIotDeviceRegistryID' - - !ruby/object:Api::Type::Array - name: 'eventNotificationConfigs' - description: | - List of configurations for event notifications, such as PubSub topics - to publish device events to. - max_size: 10 - default_from_api: true - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::String - name: 'subfolderMatches' - description: | - If the subfolder name matches this string exactly, this - configuration will be used. The string must not include the - leading '/' character. If empty, all strings are matched. Empty - value can only be used for the last `event_notification_configs` - item. - validation: !ruby/object:Provider::Terraform::Validation - function: 'validateCloudIotDeviceRegistrySubfolderMatch' - - !ruby/object:Api::Type::String - name: 'pubsubTopicName' - required: true - description: | - PubSub topic name to publish device events. - diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' - - !ruby/object:Api::Type::Enum - name: 'logLevel' - default_value: :NONE - description: | - The default logging verbosity for activity from devices in this - registry. Specifies which events should be written to logs. For - example, if the LogLevel is ERROR, only events that terminate in - errors will be logged. LogLevel is inclusive; enabling INFO logging - will also enable ERROR logging. - values: - - :NONE - - :ERROR - - :INFO - - :DEBUG - diff_suppress_func: 'tpgresource.EmptyOrDefaultStringSuppress("NONE")' diff --git a/mmv1/products/cloudiot/product.yaml b/mmv1/products/cloudiot/product.yaml deleted file mode 100644 index 2539129f14da..000000000000 --- a/mmv1/products/cloudiot/product.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright 2020 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: CloudIot -display_name: Cloud IoT Core -legacy_name: 'cloudiot' -versions: - - !ruby/object:Api::Product::Version - name: ga - base_url: https://cloudiot.googleapis.com/v1/ -scopes: - - https://www.googleapis.com/auth/cloudiot - - https://www.googleapis.com/auth/cloud-platform diff --git a/mmv1/templates/terraform/constants/cloudiot.go.erb b/mmv1/templates/terraform/constants/cloudiot.go.erb deleted file mode 100644 index 03905061d6ef..000000000000 --- a/mmv1/templates/terraform/constants/cloudiot.go.erb +++ /dev/null @@ -1,241 +0,0 @@ -func expandCloudIotDeviceRegistryHTTPConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - original := v.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedHTTPEnabledState, err := expandCloudIotDeviceRegistryHTTPEnabledState(original["http_enabled_state"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedHTTPEnabledState); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["httpEnabledState"] = transformedHTTPEnabledState - } - - return transformed, nil -} - -func expandCloudIotDeviceRegistryHTTPEnabledState(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - return v, nil -} - -func expandCloudIotDeviceRegistryMqttConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - original := v.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedMqttEnabledState, err := expandCloudIotDeviceRegistryMqttEnabledState(original["mqtt_enabled_state"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedMqttEnabledState); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["mqttEnabledState"] = transformedMqttEnabledState - } - - return transformed, nil -} - -func expandCloudIotDeviceRegistryMqttEnabledState(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - return v, nil -} - -func expandCloudIotDeviceRegistryStateNotificationConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - original := v.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedPubsubTopicName, err := expandCloudIotDeviceRegistryStateNotificationConfigPubsubTopicName(original["pubsub_topic_name"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedPubsubTopicName); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["pubsubTopicName"] = transformedPubsubTopicName - } - - return transformed, nil -} - -func expandCloudIotDeviceRegistryStateNotificationConfigPubsubTopicName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - return v, nil -} - -func expandCloudIotDeviceRegistryCredentials(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - l := v.([]interface{}) - req := make([]interface{}, 0, len(l)) - - for _, raw := range l { - if raw == nil { - continue - } - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedPublicKeyCertificate, err := expandCloudIotDeviceRegistryCredentialsPublicKeyCertificate(original["public_key_certificate"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedPublicKeyCertificate); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["publicKeyCertificate"] = transformedPublicKeyCertificate - } - - req = append(req, transformed) - } - - return req, nil -} - -func expandCloudIotDeviceRegistryCredentialsPublicKeyCertificate(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - original := v.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedFormat, err := expandCloudIotDeviceRegistryPublicKeyCertificateFormat(original["format"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedFormat); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["format"] = transformedFormat - } - - transformedCertificate, err := expandCloudIotDeviceRegistryPublicKeyCertificateCertificate(original["certificate"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedCertificate); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["certificate"] = transformedCertificate - } - - return transformed, nil -} - -func expandCloudIotDeviceRegistryPublicKeyCertificateFormat(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - return v, nil -} - -func expandCloudIotDeviceRegistryPublicKeyCertificateCertificate(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - return v, nil -} - -func flattenCloudIotDeviceRegistryCredentials(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - log.Printf("[DEBUG] Flattening device resitry credentials: %q", d.Id()) - if v == nil { - log.Printf("[DEBUG] The credentials array is nil: %q", d.Id()) - return v - } - l := v.([]interface{}) - transformed := make([]interface{}, 0, len(l)) - for _, raw := range l { - original := raw.(map[string]interface{}) - log.Printf("[DEBUG] Original credential: %+v", original) - if len(original) < 1 { - log.Printf("[DEBUG] Excluding empty credential that the API returned. %q", d.Id()) - continue - } - log.Printf("[DEBUG] Credentials array before appending a new credential: %+v", transformed) - transformed = append(transformed, map[string]interface{}{ - "public_key_certificate": flattenCloudIotDeviceRegistryCredentialsPublicKeyCertificate(original["publicKeyCertificate"], d, config), - }) - log.Printf("[DEBUG] Credentials array after appending a new credential: %+v", transformed) - } - return transformed -} - -func flattenCloudIotDeviceRegistryCredentialsPublicKeyCertificate(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - log.Printf("[DEBUG] Flattening device resitry credentials public key certificate: %q", d.Id()) - if v == nil { - log.Printf("[DEBUG] The public key certificate is nil: %q", d.Id()) - return v - } - - original := v.(map[string]interface{}) - log.Printf("[DEBUG] Original public key certificate: %+v", original) - transformed := make(map[string]interface{}) - - transformedPublicKeyCertificateFormat := flattenCloudIotDeviceRegistryPublicKeyCertificateFormat(original["format"], d, config) - transformed["format"] = transformedPublicKeyCertificateFormat - - transformedPublicKeyCertificateCertificate := flattenCloudIotDeviceRegistryPublicKeyCertificateCertificate(original["certificate"], d, config) - transformed["certificate"] = transformedPublicKeyCertificateCertificate - - log.Printf("[DEBUG] Transformed public key certificate: %+v", transformed) - - return transformed -} - -func flattenCloudIotDeviceRegistryPublicKeyCertificateFormat(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return v -} - -func flattenCloudIotDeviceRegistryPublicKeyCertificateCertificate(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return v -} - -func flattenCloudIotDeviceRegistryHTTPConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - if v == nil { - return v - } - - original := v.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedHTTPEnabledState := flattenCloudIotDeviceRegistryHTTPConfigHTTPEnabledState(original["httpEnabledState"], d, config) - transformed["http_enabled_state"] = transformedHTTPEnabledState - - return transformed -} - -func flattenCloudIotDeviceRegistryHTTPConfigHTTPEnabledState(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return v -} - -func flattenCloudIotDeviceRegistryMqttConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - if v == nil { - return v - } - - original := v.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedMqttEnabledState := flattenCloudIotDeviceRegistryMqttConfigMqttEnabledState(original["mqttEnabledState"], d, config) - transformed["mqtt_enabled_state"] = transformedMqttEnabledState - - return transformed -} - -func flattenCloudIotDeviceRegistryMqttConfigMqttEnabledState(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return v -} - -func flattenCloudIotDeviceRegistryStateNotificationConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - log.Printf("[DEBUG] Flattening state notification config: %+v", v) - if v == nil { - return v - } - - original := v.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedPubsubTopicName := flattenCloudIotDeviceRegistryStateNotificationConfigPubsubTopicName(original["pubsubTopicName"], d, config) - if val := reflect.ValueOf(transformedPubsubTopicName); val.IsValid() && !tpgresource.IsEmptyValue(val) { - log.Printf("[DEBUG] pubsub topic name is not null: %v", d.Get("pubsub_topic_name")) - transformed["pubsub_topic_name"] = transformedPubsubTopicName - } - - - return transformed -} - -func flattenCloudIotDeviceRegistryStateNotificationConfigPubsubTopicName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return v -} - -func ValidateCloudIotDeviceRegistryID(v interface{}, k string) (warnings []string, errors []error) { - value := v.(string) - if strings.HasPrefix(value, "goog") { - errors = append(errors, fmt.Errorf( - "%q (%q) can not start with \"goog\"", k, value)) - } - if !regexp.MustCompile(verify.CloudIoTIdRegex).MatchString(value) { - errors = append(errors, fmt.Errorf( - "%q (%q) doesn't match regexp %q", k, value, verify.CloudIoTIdRegex)) - } - return -} - -func validateCloudIotDeviceRegistrySubfolderMatch(v interface{}, k string) (warnings []string, errors []error) { - value := v.(string) - if strings.HasPrefix(value, "/") { - errors = append(errors, fmt.Errorf( - "%q (%q) can not start with '/'", k, value)) - } - return -} diff --git a/mmv1/templates/terraform/decoders/cloudiot_device_registry.go.erb b/mmv1/templates/terraform/decoders/cloudiot_device_registry.go.erb deleted file mode 100644 index b5652175ebee..000000000000 --- a/mmv1/templates/terraform/decoders/cloudiot_device_registry.go.erb +++ /dev/null @@ -1,31 +0,0 @@ -config := meta.(*transport_tpg.Config) - -log.Printf("[DEBUG] Decoding state notification config: %q", d.Id()) -log.Printf("[DEBUG] State notification config before decoding: %v", d.Get("state_notification_config")) -if err := d.Set("state_notification_config", flattenCloudIotDeviceRegistryStateNotificationConfig(res["stateNotificationConfig"], d, config)); err != nil { - return nil, fmt.Errorf("Error reading DeviceRegistry: %s", err) -} -log.Printf("[DEBUG] State notification config after decoding: %v", d.Get("state_notification_config")) - -log.Printf("[DEBUG] Decoding HTTP config: %q", d.Id()) -log.Printf("[DEBUG] HTTP config before decoding: %v", d.Get("http_config")) -if err := d.Set("http_config", flattenCloudIotDeviceRegistryHTTPConfig(res["httpConfig"], d, config)); err != nil { - return nil, fmt.Errorf("Error reading DeviceRegistry: %s", err) -} -log.Printf("[DEBUG] HTTP config after decoding: %v", d.Get("http_config")) - -log.Printf("[DEBUG] Decoding MQTT config: %q", d.Id()) -log.Printf("[DEBUG] MQTT config before decoding: %v", d.Get("mqtt_config")) -if err := d.Set("mqtt_config", flattenCloudIotDeviceRegistryMqttConfig(res["mqttConfig"], d, config)); err != nil { - return nil, fmt.Errorf("Error reading DeviceRegistry: %s", err) -} -log.Printf("[DEBUG] MQTT config after decoding: %v", d.Get("mqtt_config")) - -log.Printf("[DEBUG] Decoding credentials: %q", d.Id()) -log.Printf("[DEBUG] credentials before decoding: %v", d.Get("credentials")) -if err := d.Set("credentials", flattenCloudIotDeviceRegistryCredentials(res["credentials"], d, config)); err != nil { - return nil, fmt.Errorf("Error reading DeviceRegistry: %s", err) -} -log.Printf("[DEBUG] credentials after decoding: %v", d.Get("credentials")) - -return res, nil diff --git a/mmv1/templates/terraform/encoders/cloudiot_device_registry.go.erb b/mmv1/templates/terraform/encoders/cloudiot_device_registry.go.erb deleted file mode 100644 index 37794ff71630..000000000000 --- a/mmv1/templates/terraform/encoders/cloudiot_device_registry.go.erb +++ /dev/null @@ -1,43 +0,0 @@ -config := meta.(*transport_tpg.Config) - -log.Printf("[DEBUG] Resource data before encoding extra schema entries %q: %#v", d.Id(), obj) - -log.Printf("[DEBUG] Encoding state notification config: %q", d.Id()) -stateNotificationConfigProp, err := expandCloudIotDeviceRegistryStateNotificationConfig(d.Get("state_notification_config"), d, config) -if err != nil { - return nil, err -} else if v, ok := d.GetOkExists("state_notification_config"); !tpgresource.IsEmptyValue(reflect.ValueOf(stateNotificationConfigProp)) && (ok || !reflect.DeepEqual(v, stateNotificationConfigProp)) { - log.Printf("[DEBUG] Encoding %q. Setting stateNotificationConfig: %#v", d.Id(), stateNotificationConfigProp) - obj["stateNotificationConfig"] = stateNotificationConfigProp -} - -log.Printf("[DEBUG] Encoding HTTP config: %q", d.Id()) -httpConfigProp, err := expandCloudIotDeviceRegistryHTTPConfig(d.Get("http_config"), d, config) -if err != nil { - return nil, err -} else if v, ok := d.GetOkExists("http_config"); !tpgresource.IsEmptyValue(reflect.ValueOf(httpConfigProp)) && (ok || !reflect.DeepEqual(v, httpConfigProp)) { - log.Printf("[DEBUG] Encoding %q. Setting httpConfig: %#v", d.Id(), httpConfigProp) - obj["httpConfig"] = httpConfigProp -} - -log.Printf("[DEBUG] Encoding MQTT config: %q", d.Id()) -mqttConfigProp, err := expandCloudIotDeviceRegistryMqttConfig(d.Get("mqtt_config"), d, config) -if err != nil { - return nil, err -} else if v, ok := d.GetOkExists("mqtt_config"); !tpgresource.IsEmptyValue(reflect.ValueOf(mqttConfigProp)) && (ok || !reflect.DeepEqual(v, mqttConfigProp)) { - log.Printf("[DEBUG] Encoding %q. Setting mqttConfig: %#v", d.Id(), mqttConfigProp) - obj["mqttConfig"] = mqttConfigProp -} - -log.Printf("[DEBUG] Encoding credentials: %q", d.Id()) -credentialsProp, err := expandCloudIotDeviceRegistryCredentials(d.Get("credentials"), d, config) -if err != nil { - return nil, err -} else if v, ok := d.GetOkExists("credentials"); !tpgresource.IsEmptyValue(reflect.ValueOf(credentialsProp)) && (ok || !reflect.DeepEqual(v, credentialsProp)) { - log.Printf("[DEBUG] Encoding %q. Setting credentials: %#v", d.Id(), credentialsProp) - obj["credentials"] = credentialsProp -} - -log.Printf("[DEBUG] Resource data after encoding extra schema entries %q: %#v", d.Id(), obj) - -return obj, nil diff --git a/mmv1/templates/terraform/examples/cloudiot_device_basic.tf.erb b/mmv1/templates/terraform/examples/cloudiot_device_basic.tf.erb deleted file mode 100644 index dbfd02b17e4d..000000000000 --- a/mmv1/templates/terraform/examples/cloudiot_device_basic.tf.erb +++ /dev/null @@ -1,8 +0,0 @@ -resource "google_cloudiot_registry" "registry" { - name = "<%= ctx[:vars]['cloudiot_device_registry_name'] %>" -} - -resource "google_cloudiot_device" "<%= ctx[:primary_resource_id] %>" { - name = "<%= ctx[:vars]['cloudiot_device_name'] %>" - registry = google_cloudiot_registry.registry.id -} diff --git a/mmv1/templates/terraform/examples/cloudiot_device_full.tf.erb b/mmv1/templates/terraform/examples/cloudiot_device_full.tf.erb deleted file mode 100644 index 0c3457d4029c..000000000000 --- a/mmv1/templates/terraform/examples/cloudiot_device_full.tf.erb +++ /dev/null @@ -1,27 +0,0 @@ -resource "google_cloudiot_registry" "registry" { - name = "<%= ctx[:vars]['cloudiot_device_registry_name'] %>" -} - -resource "google_cloudiot_device" "<%= ctx[:primary_resource_id] %>" { - name = "<%= ctx[:vars]['cloudiot_device_name'] %>" - registry = google_cloudiot_registry.registry.id - - credentials { - public_key { - format = "RSA_PEM" - key = file("test-fixtures/rsa_public.pem") - } - } - - blocked = false - - log_level = "INFO" - - metadata = { - test_key_1 = "test_value_1" - } - - gateway_config { - gateway_type = "NON_GATEWAY" - } -} diff --git a/mmv1/templates/terraform/examples/cloudiot_device_registry_basic.tf.erb b/mmv1/templates/terraform/examples/cloudiot_device_registry_basic.tf.erb deleted file mode 100644 index 67bf5e108304..000000000000 --- a/mmv1/templates/terraform/examples/cloudiot_device_registry_basic.tf.erb +++ /dev/null @@ -1,3 +0,0 @@ -resource "google_cloudiot_registry" "<%= ctx[:primary_resource_id] %>" { - name = "<%= ctx[:vars]['cloudiot_registry_name'] %>" -} diff --git a/mmv1/templates/terraform/examples/cloudiot_device_registry_full.tf.erb b/mmv1/templates/terraform/examples/cloudiot_device_registry_full.tf.erb deleted file mode 100644 index f5c11d9abdcc..000000000000 --- a/mmv1/templates/terraform/examples/cloudiot_device_registry_full.tf.erb +++ /dev/null @@ -1,46 +0,0 @@ -resource "google_pubsub_topic" "default-devicestatus" { - name = "<%= ctx[:vars]['cloudiot_device_status_topic_name'] %>" -} - -resource "google_pubsub_topic" "default-telemetry" { - name = "<%= ctx[:vars]['cloudiot_device_telemetry_topic_name'] %>" -} - -resource "google_pubsub_topic" "additional-telemetry" { - name = "<%= ctx[:vars]['cloudiot_additional_device_telemetry_topic_name'] %>" -} - -resource "google_cloudiot_registry" "<%= ctx[:primary_resource_id] %>" { - name = "<%= ctx[:vars]['cloudiot_registry_name'] %>" - - event_notification_configs { - pubsub_topic_name = google_pubsub_topic.additional-telemetry.id - subfolder_matches = "<%= ctx[:vars]['cloudiot_subfolder_matches_additional_device_telemetry_topic'] %>" - } - - event_notification_configs { - pubsub_topic_name = google_pubsub_topic.default-telemetry.id - subfolder_matches = "" - } - - state_notification_config = { - pubsub_topic_name = google_pubsub_topic.default-devicestatus.id - } - - mqtt_config = { - mqtt_enabled_state = "MQTT_ENABLED" - } - - http_config = { - http_enabled_state = "HTTP_ENABLED" - } - - log_level = "INFO" - - credentials { - public_key_certificate = { - format = "X509_CERTIFICATE_PEM" - certificate = file("test-fixtures/rsa_cert.pem") - } - } -} diff --git a/mmv1/templates/terraform/examples/cloudiot_device_registry_single_event_notification_configs.tf.erb b/mmv1/templates/terraform/examples/cloudiot_device_registry_single_event_notification_configs.tf.erb deleted file mode 100644 index 45139229a27c..000000000000 --- a/mmv1/templates/terraform/examples/cloudiot_device_registry_single_event_notification_configs.tf.erb +++ /dev/null @@ -1,13 +0,0 @@ -resource "google_pubsub_topic" "default-telemetry" { - name = "<%= ctx[:vars]['cloudiot_device_telemetry_topic_name'] %>" -} - -resource "google_cloudiot_registry" "<%= ctx[:primary_resource_id] %>" { - name = "<%= ctx[:vars]['cloudiot_registry_name'] %>" - - event_notification_configs { - pubsub_topic_name = google_pubsub_topic.default-telemetry.id - subfolder_matches = "" - } - -} diff --git a/mmv1/templates/terraform/extra_schema_entry/cloudiot_device_registry.go.erb b/mmv1/templates/terraform/extra_schema_entry/cloudiot_device_registry.go.erb deleted file mode 100644 index 7a1a8eec8f7a..000000000000 --- a/mmv1/templates/terraform/extra_schema_entry/cloudiot_device_registry.go.erb +++ /dev/null @@ -1,32 +0,0 @@ -"state_notification_config": { - Type: schema.TypeMap, - Description: `A PubSub topic to publish device state updates.`, - Optional: true, -}, -"mqtt_config": { - Type: schema.TypeMap, - Description: `Activate or deactivate MQTT.`, - Computed: true, - Optional: true, -}, -"http_config": { - Type: schema.TypeMap, - Description: `Activate or deactivate HTTP.`, - Computed: true, - Optional: true, -}, -"credentials": { - Type: schema.TypeList, - Description: `List of public key certificates to authenticate devices.`, - Optional: true, - MaxItems: 10, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "public_key_certificate": { - Type: schema.TypeMap, - Description: `A public key certificate format and data.`, - Required: true, - }, - }, - }, -}, diff --git a/mmv1/templates/terraform/pre_update/cloudiot_device_registry.go.erb b/mmv1/templates/terraform/pre_update/cloudiot_device_registry.go.erb deleted file mode 100644 index 226c0efca146..000000000000 --- a/mmv1/templates/terraform/pre_update/cloudiot_device_registry.go.erb +++ /dev/null @@ -1,35 +0,0 @@ -log.Printf("[DEBUG] updateMask before adding extra schema entries %q: %v", d.Id(), updateMask) - -log.Printf("[DEBUG] Pre-update on state notification config: %q", d.Id()) -if d.HasChange("state_notification_config") { - log.Printf("[DEBUG] %q stateNotificationConfig.pubsubTopicName has a change. Adding it to the update mask", d.Id()) - updateMask = append(updateMask, "stateNotificationConfig.pubsubTopicName") -} - -log.Printf("[DEBUG] Pre-update on MQTT config: %q", d.Id()) -if d.HasChange("mqtt_config") { - log.Printf("[DEBUG] %q mqttConfig.mqttEnabledState has a change. Adding it to the update mask", d.Id()) - updateMask = append(updateMask, "mqttConfig.mqttEnabledState") -} - -log.Printf("[DEBUG] Pre-update on HTTP config: %q", d.Id()) -if d.HasChange("http_config") { - log.Printf("[DEBUG] %q httpConfig.httpEnabledState has a change. Adding it to the update mask", d.Id()) - updateMask = append(updateMask, "httpConfig.httpEnabledState") -} - -log.Printf("[DEBUG] Pre-update on credentials: %q", d.Id()) -if d.HasChange("credentials") { - log.Printf("[DEBUG] %q credentials has a change. Adding it to the update mask", d.Id()) - updateMask = append(updateMask, "credentials") -} - -log.Printf("[DEBUG] updateMask after adding extra schema entries %q: %v", d.Id(), updateMask) - -// Refreshing updateMask after adding extra schema entries -url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")}) -if err != nil { - return err -} - -log.Printf("[DEBUG] Update URL %q: %v", d.Id(), url) diff --git a/mmv1/third_party/terraform/services/cloudiot/resource_cloudiot_device_registry_id_test.go b/mmv1/third_party/terraform/services/cloudiot/resource_cloudiot_device_registry_id_test.go deleted file mode 100644 index 41d926e421e0..000000000000 --- a/mmv1/third_party/terraform/services/cloudiot/resource_cloudiot_device_registry_id_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package cloudiot_test - -import ( - "strings" - "testing" - - "github.com/hashicorp/terraform-provider-google/google/services/cloudiot" - "github.com/hashicorp/terraform-provider-google/google/verify" -) - -func TestValidateCloudIoTDeviceRegistryId(t *testing.T) { - x := []verify.StringValidationTestCase{ - // No errors - {TestName: "basic", Value: "foobar"}, - {TestName: "with numbers", Value: "foobar123"}, - {TestName: "short", Value: "foo"}, - {TestName: "long", Value: "foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoo"}, - {TestName: "has a hyphen", Value: "foo-bar"}, - - // With errors - {TestName: "empty", Value: "", ExpectError: true}, - {TestName: "starts with a goog", Value: "googfoobar", ExpectError: true}, - {TestName: "starts with a number", Value: "1foobar", ExpectError: true}, - {TestName: "has an slash", Value: "foo/bar", ExpectError: true}, - {TestName: "has an backslash", Value: "foo\bar", ExpectError: true}, - {TestName: "too long", Value: strings.Repeat("f", 260), ExpectError: true}, - } - - es := verify.TestStringValidationCases(x, cloudiot.ValidateCloudIotDeviceRegistryID) - if len(es) > 0 { - t.Errorf("Failed to validate CloudIoT ID names: %v", es) - } -} diff --git a/mmv1/third_party/terraform/services/cloudiot/resource_cloudiot_device_update_test.go b/mmv1/third_party/terraform/services/cloudiot/resource_cloudiot_device_update_test.go deleted file mode 100644 index 799b4a58c372..000000000000 --- a/mmv1/third_party/terraform/services/cloudiot/resource_cloudiot_device_update_test.go +++ /dev/null @@ -1,104 +0,0 @@ -package cloudiot_test - -import ( - "fmt" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" - "github.com/hashicorp/terraform-provider-google/google/acctest" -) - -func TestAccCloudIoTDevice_update(t *testing.T) { - t.Parallel() - - registryName := fmt.Sprintf("psregistry-test-%s", acctest.RandString(t, 10)) - deviceName := fmt.Sprintf("psdevice-test-%s", acctest.RandString(t, 10)) - resourceName := fmt.Sprintf("google_cloudiot_device.%s", deviceName) - - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckCloudIotDeviceDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccCloudIoTDeviceBasic(deviceName, registryName), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - { - Config: testAccCloudIoTDeviceExtended(deviceName, registryName), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - { - Config: testAccCloudIoTDeviceBasic(deviceName, registryName), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func testAccCloudIoTDeviceBasic(deviceName string, registryName string) string { - return fmt.Sprintf(` - -resource "google_cloudiot_registry" "%s" { - name = "%s" -} - -resource "google_cloudiot_device" "%s" { - name = "%s" - registry = google_cloudiot_registry.%s.id - - gateway_config { - gateway_auth_method = "DEVICE_AUTH_TOKEN_ONLY" - gateway_type = "GATEWAY" - } -} - - -`, registryName, registryName, deviceName, deviceName, registryName) -} - -func testAccCloudIoTDeviceExtended(deviceName string, registryName string) string { - return fmt.Sprintf(` - -resource "google_cloudiot_registry" "%s" { - name = "%s" -} - -resource "google_cloudiot_device" "%s" { - name = "%s" - registry = google_cloudiot_registry.%s.id - - credentials { - public_key { - format = "RSA_PEM" - key = file("test-fixtures/rsa_public.pem") - } - } - - blocked = false - - log_level = "INFO" - - metadata = { - test_key_1 = "test_value_1" - } - - gateway_config { - gateway_auth_method = "ASSOCIATION_AND_DEVICE_AUTH_TOKEN" - gateway_type = "GATEWAY" - } -} -`, registryName, registryName, deviceName, deviceName, registryName) -} diff --git a/mmv1/third_party/terraform/services/cloudiot/resource_cloudiot_registry_update_test.go b/mmv1/third_party/terraform/services/cloudiot/resource_cloudiot_registry_update_test.go deleted file mode 100644 index 9493f26bd4ca..000000000000 --- a/mmv1/third_party/terraform/services/cloudiot/resource_cloudiot_registry_update_test.go +++ /dev/null @@ -1,110 +0,0 @@ -package cloudiot_test - -import ( - "fmt" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" - "github.com/hashicorp/terraform-provider-google/google/acctest" -) - -func TestAccCloudIoTRegistry_update(t *testing.T) { - t.Parallel() - - registryName := fmt.Sprintf("psregistry-test-%s", acctest.RandString(t, 10)) - resourceName := fmt.Sprintf("google_cloudiot_registry.%s", registryName) - deviceStatus := fmt.Sprintf("psregistry-test-devicestatus-%s", acctest.RandString(t, 10)) - defaultTelemetry := fmt.Sprintf("psregistry-test-telemetry-%s", acctest.RandString(t, 10)) - additionalTelemetry := fmt.Sprintf("psregistry-additional-test-telemetry-%s", acctest.RandString(t, 10)) - - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckCloudIotDeviceRegistryDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccCloudIoTRegistryBasic(registryName), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - { - Config: testAccCloudIoTRegistryExtended(registryName, deviceStatus, defaultTelemetry, additionalTelemetry), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - { - Config: testAccCloudIoTRegistryBasic(registryName), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func testAccCloudIoTRegistryBasic(registryName string) string { - return fmt.Sprintf(` - -resource "google_cloudiot_registry" "%s" { - name = "%s" -} -`, registryName, registryName) -} - -func testAccCloudIoTRegistryExtended(registryName string, deviceStatus string, defaultTelemetry string, additionalTelemetry string) string { - return fmt.Sprintf(` - -resource "google_pubsub_topic" "default-devicestatus" { - name = "psregistry-test-devicestatus-%s" -} - -resource "google_pubsub_topic" "default-telemetry" { - name = "psregistry-test-telemetry-%s" -} - -resource "google_pubsub_topic" "additional-telemetry" { - name = "psregistry-additional-test-telemetry-%s" -} - -resource "google_cloudiot_registry" "%s" { - name = "%s" - - event_notification_configs { - pubsub_topic_name = google_pubsub_topic.additional-telemetry.id - subfolder_matches = "test/directory" - } - - event_notification_configs { - pubsub_topic_name = google_pubsub_topic.default-telemetry.id - subfolder_matches = "" - } - - state_notification_config = { - pubsub_topic_name = google_pubsub_topic.default-devicestatus.id - } - - mqtt_config = { - mqtt_enabled_state = "MQTT_DISABLED" - } - - http_config = { - http_enabled_state = "HTTP_DISABLED" - } - - credentials { - public_key_certificate = { - format = "X509_CERTIFICATE_PEM" - certificate = file("test-fixtures/rsa_cert.pem") - } - } -} -`, deviceStatus, defaultTelemetry, additionalTelemetry, registryName, registryName) -} diff --git a/mmv1/third_party/terraform/services/cloudiot/test-fixtures/rsa_cert.pem b/mmv1/third_party/terraform/services/cloudiot/test-fixtures/rsa_cert.pem deleted file mode 100644 index d8a834633c91..000000000000 --- a/mmv1/third_party/terraform/services/cloudiot/test-fixtures/rsa_cert.pem +++ /dev/null @@ -1,17 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICoDCCAYgCCQDzZ6R7RYs0sTANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZ1 -bnVzZWQwIBcNMTgwMTIwMTA0OTIzWhgPNDc1NTEyMTgxMDQ5MjNaMBExDzANBgNV -BAMMBnVudXNlZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMXX/5jI -tvxpst1mFVKVXfyu5S5AOQF+i/ny6Ef+h8py8y42XfsE2AAPSTE3JCIgWemw7NQ/ -xnTQ3f6b7/6+ZsdM4/hoiedwYV8X3LVPB9NRnKe82OHUhzo1psVMJVvHtE3GsD/V -i40ki/L4Xs64E2GJqQfrkgeNfIyCeKev64fR5aMazqOw1cNrVe34mY3L1hgXpn7e -SnO0oqnV86pTh+jTT8EKgo9AI7/QuJbPWpJhnj1/Fm8i3DdCdpQqloX9Fc4f6whA -XlZ2tkma0PsBraxMua5GPglJ7m3RabQIoyAW+4hEYAcu7U0wIhCK+C8WTNgEYZaK -zvp8vK6vOgBIjE0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAvVXus7dLikEAM6+I -6xeN7aHEMJRR0h2rigLiYjfl8R9zG/zxUPUunWPAYaKvWOFviXcX/KqpjDqIIeWx -Gm0yNfyalHq476nRCf/0t9AH5X4Qy0KJSW5KfhQLG9X2z/UiJxwHKCwaWZtEEzPu -mGqvwhNXUOL/GuAZCJWPdWrUGM4kHHz3kw5v3UPNS2xA7yMtN9N1b8/pkTQ77XNk -DA4wngA5zc7Ae72SJDrY8XXqLfL4Nagkrn6AOhGK3/Ewvca6hkThMcHI0WF2AqFo -mo3iGUJzR5lOUx+4RiEBC5NNEZsE9GMNEiu8kYvCAS0FMKYmxFPGx1U/kiOeeuIw -W3sOEA== ------END CERTIFICATE----- diff --git a/mmv1/third_party/terraform/services/cloudiot/test-fixtures/rsa_public.pem b/mmv1/third_party/terraform/services/cloudiot/test-fixtures/rsa_public.pem deleted file mode 100644 index 2b2acadf6760..000000000000 --- a/mmv1/third_party/terraform/services/cloudiot/test-fixtures/rsa_public.pem +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAv6weC1aT16l2qS6qdYcy -7BOjzP7TwT9zUAiFhWpL256GRqC8yQRdqMsi68Q//762IUyu/qaHbEgQ8WRmQdVV -GDlxkBfrA/iXB2dgujq8jh0HWIV2ev3TerV3aUwvYUlrowhq027SX9U1hbufdGCM -uKsHiF05ErgNvEuR8XAkeJ/YV2DV2+sRq+Wg9y4RwUYbdchdFty1d5SX/s0Yqswg -yOG9VoCdR7baF22ughVR44aRm+83mgtqAZ4M+Rpe7JGRsUGY/pR391Toi0s8En15 -JGiAhqX2W0Uo/FZZry3yuqRfdHYENB+ADuyTMTrUaKZv7eua0lTBz5oom3jSF3gv -I7SQoLdK/jhEVOOq41IjB8D60Sgd69bD7yTI516yvZ/s3AyKzW6f6KnjdbCcZKKT -0GAePNLNhDYfSlA9bwJ8HQS2FenSpSTArKvGiVrsinJuNjbQdPuQHcpWf9x1m3GR -TMvF+TNYM/lp7IL2VMbJRfWPy1iWxm9F1Yr6dkHVoLP7ocYkNRHoPLut5E6IFJtK -lVI2NneUYJGnYSO+1xPV9TqlJeMNwr3uFMAN8N/oB3f4WWwuRYgR0L5g2A+Lvx+g -bbdl+Tb/0CNfslfSuDrFV8Z4n6gVwb9ZPGlNHCvnqRfLUpRFJwmR7UYvzi/E7rXJ -EDkK+tcnPkz2JtjdLKR7qVcCAwEAAQ== ------END PUBLIC KEY----- From bf3f834dca11414c0e7d64344cde5c6552f25df4 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Wed, 6 Sep 2023 11:41:32 -0700 Subject: [PATCH 22/67] Add provider default labels (#8670) * Add provider default labels * Fix the filed names * Fix the field name * Don't expand lables field * Fix syntax errors * Fix bug to set metadata.0.terraform_labels * Ignore state verify for terraform_labels * Add logs * Add more logs * Skip test if vcr is enabled * Add new type KeyValueTerraformLabels * Fix rake test * Add terraform_labels to tfplan.json files * Comment out tgc integration tests --- .ci/gcb-generate-diffs-new.yml | 76 +++---- mmv1/api/resource.rb | 40 +++- mmv1/api/type.rb | 10 +- mmv1/compiler.rb | 4 +- mmv1/products/compute/ForwardingRule.yaml | 2 +- mmv1/products/compute/GlobalAddress.yaml | 2 +- .../compute/GlobalForwardingRule.yaml | 2 +- mmv1/products/compute/VpnTunnel.yaml | 2 +- mmv1/provider/core.rb | 3 +- mmv1/provider/terraform.rb | 1 + .../examples/base_configs/test_file.go.erb | 2 +- .../terraform/flatten_property_method.erb | 2 +- .../terraform/post_create/labels.erb | 14 +- .../terraform/fwmodels/provider_model.go.erb | 1 + .../fwprovider/framework_provider.go.erb | 4 + .../terraform/provider/provider.go.erb | 13 ++ .../resource_bigquery_dataset_test.go | 20 +- .../resource_compute_address_test.go.erb | 185 +++++++++++++++++- ...source_compute_forwarding_rule_test.go.erb | 2 + ...compute_global_forwarding_rule_test.go.erb | 4 +- .../terraform/tpgresource/labels.go | 61 ++++++ .../terraform/transport/config.go.erb | 1 + .../data/example_bigquery_dataset.tfplan.json | 7 + ...e_bigquery_dataset_iam_binding.tfplan.json | 7 + ...le_bigquery_dataset_iam_member.tfplan.json | 7 + ...le_bigquery_dataset_iam_policy.tfplan.json | 7 + 26 files changed, 406 insertions(+), 73 deletions(-) create mode 100644 mmv1/third_party/terraform/tpgresource/labels.go diff --git a/.ci/gcb-generate-diffs-new.yml b/.ci/gcb-generate-diffs-new.yml index 8a8a93377a88..d998cd945140 100644 --- a/.ci/gcb-generate-diffs-new.yml +++ b/.ci/gcb-generate-diffs-new.yml @@ -200,45 +200,45 @@ steps: - "17" # Build step - terraform-google-conversion - - name: 'gcr.io/graphite-docker-images/go-plus' - id: tgc-test-integration-0.12.31 - entrypoint: '/workspace/.ci/scripts/go-plus/terraform-validator-tester-integration/test_terraform_validator_integration.sh' - allowFailure: true - secretEnv: ["GITHUB_TOKEN"] - waitFor: ["tpgb-head", "tpgb-base", "tgc-head", "tgc-base"] - env: - - TERRAFORM_VERSION=0.12.31 - - TEST_PROJECT=$_VALIDATOR_TEST_PROJECT - - TEST_FOLDER_ID=$_VALIDATOR_TEST_FOLDER - - TEST_ANCESTRY=$_VALIDATOR_TEST_ANCESTRY - - TEST_ORG_ID=$_VALIDATOR_TEST_ORG - args: - - $_PR_NUMBER - - $COMMIT_SHA - - $BUILD_ID - - $PROJECT_ID - - "18" # Build step - - terraform-google-conversion + # - name: 'gcr.io/graphite-docker-images/go-plus' + # id: tgc-test-integration-0.12.31 + # entrypoint: '/workspace/.ci/scripts/go-plus/terraform-validator-tester-integration/test_terraform_validator_integration.sh' + # allowFailure: true + # secretEnv: ["GITHUB_TOKEN"] + # waitFor: ["tpgb-head", "tpgb-base", "tgc-head", "tgc-base"] + # env: + # - TERRAFORM_VERSION=0.12.31 + # - TEST_PROJECT=$_VALIDATOR_TEST_PROJECT + # - TEST_FOLDER_ID=$_VALIDATOR_TEST_FOLDER + # - TEST_ANCESTRY=$_VALIDATOR_TEST_ANCESTRY + # - TEST_ORG_ID=$_VALIDATOR_TEST_ORG + # args: + # - $_PR_NUMBER + # - $COMMIT_SHA + # - $BUILD_ID + # - $PROJECT_ID + # - "18" # Build step + # - terraform-google-conversion - - name: 'gcr.io/graphite-docker-images/go-plus' - id: tgc-test-integration-0.13.7 - entrypoint: '/workspace/.ci/scripts/go-plus/terraform-validator-tester-integration/test_terraform_validator_integration.sh' - allowFailure: true - secretEnv: ["GITHUB_TOKEN"] - waitFor: ["tpgb-head", "tpgb-base", "tgc-head", "tgc-base"] - env: - - TERRAFORM_VERSION=0.13.7 - - TEST_PROJECT=$_VALIDATOR_TEST_PROJECT - - TEST_FOLDER_ID=$_VALIDATOR_TEST_FOLDER - - TEST_ANCESTRY=$_VALIDATOR_TEST_ANCESTRY - - TEST_ORG_ID=$_VALIDATOR_TEST_ORG - args: - - $_PR_NUMBER - - $COMMIT_SHA - - $BUILD_ID - - $PROJECT_ID - - "19" # Build step - - terraform-google-conversion + # - name: 'gcr.io/graphite-docker-images/go-plus' + # id: tgc-test-integration-0.13.7 + # entrypoint: '/workspace/.ci/scripts/go-plus/terraform-validator-tester-integration/test_terraform_validator_integration.sh' + # allowFailure: true + # secretEnv: ["GITHUB_TOKEN"] + # waitFor: ["tpgb-head", "tpgb-base", "tgc-head", "tgc-base"] + # env: + # - TERRAFORM_VERSION=0.13.7 + # - TEST_PROJECT=$_VALIDATOR_TEST_PROJECT + # - TEST_FOLDER_ID=$_VALIDATOR_TEST_FOLDER + # - TEST_ANCESTRY=$_VALIDATOR_TEST_ANCESTRY + # - TEST_ORG_ID=$_VALIDATOR_TEST_ORG + # args: + # - $_PR_NUMBER + # - $COMMIT_SHA + # - $BUILD_ID + # - $PROJECT_ID + # - "19" # Build step + # - terraform-google-conversion - name: 'gcr.io/graphite-docker-images/bash-plus' id: tpgb-test diff --git a/mmv1/api/resource.rb b/mmv1/api/resource.rb index 0321f88f89f5..0670658de06d 100644 --- a/mmv1/api/resource.rb +++ b/mmv1/api/resource.rb @@ -394,8 +394,11 @@ def all_resourcerefs # 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 - all_user_properties.reject { |v| v.output && !v.is_a?(Api::Type::Fingerprint) } - .reject(&:url_param_only) + settable_properties = all_user_properties.reject do |v| + v.output && !v.is_a?(Api::Type::Fingerprint) && !v.is_a?(Api::Type::KeyValueTerraformLabels) + end + settable_properties.reject(&:url_param_only) + .reject { |v| v.is_a?(Api::Type::KeyValueLabels) } end # Properties that will be returned in the API body @@ -448,14 +451,26 @@ def decoder? !@transport&.decoder.nil? end - def add_labels_related_fields(props) + def add_labels_related_fields(props, parent) props.each do |p| if p.is_a? Api::Type::KeyValueLabels + # The terraform_labels field is used to write to API, instead of the labels field. + p.ignore_write = true + + @custom_diff ||= [] + if parent.nil? + @custom_diff.append('tpgresource.SetTerraformLabelsDiff') + elsif parent == 'metadata' + @custom_diff.append('tpgresource.SetMetadataTerraformLabelsDiff') + end + + props << build_terraform_labels_field('labels', p.field_min_version, p.update_verb, + p.update_url) props << build_effective_labels_field('labels', p.field_min_version) elsif p.is_a? Api::Type::KeyValueAnnotations props << build_effective_labels_field('annotations', p.field_min_version) elsif (p.is_a? Api::Type::NestedObject) && !p.all_properties.nil? - p.properties = add_labels_related_fields(p.all_properties) + p.properties = add_labels_related_fields(p.all_properties, p.name) end end props @@ -467,7 +482,7 @@ def build_effective_labels_field(name, min_version) other clients and services." Api::Type::KeyValuePairs.new( - name: "effective_#{name}", + name: "effective#{name.capitalize}", output: true, api_name: name, description:, @@ -476,6 +491,21 @@ def build_effective_labels_field(name, min_version) ) end + def build_terraform_labels_field(name, min_version, update_verb, update_url) + description = "The combination of #{name} configured directly on the resource + and default #{name} configured on the provider." + + Api::Type::KeyValueTerraformLabels.new( + name: "terraform#{name.capitalize}", + output: true, + api_name: name, + description:, + min_version:, + update_verb:, + update_url: + ) + end + # ==================== # Version-related methods # ==================== diff --git a/mmv1/api/type.rb b/mmv1/api/type.rb index d8b505199993..b2959da9aed9 100644 --- a/mmv1/api/type.rb +++ b/mmv1/api/type.rb @@ -766,10 +766,10 @@ def exclude_if_not_in_version!(version) # in Map. class KeyValuePairs < Composite # Ignore writing the "effective_labels" and "effective_annotations" fields to API. - attr_reader :ignore_write + attr_accessor :ignore_write def initialize(name: nil, output: nil, api_name: nil, description: nil, min_version: nil, - ignore_write: nil) + ignore_write: nil, update_verb: nil, update_url: nil) super() @name = name @@ -778,6 +778,8 @@ def initialize(name: nil, output: nil, api_name: nil, description: nil, min_vers @description = description @min_version = min_version @ignore_write = ignore_write + @update_verb = update_verb + @update_url = update_url end def validate @@ -801,6 +803,10 @@ def validate end end + # An array of string -> string key -> value pairs used for the "terraform_labels" field. + class KeyValueTerraformLabels < KeyValuePairs + end + # An array of string -> string key -> value pairs used specifically for the "annotations" field. # The field name with this type should be "annotations" literally. class KeyValueAnnotations < KeyValuePairs diff --git a/mmv1/compiler.rb b/mmv1/compiler.rb index 0ca7dc22b610..609552842899 100755 --- a/mmv1/compiler.rb +++ b/mmv1/compiler.rb @@ -223,7 +223,9 @@ end res_yaml = File.read(file_path) resource = Api::Compiler.new(res_yaml).run - resource.properties = resource.add_labels_related_fields(resource.properties_with_excluded) + resource.properties = resource.add_labels_related_fields( + resource.properties_with_excluded, nil + ) resource.validate resources.push(resource) end diff --git a/mmv1/products/compute/ForwardingRule.yaml b/mmv1/products/compute/ForwardingRule.yaml index 15acdafc7c78..771626523dec 100644 --- a/mmv1/products/compute/ForwardingRule.yaml +++ b/mmv1/products/compute/ForwardingRule.yaml @@ -503,7 +503,7 @@ properties: send_empty_value: true update_verb: :PATCH update_url: projects/{{project}}/regions/{{region}}/forwardingRules/{{name}} - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels to apply to this forwarding rule. A list of key->value pairs. diff --git a/mmv1/products/compute/GlobalAddress.yaml b/mmv1/products/compute/GlobalAddress.yaml index b5cd3bd89ca5..320460dc8f7f 100644 --- a/mmv1/products/compute/GlobalAddress.yaml +++ b/mmv1/products/compute/GlobalAddress.yaml @@ -86,7 +86,7 @@ properties: characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash. required: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels to apply to this address. A list of key->value pairs. diff --git a/mmv1/products/compute/GlobalForwardingRule.yaml b/mmv1/products/compute/GlobalForwardingRule.yaml index ee6df3585dfd..780dc6e8a562 100644 --- a/mmv1/products/compute/GlobalForwardingRule.yaml +++ b/mmv1/products/compute/GlobalForwardingRule.yaml @@ -296,7 +296,7 @@ properties: values: - :IPV4 - :IPV6 - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels to apply to this forwarding rule. A list of key->value pairs. diff --git a/mmv1/products/compute/VpnTunnel.yaml b/mmv1/products/compute/VpnTunnel.yaml index 3020328720d5..f1724d01ef68 100644 --- a/mmv1/products/compute/VpnTunnel.yaml +++ b/mmv1/products/compute/VpnTunnel.yaml @@ -230,7 +230,7 @@ properties: is_set: true default_from_api: true item_type: Api::Type::String - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Labels to apply to this VpnTunnel. update_verb: :POST diff --git a/mmv1/provider/core.rb b/mmv1/provider/core.rb index fb66cbbc4377..a5651ec92ae2 100644 --- a/mmv1/provider/core.rb +++ b/mmv1/provider/core.rb @@ -401,7 +401,8 @@ def field_specific_update_methods(properties) # method and group them by update url & verb. def properties_by_custom_update(properties) update_props = properties.reject do |p| - p.update_url.nil? || p.update_verb.nil? || p.update_verb == :NOOP + p.update_url.nil? || p.update_verb.nil? || p.update_verb == :NOOP || + p.is_a?(Api::Type::KeyValueLabels) end update_props.group_by do |p| diff --git a/mmv1/provider/terraform.rb b/mmv1/provider/terraform.rb index 1cf370b33667..5d9cb7a4a696 100644 --- a/mmv1/provider/terraform.rb +++ b/mmv1/provider/terraform.rb @@ -92,6 +92,7 @@ def tf_types Api::Type::Array => 'schema.TypeList', Api::Type::KeyValuePairs => 'schema.TypeMap', Api::Type::KeyValueLabels => 'schema.TypeMap', + Api::Type::KeyValueTerraformLabels => 'schema.TypeMap', Api::Type::KeyValueAnnotations => 'schema.TypeMap', Api::Type::Map => 'schema.TypeSet', Api::Type::Fingerprint => 'schema.TypeString' diff --git a/mmv1/templates/terraform/examples/base_configs/test_file.go.erb b/mmv1/templates/terraform/examples/base_configs/test_file.go.erb index ab2ed99c2be9..3e9b14c491df 100644 --- a/mmv1/templates/terraform/examples/base_configs/test_file.go.erb +++ b/mmv1/templates/terraform/examples/base_configs/test_file.go.erb @@ -44,7 +44,7 @@ object.examples test_slug = "#{resource_name}_#{example.name.camelize(:lower)}Example" ignore_read = object.all_user_properties - .select{|p| p.url_param_only || p.ignore_read || p.is_a?(Api::Type::ResourceRef) || p.is_a?(Api::Type::KeyValueLabels || p.is_a?(Api::Type::KeyValueAnnotations))} + .select{|p| p.url_param_only || p.ignore_read || p.is_a?(Api::Type::ResourceRef) || p.is_a?(Api::Type::KeyValueLabels) || p.is_a?(Api::Type::KeyValueAnnotations) || p.is_a?(Api::Type::KeyValueTerraformLabels)} .map { |p| p.name.underscore } .concat(example.ignore_read_extra) diff --git a/mmv1/templates/terraform/flatten_property_method.erb b/mmv1/templates/terraform/flatten_property_method.erb index 5f8fdb875590..e19121c4f953 100644 --- a/mmv1/templates/terraform/flatten_property_method.erb +++ b/mmv1/templates/terraform/flatten_property_method.erb @@ -94,7 +94,7 @@ func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d }) } return transformed -<% elsif (property.is_a?(Api::Type::KeyValueLabels)) || (property.is_a?(Api::Type::KeyValueAnnotations)) -%> +<% elsif (property.is_a?(Api::Type::KeyValueLabels)) || (property.is_a?(Api::Type::KeyValueAnnotations)) || property.name == "terraformLabels" -%> if v == nil { return v } diff --git a/mmv1/templates/terraform/post_create/labels.erb b/mmv1/templates/terraform/post_create/labels.erb index e725830eaabd..f47ed50f122c 100644 --- a/mmv1/templates/terraform/post_create/labels.erb +++ b/mmv1/templates/terraform/post_create/labels.erb @@ -1,5 +1,6 @@ <% if properties.any?{ |p| p.name == "labels" } -%> -if v, ok := d.GetOkExists("labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) { +if v, ok := d.GetOkExists("terraform_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) { + labels := d.Get("labels") // Labels cannot be set in a create. We'll have to set them here. err = resource<%= resource_name -%>Read(d, meta) if err != nil { @@ -7,8 +8,8 @@ if v, ok := d.GetOkExists("labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v } obj := make(map[string]interface{}) - // d.Get("labels") will have been overridden by the Read call. - labelsProp, err := expand<%= resource_name -%>Labels(v, d, config) + // d.Get("terraform_labels") will have been overridden by the Read call. + labelsProp, err := expand<%= resource_name -%>TerraformLabels(v, d, config) if err != nil { return err } @@ -47,8 +48,13 @@ if v, ok := d.GetOkExists("labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v } // Set back the labels field, as it is needed to decide the value of "labels" in the state in the read function. - if err := d.Set("labels", v); err != nil { + if err := d.Set("labels", labels); err != nil { return fmt.Errorf("Error setting back labels: %s", err) } + + // Set back the terraform_labels field, as it is needed to decide the value of "terraform_labels" in the state in the read function. + if err := d.Set("terraform_labels", v); err != nil { + return fmt.Errorf("Error setting back terraform_labels: %s", err) + } } <% end -%> diff --git a/mmv1/third_party/terraform/fwmodels/provider_model.go.erb b/mmv1/third_party/terraform/fwmodels/provider_model.go.erb index 9d16de58a938..cba7e8f8f5c8 100644 --- a/mmv1/third_party/terraform/fwmodels/provider_model.go.erb +++ b/mmv1/third_party/terraform/fwmodels/provider_model.go.erb @@ -21,6 +21,7 @@ type ProviderModel struct { UserProjectOverride types.Bool `tfsdk:"user_project_override"` RequestTimeout types.String `tfsdk:"request_timeout"` RequestReason types.String `tfsdk:"request_reason"` + DefaultLabels types.Map `tfsdk:"default_labels"` // Generated Products <% products.each do |product| -%> diff --git a/mmv1/third_party/terraform/fwprovider/framework_provider.go.erb b/mmv1/third_party/terraform/fwprovider/framework_provider.go.erb index 803fb435c023..1805877939e9 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_provider.go.erb +++ b/mmv1/third_party/terraform/fwprovider/framework_provider.go.erb @@ -113,6 +113,10 @@ func (p *FrameworkProvider) Schema(_ context.Context, _ provider.SchemaRequest, "request_reason": schema.StringAttribute{ Optional: true, }, + "default_labels": schema.MapAttribute{ + Optional: true, + ElementType: types.StringType, + }, // Generated Products <% products.each do |product| -%> diff --git a/mmv1/third_party/terraform/provider/provider.go.erb b/mmv1/third_party/terraform/provider/provider.go.erb index 8f86f3905ca9..28ef411adc91 100644 --- a/mmv1/third_party/terraform/provider/provider.go.erb +++ b/mmv1/third_party/terraform/provider/provider.go.erb @@ -143,6 +143,12 @@ func Provider() *schema.Provider { Optional: true, }, + "default_labels": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + // Generated Products <% products.each do |product| -%> "<%= product[:definitions].name.underscore -%>_custom_endpoint": { @@ -715,6 +721,13 @@ func ProviderConfigure(ctx context.Context, d *schema.ResourceData, p *schema.Pr config.Scopes[i] = scope.(string) } + config.DefaultLabels = make(map[string]string) + defaultLabels := d.Get("default_labels").(map[string]interface{}) + + for k, v := range defaultLabels { + config.DefaultLabels[k] = v.(string) + } + batchCfg, err := transport_tpg.ExpandProviderBatchingConfig(d.Get("batching")) if err != nil { return nil, diag.FromErr(err) 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 9bdb54d0502a..e7aa05f777d4 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 @@ -51,7 +51,7 @@ func TestAccBigQueryDataset_basic(t *testing.T) { 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"}, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccBigQueryDatasetUpdated(datasetID), @@ -69,7 +69,7 @@ func TestAccBigQueryDataset_basic(t *testing.T) { ResourceName: "google_bigquery_dataset.test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"labels"}, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccBigQueryDatasetUpdated2(datasetID), @@ -78,7 +78,7 @@ func TestAccBigQueryDataset_basic(t *testing.T) { ResourceName: "google_bigquery_dataset.test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"labels"}, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccBigQueryDataset_withoutLabels(datasetID), @@ -156,7 +156,7 @@ func TestAccBigQueryDataset_datasetWithContents(t *testing.T) { ResourceName: "google_bigquery_dataset.contents_test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"delete_contents_on_destroy", "labels"}, + ImportStateVerifyIgnore: []string{"delete_contents_on_destroy", "labels", "terraform_labels"}, }, }, }) @@ -181,7 +181,7 @@ func TestAccBigQueryDataset_access(t *testing.T) { ResourceName: "google_bigquery_dataset.access_test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"labels"}, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccBigQueryDatasetWithTwoAccess(datasetID), @@ -190,7 +190,7 @@ func TestAccBigQueryDataset_access(t *testing.T) { ResourceName: "google_bigquery_dataset.access_test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"labels"}, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccBigQueryDatasetWithOneAccess(datasetID), @@ -199,7 +199,7 @@ func TestAccBigQueryDataset_access(t *testing.T) { ResourceName: "google_bigquery_dataset.access_test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"labels"}, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccBigQueryDatasetWithViewAccess(datasetID, otherDatasetID, otherTableID), @@ -208,7 +208,7 @@ func TestAccBigQueryDataset_access(t *testing.T) { ResourceName: "google_bigquery_dataset.access_test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"labels"}, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -231,7 +231,7 @@ func TestAccBigQueryDataset_regionalLocation(t *testing.T) { ResourceName: "google_bigquery_dataset.test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"labels"}, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -277,7 +277,7 @@ func TestAccBigQueryDataset_storageBillModel(t *testing.T) { ResourceName: "google_bigquery_dataset.test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"labels"}, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_address_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_address_test.go.erb index 79b9187aae5f..a637c410ab46 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_address_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_address_test.go.erb @@ -98,7 +98,7 @@ func TestAccComputeAddress_networkTier_withLabels(t *testing.T) { 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"}, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccComputeAddress_networkTier_withLabelsUpdate(acctest.RandString(t, 10)), @@ -116,7 +116,7 @@ func TestAccComputeAddress_networkTier_withLabels(t *testing.T) { ResourceName: "google_compute_address.foobar", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"labels"}, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccComputeAddress_networkTier(acctest.RandString(t, 10)), @@ -173,6 +173,121 @@ func TestAccComputeAddress_networkTier_withProvider5(t *testing.T) { }) } +func TestAccComputeAddress_withProviderDefaultLabels(t *testing.T) { + // The test failed if VCR testing is enabled, because the cached provider config is used. + // With the cached provider config, any changes in the provider default labels will not be applied. + acctest.SkipIfVcr(t) + t.Parallel() + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeAddressDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeAddress_withProviderDefaultLabels(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.%", "2"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.env", "foo"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.%", "3"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.default_key1", "default_value1"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.env", "foo"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.%", "3"), + ), + }, + { + ResourceName: "google_compute_address.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccComputeAddress_resourceLabelsOverridesProviderDefaultLabels(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.%", "3"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.env", "foo"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.default_expiration_ms", "3600000"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.default_key1", "value1"), + + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.%", "3"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.default_key1", "value1"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.env", "foo"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.%", "3"), + ), + }, + { + ResourceName: "google_compute_address.foobar", + 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: testAccComputeAddress_moveResourceLabelToProviderDefaultLabels(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.%", "2"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.default_expiration_ms", "3600000"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.default_key1", "value1"), + + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.%", "3"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.default_key1", "value1"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.env", "foo"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.%", "3"), + ), + }, + { + ResourceName: "google_compute_address.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccComputeAddress_resourceLabelsOverridesProviderDefaultLabels(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.%", "3"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.env", "foo"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.default_expiration_ms", "3600000"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.default_key1", "value1"), + + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.%", "3"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.default_key1", "value1"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.env", "foo"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.%", "3"), + ), + }, + { + ResourceName: "google_compute_address.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccComputeAddress_networkTier(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckNoResourceAttr("google_compute_address.foobar", "labels.%"), + resource.TestCheckNoResourceAttr("google_compute_address.foobar", "effective_labels.%"), + ), + }, + { + ResourceName: "google_compute_address.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccComputeAddress_networkTier_withLabels(i string) string { return fmt.Sprintf(` resource "google_compute_address" "foobar" { @@ -180,7 +295,7 @@ resource "google_compute_address" "foobar" { network_tier = "STANDARD" labels = { - env = "foo" + env = "foo" default_expiration_ms = 3600000 } } @@ -194,12 +309,74 @@ resource "google_compute_address" "foobar" { network_tier = "STANDARD" labels = { - env = "bar" + env = "bar" default_expiration_ms = 7200000 } } `, i) } + +func testAccComputeAddress_withProviderDefaultLabels(i string) string { + return fmt.Sprintf(` +provider "google" { + default_labels = { + default_key1 = "default_value1" + } +} + +resource "google_compute_address" "foobar" { + name = "tf-test-address-%s" + network_tier = "STANDARD" + + labels = { + env = "foo" + default_expiration_ms = 3600000 + } +} +`, i) +} + +func testAccComputeAddress_resourceLabelsOverridesProviderDefaultLabels(i string) string { + return fmt.Sprintf(` +provider "google" { + default_labels = { + default_key1 = "default_value1" + } +} + +resource "google_compute_address" "foobar" { + name = "tf-test-address-%s" + network_tier = "STANDARD" + + labels = { + env = "foo" + default_expiration_ms = 3600000 + default_key1 = "value1" + } +} +`, i) +} + +func testAccComputeAddress_moveResourceLabelToProviderDefaultLabels(i string) string { + return fmt.Sprintf(` +provider "google" { + default_labels = { + default_key1 = "default_value1" + env = "foo" + } +} + +resource "google_compute_address" "foobar" { + name = "tf-test-address-%s" + network_tier = "STANDARD" + + labels = { + default_expiration_ms = 3600000 + default_key1 = "value1" + } +} +`, i) +} <% end -%> func testAccComputeAddress_internal(i string) string { diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_forwarding_rule_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_forwarding_rule_test.go.erb index c8c34d473848..7b51fbabddbf 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_forwarding_rule_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_forwarding_rule_test.go.erb @@ -27,6 +27,7 @@ func TestAccComputeForwardingRule_update(t *testing.T) { ResourceName: "google_compute_forwarding_rule.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, resource.TestStep{ Config: testAccComputeForwardingRule_update(poolName, ruleName), @@ -35,6 +36,7 @@ func TestAccComputeForwardingRule_update(t *testing.T) { ResourceName: "google_compute_forwarding_rule.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_global_forwarding_rule_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_global_forwarding_rule_test.go.erb index 364a2583e48c..e4f0036ae180 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_global_forwarding_rule_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_global_forwarding_rule_test.go.erb @@ -108,7 +108,7 @@ func TestAccComputeGlobalForwardingRule_labels(t *testing.T) { ResourceName: "google_compute_global_forwarding_rule.forwarding_rule", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"port_range", "target"}, + ImportStateVerifyIgnore: []string{"port_range", "target", "labels", "terraform_labels"}, }, { Config: testAccComputeGlobalForwardingRule_labelsUpdated(fr, proxy, backend, hc, urlmap), @@ -117,7 +117,7 @@ func TestAccComputeGlobalForwardingRule_labels(t *testing.T) { ResourceName: "google_compute_global_forwarding_rule.forwarding_rule", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"port_range", "target"}, + ImportStateVerifyIgnore: []string{"port_range", "target", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/tpgresource/labels.go b/mmv1/third_party/terraform/tpgresource/labels.go new file mode 100644 index 000000000000..e18d1323c890 --- /dev/null +++ b/mmv1/third_party/terraform/tpgresource/labels.go @@ -0,0 +1,61 @@ +package tpgresource + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func SetTerraformLabelsDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) error { + config := meta.(*transport_tpg.Config) + + // Merge provider default labels with the user defined labels in the resource to get terraform managed labels + terraformLabels := make(map[string]string) + for k, v := range config.DefaultLabels { + terraformLabels[k] = v + } + + labels := d.Get("labels").(map[string]interface{}) + for k, v := range labels { + terraformLabels[k] = v.(string) + } + + if err := d.SetNew("terraform_labels", terraformLabels); err != nil { + return fmt.Errorf("error setting new terraform_labels diff: %w", err) + } + + return nil +} + +func SetMetadataTerraformLabelsDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) error { + v := d.Get("metadata") + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil + } + + config := meta.(*transport_tpg.Config) + + // Merge provider default labels with the user defined labels in the resource to get terraform managed labels + terraformLabels := make(map[string]string) + for k, v := range config.DefaultLabels { + terraformLabels[k] = v + } + + labels := d.Get("metadata.0.labels").(map[string]interface{}) + for k, v := range labels { + terraformLabels[k] = v.(string) + } + + raw := l[0] + original := raw.(map[string]interface{}) + original["terraform_labels"] = terraformLabels + + if err := d.SetNew("metadata", []interface{}{original}); err != nil { + return fmt.Errorf("error setting new metadata diff: %w", err) + } + + return nil +} diff --git a/mmv1/third_party/terraform/transport/config.go.erb b/mmv1/third_party/terraform/transport/config.go.erb index ee330cd4a26d..9e831c7d392b 100644 --- a/mmv1/third_party/terraform/transport/config.go.erb +++ b/mmv1/third_party/terraform/transport/config.go.erb @@ -189,6 +189,7 @@ type Config struct { UserProjectOverride bool RequestReason string RequestTimeout time.Duration + DefaultLabels map[string]string // PollInterval is passed to resource.StateChangeConf in common_operation.go // It controls the interval at which we poll for successful operations PollInterval time.Duration diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tfplan.json b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tfplan.json index 9249c8265cf9..1daf2ee28ffd 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tfplan.json +++ b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tfplan.json @@ -22,6 +22,9 @@ "labels": { "env": "dev" }, + "terraform_labels": { + "env": "dev" + }, "location": "EU", "timeouts": null } @@ -52,6 +55,9 @@ "labels": { "env": "dev" }, + "terraform_labels": { + "env": "dev" + }, "location": "EU", "timeouts": null }, @@ -62,6 +68,7 @@ "etag": true, "id": true, "labels": {}, + "terraform_labels": {}, "last_modified_time": true, "project": true, "self_link": true diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tfplan.json b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tfplan.json index d3a1e114db80..7519ca4bd735 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tfplan.json +++ b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tfplan.json @@ -21,6 +21,9 @@ "labels": { "env": "dev" }, + "terraform_labels": { + "env": "dev" + }, "location": "EU", "project": "{{.Provider.project}}", "timeouts": null @@ -61,6 +64,9 @@ "labels": { "env": "dev" }, + "terraform_labels": { + "env": "dev" + }, "location": "EU", "project": "{{.Provider.project}}", "timeouts": null @@ -72,6 +78,7 @@ "etag": true, "id": true, "labels": {}, + "terraform_labels": {}, "last_modified_time": true, "self_link": true } diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tfplan.json b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tfplan.json index 5848f267fdd9..6b0d5a89ce54 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tfplan.json +++ b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tfplan.json @@ -21,6 +21,9 @@ "labels": { "env": "dev" }, + "terraform_labels": { + "env": "dev" + }, "location": "EU", "project": "{{.Provider.project}}", "timeouts": null @@ -61,6 +64,9 @@ "labels": { "env": "dev" }, + "terraform_labels": { + "env": "dev" + }, "location": "EU", "project": "{{.Provider.project}}", "timeouts": null @@ -72,6 +78,7 @@ "etag": true, "id": true, "labels": {}, + "terraform_labels": {}, "last_modified_time": true, "self_link": true } diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tfplan.json index 6a19eeda793f..1725f40b59c3 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tfplan.json +++ b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tfplan.json @@ -21,6 +21,9 @@ "labels": { "env": "dev" }, + "terraform_labels": { + "env": "dev" + }, "location": "EU", "project": "{{.Provider.project}}", "timeouts": null @@ -59,6 +62,9 @@ "labels": { "env": "dev" }, + "terraform_labels": { + "env": "dev" + }, "location": "EU", "project": "{{.Provider.project}}", "timeouts": null @@ -70,6 +76,7 @@ "etag": true, "id": true, "labels": {}, + "terraform_labels": {}, "last_modified_time": true, "self_link": true } From fb61cfbb8adaf9b4517d3fb66223dcde9360cb06 Mon Sep 17 00:00:00 2001 From: pengq-google Date: Wed, 6 Sep 2023 15:14:25 -0400 Subject: [PATCH 23/67] Change the default value of unique_writer_identity in resource logging_project_sink to true. (#8875) --- .../logging/resource_logging_project_sink.go | 6 ++- .../resource_logging_project_sink_test.go | 50 ++++++++----------- 2 files changed, 24 insertions(+), 32 deletions(-) diff --git a/mmv1/third_party/terraform/services/logging/resource_logging_project_sink.go b/mmv1/third_party/terraform/services/logging/resource_logging_project_sink.go index 18b235c9b095..ced0bea2cb43 100644 --- a/mmv1/third_party/terraform/services/logging/resource_logging_project_sink.go +++ b/mmv1/third_party/terraform/services/logging/resource_logging_project_sink.go @@ -1,3 +1,5 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 package logging import ( @@ -36,9 +38,9 @@ func ResourceLoggingProjectSink() *schema.Resource { schm.Schema["unique_writer_identity"] = &schema.Schema{ Type: schema.TypeBool, Optional: true, - Default: false, + Default: true, ForceNew: true, - Description: `Whether or not to create a unique identity associated with this sink. If false (the default), then the writer_identity used is serviceAccount:cloud-logs@system.gserviceaccount.com. If true, then a unique service account is created and used for this sink. If you wish to publish logs across projects, you must set unique_writer_identity to true.`, + Description: `Whether or not to create a unique identity associated with this sink. If false (the legacy behavior), then the writer_identity used is serviceAccount:cloud-logs@system.gserviceaccount.com. If true, then a unique service account is created and used for this sink. If you wish to publish logs across projects, you must set unique_writer_identity to true.`, } return schm } diff --git a/mmv1/third_party/terraform/services/logging/resource_logging_project_sink_test.go b/mmv1/third_party/terraform/services/logging/resource_logging_project_sink_test.go index 2c5a08926abd..9cd468c45323 100644 --- a/mmv1/third_party/terraform/services/logging/resource_logging_project_sink_test.go +++ b/mmv1/third_party/terraform/services/logging/resource_logging_project_sink_test.go @@ -292,13 +292,11 @@ func testAccLoggingProjectSink_basic(name, project, bucketName string) string { resource "google_logging_project_sink" "basic" { name = "%s" project = "%s" - destination = "storage.googleapis.com/${google_storage_bucket.log-bucket.name}" + destination = "storage.googleapis.com/${google_storage_bucket.gcs-bucket.name}" filter = "logName=\"projects/%s/logs/compute.googleapis.com%%2Factivity_log\" AND severity>=ERROR" - - unique_writer_identity = false } -resource "google_storage_bucket" "log-bucket" { +resource "google_storage_bucket" "gcs-bucket" { name = "%s" location = "US" } @@ -310,14 +308,12 @@ func testAccLoggingProjectSink_described(name, project, bucketName string) strin resource "google_logging_project_sink" "described" { name = "%s" project = "%s" - destination = "storage.googleapis.com/${google_storage_bucket.log-bucket.name}" + destination = "storage.googleapis.com/${google_storage_bucket.gcs-bucket.name}" filter = "logName=\"projects/%s/logs/compute.googleapis.com%%2Factivity_log\" AND severity>=ERROR" description = "this is a description for a project level logging sink" - - unique_writer_identity = false } -resource "google_storage_bucket" "log-bucket" { +resource "google_storage_bucket" "gcs-bucket" { name = "%s" location = "US" } @@ -329,14 +325,12 @@ func testAccLoggingProjectSink_described_update(name, project, bucketName string resource "google_logging_project_sink" "described" { name = "%s" project = "%s" - destination = "storage.googleapis.com/${google_storage_bucket.log-bucket.name}" + destination = "storage.googleapis.com/${google_storage_bucket.gcs-bucket.name}" filter = "logName=\"projects/%s/logs/compute.googleapis.com%%2Factivity_log\" AND severity>=ERROR" description = "description updated" - - unique_writer_identity = false } -resource "google_storage_bucket" "log-bucket" { +resource "google_storage_bucket" "gcs-bucket" { name = "%s" location = "US" } @@ -348,14 +342,14 @@ func testAccLoggingProjectSink_disabled(name, project, bucketName string) string resource "google_logging_project_sink" "disabled" { name = "%s" project = "%s" - destination = "storage.googleapis.com/${google_storage_bucket.log-bucket.name}" + destination = "storage.googleapis.com/${google_storage_bucket.gcs-bucket.name}" filter = "logName=\"projects/%s/logs/compute.googleapis.com%%2Factivity_log\" AND severity>=ERROR" disabled = true unique_writer_identity = false } -resource "google_storage_bucket" "log-bucket" { +resource "google_storage_bucket" "gcs-bucket" { name = "%s" location = "US" } @@ -367,14 +361,14 @@ func testAccLoggingProjectSink_disabled_update(name, project, bucketName, disabl resource "google_logging_project_sink" "disabled" { name = "%s" project = "%s" - destination = "storage.googleapis.com/${google_storage_bucket.log-bucket.name}" + destination = "storage.googleapis.com/${google_storage_bucket.gcs-bucket.name}" filter = "logName=\"projects/%s/logs/compute.googleapis.com%%2Factivity_log\" AND severity>=ERROR" disabled = "%s" unique_writer_identity = true } -resource "google_storage_bucket" "log-bucket" { +resource "google_storage_bucket" "gcs-bucket" { name = "%s" location = "US" } @@ -385,13 +379,13 @@ func testAccLoggingProjectSink_uniqueWriter(name, bucketName string) string { return fmt.Sprintf(` resource "google_logging_project_sink" "unique_writer" { name = "%s" - destination = "storage.googleapis.com/${google_storage_bucket.log-bucket.name}" + destination = "storage.googleapis.com/${google_storage_bucket.gcs-bucket.name}" filter = "logName=\"projects/%s/logs/compute.googleapis.com%%2Factivity_log\" AND severity>=ERROR" unique_writer_identity = true } -resource "google_storage_bucket" "log-bucket" { +resource "google_storage_bucket" "gcs-bucket" { name = "%s" location = "US" } @@ -402,13 +396,13 @@ func testAccLoggingProjectSink_uniqueWriterUpdated(name, bucketName string) stri return fmt.Sprintf(` resource "google_logging_project_sink" "unique_writer" { name = "%s" - destination = "storage.googleapis.com/${google_storage_bucket.log-bucket.name}" + destination = "storage.googleapis.com/${google_storage_bucket.gcs-bucket.name}" filter = "logName=\"projects/%s/logs/compute.googleapis.com%%2Factivity_log\" AND severity>=WARNING" unique_writer_identity = true } -resource "google_storage_bucket" "log-bucket" { +resource "google_storage_bucket" "gcs-bucket" { name = "%s" location = "US" } @@ -420,7 +414,7 @@ func testAccLoggingProjectSink_heredoc(name, project, bucketName string) string resource "google_logging_project_sink" "heredoc" { name = "%s" project = "%s" - destination = "storage.googleapis.com/${google_storage_bucket.log-bucket.name}" + destination = "storage.googleapis.com/${google_storage_bucket.gcs-bucket.name}" filter = <=ERROR" unique_writer_identity = true @@ -454,7 +448,7 @@ resource "google_logging_project_sink" "bigquery" { } } -resource "google_bigquery_dataset" "logging_sink" { +resource "google_bigquery_dataset" "bq_dataset" { dataset_id = "%s" description = "Log sink (generated during acc test of terraform-provider-google(-beta))." } @@ -465,13 +459,11 @@ func testAccLoggingProjectSink_bigquery_after(sinkName, bqDatasetID string) stri return fmt.Sprintf(` resource "google_logging_project_sink" "bigquery" { name = "%s" - destination = "bigquery.googleapis.com/projects/%s/datasets/${google_bigquery_dataset.logging_sink.dataset_id}" + destination = "bigquery.googleapis.com/projects/%s/datasets/${google_bigquery_dataset.bq_dataset.dataset_id}" filter = "logName=\"projects/%s/logs/compute.googleapis.com%%2Factivity_log\" AND severity>=WARNING" - - unique_writer_identity = false } -resource "google_bigquery_dataset" "logging_sink" { +resource "google_bigquery_dataset" "bq_dataset" { dataset_id = "%s" description = "Log sink (generated during acc test of terraform-provider-google(-beta))." } @@ -495,8 +487,6 @@ resource "google_logging_project_sink" "loggingbucket" { description = "test-2" filter = "resource.type = k8s_container" } - - unique_writer_identity = true } `, name, project, project) From 665f32fdaad358725d781df4bd919e22b90eaaab Mon Sep 17 00:00:00 2001 From: Charles Leon Date: Thu, 7 Sep 2023 10:01:21 -0700 Subject: [PATCH 24/67] Change several fields in Access Context Manager from list to set (#8788) Co-authored-by: Charles Leon --- .../ServicePerimeter.yaml | 16 ++ .../ServicePerimeters.yaml | 18 ++- ...text_manager_service_perimeter_test.go.erb | 102 ++++++++++++ ...ontext_manager_services_perimeters_test.go | 145 +++++++++++++++++- 4 files changed, 277 insertions(+), 4 deletions(-) diff --git a/mmv1/products/accesscontextmanager/ServicePerimeter.yaml b/mmv1/products/accesscontextmanager/ServicePerimeter.yaml index 96c2bf0b5b86..dfeb24421dbf 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeter.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeter.yaml @@ -157,6 +157,7 @@ properties: - status.0.access_levels - status.0.restricted_services item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::Array name: 'accessLevels' description: | @@ -175,6 +176,7 @@ properties: - status.0.access_levels - status.0.restricted_services item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::Array name: 'restrictedServices' description: | @@ -236,6 +238,7 @@ properties: - !ruby/object:Api::Type::Array name: 'identities' 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 @@ -275,6 +278,7 @@ properties: - !ruby/object:Api::Type::Array name: 'resources' item_type: Api::Type::String + is_set: true description: | A list of resources, currently only projects in the form `projects/`, protected by this `ServicePerimeter` @@ -348,6 +352,7 @@ properties: 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. + is_set: true item_type: Api::Type::String - !ruby/object:Api::Type::NestedObject name: 'egressTo' @@ -357,6 +362,7 @@ properties: properties: - !ruby/object:Api::Type::Array name: 'resources' + is_set: true item_type: Api::Type::String description: | A list of resources, currently only projects in the form @@ -366,6 +372,7 @@ properties: the perimeter. - !ruby/object:Api::Type::Array name: 'externalResources' + is_set: true item_type: Api::Type::String description: | A list of external resources that are allowed to be accessed. A request @@ -423,6 +430,7 @@ properties: - spec.0.access_levels - spec.0.restricted_services item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::Array name: 'accessLevels' description: | @@ -441,6 +449,7 @@ properties: - spec.0.access_levels - spec.0.restricted_services item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::Array name: 'restrictedServices' description: | @@ -454,6 +463,7 @@ properties: - spec.0.access_levels - spec.0.restricted_services item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::NestedObject name: 'vpcAccessibleServices' description: | @@ -471,6 +481,7 @@ properties: The list of APIs usable within the Service Perimeter. Must be empty unless `enableRestriction` is True. item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::Array name: 'ingressPolicies' description: | @@ -500,6 +511,7 @@ properties: - !ruby/object:Api::Type::Array name: 'identities' 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 @@ -539,6 +551,7 @@ properties: - !ruby/object:Api::Type::Array name: 'resources' item_type: Api::Type::String + is_set: true description: | A list of resources, currently only projects in the form `projects/`, protected by this `ServicePerimeter` @@ -613,6 +626,7 @@ properties: Should be in the format of email address. The email address should represent individual user or service account only. item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::NestedObject name: 'egressTo' description: | @@ -622,6 +636,7 @@ properties: - !ruby/object:Api::Type::Array name: 'resources' item_type: Api::Type::String + is_set: true description: | A list of resources, currently only projects in the form `projects/`, that match this to stanza. A request matches @@ -631,6 +646,7 @@ properties: - !ruby/object:Api::Type::Array name: 'externalResources' item_type: Api::Type::String + is_set: true description: | A list of external resources that are allowed to be accessed. A request matches if it contains an external resource in this list (Example: diff --git a/mmv1/products/accesscontextmanager/ServicePerimeters.yaml b/mmv1/products/accesscontextmanager/ServicePerimeters.yaml index 72a41e289a0d..e4fb6867a3ca 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeters.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeters.yaml @@ -57,7 +57,6 @@ properties: name: 'servicePerimeters' description: | The desired Service Perimeters that should replace all existing Service Perimeters in the Access Policy. - is_set: true item_type: !ruby/object:Api::Type::NestedObject properties: - !ruby/object:Api::Type::String @@ -133,6 +132,7 @@ properties: # - status.0.access_levels # - status.0.restricted_services item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::Array name: 'accessLevels' description: | @@ -153,6 +153,7 @@ properties: # - status.0.access_levels # - status.0.restricted_services item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::Array name: 'restrictedServices' description: | @@ -194,6 +195,7 @@ properties: have multiple `IngressPolicies`, each of which is evaluated separately. Access is granted if any `Ingress Policy` grants it. Must be empty for a perimeter bridge. + is_set: true item_type: !ruby/object:Api::Type::NestedObject properties: - !ruby/object:Api::Type::NestedObject @@ -215,6 +217,7 @@ properties: - :ANY_SERVICE_ACCOUNT - !ruby/object:Api::Type::Array name: 'identities' + is_set: true item_type: Api::Type::String description: | A list of identities that are allowed access through this ingress policy. @@ -255,6 +258,7 @@ properties: - !ruby/object:Api::Type::Array name: 'resources' item_type: Api::Type::String + is_set: true description: | A list of resources, currently only projects in the form `projects/`, protected by this `ServicePerimeter` @@ -328,6 +332,7 @@ properties: 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. + is_set: true item_type: Api::Type::String - !ruby/object:Api::Type::NestedObject name: 'egressTo' @@ -338,6 +343,7 @@ properties: - !ruby/object:Api::Type::Array name: 'resources' item_type: Api::Type::String + is_set: true description: | A list of resources, currently only projects in the form `projects/`, that match this to stanza. A request matches @@ -347,6 +353,7 @@ properties: - !ruby/object:Api::Type::Array name: 'externalResources' item_type: Api::Type::String + is_set: true description: | A list of external resources that are allowed to be accessed. A request matches if it contains an external resource in this list (Example: @@ -404,9 +411,11 @@ properties: # - spec.0.resources # - spec.0.access_levels # - spec.0.restricted_services + is_set: true item_type: Api::Type::String - !ruby/object:Api::Type::Array name: 'accessLevels' + is_set: true description: | A list of AccessLevel resource names that allow resources within the ServicePerimeter to be accessed from the internet. @@ -440,6 +449,7 @@ properties: # - spec.0.access_levels # - spec.0.restricted_services item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::NestedObject name: 'vpcAccessibleServices' description: | @@ -457,6 +467,7 @@ properties: The list of APIs usable within the Service Perimeter. Must be empty unless `enableRestriction` is True. item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::Array name: 'ingressPolicies' description: | @@ -485,6 +496,7 @@ properties: - :ANY_SERVICE_ACCOUNT - !ruby/object:Api::Type::Array name: 'identities' + is_set: true item_type: Api::Type::String description: | A list of identities that are allowed access through this ingress policy. @@ -525,6 +537,7 @@ properties: - !ruby/object:Api::Type::Array name: 'resources' item_type: Api::Type::String + is_set: true description: | A list of resources, currently only projects in the form `projects/`, protected by this `ServicePerimeter` @@ -599,6 +612,7 @@ properties: Should be in the format of email address. The email address should represent individual user or service account only. item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::NestedObject name: 'egressTo' description: | @@ -608,6 +622,7 @@ properties: - !ruby/object:Api::Type::Array name: 'resources' item_type: Api::Type::String + is_set: true description: | A list of resources, currently only projects in the form `projects/`, that match this to stanza. A request matches @@ -617,6 +632,7 @@ properties: - !ruby/object:Api::Type::Array name: 'externalResources' item_type: Api::Type::String + is_set: true description: | A list of external resources that are allowed to be accessed. A request matches if it contains an external resource in this list (Example: diff --git a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_test.go.erb b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_test.go.erb index 8e945af590f8..42849562162d 100644 --- a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_test.go.erb +++ b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_test.go.erb @@ -207,6 +207,83 @@ resource "google_access_context_manager_service_perimeter" "test-access" { name = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}/servicePerimeters/%s" title = "%s" perimeter_type = "PERIMETER_TYPE_REGULAR" + use_explicit_dry_run_spec = true + spec { + restricted_services = ["bigquery.googleapis.com", "storage.googleapis.com"] + access_levels = [google_access_context_manager_access_level.test-access.name] + + 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 + } + identity_type = "ANY_IDENTITY" + } + + ingress_to { + resources = [ "*" ] + operations { + service_name = "bigquery.googleapis.com" + + method_selectors { + method = "BigQueryStorage.ReadRows" + } + + method_selectors { + method = "TableService.ListTables" + } + + method_selectors { + permission = "bigquery.jobs.get" + } + } + + operations { + service_name = "storage.googleapis.com" + + method_selectors { + method = "google.storage.objects.create" + } + } + } + } + ingress_policies { + ingress_from { + identities = ["user:test@google.com"] + } + ingress_to { + resources = ["*"] + } + } + + egress_policies { + egress_from { + identity_type = "ANY_USER_ACCOUNT" + } + egress_to { + operations { + service_name = "bigquery.googleapis.com" + method_selectors { + permission = "externalResource.read" + } + } + external_resources = ["s3://bucket1"] + } + } + egress_policies { + egress_from { + identities = ["user:test@google.com"] + } + egress_to { + resources = ["*"] + } + } + } status { restricted_services = ["bigquery.googleapis.com", "storage.googleapis.com"] access_levels = [google_access_context_manager_access_level.test-access.name] @@ -251,11 +328,36 @@ resource "google_access_context_manager_service_perimeter" "test-access" { } } } + ingress_policies { + ingress_from { + identities = ["user:test@google.com"] + } + ingress_to { + resources = ["*"] + } + } egress_policies { egress_from { identity_type = "ANY_USER_ACCOUNT" } + egress_to { + operations { + service_name = "bigquery.googleapis.com" + method_selectors { + permission = "externalResource.read" + } + } + external_resources = ["s3://bucket1"] + } + } + egress_policies { + egress_from { + identities = ["user:test@google.com"] + } + egress_to { + resources = ["*"] + } } } } diff --git a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_services_perimeters_test.go b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_services_perimeters_test.go index d66bb2950e49..a220ea5a5e26 100644 --- a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_services_perimeters_test.go +++ b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_services_perimeters_test.go @@ -199,17 +199,156 @@ resource "google_access_context_manager_service_perimeters" "test-access" { name = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}/servicePerimeters/%s" title = "%s" perimeter_type = "PERIMETER_TYPE_REGULAR" + use_explicit_dry_run_spec = true + spec { + restricted_services = ["bigquery.googleapis.com", "storage.googleapis.com"] + access_levels = [google_access_context_manager_access_level.test-access.name] + + 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 + } + identity_type = "ANY_IDENTITY" + } + + ingress_to { + resources = [ "*" ] + operations { + service_name = "bigquery.googleapis.com" + + method_selectors { + method = "BigQueryStorage.ReadRows" + } + + method_selectors { + method = "TableService.ListTables" + } + + method_selectors { + permission = "bigquery.jobs.get" + } + } + + operations { + service_name = "storage.googleapis.com" + + method_selectors { + method = "google.storage.objects.create" + } + } + } + } + ingress_policies { + ingress_from { + identities = ["user:test@google.com"] + } + ingress_to { + resources = ["*"] + } + } + + egress_policies { + egress_from { + identity_type = "ANY_USER_ACCOUNT" + } + egress_to { + operations { + service_name = "bigquery.googleapis.com" + method_selectors { + permission = "externalResource.read" + } + } + external_resources = ["s3://bucket1"] + } + } + egress_policies { + egress_from { + identities = ["user:test@google.com"] + } + egress_to { + resources = ["*"] + } + } + } status { - restricted_services = ["bigquery.googleapis.com"] + restricted_services = ["bigquery.googleapis.com", "storage.googleapis.com"] + access_levels = [google_access_context_manager_access_level.test-access.name] + + 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 + } + identity_type = "ANY_IDENTITY" + } + + ingress_to { + resources = [ "*" ] + operations { + service_name = "bigquery.googleapis.com" + + method_selectors { + method = "BigQueryStorage.ReadRows" + } + + method_selectors { + method = "TableService.ListTables" + } + + method_selectors { + permission = "bigquery.jobs.get" + } + } + + operations { + service_name = "storage.googleapis.com" + + method_selectors { + method = "google.storage.objects.create" + } + } + } + } + ingress_policies { + ingress_from { + identities = ["user:test@google.com"] + } + ingress_to { + resources = ["*"] + } + } + egress_policies { + egress_from { + identity_type = "ANY_USER_ACCOUNT" + } egress_to { - external_resources = ["s3://bucket2"] operations { service_name = "bigquery.googleapis.com" method_selectors { - method = "*" + permission = "externalResource.read" } } + external_resources = ["s3://bucket1"] + } + } + egress_policies { + egress_from { + identities = ["user:test@google.com"] + } + egress_to { + resources = ["*"] } } } From 1a3c02a61619b69a355c2930779dedf33dd6dc28 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Thu, 7 Sep 2023 10:52:16 -0700 Subject: [PATCH 25/67] Use Create instead of Patch to create google_service_networking_connection (#8872) * Use Create instead of Patch to create google_service_networking_connection * Remove bootstraped networks for service networking connection * Use resource google_compute_network for tests * Fix tests --- mmv1/products/alloydb/Backup.yaml | 4 - mmv1/products/alloydb/Instance.yaml | 2 - .../connectionprofile.yaml | 2 - mmv1/products/looker/Instance.yaml | 1 - mmv1/products/memcache/Instance.yaml | 2 - mmv1/products/redis/Instance.yaml | 2 - .../examples/alloydb_backup_basic.tf.erb | 8 +- .../examples/alloydb_backup_full.tf.erb | 8 +- .../examples/alloydb_instance_basic.tf.erb | 8 +- ..._service_connection_profile_alloydb.tf.erb | 8 +- .../looker_instance_enterprise_full.tf.erb | 8 +- .../examples/memcache_instance_basic.tf.erb | 6 +- .../redis_instance_private_service.tf.erb | 8 +- .../alloydb/resource_alloydb_backup_test.go | 33 +++---- .../resource_alloydb_cluster_restore_test.go | 88 +++++++++---------- .../alloydb/resource_alloydb_instance_test.go | 61 ++++++------- ...esource_cloudbuild_worker_pool_test.go.erb | 10 +-- .../resource_cloudids_endpoint_test.go | 18 ++-- .../resource_memcache_instance_test.go | 14 +-- .../resource_service_networking_connection.go | 19 +--- .../resource_sql_database_instance_test.go | 54 ++++++------ 21 files changed, 171 insertions(+), 193 deletions(-) diff --git a/mmv1/products/alloydb/Backup.yaml b/mmv1/products/alloydb/Backup.yaml index 3d4ac4cbf1c8..36a9f4339914 100644 --- a/mmv1/products/alloydb/Backup.yaml +++ b/mmv1/products/alloydb/Backup.yaml @@ -42,8 +42,6 @@ examples: alloydb_cluster_name: 'alloydb-cluster' alloydb_instance_name: 'alloydb-instance' network_name: 'alloydb-network' - test_vars_overrides: - network_name: 'acctest.BootstrapSharedTestNetwork(t, "alloydb-backup-basic")' ignore_read_extra: - 'reconciling' - 'update_time' @@ -55,8 +53,6 @@ examples: alloydb_cluster_name: 'alloydb-cluster' alloydb_instance_name: 'alloydb-instance' network_name: 'alloydb-network' - test_vars_overrides: - network_name: 'acctest.BootstrapSharedTestNetwork(t, "alloydb-backup-full")' ignore_read_extra: - 'reconciling' - 'update_time' diff --git a/mmv1/products/alloydb/Instance.yaml b/mmv1/products/alloydb/Instance.yaml index a8929b3965c7..5530c7434fa0 100644 --- a/mmv1/products/alloydb/Instance.yaml +++ b/mmv1/products/alloydb/Instance.yaml @@ -57,8 +57,6 @@ examples: alloydb_cluster_name: 'alloydb-cluster' alloydb_instance_name: 'alloydb-instance' network_name: 'alloydb-network' - test_vars_overrides: - network_name: 'acctest.BootstrapSharedTestNetwork(t, "alloydb-instance-basic")' ignore_read_extra: - 'reconciling' - 'update_time' diff --git a/mmv1/products/databasemigrationservice/connectionprofile.yaml b/mmv1/products/databasemigrationservice/connectionprofile.yaml index 3396127ae17b..62e6fc778024 100644 --- a/mmv1/products/databasemigrationservice/connectionprofile.yaml +++ b/mmv1/products/databasemigrationservice/connectionprofile.yaml @@ -87,8 +87,6 @@ examples: profile: 'my-profileid' global_address_name: 'private-ip-alloc' network_name: 'vpc-network' - test_vars_overrides: - network_name: 'acctest.BootstrapSharedTestNetwork(t, "profile-alloydb")' parameters: - !ruby/object:Api::Type::String name: 'connectionProfileId' diff --git a/mmv1/products/looker/Instance.yaml b/mmv1/products/looker/Instance.yaml index 7e645702f776..b830b54c7ac8 100644 --- a/mmv1/products/looker/Instance.yaml +++ b/mmv1/products/looker/Instance.yaml @@ -57,7 +57,6 @@ examples: client_id: 'my-client-id' client_secret: 'my-client-secret' test_vars_overrides: - network_name: 'acctest.BootstrapSharedTestNetwork(t, "looker-instance-enterprise")' kms_key_name: 'acctest.BootstrapKMSKeyInLocation(t, "us-central1").CryptoKey.Name' parameters: - !ruby/object:Api::Type::String diff --git a/mmv1/products/memcache/Instance.yaml b/mmv1/products/memcache/Instance.yaml index 11637e7d1cd4..a3dd514aa13f 100644 --- a/mmv1/products/memcache/Instance.yaml +++ b/mmv1/products/memcache/Instance.yaml @@ -37,8 +37,6 @@ examples: instance_name: 'test-instance' network_name: 'test-network' address_name: 'address' - test_vars_overrides: - network_name: 'acctest.BootstrapSharedTestNetwork(t, "memcache-instance-basic")' parameters: - !ruby/object:Api::Type::String name: 'region' diff --git a/mmv1/products/redis/Instance.yaml b/mmv1/products/redis/Instance.yaml index b232ae4e69bd..e49c6e3ee36c 100644 --- a/mmv1/products/redis/Instance.yaml +++ b/mmv1/products/redis/Instance.yaml @@ -67,8 +67,6 @@ examples: instance_name: 'private-cache' address_name: 'address' network_name: 'redis-test-network' - test_vars_overrides: - network_name: 'acctest.BootstrapSharedTestNetwork(t, "redis-private-service")' - !ruby/object:Provider::Terraform::Examples name: 'redis_instance_mrr' primary_resource_id: 'cache' diff --git a/mmv1/templates/terraform/examples/alloydb_backup_basic.tf.erb b/mmv1/templates/terraform/examples/alloydb_backup_basic.tf.erb index 418ccb67c8ed..41521891bfec 100644 --- a/mmv1/templates/terraform/examples/alloydb_backup_basic.tf.erb +++ b/mmv1/templates/terraform/examples/alloydb_backup_basic.tf.erb @@ -9,7 +9,7 @@ resource "google_alloydb_backup" "<%= ctx[:primary_resource_id] %>" { resource "google_alloydb_cluster" "<%= ctx[:primary_resource_id] %>" { cluster_id = "<%= ctx[:vars]['alloydb_cluster_name'] %>" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_alloydb_instance" "<%= ctx[:primary_resource_id] %>" { @@ -25,15 +25,15 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "<%= ctx[:vars]['network_name'] %>" } diff --git a/mmv1/templates/terraform/examples/alloydb_backup_full.tf.erb b/mmv1/templates/terraform/examples/alloydb_backup_full.tf.erb index bb280b783894..cb4e7b45bfde 100644 --- a/mmv1/templates/terraform/examples/alloydb_backup_full.tf.erb +++ b/mmv1/templates/terraform/examples/alloydb_backup_full.tf.erb @@ -13,7 +13,7 @@ resource "google_alloydb_backup" "<%= ctx[:primary_resource_id] %>" { resource "google_alloydb_cluster" "<%= ctx[:primary_resource_id] %>" { cluster_id = "<%= ctx[:vars]['alloydb_cluster_name'] %>" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_alloydb_instance" "<%= ctx[:primary_resource_id] %>" { @@ -29,15 +29,15 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "<%= ctx[:vars]['network_name'] %>" } diff --git a/mmv1/templates/terraform/examples/alloydb_instance_basic.tf.erb b/mmv1/templates/terraform/examples/alloydb_instance_basic.tf.erb index f6907cd44237..479245a01cb2 100644 --- a/mmv1/templates/terraform/examples/alloydb_instance_basic.tf.erb +++ b/mmv1/templates/terraform/examples/alloydb_instance_basic.tf.erb @@ -13,7 +13,7 @@ resource "google_alloydb_instance" "<%= ctx[:primary_resource_id] %>" { resource "google_alloydb_cluster" "<%= ctx[:primary_resource_id] %>" { cluster_id = "<%= ctx[:vars]['alloydb_cluster_name'] %>" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id initial_user { password = "<%= ctx[:vars]['alloydb_cluster_name'] %>" @@ -22,7 +22,7 @@ resource "google_alloydb_cluster" "<%= ctx[:primary_resource_id] %>" { data "google_project" "project" {} -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "<%= ctx[:vars]['network_name'] %>" } @@ -31,11 +31,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/database_migration_service_connection_profile_alloydb.tf.erb b/mmv1/templates/terraform/examples/database_migration_service_connection_profile_alloydb.tf.erb index 68a6ea686b57..96384e6e4b58 100644 --- a/mmv1/templates/terraform/examples/database_migration_service_connection_profile_alloydb.tf.erb +++ b/mmv1/templates/terraform/examples/database_migration_service_connection_profile_alloydb.tf.erb @@ -1,7 +1,7 @@ data "google_project" "project" { } -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "<%= ctx[:vars]['network_name'] %>" } @@ -10,11 +10,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } @@ -34,7 +34,7 @@ resource "google_database_migration_service_connection_profile" "<%= ctx[:primar user = "alloyuser%{random_suffix}" password = "alloypass%{random_suffix}" } - vpc_network = data.google_compute_network.default.id + vpc_network = google_compute_network.default.id labels = { alloyfoo = "alloybar" } diff --git a/mmv1/templates/terraform/examples/looker_instance_enterprise_full.tf.erb b/mmv1/templates/terraform/examples/looker_instance_enterprise_full.tf.erb index 5a223f1e21db..54d74ad63d8e 100644 --- a/mmv1/templates/terraform/examples/looker_instance_enterprise_full.tf.erb +++ b/mmv1/templates/terraform/examples/looker_instance_enterprise_full.tf.erb @@ -5,7 +5,7 @@ resource "google_looker_instance" "<%= ctx[:primary_resource_id] %>" { private_ip_enabled = true public_ip_enabled = false reserved_range = "${google_compute_global_address.looker_range.name}" - consumer_network = data.google_compute_network.looker_network.id + consumer_network = google_compute_network.looker_network.id admin_settings { allowed_email_domains = ["google.com"] } @@ -49,7 +49,7 @@ resource "google_looker_instance" "<%= ctx[:primary_resource_id] %>" { } resource "google_service_networking_connection" "looker_vpc_connection" { - network = data.google_compute_network.looker_network.id + network = google_compute_network.looker_network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.looker_range.name] } @@ -59,12 +59,12 @@ resource "google_compute_global_address" "looker_range" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 20 - network = data.google_compute_network.looker_network.id + network = google_compute_network.looker_network.id } data "google_project" "project" {} -data "google_compute_network" "looker_network" { +resource "google_compute_network" "looker_network" { name = "<%= ctx[:vars]["network_name"] %>" } diff --git a/mmv1/templates/terraform/examples/memcache_instance_basic.tf.erb b/mmv1/templates/terraform/examples/memcache_instance_basic.tf.erb index e021bacf3d63..0ad8d19378fd 100644 --- a/mmv1/templates/terraform/examples/memcache_instance_basic.tf.erb +++ b/mmv1/templates/terraform/examples/memcache_instance_basic.tf.erb @@ -6,7 +6,7 @@ // If this network hasn't been created and you are using this example in your // config, add an additional network resource or change // this from "data"to "resource" -data "google_compute_network" "memcache_network" { +resource "google_compute_network" "memcache_network" { name = "<%= ctx[:vars]['network_name'] %>" } @@ -15,11 +15,11 @@ resource "google_compute_global_address" "service_range" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = data.google_compute_network.memcache_network.id + network = google_compute_network.memcache_network.id } resource "google_service_networking_connection" "private_service_connection" { - network = data.google_compute_network.memcache_network.id + network = google_compute_network.memcache_network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.service_range.name] } diff --git a/mmv1/templates/terraform/examples/redis_instance_private_service.tf.erb b/mmv1/templates/terraform/examples/redis_instance_private_service.tf.erb index 800df78e22aa..90e0e4ff5698 100644 --- a/mmv1/templates/terraform/examples/redis_instance_private_service.tf.erb +++ b/mmv1/templates/terraform/examples/redis_instance_private_service.tf.erb @@ -6,7 +6,7 @@ // If this network hasn't been created and you are using this example in your // config, add an additional network resource or change // this from "data"to "resource" -data "google_compute_network" "redis-network" { +resource "google_compute_network" "redis-network" { name = "<%= ctx[:vars]['network_name'] %>" } @@ -15,11 +15,11 @@ resource "google_compute_global_address" "service_range" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = data.google_compute_network.redis-network.id + network = google_compute_network.redis-network.id } resource "google_service_networking_connection" "private_service_connection" { - network = data.google_compute_network.redis-network.id + network = google_compute_network.redis-network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.service_range.name] } @@ -32,7 +32,7 @@ resource "google_redis_instance" "<%= ctx[:primary_resource_id] %>" { location_id = "us-central1-a" alternative_location_id = "us-central1-f" - authorized_network = data.google_compute_network.redis-network.id + authorized_network = google_compute_network.redis-network.id connect_mode = "PRIVATE_SERVICE_ACCESS" redis_version = "REDIS_4_0" diff --git a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_backup_test.go b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_backup_test.go index 4da0e5c86fa7..33091f142314 100644 --- a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_backup_test.go +++ b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_backup_test.go @@ -10,9 +10,10 @@ import ( func TestAccAlloydbBackup_update(t *testing.T) { t.Parallel() + random_suffix := acctest.RandString(t, 10) context := map[string]interface{}{ - "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydb-backup-update"), - "random_suffix": acctest.RandString(t, 10), + "network_name": "tf-test-alloydb-network" + random_suffix, + "random_suffix": random_suffix, } acctest.VcrTest(t, resource.TestCase{ @@ -61,7 +62,7 @@ resource "google_alloydb_backup" "default" { resource "google_alloydb_cluster" "default" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_alloydb_instance" "default" { @@ -77,16 +78,16 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "%{network_name}" } `, context) @@ -98,7 +99,7 @@ func TestAccAlloydbBackup_createBackupWithMandatoryFields(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), - "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydbbackup-mandatory"), + "network_name": "tf-test-" + acctest.RandString(t, 10), } acctest.VcrTest(t, resource.TestCase{ @@ -125,12 +126,12 @@ resource "google_alloydb_backup" "default" { resource "google_alloydb_cluster" "default" { location = "us-central1" cluster_id = "tf-test-alloydb-cluster%{random_suffix}" - network = data.google_compute_network.default.id + network = google_compute_network.default.id } data "google_project" "project" { } -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "%{network_name}" } @@ -147,7 +148,7 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id lifecycle { ignore_changes = [ address, @@ -161,7 +162,7 @@ resource "google_compute_global_address" "private_ip_alloc" { } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } @@ -172,7 +173,7 @@ func TestAccAlloydbBackup_usingCMEK(t *testing.T) { t.Parallel() context := map[string]interface{}{ - "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydb-backup-cmek"), + "network_name": "tf-test-" + acctest.RandString(t, 10), "random_suffix": acctest.RandString(t, 10), "key_name": "tf-test-key-" + acctest.RandString(t, 10), } @@ -215,7 +216,7 @@ resource "google_alloydb_backup" "default" { resource "google_alloydb_cluster" "default" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_alloydb_instance" "default" { @@ -231,16 +232,16 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "%{network_name}" } data "google_project" "project" {} diff --git a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_restore_test.go b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_restore_test.go index d6def69f6832..9e3d209581e0 100644 --- a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_restore_test.go +++ b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_restore_test.go @@ -19,7 +19,7 @@ func TestAccAlloydbCluster_restore(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), - "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydbinstance-restore"), + "network_name": "tf-test-" + acctest.RandString(t, 10), } acctest.VcrTest(t, resource.TestCase{ @@ -86,7 +86,7 @@ func testAccAlloydbClusterAndInstanceAndBackup(context map[string]interface{}) s resource "google_alloydb_cluster" "source" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_alloydb_instance" "source" { @@ -107,7 +107,7 @@ resource "google_alloydb_backup" "default" { data "google_project" "project" {} -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "%{network_name}" } @@ -116,11 +116,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } @@ -133,7 +133,7 @@ func testAccAlloydbClusterAndInstanceAndBackup_OnlyOneSourceAllowed(context map[ resource "google_alloydb_cluster" "source" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_alloydb_instance" "source" { @@ -155,7 +155,7 @@ resource "google_alloydb_backup" "default" { resource "google_alloydb_cluster" "restored" { cluster_id = "tf-test-alloydb-backup-restored-cluster-%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id restore_backup_source { backup_name = google_alloydb_backup.default.name } @@ -171,7 +171,7 @@ resource "google_alloydb_cluster" "restored" { data "google_project" "project" {} -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "%{network_name}" } @@ -180,11 +180,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } @@ -197,7 +197,7 @@ func testAccAlloydbClusterAndInstanceAndBackup_SourceClusterAndPointInTimeRequir resource "google_alloydb_cluster" "source" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_alloydb_instance" "source" { @@ -219,7 +219,7 @@ resource "google_alloydb_backup" "default" { resource "google_alloydb_cluster" "restored" { cluster_id = "tf-test-alloydb-backup-restored-cluster-%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id restore_continuous_backup_source { cluster = google_alloydb_cluster.source.name @@ -232,7 +232,7 @@ resource "google_alloydb_cluster" "restored" { data "google_project" "project" {} -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "%{network_name}" } @@ -241,11 +241,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } @@ -257,7 +257,7 @@ func testAccAlloydbClusterAndInstanceAndBackup_RestoredFromBackup(context map[st resource "google_alloydb_cluster" "source" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_alloydb_instance" "source" { @@ -279,7 +279,7 @@ resource "google_alloydb_backup" "default" { resource "google_alloydb_cluster" "restored_from_backup" { cluster_id = "tf-test-alloydb-backup-restored-cluster-%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id restore_backup_source { backup_name = google_alloydb_backup.default.name } @@ -291,7 +291,7 @@ resource "google_alloydb_cluster" "restored_from_backup" { data "google_project" "project" {} -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "%{network_name}" } @@ -300,11 +300,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } @@ -318,7 +318,7 @@ func testAccAlloydbClusterAndInstanceAndBackup_RestoredFromBackupAndRestoredFrom resource "google_alloydb_cluster" "source" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_alloydb_instance" "source" { @@ -340,7 +340,7 @@ resource "google_alloydb_backup" "default" { resource "google_alloydb_cluster" "restored_from_backup" { cluster_id = "tf-test-alloydb-backup-restored-cluster-%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id restore_backup_source { backup_name = google_alloydb_backup.default.name } @@ -353,7 +353,7 @@ resource "google_alloydb_cluster" "restored_from_backup" { resource "google_alloydb_cluster" "restored_from_point_in_time" { cluster_id = "tf-test-alloydb-pitr-restored-cluster-%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id restore_continuous_backup_source { cluster = google_alloydb_cluster.source.name point_in_time = google_alloydb_backup.default.update_time @@ -366,7 +366,7 @@ resource "google_alloydb_cluster" "restored_from_point_in_time" { data "google_project" "project" {} -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "%{network_name}" } @@ -375,11 +375,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } @@ -393,7 +393,7 @@ func testAccAlloydbClusterAndInstanceAndBackup_RestoredFromBackupAndRestoredFrom resource "google_alloydb_cluster" "source" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_alloydb_instance" "source" { @@ -415,7 +415,7 @@ resource "google_alloydb_backup" "default" { resource "google_alloydb_cluster" "restored_from_backup" { cluster_id = "tf-test-alloydb-backup-restored-cluster-%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id restore_backup_source { backup_name = google_alloydb_backup.default.name } @@ -433,7 +433,7 @@ resource "google_alloydb_cluster" "restored_from_backup" { resource "google_alloydb_cluster" "restored_from_point_in_time" { cluster_id = "tf-test-alloydb-pitr-restored-cluster-%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id restore_continuous_backup_source { cluster = google_alloydb_cluster.source.name point_in_time = google_alloydb_backup.default.update_time @@ -451,7 +451,7 @@ resource "google_alloydb_cluster" "restored_from_point_in_time" { data "google_project" "project" {} -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "%{network_name}" } @@ -460,11 +460,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } @@ -478,7 +478,7 @@ func testAccAlloydbClusterAndInstanceAndBackup_RestoredFromBackupAndRestoredFrom resource "google_alloydb_cluster" "source" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_alloydb_instance" "source" { @@ -508,7 +508,7 @@ resource "google_alloydb_backup" "default2" { resource "google_alloydb_cluster" "restored_from_backup" { cluster_id = "tf-test-alloydb-backup-restored-cluster-%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id restore_backup_source { backup_name = google_alloydb_backup.default2.name } @@ -528,7 +528,7 @@ resource "google_alloydb_cluster" "restored_from_backup" { resource "google_alloydb_cluster" "restored_from_point_in_time" { cluster_id = "tf-test-alloydb-pitr-restored-cluster-%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id restore_continuous_backup_source { cluster = google_alloydb_cluster.restored_from_backup.name point_in_time = google_alloydb_backup.default.update_time @@ -546,7 +546,7 @@ resource "google_alloydb_cluster" "restored_from_point_in_time" { data "google_project" "project" {} -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "%{network_name}" } @@ -555,11 +555,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } @@ -573,7 +573,7 @@ func testAccAlloydbClusterAndInstanceAndBackup_RestoredFromBackupAndRestoredFrom resource "google_alloydb_cluster" "source" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_alloydb_instance" "source" { @@ -595,7 +595,7 @@ resource "google_alloydb_backup" "default" { resource "google_alloydb_cluster" "restored_from_backup" { cluster_id = "tf-test-alloydb-backup-restored-cluster-%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id restore_backup_source { backup_name = google_alloydb_backup.default.name } @@ -604,7 +604,7 @@ resource "google_alloydb_cluster" "restored_from_backup" { resource "google_alloydb_cluster" "restored_from_point_in_time" { cluster_id = "tf-test-alloydb-pitr-restored-cluster-%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id restore_continuous_backup_source { cluster = google_alloydb_cluster.source.name point_in_time = google_alloydb_backup.default.update_time @@ -613,7 +613,7 @@ resource "google_alloydb_cluster" "restored_from_point_in_time" { data "google_project" "project" {} -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "%{network_name}" } @@ -622,11 +622,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } diff --git a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_instance_test.go b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_instance_test.go index 944d04c25ad1..824bab8b12f0 100644 --- a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_instance_test.go +++ b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_instance_test.go @@ -10,9 +10,10 @@ import ( func TestAccAlloydbInstance_update(t *testing.T) { t.Parallel() + random_suffix := acctest.RandString(t, 10) context := map[string]interface{}{ - "random_suffix": acctest.RandString(t, 10), - "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydbinstance-update"), + "random_suffix": random_suffix, + "network_name": "tf-test-alloydb-network" + random_suffix, } acctest.VcrTest(t, resource.TestCase{ @@ -63,7 +64,7 @@ resource "google_alloydb_instance" "default" { resource "google_alloydb_cluster" "default" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id initial_user { password = "tf-test-alloydb-cluster%{random_suffix}" @@ -73,7 +74,7 @@ resource "google_alloydb_cluster" "default" { data "google_project" "project" { } -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "%{network_name}" } @@ -82,11 +83,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } @@ -99,7 +100,7 @@ func TestAccAlloydbInstance_createInstanceWithMandatoryFields(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), - "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydbinstance-mandatory"), + "network_name": "tf-test-" + acctest.RandString(t, 10), } acctest.VcrTest(t, resource.TestCase{ @@ -127,12 +128,12 @@ resource "google_alloydb_instance" "default" { resource "google_alloydb_cluster" "default" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id } data "google_project" "project" {} -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "%{network_name}" } @@ -141,11 +142,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } @@ -158,7 +159,7 @@ func TestAccAlloydbInstance_createInstanceWithMaximumFields(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), - "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydbinstance-maximum"), + "network_name": "tf-test-" + acctest.RandString(t, 10), } acctest.VcrTest(t, resource.TestCase{ @@ -205,12 +206,12 @@ resource "google_alloydb_instance" "default" { resource "google_alloydb_cluster" "default" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id } data "google_project" "project" {} -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "%{network_name}" } @@ -219,11 +220,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } @@ -236,7 +237,7 @@ func TestAccAlloydbInstance_createPrimaryAndReadPoolInstance(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), - "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydbinstance-readpool"), + "network_name": "tf-test-" + acctest.RandString(t, 10), } acctest.VcrTest(t, resource.TestCase{ @@ -273,12 +274,12 @@ resource "google_alloydb_instance" "read_pool" { resource "google_alloydb_cluster" "default" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id } data "google_project" "project" {} -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "%{network_name}" } @@ -287,11 +288,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } @@ -304,7 +305,7 @@ func TestAccAlloydbInstance_updateDatabaseFlagInPrimaryInstance(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), - "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydbinstance-updatedb"), + "network_name": "tf-test-" + acctest.RandString(t, 10), } acctest.VcrTest(t, resource.TestCase{ @@ -342,12 +343,12 @@ resource "google_alloydb_instance" "primary" { resource "google_alloydb_cluster" "default" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id } data "google_project" "project" {} -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "%{network_name}" } @@ -356,11 +357,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } @@ -382,12 +383,12 @@ resource "google_alloydb_instance" "primary" { resource "google_alloydb_cluster" "default" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id } data "google_project" "project" {} -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "%{network_name}" } @@ -396,11 +397,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } 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 601dc86d27d9..6cc7a87dd96c 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 @@ -104,7 +104,7 @@ func TestAccCloudbuildWorkerPool_withNetwork(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), "project": envvar.GetTestProjectFromEnv(), - "network_name": acctest.BootstrapSharedTestNetwork(t, "cloudbuild-workerpool"), + "network_name": "tf-test-" + acctest.RandString(t, 10), } acctest.VcrTest(t, resource.TestCase{ @@ -127,7 +127,7 @@ func TestAccCloudbuildWorkerPool_withNetwork(t *testing.T) { func testAccCloudbuildWorkerPool_withNetwork(context map[string]interface{}) string { return acctest.Nprintf(` -data "google_compute_network" "network" { +resource "google_compute_network" "network" { name = "%{network_name}" } @@ -136,11 +136,11 @@ resource "google_compute_global_address" "worker_range" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = data.google_compute_network.network.id + network = google_compute_network.network.id } resource "google_service_networking_connection" "worker_pool_conn" { - network = data.google_compute_network.network.id + network = google_compute_network.network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.worker_range.name] } @@ -154,7 +154,7 @@ resource "google_cloudbuild_worker_pool" "pool" { no_external_ip = false } network_config { - peered_network = data.google_compute_network.network.id + peered_network = google_compute_network.network.id peered_network_ip_range = "/29" } depends_on = [google_service_networking_connection.worker_pool_conn] diff --git a/mmv1/third_party/terraform/services/cloudids/resource_cloudids_endpoint_test.go b/mmv1/third_party/terraform/services/cloudids/resource_cloudids_endpoint_test.go index 65153dada11c..3e6f8a626c90 100644 --- a/mmv1/third_party/terraform/services/cloudids/resource_cloudids_endpoint_test.go +++ b/mmv1/third_party/terraform/services/cloudids/resource_cloudids_endpoint_test.go @@ -18,7 +18,7 @@ func TestAccCloudIdsEndpoint_basic(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), - "network_name": acctest.BootstrapSharedTestNetwork(t, "cloud-ids-endpoint"), + "network_name": "tf-test-key-" + acctest.RandString(t, 10), } acctest.VcrTest(t, resource.TestCase{ @@ -48,7 +48,7 @@ func TestAccCloudIdsEndpoint_basic(t *testing.T) { func testCloudIds_basic(context map[string]interface{}) string { return acctest.Nprintf(` -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "%{network_name}" } resource "google_compute_global_address" "service_range" { @@ -56,10 +56,10 @@ resource "google_compute_global_address" "service_range" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "private_service_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.service_range.name] } @@ -67,7 +67,7 @@ resource "google_service_networking_connection" "private_service_connection" { resource "google_cloud_ids_endpoint" "endpoint" { name = "cloud-ids-test-%{random_suffix}" location = "us-central1-f" - network = data.google_compute_network.default.id + network = google_compute_network.default.id severity = "INFORMATIONAL" threat_exceptions = ["12", "67"] depends_on = [google_service_networking_connection.private_service_connection] @@ -77,7 +77,7 @@ resource "google_cloud_ids_endpoint" "endpoint" { func testCloudIds_basicUpdate(context map[string]interface{}) string { return acctest.Nprintf(` -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "%{network_name}" } resource "google_compute_global_address" "service_range" { @@ -85,10 +85,10 @@ resource "google_compute_global_address" "service_range" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "private_service_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.service_range.name] } @@ -96,7 +96,7 @@ resource "google_service_networking_connection" "private_service_connection" { resource "google_cloud_ids_endpoint" "endpoint" { name = "cloud-ids-test-%{random_suffix}" location = "us-central1-f" - network = data.google_compute_network.default.id + network = google_compute_network.default.id severity = "INFORMATIONAL" threat_exceptions = ["33"] depends_on = [google_service_networking_connection.private_service_connection] diff --git a/mmv1/third_party/terraform/services/memcache/resource_memcache_instance_test.go b/mmv1/third_party/terraform/services/memcache/resource_memcache_instance_test.go index 51b78686511e..7c42f5632e91 100644 --- a/mmv1/third_party/terraform/services/memcache/resource_memcache_instance_test.go +++ b/mmv1/third_party/terraform/services/memcache/resource_memcache_instance_test.go @@ -13,7 +13,7 @@ func TestAccMemcacheInstance_update(t *testing.T) { prefix := fmt.Sprintf("%d", acctest.RandInt(t)) name := fmt.Sprintf("tf-test-%s", prefix) - network := acctest.BootstrapSharedTestNetwork(t, "memcache-instance-update") + network := "tf-test-" + acctest.RandString(t, 10) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -47,11 +47,11 @@ resource "google_compute_global_address" "service_range" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = data.google_compute_network.memcache_network.id + network = google_compute_network.memcache_network.id } resource "google_service_networking_connection" "private_service_connection" { - network = data.google_compute_network.memcache_network.id + network = google_compute_network.memcache_network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.service_range.name] } @@ -75,7 +75,7 @@ resource "google_memcache_instance" "test" { } } -data "google_compute_network" "memcache_network" { +resource "google_compute_network" "memcache_network" { name = "%s" } `, prefix, name, network) @@ -88,11 +88,11 @@ resource "google_compute_global_address" "service_range" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = data.google_compute_network.memcache_network.id + network = google_compute_network.memcache_network.id } resource "google_service_networking_connection" "private_service_connection" { - network = data.google_compute_network.memcache_network.id + network = google_compute_network.memcache_network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.service_range.name] } @@ -116,7 +116,7 @@ resource "google_memcache_instance" "test" { } } -data "google_compute_network" "memcache_network" { +resource "google_compute_network" "memcache_network" { name = "%s" } `, prefix, name, network) diff --git a/mmv1/third_party/terraform/services/servicenetworking/resource_service_networking_connection.go b/mmv1/third_party/terraform/services/servicenetworking/resource_service_networking_connection.go index ac1ff4a07912..249b268ba58f 100644 --- a/mmv1/third_party/terraform/services/servicenetworking/resource_service_networking_connection.go +++ b/mmv1/third_party/terraform/services/servicenetworking/resource_service_networking_connection.go @@ -94,27 +94,16 @@ func resourceServiceNetworkingConnectionCreate(d *schema.ResourceData, meta inte project := networkFieldValue.Project parentService := formatParentService(d.Get("service").(string)) - // We use Patch instead of Create, because we're getting - // "Error waiting for Create Service Networking Connection: - // Error code 9, message: Cannot modify allocated ranges in - // CreateConnection. Please use UpdateConnection." - // if we're creating peerings to more than one VPC (like two - // CloudSQL instances within one project, peered with two - // clusters.) - // - // This is a workaround for: - // https://issuetracker.google.com/issues/131908322 - // - // The API docs don't specify that you can do connections/-, - // but that's what gcloud does, and it's easier than grabbing - // the connection name. + + // There is no blocker to use Create method, as the bug in CloudSQL has been fixed (https://b.corp.google.com/issues/123276199). + // Read more in https://stackoverflow.com/questions/55135559/unable-to-recreate-private-service-access-on-gcp // err == nil indicates that the billing_project value was found if bp, err := tpgresource.GetBillingProject(d, config); err == nil { project = bp } - createCall := config.NewServiceNetworkingClient(userAgent).Services.Connections.Patch(parentService+"/connections/-", connection).UpdateMask("reservedPeeringRanges").Force(true) + createCall := config.NewServiceNetworkingClient(userAgent).Services.Connections.Create(parentService, connection) if config.UserProjectOverride { createCall.Header().Add("X-Goog-User-Project", project) } diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go index 64607beb5cb0..fa295d443061 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go @@ -179,7 +179,7 @@ func TestAccSqlDatabaseInstance_deleteDefaultUserBeforeSubsequentApiCalls(t *tes databaseName := "tf-test-" + acctest.RandString(t, 10) addressName := "tf-test-" + acctest.RandString(t, 10) - networkName := acctest.BootstrapSharedTestNetwork(t, "sql-instance-private-network-clone-2") + networkName := "tf-test-" + acctest.RandString(t, 10) // 1. Create an instance. // 2. Add a root@'%' user. @@ -737,7 +737,7 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(t *te databaseName := "tf-test-" + acctest.RandString(t, 10) addressName := "tf-test-" + acctest.RandString(t, 10) - networkName := acctest.BootstrapSharedTestNetwork(t, "sql-instance-private-network") + networkName := "tf-test-" + acctest.RandString(t, 10) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -970,9 +970,9 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRange(t *testi databaseName := "tf-test-" + acctest.RandString(t, 10) addressName := "tf-test-" + acctest.RandString(t, 10) - networkName := acctest.BootstrapSharedTestNetwork(t, "sql-instance-private-network-allocated") + networkName := "tf-test-" + acctest.RandString(t, 10) addressName_update := "tf-test-" + acctest.RandString(t, 10) + "update" - networkName_update := acctest.BootstrapSharedTestNetwork(t, "sql-instance-private-network-allocated-update") + networkName_update := "tf-test-" + acctest.RandString(t, 10) + "update" acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -1007,7 +1007,7 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRangeReplica(t databaseName := "tf-test-" + acctest.RandString(t, 10) addressName := "tf-test-" + acctest.RandString(t, 10) - networkName := acctest.BootstrapSharedTestNetwork(t, "sql-instance-private-network-replica") + networkName := "tf-test-" + acctest.RandString(t, 10) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -1039,7 +1039,7 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRangeClone(t * databaseName := "tf-test-" + acctest.RandString(t, 10) addressName := "tf-test-" + acctest.RandString(t, 10) - networkName := acctest.BootstrapSharedTestNetwork(t, "sql-instance-private-network-clone") + networkName := "tf-test-" + acctest.RandString(t, 10) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -2798,7 +2798,7 @@ func testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(datab } return fmt.Sprintf(` -data "google_compute_network" "servicenet" { +resource "google_compute_network" "servicenet" { name = "%s" } @@ -2807,11 +2807,11 @@ resource "google_compute_global_address" "foobar" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = data.google_compute_network.servicenet.self_link + network = google_compute_network.servicenet.self_link } resource "google_service_networking_connection" "foobar" { - network = data.google_compute_network.servicenet.self_link + network = google_compute_network.servicenet.self_link service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.foobar.name] } @@ -2826,7 +2826,7 @@ resource "google_sql_database_instance" "instance" { tier = "db-f1-micro" ip_configuration { ipv4_enabled = "false" - private_network = data.google_compute_network.servicenet.self_link + private_network = google_compute_network.servicenet.self_link %s } } @@ -2836,7 +2836,7 @@ resource "google_sql_database_instance" "instance" { func testAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRange(databaseName, networkName, addressRangeName string) string { return fmt.Sprintf(` -data "google_compute_network" "servicenet" { +resource "google_compute_network" "servicenet" { name = "%s" } @@ -2845,11 +2845,11 @@ resource "google_compute_global_address" "foobar" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = data.google_compute_network.servicenet.self_link + network = google_compute_network.servicenet.self_link } resource "google_service_networking_connection" "foobar" { - network = data.google_compute_network.servicenet.self_link + network = google_compute_network.servicenet.self_link service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.foobar.name] } @@ -2864,7 +2864,7 @@ resource "google_sql_database_instance" "instance" { tier = "db-f1-micro" ip_configuration { ipv4_enabled = "false" - private_network = data.google_compute_network.servicenet.self_link + private_network = google_compute_network.servicenet.self_link allocated_ip_range = google_compute_global_address.foobar.name } } @@ -2874,7 +2874,7 @@ resource "google_sql_database_instance" "instance" { func testAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRangeReplica(databaseName, networkName, addressRangeName string) string { return fmt.Sprintf(` -data "google_compute_network" "servicenet" { +resource "google_compute_network" "servicenet" { name = "%s" } @@ -2883,11 +2883,11 @@ resource "google_compute_global_address" "foobar" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = data.google_compute_network.servicenet.self_link + network = google_compute_network.servicenet.self_link } resource "google_service_networking_connection" "foobar" { - network = data.google_compute_network.servicenet.self_link + network = google_compute_network.servicenet.self_link service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.foobar.name] } @@ -2902,7 +2902,7 @@ resource "google_sql_database_instance" "instance" { tier = "db-f1-micro" ip_configuration { ipv4_enabled = "false" - private_network = data.google_compute_network.servicenet.self_link + private_network = google_compute_network.servicenet.self_link } backup_configuration { enabled = true @@ -2921,7 +2921,7 @@ resource "google_sql_database_instance" "replica1" { tier = "db-f1-micro" ip_configuration { ipv4_enabled = "false" - private_network = data.google_compute_network.servicenet.self_link + private_network = google_compute_network.servicenet.self_link allocated_ip_range = google_compute_global_address.foobar.name } } @@ -2942,7 +2942,7 @@ resource "google_sql_database_instance" "replica1" { func testAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRangeClone(databaseName, networkName, addressRangeName string) string { return fmt.Sprintf(` -data "google_compute_network" "servicenet" { +resource "google_compute_network" "servicenet" { name = "%s" } @@ -2951,11 +2951,11 @@ resource "google_compute_global_address" "foobar" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = data.google_compute_network.servicenet.self_link + network = google_compute_network.servicenet.self_link } resource "google_service_networking_connection" "foobar" { - network = data.google_compute_network.servicenet.self_link + network = google_compute_network.servicenet.self_link service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.foobar.name] } @@ -2970,7 +2970,7 @@ resource "google_sql_database_instance" "instance" { tier = "db-f1-micro" ip_configuration { ipv4_enabled = "false" - private_network = data.google_compute_network.servicenet.self_link + private_network = google_compute_network.servicenet.self_link } backup_configuration { enabled = true @@ -2997,7 +2997,7 @@ resource "google_sql_database_instance" "clone1" { func testAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRangeClone_withSettings(databaseName, networkName, addressRangeName string) string { return fmt.Sprintf(` -data "google_compute_network" "servicenet" { +resource "google_compute_network" "servicenet" { name = "%s" } @@ -3006,11 +3006,11 @@ resource "google_compute_global_address" "foobar" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = data.google_compute_network.servicenet.self_link + network = google_compute_network.servicenet.self_link } resource "google_service_networking_connection" "foobar" { - network = data.google_compute_network.servicenet.self_link + network = google_compute_network.servicenet.self_link service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.foobar.name] } @@ -3025,7 +3025,7 @@ resource "google_sql_database_instance" "instance" { tier = "db-f1-micro" ip_configuration { ipv4_enabled = "false" - private_network = data.google_compute_network.servicenet.self_link + private_network = google_compute_network.servicenet.self_link } backup_configuration { enabled = true From 85bf78e0d6473af71141b65c869ac4168a2af7c7 Mon Sep 17 00:00:00 2001 From: Lingkai Shen Date: Thu, 7 Sep 2023 15:26:39 -0400 Subject: [PATCH 26/67] Remove firebase_project_location (#8783) --- mmv1/products/firebase/ProjectLocation.yaml | 58 ------------------- .../firebase_project_location_basic.tf.erb | 23 -------- 2 files changed, 81 deletions(-) delete mode 100644 mmv1/products/firebase/ProjectLocation.yaml delete mode 100644 mmv1/templates/terraform/examples/firebase_project_location_basic.tf.erb diff --git a/mmv1/products/firebase/ProjectLocation.yaml b/mmv1/products/firebase/ProjectLocation.yaml deleted file mode 100644 index e1957694e954..000000000000 --- a/mmv1/products/firebase/ProjectLocation.yaml +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright 2023 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: 'ProjectLocation' -min_version: beta -base_url: projects/{{project}} -self_link: projects/{{project}} -create_url: projects/{{project}}/defaultLocation:finalize -nested_query: !ruby/object:Api::Resource::NestedQuery - keys: - - resources -immutable: true -description: | - Sets the default Google Cloud Platform (GCP) resource location for the specified FirebaseProject. - This method creates an App Engine application with a default Cloud Storage bucket, located in the specified - locationId. This location must be one of the available GCP resource locations. - After the default GCP resource location is finalized, or if it was already set, it cannot be changed. - The default GCP resource location for the specified FirebaseProject might already be set because either the - GCP Project already has an App Engine application or defaultLocation.finalize was previously called with a - specified locationId. Any new calls to defaultLocation.finalize with a different specified locationId will - return a 409 error. -references: !ruby/object:Api::Resource::ReferenceLinks - guides: - 'Official Documentation': 'https://firebase.google.com/' - api: 'https://firebase.google.com/docs/reference/firebase-management/rest/v1beta1/projects.defaultLocation/finalize' -import_format: ['projects/{{project}}', '{{project}}'] -skip_delete: true -skip_sweeper: true -deprecation_message: >- - `google_firebase_project_location` is deprecated in favor of explicitly configuring `google_app_engine_application` - and `google_firestore_database`. This resource will be removed in the next major release of the provider. -examples: - - !ruby/object:Provider::Terraform::Examples - name: 'firebase_project_location_basic' - min_version: 'beta' - primary_resource_id: 'basic' - test_env_vars: - org_id: :ORG_ID - vars: - project_name: "my-project" -properties: - - !ruby/object:Api::Type::String - name: locationId - required: true - description: | - The ID of the default GCP resource location for the Project. The location must be one of the available GCP - resource locations. diff --git a/mmv1/templates/terraform/examples/firebase_project_location_basic.tf.erb b/mmv1/templates/terraform/examples/firebase_project_location_basic.tf.erb deleted file mode 100644 index 4cdebbe83a21..000000000000 --- a/mmv1/templates/terraform/examples/firebase_project_location_basic.tf.erb +++ /dev/null @@ -1,23 +0,0 @@ -resource "google_project" "default" { - provider = google-beta - - project_id = "<%= ctx[:vars]['project_name'] %>" - name = "<%= ctx[:vars]['project_name'] %>" - org_id = "<%= ctx[:test_env_vars]['org_id'] %>" - - labels = { - "firebase" = "enabled" - } -} - -resource "google_firebase_project" "default" { - provider = google-beta - project = google_project.default.project_id -} - -resource "google_firebase_project_location" "<%= ctx[:primary_resource_id] %>" { - provider = google-beta - project = google_firebase_project.default.project - - location_id = "us-central" -} From 186acac752c74d3cc6e716bd7c5ef06f1360d0ef Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Thu, 7 Sep 2023 14:15:36 -0700 Subject: [PATCH 27/67] Don't override Terraform unmanaged labels (#8881) * Don't override Terraform unmanaged labels * Merge labels customdiff functions --- mmv1/api/resource.rb | 73 +++++++++++++------ mmv1/api/type.rb | 5 ++ mmv1/products/alloydb/Instance.yaml | 4 +- mmv1/products/cloudrunv2/Service.yaml | 2 +- mmv1/products/containerattached/Cluster.yaml | 2 +- mmv1/provider/core.rb | 2 +- mmv1/provider/terraform.rb | 1 + .../terraform/flatten_property_method.erb | 2 +- .../terraform/post_create/labels.erb | 15 +++- .../alloydb/resource_alloydb_instance_test.go | 2 +- .../resource_cloud_run_v2_service_test.go | 16 ++-- ..._container_attached_cluster_update_test.go | 6 +- .../terraform/tpgresource/annotations.go | 58 +++++++++++++++ .../terraform/tpgresource/labels.go | 45 ++++++++++-- .../data/example_bigquery_dataset.tfplan.json | 7 ++ ...e_bigquery_dataset_iam_binding.tfplan.json | 7 ++ ...le_bigquery_dataset_iam_member.tfplan.json | 7 ++ ...le_bigquery_dataset_iam_policy.tfplan.json | 7 ++ 18 files changed, 209 insertions(+), 52 deletions(-) create mode 100644 mmv1/third_party/terraform/tpgresource/annotations.go diff --git a/mmv1/api/resource.rb b/mmv1/api/resource.rb index 0670658de06d..a0ae098eaad7 100644 --- a/mmv1/api/resource.rb +++ b/mmv1/api/resource.rb @@ -394,11 +394,13 @@ def all_resourcerefs # 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 - settable_properties = all_user_properties.reject do |v| - v.output && !v.is_a?(Api::Type::Fingerprint) && !v.is_a?(Api::Type::KeyValueTerraformLabels) + props = all_user_properties.reject do |v| + v.output && !v.is_a?(Api::Type::Fingerprint) && !v.is_a?(Api::Type::KeyValueEffectiveLabels) + end + props = props.reject(&:url_param_only) + props.reject do |v| + v.is_a?(Api::Type::KeyValueLabels) || v.is_a?(Api::Type::KeyValueAnnotations) end - settable_properties.reject(&:url_param_only) - .reject { |v| v.is_a?(Api::Type::KeyValueLabels) } end # Properties that will be returned in the API body @@ -454,21 +456,9 @@ def decoder? def add_labels_related_fields(props, parent) props.each do |p| if p.is_a? Api::Type::KeyValueLabels - # The terraform_labels field is used to write to API, instead of the labels field. - p.ignore_write = true - - @custom_diff ||= [] - if parent.nil? - @custom_diff.append('tpgresource.SetTerraformLabelsDiff') - elsif parent == 'metadata' - @custom_diff.append('tpgresource.SetMetadataTerraformLabelsDiff') - end - - props << build_terraform_labels_field('labels', p.field_min_version, p.update_verb, - p.update_url) - props << build_effective_labels_field('labels', p.field_min_version) + add_labels_fields(props, parent, p) elsif p.is_a? Api::Type::KeyValueAnnotations - props << build_effective_labels_field('annotations', p.field_min_version) + 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.name) end @@ -476,22 +466,58 @@ def add_labels_related_fields(props, parent) props end - def build_effective_labels_field(name, min_version) + def add_labels_fields(props, parent, labels) + # The effective_labels field is used to write to API, instead of the labels field. + labels.ignore_write = true + + @custom_diff ||= [] + if parent.nil? + @custom_diff.append('tpgresource.SetLabelsDiff') + elsif parent == 'metadata' + @custom_diff.append('tpgresource.SetMetadataLabelsDiff') + end + + props << build_terraform_labels_field('labels', labels.field_min_version) + props << build_effective_labels_field( + 'labels', labels.field_min_version, labels.update_verb, labels.update_url + ) + 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 + + @custom_diff ||= [] + if parent.nil? + @custom_diff.append('tpgresource.SetAnnotationsDiff') + elsif parent == 'metadata' + @custom_diff.append('tpgresource.SetMetadataAnnotationsDiff') + end + + props << build_effective_labels_field( + 'annotations', annotations.field_min_version, + annotations.update_verb, annotations.update_url + ) + end + + def build_effective_labels_field(name, min_version, update_verb, update_url) 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::KeyValuePairs.new( + Api::Type::KeyValueEffectiveLabels.new( name: "effective#{name.capitalize}", output: true, api_name: name, description:, min_version:, - ignore_write: true + update_verb:, + update_url: ) end - def build_terraform_labels_field(name, min_version, update_verb, update_url) + def build_terraform_labels_field(name, min_version) description = "The combination of #{name} configured directly on the resource and default #{name} configured on the provider." @@ -501,8 +527,7 @@ def build_terraform_labels_field(name, min_version, update_verb, update_url) api_name: name, description:, min_version:, - update_verb:, - update_url: + ignore_write: true ) end diff --git a/mmv1/api/type.rb b/mmv1/api/type.rb index b2959da9aed9..c9b385e6b4b6 100644 --- a/mmv1/api/type.rb +++ b/mmv1/api/type.rb @@ -807,6 +807,11 @@ def validate class KeyValueTerraformLabels < KeyValuePairs end + # An array of string -> string key -> value pairs used for the "effective_labels" + # and "effective_annotations" fields. + class KeyValueEffectiveLabels < KeyValuePairs + end + # An array of string -> string key -> value pairs used specifically for the "annotations" field. # The field name with this type should be "annotations" literally. class KeyValueAnnotations < KeyValuePairs diff --git a/mmv1/products/alloydb/Instance.yaml b/mmv1/products/alloydb/Instance.yaml index 5530c7434fa0..972aaa4e079f 100644 --- a/mmv1/products/alloydb/Instance.yaml +++ b/mmv1/products/alloydb/Instance.yaml @@ -99,10 +99,10 @@ properties: output: true description: | The system-generated UID of the resource. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'User-defined labels for the alloydb instance.' - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueAnnotations name: 'annotations' description: 'Annotations to allow client tools to store small amount of arbitrary diff --git a/mmv1/products/cloudrunv2/Service.yaml b/mmv1/products/cloudrunv2/Service.yaml index dc5a781d36cf..db919ee81e51 100644 --- a/mmv1/products/cloudrunv2/Service.yaml +++ b/mmv1/products/cloudrunv2/Service.yaml @@ -152,7 +152,7 @@ properties: Cloud Run API v2 does not support labels with `run.googleapis.com`, `cloud.googleapis.com`, `serving.knative.dev`, or `autoscaling.knative.dev` namespaces, and they will be rejected. All system labels in v1 now have a corresponding field in v2 Service. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueAnnotations name: 'annotations' description: |- Unstructured key value map that may be set by external tools to store and arbitrary metadata. They are not queryable and should be preserved when modifying objects. diff --git a/mmv1/products/containerattached/Cluster.yaml b/mmv1/products/containerattached/Cluster.yaml index 3d64fa3485b5..96acf1f86b14 100644 --- a/mmv1/products/containerattached/Cluster.yaml +++ b/mmv1/products/containerattached/Cluster.yaml @@ -202,7 +202,7 @@ properties: description: | The Kubernetes version of the cluster. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueAnnotations name: annotations description: | Optional. Annotations on the cluster. This field has the same diff --git a/mmv1/provider/core.rb b/mmv1/provider/core.rb index a5651ec92ae2..0cdf06f8c4e9 100644 --- a/mmv1/provider/core.rb +++ b/mmv1/provider/core.rb @@ -402,7 +402,7 @@ def field_specific_update_methods(properties) def properties_by_custom_update(properties) update_props = properties.reject do |p| p.update_url.nil? || p.update_verb.nil? || p.update_verb == :NOOP || - p.is_a?(Api::Type::KeyValueLabels) + p.is_a?(Api::Type::KeyValueLabels) # effective_labels is used for update end update_props.group_by do |p| diff --git a/mmv1/provider/terraform.rb b/mmv1/provider/terraform.rb index 5d9cb7a4a696..4b89fb535374 100644 --- a/mmv1/provider/terraform.rb +++ b/mmv1/provider/terraform.rb @@ -93,6 +93,7 @@ def tf_types Api::Type::KeyValuePairs => 'schema.TypeMap', Api::Type::KeyValueLabels => 'schema.TypeMap', Api::Type::KeyValueTerraformLabels => 'schema.TypeMap', + Api::Type::KeyValueEffectiveLabels => 'schema.TypeMap', Api::Type::KeyValueAnnotations => 'schema.TypeMap', Api::Type::Map => 'schema.TypeSet', Api::Type::Fingerprint => 'schema.TypeString' diff --git a/mmv1/templates/terraform/flatten_property_method.erb b/mmv1/templates/terraform/flatten_property_method.erb index e19121c4f953..f13a7d670744 100644 --- a/mmv1/templates/terraform/flatten_property_method.erb +++ b/mmv1/templates/terraform/flatten_property_method.erb @@ -94,7 +94,7 @@ func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d }) } return transformed -<% elsif (property.is_a?(Api::Type::KeyValueLabels)) || (property.is_a?(Api::Type::KeyValueAnnotations)) || property.name == "terraformLabels" -%> +<% elsif (property.is_a?(Api::Type::KeyValueLabels)) || (property.is_a?(Api::Type::KeyValueAnnotations)) || (property.is_a?(Api::Type::KeyValueTerraformLabels)) -%> if v == nil { return v } diff --git a/mmv1/templates/terraform/post_create/labels.erb b/mmv1/templates/terraform/post_create/labels.erb index f47ed50f122c..1aaf5c26ce90 100644 --- a/mmv1/templates/terraform/post_create/labels.erb +++ b/mmv1/templates/terraform/post_create/labels.erb @@ -1,6 +1,8 @@ <% if properties.any?{ |p| p.name == "labels" } -%> -if v, ok := d.GetOkExists("terraform_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) { +if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) { labels := d.Get("labels") + terraformLables := d.Get("terraform_labels") + // Labels cannot be set in a create. We'll have to set them here. err = resource<%= resource_name -%>Read(d, meta) if err != nil { @@ -8,8 +10,8 @@ if v, ok := d.GetOkExists("terraform_labels"); !tpgresource.IsEmptyValue(reflect } obj := make(map[string]interface{}) - // d.Get("terraform_labels") will have been overridden by the Read call. - labelsProp, err := expand<%= resource_name -%>TerraformLabels(v, d, config) + // d.Get("effective_labels") will have been overridden by the Read call. + labelsProp, err := expand<%= resource_name -%>EffectiveLabels(v, d, config) if err != nil { return err } @@ -53,8 +55,13 @@ if v, ok := d.GetOkExists("terraform_labels"); !tpgresource.IsEmptyValue(reflect } // Set back the terraform_labels field, as it is needed to decide the value of "terraform_labels" in the state in the read function. - if err := d.Set("terraform_labels", v); err != nil { + if err := d.Set("terraform_labels", terraformLables); err != nil { return fmt.Errorf("Error setting back terraform_labels: %s", err) } + + // Set back the effective_labels field, as it is needed to decide the value of "effective_labels" in the state in the read function. + if err := d.Set("effective_labels", v); err != nil { + return fmt.Errorf("Error setting back effective_labels: %s", err) + } } <% end -%> diff --git a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_instance_test.go b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_instance_test.go index 824bab8b12f0..52c40c4efb5b 100644 --- a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_instance_test.go +++ b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_instance_test.go @@ -37,7 +37,7 @@ func TestAccAlloydbInstance_update(t *testing.T) { ResourceName: "google_alloydb_instance.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"cluster", "instance_id", "reconciling", "update_time"}, + ImportStateVerifyIgnore: []string{"cluster", "instance_id", "reconciling", "update_time", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go index 00ddd0472239..feb6bfbd9959 100644 --- a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go +++ b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go @@ -30,7 +30,7 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceFullUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "annotations"}, }, { Config: testAccCloudRunV2Service_cloudrunv2ServiceFullUpdate(context), @@ -39,7 +39,7 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceFullUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "annotations"}, }, }, }) @@ -227,7 +227,7 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceTCPProbesUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "annotations"}, }, { Config: testAccCloudRunV2Service_cloudrunv2ServiceUpdateWithTCPStartupProbeAndHTTPLivenessProbe(context), @@ -236,7 +236,7 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceTCPProbesUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "annotations"}, }, }, }) @@ -261,7 +261,7 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceHTTPProbesUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "annotations"}, }, { Config: testAccCloudRunV2Service_cloudrunv2ServiceUpdateWithHTTPStartupProbe(context), @@ -270,7 +270,7 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceHTTPProbesUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "annotations"}, }, }, }) @@ -296,7 +296,7 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceGRPCProbesUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "annotations"}, }, { Config: testAccCloudRunV2Service_cloudRunServiceUpdateWithGRPCLivenessProbe(context), @@ -305,7 +305,7 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceGRPCProbesUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "annotations"}, }, // The following test steps of gRPC startup probe are expected to fail with startup probe check failures. // This is because, due to the unavailability of ready-to-use container images of a gRPC service that diff --git a/mmv1/third_party/terraform/services/containerattached/resource_container_attached_cluster_update_test.go b/mmv1/third_party/terraform/services/containerattached/resource_container_attached_cluster_update_test.go index 8df998cc8aab..1c5e7936000d 100644 --- a/mmv1/third_party/terraform/services/containerattached/resource_container_attached_cluster_update_test.go +++ b/mmv1/third_party/terraform/services/containerattached/resource_container_attached_cluster_update_test.go @@ -26,7 +26,7 @@ func TestAccContainerAttachedCluster_update(t *testing.T) { ResourceName: "google_container_attached_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"location"}, + ImportStateVerifyIgnore: []string{"location", "annotations"}, }, { Config: testAccContainerAttachedCluster_containerAttachedCluster_update(context), @@ -35,7 +35,7 @@ func TestAccContainerAttachedCluster_update(t *testing.T) { ResourceName: "google_container_attached_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"location"}, + ImportStateVerifyIgnore: []string{"location", "annotations"}, }, { Config: testAccContainerAttachedCluster_containerAttachedCluster_destroy(context), @@ -44,7 +44,7 @@ func TestAccContainerAttachedCluster_update(t *testing.T) { ResourceName: "google_container_attached_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"location"}, + ImportStateVerifyIgnore: []string{"location", "annotations"}, }, }, }) diff --git a/mmv1/third_party/terraform/tpgresource/annotations.go b/mmv1/third_party/terraform/tpgresource/annotations.go new file mode 100644 index 000000000000..f6a14211c8e8 --- /dev/null +++ b/mmv1/third_party/terraform/tpgresource/annotations.go @@ -0,0 +1,58 @@ +package tpgresource + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func SetAnnotationsDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) error { + o, n := d.GetChange("annotations") + effectiveAnnotations := d.Get("effective_annotations").(map[string]interface{}) + + for k, v := range n.(map[string]interface{}) { + effectiveAnnotations[k] = v.(string) + } + + for k := range o.(map[string]interface{}) { + if _, ok := n.(map[string]interface{})[k]; !ok { + delete(effectiveAnnotations, k) + } + } + + if err := d.SetNew("effective_annotations", effectiveAnnotations); err != nil { + return fmt.Errorf("error setting new effective_annotations diff: %w", err) + } + + return nil +} + +func SetMetadataAnnotationsDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) error { + l := d.Get("metadata").([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil + } + + o, n := d.GetChange("metadata.0.annotations") + effectiveAnnotations := d.Get("metadata.0.effective_annotations").(map[string]interface{}) + + for k, v := range n.(map[string]interface{}) { + effectiveAnnotations[k] = v.(string) + } + + for k := range o.(map[string]interface{}) { + if _, ok := n.(map[string]interface{})[k]; !ok { + delete(effectiveAnnotations, k) + } + } + + original := l[0].(map[string]interface{}) + original["effective_annotations"] = effectiveAnnotations + + if err := d.SetNew("metadata", []interface{}{original}); err != nil { + return fmt.Errorf("error setting new metadata diff: %w", err) + } + + return nil +} diff --git a/mmv1/third_party/terraform/tpgresource/labels.go b/mmv1/third_party/terraform/tpgresource/labels.go index e18d1323c890..06cb72c7c9bb 100644 --- a/mmv1/third_party/terraform/tpgresource/labels.go +++ b/mmv1/third_party/terraform/tpgresource/labels.go @@ -8,7 +8,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" ) -func SetTerraformLabelsDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) error { +func SetLabelsDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) error { config := meta.(*transport_tpg.Config) // Merge provider default labels with the user defined labels in the resource to get terraform managed labels @@ -26,12 +26,28 @@ func SetTerraformLabelsDiff(_ context.Context, d *schema.ResourceDiff, meta inte return fmt.Errorf("error setting new terraform_labels diff: %w", err) } + o, n := d.GetChange("terraform_labels") + effectiveLabels := d.Get("effective_labels").(map[string]interface{}) + + for k, v := range n.(map[string]interface{}) { + effectiveLabels[k] = v.(string) + } + + for k := range o.(map[string]interface{}) { + if _, ok := n.(map[string]interface{})[k]; !ok { + delete(effectiveLabels, k) + } + } + + if err := d.SetNew("effective_labels", effectiveLabels); err != nil { + return fmt.Errorf("error setting new effective_labels diff: %w", err) + } + return nil } -func SetMetadataTerraformLabelsDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) error { - v := d.Get("metadata") - l := v.([]interface{}) +func SetMetadataLabelsDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) error { + l := d.Get("metadata").([]interface{}) if len(l) == 0 || l[0] == nil { return nil } @@ -49,10 +65,27 @@ func SetMetadataTerraformLabelsDiff(_ context.Context, d *schema.ResourceDiff, m terraformLabels[k] = v.(string) } - raw := l[0] - original := raw.(map[string]interface{}) + original := l[0].(map[string]interface{}) + original["terraform_labels"] = terraformLabels + if err := d.SetNew("metadata", []interface{}{original}); err != nil { + return fmt.Errorf("error setting new metadata diff: %w", err) + } + + o, n := d.GetChange("metadata.0.terraform_labels") + effectiveLabels := d.Get("metadata.0.effective_labels").(map[string]interface{}) + + for k, v := range n.(map[string]interface{}) { + effectiveLabels[k] = v.(string) + } + + for k := range o.(map[string]interface{}) { + if _, ok := n.(map[string]interface{})[k]; !ok { + delete(effectiveLabels, k) + } + } + original["effective_labels"] = effectiveLabels if err := d.SetNew("metadata", []interface{}{original}); err != nil { return fmt.Errorf("error setting new metadata diff: %w", err) } diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tfplan.json b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tfplan.json index 1daf2ee28ffd..75f53ab54889 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tfplan.json +++ b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tfplan.json @@ -18,6 +18,9 @@ "default_table_expiration_ms": 3600000, "delete_contents_on_destroy": false, "description": null, + "effective_labels": { + "env": "dev" + }, "friendly_name": null, "labels": { "env": "dev" @@ -51,6 +54,9 @@ "default_table_expiration_ms": 3600000, "delete_contents_on_destroy": false, "description": null, + "effective_labels": { + "env": "dev" + }, "friendly_name": null, "labels": { "env": "dev" @@ -65,6 +71,7 @@ "access": true, "creation_time": true, "default_encryption_configuration": [], + "effective_labels": {}, "etag": true, "id": true, "labels": {}, diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tfplan.json b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tfplan.json index 7519ca4bd735..057733326a31 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tfplan.json +++ b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tfplan.json @@ -17,6 +17,9 @@ "default_table_expiration_ms": 3600000, "delete_contents_on_destroy": false, "description": null, + "effective_labels": { + "env": "dev" + }, "friendly_name": null, "labels": { "env": "dev" @@ -60,6 +63,9 @@ "default_table_expiration_ms": 3600000, "delete_contents_on_destroy": false, "description": null, + "effective_labels": { + "env": "dev" + }, "friendly_name": null, "labels": { "env": "dev" @@ -75,6 +81,7 @@ "access": true, "creation_time": true, "default_encryption_configuration": [], + "effective_labels": {}, "etag": true, "id": true, "labels": {}, diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tfplan.json b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tfplan.json index 6b0d5a89ce54..45223f402c7c 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tfplan.json +++ b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tfplan.json @@ -17,6 +17,9 @@ "default_table_expiration_ms": 3600000, "delete_contents_on_destroy": false, "description": null, + "effective_labels": { + "env": "dev" + }, "friendly_name": null, "labels": { "env": "dev" @@ -60,6 +63,9 @@ "default_table_expiration_ms": 3600000, "delete_contents_on_destroy": false, "description": null, + "effective_labels": { + "env": "dev" + }, "friendly_name": null, "labels": { "env": "dev" @@ -75,6 +81,7 @@ "access": true, "creation_time": true, "default_encryption_configuration": [], + "effective_labels": {}, "etag": true, "id": true, "labels": {}, diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tfplan.json index 1725f40b59c3..7885b3b94ef0 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tfplan.json +++ b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tfplan.json @@ -17,6 +17,9 @@ "default_table_expiration_ms": 3600000, "delete_contents_on_destroy": false, "description": null, + "effective_labels": { + "env": "dev" + }, "friendly_name": null, "labels": { "env": "dev" @@ -58,6 +61,9 @@ "default_table_expiration_ms": 3600000, "delete_contents_on_destroy": false, "description": null, + "effective_labels": { + "env": "dev" + }, "friendly_name": null, "labels": { "env": "dev" @@ -73,6 +79,7 @@ "access": true, "creation_time": true, "default_encryption_configuration": [], + "effective_labels": {}, "etag": true, "id": true, "labels": {}, From df9725a7dfeffdced3a5ca1c3ddd35101abc4bf4 Mon Sep 17 00:00:00 2001 From: Nick Elliot Date: Mon, 11 Sep 2023 10:13:02 -0700 Subject: [PATCH 28/67] existing Data Sources now return errors on 404s (#8858) --- ...e_access_approval_folder_service_account.go | 2 +- ...ss_approval_organization_service_account.go | 2 +- ..._access_approval_project_service_account.go | 2 +- .../alloydb/data_source_alloydb_locations.go | 4 ++-- ..._source_alloydb_supported_database_flags.go | 4 ++-- ...oogle_app_engine_default_service_account.go | 2 +- ...data_source_artifact_registry_repository.go | 7 ++++++- ..._source_google_beyondcorp_app_connection.go | 14 ++++++++++++-- ...a_source_google_beyondcorp_app_connector.go | 14 ++++++++++++-- ...ata_source_google_beyondcorp_app_gateway.go | 14 ++++++++++++-- ..._google_bigquery_default_service_account.go | 2 +- .../data_source_google_billing_account.go | 2 +- .../data_source_google_cloudbuild_trigger.go | 13 +++++++++++-- ...ta_source_google_cloudfunctions_function.go | 6 ++++++ ...a_source_google_cloudfunctions2_function.go | 7 ++++++- ...rce_cloud_identity_group_memberships.go.erb | 2 +- .../data_source_cloud_identity_groups.go.erb | 2 +- .../cloudrun/data_source_cloud_run_service.go | 11 ++++++++++- .../data_source_google_composer_environment.go | 13 +++++++++++-- .../data_source_compute_health_check.go | 13 ++++++++++++- ...ta_source_compute_network_endpoint_group.go | 18 +++++++++++++++--- .../data_source_compute_network_peering.go | 14 ++++++++++++-- .../data_source_google_compute_address.go | 6 ++++-- ...ata_source_google_compute_backend_bucket.go | 14 ++++++++++++-- ...ta_source_google_compute_backend_service.go | 14 ++++++++++++-- ...e_google_compute_default_service_account.go | 4 ++-- .../compute/data_source_google_compute_disk.go | 11 ++++++++++- ...ta_source_google_compute_forwarding_rule.go | 14 ++++++++++++-- ...ata_source_google_compute_global_address.go | 6 ++++-- ...ata_source_google_compute_ha_vpn_gateway.go | 14 ++++++++++++-- .../data_source_google_compute_instance.go.erb | 4 +++- ...ata_source_google_compute_instance_group.go | 17 ++++++++++++++--- .../data_source_google_compute_network.go | 7 +++++-- ...google_compute_region_instance_group.go.erb | 6 +++--- ...le_compute_region_network_endpoint_group.go | 16 +++++++++++++--- ...ce_google_compute_region_ssl_certificate.go | 13 +++++++++++-- ...ource_google_compute_resource_policy.go.erb | 14 ++++++++++++-- .../data_source_google_compute_router.go | 12 +++++++++++- .../data_source_google_compute_router_nat.go | 11 ++++++++++- ...ta_source_google_compute_ssl_certificate.go | 14 ++++++++++++-- .../data_source_google_compute_ssl_policy.go | 14 ++++++++++++-- ...ata_source_google_compute_subnetwork.go.erb | 5 +++-- ...ta_source_google_compute_vpn_gateway.go.erb | 5 +++-- ...ce_google_global_compute_forwarding_rule.go | 14 ++++++++++++-- ...ta_source_dataproc_metastore_service.go.erb | 10 +++++++++- .../services/dns/data_source_dns_keys.go | 5 +---- ...a_source_google_firebase_android_app.go.erb | 10 +++++++++- ...ata_source_google_firebase_apple_app.go.erb | 10 +++++++++- .../data_source_google_firebase_web_app.go.erb | 10 +++++++++- ...urce_google_firebase_hosting_channel.go.erb | 10 +++++++++- ...urce_iam_beta_workload_identity_pool.go.erb | 10 +++++++++- ...beta_workload_identity_pool_provider.go.erb | 10 +++++++++- .../services/iap/data_source_iap_client.go | 10 +++++++++- .../kms/data_source_google_kms_crypto_key.go | 15 +++++++++++++-- ...ata_source_google_kms_crypto_key_version.go | 4 ++-- .../kms/data_source_google_kms_key_ring.go | 15 +++++++++++++-- ...rce_google_logging_project_cmek_settings.go | 2 +- .../logging/data_source_google_logging_sink.go | 2 +- .../data_source_certificate_authority.go | 2 +- .../pubsub/data_source_pubsub_subscription.go | 10 +++++++++- .../pubsub/data_source_pubsub_topic.go | 10 +++++++++- .../redis/data_source_redis_instance.go | 12 +++++++++++- .../data_source_google_folder.go | 5 +++-- ...source_google_folder_organization_policy.go | 13 +++++++++++-- .../data_source_google_iam_role.go | 2 +- .../data_source_google_organization.go | 2 +- ...ource_google_project_organization_policy.go | 13 +++++++++++-- .../data_source_google_project_service.go | 10 +++++++++- .../data_source_google_service_account.go | 2 +- .../data_source_google_service_account_key.go | 2 +- .../data_source_runtimeconfig_config.go.erb | 10 +++++++++- .../data_source_runtimeconfig_variable.go.erb | 10 +++++++++- .../data_source_secret_manager_secret.go | 10 +++++++++- .../data_source_sourcerepo_repository.go | 10 +++++++++- .../spanner/data_source_spanner_instance.go | 10 +++++++++- .../services/sql/data_source_sql_database.go | 6 +++++- .../sql/data_source_sql_database_instance.go | 12 +++++++++++- .../services/sql/data_source_sql_databases.go | 2 +- ...e_google_storage_project_service_account.go | 2 +- ...storage_transfer_project_service_account.go | 2 +- .../vertexai/data_source_vertex_ai_index.go | 10 +++++++++- ...a_source_google_vmwareengine_cluster.go.erb | 10 +++++++++- ...a_source_google_vmwareengine_network.go.erb | 10 +++++++++- ...ce_google_vmwareengine_private_cloud.go.erb | 10 +++++++++- .../data_source_vpc_access_connector.go | 10 +++++++++- .../terraform/transport/transport.go | 9 +++++++++ 86 files changed, 618 insertions(+), 124 deletions(-) diff --git a/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_folder_service_account.go b/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_folder_service_account.go index 2bc48454a986..4727870ba944 100644 --- a/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_folder_service_account.go +++ b/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_folder_service_account.go @@ -56,7 +56,7 @@ func dataSourceAccessApprovalFolderServiceAccountRead(d *schema.ResourceData, me UserAgent: userAgent, }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("AccessApprovalFolderServiceAccount %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("AccessApprovalFolderServiceAccount %q", d.Id()), url) } if err := d.Set("name", res["name"]); err != nil { diff --git a/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_organization_service_account.go b/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_organization_service_account.go index b7b2005fbc6e..d785f52f82ed 100644 --- a/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_organization_service_account.go +++ b/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_organization_service_account.go @@ -56,7 +56,7 @@ func dataSourceAccessApprovalOrganizationServiceAccountRead(d *schema.ResourceDa UserAgent: userAgent, }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("AccessApprovalOrganizationServiceAccount %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("AccessApprovalOrganizationServiceAccount %q", d.Id()), url) } if err := d.Set("name", res["name"]); err != nil { diff --git a/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_project_service_account.go b/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_project_service_account.go index 1f9794f50e5e..4a0cf4b73036 100644 --- a/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_project_service_account.go +++ b/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_project_service_account.go @@ -56,7 +56,7 @@ func dataSourceAccessApprovalProjectServiceAccountRead(d *schema.ResourceData, m UserAgent: userAgent, }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("AccessApprovalProjectServiceAccount %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("AccessApprovalProjectServiceAccount %q", d.Id()), url) } if err := d.Set("name", res["name"]); err != nil { diff --git a/mmv1/third_party/terraform/services/alloydb/data_source_alloydb_locations.go b/mmv1/third_party/terraform/services/alloydb/data_source_alloydb_locations.go index d23793f6a7d2..e79df23ac67b 100644 --- a/mmv1/third_party/terraform/services/alloydb/data_source_alloydb_locations.go +++ b/mmv1/third_party/terraform/services/alloydb/data_source_alloydb_locations.go @@ -94,7 +94,7 @@ func dataSourceAlloydbLocationsRead(d *schema.ResourceData, meta interface{}) er UserAgent: userAgent, }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Locations %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Locations %q", d.Id()), url) } var locations []map[string]interface{} for { @@ -142,7 +142,7 @@ func dataSourceAlloydbLocationsRead(d *schema.ResourceData, meta interface{}) er UserAgent: userAgent, }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Locations %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Locations %q", d.Id()), url) } } diff --git a/mmv1/third_party/terraform/services/alloydb/data_source_alloydb_supported_database_flags.go b/mmv1/third_party/terraform/services/alloydb/data_source_alloydb_supported_database_flags.go index 6404eaa63247..a1615661d5cc 100644 --- a/mmv1/third_party/terraform/services/alloydb/data_source_alloydb_supported_database_flags.go +++ b/mmv1/third_party/terraform/services/alloydb/data_source_alloydb_supported_database_flags.go @@ -147,7 +147,7 @@ func dataSourceAlloydbSupportedDatabaseFlagsRead(d *schema.ResourceData, meta in UserAgent: userAgent, }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("SupportedDatabaseFlags %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("SupportedDatabaseFlags %q", d.Id()), url) } var supportedDatabaseFlags []map[string]interface{} for { @@ -221,7 +221,7 @@ func dataSourceAlloydbSupportedDatabaseFlagsRead(d *schema.ResourceData, meta in UserAgent: userAgent, }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("SupportedDatabaseFlags %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("SupportedDatabaseFlags %q", d.Id()), url) } } if err := d.Set("supported_database_flags", supportedDatabaseFlags); err != nil { diff --git a/mmv1/third_party/terraform/services/appengine/data_source_google_app_engine_default_service_account.go b/mmv1/third_party/terraform/services/appengine/data_source_google_app_engine_default_service_account.go index bd38291084d5..99764bfe0fcf 100644 --- a/mmv1/third_party/terraform/services/appengine/data_source_google_app_engine_default_service_account.go +++ b/mmv1/third_party/terraform/services/appengine/data_source_google_app_engine_default_service_account.go @@ -62,7 +62,7 @@ func dataSourceGoogleAppEngineDefaultServiceAccountRead(d *schema.ResourceData, sa, err := config.NewIamClient(userAgent).Projects.ServiceAccounts.Get(serviceAccountName).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Service Account %q", serviceAccountName)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Service Account %q", serviceAccountName), serviceAccountName) } d.SetId(sa.Name) diff --git a/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository.go b/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository.go index 09c832b4aff9..fb0271a17040 100644 --- a/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository.go +++ b/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository.go @@ -38,12 +38,17 @@ func dataSourceArtifactRegistryRepositoryRead(d *schema.ResourceData, meta inter } repository_id := d.Get("repository_id").(string) - d.SetId(fmt.Sprintf("projects/%s/locations/%s/repositories/%s", project, location, repository_id)) + id := fmt.Sprintf("projects/%s/locations/%s/repositories/%s", project, location, repository_id) + d.SetId(id) err = resourceArtifactRegistryRepositoryRead(d, meta) if err != nil { return err } + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection.go b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection.go index fef0cf119493..13d16ca2c5de 100644 --- a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection.go +++ b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection.go @@ -38,7 +38,17 @@ func dataSourceGoogleBeyondcorpAppConnectionRead(d *schema.ResourceData, meta in return err } - d.SetId(fmt.Sprintf("projects/%s/locations/%s/appConnections/%s", project, region, name)) + id := fmt.Sprintf("projects/%s/locations/%s/appConnections/%s", project, region, name) + d.SetId(id) - return resourceBeyondcorpAppConnectionRead(d, meta) + err = resourceBeyondcorpAppConnectionRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connector.go b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connector.go index 202941b1448c..b06bc5f4fbbe 100644 --- a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connector.go +++ b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connector.go @@ -38,7 +38,17 @@ func dataSourceGoogleBeyondcorpAppConnectorRead(d *schema.ResourceData, meta int return err } - d.SetId(fmt.Sprintf("projects/%s/locations/%s/appConnectors/%s", project, region, name)) + id := fmt.Sprintf("projects/%s/locations/%s/appConnectors/%s", project, region, name) + d.SetId(id) - return resourceBeyondcorpAppConnectorRead(d, meta) + err = resourceBeyondcorpAppConnectorRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_gateway.go b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_gateway.go index a713c74e6a25..104f2798482e 100644 --- a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_gateway.go +++ b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_gateway.go @@ -38,7 +38,17 @@ func dataSourceGoogleBeyondcorpAppGatewayRead(d *schema.ResourceData, meta inter return err } - d.SetId(fmt.Sprintf("projects/%s/locations/%s/appGateways/%s", project, region, name)) + id := fmt.Sprintf("projects/%s/locations/%s/appGateways/%s", project, region, name) + d.SetId(id) - return resourceBeyondcorpAppGatewayRead(d, meta) + err = resourceBeyondcorpAppGatewayRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/bigquery/data_source_google_bigquery_default_service_account.go b/mmv1/third_party/terraform/services/bigquery/data_source_google_bigquery_default_service_account.go index cc1e4f0a6d2a..d25349166440 100644 --- a/mmv1/third_party/terraform/services/bigquery/data_source_google_bigquery_default_service_account.go +++ b/mmv1/third_party/terraform/services/bigquery/data_source_google_bigquery_default_service_account.go @@ -43,7 +43,7 @@ func dataSourceGoogleBigqueryDefaultServiceAccountRead(d *schema.ResourceData, m projectResource, err := config.NewBigQueryClient(userAgent).Projects.GetServiceAccount(project).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, "BigQuery service account not found") + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Project %q BigQuery service account", project), fmt.Sprintf("Project %q BigQuery service account", project)) } d.SetId(projectResource.Email) diff --git a/mmv1/third_party/terraform/services/billing/data_source_google_billing_account.go b/mmv1/third_party/terraform/services/billing/data_source_google_billing_account.go index 35faf461500d..7c47a741c13c 100644 --- a/mmv1/third_party/terraform/services/billing/data_source_google_billing_account.go +++ b/mmv1/third_party/terraform/services/billing/data_source_google_billing_account.go @@ -64,7 +64,7 @@ func dataSourceBillingAccountRead(d *schema.ResourceData, meta interface{}) erro if v, ok := d.GetOk("billing_account"); ok { resp, err := config.NewBillingClient(userAgent).BillingAccounts.Get(CanonicalBillingAccountName(v.(string))).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Billing Account Not Found : %s", v)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Billing Account Not Found : %s", v), CanonicalBillingAccountName(v.(string))) } if openOk && resp.Open != open.(bool) { diff --git a/mmv1/third_party/terraform/services/cloudbuild/data_source_google_cloudbuild_trigger.go b/mmv1/third_party/terraform/services/cloudbuild/data_source_google_cloudbuild_trigger.go index 499f4930dcb4..274a8e6e1dad 100644 --- a/mmv1/third_party/terraform/services/cloudbuild/data_source_google_cloudbuild_trigger.go +++ b/mmv1/third_party/terraform/services/cloudbuild/data_source_google_cloudbuild_trigger.go @@ -32,7 +32,16 @@ func dataSourceGoogleCloudBuildTriggerRead(d *schema.ResourceData, meta interfac } id = strings.ReplaceAll(id, "/locations/global/", "/") - d.SetId(id) - return resourceCloudBuildTriggerRead(d, meta) + + err = resourceCloudBuildTriggerRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/cloudfunctions/data_source_google_cloudfunctions_function.go b/mmv1/third_party/terraform/services/cloudfunctions/data_source_google_cloudfunctions_function.go index 04c0463dbf49..5255c37268df 100644 --- a/mmv1/third_party/terraform/services/cloudfunctions/data_source_google_cloudfunctions_function.go +++ b/mmv1/third_party/terraform/services/cloudfunctions/data_source_google_cloudfunctions_function.go @@ -1,6 +1,8 @@ package cloudfunctions 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" @@ -48,5 +50,9 @@ func dataSourceGoogleCloudFunctionsFunctionRead(d *schema.ResourceData, meta int return err } + if d.Id() == "" { + return fmt.Errorf("%s not found", cloudFuncId.CloudFunctionId()) + } + return nil } diff --git a/mmv1/third_party/terraform/services/cloudfunctions2/data_source_google_cloudfunctions2_function.go b/mmv1/third_party/terraform/services/cloudfunctions2/data_source_google_cloudfunctions2_function.go index f340b7608cc6..6769c2701231 100644 --- a/mmv1/third_party/terraform/services/cloudfunctions2/data_source_google_cloudfunctions2_function.go +++ b/mmv1/third_party/terraform/services/cloudfunctions2/data_source_google_cloudfunctions2_function.go @@ -32,12 +32,17 @@ func dataSourceGoogleCloudFunctions2FunctionRead(d *schema.ResourceData, meta in return err } - d.SetId(fmt.Sprintf("projects/%s/locations/%s/functions/%s", project, d.Get("location").(string), d.Get("name").(string))) + id := fmt.Sprintf("projects/%s/locations/%s/functions/%s", project, d.Get("location").(string), d.Get("name").(string)) + d.SetId(id) err = resourceCloudfunctions2functionRead(d, meta) if err != nil { return err } + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/cloudidentity/data_source_cloud_identity_group_memberships.go.erb b/mmv1/third_party/terraform/services/cloudidentity/data_source_cloud_identity_group_memberships.go.erb index 0035138b50d1..e397219ae527 100644 --- a/mmv1/third_party/terraform/services/cloudidentity/data_source_cloud_identity_group_memberships.go.erb +++ b/mmv1/third_party/terraform/services/cloudidentity/data_source_cloud_identity_group_memberships.go.erb @@ -85,7 +85,7 @@ func dataSourceGoogleCloudIdentityGroupMembershipsRead(d *schema.ResourceData, m return nil }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("CloudIdentityGroupMemberships %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("CloudIdentityGroupMemberships %q", d.Id()), "") } if err := d.Set("memberships", result); err != nil { diff --git a/mmv1/third_party/terraform/services/cloudidentity/data_source_cloud_identity_groups.go.erb b/mmv1/third_party/terraform/services/cloudidentity/data_source_cloud_identity_groups.go.erb index 848366d3e4eb..3295619a25f9 100644 --- a/mmv1/third_party/terraform/services/cloudidentity/data_source_cloud_identity_groups.go.erb +++ b/mmv1/third_party/terraform/services/cloudidentity/data_source_cloud_identity_groups.go.erb @@ -84,7 +84,7 @@ func dataSourceGoogleCloudIdentityGroupsRead(d *schema.ResourceData, meta interf return nil }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("CloudIdentityGroups %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("CloudIdentityGroups %q", d.Id()), "Groups") } if err := d.Set("groups", result); err != nil { diff --git a/mmv1/third_party/terraform/services/cloudrun/data_source_cloud_run_service.go b/mmv1/third_party/terraform/services/cloudrun/data_source_cloud_run_service.go index f689e97107e4..c674b097723d 100644 --- a/mmv1/third_party/terraform/services/cloudrun/data_source_cloud_run_service.go +++ b/mmv1/third_party/terraform/services/cloudrun/data_source_cloud_run_service.go @@ -28,5 +28,14 @@ func dataSourceGoogleCloudRunServiceRead(d *schema.ResourceData, meta interface{ return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceCloudRunServiceRead(d, meta) + err = resourceCloudRunServiceRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/composer/data_source_google_composer_environment.go b/mmv1/third_party/terraform/services/composer/data_source_google_composer_environment.go index f536428c6d3c..5b37ab9ad17a 100644 --- a/mmv1/third_party/terraform/services/composer/data_source_google_composer_environment.go +++ b/mmv1/third_party/terraform/services/composer/data_source_google_composer_environment.go @@ -35,7 +35,16 @@ func dataSourceGoogleComposerEnvironmentRead(d *schema.ResourceData, meta interf } envName := d.Get("name").(string) - d.SetId(fmt.Sprintf("projects/%s/locations/%s/environments/%s", project, region, envName)) + id := fmt.Sprintf("projects/%s/locations/%s/environments/%s", project, region, envName) + d.SetId(id) + err = resourceComposerEnvironmentRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } - return resourceComposerEnvironmentRead(d, meta) + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_compute_health_check.go b/mmv1/third_party/terraform/services/compute/data_source_compute_health_check.go index e47066ea9b26..8703c6fcaf7f 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_compute_health_check.go +++ b/mmv1/third_party/terraform/services/compute/data_source_compute_health_check.go @@ -1,6 +1,8 @@ package compute 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" @@ -29,5 +31,14 @@ func dataSourceGoogleComputeHealthCheckRead(d *schema.ResourceData, meta interfa } d.SetId(id) - return resourceComputeHealthCheckRead(d, meta) + err = resourceComputeHealthCheckRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_compute_network_endpoint_group.go b/mmv1/third_party/terraform/services/compute/data_source_compute_network_endpoint_group.go index e12c2958b4d5..bb5d4db55efa 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_compute_network_endpoint_group.go +++ b/mmv1/third_party/terraform/services/compute/data_source_compute_network_endpoint_group.go @@ -27,6 +27,7 @@ func DataSourceGoogleComputeNetworkEndpointGroup() *schema.Resource { func dataSourceComputeNetworkEndpointGroupRead(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) + id := "" if name, ok := d.GetOk("name"); ok { project, err := tpgresource.GetProject(d, config) if err != nil { @@ -36,7 +37,8 @@ func dataSourceComputeNetworkEndpointGroupRead(d *schema.ResourceData, meta inte if err != nil { return err } - d.SetId(fmt.Sprintf("projects/%s/zones/%s/networkEndpointGroups/%s", project, zone, name.(string))) + id = fmt.Sprintf("projects/%s/zones/%s/networkEndpointGroups/%s", project, zone, name.(string)) + d.SetId(id) } else if selfLink, ok := d.GetOk("self_link"); ok { parsed, err := tpgresource.ParseNetworkEndpointGroupFieldValue(selfLink.(string), d, config) if err != nil { @@ -51,10 +53,20 @@ func dataSourceComputeNetworkEndpointGroupRead(d *schema.ResourceData, meta inte if err := d.Set("project", parsed.Project); err != nil { return fmt.Errorf("Error setting project: %s", err) } - d.SetId(fmt.Sprintf("projects/%s/zones/%s/networkEndpointGroups/%s", parsed.Project, parsed.Zone, parsed.Name)) + id = fmt.Sprintf("projects/%s/zones/%s/networkEndpointGroups/%s", parsed.Project, parsed.Zone, parsed.Name) + d.SetId(id) } else { return errors.New("Must provide either `self_link` or `zone/name`") } - return resourceComputeNetworkEndpointGroupRead(d, meta) + err := resourceComputeNetworkEndpointGroupRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_compute_network_peering.go b/mmv1/third_party/terraform/services/compute/data_source_compute_network_peering.go index fed49bd6ba1e..edc7827e5fbf 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_compute_network_peering.go +++ b/mmv1/third_party/terraform/services/compute/data_source_compute_network_peering.go @@ -35,7 +35,17 @@ func dataSourceComputeNetworkPeeringRead(d *schema.ResourceData, meta interface{ if err != nil { return err } - d.SetId(fmt.Sprintf("%s/%s", networkFieldValue.Name, d.Get("name").(string))) + id := fmt.Sprintf("%s/%s", networkFieldValue.Name, d.Get("name").(string)) + d.SetId(id) - return resourceComputeNetworkPeeringRead(d, meta) + err = resourceComputeNetworkPeeringRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_address.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_address.go index f987531b05d7..f8faecfec4cd 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_address.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_address.go @@ -108,9 +108,11 @@ func dataSourceGoogleComputeAddressRead(d *schema.ResourceData, meta interface{} } name := d.Get("name").(string) + id := fmt.Sprintf("projects/%s/regions/%s/addresses/%s", project, region, name) + address, err := config.NewComputeClient(userAgent).Addresses.Get(project, region, name).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Address Not Found : %s", name)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Address Not Found : %s", name), id) } if err := d.Set("address", address.Address); err != nil { @@ -147,7 +149,7 @@ func dataSourceGoogleComputeAddressRead(d *schema.ResourceData, meta interface{} return fmt.Errorf("Error setting region: %s", err) } - d.SetId(fmt.Sprintf("projects/%s/regions/%s/addresses/%s", project, region, name)) + d.SetId(id) return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_backend_bucket.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_backend_bucket.go index b56c80f7c5bc..43e555c17d7b 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_backend_bucket.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_backend_bucket.go @@ -33,7 +33,17 @@ func dataSourceComputeBackendBucketRead(d *schema.ResourceData, meta interface{} return err } - d.SetId(fmt.Sprintf("projects/%s/global/backendBuckets/%s", project, backendBucketName)) + id := fmt.Sprintf("projects/%s/global/backendBuckets/%s", project, backendBucketName) + d.SetId(id) - return resourceComputeBackendBucketRead(d, meta) + err = resourceComputeBackendBucketRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_backend_service.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_backend_service.go index eac09d83ae6a..284dc85905f9 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_backend_service.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_backend_service.go @@ -33,7 +33,17 @@ func dataSourceComputeBackendServiceRead(d *schema.ResourceData, meta interface{ return err } - d.SetId(fmt.Sprintf("projects/%s/global/backendServices/%s", project, serviceName)) + id := fmt.Sprintf("projects/%s/global/backendServices/%s", project, serviceName) + d.SetId(id) - return resourceComputeBackendServiceRead(d, meta) + err = resourceComputeBackendServiceRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_default_service_account.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_default_service_account.go index 59264ef77c8b..a41e4a5225fc 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_default_service_account.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_default_service_account.go @@ -51,7 +51,7 @@ func dataSourceGoogleComputeDefaultServiceAccountRead(d *schema.ResourceData, me projectCompResource, err := config.NewComputeClient(userAgent).Projects.Get(project).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, "GCE default service account") + return transport_tpg.HandleDataSourceNotFoundError(err, d, "GCE default service account", fmt.Sprintf("%q GCE default service account", project)) } serviceAccountName, err := tpgresource.ServiceAccountFQN(projectCompResource.DefaultServiceAccount, d, config) @@ -61,7 +61,7 @@ func dataSourceGoogleComputeDefaultServiceAccountRead(d *schema.ResourceData, me sa, err := config.NewIamClient(userAgent).Projects.ServiceAccounts.Get(serviceAccountName).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Service Account %q", serviceAccountName)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Service Account %q", serviceAccountName), serviceAccountName) } d.SetId(sa.Name) diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_disk.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_disk.go index 9b660c8989e5..7a68c1fa9f7c 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_disk.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_disk.go @@ -29,5 +29,14 @@ func dataSourceGoogleComputeDiskRead(d *schema.ResourceData, meta interface{}) e return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceComputeDiskRead(d, meta) + err = resourceComputeDiskRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rule.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rule.go index 9dc06385eb78..555748f1064e 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rule.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rule.go @@ -39,7 +39,17 @@ func dataSourceGoogleComputeForwardingRuleRead(d *schema.ResourceData, meta inte return err } - d.SetId(fmt.Sprintf("projects/%s/regions/%s/forwardingRules/%s", project, region, name)) + id := fmt.Sprintf("projects/%s/regions/%s/forwardingRules/%s", project, region, name) + d.SetId(id) - return resourceComputeForwardingRuleRead(d, meta) + err = resourceComputeForwardingRuleRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_global_address.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_global_address.go index 14e6a8d1a8e0..44239ffdb887 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_global_address.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_global_address.go @@ -89,9 +89,11 @@ func dataSourceGoogleComputeGlobalAddressRead(d *schema.ResourceData, meta inter return err } name := d.Get("name").(string) + id := fmt.Sprintf("projects/%s/global/addresses/%s", project, name) + address, err := config.NewComputeClient(userAgent).GlobalAddresses.Get(project, name).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Global Address Not Found : %s", name)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Global Address Not Found : %s", name), id) } if err := d.Set("address", address.Address); err != nil { @@ -124,6 +126,6 @@ func dataSourceGoogleComputeGlobalAddressRead(d *schema.ResourceData, meta inter if err := d.Set("project", project); err != nil { return fmt.Errorf("Error setting project: %s", err) } - d.SetId(fmt.Sprintf("projects/%s/global/addresses/%s", project, name)) + d.SetId(id) return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_ha_vpn_gateway.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_ha_vpn_gateway.go index a5408b608dea..c658e4cdf376 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_ha_vpn_gateway.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_ha_vpn_gateway.go @@ -39,7 +39,17 @@ func dataSourceGoogleComputeHaVpnGatewayRead(d *schema.ResourceData, meta interf return err } - d.SetId(fmt.Sprintf("projects/%s/regions/%s/vpnGateways/%s", project, region, name)) + id := fmt.Sprintf("projects/%s/regions/%s/vpnGateways/%s", project, region, name) + d.SetId(id) - return resourceComputeHaVpnGatewayRead(d, meta) + err = resourceComputeHaVpnGatewayRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance.go.erb b/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance.go.erb index 19a49a5b4410..0c885da98bd8 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance.go.erb +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance.go.erb @@ -34,9 +34,11 @@ func dataSourceGoogleComputeInstanceRead(d *schema.ResourceData, meta interface{ return err } + id := fmt.Sprintf("projects/%s/zones/%s/instances/%s", project, zone, name) + instance, err := config.NewComputeClient(userAgent).Instances.Get(project, zone, name).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Instance %s", name)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Instance %s", name), id) } md := flattenMetadataBeta(instance.Metadata) diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_group.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_group.go index 7be1e9c072fe..bbe683b335dd 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_group.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_group.go @@ -84,6 +84,7 @@ func DataSourceGoogleComputeInstanceGroup() *schema.Resource { func dataSourceComputeInstanceGroupRead(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) + id := "" if name, ok := d.GetOk("name"); ok { zone, err := tpgresource.GetZone(d, config) if err != nil { @@ -93,7 +94,7 @@ func dataSourceComputeInstanceGroupRead(d *schema.ResourceData, meta interface{} if err != nil { return err } - d.SetId(fmt.Sprintf("projects/%s/zones/%s/instanceGroups/%s", project, zone, name.(string))) + id = fmt.Sprintf("projects/%s/zones/%s/instanceGroups/%s", project, zone, name.(string)) } else if selfLink, ok := d.GetOk("self_link"); ok { parsed, err := tpgresource.ParseInstanceGroupFieldValue(selfLink.(string), d, config) if err != nil { @@ -108,10 +109,20 @@ func dataSourceComputeInstanceGroupRead(d *schema.ResourceData, meta interface{} if err := d.Set("project", parsed.Project); err != nil { return fmt.Errorf("Error setting project: %s", err) } - d.SetId(fmt.Sprintf("projects/%s/zones/%s/instanceGroups/%s", parsed.Project, parsed.Zone, parsed.Name)) + id = fmt.Sprintf("projects/%s/zones/%s/instanceGroups/%s", parsed.Project, parsed.Zone, parsed.Name) } else { return errors.New("Must provide either `self_link` or `zone/name`") } + d.SetId(id) - return resourceComputeInstanceGroupRead(d, meta) + err := resourceComputeInstanceGroupRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_network.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_network.go index aa12f0b8423e..e0a6b9b63201 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_network.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_network.go @@ -59,9 +59,12 @@ func dataSourceGoogleComputeNetworkRead(d *schema.ResourceData, meta interface{} return err } name := d.Get("name").(string) + + id := fmt.Sprintf("projects/%s/global/networks/%s", project, name) + network, err := config.NewComputeClient(userAgent).Networks.Get(project, name).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Network Not Found : %s", name)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Network Not Found : %s", name), id) } if err := d.Set("gateway_ipv4", network.GatewayIPv4); err != nil { return fmt.Errorf("Error setting gateway_ipv4: %s", err) @@ -75,6 +78,6 @@ func dataSourceGoogleComputeNetworkRead(d *schema.ResourceData, meta interface{} if err := d.Set("subnetworks_self_links", network.Subnetworks); err != nil { return fmt.Errorf("Error setting subnetworks_self_links: %s", err) } - d.SetId(fmt.Sprintf("projects/%s/global/networks/%s", project, network.Name)) + d.SetId(id) return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_group.go.erb b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_group.go.erb index 43c8499ce26b..b4820f426979 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_group.go.erb +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_group.go.erb @@ -104,11 +104,11 @@ func dataSourceComputeRegionInstanceGroupRead(d *schema.ResourceData, meta inter if err != nil { return err } - + id := fmt.Sprintf("projects/%s/regions/%s/instanceGroups/%s", project, region, name) instanceGroup, err := config.NewComputeClient(userAgent).RegionInstanceGroups.Get( project, region, name).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Region Instance Group %q", name)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Region Instance Group %q", name), id) } members, err := config.NewComputeClient(userAgent).RegionInstanceGroups.ListInstances( @@ -129,7 +129,7 @@ func dataSourceComputeRegionInstanceGroupRead(d *schema.ResourceData, meta inter return fmt.Errorf("Error setting instances: %s", err) } } - d.SetId(fmt.Sprintf("projects/%s/regions/%s/instanceGroups/%s", project, region, name)) + d.SetId(id) if err := d.Set("self_link", instanceGroup.SelfLink); err != nil { return fmt.Errorf("Error setting self_link: %s", err) } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_network_endpoint_group.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_network_endpoint_group.go index 0147cd280d3d..3834a12ce9bf 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_network_endpoint_group.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_network_endpoint_group.go @@ -26,6 +26,7 @@ func DataSourceGoogleComputeRegionNetworkEndpointGroup() *schema.Resource { func dataSourceComputeRegionNetworkEndpointGroupRead(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) + id := "" if name, ok := d.GetOk("name"); ok { project, err := tpgresource.GetProject(d, config) if err != nil { @@ -36,7 +37,7 @@ func dataSourceComputeRegionNetworkEndpointGroupRead(d *schema.ResourceData, met return err } - d.SetId(fmt.Sprintf("projects/%s/regions/%s/networkEndpointGroups/%s", project, region, name.(string))) + id = fmt.Sprintf("projects/%s/regions/%s/networkEndpointGroups/%s", project, region, name.(string)) } else if selfLink, ok := d.GetOk("self_link"); ok { parsed, err := tpgresource.ParseNetworkEndpointGroupRegionalFieldValue(selfLink.(string), d, config) if err != nil { @@ -52,10 +53,19 @@ func dataSourceComputeRegionNetworkEndpointGroupRead(d *schema.ResourceData, met return fmt.Errorf("Error setting region: %s", err) } - d.SetId(fmt.Sprintf("projects/%s/regions/%s/networkEndpointGroups/%s", parsed.Project, parsed.Region, parsed.Name)) + id = fmt.Sprintf("projects/%s/regions/%s/networkEndpointGroups/%s", parsed.Project, parsed.Region, parsed.Name) } else { return errors.New("Must provide either `self_link` or `region/name`") } + d.SetId(id) + err := resourceComputeRegionNetworkEndpointGroupRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } - return resourceComputeRegionNetworkEndpointGroupRead(d, meta) + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_ssl_certificate.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_ssl_certificate.go index a42e9bc85491..17305595d0a6 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_ssl_certificate.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_ssl_certificate.go @@ -33,7 +33,16 @@ func dataSourceComputeRegionSslCertificateRead(d *schema.ResourceData, meta inte return err } - d.SetId(fmt.Sprintf("projects/%s/regions/%s/sslCertificates/%s", project, region, name)) + id := fmt.Sprintf("projects/%s/regions/%s/sslCertificates/%s", project, region, name) + d.SetId(id) - return resourceComputeRegionSslCertificateRead(d, meta) + err = resourceComputeRegionSslCertificateRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_resource_policy.go.erb b/mmv1/third_party/terraform/services/compute/data_source_google_compute_resource_policy.go.erb index 3485a7051fe3..ae8d93646032 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_resource_policy.go.erb +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_resource_policy.go.erb @@ -36,7 +36,17 @@ func dataSourceGoogleComputeResourcePolicyRead(d *schema.ResourceData, meta inte return err } - d.SetId(fmt.Sprintf("projects/%s/regions/%s/resourcePolicies/%s", project, region, name)) + id := fmt.Sprintf("projects/%s/regions/%s/resourcePolicies/%s", project, region, name) + d.SetId(id) - return resourceComputeResourcePolicyRead(d, meta) + err = resourceComputeResourcePolicyRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_router.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_router.go index 01f1ab0218e6..af235d576544 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_router.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_router.go @@ -1,6 +1,8 @@ package compute import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-google/google/tpgresource" ) @@ -22,5 +24,13 @@ func dataSourceComputeRouterRead(d *schema.ResourceData, meta interface{}) error routerName := d.Get("name").(string) d.SetId(routerName) - return resourceComputeRouterRead(d, meta) + err := resourceComputeRouterRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", routerName) + } + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_router_nat.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_router_nat.go index b9f8fd1dae48..b74823b94b21 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_router_nat.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_router_nat.go @@ -31,5 +31,14 @@ func dataSourceGoogleComputeRouterNatRead(d *schema.ResourceData, meta interface } d.SetId(id) - return resourceComputeRouterNatRead(d, meta) + err = resourceComputeRouterNatRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_ssl_certificate.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_ssl_certificate.go index 20e9bf9d4110..31cc3426988d 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_ssl_certificate.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_ssl_certificate.go @@ -33,7 +33,17 @@ func dataSourceComputeSslCertificateRead(d *schema.ResourceData, meta interface{ } certificateName := d.Get("name").(string) - d.SetId(fmt.Sprintf("projects/%s/global/sslCertificates/%s", project, certificateName)) + id := fmt.Sprintf("projects/%s/global/sslCertificates/%s", project, certificateName) + d.SetId(id) - return resourceComputeSslCertificateRead(d, meta) + err = resourceComputeSslCertificateRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_ssl_policy.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_ssl_policy.go index 8710928be8e4..1266e7370867 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_ssl_policy.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_ssl_policy.go @@ -33,7 +33,17 @@ func datasourceComputeSslPolicyRead(d *schema.ResourceData, meta interface{}) er } policyName := d.Get("name").(string) - d.SetId(fmt.Sprintf("projects/%s/global/sslPolicies/%s", project, policyName)) + id := fmt.Sprintf("projects/%s/global/sslPolicies/%s", project, policyName) + d.SetId(id) - return resourceComputeSslPolicyRead(d, meta) + err = resourceComputeSslPolicyRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_subnetwork.go.erb b/mmv1/third_party/terraform/services/compute/data_source_google_compute_subnetwork.go.erb index 5652ba319f87..5af117f5893d 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_subnetwork.go.erb +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_subnetwork.go.erb @@ -90,10 +90,11 @@ func dataSourceGoogleComputeSubnetworkRead(d *schema.ResourceData, meta interfac if err != nil { return err } + id := fmt.Sprintf("projects/%s/regions/%s/subnetworks/%s", project, region, name) subnetwork, err := config.NewComputeClient(userAgent).Subnetworks.Get(project, region, name).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Subnetwork Not Found : %s", name)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Subnetwork Not Found : %s", name), id) } if err := d.Set("ip_cidr_range", subnetwork.IpCidrRange); err != nil { @@ -127,7 +128,7 @@ func dataSourceGoogleComputeSubnetworkRead(d *schema.ResourceData, meta interfac return fmt.Errorf("Error setting secondary_ip_range: %s", err) } - d.SetId(fmt.Sprintf("projects/%s/regions/%s/subnetworks/%s", project, region, name)) + d.SetId(id) return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_vpn_gateway.go.erb b/mmv1/third_party/terraform/services/compute/data_source_google_compute_vpn_gateway.go.erb index e11c1711211b..ba7f79403e9d 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_vpn_gateway.go.erb +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_vpn_gateway.go.erb @@ -72,12 +72,13 @@ func dataSourceGoogleComputeVpnGatewayRead(d *schema.ResourceData, meta interfac } name := d.Get("name").(string) + id := fmt.Sprintf("projects/%s/regions/%s/targetVpnGateways/%s", project, region, name) vpnGatewaysService := compute.NewTargetVpnGatewaysService(config.NewComputeClient(userAgent)) gateway, err := vpnGatewaysService.Get(project, region, name).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("VPN Gateway Not Found : %s", name)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("VPN Gateway Not Found : %s", name), id) } if err := d.Set("network", tpgresource.ConvertSelfLinkToV1(gateway.Network)); err != nil { return fmt.Errorf("Error setting network: %s", err) @@ -94,6 +95,6 @@ func dataSourceGoogleComputeVpnGatewayRead(d *schema.ResourceData, meta interfac if err := d.Set("project", project); err != nil { return fmt.Errorf("Error setting project: %s", err) } - d.SetId(fmt.Sprintf("projects/%s/regions/%s/targetVpnGateways/%s", project, region, name)) + d.SetId(id) return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_global_compute_forwarding_rule.go b/mmv1/third_party/terraform/services/compute/data_source_google_global_compute_forwarding_rule.go index 1b25c01babef..ed1bad56b537 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_global_compute_forwarding_rule.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_global_compute_forwarding_rule.go @@ -33,7 +33,17 @@ func dataSourceGoogleComputeGlobalForwardingRuleRead(d *schema.ResourceData, met return err } - d.SetId(fmt.Sprintf("projects/%s/global/forwardingRules/%s", project, name)) + id := fmt.Sprintf("projects/%s/global/forwardingRules/%s", project, name) + d.SetId(id) - return resourceComputeGlobalForwardingRuleRead(d, meta) + err = resourceComputeGlobalForwardingRuleRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/dataprocmetastore/data_source_dataproc_metastore_service.go.erb b/mmv1/third_party/terraform/services/dataprocmetastore/data_source_dataproc_metastore_service.go.erb index 6a351893759d..76b166edfa33 100644 --- a/mmv1/third_party/terraform/services/dataprocmetastore/data_source_dataproc_metastore_service.go.erb +++ b/mmv1/third_party/terraform/services/dataprocmetastore/data_source_dataproc_metastore_service.go.erb @@ -28,5 +28,13 @@ func dataSourceDataprocMetastoreServiceRead(d *schema.ResourceData, meta interfa return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceDataprocMetastoreServiceRead(d, meta) + err = resourceDataprocMetastoreServiceRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/dns/data_source_dns_keys.go b/mmv1/third_party/terraform/services/dns/data_source_dns_keys.go index 1cc9c8af095f..470815cdc2d0 100644 --- a/mmv1/third_party/terraform/services/dns/data_source_dns_keys.go +++ b/mmv1/third_party/terraform/services/dns/data_source_dns_keys.go @@ -16,7 +16,6 @@ import ( "github.com/hashicorp/terraform-provider-google/google/fwmodels" "github.com/hashicorp/terraform-provider-google/google/fwresource" "github.com/hashicorp/terraform-provider-google/google/fwtransport" - transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" ) // Ensure the implementation satisfies the expected interfaces @@ -179,9 +178,7 @@ func (d *GoogleDnsKeysDataSource) Read(ctx context.Context, req datasource.ReadR clientResp, err := d.client.DnsKeys.List(data.Project.ValueString(), data.ManagedZone.ValueString()).Do() if err != nil { - if !transport_tpg.IsGoogleApiErrorWithCode(err, 404) { - resp.Diagnostics.AddError(fmt.Sprintf("Error when reading or editing dataSourceDnsKeys"), err.Error()) - } + resp.Diagnostics.AddError(fmt.Sprintf("Error when reading or editing dataSourceDnsKeys"), err.Error()) // Save data into Terraform state resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) return diff --git a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_android_app.go.erb b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_android_app.go.erb index e9167e5d8d3e..1c8ca39a6f46 100644 --- a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_android_app.go.erb +++ b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_android_app.go.erb @@ -37,6 +37,14 @@ func dataSourceGoogleFirebaseAndroidAppRead(d *schema.ResourceData, meta interfa if err := d.Set("name", name); err != nil { return fmt.Errorf("Error setting name: %s", err) } - return resourceFirebaseAndroidAppRead(d, meta) + err = resourceFirebaseAndroidAppRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", name) + } + return nil } <% end -%> diff --git a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_apple_app.go.erb b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_apple_app.go.erb index 9d2351c22011..8737c2800b1a 100644 --- a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_apple_app.go.erb +++ b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_apple_app.go.erb @@ -37,6 +37,14 @@ func dataSourceGoogleFirebaseAppleAppRead(d *schema.ResourceData, meta interface if err := d.Set("name", name); err != nil { return fmt.Errorf("Error setting name: %s", err) } - return resourceFirebaseAppleAppRead(d, meta) + err = resourceFirebaseAppleAppRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", name) + } + return nil } <% end -%> diff --git a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app.go.erb b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app.go.erb index d6da3622e83c..4c5616580314 100644 --- a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app.go.erb +++ b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app.go.erb @@ -37,6 +37,14 @@ func dataSourceGoogleFirebaseWebAppRead(d *schema.ResourceData, meta interface{} if err := d.Set("name", name); err != nil { return fmt.Errorf("Error setting name: %s", err) } - return resourceFirebaseWebAppRead(d, meta) + err = resourceFirebaseWebAppRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", name) + } + return nil } <% end -%> diff --git a/mmv1/third_party/terraform/services/firebasehosting/data_source_google_firebase_hosting_channel.go.erb b/mmv1/third_party/terraform/services/firebasehosting/data_source_google_firebase_hosting_channel.go.erb index c8cd9e60a3a1..993392fd2b1c 100644 --- a/mmv1/third_party/terraform/services/firebasehosting/data_source_google_firebase_hosting_channel.go.erb +++ b/mmv1/third_party/terraform/services/firebasehosting/data_source_google_firebase_hosting_channel.go.erb @@ -31,6 +31,14 @@ func dataSourceGoogleFirebaseHostingChannelRead(d *schema.ResourceData, meta int } d.SetId(id) - return resourceFirebaseHostingChannelRead(d, meta) + err = resourceFirebaseHostingChannelRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } <% end -%> diff --git a/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool.go.erb b/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool.go.erb index 88588781b10d..6df5264d41b5 100644 --- a/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool.go.erb +++ b/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool.go.erb @@ -31,7 +31,15 @@ func dataSourceIAMBetaWorkloadIdentityPoolRead(d *schema.ResourceData, meta inte return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceIAMBetaWorkloadIdentityPoolRead(d, meta) + err = resourceIAMBetaWorkloadIdentityPoolRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } <% end -%> diff --git a/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool_provider.go.erb b/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool_provider.go.erb index 0aef39e9cfbc..582cd395c5fb 100644 --- a/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool_provider.go.erb +++ b/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool_provider.go.erb @@ -32,7 +32,15 @@ func dataSourceIAMBetaWorkloadIdentityPoolProviderRead(d *schema.ResourceData, m return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceIAMBetaWorkloadIdentityPoolProviderRead(d, meta) + err = resourceIAMBetaWorkloadIdentityPoolProviderRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } <% end -%> diff --git a/mmv1/third_party/terraform/services/iap/data_source_iap_client.go b/mmv1/third_party/terraform/services/iap/data_source_iap_client.go index 6cd3a863188d..736e18da0fe3 100644 --- a/mmv1/third_party/terraform/services/iap/data_source_iap_client.go +++ b/mmv1/third_party/terraform/services/iap/data_source_iap_client.go @@ -27,5 +27,13 @@ func dataSourceGoogleIapClientRead(d *schema.ResourceData, meta interface{}) err return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceIapClientRead(d, meta) + err = resourceIapClientRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/kms/data_source_google_kms_crypto_key.go b/mmv1/third_party/terraform/services/kms/data_source_google_kms_crypto_key.go index 84c124eba250..0d39492d0f27 100644 --- a/mmv1/third_party/terraform/services/kms/data_source_google_kms_crypto_key.go +++ b/mmv1/third_party/terraform/services/kms/data_source_google_kms_crypto_key.go @@ -1,6 +1,8 @@ package kms 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" @@ -31,7 +33,16 @@ func dataSourceGoogleKmsCryptoKeyRead(d *schema.ResourceData, meta interface{}) Name: d.Get("name").(string), } - d.SetId(cryptoKeyId.CryptoKeyId()) + id := cryptoKeyId.CryptoKeyId() + d.SetId(id) + + err = resourceKMSCryptoKeyRead(d, meta) + if err != nil { + return err + } - return resourceKMSCryptoKeyRead(d, meta) + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/kms/data_source_google_kms_crypto_key_version.go b/mmv1/third_party/terraform/services/kms/data_source_google_kms_crypto_key_version.go index eb7253f2c674..21192c68ea48 100644 --- a/mmv1/third_party/terraform/services/kms/data_source_google_kms_crypto_key_version.go +++ b/mmv1/third_party/terraform/services/kms/data_source_google_kms_crypto_key_version.go @@ -87,7 +87,7 @@ func dataSourceGoogleKmsCryptoKeyVersionRead(d *schema.ResourceData, meta interf UserAgent: userAgent, }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("KmsCryptoKeyVersion %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("KmsCryptoKeyVersion %q", d.Id()), url) } if err := d.Set("version", flattenKmsCryptoKeyVersionVersion(res["name"], d)); err != nil { @@ -120,7 +120,7 @@ func dataSourceGoogleKmsCryptoKeyVersionRead(d *schema.ResourceData, meta interf UserAgent: userAgent, }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("KmsCryptoKey %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("KmsCryptoKey %q", d.Id()), url) } if res["purpose"] == "ASYMMETRIC_SIGN" || res["purpose"] == "ASYMMETRIC_DECRYPT" { diff --git a/mmv1/third_party/terraform/services/kms/data_source_google_kms_key_ring.go b/mmv1/third_party/terraform/services/kms/data_source_google_kms_key_ring.go index ae1bc4f73199..7a47f9b798ef 100644 --- a/mmv1/third_party/terraform/services/kms/data_source_google_kms_key_ring.go +++ b/mmv1/third_party/terraform/services/kms/data_source_google_kms_key_ring.go @@ -1,6 +1,8 @@ package kms 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" @@ -31,7 +33,16 @@ func dataSourceGoogleKmsKeyRingRead(d *schema.ResourceData, meta interface{}) er Location: d.Get("location").(string), Project: project, } - d.SetId(keyRingId.KeyRingId()) + id := keyRingId.KeyRingId() + d.SetId(id) + + err = resourceKMSKeyRingRead(d, meta) + if err != nil { + return err + } - return resourceKMSKeyRingRead(d, meta) + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/logging/data_source_google_logging_project_cmek_settings.go b/mmv1/third_party/terraform/services/logging/data_source_google_logging_project_cmek_settings.go index a2b30a6e414a..f839cbe7a868 100644 --- a/mmv1/third_party/terraform/services/logging/data_source_google_logging_project_cmek_settings.go +++ b/mmv1/third_party/terraform/services/logging/data_source_google_logging_project_cmek_settings.go @@ -85,7 +85,7 @@ func dataSourceGoogleLoggingProjectCmekSettingsRead(d *schema.ResourceData, meta UserAgent: userAgent, }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("LoggingProjectCmekSettings %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("LoggingProjectCmekSettings %q", d.Id()), url) } d.SetId(fmt.Sprintf("projects/%s/cmekSettings", project)) diff --git a/mmv1/third_party/terraform/services/logging/data_source_google_logging_sink.go b/mmv1/third_party/terraform/services/logging/data_source_google_logging_sink.go index 64788602d8d7..95cf8663a709 100644 --- a/mmv1/third_party/terraform/services/logging/data_source_google_logging_sink.go +++ b/mmv1/third_party/terraform/services/logging/data_source_google_logging_sink.go @@ -33,7 +33,7 @@ func dataSourceGoogleLoggingSinkRead(d *schema.ResourceData, meta interface{}) e sink, err := config.NewLoggingClient(userAgent).Sinks.Get(sinkId).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Logging Sink %s", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Logging Sink %s", d.Id()), sinkId) } if err := flattenResourceLoggingSink(d, sink); err != nil { diff --git a/mmv1/third_party/terraform/services/privateca/data_source_certificate_authority.go b/mmv1/third_party/terraform/services/privateca/data_source_certificate_authority.go index 1c72eda30b86..b2beeb943b01 100644 --- a/mmv1/third_party/terraform/services/privateca/data_source_certificate_authority.go +++ b/mmv1/third_party/terraform/services/privateca/data_source_certificate_authority.go @@ -73,7 +73,7 @@ func dataSourcePrivatecaCertificateAuthorityRead(d *schema.ResourceData, meta in UserAgent: userAgent, }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("PrivatecaCertificateAuthority %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("PrivatecaCertificateAuthority %q", d.Id()), url) } if err := d.Set("pem_csr", res["pemCsr"]); err != nil { return fmt.Errorf("Error fetching CertificateAuthority: %s", err) diff --git a/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_subscription.go b/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_subscription.go index 745315ad39fd..2e0b49ecb368 100644 --- a/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_subscription.go +++ b/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_subscription.go @@ -28,5 +28,13 @@ func dataSourceGooglePubsubSubscriptionRead(d *schema.ResourceData, meta interfa return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourcePubsubSubscriptionRead(d, meta) + err = resourcePubsubSubscriptionRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_topic.go b/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_topic.go index 9e0fbb909b11..158d1c600535 100644 --- a/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_topic.go +++ b/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_topic.go @@ -28,5 +28,13 @@ func dataSourceGooglePubsubTopicRead(d *schema.ResourceData, meta interface{}) e return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourcePubsubTopicRead(d, meta) + err = resourcePubsubTopicRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/redis/data_source_redis_instance.go b/mmv1/third_party/terraform/services/redis/data_source_redis_instance.go index b3da20ecba44..2dd7ad098b71 100644 --- a/mmv1/third_party/terraform/services/redis/data_source_redis_instance.go +++ b/mmv1/third_party/terraform/services/redis/data_source_redis_instance.go @@ -1,6 +1,8 @@ package redis 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" @@ -29,5 +31,13 @@ func dataSourceGoogleRedisInstanceRead(d *schema.ResourceData, meta interface{}) } d.SetId(id) - return resourceRedisInstanceRead(d, meta) + err = resourceRedisInstanceRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_folder.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_folder.go index fa3099bb8bd5..fb95137a83cc 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_folder.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_folder.go @@ -61,13 +61,14 @@ func dataSourceFolderRead(d *schema.ResourceData, meta interface{}) error { return err } - d.SetId(canonicalFolderName(d.Get("folder").(string))) + id := canonicalFolderName(d.Get("folder").(string)) + d.SetId(id) if err := resourceGoogleFolderRead(d, meta); err != nil { return err } // If resource doesn't exist, read will not set ID and we should return error. if d.Id() == "" { - return nil + return fmt.Errorf("%s not found", id) } if v, ok := d.GetOk("lookup_organization"); ok && v.(bool) { diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_folder_organization_policy.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_folder_organization_policy.go index a0bbf3fbd779..aa7249c8e99b 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_folder_organization_policy.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_folder_organization_policy.go @@ -22,7 +22,16 @@ func DataSourceGoogleFolderOrganizationPolicy() *schema.Resource { func datasourceGoogleFolderOrganizationPolicyRead(d *schema.ResourceData, meta interface{}) error { - d.SetId(fmt.Sprintf("%s/%s", d.Get("folder"), d.Get("constraint"))) + id := fmt.Sprintf("%s/%s", d.Get("folder"), d.Get("constraint")) + d.SetId(id) - return resourceGoogleFolderOrganizationPolicyRead(d, meta) + err := resourceGoogleFolderOrganizationPolicyRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_iam_role.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_iam_role.go index 83639d864e95..aad1818e1624 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_iam_role.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_iam_role.go @@ -43,7 +43,7 @@ func dataSourceGoogleIamRoleRead(d *schema.ResourceData, meta interface{}) error roleName := d.Get("name").(string) role, err := config.NewIamClient(userAgent).Roles.Get(roleName).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Error reading IAM Role %s: %s", roleName, err)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Error reading IAM Role %s: %s", roleName, err), roleName) } d.SetId(role.Name) diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_organization.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_organization.go index d600eebddaa9..294a1b652aef 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_organization.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_organization.go @@ -103,7 +103,7 @@ func dataSourceOrganizationRead(d *schema.ResourceData, meta interface{}) error Timeout: d.Timeout(schema.TimeoutRead), }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Organization Not Found : %s", v)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Organization Not Found : %s", v), canonicalOrganizationName(v.(string))) } organization = resp diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_organization_policy.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_organization_policy.go index 597b51beb943..6aaa7d54dcfc 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_organization_policy.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_organization_policy.go @@ -22,7 +22,16 @@ func DataSourceGoogleProjectOrganizationPolicy() *schema.Resource { func datasourceGoogleProjectOrganizationPolicyRead(d *schema.ResourceData, meta interface{}) error { - d.SetId(fmt.Sprintf("%s:%s", d.Get("project"), d.Get("constraint"))) + id := fmt.Sprintf("%s:%s", d.Get("project"), d.Get("constraint")) + d.SetId(id) - return resourceGoogleProjectOrganizationPolicyRead(d, meta) + err := resourceGoogleProjectOrganizationPolicyRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_service.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_service.go index d056b6489828..7bcaa985ca2d 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_service.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_service.go @@ -28,5 +28,13 @@ func dataSourceGoogleProjectServiceRead(d *schema.ResourceData, meta interface{} return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceGoogleProjectServiceRead(d, meta) + err = resourceGoogleProjectServiceRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_account.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_account.go index c917c396dfbc..15b075a1e763 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_account.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_account.go @@ -59,7 +59,7 @@ func dataSourceGoogleServiceAccountRead(d *schema.ResourceData, meta interface{} sa, err := config.NewIamClient(userAgent).Projects.ServiceAccounts.Get(serviceAccountName).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Service Account %q", serviceAccountName)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Service Account %q", serviceAccountName), serviceAccountName) } d.SetId(sa.Name) diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_account_key.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_account_key.go index d3ab027a8cf0..95b47a88cc79 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_account_key.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_account_key.go @@ -66,7 +66,7 @@ func dataSourceGoogleServiceAccountKeyRead(d *schema.ResourceData, meta interfac // Confirm the service account key exists sak, err := config.NewIamClient(userAgent).Projects.ServiceAccounts.Keys.Get(keyName).PublicKeyType(publicKeyType).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Service Account Key %q", keyName)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Service Account Key %q", keyName), keyName) } d.SetId(sak.Name) diff --git a/mmv1/third_party/terraform/services/runtimeconfig/data_source_runtimeconfig_config.go.erb b/mmv1/third_party/terraform/services/runtimeconfig/data_source_runtimeconfig_config.go.erb index 1d2ae6c688e4..eca8279a8ae3 100644 --- a/mmv1/third_party/terraform/services/runtimeconfig/data_source_runtimeconfig_config.go.erb +++ b/mmv1/third_party/terraform/services/runtimeconfig/data_source_runtimeconfig_config.go.erb @@ -31,6 +31,14 @@ func dataSourceGoogleRuntimeconfigConfigRead(d *schema.ResourceData, meta interf return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceRuntimeconfigConfigRead(d, meta) + err = resourceRuntimeconfigConfigRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } <% end %> diff --git a/mmv1/third_party/terraform/services/runtimeconfig/data_source_runtimeconfig_variable.go.erb b/mmv1/third_party/terraform/services/runtimeconfig/data_source_runtimeconfig_variable.go.erb index 3d3538dca306..9531af6cda41 100644 --- a/mmv1/third_party/terraform/services/runtimeconfig/data_source_runtimeconfig_variable.go.erb +++ b/mmv1/third_party/terraform/services/runtimeconfig/data_source_runtimeconfig_variable.go.erb @@ -33,7 +33,15 @@ func dataSourceGoogleRuntimeconfigVariableRead(d *schema.ResourceData, meta inte return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceRuntimeconfigVariableRead(d, meta) + err = resourceRuntimeconfigVariableRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } <% end -%> diff --git a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret.go b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret.go index 6f424b7cd691..a7a725dccfa5 100644 --- a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret.go +++ b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret.go @@ -26,5 +26,13 @@ func dataSourceSecretManagerSecretRead(d *schema.ResourceData, meta interface{}) return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceSecretManagerSecretRead(d, meta) + err = resourceSecretManagerSecretRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/sourcerepo/data_source_sourcerepo_repository.go b/mmv1/third_party/terraform/services/sourcerepo/data_source_sourcerepo_repository.go index 5fa2a433c7bf..03dd46452142 100644 --- a/mmv1/third_party/terraform/services/sourcerepo/data_source_sourcerepo_repository.go +++ b/mmv1/third_party/terraform/services/sourcerepo/data_source_sourcerepo_repository.go @@ -31,5 +31,13 @@ func dataSourceGoogleSourceRepoRepositoryRead(d *schema.ResourceData, meta inter } d.SetId(id) - return resourceSourceRepoRepositoryRead(d, meta) + err = resourceSourceRepoRepositoryRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/spanner/data_source_spanner_instance.go b/mmv1/third_party/terraform/services/spanner/data_source_spanner_instance.go index 26dff8a17c7d..4c1fb9a0c563 100644 --- a/mmv1/third_party/terraform/services/spanner/data_source_spanner_instance.go +++ b/mmv1/third_party/terraform/services/spanner/data_source_spanner_instance.go @@ -32,5 +32,13 @@ func dataSourceSpannerInstanceRead(d *schema.ResourceData, meta interface{}) err } d.SetId(id) - return resourceSpannerInstanceRead(d, meta) + err = resourceSpannerInstanceRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/sql/data_source_sql_database.go b/mmv1/third_party/terraform/services/sql/data_source_sql_database.go index 264cde5a1f4f..5c4696314c59 100644 --- a/mmv1/third_party/terraform/services/sql/data_source_sql_database.go +++ b/mmv1/third_party/terraform/services/sql/data_source_sql_database.go @@ -27,11 +27,15 @@ func dataSourceSqlDatabaseRead(d *schema.ResourceData, meta interface{}) error { if err != nil { return fmt.Errorf("Error fetching project for Database: %s", err) } - d.SetId(fmt.Sprintf("projects/%s/instances/%s/databases/%s", project, d.Get("instance").(string), d.Get("name").(string))) + id := fmt.Sprintf("projects/%s/instances/%s/databases/%s", project, d.Get("instance").(string), d.Get("name").(string)) + d.SetId(id) err = resourceSQLDatabaseRead(d, meta) if err != nil { return err } + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } if err := d.Set("deletion_policy", nil); err != nil { return fmt.Errorf("Error setting deletion_policy: %s", err) } diff --git a/mmv1/third_party/terraform/services/sql/data_source_sql_database_instance.go b/mmv1/third_party/terraform/services/sql/data_source_sql_database_instance.go index 9aac126ad1e9..e9135ba07723 100644 --- a/mmv1/third_party/terraform/services/sql/data_source_sql_database_instance.go +++ b/mmv1/third_party/terraform/services/sql/data_source_sql_database_instance.go @@ -1,6 +1,8 @@ package sql import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-google/google/tpgresource" ) @@ -18,7 +20,15 @@ func DataSourceSqlDatabaseInstance() *schema.Resource { } func dataSourceSqlDatabaseInstanceRead(d *schema.ResourceData, meta interface{}) error { + id := d.Get("name").(string) + err := resourceSqlDatabaseInstanceRead(d, meta) + if err != nil { + return err + } - return resourceSqlDatabaseInstanceRead(d, meta) + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/sql/data_source_sql_databases.go b/mmv1/third_party/terraform/services/sql/data_source_sql_databases.go index ed4ecc4f4f9d..1662765ab489 100644 --- a/mmv1/third_party/terraform/services/sql/data_source_sql_databases.go +++ b/mmv1/third_party/terraform/services/sql/data_source_sql_databases.go @@ -60,7 +60,7 @@ func dataSourceSqlDatabasesRead(d *schema.ResourceData, meta interface{}) error }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Databases in %q instance", d.Get("instance").(string))) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Databases in %q instance", d.Get("instance").(string)), fmt.Sprintf("Databases in %q instance", d.Get("instance").(string))) } flattenedDatabases := flattenDatabases(databases.Items) diff --git a/mmv1/third_party/terraform/services/storage/data_source_google_storage_project_service_account.go b/mmv1/third_party/terraform/services/storage/data_source_google_storage_project_service_account.go index 0b248d5b53ca..188627eb2838 100644 --- a/mmv1/third_party/terraform/services/storage/data_source_google_storage_project_service_account.go +++ b/mmv1/third_party/terraform/services/storage/data_source_google_storage_project_service_account.go @@ -55,7 +55,7 @@ func dataSourceGoogleStorageProjectServiceAccountRead(d *schema.ResourceData, me serviceAccount, err := serviceAccountGetRequest.Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, "GCS service account not found") + return transport_tpg.HandleDataSourceNotFoundError(err, d, "GCS service account not found", fmt.Sprintf("Project %q GCS service account", project)) } if err := d.Set("project", project); err != nil { diff --git a/mmv1/third_party/terraform/services/storagetransfer/data_source_google_storage_transfer_project_service_account.go b/mmv1/third_party/terraform/services/storagetransfer/data_source_google_storage_transfer_project_service_account.go index 4dc7ec9413b1..584791693df6 100644 --- a/mmv1/third_party/terraform/services/storagetransfer/data_source_google_storage_transfer_project_service_account.go +++ b/mmv1/third_party/terraform/services/storagetransfer/data_source_google_storage_transfer_project_service_account.go @@ -47,7 +47,7 @@ func dataSourceGoogleStorageTransferProjectServiceAccountRead(d *schema.Resource serviceAccount, err := config.NewStorageTransferClient(userAgent).GoogleServiceAccounts.Get(project).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, "Google Cloud Storage Transfer service account not found") + return transport_tpg.HandleDataSourceNotFoundError(err, d, "Google Cloud Storage Transfer service account not found", fmt.Sprintf("Project %q Google Cloud Storage Transfer account", project)) } d.SetId(serviceAccount.AccountEmail) diff --git a/mmv1/third_party/terraform/services/vertexai/data_source_vertex_ai_index.go b/mmv1/third_party/terraform/services/vertexai/data_source_vertex_ai_index.go index 50e58e12c221..8cd28fdb7044 100644 --- a/mmv1/third_party/terraform/services/vertexai/data_source_vertex_ai_index.go +++ b/mmv1/third_party/terraform/services/vertexai/data_source_vertex_ai_index.go @@ -29,5 +29,13 @@ func dataSourceVertexAIIndexRead(d *schema.ResourceData, meta interface{}) error return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceVertexAIIndexRead(d, meta) + err = resourceVertexAIIndexRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_cluster.go.erb b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_cluster.go.erb index b5668f99aaee..cdeff513d0e0 100644 --- a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_cluster.go.erb +++ b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_cluster.go.erb @@ -28,6 +28,14 @@ func dataSourceVmwareengineClusterRead(d *schema.ResourceData, meta interface{}) return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceVmwareengineClusterRead(d, meta) + err = resourceVmwareengineClusterRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } <% end -%> \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network.go.erb b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network.go.erb index dbbdfa4f2fd8..87465bef390a 100644 --- a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network.go.erb +++ b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network.go.erb @@ -30,6 +30,14 @@ func dataSourceVmwareengineNetworkRead(d *schema.ResourceData, meta interface{}) return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceVmwareengineNetworkRead(d, meta) + err = resourceVmwareengineNetworkRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } <% end -%> \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_private_cloud.go.erb b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_private_cloud.go.erb index 800536162504..915240857698 100644 --- a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_private_cloud.go.erb +++ b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_private_cloud.go.erb @@ -30,6 +30,14 @@ func dataSourceVmwareenginePrivateCloudRead(d *schema.ResourceData, meta interfa return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceVmwareenginePrivateCloudRead(d, meta) + err = resourceVmwareenginePrivateCloudRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } <% end -%> \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/vpcaccess/data_source_vpc_access_connector.go b/mmv1/third_party/terraform/services/vpcaccess/data_source_vpc_access_connector.go index 7caa852d8ee7..b8b79401c819 100644 --- a/mmv1/third_party/terraform/services/vpcaccess/data_source_vpc_access_connector.go +++ b/mmv1/third_party/terraform/services/vpcaccess/data_source_vpc_access_connector.go @@ -30,5 +30,13 @@ func dataSourceVPCAccessConnectorRead(d *schema.ResourceData, meta interface{}) d.SetId(id) - return resourceVPCAccessConnectorRead(d, meta) + err = resourceVPCAccessConnectorRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/transport/transport.go b/mmv1/third_party/terraform/transport/transport.go index 374841b34ec1..01f0fd1a1aa6 100644 --- a/mmv1/third_party/terraform/transport/transport.go +++ b/mmv1/third_party/terraform/transport/transport.go @@ -136,6 +136,15 @@ func HandleNotFoundError(err error, d *schema.ResourceData, resource string) err fmt.Sprintf("Error when reading or editing %s: {{err}}", resource), err) } +func HandleDataSourceNotFoundError(err error, d *schema.ResourceData, resource, url string) error { + if IsGoogleApiErrorWithCode(err, 404) { + return fmt.Errorf("%s not found", url) + } + + return errwrap.Wrapf( + fmt.Sprintf("Error when reading or editing %s: {{err}}", resource), err) +} + func IsGoogleApiErrorWithCode(err error, errCode int) bool { gerr, ok := errwrap.GetType(err, &googleapi.Error{}).(*googleapi.Error) return ok && gerr != nil && gerr.Code == errCode From acdfd68bf7acb86ab7df0107631c073a62ec67f3 Mon Sep 17 00:00:00 2001 From: Scott Suarez Date: Tue, 12 Sep 2023 15:36:42 -0700 Subject: [PATCH 29/67] Make `location` required on `google_cloudfunctions2_function` (#8928) --- mmv1/products/cloudfunctions2/Function.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/mmv1/products/cloudfunctions2/Function.yaml b/mmv1/products/cloudfunctions2/Function.yaml index 69d5e04907b7..a8ca2d64185a 100644 --- a/mmv1/products/cloudfunctions2/Function.yaml +++ b/mmv1/products/cloudfunctions2/Function.yaml @@ -251,6 +251,7 @@ parameters: - !ruby/object:Api::Type::String name: 'location' immutable: true + required: true url_param_only: true description: The location of this cloud function. properties: From ccc68deb0101b0c658991ee2dea984ae1f116e5c Mon Sep 17 00:00:00 2001 From: Scott Suarez Date: Tue, 12 Sep 2023 15:37:00 -0700 Subject: [PATCH 30/67] Transitioned `volumes.cloud_sql_instance.instances` to SET from array (#8929) --- 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 db919ee81e51..337e63381f52 100644 --- a/mmv1/products/cloudrunv2/Service.yaml +++ b/mmv1/products/cloudrunv2/Service.yaml @@ -690,6 +690,7 @@ properties: description: |- The Cloud SQL instance connection names, as can be found in https://console.cloud.google.com/sql/instances. Visit https://cloud.google.com/sql/docs/mysql/connect-run for more information on how to connect Cloud SQL and Cloud Run. Format: {project}:{location}:{instance} item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::NestedObject name: 'emptyDir' description: |- From 75dcc62694b06c8a8de1b4bb90da88a97c4fb082 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Wed, 13 Sep 2023 11:44:35 -0700 Subject: [PATCH 31/67] Support provider default labels for DCL resources (#8893) --- .../resource_clouddeploy_target_test.go | 278 ++++++++++++++++++ ...rce_dataproc_workflow_template_test.go.erb | 4 +- tpgtools/property.go | 37 ++- tpgtools/resource.go | 14 +- tpgtools/templates/resource.go.tmpl | 19 +- tpgtools/templates/serialization.go.tmpl | 2 +- 6 files changed, 345 insertions(+), 9 deletions(-) create mode 100644 mmv1/third_party/terraform/services/clouddeploy/resource_clouddeploy_target_test.go diff --git a/mmv1/third_party/terraform/services/clouddeploy/resource_clouddeploy_target_test.go b/mmv1/third_party/terraform/services/clouddeploy/resource_clouddeploy_target_test.go new file mode 100644 index 000000000000..e8393b2a09ba --- /dev/null +++ b/mmv1/third_party/terraform/services/clouddeploy/resource_clouddeploy_target_test.go @@ -0,0 +1,278 @@ +package clouddeploy_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 TestAccClouddeployTarget_withProviderDefaultLabels(t *testing.T) { + // The test failed if VCR testing is enabled, because the cached provider config is used. + // Any changes in the provider default labels will not be applied. + acctest.SkipIfVcr(t) + t.Parallel() + + context := map[string]interface{}{ + "project_name": envvar.GetTestProjectFromEnv(), + "region": envvar.GetTestRegionFromEnv(), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckClouddeployTargetDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccClouddeployTarget_withProviderDefaultLabels(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.%", "2"), + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.my_first_label", "example-label-1"), + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.my_second_label", "example-label-2"), + + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.%", "3"), + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.my_first_label", "example-label-1"), + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.my_second_label", "example-label-2"), + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.default_key1", "default_value1"), + + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "effective_labels.%", "3"), + ), + }, + { + ResourceName: "google_clouddeploy_target.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels", "annotations"}, + }, + { + Config: testAccClouddeployTarget_resourceLabelsOverridesProviderDefaultLabels(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.%", "3"), + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.my_first_label", "example-label-1"), + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.my_second_label", "example-label-2"), + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.default_key1", "value1"), + + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.%", "3"), + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.my_first_label", "example-label-1"), + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.my_second_label", "example-label-2"), + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.default_key1", "value1"), + + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "effective_labels.%", "3"), + ), + }, + { + ResourceName: "google_clouddeploy_target.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels", "annotations"}, + }, + { + Config: testAccClouddeployTarget_moveResourceLabelToProviderDefaultLabels(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.%", "2"), + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.my_first_label", "example-label-1"), + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.default_key1", "value1"), + + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.%", "3"), + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.my_first_label", "example-label-1"), + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.my_second_label", "example-label-2"), + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.default_key1", "value1"), + + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "effective_labels.%", "3"), + ), + }, + { + ResourceName: "google_clouddeploy_target.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels", "annotations"}, + }, + { + Config: testAccClouddeployTarget_resourceLabelsOverridesProviderDefaultLabels(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.%", "3"), + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.my_first_label", "example-label-1"), + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.my_second_label", "example-label-2"), + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "labels.default_key1", "value1"), + + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.%", "3"), + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.my_first_label", "example-label-1"), + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.my_second_label", "example-label-2"), + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "terraform_labels.default_key1", "value1"), + + resource.TestCheckResourceAttr("google_clouddeploy_target.primary", "effective_labels.%", "3"), + ), + }, + { + ResourceName: "google_clouddeploy_target.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels", "annotations"}, + }, + { + Config: testAccClouddeployTarget_withoutLabels(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckNoResourceAttr("google_clouddeploy_target.primary", "labels.%"), + resource.TestCheckNoResourceAttr("google_clouddeploy_target.primary", "terraform_labels.%"), + resource.TestCheckNoResourceAttr("google_clouddeploy_target.primary", "effective_labels.%"), + ), + }, + { + ResourceName: "google_clouddeploy_target.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels", "annotations"}, + }, + }, + }) +} + +func testAccClouddeployTarget_withProviderDefaultLabels(context map[string]interface{}) string { + return acctest.Nprintf(` +provider "google" { + default_labels = { + default_key1 = "default_value1" + } +} + +resource "google_clouddeploy_target" "primary" { + location = "%{region}" + name = "tf-test-target%{random_suffix}" + + deploy_parameters = { + deployParameterKey = "deployParameterValue" + } + + description = "basic description" + + gke { + cluster = "projects/%{project_name}/locations/%{region}/clusters/example-cluster-name" + } + + project = "%{project_name}" + require_approval = false + + annotations = { + my_first_annotation = "example-annotation-1" + + my_second_annotation = "example-annotation-2" + } + + labels = { + my_first_label = "example-label-1" + my_second_label = "example-label-2" + } +} +`, context) +} + +func testAccClouddeployTarget_resourceLabelsOverridesProviderDefaultLabels(context map[string]interface{}) string { + return acctest.Nprintf(` +provider "google" { + default_labels = { + default_key1 = "default_value1" + } +} + +resource "google_clouddeploy_target" "primary" { + location = "%{region}" + name = "tf-test-target%{random_suffix}" + + deploy_parameters = { + deployParameterKey = "deployParameterValue" + } + + description = "basic description" + + gke { + cluster = "projects/%{project_name}/locations/%{region}/clusters/example-cluster-name" + } + + project = "%{project_name}" + require_approval = false + + annotations = { + my_first_annotation = "example-annotation-1" + + my_second_annotation = "example-annotation-2" + } + + labels = { + my_first_label = "example-label-1" + my_second_label = "example-label-2" + default_key1 = "value1" + } +} +`, context) +} + +func testAccClouddeployTarget_moveResourceLabelToProviderDefaultLabels(context map[string]interface{}) string { + return acctest.Nprintf(` +provider "google" { + default_labels = { + default_key1 = "default_value1" + my_second_label = "example-label-2" + } +} + +resource "google_clouddeploy_target" "primary" { + location = "%{region}" + name = "tf-test-target%{random_suffix}" + + deploy_parameters = { + deployParameterKey = "deployParameterValue" + } + + description = "basic description" + + gke { + cluster = "projects/%{project_name}/locations/%{region}/clusters/example-cluster-name" + } + + project = "%{project_name}" + require_approval = false + + annotations = { + my_first_annotation = "example-annotation-1" + + my_second_annotation = "example-annotation-2" + } + + labels = { + my_first_label = "example-label-1" + default_key1 = "value1" + } +} +`, context) +} + +func testAccClouddeployTarget_withoutLabels(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_clouddeploy_target" "primary" { + location = "%{region}" + name = "tf-test-target%{random_suffix}" + + deploy_parameters = { + deployParameterKey = "deployParameterValue" + } + + description = "basic description" + + gke { + cluster = "projects/%{project_name}/locations/%{region}/clusters/example-cluster-name" + } + + project = "%{project_name}" + require_approval = false + + annotations = { + my_first_annotation = "example-annotation-1" + + my_second_annotation = "example-annotation-2" + } +} +`, context) +} diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_workflow_template_test.go.erb b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_workflow_template_test.go.erb index aa3dc64a6223..21988d0cb673 100644 --- a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_workflow_template_test.go.erb +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_workflow_template_test.go.erb @@ -38,9 +38,9 @@ func TestAccDataprocWorkflowTemplate_basic(t *testing.T) { ImportState: true, ImportStateVerify: true, // The "labels" field in the state are decided by the configuration. - // During importing, as the configuration is unavailableafter, the "labels" field in the state will be empty. + // During importing, as the configuration is unavailable, the "labels" field in the state will be empty. // So add the "labels" to the ImportStateVerifyIgnore list. - ImportStateVerifyIgnore: []string{"labels"}, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, ResourceName: "google_dataproc_workflow_template.template", }, }, diff --git a/tpgtools/property.go b/tpgtools/property.go index 0292c3124857..f95c8ddbb089 100644 --- a/tpgtools/property.go +++ b/tpgtools/property.go @@ -452,6 +452,10 @@ func (p Property) IsResourceAnnotations() bool { return p.Name() == "annotations" && p.parent == nil } +func (p Property) ShouldShowUpInSamples() bool { + return (p.Settable && p.Name() != "effective_labels" && p.Name() != "effective_annotations") || p.IsResourceLabels() || p.IsResourceAnnotations() +} + // collapsedProperties returns the input list of properties with nested objects collapsed if needed. func collapsedProperties(props []Property) (collapsed []Property) { for _, v := range props { @@ -897,7 +901,14 @@ func createPropertiesFromSchema(schema *openapi.Schema, typeFetcher *TypeFetcher note := "**Note**: This field is non-authoritative, and will only manage the labels present in your configuration. " + "Please refer to the field `effective_labels` for all of the labels present on the resource." p.Description = fmt.Sprintf("%s\n\n%s", p.Description, note) + p.Settable = false + p.StateGetter = nil + props = append(props, build_effective_labels_field(p, resource, parent)) + + if p.IsResourceLabels() { + props = append(props, build_terraform_labels_field(p, resource, parent)) + } } props = append(props, p) @@ -929,7 +940,7 @@ func build_effective_labels_field(p Property, resource *Resource, parent *Proper description := fmt.Sprintf("All of %s (key/value pairs) present on the resource in GCP, including the %s configured through Terraform, other clients and services.", p.title, p.title) stateSetter := fmt.Sprintf("d.Set(%q, res.%s)", title, p.PackageName) - return Property{ + effectiveLabels := Property{ title: title, Type: p.Type, Description: description, @@ -937,6 +948,30 @@ func build_effective_labels_field(p Property, resource *Resource, parent *Proper parent: parent, Optional: false, Computed: true, + ForceNew: p.ForceNew, // Add ForceNew property if labels field has it + PackageName: p.PackageName, + Settable: true, + StateSetter: &stateSetter, + } + + stateGetter := effectiveLabels.DefaultStateGetter() + effectiveLabels.StateGetter = &stateGetter + return effectiveLabels +} + +func build_terraform_labels_field(p Property, resource *Resource, parent *Property) Property { + title := fmt.Sprintf("terraform_%s", p.title) + description := fmt.Sprintf("The combination of %s configured directly on the resource and default %s configured on the provider.", p.title, p.title) + stateSetter := fmt.Sprintf("d.Set(%q, flatten%sTerraform%s(res.%s, d))", title, p.resource.PathType(), p.PackagePath(), p.PackageName) + + return Property{ + title: title, + Type: p.Type, + Description: description, + resource: resource, + parent: parent, + Computed: true, + PackageName: p.PackageName, StateSetter: &stateSetter, } } diff --git a/tpgtools/resource.go b/tpgtools/resource.go index 1e6f6e7a1498..26c94420ef45 100644 --- a/tpgtools/resource.go +++ b/tpgtools/resource.go @@ -586,6 +586,14 @@ func createResource(schema *openapi.Schema, info *openapi.Info, typeFetcher *Typ res.CustomizeDiff = cdiff.Functions } + if res.HasLabels() { + res.CustomizeDiff = append(res.CustomizeDiff, "tpgresource.SetLabelsDiff") + } + + if res.HasAnnotations() { + res.CustomizeDiff = append(res.CustomizeDiff, "tpgresource.SetAnnotationsDiff") + } + // ListFields if parameters, ok := typeFetcher.doc.Paths["list"]; ok { for _, param := range parameters.Parameters { @@ -835,7 +843,7 @@ func (r *Resource) loadHandWrittenSamples() []Sample { // During importing, as the configuration is unavailableafter, the "labels" and "annotations" fields in the state will be empty. // So add the "labels" and the "annotations" fields to the ImportStateVerifyIgnore list. if r.HasLabels() { - sample.IgnoreRead = append(sample.IgnoreRead, "labels") + sample.IgnoreRead = append(sample.IgnoreRead, "labels", "terraform_labels") } if r.HasAnnotations() { @@ -930,10 +938,10 @@ func (r *Resource) loadDCLSamples() []Sample { sample.TestSlug = RenderedString(sampleNameToTitleCase(*sample.Name).titlecase()) // The "labels" and "annotations" fields in the state are decided by the configuration. - // During importing, as the configuration is unavailableafter, the "labels" and "annotations" fields in the state will be empty. + // During importing, as the configuration is unavailable, the "labels" and "annotations" fields in the state will be empty. // So add the "labels" and the "annotations" fields to the ImportStateVerifyIgnore list. if r.HasLabels() { - sample.IgnoreRead = append(sample.IgnoreRead, "labels") + sample.IgnoreRead = append(sample.IgnoreRead, "labels", "terraform_labels") } if r.HasAnnotations() { diff --git a/tpgtools/templates/resource.go.tmpl b/tpgtools/templates/resource.go.tmpl index a3f10f2db10b..db1eeb4d6aea 100644 --- a/tpgtools/templates/resource.go.tmpl +++ b/tpgtools/templates/resource.go.tmpl @@ -723,7 +723,22 @@ func flatten{{$.PathType}}Labels(v map[string]string, d *schema.ResourceData) in transformed := make(map[string]interface{}) if l, ok := d.Get("labels").(map[string]interface{}); ok { for k, _ := range l { - transformed[k] = l[k] + transformed[k] = v[k] + } + } + + return transformed +} + +func flatten{{$.PathType}}TerraformLabels(v map[string]string, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + + transformed := make(map[string]interface{}) + if l, ok := d.Get("terraform_labels").(map[string]interface{}); ok { + for k, _ := range l { + transformed[k] = v[k] } } @@ -740,7 +755,7 @@ func flatten{{$.PathType}}Annotations(v map[string]string, d *schema.ResourceDat transformed := make(map[string]interface{}) if l, ok := d.Get("annotations").(map[string]interface{}); ok { for k, _ := range l { - transformed[k] = l[k] + transformed[k] = v[k] } } diff --git a/tpgtools/templates/serialization.go.tmpl b/tpgtools/templates/serialization.go.tmpl index 7936e1a0119c..faba0a38cdfc 100644 --- a/tpgtools/templates/serialization.go.tmpl +++ b/tpgtools/templates/serialization.go.tmpl @@ -126,7 +126,7 @@ func ConvertSampleJSONToHCL(product DCLPackageName, resource miscellaneousNameSn func {{ $res.TitleCaseFullName }}{{$version.SerializationSuffix}}AsHCL(r {{$res.Package}}{{$version.SerializationSuffix}}.{{$res.DCLStructName}}, hasGAEquivalent bool) (string, error) { outputConfig := "resource \"{{$res.TerraformName}}\" \"output\" {\n" {{- range $field := $res.Properties}} - {{- if $field.Settable }} + {{- if $field.ShouldShowUpInSamples }} {{- if eq $field.Type.String "TypeString" "TypeInt" "TypeBool" "TypeFloat" }} {{- if $field.Type.IsDateTime }} if !r.{{$field.PackageName}}.IsZero() { From ffda75272f70e04797dfa725baf17e6637800033 Mon Sep 17 00:00:00 2001 From: Shuya Ma Date: Wed, 13 Sep 2023 20:47:59 -0700 Subject: [PATCH 32/67] resolve more conflicts --- .../services/bigquery/resource_bigquery_table_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go index 046b41bf9e74..cc5f910604d3 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go @@ -633,7 +633,6 @@ func TestAccBigQueryTable_MaterializedView_WithView(t *testing.T) { { Config: testAccBigQueryTableWithMatViewAndView(datasetID, tableID, materializedViewID, query), ExpectError: regexp.MustCompile("\"materialized_view\": conflicts with view"), ->>>>>>> FEATURE-BRANCH-major-release-5.0.0 }, }, }) @@ -3552,7 +3551,7 @@ func testAccBigQueryTableTableConstraintsUpdate(projectID, datasetID, tableID_pk } `, datasetID, tableID_pk, projectID, projectID, tableID_fk) } - + func testAccBigQueryTableWithSchema(datasetID, tableID, schema string) string { return fmt.Sprintf(` resource "google_bigquery_dataset" "test" { From a63b21f5a4b5dc391f905acb9dd8962a451a29be Mon Sep 17 00:00:00 2001 From: abheda-crest <105624942+abheda-crest@users.noreply.github.com> Date: Fri, 15 Sep 2023 21:21:34 +0530 Subject: [PATCH 33/67] Removed the `automatic` field from the `google_secret_manager_secret` resource (#8859) --- mmv1/products/secretmanager/Secret.yaml | 17 +- .../secret_manager_replication.go.erb | 180 ------------------ .../secret_manager_replication.go.erb | 118 ------------ ...resource_secret_manager_secret_test.go.erb | 41 ---- 4 files changed, 2 insertions(+), 354 deletions(-) delete mode 100644 mmv1/templates/terraform/custom_expand/secret_manager_replication.go.erb delete mode 100644 mmv1/templates/terraform/custom_flatten/secret_manager_replication.go.erb diff --git a/mmv1/products/secretmanager/Secret.yaml b/mmv1/products/secretmanager/Secret.yaml index c2e8a0832e77..4d4b921ddca9 100644 --- a/mmv1/products/secretmanager/Secret.yaml +++ b/mmv1/products/secretmanager/Secret.yaml @@ -117,29 +117,17 @@ properties: name: replication required: true immutable: true - custom_expand: templates/terraform/custom_expand/secret_manager_replication.go.erb - custom_flatten: templates/terraform/custom_flatten/secret_manager_replication.go.erb description: | The replication policy of the secret data attached to the Secret. It cannot be changed after the Secret has been created. properties: - - !ruby/object:Api::Type::Boolean - name: automatic - immutable: true - exactly_one_of: - - replication.0.automatic - - replication.0.user_managed - - replication.0.auto - deprecation_message: >- - `automatic` is deprecated and will be removed in a future major release. Use `auto` instead. - description: | - The Secret will automatically be replicated without any restrictions. - !ruby/object:Api::Type::NestedObject name: auto api_name: automatic immutable: true + allow_empty_object: true + send_empty_value: true exactly_one_of: - - replication.0.automatic - replication.0.user_managed - replication.0.auto description: | @@ -161,7 +149,6 @@ properties: name: userManaged immutable: true exactly_one_of: - - replication.0.automatic - replication.0.user_managed - replication.0.auto description: | diff --git a/mmv1/templates/terraform/custom_expand/secret_manager_replication.go.erb b/mmv1/templates/terraform/custom_expand/secret_manager_replication.go.erb deleted file mode 100644 index af13a17e9002..000000000000 --- a/mmv1/templates/terraform/custom_expand/secret_manager_replication.go.erb +++ /dev/null @@ -1,180 +0,0 @@ -<%# The license inside this block applies to this file. - # Copyright 2023 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. --%> -func expandSecretManagerSecretReplication(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - l := v.([]interface{}) - if len(l) == 0 || l[0] == nil { - return nil, nil - } - raw := l[0] - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) - - if _, ok := d.GetOk("replication.0.automatic"); ok{ - transformedAutomatic, err := expandSecretManagerSecretReplicationAutomatic(original["automatic"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedAutomatic); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["automatic"] = transformedAutomatic - } - } - - if _, ok := d.GetOk("replication.0.auto"); ok{ - transformedAuto, err := expandSecretManagerSecretReplicationAuto(original["auto"], d, config) - if err != nil { - return nil, err - } else { - transformed["automatic"] = transformedAuto - } - } - - transformedUserManaged, err := expandSecretManagerSecretReplicationUserManaged(original["user_managed"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedUserManaged); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["userManaged"] = transformedUserManaged - } - - return transformed, nil -} - -func expandSecretManagerSecretReplicationAutomatic(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - if v == nil || !v.(bool) { - return nil, nil - } - - return struct{}{}, nil -} - -func expandSecretManagerSecretReplicationAuto(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - l := v.([]interface{}) - if len(l) == 0 { - return nil, nil - } - - if l[0] == nil { - transformed := make(map[string]interface{}) - return transformed, nil - } - raw := l[0] - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedCustomerManagedEncryption, err := expandSecretManagerSecretReplicationAutoCustomerManagedEncryption(original["customer_managed_encryption"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedCustomerManagedEncryption); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["customerManagedEncryption"] = transformedCustomerManagedEncryption - } - - return transformed, nil -} - -func expandSecretManagerSecretReplicationAutoCustomerManagedEncryption(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - l := v.([]interface{}) - if len(l) == 0 || l[0] == nil { - return nil, nil - } - raw := l[0] - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedKmsKeyName, err := expandSecretManagerSecretReplicationAutoCustomerManagedEncryptionKmsKeyName(original["kms_key_name"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedKmsKeyName); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["kmsKeyName"] = transformedKmsKeyName - } - - return transformed, nil -} - -func expandSecretManagerSecretReplicationAutoCustomerManagedEncryptionKmsKeyName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - return v, nil -} - -func expandSecretManagerSecretReplicationUserManaged(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - l := v.([]interface{}) - if len(l) == 0 || l[0] == nil { - return nil, nil - } - raw := l[0] - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedReplicas, err := expandSecretManagerSecretReplicationUserManagedReplicas(original["replicas"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedReplicas); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["replicas"] = transformedReplicas - } - - return transformed, nil -} - -func expandSecretManagerSecretReplicationUserManagedReplicas(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - l := v.([]interface{}) - req := make([]interface{}, 0, len(l)) - for _, raw := range l { - if raw == nil { - continue - } - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedLocation, err := expandSecretManagerSecretReplicationUserManagedReplicasLocation(original["location"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedLocation); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["location"] = transformedLocation - } - - transformedCustomerManagedEncryption, err := expandSecretManagerSecretReplicationUserManagedReplicasCustomerManagedEncryption(original["customer_managed_encryption"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedCustomerManagedEncryption); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["customerManagedEncryption"] = transformedCustomerManagedEncryption - } - - req = append(req, transformed) - } - return req, nil -} - -func expandSecretManagerSecretReplicationUserManagedReplicasLocation(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - return v, nil -} - -func expandSecretManagerSecretReplicationUserManagedReplicasCustomerManagedEncryption(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - l := v.([]interface{}) - if len(l) == 0 || l[0] == nil { - return nil, nil - } - raw := l[0] - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedKmsKeyName, err := expandSecretManagerSecretReplicationUserManagedReplicasCustomerManagedEncryptionKmsKeyName(original["kms_key_name"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedKmsKeyName); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["kmsKeyName"] = transformedKmsKeyName - } - - return transformed, nil -} - -func expandSecretManagerSecretReplicationUserManagedReplicasCustomerManagedEncryptionKmsKeyName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - return v, nil -} diff --git a/mmv1/templates/terraform/custom_flatten/secret_manager_replication.go.erb b/mmv1/templates/terraform/custom_flatten/secret_manager_replication.go.erb deleted file mode 100644 index 76f56f85396d..000000000000 --- a/mmv1/templates/terraform/custom_flatten/secret_manager_replication.go.erb +++ /dev/null @@ -1,118 +0,0 @@ -<%# The license inside this block applies to this file. - # Copyright 2023 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. --%> -func flattenSecretManagerSecretReplication(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{}) - _, ok := d.GetOk("replication.0.automatic") - if ok { - transformed["automatic"] = - flattenSecretManagerSecretReplicationAutomatic(original["automatic"], d, config) - } else { - transformed["auto"] = - flattenSecretManagerSecretReplicationAuto(original["automatic"], d, config) - } - transformed["user_managed"] = - flattenSecretManagerSecretReplicationUserManaged(original["userManaged"], d, config) - return []interface{}{transformed} -} -func flattenSecretManagerSecretReplicationAutomatic(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return v != nil -} - -func flattenSecretManagerSecretReplicationAuto(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - if v == nil { - return nil - } - original := v.(map[string]interface{}) - transformed := make(map[string]interface{}) - transformed["customer_managed_encryption"] = - flattenSecretManagerSecretReplicationAutoCustomerManagedEncryption(original["customerManagedEncryption"], d, config) - return []interface{}{transformed} -} -func flattenSecretManagerSecretReplicationAutoCustomerManagedEncryption(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["kms_key_name"] = - flattenSecretManagerSecretReplicationAutoCustomerManagedEncryptionKmsKeyName(original["kmsKeyName"], d, config) - return []interface{}{transformed} -} -func flattenSecretManagerSecretReplicationAutoCustomerManagedEncryptionKmsKeyName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return v -} - -func flattenSecretManagerSecretReplicationUserManaged(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["replicas"] = - flattenSecretManagerSecretReplicationUserManagedReplicas(original["replicas"], d, config) - return []interface{}{transformed} -} -func flattenSecretManagerSecretReplicationUserManagedReplicas(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - if v == nil { - return v - } - l := v.([]interface{}) - transformed := make([]interface{}, 0, len(l)) - for _, raw := range l { - original := raw.(map[string]interface{}) - if len(original) < 1 { - // Do not include empty json objects coming back from the api - continue - } - transformed = append(transformed, map[string]interface{}{ - "location": flattenSecretManagerSecretReplicationUserManagedReplicasLocation(original["location"], d, config), - "customer_managed_encryption": flattenSecretManagerSecretReplicationUserManagedReplicasCustomerManagedEncryption(original["customerManagedEncryption"], d, config), - }) - } - return transformed -} -func flattenSecretManagerSecretReplicationUserManagedReplicasLocation(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return v -} - -func flattenSecretManagerSecretReplicationUserManagedReplicasCustomerManagedEncryption(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["kms_key_name"] = - flattenSecretManagerSecretReplicationUserManagedReplicasCustomerManagedEncryptionKmsKeyName(original["kmsKeyName"], d, config) - return []interface{}{transformed} -} -func flattenSecretManagerSecretReplicationUserManagedReplicasCustomerManagedEncryptionKmsKeyName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return v -} diff --git a/mmv1/third_party/terraform/services/secretmanager/resource_secret_manager_secret_test.go.erb b/mmv1/third_party/terraform/services/secretmanager/resource_secret_manager_secret_test.go.erb index e5c61c864c25..41802a5c5860 100644 --- a/mmv1/third_party/terraform/services/secretmanager/resource_secret_manager_secret_test.go.erb +++ b/mmv1/third_party/terraform/services/secretmanager/resource_secret_manager_secret_test.go.erb @@ -234,15 +234,6 @@ func TestAccSecretManagerSecret_automaticCmekUpdate(t *testing.T) { ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccCheckSecretManagerSecretDestroyProducer(t), Steps: []resource.TestStep{ - { - Config: testAccSecretMangerSecret_automaticBasic(context), - }, - { - ResourceName: "google_secret_manager_secret.secret-basic", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl", "replication.0.automatic", "replication.0.auto"}, - }, { Config: testAccSecretMangerSecret_automaticCmekBasic(context), }, @@ -698,38 +689,6 @@ resource "google_secret_manager_secret" "secret-basic" { `, context) } -func testAccSecretMangerSecret_automaticBasic(context map[string]interface{}) string { - return acctest.Nprintf(` -data "google_project" "project" { - project_id = "%{pid}" -} -resource "google_kms_crypto_key_iam_member" "kms-secret-binding-1" { - crypto_key_id = "%{kms_key_name_1}" - role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-secretmanager.iam.gserviceaccount.com" -} -resource "google_kms_crypto_key_iam_member" "kms-secret-binding-2" { - crypto_key_id = "%{kms_key_name_2}" - role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-secretmanager.iam.gserviceaccount.com" -} -resource "google_secret_manager_secret" "secret-basic" { - secret_id = "tf-test-secret-%{random_suffix}" - - labels = { - label = "my-label" - } - replication { - automatic = true - } - depends_on = [ - google_kms_crypto_key_iam_member.kms-secret-binding-1, - google_kms_crypto_key_iam_member.kms-secret-binding-2, - ] -} -`, context) -} - func testAccSecretMangerSecret_automaticCmekBasic(context map[string]interface{}) string { return acctest.Nprintf(` data "google_project" "project" { From dbd00e381a8de9283a3826ef250ce19bc011b3ab Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Fri, 15 Sep 2023 09:27:18 -0700 Subject: [PATCH 34/67] Apply new annotations model to more resources (#8931) --- mmv1/products/cloudrunv2/Job.yaml | 2 +- .../gkeonprem/BareMetalAdminCluster.yaml | 2 +- mmv1/products/gkeonprem/BareMetalCluster.yaml | 3 +-- .../products/gkeonprem/BareMetalNodePool.yaml | 3 +-- mmv1/products/gkeonprem/VmwareCluster.yaml | 3 +-- mmv1/products/gkeonprem/VmwareNodePool.yaml | 3 +-- mmv1/products/secretmanager/Secret.yaml | 2 +- mmv1/products/workstations/Workstation.yaml | 2 +- .../workstations/WorkstationCluster.yaml | 2 +- .../workstations/WorkstationConfig.yaml | 2 +- ...nprem_bare_metal_admin_cluster_full.tf.erb | 4 +++- .../examples/workstation_config_basic.tf.erb | 4 ++++ .../resource_cloud_run_v2_job_test.go | 4 ++-- ...e_gkeonprem_bare_metal_cluster_test.go.erb | 8 ++++++++ ...gkeonprem_bare_metal_node_pool_test.go.erb | 10 ++++++++-- ...ource_gkeonprem_vmware_cluster_test.go.erb | 10 ++++++++-- ...rce_gkeonprem_vmware_node_pool_test.go.erb | 10 ++++++++-- ...resource_secret_manager_secret_test.go.erb | 6 +++--- ...rkstations_workstation_cluster_test.go.erb | 8 ++++---- ...orkstations_workstation_config_test.go.erb | 6 +++--- .../terraform/tpgresource/labels.go | 14 ++++++++++++++ .../terraform/tpgresource/lables.go | 19 ------------------- 22 files changed, 75 insertions(+), 52 deletions(-) delete mode 100644 mmv1/third_party/terraform/tpgresource/lables.go diff --git a/mmv1/products/cloudrunv2/Job.yaml b/mmv1/products/cloudrunv2/Job.yaml index c31f83dce0f5..d8b928f7962f 100644 --- a/mmv1/products/cloudrunv2/Job.yaml +++ b/mmv1/products/cloudrunv2/Job.yaml @@ -137,7 +137,7 @@ properties: Cloud Run API v2 does not support labels with `run.googleapis.com`, `cloud.googleapis.com`, `serving.knative.dev`, or `autoscaling.knative.dev` namespaces, and they will be rejected. All system labels in v1 now have a corresponding field in v2 Job. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueAnnotations name: "annotations" description: |- Unstructured key value map that may be set by external tools to store and arbitrary metadata. They are not queryable and should be preserved when modifying objects. diff --git a/mmv1/products/gkeonprem/BareMetalAdminCluster.yaml b/mmv1/products/gkeonprem/BareMetalAdminCluster.yaml index e14dcc81ce9d..1d873319ed61 100644 --- a/mmv1/products/gkeonprem/BareMetalAdminCluster.yaml +++ b/mmv1/products/gkeonprem/BareMetalAdminCluster.yaml @@ -133,7 +133,7 @@ properties: Allows clients to perform consistent read-modify-writes through optimistic concurrency control. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueAnnotations name: "annotations" description: | Annotations on the Bare Metal Admin Cluster. diff --git a/mmv1/products/gkeonprem/BareMetalCluster.yaml b/mmv1/products/gkeonprem/BareMetalCluster.yaml index 0f4bf81e2bf4..a2648c7ef029 100644 --- a/mmv1/products/gkeonprem/BareMetalCluster.yaml +++ b/mmv1/products/gkeonprem/BareMetalCluster.yaml @@ -85,7 +85,7 @@ properties: required: true description: | A human readable description of this Bare Metal User Cluster. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueAnnotations name: "annotations" description: | Annotations on the Bare Metal User Cluster. @@ -96,7 +96,6 @@ properties: Prefix must be a DNS subdomain. Name must be 63 characters or less, begin and end with alphanumerics, with dashes (-), underscores (_), dots (.), and alphanumerics between. - default_from_api: true - !ruby/object:Api::Type::NestedObject name: "networkConfig" description: | diff --git a/mmv1/products/gkeonprem/BareMetalNodePool.yaml b/mmv1/products/gkeonprem/BareMetalNodePool.yaml index 42d8ac17f5d1..8060fafcf655 100644 --- a/mmv1/products/gkeonprem/BareMetalNodePool.yaml +++ b/mmv1/products/gkeonprem/BareMetalNodePool.yaml @@ -74,7 +74,7 @@ properties: name: 'displayName' description: | The display name for the Bare Metal Node Pool. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueAnnotations name: 'annotations' description: | Annotations on the Bare Metal Node Pool. @@ -85,7 +85,6 @@ properties: Prefix must be a DNS subdomain. Name must be 63 characters or less, begin and end with alphanumerics, with dashes (-), underscores (_), dots (.), and alphanumerics between. - default_from_api: true - !ruby/object:Api::Type::NestedObject name: 'nodePoolConfig' required: true diff --git a/mmv1/products/gkeonprem/VmwareCluster.yaml b/mmv1/products/gkeonprem/VmwareCluster.yaml index f460b42f42bd..c2ccf1c6b2b3 100644 --- a/mmv1/products/gkeonprem/VmwareCluster.yaml +++ b/mmv1/products/gkeonprem/VmwareCluster.yaml @@ -89,7 +89,7 @@ properties: required: true description: | The Anthos clusters on the VMware version for your user cluster. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueAnnotations name: 'annotations' description: | Annotations on the VMware User Cluster. @@ -100,7 +100,6 @@ properties: Prefix must be a DNS subdomain. Name must be 63 characters or less, begin and end with alphanumerics, with dashes (-), underscores (_), dots (.), and alphanumerics between. - default_from_api: true - !ruby/object:Api::Type::NestedObject name: 'controlPlaneNode' description: | diff --git a/mmv1/products/gkeonprem/VmwareNodePool.yaml b/mmv1/products/gkeonprem/VmwareNodePool.yaml index bfaf50cdb0ee..1579c1acff40 100644 --- a/mmv1/products/gkeonprem/VmwareNodePool.yaml +++ b/mmv1/products/gkeonprem/VmwareNodePool.yaml @@ -71,7 +71,7 @@ properties: - !ruby/object:Api::Type::String name: "displayName" description: The display name for the node pool. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueAnnotations name: "annotations" description: | Annotations on the node Pool. @@ -82,7 +82,6 @@ properties: Prefix must be a DNS subdomain. Name must be 63 characters or less, begin and end with alphanumerics, with dashes (-), underscores (_), dots (.), and alphanumerics between. - default_from_api: true - !ruby/object:Api::Type::NestedObject name: "nodePoolAutoscaling" description: Node Pool autoscaling config for the node pool. diff --git a/mmv1/products/secretmanager/Secret.yaml b/mmv1/products/secretmanager/Secret.yaml index 4d4b921ddca9..be039109d7b9 100644 --- a/mmv1/products/secretmanager/Secret.yaml +++ b/mmv1/products/secretmanager/Secret.yaml @@ -84,7 +84,7 @@ properties: An object containing a list of "key": value pairs. Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueAnnotations name: annotations description: | Custom metadata about the secret. diff --git a/mmv1/products/workstations/Workstation.yaml b/mmv1/products/workstations/Workstation.yaml index 39608a4ba043..8edfa75b85e7 100644 --- a/mmv1/products/workstations/Workstation.yaml +++ b/mmv1/products/workstations/Workstation.yaml @@ -122,7 +122,7 @@ properties: description: 'Client-specified labels that are applied to the resource and that are also propagated to the underlying Compute Engine resources.' - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueAnnotations name: 'annotations' description: 'Client-specified annotations. This is distinct from labels.' - !ruby/object:Api::Type::KeyValuePairs diff --git a/mmv1/products/workstations/WorkstationCluster.yaml b/mmv1/products/workstations/WorkstationCluster.yaml index ed0f940c896d..e6013adaddbf 100644 --- a/mmv1/products/workstations/WorkstationCluster.yaml +++ b/mmv1/products/workstations/WorkstationCluster.yaml @@ -118,7 +118,7 @@ properties: Whether this resource is in degraded mode, in which case it may require user action to restore full functionality. Details can be found in the conditions field. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueAnnotations name: "annotations" description: "Client-specified annotations. This is distinct from labels." - !ruby/object:Api::Type::Fingerprint diff --git a/mmv1/products/workstations/WorkstationConfig.yaml b/mmv1/products/workstations/WorkstationConfig.yaml index 4a64f9f44852..aafeee3a5d9a 100644 --- a/mmv1/products/workstations/WorkstationConfig.yaml +++ b/mmv1/products/workstations/WorkstationConfig.yaml @@ -158,7 +158,7 @@ properties: description: 'Client-specified labels that are applied to the resource and that are also propagated to the underlying Compute Engine resources.' - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueAnnotations name: 'annotations' description: 'Client-specified annotations. This is distinct from labels.' - !ruby/object:Api::Type::Fingerprint diff --git a/mmv1/templates/terraform/examples/gkeonprem_bare_metal_admin_cluster_full.tf.erb b/mmv1/templates/terraform/examples/gkeonprem_bare_metal_admin_cluster_full.tf.erb index 58046c4f55cc..327d91fd302d 100644 --- a/mmv1/templates/terraform/examples/gkeonprem_bare_metal_admin_cluster_full.tf.erb +++ b/mmv1/templates/terraform/examples/gkeonprem_bare_metal_admin_cluster_full.tf.erb @@ -4,7 +4,9 @@ resource "google_gkeonprem_bare_metal_admin_cluster" "<%= ctx[:primary_resource_ location = "us-west1" description = "test description" bare_metal_version = "1.13.4" - annotations = {} + annotations = { + env = "test" + } network_config { island_mode_cidr { service_address_cidr_blocks = ["172.26.0.0/16"] diff --git a/mmv1/templates/terraform/examples/workstation_config_basic.tf.erb b/mmv1/templates/terraform/examples/workstation_config_basic.tf.erb index 314df7dd12f2..987413cb6199 100644 --- a/mmv1/templates/terraform/examples/workstation_config_basic.tf.erb +++ b/mmv1/templates/terraform/examples/workstation_config_basic.tf.erb @@ -37,6 +37,10 @@ resource "google_workstations_workstation_config" "<%= ctx[:primary_resource_id] idle_timeout = "600s" running_timeout = "21600s" + annotations = { + label-one = "value-one" + } + host { gce_instance { machine_type = "e2-standard-4" 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 index a874e89e16ff..7620f5b6978b 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 @@ -26,7 +26,7 @@ func TestAccCloudRunV2Job_cloudrunv2JobFullUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_job.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"location", "launch_stage"}, + ImportStateVerifyIgnore: []string{"location", "launch_stage", "annotations"}, }, { Config: testAccCloudRunV2Job_cloudrunv2JobFullUpdate(context), @@ -35,7 +35,7 @@ func TestAccCloudRunV2Job_cloudrunv2JobFullUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_job.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"location", "launch_stage"}, + ImportStateVerifyIgnore: []string{"location", "launch_stage", "annotations"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_bare_metal_cluster_test.go.erb b/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_bare_metal_cluster_test.go.erb index be8905f2f378..9664b054d931 100644 --- a/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_bare_metal_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_bare_metal_cluster_test.go.erb @@ -27,6 +27,7 @@ func TestAccGkeonpremBareMetalCluster_bareMetalClusterUpdateBasic(t *testing.T) ResourceName: "google_gkeonprem_bare_metal_cluster.cluster-metallb", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations"}, }, { Config: testAccGkeonpremBareMetalCluster_bareMetalClusterUpdateMetalLb(context), @@ -35,6 +36,7 @@ func TestAccGkeonpremBareMetalCluster_bareMetalClusterUpdateBasic(t *testing.T) ResourceName: "google_gkeonprem_bare_metal_cluster.cluster-metallb", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations"}, }, }, }) @@ -111,6 +113,9 @@ func testAccGkeonpremBareMetalCluster_bareMetalClusterUpdateMetalLbStart(context provider = google-beta name = "cluster-metallb%{random_suffix}" location = "us-west1" + annotations = { + env = "test" + } admin_cluster_membership = "projects/870316890899/locations/global/memberships/gkeonprem-terraform-test" bare_metal_version = "1.12.3" network_config { @@ -187,6 +192,9 @@ func testAccGkeonpremBareMetalCluster_bareMetalClusterUpdateMetalLb(context map[ provider = google-beta name = "cluster-metallb%{random_suffix}" location = "us-west1" + annotations = { + env = "test-update" + } admin_cluster_membership = "projects/870316890899/locations/global/memberships/gkeonprem-terraform-test" bare_metal_version = "1.12.3" network_config { diff --git a/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_bare_metal_node_pool_test.go.erb b/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_bare_metal_node_pool_test.go.erb index 2819f8f66a34..866021db160f 100644 --- a/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_bare_metal_node_pool_test.go.erb +++ b/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_bare_metal_node_pool_test.go.erb @@ -27,6 +27,7 @@ func TestAccGkeonpremBareMetalNodePool_bareMetalNodePoolUpdate(t *testing.T) { ResourceName: "google_gkeonprem_bare_metal_node_pool.nodepool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations"}, }, { Config: testAccGkeonpremBareMetalNodePool_bareMetalNodePoolUpdate(context), @@ -35,6 +36,7 @@ func TestAccGkeonpremBareMetalNodePool_bareMetalNodePoolUpdate(t *testing.T) { ResourceName: "google_gkeonprem_bare_metal_node_pool.nodepool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations"}, }, }, }) @@ -121,7 +123,9 @@ func testAccGkeonpremBareMetalNodePool_bareMetalNodePoolUpdateStart(context map[ name = "tf-test-nodepool-%{random_suffix}" location = "us-west1" bare_metal_cluster = google_gkeonprem_bare_metal_cluster.cluster.name - annotations = {} + annotations = { + env = "test" + } node_pool_config { operating_system = "LINUX" labels = {} @@ -215,7 +219,9 @@ func testAccGkeonpremBareMetalNodePool_bareMetalNodePoolUpdate(context map[strin name = "tf-test-nodepool-%{random_suffix}" location = "us-west1" bare_metal_cluster = google_gkeonprem_bare_metal_cluster.cluster.name - annotations = {} + annotations = { + env = "test-update" + } node_pool_config { operating_system = "LINUX" labels = {} diff --git a/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_vmware_cluster_test.go.erb b/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_vmware_cluster_test.go.erb index a2cc7e50f7e9..3771d14f521f 100644 --- a/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_vmware_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_vmware_cluster_test.go.erb @@ -27,6 +27,7 @@ func TestAccGkeonpremVmwareCluster_vmwareClusterUpdateBasic(t *testing.T) { ResourceName: "google_gkeonprem_vmware_cluster.cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations"}, }, { Config: testAccGkeonpremVmwareCluster_vmwareClusterUpdateMetalLb(context), @@ -35,6 +36,7 @@ func TestAccGkeonpremVmwareCluster_vmwareClusterUpdateBasic(t *testing.T) { ResourceName: "google_gkeonprem_vmware_cluster.cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations"}, }, }, }) @@ -117,7 +119,9 @@ func testAccGkeonpremVmwareCluster_vmwareClusterUpdateMetalLbStart(context map[s admin_cluster_membership = "projects/870316890899/locations/global/memberships/gkeonprem-terraform-test" description = "test cluster" on_prem_version = "1.13.1-gke.35" - annotations = {} + annotations = { + env = "test" + } network_config { service_address_cidr_blocks = ["10.96.0.0/12"] pod_address_cidr_blocks = ["192.168.0.0/16"] @@ -165,7 +169,9 @@ func testAccGkeonpremVmwareCluster_vmwareClusterUpdateMetalLb(context map[string admin_cluster_membership = "projects/870316890899/locations/global/memberships/gkeonprem-terraform-test" description = "test cluster updated" on_prem_version = "1.13.1-gke.36" - annotations = {} + annotations = { + env = "test-update" + } network_config { service_address_cidr_blocks = ["10.96.0.0/16"] pod_address_cidr_blocks = ["192.168.0.0/20"] diff --git a/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_vmware_node_pool_test.go.erb b/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_vmware_node_pool_test.go.erb index 4be86f65a2c1..8589b95ba4e8 100644 --- a/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_vmware_node_pool_test.go.erb +++ b/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_vmware_node_pool_test.go.erb @@ -27,6 +27,7 @@ func TestAccGkeonpremVmwareNodePool_vmwareNodePoolUpdate(t *testing.T) { ResourceName: "google_gkeonprem_vmware_node_pool.nodepool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations"}, }, { Config: testAccGkeonpremVmwareNodePool_vmwareNodePoolUpdate(context), @@ -35,6 +36,7 @@ func TestAccGkeonpremVmwareNodePool_vmwareNodePoolUpdate(t *testing.T) { ResourceName: "google_gkeonprem_vmware_node_pool.nodepool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations"}, }, }, }) @@ -92,7 +94,9 @@ func testAccGkeonpremVmwareNodePool_vmwareNodePoolUpdateStart(context map[string name = "tf-test-nodepool-%{random_suffix}" location = "us-west1" vmware_cluster = google_gkeonprem_vmware_cluster.cluster.name - annotations = {} + annotations = { + env = "test" + } config { cpus = 4 memory_mb = 8196 @@ -167,7 +171,9 @@ func testAccGkeonpremVmwareNodePool_vmwareNodePoolUpdate(context map[string]inte name = "tf-test-nodepool-%{random_suffix}" location = "us-west1" vmware_cluster = google_gkeonprem_vmware_cluster.cluster.name - annotations = {} + annotations = { + env = "test-update" + } config { cpus = 5 memory_mb = 4096 diff --git a/mmv1/third_party/terraform/services/secretmanager/resource_secret_manager_secret_test.go.erb b/mmv1/third_party/terraform/services/secretmanager/resource_secret_manager_secret_test.go.erb index 41802a5c5860..da8d40853c23 100644 --- a/mmv1/third_party/terraform/services/secretmanager/resource_secret_manager_secret_test.go.erb +++ b/mmv1/third_party/terraform/services/secretmanager/resource_secret_manager_secret_test.go.erb @@ -83,7 +83,7 @@ func TestAccSecretManagerSecret_annotationsUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-with-annotations", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels", "annotations"}, }, { Config: testAccSecretManagerSecret_annotationsUpdate(context), @@ -92,7 +92,7 @@ func TestAccSecretManagerSecret_annotationsUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-with-annotations", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels", "annotations"}, }, { Config: testAccSecretManagerSecret_annotationsBasic(context), @@ -101,7 +101,7 @@ func TestAccSecretManagerSecret_annotationsUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-with-annotations", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels", "annotations"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_cluster_test.go.erb b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_cluster_test.go.erb index af09534de104..e544f9085579 100644 --- a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_cluster_test.go.erb @@ -28,7 +28,7 @@ func TestAccWorkstationsWorkstationCluster_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "annotations"}, }, { Config: testAccWorkstationsWorkstationCluster_update(context), @@ -37,7 +37,7 @@ func TestAccWorkstationsWorkstationCluster_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "annotations"}, }, }, }) @@ -62,7 +62,7 @@ func TestAccWorkstationsWorkstationCluster_Private_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "annotations"}, }, { Config: testAccWorkstationsWorkstationCluster_private_update(context), @@ -71,7 +71,7 @@ func TestAccWorkstationsWorkstationCluster_Private_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "annotations"}, }, }, }) 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 ebdc135e6095..4a4984fae0d1 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 @@ -242,7 +242,7 @@ func TestAccWorkstationsWorkstationConfig_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "annotations"}, }, { Config: testAccWorkstationsWorkstationConfig_update(context), @@ -251,7 +251,7 @@ func TestAccWorkstationsWorkstationConfig_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "annotations"}, }, { Config: testAccWorkstationsWorkstationConfig_workstationConfigBasicExample(context), @@ -260,7 +260,7 @@ func TestAccWorkstationsWorkstationConfig_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "annotations"}, }, }, }) diff --git a/mmv1/third_party/terraform/tpgresource/labels.go b/mmv1/third_party/terraform/tpgresource/labels.go index 06cb72c7c9bb..a0b13c52b78d 100644 --- a/mmv1/third_party/terraform/tpgresource/labels.go +++ b/mmv1/third_party/terraform/tpgresource/labels.go @@ -8,6 +8,20 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" ) +func FlattenLabels(labels map[string]string, d *schema.ResourceData) map[string]interface{} { + transformed := make(map[string]interface{}) + + if v, ok := d.GetOk("labels"); ok { + if labels != nil { + for k, _ := range v.(map[string]interface{}) { + transformed[k] = labels[k] + } + } + } + + return transformed +} + func SetLabelsDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) error { config := meta.(*transport_tpg.Config) diff --git a/mmv1/third_party/terraform/tpgresource/lables.go b/mmv1/third_party/terraform/tpgresource/lables.go deleted file mode 100644 index 1e76a2aeb35c..000000000000 --- a/mmv1/third_party/terraform/tpgresource/lables.go +++ /dev/null @@ -1,19 +0,0 @@ -package tpgresource - -import ( - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" -) - -func FlattenLabels(labels map[string]string, d *schema.ResourceData) map[string]interface{} { - transformed := make(map[string]interface{}) - - if v, ok := d.GetOk("labels"); ok { - if labels != nil { - for k, _ := range v.(map[string]interface{}) { - transformed[k] = labels[k] - } - } - } - - return transformed -} From 1a32f8d83008febd8f76b81aebf53742b6ffc660 Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Fri, 15 Sep 2023 13:19:42 -0500 Subject: [PATCH 35/67] remove container cluster `enable_binary_authorization` (#8784) --- .../resource_container_cluster.go.erb | 82 ++++++++----------- .../resource_container_cluster_test.go.erb | 45 ---------- .../docs/r/container_cluster.html.markdown | 4 - mmv1/third_party/tgc/container.go | 10 --- .../example_container_cluster.tfplan.json | 4 +- .../tgc/tests/data/full_container_cluster.tf | 1 - .../data/full_container_cluster.tfplan.json | 4 +- 7 files changed, 34 insertions(+), 116 deletions(-) diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb index 19b8c98d860b..d031f130dcd0 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb @@ -780,40 +780,31 @@ func ResourceContainerCluster() *schema.Resource { Description: ` Description of the cluster.`, }, - "enable_binary_authorization": { - Type: schema.TypeBool, - Optional: true, - Default: false, - Deprecated: "Deprecated in favor of binary_authorization.", - Description: `Enable Binary Authorization for this cluster. If enabled, all container images will be validated by Google Binary Authorization.`, - ConflictsWith: []string{"enable_autopilot", "binary_authorization"}, + "binary_authorization": { + Type: schema.TypeList, + Optional: true, + DiffSuppressFunc: BinaryAuthorizationDiffSuppress, + MaxItems: 1, + Description: "Configuration options for the Binary Authorization feature.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Optional: true, + Deprecated: "Deprecated in favor of evaluation_mode.", + Description: "Enable Binary Authorization for this cluster.", + ConflictsWith: []string{"enable_autopilot", "binary_authorization.0.evaluation_mode"}, + }, + "evaluation_mode": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"DISABLED", "PROJECT_SINGLETON_POLICY_ENFORCE"}, false), + Description: "Mode of operation for Binary Authorization policy evaluation.", + ConflictsWith: []string{"binary_authorization.0.enabled"}, + }, + }, + }, }, - "binary_authorization": { - Type: schema.TypeList, - Optional: true, - DiffSuppressFunc: BinaryAuthorizationDiffSuppress, - MaxItems: 1, - Description: "Configuration options for the Binary Authorization feature.", - ConflictsWith: []string{"enable_binary_authorization"}, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "enabled": { - Type: schema.TypeBool, - Optional: true, - Deprecated: "Deprecated in favor of evaluation_mode.", - Description: "Enable Binary Authorization for this cluster.", - ConflictsWith: []string{"enable_autopilot", "binary_authorization.0.evaluation_mode"}, - }, - "evaluation_mode": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice([]string{"DISABLED", "PROJECT_SINGLETON_POLICY_ENFORCE"}, false), - Description: "Mode of operation for Binary Authorization policy evaluation.", - ConflictsWith: []string{"binary_authorization.0.enabled"}, - }, - }, - }, - }, "enable_kubernetes_alpha": { Type: schema.TypeBool, @@ -2154,7 +2145,7 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er PodSecurityPolicyConfig: expandPodSecurityPolicyConfig(d.Get("pod_security_policy_config")), <% end -%> Autoscaling: expandClusterAutoscaling(d.Get("cluster_autoscaling"), d), - BinaryAuthorization: expandBinaryAuthorization(d.Get("binary_authorization"), d.Get("enable_binary_authorization").(bool)), + BinaryAuthorization: expandBinaryAuthorization(d.Get("binary_authorization")), Autopilot: &container.Autopilot{ Enabled: d.Get("enable_autopilot").(bool), WorkloadPolicyConfig: workloadPolicyConfig, @@ -2638,19 +2629,10 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro } if err := d.Set("cluster_autoscaling", flattenClusterAutoscaling(cluster.Autoscaling)); err != nil { return err - } - binauthz_enabled := d.Get("binary_authorization.0.enabled").(bool) - legacy_binauthz_enabled := d.Get("enable_binary_authorization").(bool) - if !binauthz_enabled { - if err := d.Set("enable_binary_authorization", cluster.BinaryAuthorization != nil && cluster.BinaryAuthorization.Enabled); err != nil { - return fmt.Errorf("Error setting enable_binary_authorization: %s", err) - } - } - if !legacy_binauthz_enabled { - if err := d.Set("binary_authorization", flattenBinaryAuthorization(cluster.BinaryAuthorization)); err != nil { - return err - } - } + } + if err := d.Set("binary_authorization", flattenBinaryAuthorization(cluster.BinaryAuthorization)); err != nil { + return err + } if autopilot := cluster.Autopilot; autopilot != nil { if err := d.Set("enable_autopilot", autopilot.Enabled); err != nil { return fmt.Errorf("Error setting enable_autopilot: %s", err) @@ -3004,7 +2986,7 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er if d.HasChange("binary_authorization") { req := &container.UpdateClusterRequest{ Update: &container.ClusterUpdate{ - DesiredBinaryAuthorization: expandBinaryAuthorization(d.Get("binary_authorization"), d.Get("enable_binary_authorization").(bool)), + DesiredBinaryAuthorization: expandBinaryAuthorization(d.Get("binary_authorization")), }, } @@ -4830,11 +4812,11 @@ func expandNotificationConfig(configured interface{}) *container.NotificationCon } } -func expandBinaryAuthorization(configured interface{}, legacy_enabled bool) *container.BinaryAuthorization { +func expandBinaryAuthorization(configured interface{}) *container.BinaryAuthorization { l := configured.([]interface{}) if len(l) == 0 || l[0] == nil { return &container.BinaryAuthorization{ - Enabled: legacy_enabled, + Enabled: false, ForceSendFields: []string{"Enabled"}, } } diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb index 91f4c3b4e3ea..6b0db114d9dd 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb @@ -3074,7 +3074,6 @@ func TestAccContainerCluster_withBinaryAuthorizationEnabledBool(t *testing.T) { ResourceName: "google_container_cluster.with_binary_authorization_enabled_bool", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"enable_binary_authorization"}, }, { Config: testAccContainerCluster_withBinaryAuthorizationEnabledBool(clusterName, false), @@ -3088,38 +3087,6 @@ func TestAccContainerCluster_withBinaryAuthorizationEnabledBool(t *testing.T) { }) } -func TestAccContainerCluster_withBinaryAuthorizationEnabledBoolLegacy(t *testing.T) { - t.Parallel() - - clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) - - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccContainerCluster_withBinaryAuthorizationEnabledBoolLegacy(clusterName, true), - }, - { - ResourceName: "google_container_cluster.with_binary_authorization_enabled_bool_legacy", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"enable_binary_authorization", "binary_authorization.#", "binary_authorization.0.%", "binary_authorization.0.enabled", "binary_authorization.0.evaluation_mode"}, - }, - { - Config: testAccContainerCluster_withBinaryAuthorizationEnabledBoolLegacy(clusterName, false), - }, - { - ResourceName: "google_container_cluster.with_binary_authorization_enabled_bool_legacy", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"enable_binary_authorization"}, - }, - }, - }) -} - func TestAccContainerCluster_withBinaryAuthorizationEvaluationModeAutopilot(t *testing.T) { t.Parallel() @@ -7197,18 +7164,6 @@ resource "google_container_cluster" "with_binary_authorization_enabled_bool" { `, clusterName, enabled) } -func testAccContainerCluster_withBinaryAuthorizationEnabledBoolLegacy(clusterName string, enabled bool) string { - return fmt.Sprintf(` -resource "google_container_cluster" "with_binary_authorization_enabled_bool_legacy" { - name = "%s" - location = "us-central1-a" - initial_node_count = 1 - - enable_binary_authorization = %v -} -`, clusterName, enabled) -} - func testAccContainerCluster_withBinaryAuthorizationEvaluationMode(clusterName string, autopilot_enabled bool, evaluation_mode string) string { return fmt.Sprintf(` resource "google_container_cluster" "with_binary_authorization_evaluation_mode" { diff --git a/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown b/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown index e5eb29fe4011..d8fccdc7eb5d 100644 --- a/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown @@ -156,10 +156,6 @@ per node in this cluster. This doesn't work on "routes-based" clusters, clusters that don't have IP Aliasing enabled. See the [official documentation](https://cloud.google.com/kubernetes-engine/docs/how-to/flexible-pod-cidr) for more information. -* `enable_binary_authorization` - (DEPRECATED) Enable Binary Authorization for this cluster. - If enabled, all container images will be validated by Google Binary Authorization. - Deprecated in favor of `binary_authorization`. - * `enable_kubernetes_alpha` - (Optional) Whether to enable Kubernetes Alpha features for this cluster. Note that when this option is enabled, the cluster cannot be upgraded and will be automatically deleted after 30 days. diff --git a/mmv1/third_party/tgc/container.go b/mmv1/third_party/tgc/container.go index 86085212e70f..806b64e228b4 100644 --- a/mmv1/third_party/tgc/container.go +++ b/mmv1/third_party/tgc/container.go @@ -47,10 +47,6 @@ func expandContainerClusterEnableLegacyAbac(v interface{}, d tpgresource.Terrafo return expandContainerEnabledObject(v, d, config) } -func expandContainerClusterEnableBinaryAuthorization(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - return expandContainerEnabledObject(v, d, config) -} - func expandContainerMaxPodsConstraint(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { if val := reflect.ValueOf(v); !val.IsValid() || tpgresource.IsEmptyValue(val) { return nil, nil @@ -126,12 +122,6 @@ func GetContainerClusterCaiObject(d tpgresource.TerraformResourceData, config *t func GetContainerClusterApiObject(d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]interface{}, error) { obj := make(map[string]interface{}) - binaryAuthorizationProp, err := expandContainerClusterEnableBinaryAuthorization(d.Get("enable_binary_authorization"), d, config) - if err != nil { - return nil, err - } else if v, ok := d.GetOkExists("enable_binary_authorization"); !tpgresource.IsEmptyValue(reflect.ValueOf(binaryAuthorizationProp)) && (ok || !reflect.DeepEqual(v, binaryAuthorizationProp)) { - obj["binaryAuthorization"] = binaryAuthorizationProp - } enableKubernetesAlphaProp, err := expandContainerClusterEnableKubernetesAlpha(d.Get("enable_kubernetes_alpha"), d, config) if err != nil { return nil, err diff --git a/mmv1/third_party/tgc/tests/data/example_container_cluster.tfplan.json b/mmv1/third_party/tgc/tests/data/example_container_cluster.tfplan.json index 998e197fae0d..1f54b16a9b4e 100644 --- a/mmv1/third_party/tgc/tests/data/example_container_cluster.tfplan.json +++ b/mmv1/third_party/tgc/tests/data/example_container_cluster.tfplan.json @@ -13,7 +13,6 @@ "schema_version": 1, "values": { "description": null, - "enable_binary_authorization": false, "enable_intranode_visibility": null, "enable_kubernetes_alpha": false, "enable_legacy_abac": false, @@ -98,7 +97,6 @@ "before": null, "after": { "description": null, - "enable_binary_authorization": false, "enable_intranode_visibility": null, "enable_kubernetes_alpha": false, "enable_legacy_abac": false, @@ -344,4 +342,4 @@ ] } } -} +} \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/full_container_cluster.tf b/mmv1/third_party/tgc/tests/data/full_container_cluster.tf index fe7966114c5e..b43baca7f928 100644 --- a/mmv1/third_party/tgc/tests/data/full_container_cluster.tf +++ b/mmv1/third_party/tgc/tests/data/full_container_cluster.tf @@ -36,7 +36,6 @@ resource "google_container_cluster" "full_list_default_1" { # authenticator_groups_config # cluster_autoscaling # database_encryption - # enable_binary_authorization # enable_intranode_visibility # enable_shielded_nodes # enable_tpu diff --git a/mmv1/third_party/tgc/tests/data/full_container_cluster.tfplan.json b/mmv1/third_party/tgc/tests/data/full_container_cluster.tfplan.json index a9370d3d5cc1..f7074cc4d604 100644 --- a/mmv1/third_party/tgc/tests/data/full_container_cluster.tfplan.json +++ b/mmv1/third_party/tgc/tests/data/full_container_cluster.tfplan.json @@ -34,7 +34,6 @@ "default_max_pods_per_node": 42, "description": "test-description", "enable_autopilot": null, - "enable_binary_authorization": false, "enable_kubernetes_alpha": true, "enable_legacy_abac": true, "enable_shielded_nodes": true, @@ -277,7 +276,6 @@ "default_max_pods_per_node": 42, "description": "test-description", "enable_autopilot": null, - "enable_binary_authorization": false, "enable_kubernetes_alpha": true, "enable_legacy_abac": true, "enable_shielded_nodes": true, @@ -815,4 +813,4 @@ ] } } -} +} \ No newline at end of file From 0ef602f678611b77172a342e8e2980633054ed01 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Fri, 15 Sep 2023 16:05:37 -0700 Subject: [PATCH 36/67] Apply new labels model to more resources (part 1) (#8950) * Apply new labels model to more resources (part 1) * Handle labels field inside flatten object * Fix the tests for datasource * Fix typo * Fix typo --- mmv1/api/resource.rb | 41 ++++++++++++------- mmv1/api/type.rb | 5 ++- mmv1/products/activedirectory/Domain.yaml | 2 +- mmv1/products/activedirectory/Peering.yaml | 2 +- mmv1/products/alloydb/Backup.yaml | 2 +- mmv1/products/alloydb/Cluster.yaml | 2 +- mmv1/products/apigateway/ApiConfig.yaml | 2 +- mmv1/products/apigateway/ApiResource.yaml | 2 +- mmv1/products/apigateway/Gateway.yaml | 2 +- .../products/artifactregistry/Repository.yaml | 2 +- mmv1/products/beyondcorp/AppConnection.yaml | 2 +- mmv1/products/beyondcorp/AppConnector.yaml | 2 +- mmv1/products/beyondcorp/AppGateway.yaml | 2 +- mmv1/products/bigquery/Job.yaml | 2 +- mmv1/products/bigquery/Table.yaml | 2 +- .../certificatemanager/Certificate.yaml | 2 +- .../CertificateIssuanceConfig.yaml | 2 +- .../certificatemanager/CertificateMap.yaml | 3 +- .../CertificateMapEntry.yaml | 3 +- .../certificatemanager/DnsAuthorization.yaml | 2 +- .../certificatemanager/TrustConfig.yaml | 2 +- .../cloudfunctions/CloudFunction.yaml | 2 +- mmv1/products/cloudfunctions2/Function.yaml | 2 +- mmv1/products/cloudrunv2/Job.yaml | 2 +- mmv1/products/cloudrunv2/Service.yaml | 2 +- .../connectionprofile.yaml | 2 +- mmv1/products/datafusion/Instance.yaml | 2 +- mmv1/products/dataplex/Datascan.yaml | 2 +- mmv1/products/dataplex/Task.yaml | 2 +- .../datastream/ConnectionProfile.yaml | 2 +- .../datastream/PrivateConnection.yaml | 2 +- mmv1/products/datastream/Stream.yaml | 2 +- mmv1/provider/terraform.rb | 2 +- .../examples/base_configs/test_file.go.erb | 3 +- ...ager_google_managed_certificate_dns.tf.erb | 3 ++ .../terraform/expand_property_method.erb | 1 + .../terraform/acctest/test_utils.go.erb | 6 +++ ...rce_active_directory_domain_update_test.go | 6 +-- .../alloydb/resource_alloydb_backup_test.go | 6 +-- .../alloydb/resource_alloydb_cluster_test.go | 4 +- ...ource_artifact_registry_repository_test.go | 8 +++- ...e_artifact_registry_repository_test.go.erb | 2 + .../bigquery/resource_bigquery_job_test.go | 2 +- .../bigquery/resource_bigquery_table_test.go | 10 ++--- ...tificate_manager_dns_authorization_test.go | 4 +- ...e_certificate_manager_trust_config_test.go | 14 ++++--- ...source_cloudfunctions_function_test.go.erb | 10 ++--- ...ce_google_cloudfunctions2_function_test.go | 14 ++++++- .../resource_cloudfunctions2_function_test.go | 14 +++++-- .../resource_cloud_run_v2_job_test.go | 4 +- .../resource_cloud_run_v2_service_test.go | 4 +- ...gration_service_connection_profile_test.go | 4 +- .../resource_data_fusion_instance_test.go | 28 +++++++------ .../resource_datastream_stream_test.go | 8 ++-- 54 files changed, 157 insertions(+), 108 deletions(-) diff --git a/mmv1/api/resource.rb b/mmv1/api/resource.rb index a0ae098eaad7..cf4f9d45542b 100644 --- a/mmv1/api/resource.rb +++ b/mmv1/api/resource.rb @@ -460,7 +460,7 @@ def add_labels_related_fields(props, parent) 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.name) + p.properties = add_labels_related_fields(p.all_properties, p) end end props @@ -471,16 +471,14 @@ def add_labels_fields(props, parent, labels) labels.ignore_write = true @custom_diff ||= [] - if parent.nil? + if parent.nil? || parent.flatten_object @custom_diff.append('tpgresource.SetLabelsDiff') - elsif parent == 'metadata' + elsif parent.name == 'metadata' @custom_diff.append('tpgresource.SetMetadataLabelsDiff') end props << build_terraform_labels_field('labels', labels.field_min_version) - props << build_effective_labels_field( - 'labels', labels.field_min_version, labels.update_verb, labels.update_url - ) + props << build_effective_labels_field('labels', labels) end def add_annotations_fields(props, parent, annotations) @@ -491,17 +489,14 @@ def add_annotations_fields(props, parent, annotations) @custom_diff ||= [] if parent.nil? @custom_diff.append('tpgresource.SetAnnotationsDiff') - elsif parent == 'metadata' + elsif parent.name == 'metadata' @custom_diff.append('tpgresource.SetMetadataAnnotationsDiff') end - props << build_effective_labels_field( - 'annotations', annotations.field_min_version, - annotations.update_verb, annotations.update_url - ) + props << build_effective_labels_field('annotations', annotations) end - def build_effective_labels_field(name, min_version, update_verb, update_url) + 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." @@ -511,9 +506,10 @@ def build_effective_labels_field(name, min_version, update_verb, update_url) output: true, api_name: name, description:, - min_version:, - update_verb:, - update_url: + min_version: labels.field_min_version, + update_verb: labels.update_verb, + update_url: labels.update_url, + immutable: labels.immutable ) end @@ -531,6 +527,21 @@ def build_terraform_labels_field(name, min_version) ) 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 + # ==================== # Version-related methods # ==================== diff --git a/mmv1/api/type.rb b/mmv1/api/type.rb index c9b385e6b4b6..0d81c8335929 100644 --- a/mmv1/api/type.rb +++ b/mmv1/api/type.rb @@ -269,7 +269,7 @@ def lineage # 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(). def terraform_lineage - return name&.underscore if __parent.nil? + return name&.underscore if __parent.nil? || __parent.flatten_object "#{__parent.terraform_lineage}.0.#{name&.underscore}" end @@ -769,7 +769,7 @@ class KeyValuePairs < Composite attr_accessor :ignore_write def initialize(name: nil, output: nil, api_name: nil, description: nil, min_version: nil, - ignore_write: nil, update_verb: nil, update_url: nil) + ignore_write: nil, update_verb: nil, update_url: nil, immutable: nil) super() @name = name @@ -780,6 +780,7 @@ def initialize(name: nil, output: nil, api_name: nil, description: nil, min_vers @ignore_write = ignore_write @update_verb = update_verb @update_url = update_url + @immutable = immutable end def validate diff --git a/mmv1/products/activedirectory/Domain.yaml b/mmv1/products/activedirectory/Domain.yaml index 8b0cc3e78b33..7ca646ef3565 100644 --- a/mmv1/products/activedirectory/Domain.yaml +++ b/mmv1/products/activedirectory/Domain.yaml @@ -85,7 +85,7 @@ properties: description: 'The unique name of the domain using the format: `projects/{project}/locations/global/domains/{domainName}`.' - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'Resource labels that can contain user-provided metadata' - !ruby/object:Api::Type::Array diff --git a/mmv1/products/activedirectory/Peering.yaml b/mmv1/products/activedirectory/Peering.yaml index b98c94b7ac59..b760bb8ef788 100644 --- a/mmv1/products/activedirectory/Peering.yaml +++ b/mmv1/products/activedirectory/Peering.yaml @@ -73,7 +73,7 @@ properties: output: true description: | Unique name of the peering in this scope including projects and location using the form: projects/{projectId}/locations/global/peerings/{peeringId}. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'Resource labels that can contain user-provided metadata' - !ruby/object:Api::Type::String diff --git a/mmv1/products/alloydb/Backup.yaml b/mmv1/products/alloydb/Backup.yaml index 36a9f4339914..ee306347295e 100644 --- a/mmv1/products/alloydb/Backup.yaml +++ b/mmv1/products/alloydb/Backup.yaml @@ -92,7 +92,7 @@ properties: required: true immutable: true diff_suppress_func: 'tpgresource.ProjectNumberDiffSuppress' - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'User-defined labels for the alloydb backup.' - !ruby/object:Api::Type::Time diff --git a/mmv1/products/alloydb/Cluster.yaml b/mmv1/products/alloydb/Cluster.yaml index cf597bad4d43..3922c2ddc624 100644 --- a/mmv1/products/alloydb/Cluster.yaml +++ b/mmv1/products/alloydb/Cluster.yaml @@ -106,7 +106,7 @@ properties: output: true description: | The system-generated UID of the resource. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'User-defined labels for the alloydb cluster.' - !ruby/object:Api::Type::NestedObject diff --git a/mmv1/products/apigateway/ApiConfig.yaml b/mmv1/products/apigateway/ApiConfig.yaml index 2c795186cbed..da35b85703d9 100644 --- a/mmv1/products/apigateway/ApiConfig.yaml +++ b/mmv1/products/apigateway/ApiConfig.yaml @@ -120,7 +120,7 @@ properties: output: true description: | The ID of the associated Service Config (https://cloud.google.com/service-infrastructure/docs/glossary#config). - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels to represent user-provided metadata. diff --git a/mmv1/products/apigateway/ApiResource.yaml b/mmv1/products/apigateway/ApiResource.yaml index f295dd636fee..93ae56e5e75b 100644 --- a/mmv1/products/apigateway/ApiResource.yaml +++ b/mmv1/products/apigateway/ApiResource.yaml @@ -87,7 +87,7 @@ properties: name: 'createTime' description: Creation timestamp in RFC3339 text format. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels to represent user-provided metadata. diff --git a/mmv1/products/apigateway/Gateway.yaml b/mmv1/products/apigateway/Gateway.yaml index 5ce68c7f3315..9dc7b3b17b02 100644 --- a/mmv1/products/apigateway/Gateway.yaml +++ b/mmv1/products/apigateway/Gateway.yaml @@ -102,7 +102,7 @@ properties: description: The default API Gateway host name of the form {gatewayId}-{hash}.{region_code}.gateway.dev. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels to represent user-provided metadata. diff --git a/mmv1/products/artifactregistry/Repository.yaml b/mmv1/products/artifactregistry/Repository.yaml index 4a7e32d73a1c..1ceb42a714f3 100644 --- a/mmv1/products/artifactregistry/Repository.yaml +++ b/mmv1/products/artifactregistry/Repository.yaml @@ -131,7 +131,7 @@ properties: name: description description: |- The user-provided description of the repository. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels with user-defined metadata. diff --git a/mmv1/products/beyondcorp/AppConnection.yaml b/mmv1/products/beyondcorp/AppConnection.yaml index 215bac419709..1ebf2c7368fb 100644 --- a/mmv1/products/beyondcorp/AppConnection.yaml +++ b/mmv1/products/beyondcorp/AppConnection.yaml @@ -88,7 +88,7 @@ properties: name: 'displayName' description: | An arbitrary user-provided name for the AppConnection. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels to represent user provided metadata. diff --git a/mmv1/products/beyondcorp/AppConnector.yaml b/mmv1/products/beyondcorp/AppConnector.yaml index 20a6b3a11bcc..fb8e23bedbf6 100644 --- a/mmv1/products/beyondcorp/AppConnector.yaml +++ b/mmv1/products/beyondcorp/AppConnector.yaml @@ -82,7 +82,7 @@ properties: name: 'displayName' description: | An arbitrary user-provided name for the AppConnector. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels to represent user provided metadata. diff --git a/mmv1/products/beyondcorp/AppGateway.yaml b/mmv1/products/beyondcorp/AppGateway.yaml index 1eda5d9eeefe..7d6fc2fc42fe 100644 --- a/mmv1/products/beyondcorp/AppGateway.yaml +++ b/mmv1/products/beyondcorp/AppGateway.yaml @@ -98,7 +98,7 @@ properties: name: 'displayName' description: | An arbitrary user-provided name for the AppGateway. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels to represent user provided metadata. diff --git a/mmv1/products/bigquery/Job.yaml b/mmv1/products/bigquery/Job.yaml index cf12ae9fdf3d..016f76d03a72 100644 --- a/mmv1/products/bigquery/Job.yaml +++ b/mmv1/products/bigquery/Job.yaml @@ -168,7 +168,7 @@ properties: name: 'jobTimeoutMs' description: | Job timeout in milliseconds. If this time limit is exceeded, BigQuery may attempt to terminate the job. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | The labels associated with this job. You can use these to organize and group your jobs. diff --git a/mmv1/products/bigquery/Table.yaml b/mmv1/products/bigquery/Table.yaml index ae9c5bb81666..2c248d787213 100644 --- a/mmv1/products/bigquery/Table.yaml +++ b/mmv1/products/bigquery/Table.yaml @@ -88,7 +88,7 @@ properties: name: 'id' description: 'An opaque ID uniquely identifying the table.' output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | The labels associated with this dataset. You can use these to diff --git a/mmv1/products/certificatemanager/Certificate.yaml b/mmv1/products/certificatemanager/Certificate.yaml index 552364c08bba..a2cee514e99d 100644 --- a/mmv1/products/certificatemanager/Certificate.yaml +++ b/mmv1/products/certificatemanager/Certificate.yaml @@ -95,7 +95,7 @@ properties: name: 'description' description: | A human-readable description of the resource. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'Set of label tags associated with the Certificate resource.' - !ruby/object:Api::Type::String diff --git a/mmv1/products/certificatemanager/CertificateIssuanceConfig.yaml b/mmv1/products/certificatemanager/CertificateIssuanceConfig.yaml index 6a994704207a..fa4cec9f21ac 100644 --- a/mmv1/products/certificatemanager/CertificateIssuanceConfig.yaml +++ b/mmv1/products/certificatemanager/CertificateIssuanceConfig.yaml @@ -109,7 +109,7 @@ properties: accurate to nanoseconds with up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | 'Set of label tags associated with the CertificateIssuanceConfig resource. diff --git a/mmv1/products/certificatemanager/CertificateMap.yaml b/mmv1/products/certificatemanager/CertificateMap.yaml index 1342e8344e46..96df010f7666 100644 --- a/mmv1/products/certificatemanager/CertificateMap.yaml +++ b/mmv1/products/certificatemanager/CertificateMap.yaml @@ -76,11 +76,10 @@ properties: accurate to nanoseconds with up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Set of labels associated with a Certificate Map resource. - default_from_api: true - !ruby/object:Api::Type::Array name: 'gclbTargets' description: | diff --git a/mmv1/products/certificatemanager/CertificateMapEntry.yaml b/mmv1/products/certificatemanager/CertificateMapEntry.yaml index 296e342a6920..aa1ac5d57570 100644 --- a/mmv1/products/certificatemanager/CertificateMapEntry.yaml +++ b/mmv1/products/certificatemanager/CertificateMapEntry.yaml @@ -92,13 +92,12 @@ properties: with nanosecond resolution and up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Set of labels associated with a Certificate Map Entry. An object containing a list of "key": value pairs. Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }. - default_from_api: true - !ruby/object:Api::Type::Array name: 'certificates' required: true diff --git a/mmv1/products/certificatemanager/DnsAuthorization.yaml b/mmv1/products/certificatemanager/DnsAuthorization.yaml index fa6e636e7691..bcb50c60c329 100644 --- a/mmv1/products/certificatemanager/DnsAuthorization.yaml +++ b/mmv1/products/certificatemanager/DnsAuthorization.yaml @@ -63,7 +63,7 @@ properties: name: 'description' description: | A human-readable description of the resource. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'Set of label tags associated with the DNS Authorization resource.' diff --git a/mmv1/products/certificatemanager/TrustConfig.yaml b/mmv1/products/certificatemanager/TrustConfig.yaml index d4ff25e5256c..d7395fa22948 100644 --- a/mmv1/products/certificatemanager/TrustConfig.yaml +++ b/mmv1/products/certificatemanager/TrustConfig.yaml @@ -84,7 +84,7 @@ properties: A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'Set of label tags associated with the trust config.' immutable: true diff --git a/mmv1/products/cloudfunctions/CloudFunction.yaml b/mmv1/products/cloudfunctions/CloudFunction.yaml index ad310f7293ab..6ac2766e6ffe 100644 --- a/mmv1/products/cloudfunctions/CloudFunction.yaml +++ b/mmv1/products/cloudfunctions/CloudFunction.yaml @@ -129,7 +129,7 @@ properties: description: | The version identifier of the Cloud Function. Each deployment attempt results in a new version of a function being created. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | A set of key/value label pairs associated with this Cloud Function. diff --git a/mmv1/products/cloudfunctions2/Function.yaml b/mmv1/products/cloudfunctions2/Function.yaml index a8ca2d64185a..5b0a0ff36b0a 100644 --- a/mmv1/products/cloudfunctions2/Function.yaml +++ b/mmv1/products/cloudfunctions2/Function.yaml @@ -630,7 +630,7 @@ properties: name: 'updateTime' output: true description: 'The last update timestamp of a Cloud Function.' - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | A set of key/value label pairs associated with this Cloud Function. diff --git a/mmv1/products/cloudrunv2/Job.yaml b/mmv1/products/cloudrunv2/Job.yaml index d8b928f7962f..82bd0618fb85 100644 --- a/mmv1/products/cloudrunv2/Job.yaml +++ b/mmv1/products/cloudrunv2/Job.yaml @@ -129,7 +129,7 @@ properties: output: true description: | A number that monotonically increases every time the user modifies the desired state. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: |- Unstructured key value map that can be used to organize and categorize objects. User-provided labels are shared with Google's billing system, so they can be used to filter, or break down billing charges by team, component, diff --git a/mmv1/products/cloudrunv2/Service.yaml b/mmv1/products/cloudrunv2/Service.yaml index 337e63381f52..daf10dbf9fbb 100644 --- a/mmv1/products/cloudrunv2/Service.yaml +++ b/mmv1/products/cloudrunv2/Service.yaml @@ -144,7 +144,7 @@ properties: output: true description: | A number that monotonically increases every time the user modifies the desired state. Please note that unlike v1, this is an int64 value. As with most Google APIs, its JSON representation will be a string instead of an integer. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: |- Unstructured key value map that can be used to organize and categorize objects. User-provided labels are shared with Google's billing system, so they can be used to filter, or break down billing charges by team, component, diff --git a/mmv1/products/databasemigrationservice/connectionprofile.yaml b/mmv1/products/databasemigrationservice/connectionprofile.yaml index 62e6fc778024..f9383453a7f0 100644 --- a/mmv1/products/databasemigrationservice/connectionprofile.yaml +++ b/mmv1/products/databasemigrationservice/connectionprofile.yaml @@ -116,7 +116,7 @@ properties: output: true description: | Output only. The timestamp when the resource was created. A timestamp in RFC3339 UTC 'Zulu' format, accurate to nanoseconds. Example: '2014-10-02T15:01:23.045123456Z'. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | The resource labels for connection profile to use to annotate any related underlying resources such as Compute Engine VMs. diff --git a/mmv1/products/datafusion/Instance.yaml b/mmv1/products/datafusion/Instance.yaml index 17f0333f65d8..ccd0efd1c762 100644 --- a/mmv1/products/datafusion/Instance.yaml +++ b/mmv1/products/datafusion/Instance.yaml @@ -141,7 +141,7 @@ properties: name: 'enableRbac' description: | Option to enable granular role-based access control. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | The resource labels for instance to use to annotate any related underlying resources, diff --git a/mmv1/products/dataplex/Datascan.yaml b/mmv1/products/dataplex/Datascan.yaml index 2f0820034380..c3900509e163 100644 --- a/mmv1/products/dataplex/Datascan.yaml +++ b/mmv1/products/dataplex/Datascan.yaml @@ -126,7 +126,7 @@ properties: name: 'displayName' description: | User friendly display name. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | User-defined labels for the scan. A list of key->value pairs. diff --git a/mmv1/products/dataplex/Task.yaml b/mmv1/products/dataplex/Task.yaml index 3a4095794264..66ed12c16dbb 100644 --- a/mmv1/products/dataplex/Task.yaml +++ b/mmv1/products/dataplex/Task.yaml @@ -116,7 +116,7 @@ properties: - :CREATING - :DELETING - :ACTION_REQUIRED - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | User-defined labels for the task. diff --git a/mmv1/products/datastream/ConnectionProfile.yaml b/mmv1/products/datastream/ConnectionProfile.yaml index 5e5258e765b6..3a8a4d94879f 100644 --- a/mmv1/products/datastream/ConnectionProfile.yaml +++ b/mmv1/products/datastream/ConnectionProfile.yaml @@ -81,7 +81,7 @@ properties: name: 'name' output: true description: The resource's name. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Labels. - !ruby/object:Api::Type::String diff --git a/mmv1/products/datastream/PrivateConnection.yaml b/mmv1/products/datastream/PrivateConnection.yaml index dcd9a6da8d71..c2a10d6c8bce 100644 --- a/mmv1/products/datastream/PrivateConnection.yaml +++ b/mmv1/products/datastream/PrivateConnection.yaml @@ -59,7 +59,7 @@ properties: name: 'name' output: true description: The resource's name. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Labels. - !ruby/object:Api::Type::String diff --git a/mmv1/products/datastream/Stream.yaml b/mmv1/products/datastream/Stream.yaml index 039b51a75457..a88ed1eeb73c 100644 --- a/mmv1/products/datastream/Stream.yaml +++ b/mmv1/products/datastream/Stream.yaml @@ -157,7 +157,7 @@ properties: name: 'name' output: true description: The stream's name. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Labels. - !ruby/object:Api::Type::String diff --git a/mmv1/provider/terraform.rb b/mmv1/provider/terraform.rb index 4b89fb535374..512a26b353bf 100644 --- a/mmv1/provider/terraform.rb +++ b/mmv1/provider/terraform.rb @@ -105,7 +105,7 @@ def updatable?(resource, properties) end def force_new?(property, resource) - !property.output && + (!property.output || property.is_a?(Api::Type::KeyValueEffectiveLabels)) && (property.immutable || (resource.immutable && property.update_url.nil? && property.immutable.nil? && (property.parent.nil? || diff --git a/mmv1/templates/terraform/examples/base_configs/test_file.go.erb b/mmv1/templates/terraform/examples/base_configs/test_file.go.erb index 3e9b14c491df..64aa47337ddd 100644 --- a/mmv1/templates/terraform/examples/base_configs/test_file.go.erb +++ b/mmv1/templates/terraform/examples/base_configs/test_file.go.erb @@ -44,9 +44,10 @@ object.examples test_slug = "#{resource_name}_#{example.name.camelize(:lower)}Example" ignore_read = object.all_user_properties - .select{|p| p.url_param_only || p.ignore_read || p.is_a?(Api::Type::ResourceRef) || p.is_a?(Api::Type::KeyValueLabels) || p.is_a?(Api::Type::KeyValueAnnotations) || p.is_a?(Api::Type::KeyValueTerraformLabels)} + .select{|p| p.url_param_only || p.ignore_read || p.is_a?(Api::Type::ResourceRef)} .map { |p| p.name.underscore } .concat(example.ignore_read_extra) + .concat(object.ignore_read_labels_fields(object.properties_with_excluded)) # Use explicit version for the example if given. # Otherwise, use object version. diff --git a/mmv1/templates/terraform/examples/certificate_manager_google_managed_certificate_dns.tf.erb b/mmv1/templates/terraform/examples/certificate_manager_google_managed_certificate_dns.tf.erb index 48d499afeff7..6e457875fbd2 100644 --- a/mmv1/templates/terraform/examples/certificate_manager_google_managed_certificate_dns.tf.erb +++ b/mmv1/templates/terraform/examples/certificate_manager_google_managed_certificate_dns.tf.erb @@ -2,6 +2,9 @@ resource "google_certificate_manager_certificate" "<%= ctx[:primary_resource_id] name = "<%= ctx[:vars]['cert_name'] %>" description = "The default cert" scope = "EDGE_CACHE" + labels = { + env = "test" + } managed { domains = [ google_certificate_manager_dns_authorization.instance.domain, diff --git a/mmv1/templates/terraform/expand_property_method.erb b/mmv1/templates/terraform/expand_property_method.erb index 880242320bd5..d74d7bcc777c 100644 --- a/mmv1/templates/terraform/expand_property_method.erb +++ b/mmv1/templates/terraform/expand_property_method.erb @@ -75,6 +75,7 @@ func expand<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d t func expand<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { transformed := make(map[string]interface{}) <% property.nested_properties.each do |prop| -%> +<% next if prop.is_a?(Api::Type::KeyValuePairs) && prop.ignore_write -%> <% schemaPrefix = prop.flatten_object ? "nil" : "d.Get( \"#{prop.name.underscore}\" )" -%> transformed<%= titlelize_property(prop) -%>, err := expand<%= prefix -%><%= titlelize_property(property) -%><%= titlelize_property(prop) -%>(<%= schemaPrefix -%>, d, config) if err != nil { diff --git a/mmv1/third_party/terraform/acctest/test_utils.go.erb b/mmv1/third_party/terraform/acctest/test_utils.go.erb index bf081eac3c9a..3fc319222497 100644 --- a/mmv1/third_party/terraform/acctest/test_utils.go.erb +++ b/mmv1/third_party/terraform/acctest/test_utils.go.erb @@ -50,6 +50,12 @@ func CheckDataSourceStateMatchesResourceStateWithIgnores(dataSourceName, resourc if _, ok := ignoreFields[k]; ok { continue } + if _, ok := ignoreFields["labels.%"]; ok && strings.HasPrefix(k, "labels.") { + continue + } + if _, ok := ignoreFields["terraform_labels.%"]; ok && strings.HasPrefix(k, "terraform_labels.") { + continue + } if k == "%" { continue } diff --git a/mmv1/third_party/terraform/services/activedirectory/resource_active_directory_domain_update_test.go b/mmv1/third_party/terraform/services/activedirectory/resource_active_directory_domain_update_test.go index f88bc7f5e808..de9069c50cc4 100644 --- a/mmv1/third_party/terraform/services/activedirectory/resource_active_directory_domain_update_test.go +++ b/mmv1/third_party/terraform/services/activedirectory/resource_active_directory_domain_update_test.go @@ -39,7 +39,7 @@ func TestAccActiveDirectoryDomain_update(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"domain_name"}, + ImportStateVerifyIgnore: []string{"domain_name", "labels", "terraform_labels"}, }, { Config: testAccADDomainUpdate(context), @@ -48,7 +48,7 @@ func TestAccActiveDirectoryDomain_update(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"domain_name"}, + ImportStateVerifyIgnore: []string{"domain_name", "labels", "terraform_labels"}, }, { Config: testAccADDomainBasic(context), @@ -57,7 +57,7 @@ func TestAccActiveDirectoryDomain_update(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"domain_name"}, + ImportStateVerifyIgnore: []string{"domain_name", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_backup_test.go b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_backup_test.go index 33091f142314..4223e1a81555 100644 --- a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_backup_test.go +++ b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_backup_test.go @@ -28,7 +28,7 @@ func TestAccAlloydbBackup_update(t *testing.T) { ResourceName: "google_alloydb_backup.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"backup_id", "location", "reconciling", "update_time"}, + ImportStateVerifyIgnore: []string{"backup_id", "location", "reconciling", "update_time", "labels", "terraform_labels"}, }, { Config: testAccAlloydbBackup_update(context), @@ -37,7 +37,7 @@ func TestAccAlloydbBackup_update(t *testing.T) { ResourceName: "google_alloydb_backup.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"backup_id", "location", "reconciling", "update_time"}, + ImportStateVerifyIgnore: []string{"backup_id", "location", "reconciling", "update_time", "labels", "terraform_labels"}, }, }, }) @@ -190,7 +190,7 @@ func TestAccAlloydbBackup_usingCMEK(t *testing.T) { ResourceName: "google_alloydb_backup.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"backup_id", "location", "reconciling", "update_time"}, + ImportStateVerifyIgnore: []string{"backup_id", "location", "reconciling", "update_time", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_test.go b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_test.go index 0539c908324b..f9394bced4c2 100644 --- a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_test.go +++ b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_test.go @@ -26,7 +26,7 @@ func TestAccAlloydbCluster_update(t *testing.T) { ResourceName: "google_alloydb_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location"}, + ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location", "labels", "terraform_labels"}, }, { Config: testAccAlloydbCluster_update(context), @@ -35,7 +35,7 @@ func TestAccAlloydbCluster_update(t *testing.T) { ResourceName: "google_alloydb_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location"}, + ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location", "labels", "terraform_labels"}, }, { Config: testAccAlloydbCluster_alloydbClusterBasicExample(context), diff --git a/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository_test.go b/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository_test.go index 7c663fbe0a60..735bec2d3beb 100644 --- a/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository_test.go +++ b/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository_test.go @@ -23,8 +23,8 @@ func TestAccDataSourceGoogleArtifactRegistryRepositoryConfig(t *testing.T) { { Config: testAccDataSourceGoogleArtifactRegistryRepositoryConfig(context), Check: resource.ComposeTestCheckFunc( - acctest.CheckDataSourceStateMatchesResourceState(funcDataName, - "google_artifact_registry_repository.my-repo"), + acctest.CheckDataSourceStateMatchesResourceStateWithIgnores(funcDataName, + "google_artifact_registry_repository.my-repo", map[string]struct{}{"labels.%": {}, "terraform_labels.%": {}}), ), }, }, @@ -38,6 +38,10 @@ resource "google_artifact_registry_repository" "my-repo" { repository_id = "tf-test-my-repository%{random_suffix}" description = "example docker repository%{random_suffix}" format = "DOCKER" + labels = { + my_key = "my_val" + other_key = "other_val" + } } data "google_artifact_registry_repository" "my-repo" { diff --git a/mmv1/third_party/terraform/services/artifactregistry/resource_artifact_registry_repository_test.go.erb b/mmv1/third_party/terraform/services/artifactregistry/resource_artifact_registry_repository_test.go.erb index d098eb1c0edc..6f409d267936 100644 --- a/mmv1/third_party/terraform/services/artifactregistry/resource_artifact_registry_repository_test.go.erb +++ b/mmv1/third_party/terraform/services/artifactregistry/resource_artifact_registry_repository_test.go.erb @@ -26,6 +26,7 @@ func TestAccArtifactRegistryRepository_update(t *testing.T) { ResourceName: "google_artifact_registry_repository.test", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccArtifactRegistryRepository_update2(repositoryID), @@ -34,6 +35,7 @@ func TestAccArtifactRegistryRepository_update(t *testing.T) { ResourceName: "google_artifact_registry_repository.test", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_job_test.go b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_job_test.go index 9de93bb6a2f7..3e8b4b832e3f 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_job_test.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_job_test.go @@ -32,7 +32,7 @@ func TestAccBigQueryJob_withLocation(t *testing.T) { ImportStateId: importID, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "status.0.state"}, + ImportStateVerifyIgnore: []string{"etag", "status.0.state", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go index cc5f910604d3..cb3482a9532b 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go @@ -1031,7 +1031,7 @@ func TestAccBigQueryDataTable_jsonEquivalency(t *testing.T) { ResourceName: "google_bigquery_table.test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection", "labels"}, + ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection", "labels", "terraform_labels"}, }, { Config: testAccBigQueryTable_jsonEqModeRemoved(datasetID, tableID), @@ -1040,7 +1040,7 @@ func TestAccBigQueryDataTable_jsonEquivalency(t *testing.T) { ResourceName: "google_bigquery_table.test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection", "labels"}, + ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection", "labels", "terraform_labels"}, }, }, }) @@ -1090,7 +1090,7 @@ func TestAccBigQueryDataTable_expandArray(t *testing.T) { ResourceName: "google_bigquery_table.test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection", "labels"}, + ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection", "labels", "terraform_labels"}, }, { Config: testAccBigQueryTable_arrayExpanded(datasetID, tableID), @@ -1099,7 +1099,7 @@ func TestAccBigQueryDataTable_expandArray(t *testing.T) { ResourceName: "google_bigquery_table.test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection", "labels"}, + ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection", "labels", "terraform_labels"}, }, }, }) @@ -1123,7 +1123,7 @@ func TestAccBigQueryTable_allowDestroy(t *testing.T) { ResourceName: "google_bigquery_table.test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"deletion_protection", "labels"}, + ImportStateVerifyIgnore: []string{"deletion_protection", "labels", "terraform_labels"}, }, { Config: testAccBigQueryTable_noAllowDestroy(datasetID, tableID), diff --git a/mmv1/third_party/terraform/services/certificatemanager/resource_certificate_manager_dns_authorization_test.go b/mmv1/third_party/terraform/services/certificatemanager/resource_certificate_manager_dns_authorization_test.go index f824e92ce94c..c25f72515e87 100644 --- a/mmv1/third_party/terraform/services/certificatemanager/resource_certificate_manager_dns_authorization_test.go +++ b/mmv1/third_party/terraform/services/certificatemanager/resource_certificate_manager_dns_authorization_test.go @@ -26,7 +26,7 @@ func TestAccCertificateManagerDnsAuthorization_update(t *testing.T) { ResourceName: "google_certificate_manager_dns_authorization.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name"}, + ImportStateVerifyIgnore: []string{"name", "labels", "terraform_labels"}, }, { Config: testAccCertificateManagerDnsAuthorization_update1(context), @@ -35,7 +35,7 @@ func TestAccCertificateManagerDnsAuthorization_update(t *testing.T) { ResourceName: "google_certificate_manager_dns_authorization.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name"}, + ImportStateVerifyIgnore: []string{"name", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/certificatemanager/resource_certificate_manager_trust_config_test.go b/mmv1/third_party/terraform/services/certificatemanager/resource_certificate_manager_trust_config_test.go index 89a5d4d0a9ad..b84cbb0530f6 100644 --- a/mmv1/third_party/terraform/services/certificatemanager/resource_certificate_manager_trust_config_test.go +++ b/mmv1/third_party/terraform/services/certificatemanager/resource_certificate_manager_trust_config_test.go @@ -23,17 +23,19 @@ func TestAccCertificateManagerTrustConfig_update(t *testing.T) { Config: testAccCertificateManagerTrustConfig_update0(context), }, { - ResourceName: "google_certificate_manager_trust_config.default", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_certificate_manager_trust_config.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccCertificateManagerTrustConfig_update1(context), }, { - ResourceName: "google_certificate_manager_trust_config.default", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_certificate_manager_trust_config.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function_test.go.erb b/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function_test.go.erb index 97805cafbf09..9bf727547801 100644 --- a/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function_test.go.erb +++ b/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function_test.go.erb @@ -80,7 +80,7 @@ func TestAccCloudFunctionsFunction_basic(t *testing.T) { ResourceName: funcResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"build_environment_variables", "labels"}, + ImportStateVerifyIgnore: []string{"build_environment_variables", "labels", "terraform_labels"}, }, }, }) @@ -117,7 +117,7 @@ func TestAccCloudFunctionsFunction_update(t *testing.T) { ResourceName: funcResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"build_environment_variables", "labels"}, + ImportStateVerifyIgnore: []string{"build_environment_variables", "labels", "terraform_labels"}, }, { Config: testAccCloudFunctionsFunction_updated(functionName, bucketName, zipFileUpdatePath, random_suffix), @@ -150,7 +150,7 @@ func TestAccCloudFunctionsFunction_update(t *testing.T) { ResourceName: funcResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"build_environment_variables", "labels"}, + ImportStateVerifyIgnore: []string{"build_environment_variables", "labels", "terraform_labels"}, }, }, }) @@ -425,7 +425,7 @@ func TestAccCloudFunctionsFunction_vpcConnector(t *testing.T) { ResourceName: funcResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"build_environment_variables", "labels"}, + ImportStateVerifyIgnore: []string{"build_environment_variables", "labels", "terraform_labels"}, }, { Config: testAccCloudFunctionsFunction_vpcConnector(projectNumber, networkName, functionName, bucketName, zipFilePath, "10.20.0.0/28", vpcConnectorName+"-update"), @@ -434,7 +434,7 @@ func TestAccCloudFunctionsFunction_vpcConnector(t *testing.T) { ResourceName: funcResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"build_environment_variables", "labels"}, + ImportStateVerifyIgnore: []string{"build_environment_variables", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/cloudfunctions2/data_source_google_cloudfunctions2_function_test.go b/mmv1/third_party/terraform/services/cloudfunctions2/data_source_google_cloudfunctions2_function_test.go index 3769b961f991..7f4d5db5baf7 100644 --- a/mmv1/third_party/terraform/services/cloudfunctions2/data_source_google_cloudfunctions2_function_test.go +++ b/mmv1/third_party/terraform/services/cloudfunctions2/data_source_google_cloudfunctions2_function_test.go @@ -24,9 +24,11 @@ func TestAccDataSourceGoogleCloudFunctions2Function_basic(t *testing.T) { { Config: testAccDataSourceGoogleCloudFunctions2FunctionConfig(functionName, bucketName, zipFilePath), + // As the value of "labels" and "terraform_labels" in the state is dependent on the configuration, + // and these fields are not set in the configuration of the data source, so these fields are empty in the state of the data source. Check: resource.ComposeTestCheckFunc( acctest.CheckDataSourceStateMatchesResourceStateWithIgnores(funcDataNameHttp, - "google_cloudfunctions2_function.function_http_v2", map[string]struct{}{"build_config.0.source.0.storage_source.0.bucket": {}, "build_config.0.source.0.storage_source.0.object": {}}), + "google_cloudfunctions2_function.function_http_v2", map[string]struct{}{"build_config.0.source.0.storage_source.0.bucket": {}, "build_config.0.source.0.storage_source.0.object": {}, "labels.%": {}, "terraform_labels.%": {}}), ), }, }, @@ -35,6 +37,12 @@ func TestAccDataSourceGoogleCloudFunctions2Function_basic(t *testing.T) { func testAccDataSourceGoogleCloudFunctions2FunctionConfig(functionName, bucketName, zipFilePath string) string { return fmt.Sprintf(` +provider "google" { + default_labels = { + default_key1 = "default_value1" + } +} + resource "google_storage_bucket" "bucket" { name = "%s" location = "US" @@ -50,7 +58,9 @@ resource "google_cloudfunctions2_function" "function_http_v2" { name = "%s" location = "us-central1" description = "a new function" - + labels = { + env = "test" + } build_config { runtime = "nodejs12" entry_point = "helloHttp" diff --git a/mmv1/third_party/terraform/services/cloudfunctions2/resource_cloudfunctions2_function_test.go b/mmv1/third_party/terraform/services/cloudfunctions2/resource_cloudfunctions2_function_test.go index 443a86fa0e94..ab82a584fbca 100644 --- a/mmv1/third_party/terraform/services/cloudfunctions2/resource_cloudfunctions2_function_test.go +++ b/mmv1/third_party/terraform/services/cloudfunctions2/resource_cloudfunctions2_function_test.go @@ -28,7 +28,7 @@ func TestAccCloudFunctions2Function_update(t *testing.T) { ResourceName: "google_cloudfunctions2_function.terraform-test2", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"location", "build_config.0.source.0.storage_source.0.object", "build_config.0.source.0.storage_source.0.bucket"}, + ImportStateVerifyIgnore: []string{"location", "build_config.0.source.0.storage_source.0.object", "build_config.0.source.0.storage_source.0.bucket", "labels", "terraform_labels"}, }, { Config: testAccCloudFunctions2Function_test_update(context), @@ -37,7 +37,7 @@ func TestAccCloudFunctions2Function_update(t *testing.T) { ResourceName: "google_cloudfunctions2_function.terraform-test2", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"location", "build_config.0.source.0.storage_source.0.object", "build_config.0.source.0.storage_source.0.bucket"}, + ImportStateVerifyIgnore: []string{"location", "build_config.0.source.0.storage_source.0.object", "build_config.0.source.0.storage_source.0.bucket", "labels", "terraform_labels"}, }, { Config: testAccCloudFunctions2Function_test_redeploy(context), @@ -46,7 +46,7 @@ func TestAccCloudFunctions2Function_update(t *testing.T) { ResourceName: "google_cloudfunctions2_function.terraform-test2", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"location", "build_config.0.source.0.storage_source.0.object", "build_config.0.source.0.storage_source.0.bucket"}, + ImportStateVerifyIgnore: []string{"location", "build_config.0.source.0.storage_source.0.object", "build_config.0.source.0.storage_source.0.bucket", "labels", "terraform_labels"}, }, }, }) @@ -70,6 +70,9 @@ resource "google_cloudfunctions2_function" "terraform-test2" { name = "tf-test-test-function%{random_suffix}" location = "us-central1" description = "a new function" + labels = { + env = "test" + } build_config { runtime = "nodejs12" @@ -109,7 +112,10 @@ resource "google_cloudfunctions2_function" "terraform-test2" { name = "tf-test-test-function%{random_suffix}" location = "us-central1" description = "an updated function" - + labels = { + env = "test-update" + } + build_config { runtime = "nodejs12" entry_point = "helloHttp" 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 index 7620f5b6978b..4b03127fa114 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 @@ -26,7 +26,7 @@ func TestAccCloudRunV2Job_cloudrunv2JobFullUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_job.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"location", "launch_stage", "annotations"}, + ImportStateVerifyIgnore: []string{"location", "launch_stage", "labels", "terraform_labels", "annotations"}, }, { Config: testAccCloudRunV2Job_cloudrunv2JobFullUpdate(context), @@ -35,7 +35,7 @@ func TestAccCloudRunV2Job_cloudrunv2JobFullUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_job.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"location", "launch_stage", "annotations"}, + ImportStateVerifyIgnore: []string{"location", "launch_stage", "labels", "terraform_labels", "annotations"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go index feb6bfbd9959..b7ff80105dda 100644 --- a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go +++ b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go @@ -30,7 +30,7 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceFullUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location", "annotations"}, + ImportStateVerifyIgnore: []string{"name", "location", "annotations", "labels", "terraform_labels"}, }, { Config: testAccCloudRunV2Service_cloudrunv2ServiceFullUpdate(context), @@ -39,7 +39,7 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceFullUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location", "annotations"}, + ImportStateVerifyIgnore: []string{"name", "location", "annotations", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/databasemigrationservice/resource_database_migration_service_connection_profile_test.go b/mmv1/third_party/terraform/services/databasemigrationservice/resource_database_migration_service_connection_profile_test.go index 598da3507871..439c8b395198 100644 --- a/mmv1/third_party/terraform/services/databasemigrationservice/resource_database_migration_service_connection_profile_test.go +++ b/mmv1/third_party/terraform/services/databasemigrationservice/resource_database_migration_service_connection_profile_test.go @@ -25,7 +25,7 @@ func TestAccDatabaseMigrationServiceConnectionProfile_update(t *testing.T) { ResourceName: "google_database_migration_service_connection_profile.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"connection_profile_id", "location", "mysql.0.password"}, + ImportStateVerifyIgnore: []string{"connection_profile_id", "location", "mysql.0.password", "labels", "terraform_labels"}, }, { Config: testAccDatabaseMigrationServiceConnectionProfile_update(suffix), @@ -34,7 +34,7 @@ func TestAccDatabaseMigrationServiceConnectionProfile_update(t *testing.T) { ResourceName: "google_database_migration_service_connection_profile.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"connection_profile_id", "location", "mysql.0.password"}, + ImportStateVerifyIgnore: []string{"connection_profile_id", "location", "mysql.0.password", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/datafusion/resource_data_fusion_instance_test.go b/mmv1/third_party/terraform/services/datafusion/resource_data_fusion_instance_test.go index f245f7334cce..b741c39a53b6 100644 --- a/mmv1/third_party/terraform/services/datafusion/resource_data_fusion_instance_test.go +++ b/mmv1/third_party/terraform/services/datafusion/resource_data_fusion_instance_test.go @@ -21,17 +21,19 @@ func TestAccDataFusionInstance_update(t *testing.T) { Config: testAccDataFusionInstance_basic(instanceName), }, { - ResourceName: "google_data_fusion_instance.foobar", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_data_fusion_instance.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccDataFusionInstance_updated(instanceName), }, { - ResourceName: "google_data_fusion_instance.foobar", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_data_fusion_instance.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -97,17 +99,19 @@ func TestAccDataFusionInstanceEnterprise_update(t *testing.T) { Config: testAccDataFusionInstanceEnterprise_basic(instanceName), }, { - ResourceName: "google_data_fusion_instance.foobar", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_data_fusion_instance.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccDataFusionInstanceEnterprise_updated(instanceName), }, { - ResourceName: "google_data_fusion_instance.foobar", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_data_fusion_instance.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/datastream/resource_datastream_stream_test.go b/mmv1/third_party/terraform/services/datastream/resource_datastream_stream_test.go index dde019ab0af1..ad71b868cd22 100644 --- a/mmv1/third_party/terraform/services/datastream/resource_datastream_stream_test.go +++ b/mmv1/third_party/terraform/services/datastream/resource_datastream_stream_test.go @@ -33,7 +33,7 @@ func TestAccDatastreamStream_update(t *testing.T) { ResourceName: "google_datastream_stream.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"stream_id", "location", "desired_state"}, + ImportStateVerifyIgnore: []string{"stream_id", "location", "desired_state", "labels", "terraform_labels"}, }, { Config: testAccDatastreamStream_datastreamStreamBasicUpdate(context, "RUNNING", true), @@ -43,7 +43,7 @@ func TestAccDatastreamStream_update(t *testing.T) { ResourceName: "google_datastream_stream.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"stream_id", "location", "desired_state"}, + ImportStateVerifyIgnore: []string{"stream_id", "location", "desired_state", "labels", "terraform_labels"}, }, { Config: testAccDatastreamStream_datastreamStreamBasicUpdate(context, "PAUSED", true), @@ -53,7 +53,7 @@ func TestAccDatastreamStream_update(t *testing.T) { ResourceName: "google_datastream_stream.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"stream_id", "location", "desired_state"}, + ImportStateVerifyIgnore: []string{"stream_id", "location", "desired_state", "labels", "terraform_labels"}, }, { Config: testAccDatastreamStream_datastreamStreamBasicUpdate(context, "RUNNING", true), @@ -63,7 +63,7 @@ func TestAccDatastreamStream_update(t *testing.T) { ResourceName: "google_datastream_stream.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"stream_id", "location", "desired_state"}, + ImportStateVerifyIgnore: []string{"stream_id", "location", "desired_state", "labels", "terraform_labels"}, }, { // Disable prevent_destroy From 912551f1606753d938c76c892b28240de7d6c8ab Mon Sep 17 00:00:00 2001 From: Riley Karson Date: Mon, 18 Sep 2023 13:07:19 -0700 Subject: [PATCH 37/67] Breaking change: Stop deleting failed GKE clusters, taint instead (#8978) --- .../resource_container_cluster.go.erb | 72 +++---------------- .../resource_container_cluster_test.go.erb | 15 ++-- 2 files changed, 17 insertions(+), 70 deletions(-) diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb index d031f130dcd0..29bd46fee95a 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb @@ -2324,12 +2324,11 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er } // For now PSC based cluster don't support `enable_private_endpoint` on `create`, but only on `update` API call. - // If cluster is PSC based and enable_private_endpoint is set to true we will ignore it on `create` call and update cluster right after creation. + // If cluster is PSC based and enable_private_endpoint is set to true we will ignore it on `create` call and update cluster right after creation. enablePrivateEndpointPSCCluster := isEnablePrivateEndpointPSCCluster(cluster) if enablePrivateEndpointPSCCluster { cluster.PrivateClusterConfig.EnablePrivateEndpoint = false } - req := &container.CreateClusterRequest{ Cluster: cluster, @@ -2369,29 +2368,26 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er if err := d.Set("operation", op.Name); err != nil { return fmt.Errorf("Error setting operation: %s", err) } + return nil default: // leaving default case to ensure this is non blocking } + // Try a GET on the cluster so we can see the state in debug logs. This will help classify error states. clusterGetCall := config.NewContainerClient(userAgent).Projects.Locations.Clusters.Get(containerClusterFullName(project, location, clusterName)) if config.UserProjectOverride { clusterGetCall.Header().Add("X-Goog-User-Project", project) } + _, getErr := clusterGetCall.Do() if getErr != nil { log.Printf("[WARN] Cluster %s was created in an error state and not found", clusterName) d.SetId("") } - if deleteErr := cleanFailedContainerCluster(d, meta); deleteErr != nil { - log.Printf("[WARN] Unable to clean up cluster from failed creation: %s", deleteErr) - // Leave ID set as the cluster likely still exists and should not be removed from state yet. - } else { - log.Printf("[WARN] Verified failed creation of cluster %s was cleaned up", d.Id()) - d.SetId("") - } - // The resource didn't actually create + // Don't clear cluster id, this will taint the resource + log.Printf("[WARN] GKE cluster %s was created in an error state, and has been marked as tainted", clusterName) return waitErr } @@ -2536,14 +2532,8 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro d.SetId("") } - if deleteErr := cleanFailedContainerCluster(d, meta); deleteErr != nil { - log.Printf("[WARN] Unable to clean up cluster from failed creation: %s", deleteErr) - // Leave ID set as the cluster likely still exists and should not be removed from state yet. - } else { - log.Printf("[WARN] Verified failed creation of cluster %s was cleaned up", d.Id()) - d.SetId("") - } - // The resource didn't actually create + // Don't clear cluster id, this will taint the resource + log.Printf("[WARN] GKE cluster %s was created in an error state, and has been marked as tainted", clusterName) return waitErr } } @@ -4153,52 +4143,6 @@ func resourceContainerClusterDelete(d *schema.ResourceData, meta interface{}) er return nil } -// cleanFailedContainerCluster deletes clusters that failed but were -// created in an error state. Similar to resourceContainerClusterDelete -// but implemented in separate function as it doesn't try to lock already -// locked cluster state, does different error handling, and doesn't do retries. -func cleanFailedContainerCluster(d *schema.ResourceData, meta interface{}) error { - config := meta.(*transport_tpg.Config) - - project, err := tpgresource.GetProject(d, config) - if err != nil { - return err - } - - location, err := tpgresource.GetLocation(d, config) - if err != nil { - return err - } - - userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) - if err != nil { - return err - } - - clusterName := d.Get("name").(string) - fullName := containerClusterFullName(project, location, clusterName) - - log.Printf("[DEBUG] Cleaning up failed GKE cluster %s", d.Get("name").(string)) - clusterDeleteCall := config.NewContainerClient(userAgent).Projects.Locations.Clusters.Delete(fullName) - if config.UserProjectOverride { - clusterDeleteCall.Header().Add("X-Goog-User-Project", project) - } - op, err := clusterDeleteCall.Do() - if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Container Cluster %q", d.Get("name").(string))) - } - - // Wait until it's deleted - waitErr := ContainerOperationWait(config, op, project, location, "deleting GKE cluster", userAgent, d.Timeout(schema.TimeoutDelete)) - if waitErr != nil { - return waitErr - } - - log.Printf("[INFO] GKE cluster %s has been deleted", d.Id()) - d.SetId("") - return nil -} - var containerClusterRestingStates = RestingStates{ "RUNNING": ReadyState, "DEGRADED": ErrorState, diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb index 6b0db114d9dd..189b776fc7ae 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb @@ -3356,6 +3356,9 @@ func TestAccContainerCluster_autoprovisioningDefaultsManagement(t *testing.T) { }) } +// This resource originally cleaned up the dangling cluster directly, but now +// taints it, having Terraform clean it up during the next apply. This test +// name is now inexact, but is being preserved to maintain the test history. func TestAccContainerCluster_errorCleanDanglingCluster(t *testing.T) { t.Parallel() @@ -3376,18 +3379,18 @@ func TestAccContainerCluster_errorCleanDanglingCluster(t *testing.T) { Config: initConfig, }, { - ResourceName: "google_container_cluster.cidr_error_preempt", - ImportState: true, + ResourceName: "google_container_cluster.cidr_error_preempt", + ImportState: true, ImportStateVerify: true, }, { - Config: overlapConfig, + Config: overlapConfig, ExpectError: regexp.MustCompile("Error waiting for creating GKE cluster"), }, - // If dangling cluster wasn't deleted, this plan will return an error + // If tainted cluster won't be deleted, this step will return an error { - Config: overlapConfig, - PlanOnly: true, + Config: overlapConfig, + PlanOnly: true, ExpectNonEmptyPlan: true, }, }, From d6b01a29f7d15c1488d05735a4a98c3d50880ca1 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Mon, 18 Sep 2023 16:45:14 -0700 Subject: [PATCH 38/67] Apply new labels model to more resources (part 2) (#8980) * Apply new labels model to more resources (part 2) * Apply new labels model to more resources (part 3) * Fix unit test --- mmv1/products/compute/Disk.yaml | 2 +- mmv1/products/compute/ExternalVpnGateway.yaml | 2 +- mmv1/products/compute/Image.yaml | 2 +- mmv1/products/compute/Instance.yaml | 2 +- mmv1/products/compute/RegionDisk.yaml | 2 +- mmv1/products/compute/Snapshot.yaml | 2 +- mmv1/products/dialogflowcx/Intent.yaml | 2 +- mmv1/products/dns/ManagedZone.yaml | 2 +- mmv1/products/filestore/Backup.yaml | 2 +- mmv1/products/filestore/Instance.yaml | 2 +- mmv1/products/filestore/Snapshot.yaml | 2 +- mmv1/products/gkehub/Membership.yaml | 2 +- mmv1/products/gkehub2/MembershipBinding.yaml | 2 +- mmv1/products/gkehub2/Namespace.yaml | 2 +- mmv1/products/gkehub2/Scope.yaml | 2 +- .../gkehub2/ScopeRBACRoleBinding.yaml | 2 +- mmv1/products/kms/CryptoKey.yaml | 2 +- mmv1/products/memcache/Instance.yaml | 2 +- mmv1/products/metastore/Federation.yaml | 2 +- mmv1/products/metastore/Service.yaml | 2 +- mmv1/products/mlengine/Model.yaml | 2 +- .../networkmanagement/ConnectivityTest.yaml | 2 +- .../networksecurity/AuthorizationPolicy.yaml | 2 +- .../networksecurity/ClientTlsPolicy.yaml | 2 +- .../networksecurity/ServerTlsPolicy.yaml | 2 +- .../networkservices/EdgeCacheKeyset.yaml | 2 +- .../networkservices/EdgeCacheOrigin.yaml | 2 +- .../networkservices/EdgeCacheService.yaml | 2 +- .../networkservices/EndpointPolicy.yaml | 2 +- mmv1/products/networkservices/Gateway.yaml | 2 +- mmv1/products/networkservices/GrpcRoute.yaml | 2 +- mmv1/products/networkservices/HttpRoute.yaml | 2 +- mmv1/products/networkservices/Mesh.yaml | 2 +- .../networkservices/ServiceBinding.yaml | 2 +- mmv1/products/networkservices/TcpRoute.yaml | 2 +- mmv1/products/privateca/Certificate.yaml | 2 +- mmv1/products/pubsub/Subscription.yaml | 2 +- mmv1/products/pubsub/Topic.yaml | 2 +- mmv1/products/redis/Instance.yaml | 2 +- mmv1/products/servicedirectory/Namespace.yaml | 2 +- mmv1/products/spanner/Instance.yaml | 2 +- mmv1/products/storage/Bucket.yaml | 2 +- mmv1/products/tpu/Node.yaml | 2 +- mmv1/products/vertexai/Dataset.yaml | 3 +- mmv1/products/vertexai/Featurestore.yaml | 2 +- .../vertexai/FeaturestoreEntitytype.yaml | 2 +- .../FeaturestoreEntitytypeFeature.yaml | 2 +- mmv1/products/vertexai/Index.yaml | 2 +- mmv1/products/vertexai/IndexEndpoint.yaml | 2 +- mmv1/products/vertexai/Tensorboard.yaml | 2 +- mmv1/products/workflows/Workflow.yaml | 2 +- mmv1/products/workstations/Workstation.yaml | 2 +- .../workstations/WorkstationConfig.yaml | 2 +- .../dataproc_metastore_service_basic.tf.erb | 4 ++ .../examples/gkehub_membership_basic.tf.erb | 4 ++ .../examples/memcache_instance_basic.tf.erb | 4 ++ ...agement_connectivity_test_instances.tf.erb | 3 ++ .../only_external_vpn_gateway_full.tf.erb | 1 - .../examples/vertex_ai_dataset.tf.erb | 4 ++ .../terraform/examples/workflow_basic.tf.erb | 3 ++ .../examples/workstation_config_basic.tf.erb | 4 ++ ...ata_source_google_compute_snapshot_test.go | 6 +-- .../compute/resource_compute_disk_test.go.erb | 5 ++ ...ource_compute_external_vpn_gateway_test.go | 14 ++--- .../resource_compute_image_test.go.erb | 6 +-- ...urce_compute_instance_template_test.go.erb | 1 - .../resource_compute_region_disk_test.go.erb | 4 ++ ...mpute_region_instance_template_test.go.erb | 1 - .../resource_dialogflowcx_intent_test.go | 14 ++--- .../dns/resource_dns_managed_zone_test.go.erb | 5 ++ .../resource_filestore_backup_test.go | 2 +- .../resource_filestore_instance_test.go | 2 +- ...esource_gke_hub_membership_binding_test.go | 4 +- .../resource_gke_hub_namespace_test.go | 4 +- ...ce_gke_hub_scope_rbac_role_binding_test.go | 4 +- .../gkehub2/resource_gke_hub_scope_test.go | 4 +- .../kms/resource_kms_crypto_key_test.go | 53 +++++++++++-------- ..._security_authorization_policy_test.go.erb | 2 + ...ork_security_client_tls_policy_test.go.erb | 4 +- ...ork_security_server_tls_policy_test.go.erb | 2 + ...network_services_edge_cache_keyset_test.go | 4 +- ...network_services_edge_cache_origin_test.go | 4 +- ...twork_services_endpoint_policy_test.go.erb | 2 + .../resource_network_services_gateway_test.go | 14 ++--- ...ce_network_services_grpc_route_test.go.erb | 2 + ...ce_network_services_http_route_test.go.erb | 2 + ...resource_network_services_mesh_test.go.erb | 2 + ...rce_network_services_tcp_route_test.go.erb | 4 +- .../resource_privateca_certificate_test.go | 2 +- .../resource_pubsub_subscription_test.go | 27 +++++----- .../pubsub/resource_pubsub_topic_test.go | 18 ++++--- .../redis/resource_redis_instance_test.go | 14 ++--- ...ce_service_directory_namespace_test.go.erb | 1 + .../spanner/resource_spanner_instance_test.go | 14 ++--- .../data_source_vertex_ai_index_test.go | 2 + .../resource_vertex_ai_endpoint_test.go | 4 +- .../vertexai/resource_vertex_ai_index_test.go | 4 +- .../resource_vertex_ai_tensorboard_test.go | 12 ++--- ...orkstations_workstation_config_test.go.erb | 14 ++--- ...ource_workstations_workstation_test.go.erb | 4 +- .../data/example_compute_disk.tfplan.json | 14 +++++ ...ample_compute_disk_empty_image.tfplan.json | 14 +++++ .../data/example_compute_snapshot.tfplan.json | 28 ++++++++-- .../example_pubsub_subscription.tfplan.json | 32 ++++++++++- ...ubsub_subscription_iam_binding.tfplan.json | 20 ++++++- ...pubsub_subscription_iam_member.tfplan.json | 20 ++++++- ...pubsub_subscription_iam_policy.tfplan.json | 20 ++++++- .../data/example_pubsub_topic.tfplan.json | 16 +++++- .../data/full_spanner_instance.tfplan.json | 24 ++++++++- 109 files changed, 423 insertions(+), 186 deletions(-) diff --git a/mmv1/products/compute/Disk.yaml b/mmv1/products/compute/Disk.yaml index 58935e9fa227..1a9893cd2d20 100644 --- a/mmv1/products/compute/Disk.yaml +++ b/mmv1/products/compute/Disk.yaml @@ -290,7 +290,7 @@ properties: name: 'lastDetachTimestamp' description: 'Last detach timestamp in RFC3339 text format.' output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels to apply to this disk. A list of key->value pairs. diff --git a/mmv1/products/compute/ExternalVpnGateway.yaml b/mmv1/products/compute/ExternalVpnGateway.yaml index 7fd92d7952f3..271b0f23daee 100644 --- a/mmv1/products/compute/ExternalVpnGateway.yaml +++ b/mmv1/products/compute/ExternalVpnGateway.yaml @@ -63,7 +63,7 @@ properties: - !ruby/object:Api::Type::String name: 'description' description: 'An optional description of this resource.' - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'Labels for the external VPN gateway resource.' update_verb: :POST diff --git a/mmv1/products/compute/Image.yaml b/mmv1/products/compute/Image.yaml index 2c428d454187..622f1f43d7da 100644 --- a/mmv1/products/compute/Image.yaml +++ b/mmv1/products/compute/Image.yaml @@ -170,7 +170,7 @@ properties: The service account being used for the encryption request for the given KMS key. If absent, the Compute Engine default service account is used. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Labels to apply to this Image. update_verb: :POST diff --git a/mmv1/products/compute/Instance.yaml b/mmv1/products/compute/Instance.yaml index 4d8111c04eae..027578e5e10c 100644 --- a/mmv1/products/compute/Instance.yaml +++ b/mmv1/products/compute/Instance.yaml @@ -295,7 +295,7 @@ properties: internally during updates. update_url: 'projects/{{project}}/zones/{{zone}}/instances/{{name}}/setLabels' update_verb: :POST - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels to apply to this instance. A list of key->value pairs. diff --git a/mmv1/products/compute/RegionDisk.yaml b/mmv1/products/compute/RegionDisk.yaml index 94424537f21b..d421a950923f 100644 --- a/mmv1/products/compute/RegionDisk.yaml +++ b/mmv1/products/compute/RegionDisk.yaml @@ -218,7 +218,7 @@ properties: name: 'lastDetachTimestamp' description: 'Last detach timestamp in RFC3339 text format.' output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels to apply to this disk. A list of key->value pairs. diff --git a/mmv1/products/compute/Snapshot.yaml b/mmv1/products/compute/Snapshot.yaml index 2f04ab0fb2a1..9d7ad7ffe598 100644 --- a/mmv1/products/compute/Snapshot.yaml +++ b/mmv1/products/compute/Snapshot.yaml @@ -236,7 +236,7 @@ properties: imports: 'selfLink' description: 'A reference to a license associated with this snapshot' custom_expand: 'templates/terraform/custom_expand/array_resourceref_with_validation.go.erb' - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Labels to apply to this Snapshot. update_verb: :POST diff --git a/mmv1/products/dialogflowcx/Intent.yaml b/mmv1/products/dialogflowcx/Intent.yaml index caf8c2dd32d7..479e7756756e 100644 --- a/mmv1/products/dialogflowcx/Intent.yaml +++ b/mmv1/products/dialogflowcx/Intent.yaml @@ -144,7 +144,7 @@ properties: description: | Indicates whether this is a fallback intent. Currently only default fallback intent is allowed in the agent, which is added upon agent creation. Adding training phrases to fallback intent is useful in the case of requests that are mistakenly matched, since training phrases assigned to fallback intents act as negative examples that triggers no-match event. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | The key/value metadata to label an intent. Labels can contain lowercase letters, digits and the symbols '-' and '_'. International characters are allowed, including letters from unicase alphabets. Keys must start with a letter. Keys and values can be no longer than 63 characters and no more than 128 bytes. diff --git a/mmv1/products/dns/ManagedZone.yaml b/mmv1/products/dns/ManagedZone.yaml index 62565124dfad..9c2bf3c3c201 100644 --- a/mmv1/products/dns/ManagedZone.yaml +++ b/mmv1/products/dns/ManagedZone.yaml @@ -247,7 +247,7 @@ properties: The time that this resource was created on the server. This is in RFC3339 text format. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | A set of key/value label pairs to assign to this ManagedZone. diff --git a/mmv1/products/filestore/Backup.yaml b/mmv1/products/filestore/Backup.yaml index 134f6f46e49c..f1e78d7f8722 100644 --- a/mmv1/products/filestore/Backup.yaml +++ b/mmv1/products/filestore/Backup.yaml @@ -78,7 +78,7 @@ properties: description: | The time when the snapshot was created in RFC3339 text format. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels to represent user-provided metadata. diff --git a/mmv1/products/filestore/Instance.yaml b/mmv1/products/filestore/Instance.yaml index 22f7f161d8b3..319fb22c58f4 100644 --- a/mmv1/products/filestore/Instance.yaml +++ b/mmv1/products/filestore/Instance.yaml @@ -99,7 +99,7 @@ properties: Possible values include: STANDARD, PREMIUM, BASIC_HDD, BASIC_SSD, HIGH_SCALE_SSD and ENTERPRISE required: true immutable: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels to represent user-provided metadata. diff --git a/mmv1/products/filestore/Snapshot.yaml b/mmv1/products/filestore/Snapshot.yaml index e5390f5445ae..1ce5ea76bb50 100644 --- a/mmv1/products/filestore/Snapshot.yaml +++ b/mmv1/products/filestore/Snapshot.yaml @@ -89,7 +89,7 @@ properties: description: | The time when the snapshot was created in RFC3339 text format. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels to represent user-provided metadata. diff --git a/mmv1/products/gkehub/Membership.yaml b/mmv1/products/gkehub/Membership.yaml index a73d65715fd6..a828c70a6713 100644 --- a/mmv1/products/gkehub/Membership.yaml +++ b/mmv1/products/gkehub/Membership.yaml @@ -95,7 +95,7 @@ properties: min_version: beta description: | The name of this entity type to be displayed on the console. This field is unavailable in v1 of the API. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels to apply to this membership. diff --git a/mmv1/products/gkehub2/MembershipBinding.yaml b/mmv1/products/gkehub2/MembershipBinding.yaml index b3ff846f787f..54126ff200a0 100644 --- a/mmv1/products/gkehub2/MembershipBinding.yaml +++ b/mmv1/products/gkehub2/MembershipBinding.yaml @@ -132,7 +132,7 @@ properties: - :READY - :DELETING - :UPDATING - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels for this Membership binding. diff --git a/mmv1/products/gkehub2/Namespace.yaml b/mmv1/products/gkehub2/Namespace.yaml index 8b1901bbbe5e..b96e5e4e65e8 100644 --- a/mmv1/products/gkehub2/Namespace.yaml +++ b/mmv1/products/gkehub2/Namespace.yaml @@ -133,7 +133,7 @@ properties: Scope. Scope-level labels (`namespace_labels` in the Fleet Scope resource) take precedence over Namespace-level labels if they share a key. Keys and values must be Kubernetes-conformant. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels for this Namespace. diff --git a/mmv1/products/gkehub2/Scope.yaml b/mmv1/products/gkehub2/Scope.yaml index 86e1a806ac47..70ffbabfdaac 100644 --- a/mmv1/products/gkehub2/Scope.yaml +++ b/mmv1/products/gkehub2/Scope.yaml @@ -115,7 +115,7 @@ properties: - :READY - :DELETING - :UPDATING - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels for this Scope. diff --git a/mmv1/products/gkehub2/ScopeRBACRoleBinding.yaml b/mmv1/products/gkehub2/ScopeRBACRoleBinding.yaml index 850df3f36c3e..392699d1024e 100644 --- a/mmv1/products/gkehub2/ScopeRBACRoleBinding.yaml +++ b/mmv1/products/gkehub2/ScopeRBACRoleBinding.yaml @@ -148,7 +148,7 @@ properties: - :ADMIN - :EDIT - :VIEW - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels for this ScopeRBACRoleBinding. diff --git a/mmv1/products/kms/CryptoKey.yaml b/mmv1/products/kms/CryptoKey.yaml index bbfc7551db90..efa270a82173 100644 --- a/mmv1/products/kms/CryptoKey.yaml +++ b/mmv1/products/kms/CryptoKey.yaml @@ -80,7 +80,7 @@ properties: immutable: true url_param_only: true ignore_read: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels with user-defined metadata to apply to this resource. diff --git a/mmv1/products/memcache/Instance.yaml b/mmv1/products/memcache/Instance.yaml index a3dd514aa13f..fc24167d1212 100644 --- a/mmv1/products/memcache/Instance.yaml +++ b/mmv1/products/memcache/Instance.yaml @@ -99,7 +99,7 @@ properties: name: 'discoveryEndpoint' description: Endpoint for Discovery API output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels to represent user-provided metadata. diff --git a/mmv1/products/metastore/Federation.yaml b/mmv1/products/metastore/Federation.yaml index b4fadf816107..565f0d9f8077 100644 --- a/mmv1/products/metastore/Federation.yaml +++ b/mmv1/products/metastore/Federation.yaml @@ -92,7 +92,7 @@ properties: output: true description: | The relative resource name of the metastore federation. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'User-defined labels for the metastore federation.' - !ruby/object:Api::Type::String diff --git a/mmv1/products/metastore/Service.yaml b/mmv1/products/metastore/Service.yaml index b4097033db09..ec54fa3e782b 100644 --- a/mmv1/products/metastore/Service.yaml +++ b/mmv1/products/metastore/Service.yaml @@ -155,7 +155,7 @@ properties: output: true description: | The relative resource name of the metastore service. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'User-defined labels for the metastore service.' # This is an x-product resource reference. diff --git a/mmv1/products/mlengine/Model.yaml b/mmv1/products/mlengine/Model.yaml index 9ea33d2aa9f9..281cc3665f2e 100644 --- a/mmv1/products/mlengine/Model.yaml +++ b/mmv1/products/mlengine/Model.yaml @@ -96,6 +96,6 @@ properties: description: If true, online prediction nodes send stderr and stdout streams to Stackdriver Logging - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: One or more labels that you can add, to organize your models. diff --git a/mmv1/products/networkmanagement/ConnectivityTest.yaml b/mmv1/products/networkmanagement/ConnectivityTest.yaml index b68d0d350f43..35264ff07a99 100644 --- a/mmv1/products/networkmanagement/ConnectivityTest.yaml +++ b/mmv1/products/networkmanagement/ConnectivityTest.yaml @@ -204,7 +204,7 @@ properties: This is applicable to scenarios where a test can cross project boundaries. item_type: Api::Type::String - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels to represent user-provided metadata. diff --git a/mmv1/products/networksecurity/AuthorizationPolicy.yaml b/mmv1/products/networksecurity/AuthorizationPolicy.yaml index f4af9f533eee..daa0dda1a7fe 100644 --- a/mmv1/products/networksecurity/AuthorizationPolicy.yaml +++ b/mmv1/products/networksecurity/AuthorizationPolicy.yaml @@ -84,7 +84,7 @@ properties: description: | Time the AuthorizationPolicy was updated in UTC. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Set of label tags associated with the AuthorizationPolicy resource. diff --git a/mmv1/products/networksecurity/ClientTlsPolicy.yaml b/mmv1/products/networksecurity/ClientTlsPolicy.yaml index 7773d5354768..0f87404c7b78 100644 --- a/mmv1/products/networksecurity/ClientTlsPolicy.yaml +++ b/mmv1/products/networksecurity/ClientTlsPolicy.yaml @@ -86,7 +86,7 @@ properties: description: | Time the ClientTlsPolicy was updated in UTC. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Set of label tags associated with the ClientTlsPolicy resource. - !ruby/object:Api::Type::String diff --git a/mmv1/products/networksecurity/ServerTlsPolicy.yaml b/mmv1/products/networksecurity/ServerTlsPolicy.yaml index c300f03f5e12..556af18eb7ef 100644 --- a/mmv1/products/networksecurity/ServerTlsPolicy.yaml +++ b/mmv1/products/networksecurity/ServerTlsPolicy.yaml @@ -90,7 +90,7 @@ properties: description: | Time the ServerTlsPolicy was updated in UTC. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Set of label tags associated with the ServerTlsPolicy resource. - !ruby/object:Api::Type::String diff --git a/mmv1/products/networkservices/EdgeCacheKeyset.yaml b/mmv1/products/networkservices/EdgeCacheKeyset.yaml index d8b79ef24b28..b1ec5986023d 100644 --- a/mmv1/products/networkservices/EdgeCacheKeyset.yaml +++ b/mmv1/products/networkservices/EdgeCacheKeyset.yaml @@ -74,7 +74,7 @@ properties: name: 'description' description: | A human-readable description of the resource. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'Set of label tags associated with the EdgeCache resource.' - !ruby/object:Api::Type::Array diff --git a/mmv1/products/networkservices/EdgeCacheOrigin.yaml b/mmv1/products/networkservices/EdgeCacheOrigin.yaml index ddd14fe88e2c..3389965ce53d 100644 --- a/mmv1/products/networkservices/EdgeCacheOrigin.yaml +++ b/mmv1/products/networkservices/EdgeCacheOrigin.yaml @@ -82,7 +82,7 @@ properties: name: 'description' description: | A human-readable description of the resource. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'Set of label tags associated with the EdgeCache resource.' - !ruby/object:Api::Type::String diff --git a/mmv1/products/networkservices/EdgeCacheService.yaml b/mmv1/products/networkservices/EdgeCacheService.yaml index ff77b8df406e..71cb4feccd73 100644 --- a/mmv1/products/networkservices/EdgeCacheService.yaml +++ b/mmv1/products/networkservices/EdgeCacheService.yaml @@ -85,7 +85,7 @@ properties: name: 'description' description: | A human-readable description of the resource. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'Set of label tags associated with the EdgeCache resource.' - !ruby/object:Api::Type::Boolean diff --git a/mmv1/products/networkservices/EndpointPolicy.yaml b/mmv1/products/networkservices/EndpointPolicy.yaml index ff3effffd4cf..8a2088f5a227 100644 --- a/mmv1/products/networkservices/EndpointPolicy.yaml +++ b/mmv1/products/networkservices/EndpointPolicy.yaml @@ -76,7 +76,7 @@ properties: description: | Time the TcpRoute was updated in UTC. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Set of label tags associated with the TcpRoute resource. - !ruby/object:Api::Type::String diff --git a/mmv1/products/networkservices/Gateway.yaml b/mmv1/products/networkservices/Gateway.yaml index 49843a39241c..c04a69be5f5e 100644 --- a/mmv1/products/networkservices/Gateway.yaml +++ b/mmv1/products/networkservices/Gateway.yaml @@ -128,7 +128,7 @@ properties: description: | Time the AccessPolicy was updated in UTC. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Set of label tags associated with the Gateway resource. - !ruby/object:Api::Type::String diff --git a/mmv1/products/networkservices/GrpcRoute.yaml b/mmv1/products/networkservices/GrpcRoute.yaml index c8bd32e506c9..14efbe9ecf17 100644 --- a/mmv1/products/networkservices/GrpcRoute.yaml +++ b/mmv1/products/networkservices/GrpcRoute.yaml @@ -88,7 +88,7 @@ properties: description: | Time the GrpcRoute was updated in UTC. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Set of label tags associated with the GrpcRoute resource. - !ruby/object:Api::Type::String diff --git a/mmv1/products/networkservices/HttpRoute.yaml b/mmv1/products/networkservices/HttpRoute.yaml index 77575f4dcb0f..cb60ad50e730 100644 --- a/mmv1/products/networkservices/HttpRoute.yaml +++ b/mmv1/products/networkservices/HttpRoute.yaml @@ -97,7 +97,7 @@ properties: description: | Time the HttpRoute was updated in UTC. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Set of label tags associated with the HttpRoute resource. - !ruby/object:Api::Type::String diff --git a/mmv1/products/networkservices/Mesh.yaml b/mmv1/products/networkservices/Mesh.yaml index cc61b1d1b7c5..deb7437b985a 100644 --- a/mmv1/products/networkservices/Mesh.yaml +++ b/mmv1/products/networkservices/Mesh.yaml @@ -83,7 +83,7 @@ properties: description: | Time the Mesh was updated in UTC. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Set of label tags associated with the Mesh resource. - !ruby/object:Api::Type::String diff --git a/mmv1/products/networkservices/ServiceBinding.yaml b/mmv1/products/networkservices/ServiceBinding.yaml index ffda6f36d650..c13d23a7c94c 100644 --- a/mmv1/products/networkservices/ServiceBinding.yaml +++ b/mmv1/products/networkservices/ServiceBinding.yaml @@ -72,7 +72,7 @@ properties: description: | Time the ServiceBinding was updated in UTC. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Set of label tags associated with the ServiceBinding resource. - !ruby/object:Api::Type::String diff --git a/mmv1/products/networkservices/TcpRoute.yaml b/mmv1/products/networkservices/TcpRoute.yaml index 27be31a1b54f..7fae44f3f0bc 100644 --- a/mmv1/products/networkservices/TcpRoute.yaml +++ b/mmv1/products/networkservices/TcpRoute.yaml @@ -104,7 +104,7 @@ properties: description: | Time the TcpRoute was updated in UTC. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Set of label tags associated with the TcpRoute resource. - !ruby/object:Api::Type::String diff --git a/mmv1/products/privateca/Certificate.yaml b/mmv1/products/privateca/Certificate.yaml index 67f04352cd18..aed9215977fb 100644 --- a/mmv1/products/privateca/Certificate.yaml +++ b/mmv1/products/privateca/Certificate.yaml @@ -638,7 +638,7 @@ properties: omitted, no template will be used. This template must be in the same location as the Certificate. diff_suppress_func: 'tpgresource.CompareResourceNames' - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels with user-defined metadata to apply to this resource. diff --git a/mmv1/products/pubsub/Subscription.yaml b/mmv1/products/pubsub/Subscription.yaml index 2f40689d689c..1def915ef94c 100644 --- a/mmv1/products/pubsub/Subscription.yaml +++ b/mmv1/products/pubsub/Subscription.yaml @@ -107,7 +107,7 @@ properties: pattern: 'projects/{{project}}/topics/{{topic}}' diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' custom_expand: templates/terraform/custom_expand/computed_subscription_topic.erb - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | A set of key/value label pairs to assign to this Subscription. diff --git a/mmv1/products/pubsub/Topic.yaml b/mmv1/products/pubsub/Topic.yaml index 6bb9290a058f..16f25f459596 100644 --- a/mmv1/products/pubsub/Topic.yaml +++ b/mmv1/products/pubsub/Topic.yaml @@ -93,7 +93,7 @@ properties: (`service-{{PROJECT_NUMBER}}@gcp-sa-pubsub.iam.gserviceaccount.com`) must have `roles/cloudkms.cryptoKeyEncrypterDecrypter` to use this feature. The expected format is `projects/*/locations/*/keyRings/*/cryptoKeys/*` - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | A set of key/value label pairs to assign to this Topic. diff --git a/mmv1/products/redis/Instance.yaml b/mmv1/products/redis/Instance.yaml index e49c6e3ee36c..3aa6a3a8d434 100644 --- a/mmv1/products/redis/Instance.yaml +++ b/mmv1/products/redis/Instance.yaml @@ -156,7 +156,7 @@ properties: Hostname or IP address of the exposed Redis endpoint used by clients to connect to the service. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Resource labels to represent user provided metadata. - !ruby/object:Api::Type::KeyValuePairs diff --git a/mmv1/products/servicedirectory/Namespace.yaml b/mmv1/products/servicedirectory/Namespace.yaml index 8224784f9dd1..8d76947730ef 100644 --- a/mmv1/products/servicedirectory/Namespace.yaml +++ b/mmv1/products/servicedirectory/Namespace.yaml @@ -72,7 +72,7 @@ properties: The resource name for the namespace in the format `projects/*/locations/*/namespaces/*`. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels associated with this Namespace. No more than 64 user diff --git a/mmv1/products/spanner/Instance.yaml b/mmv1/products/spanner/Instance.yaml index bbc63c307ff6..6903c10a4416 100644 --- a/mmv1/products/spanner/Instance.yaml +++ b/mmv1/products/spanner/Instance.yaml @@ -143,7 +143,7 @@ properties: - num_nodes - processing_units default_from_api: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | An object containing a list of "key": value pairs. diff --git a/mmv1/products/storage/Bucket.yaml b/mmv1/products/storage/Bucket.yaml index bbf776e2f8df..979c5716bd58 100644 --- a/mmv1/products/storage/Bucket.yaml +++ b/mmv1/products/storage/Bucket.yaml @@ -464,7 +464,7 @@ properties: object is missing, if applicable, the service will return the named object from this bucket as the content for a 404 Not Found result. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels applied to this bucket. A list of key->value pairs. diff --git a/mmv1/products/tpu/Node.yaml b/mmv1/products/tpu/Node.yaml index e3d1ac84fdc5..c1d08907589e 100644 --- a/mmv1/products/tpu/Node.yaml +++ b/mmv1/products/tpu/Node.yaml @@ -153,7 +153,7 @@ properties: output: true description: | The port of this network endpoint. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' immutable: true description: Resource labels to represent user provided metadata. diff --git a/mmv1/products/vertexai/Dataset.yaml b/mmv1/products/vertexai/Dataset.yaml index 6f27a6d908e7..71f4bfad9ad3 100644 --- a/mmv1/products/vertexai/Dataset.yaml +++ b/mmv1/products/vertexai/Dataset.yaml @@ -81,11 +81,10 @@ properties: output: true description: | The timestamp of when the dataset was last updated in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | A set of key/value label pairs to assign to this Workflow. - default_from_api: true - !ruby/object:Api::Type::NestedObject name: 'encryptionSpec' immutable: true diff --git a/mmv1/products/vertexai/Featurestore.yaml b/mmv1/products/vertexai/Featurestore.yaml index d8ce854c04d3..40bb998ec75f 100644 --- a/mmv1/products/vertexai/Featurestore.yaml +++ b/mmv1/products/vertexai/Featurestore.yaml @@ -145,7 +145,7 @@ properties: output: true description: | The timestamp of when the featurestore was last updated in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | A set of key/value label pairs to assign to this Featurestore. diff --git a/mmv1/products/vertexai/FeaturestoreEntitytype.yaml b/mmv1/products/vertexai/FeaturestoreEntitytype.yaml index c7f097d95a1b..53fefc21ecfa 100644 --- a/mmv1/products/vertexai/FeaturestoreEntitytype.yaml +++ b/mmv1/products/vertexai/FeaturestoreEntitytype.yaml @@ -132,7 +132,7 @@ properties: output: true description: | The timestamp of when the featurestore was last updated in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | A set of key/value label pairs to assign to this EntityType. diff --git a/mmv1/products/vertexai/FeaturestoreEntitytypeFeature.yaml b/mmv1/products/vertexai/FeaturestoreEntitytypeFeature.yaml index 4152ab0e6327..b2379118329e 100644 --- a/mmv1/products/vertexai/FeaturestoreEntitytypeFeature.yaml +++ b/mmv1/products/vertexai/FeaturestoreEntitytypeFeature.yaml @@ -105,7 +105,7 @@ properties: output: true description: | The timestamp when the entity type was most recently updated in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | A set of key/value label pairs to assign to the feature. diff --git a/mmv1/products/vertexai/Index.yaml b/mmv1/products/vertexai/Index.yaml index 938893755581..b74896689f08 100644 --- a/mmv1/products/vertexai/Index.yaml +++ b/mmv1/products/vertexai/Index.yaml @@ -222,7 +222,7 @@ properties: description: Used to perform consistent read-modify-write updates. output: true ignore_read: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: The labels with user-defined metadata to organize your Indexes. - !ruby/object:Api::Type::String diff --git a/mmv1/products/vertexai/IndexEndpoint.yaml b/mmv1/products/vertexai/IndexEndpoint.yaml index 465147a362ed..ff10d04347eb 100644 --- a/mmv1/products/vertexai/IndexEndpoint.yaml +++ b/mmv1/products/vertexai/IndexEndpoint.yaml @@ -83,7 +83,7 @@ properties: description: Used to perform consistent read-modify-write updates. output: true ignore_read: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: The labels with user-defined metadata to organize your Indexes. - !ruby/object:Api::Type::String diff --git a/mmv1/products/vertexai/Tensorboard.yaml b/mmv1/products/vertexai/Tensorboard.yaml index 99c2895a1e1c..3d341ba2328e 100644 --- a/mmv1/products/vertexai/Tensorboard.yaml +++ b/mmv1/products/vertexai/Tensorboard.yaml @@ -113,7 +113,7 @@ properties: output: true description: | The timestamp of when the Tensorboard was last updated in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | The labels with user-defined metadata to organize your Tensorboards. diff --git a/mmv1/products/workflows/Workflow.yaml b/mmv1/products/workflows/Workflow.yaml index 80d80a05e276..3c7a4baad876 100644 --- a/mmv1/products/workflows/Workflow.yaml +++ b/mmv1/products/workflows/Workflow.yaml @@ -77,7 +77,7 @@ properties: name: 'state' output: true description: State of the workflow deployment. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | A set of key/value label pairs to assign to this Workflow. diff --git a/mmv1/products/workstations/Workstation.yaml b/mmv1/products/workstations/Workstation.yaml index 8edfa75b85e7..9bac34f941aa 100644 --- a/mmv1/products/workstations/Workstation.yaml +++ b/mmv1/products/workstations/Workstation.yaml @@ -117,7 +117,7 @@ properties: name: 'displayName' description: | Human-readable name for this resource. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'Client-specified labels that are applied to the resource and that are diff --git a/mmv1/products/workstations/WorkstationConfig.yaml b/mmv1/products/workstations/WorkstationConfig.yaml index aafeee3a5d9a..91ab07d5b811 100644 --- a/mmv1/products/workstations/WorkstationConfig.yaml +++ b/mmv1/products/workstations/WorkstationConfig.yaml @@ -153,7 +153,7 @@ properties: name: 'displayName' description: | Human-readable name for this resource. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'Client-specified labels that are applied to the resource and that are diff --git a/mmv1/templates/terraform/examples/dataproc_metastore_service_basic.tf.erb b/mmv1/templates/terraform/examples/dataproc_metastore_service_basic.tf.erb index a95e7607e470..368e76e15bd1 100644 --- a/mmv1/templates/terraform/examples/dataproc_metastore_service_basic.tf.erb +++ b/mmv1/templates/terraform/examples/dataproc_metastore_service_basic.tf.erb @@ -12,4 +12,8 @@ resource "google_dataproc_metastore_service" "<%= ctx[:primary_resource_id] %>" hive_metastore_config { version = "2.3.6" } + + labels = { + env = "test" + } } \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/gkehub_membership_basic.tf.erb b/mmv1/templates/terraform/examples/gkehub_membership_basic.tf.erb index 0cd1916c20eb..382cce899950 100644 --- a/mmv1/templates/terraform/examples/gkehub_membership_basic.tf.erb +++ b/mmv1/templates/terraform/examples/gkehub_membership_basic.tf.erb @@ -11,4 +11,8 @@ resource "google_gke_hub_membership" "membership" { resource_link = "//container.googleapis.com/${google_container_cluster.primary.id}" } } + + labels = { + env = "test" + } } diff --git a/mmv1/templates/terraform/examples/memcache_instance_basic.tf.erb b/mmv1/templates/terraform/examples/memcache_instance_basic.tf.erb index 0ad8d19378fd..2744c21f85b4 100644 --- a/mmv1/templates/terraform/examples/memcache_instance_basic.tf.erb +++ b/mmv1/templates/terraform/examples/memcache_instance_basic.tf.erb @@ -28,6 +28,10 @@ resource "google_memcache_instance" "<%= ctx[:primary_resource_id] %>" { name = "<%= ctx[:vars]["instance_name"] %>" authorized_network = google_service_networking_connection.private_service_connection.network + labels = { + env = "test" + } + node_config { cpu_count = 1 memory_size_mb = 1024 diff --git a/mmv1/templates/terraform/examples/network_management_connectivity_test_instances.tf.erb b/mmv1/templates/terraform/examples/network_management_connectivity_test_instances.tf.erb index 09a5dc0f7c6a..190c4fc40b1e 100644 --- a/mmv1/templates/terraform/examples/network_management_connectivity_test_instances.tf.erb +++ b/mmv1/templates/terraform/examples/network_management_connectivity_test_instances.tf.erb @@ -10,6 +10,9 @@ resource "google_network_management_connectivity_test" "<%= ctx[:primary_resourc } protocol = "TCP" + labels = { + env = "test" + } } resource "google_compute_instance" "source" { diff --git a/mmv1/templates/terraform/examples/only_external_vpn_gateway_full.tf.erb b/mmv1/templates/terraform/examples/only_external_vpn_gateway_full.tf.erb index 6fc73528fdcb..08bde7a9dab8 100644 --- a/mmv1/templates/terraform/examples/only_external_vpn_gateway_full.tf.erb +++ b/mmv1/templates/terraform/examples/only_external_vpn_gateway_full.tf.erb @@ -8,6 +8,5 @@ resource "google_compute_external_vpn_gateway" "<%= ctx[:primary_resource_id] %> } labels = { key = "value" - otherkey = "" } } diff --git a/mmv1/templates/terraform/examples/vertex_ai_dataset.tf.erb b/mmv1/templates/terraform/examples/vertex_ai_dataset.tf.erb index e5a5828cf0a2..17b7440b4288 100644 --- a/mmv1/templates/terraform/examples/vertex_ai_dataset.tf.erb +++ b/mmv1/templates/terraform/examples/vertex_ai_dataset.tf.erb @@ -2,4 +2,8 @@ resource "google_vertex_ai_dataset" "dataset" { display_name = "<%= ctx[:vars]['display_name'] %>" metadata_schema_uri = "gs://google-cloud-aiplatform/schema/dataset/metadata/image_1.0.0.yaml" region = "us-central1" + + labels = { + env = "test" + } } diff --git a/mmv1/templates/terraform/examples/workflow_basic.tf.erb b/mmv1/templates/terraform/examples/workflow_basic.tf.erb index 3369b4985048..1ec0cc3b67ca 100644 --- a/mmv1/templates/terraform/examples/workflow_basic.tf.erb +++ b/mmv1/templates/terraform/examples/workflow_basic.tf.erb @@ -8,6 +8,9 @@ resource "google_workflows_workflow" "<%= ctx[:primary_resource_id] %>" { region = "us-central1" description = "Magic" service_account = google_service_account.test_account.id + labels = { + env = "test" + } source_contents = <<-EOF # This is a sample workflow. You can replace it with your source code. # diff --git a/mmv1/templates/terraform/examples/workstation_config_basic.tf.erb b/mmv1/templates/terraform/examples/workstation_config_basic.tf.erb index 987413cb6199..60e2dc5ce0d9 100644 --- a/mmv1/templates/terraform/examples/workstation_config_basic.tf.erb +++ b/mmv1/templates/terraform/examples/workstation_config_basic.tf.erb @@ -41,6 +41,10 @@ resource "google_workstations_workstation_config" "<%= ctx[:primary_resource_id] label-one = "value-one" } + labels = { + "label" = "key" + } + host { gce_instance { machine_type = "e2-standard-4" diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_snapshot_test.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_snapshot_test.go index 97c0c1111646..2706ad32c8f2 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_snapshot_test.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_snapshot_test.go @@ -21,7 +21,7 @@ func TestAccSnapshotDatasource_name(t *testing.T) { acctest.CheckDataSourceStateMatchesResourceStateWithIgnores( "data.google_compute_snapshot.default", "google_compute_snapshot.default", - map[string]struct{}{"zone": {}}, + map[string]struct{}{"zone": {}, "labels.%": {}, "terraform_labels.%": {}}, ), ), }, @@ -42,7 +42,7 @@ func TestAccSnapshotDatasource_filter(t *testing.T) { acctest.CheckDataSourceStateMatchesResourceStateWithIgnores( "data.google_compute_snapshot.default", "google_compute_snapshot.c", - map[string]struct{}{"zone": {}}, + map[string]struct{}{"zone": {}, "labels.%": {}, "terraform_labels.%": {}}, ), ), }, @@ -63,7 +63,7 @@ func TestAccSnapshotDatasource_filterMostRecent(t *testing.T) { acctest.CheckDataSourceStateMatchesResourceStateWithIgnores( "data.google_compute_snapshot.default", "google_compute_snapshot.c", - map[string]struct{}{"zone": {}}, + map[string]struct{}{"zone": {}, "labels.%": {}, "terraform_labels.%": {}}, ), ), }, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_disk_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_disk_test.go.erb index fb144f76c5bf..bfa49ae22ba2 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_disk_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_disk_test.go.erb @@ -343,6 +343,7 @@ func TestAccComputeDisk_update(t *testing.T) { ResourceName: "google_compute_disk.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccComputeDisk_updated(diskName), @@ -351,6 +352,7 @@ func TestAccComputeDisk_update(t *testing.T) { ResourceName: "google_compute_disk.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -820,6 +822,7 @@ func TestAccComputeDisk_cloneDisk(t *testing.T) { ResourceName: "google_compute_disk.disk-clone", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -841,6 +844,7 @@ func TestAccComputeDisk_featuresUpdated(t *testing.T) { ResourceName: "google_compute_disk.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccComputeDisk_featuresUpdated(diskName), @@ -849,6 +853,7 @@ func TestAccComputeDisk_featuresUpdated(t *testing.T) { ResourceName: "google_compute_disk.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_external_vpn_gateway_test.go b/mmv1/third_party/terraform/services/compute/resource_compute_external_vpn_gateway_test.go index 5f34bac1a1d4..808c39b5c08d 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_external_vpn_gateway_test.go +++ b/mmv1/third_party/terraform/services/compute/resource_compute_external_vpn_gateway_test.go @@ -26,9 +26,10 @@ func TestAccComputeExternalVPNGateway_updateLabels(t *testing.T) { ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccComputeExternalVPNGateway_updateLabels(rnd, "test-updated", "test-updated"), @@ -38,9 +39,10 @@ func TestAccComputeExternalVPNGateway_updateLabels(t *testing.T) { ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_image_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_image_test.go.erb index 1bc622d85561..c75321a445c8 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_image_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_image_test.go.erb @@ -34,6 +34,7 @@ func TestAccComputeImage_withLicense(t *testing.T) { ResourceName: "google_compute_image.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -57,7 +58,6 @@ func TestAccComputeImage_update(t *testing.T) { testAccCheckComputeImageExists( t, "google_compute_image.foobar", &image), testAccCheckComputeImageContainsLabel(&image, "my-label", "my-label-value"), - testAccCheckComputeImageContainsLabel(&image, "empty-label", ""), ), }, { @@ -74,7 +74,7 @@ func TestAccComputeImage_update(t *testing.T) { ResourceName: "google_compute_image.foobar", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"raw_disk"}, + ImportStateVerifyIgnore: []string{"raw_disk", "labels", "terraform_labels"}, }, }, }) @@ -370,7 +370,6 @@ resource "google_compute_image" "foobar" { } labels = { my-label = "my-label-value" - empty-label = "" } } `, name) @@ -396,7 +395,6 @@ resource "google_compute_image" "foobar" { labels = { my-label = "my-label-value" - empty-label = "" } licenses = [ "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/licenses/debian-11-bullseye", diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.erb index 3c9dc02c177f..eabe9c303cb4 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.erb @@ -1732,7 +1732,6 @@ resource "google_compute_image" "foobar" { } labels = { my-label = "my-label-value" - empty-label = "" } timeouts { create = "5m" diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_disk_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_region_disk_test.go.erb index 56b630b12777..f59bb99bcd46 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_disk_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_disk_test.go.erb @@ -44,6 +44,7 @@ func TestAccComputeRegionDisk_basic(t *testing.T) { ResourceName: "google_compute_region_disk.regiondisk", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccComputeRegionDisk_basic(diskName, "name"), @@ -56,6 +57,7 @@ func TestAccComputeRegionDisk_basic(t *testing.T) { ResourceName: "google_compute_region_disk.regiondisk", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -84,6 +86,7 @@ func TestAccComputeRegionDisk_basicUpdate(t *testing.T) { ResourceName: "google_compute_region_disk.regiondisk", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccComputeRegionDisk_basicUpdated(diskName, "self_link"), @@ -100,6 +103,7 @@ func TestAccComputeRegionDisk_basicUpdate(t *testing.T) { ResourceName: "google_compute_region_disk.regiondisk", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.erb index 1f05349a2411..f53fdba3c3c6 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.erb @@ -1657,7 +1657,6 @@ resource "google_compute_image" "foobar" { } labels = { my-label = "my-label-value" - empty-label = "" } timeouts { create = "5m" diff --git a/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflowcx_intent_test.go b/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflowcx_intent_test.go index eba882c85830..e19b497bc825 100644 --- a/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflowcx_intent_test.go +++ b/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflowcx_intent_test.go @@ -25,17 +25,19 @@ func TestAccDialogflowCXIntent_update(t *testing.T) { Config: testAccDialogflowCXIntent_basic(context), }, { - ResourceName: "google_dialogflow_cx_intent.my_intent", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_dialogflow_cx_intent.my_intent", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccDialogflowCXIntent_full(context), }, { - ResourceName: "google_dialogflow_cx_intent.my_intent", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_dialogflow_cx_intent.my_intent", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/dns/resource_dns_managed_zone_test.go.erb b/mmv1/third_party/terraform/services/dns/resource_dns_managed_zone_test.go.erb index 5b6fdd6f76ba..a964f5a33b37 100644 --- a/mmv1/third_party/terraform/services/dns/resource_dns_managed_zone_test.go.erb +++ b/mmv1/third_party/terraform/services/dns/resource_dns_managed_zone_test.go.erb @@ -32,6 +32,7 @@ func TestAccDNSManagedZone_update(t *testing.T) { ResourceName: "google_dns_managed_zone.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccDnsManagedZone_basic(zoneSuffix, "description2", map[string]string{"foo": "bar"}), @@ -40,6 +41,7 @@ func TestAccDNSManagedZone_update(t *testing.T) { ResourceName: "google_dns_managed_zone.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -174,6 +176,7 @@ func TestAccDNSManagedZone_cloudLoggingConfigUpdate(t *testing.T) { ResourceName: "google_dns_managed_zone.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccDnsManagedZone_cloudLoggingConfig_update(zoneSuffix, true), @@ -182,6 +185,7 @@ func TestAccDNSManagedZone_cloudLoggingConfigUpdate(t *testing.T) { ResourceName: "google_dns_managed_zone.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccDnsManagedZone_cloudLoggingConfig_update(zoneSuffix, false), @@ -190,6 +194,7 @@ func TestAccDNSManagedZone_cloudLoggingConfigUpdate(t *testing.T) { ResourceName: "google_dns_managed_zone.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/filestore/resource_filestore_backup_test.go b/mmv1/third_party/terraform/services/filestore/resource_filestore_backup_test.go index fc024f291721..768b61b89f8f 100644 --- a/mmv1/third_party/terraform/services/filestore/resource_filestore_backup_test.go +++ b/mmv1/third_party/terraform/services/filestore/resource_filestore_backup_test.go @@ -35,7 +35,7 @@ func TestAccFilestoreBackup_update(t *testing.T) { ResourceName: "google_filestore_backup.backup", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"labels", "description", "location"}, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels", "description", "location"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/filestore/resource_filestore_instance_test.go b/mmv1/third_party/terraform/services/filestore/resource_filestore_instance_test.go index 96d44c1c8244..6f52889d72ae 100644 --- a/mmv1/third_party/terraform/services/filestore/resource_filestore_instance_test.go +++ b/mmv1/third_party/terraform/services/filestore/resource_filestore_instance_test.go @@ -56,7 +56,7 @@ func TestAccFilestoreInstance_update(t *testing.T) { ResourceName: "google_filestore_instance.instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"zone", "location"}, + ImportStateVerifyIgnore: []string{"zone", "location", "labels", "terraform_labels"}, }, { Config: testAccFilestoreInstance_update2(name), diff --git a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_membership_binding_test.go b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_membership_binding_test.go index 5834df3cb576..b800f61a99bc 100644 --- a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_membership_binding_test.go +++ b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_membership_binding_test.go @@ -29,7 +29,7 @@ func TestAccGKEHub2MembershipBinding_gkehubMembershipBindingBasicExample_update( ResourceName: "google_gke_hub_membership_binding.example", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"membership_binding_id", "scope", "membership_id", "location"}, + ImportStateVerifyIgnore: []string{"membership_binding_id", "scope", "membership_id", "location", "labels", "terraform_labels"}, }, { Config: testAccGKEHub2MembershipBinding_gkehubMembershipBindingBasicExample_update(context), @@ -38,7 +38,7 @@ func TestAccGKEHub2MembershipBinding_gkehubMembershipBindingBasicExample_update( ResourceName: "google_gke_hub_membership_binding.example", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"membership_binding_id", "scope", "membership_id", "location"}, + ImportStateVerifyIgnore: []string{"membership_binding_id", "scope", "membership_id", "location", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_namespace_test.go b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_namespace_test.go index 5dcc01cd2b83..a80cb1393807 100644 --- a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_namespace_test.go +++ b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_namespace_test.go @@ -28,7 +28,7 @@ func TestAccGKEHub2Namespace_gkehubNamespaceBasicExample_update(t *testing.T) { ResourceName: "google_gke_hub_namespace.namespace", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"scope_namespace_id", "scope", "scope_id", "scope"}, + ImportStateVerifyIgnore: []string{"scope_namespace_id", "scope", "scope_id", "scope", "labels", "terraform_labels"}, }, { Config: testAccGKEHub2Namespace_gkehubNamespaceBasicExample_update(context), @@ -37,7 +37,7 @@ func TestAccGKEHub2Namespace_gkehubNamespaceBasicExample_update(t *testing.T) { ResourceName: "google_gke_hub_namespace.namespace", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"scope_namespace_id", "scope", "scope_id", "scope"}, + ImportStateVerifyIgnore: []string{"scope_namespace_id", "scope", "scope_id", "scope", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_scope_rbac_role_binding_test.go b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_scope_rbac_role_binding_test.go index a1f9e6f5742e..5756e6c2a8b3 100644 --- a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_scope_rbac_role_binding_test.go +++ b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_scope_rbac_role_binding_test.go @@ -28,7 +28,7 @@ func TestAccGKEHub2ScopeRBACRoleBinding_gkehubScopeRbacRoleBindingBasicExample_u ResourceName: "google_gke_hub_scope_rbac_role_binding.scoperbacrolebinding", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"scope_rbac_role_binding_id", "scope_id"}, + ImportStateVerifyIgnore: []string{"scope_rbac_role_binding_id", "scope_id", "labels", "terraform_labels"}, }, { Config: testAccGKEHub2ScopeRBACRoleBinding_gkehubScopeRbacRoleBindingBasicExample_update(context), @@ -37,7 +37,7 @@ func TestAccGKEHub2ScopeRBACRoleBinding_gkehubScopeRbacRoleBindingBasicExample_u ResourceName: "google_gke_hub_scope_rbac_role_binding.scoperbacrolebinding", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"scope_rbac_role_binding_id", "scope_id"}, + ImportStateVerifyIgnore: []string{"scope_rbac_role_binding_id", "scope_id", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_scope_test.go b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_scope_test.go index 0c3c84e598ab..967fe08c4bc2 100644 --- a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_scope_test.go +++ b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_scope_test.go @@ -28,7 +28,7 @@ func TestAccGKEHub2Scope_gkehubScopeBasicExample_update(t *testing.T) { ResourceName: "google_gke_hub_scope.scope", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"scope_id"}, + ImportStateVerifyIgnore: []string{"scope_id", "labels", "terraform_labels"}, }, { Config: testAccGKEHub2Scope_gkehubScopeBasicExample_update(context), @@ -37,7 +37,7 @@ func TestAccGKEHub2Scope_gkehubScopeBasicExample_update(t *testing.T) { ResourceName: "google_gke_hub_scope.scope", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"scope_id"}, + ImportStateVerifyIgnore: []string{"scope_id", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/kms/resource_kms_crypto_key_test.go b/mmv1/third_party/terraform/services/kms/resource_kms_crypto_key_test.go index 6f84c616dc29..d067dbcdb9af 100644 --- a/mmv1/third_party/terraform/services/kms/resource_kms_crypto_key_test.go +++ b/mmv1/third_party/terraform/services/kms/resource_kms_crypto_key_test.go @@ -152,16 +152,18 @@ func TestAccKmsCryptoKey_basic(t *testing.T) { Config: testGoogleKmsCryptoKey_basic(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName), }, { - ResourceName: "google_kms_crypto_key.crypto_key", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_kms_crypto_key.crypto_key", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, // Test importing with a short id { - ResourceName: "google_kms_crypto_key.crypto_key", - ImportState: true, - ImportStateId: fmt.Sprintf("%s/%s/%s/%s", projectId, location, keyRingName, cryptoKeyName), - ImportStateVerify: true, + ResourceName: "google_kms_crypto_key.crypto_key", + ImportState: true, + ImportStateId: fmt.Sprintf("%s/%s/%s/%s", projectId, location, keyRingName, cryptoKeyName), + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, // Use a separate TestStep rather than a CheckDestroy because we need the project to still exist. { @@ -294,9 +296,10 @@ func TestAccKmsCryptoKey_destroyDuration(t *testing.T) { Config: testGoogleKmsCryptoKey_destroyDuration(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName), }, { - ResourceName: "google_kms_crypto_key.crypto_key", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_kms_crypto_key.crypto_key", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, // Use a separate TestStep rather than a CheckDestroy because we need the project to still exist. { @@ -332,7 +335,7 @@ func TestAccKmsCryptoKey_importOnly(t *testing.T) { ResourceName: "google_kms_crypto_key.crypto_key", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"skip_initial_version_creation"}, + ImportStateVerifyIgnore: []string{"skip_initial_version_creation", "labels", "terraform_labels"}, }, // Use a separate TestStep rather than a CheckDestroy because we need the project to still exist. { @@ -426,9 +429,10 @@ func TestAccKmsCryptoKeyVersion_basic(t *testing.T) { Config: testGoogleKmsCryptoKeyVersion_basic(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName), }, { - ResourceName: "google_kms_crypto_key_version.crypto_key_version", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_kms_crypto_key_version.crypto_key_version", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testGoogleKmsCryptoKeyVersion_removed(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName), @@ -454,9 +458,10 @@ func TestAccKmsCryptoKeyVersion_skipInitialVersion(t *testing.T) { Config: testGoogleKmsCryptoKeyVersion_skipInitialVersion(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName), }, { - ResourceName: "google_kms_crypto_key_version.crypto_key_version", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_kms_crypto_key_version.crypto_key_version", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -480,17 +485,19 @@ func TestAccKmsCryptoKeyVersion_patch(t *testing.T) { Config: testGoogleKmsCryptoKeyVersion_patchInitialize(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName), }, { - ResourceName: "google_kms_crypto_key_version.crypto_key_version", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_kms_crypto_key_version.crypto_key_version", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testGoogleKmsCryptoKeyVersion_patch("true", projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName, state), }, { - ResourceName: "google_kms_crypto_key_version.crypto_key_version", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_kms_crypto_key_version.crypto_key_version", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testGoogleKmsCryptoKeyVersion_patch("false", projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName, state), diff --git a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_authorization_policy_test.go.erb b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_authorization_policy_test.go.erb index b4993f5084d8..2d1c4af67055 100644 --- a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_authorization_policy_test.go.erb +++ b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_authorization_policy_test.go.erb @@ -27,6 +27,7 @@ func TestAccNetworkSecurityAuthorizationPolicy_update(t *testing.T) { ResourceName: "google_network_security_authorization_policy.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkSecurityAuthorizationPolicy_update(authorizationPolicyName), @@ -35,6 +36,7 @@ func TestAccNetworkSecurityAuthorizationPolicy_update(t *testing.T) { ResourceName: "google_network_security_authorization_policy.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_client_tls_policy_test.go.erb b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_client_tls_policy_test.go.erb index 67de18513d1d..d91d8e030965 100644 --- a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_client_tls_policy_test.go.erb +++ b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_client_tls_policy_test.go.erb @@ -21,12 +21,13 @@ func TestAccNetworkSecurityClientTlsPolicy_update(t *testing.T) { CheckDestroy: testAccCheckNetworkSecurityClientTlsPolicyDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccNetworkSecurityClientTlsPolicy_basic(clientTlsPolicyName), + Config: testAccNetworkSecurityClientTlsPolicy_basic(clientTlsPolicyName), }, { ResourceName: "google_network_security_client_tls_policy.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkSecurityClientTlsPolicy_update(clientTlsPolicyName), @@ -35,6 +36,7 @@ func TestAccNetworkSecurityClientTlsPolicy_update(t *testing.T) { ResourceName: "google_network_security_client_tls_policy.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_server_tls_policy_test.go.erb b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_server_tls_policy_test.go.erb index 00f7755bf324..f1000f4665de 100644 --- a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_server_tls_policy_test.go.erb +++ b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_server_tls_policy_test.go.erb @@ -27,6 +27,7 @@ func TestAccNetworkSecurityServerTlsPolicy_update(t *testing.T) { ResourceName: "google_network_security_server_tls_policy.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkSecurityServerTlsPolicy_update(serverTlsPolicyName), @@ -35,6 +36,7 @@ func TestAccNetworkSecurityServerTlsPolicy_update(t *testing.T) { ResourceName: "google_network_security_server_tls_policy.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networkservices/resource_network_services_edge_cache_keyset_test.go b/mmv1/third_party/terraform/services/networkservices/resource_network_services_edge_cache_keyset_test.go index f12e0cec4b04..56b1cd8bfcd3 100644 --- a/mmv1/third_party/terraform/services/networkservices/resource_network_services_edge_cache_keyset_test.go +++ b/mmv1/third_party/terraform/services/networkservices/resource_network_services_edge_cache_keyset_test.go @@ -26,7 +26,7 @@ func TestAccNetworkServicesEdgeCacheKeyset_update(t *testing.T) { ResourceName: "google_network_services_edge_cache_keyset.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name"}, + ImportStateVerifyIgnore: []string{"name", "labels", "terraform_labels"}, }, { Config: testAccNetworkServicesEdgeCacheKeyset_update(context), @@ -35,7 +35,7 @@ func TestAccNetworkServicesEdgeCacheKeyset_update(t *testing.T) { ResourceName: "google_network_services_edge_cache_keyset.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name"}, + ImportStateVerifyIgnore: []string{"name", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networkservices/resource_network_services_edge_cache_origin_test.go b/mmv1/third_party/terraform/services/networkservices/resource_network_services_edge_cache_origin_test.go index 9e68d59853d6..6ad86ecb883f 100644 --- a/mmv1/third_party/terraform/services/networkservices/resource_network_services_edge_cache_origin_test.go +++ b/mmv1/third_party/terraform/services/networkservices/resource_network_services_edge_cache_origin_test.go @@ -23,7 +23,7 @@ func TestAccNetworkServicesEdgeCacheOrigin_updateAndImport(t *testing.T) { ResourceName: "google_network_services_edge_cache_origin.instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name"}, + ImportStateVerifyIgnore: []string{"name", "labels", "terraform_labels"}, }, { Config: testAccNetworkServicesEdgeCacheOrigin_update_1(name), @@ -32,7 +32,7 @@ func TestAccNetworkServicesEdgeCacheOrigin_updateAndImport(t *testing.T) { ResourceName: "google_network_services_edge_cache_origin.instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name"}, + ImportStateVerifyIgnore: []string{"name", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networkservices/resource_network_services_endpoint_policy_test.go.erb b/mmv1/third_party/terraform/services/networkservices/resource_network_services_endpoint_policy_test.go.erb index 5ca9e8290821..3369b28dc114 100644 --- a/mmv1/third_party/terraform/services/networkservices/resource_network_services_endpoint_policy_test.go.erb +++ b/mmv1/third_party/terraform/services/networkservices/resource_network_services_endpoint_policy_test.go.erb @@ -27,6 +27,7 @@ func TestAccNetworkServicesEndpointPolicy_update(t *testing.T) { ResourceName: "google_network_services_endpoint_policy.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkServicesEndpointPolicy_update(endpointPolicyName), @@ -35,6 +36,7 @@ func TestAccNetworkServicesEndpointPolicy_update(t *testing.T) { ResourceName: "google_network_services_endpoint_policy.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networkservices/resource_network_services_gateway_test.go b/mmv1/third_party/terraform/services/networkservices/resource_network_services_gateway_test.go index 9aae107edfc1..d572021996d1 100644 --- a/mmv1/third_party/terraform/services/networkservices/resource_network_services_gateway_test.go +++ b/mmv1/third_party/terraform/services/networkservices/resource_network_services_gateway_test.go @@ -23,17 +23,19 @@ func TestAccNetworkServicesGateway_update(t *testing.T) { Config: testAccNetworkServicesGateway_basic(gatewayName), }, { - ResourceName: "google_network_services_gateway.foobar", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_network_services_gateway.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkServicesGateway_update(gatewayName), }, { - ResourceName: "google_network_services_gateway.foobar", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_network_services_gateway.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networkservices/resource_network_services_grpc_route_test.go.erb b/mmv1/third_party/terraform/services/networkservices/resource_network_services_grpc_route_test.go.erb index 3220d937b433..e2a10dd024e7 100644 --- a/mmv1/third_party/terraform/services/networkservices/resource_network_services_grpc_route_test.go.erb +++ b/mmv1/third_party/terraform/services/networkservices/resource_network_services_grpc_route_test.go.erb @@ -27,6 +27,7 @@ func TestAccNetworkServicesGrpcRoute_update(t *testing.T) { ResourceName: "google_network_services_grpc_route.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkServicesGrpcRoute_update(grpcRouteName), @@ -35,6 +36,7 @@ func TestAccNetworkServicesGrpcRoute_update(t *testing.T) { ResourceName: "google_network_services_grpc_route.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networkservices/resource_network_services_http_route_test.go.erb b/mmv1/third_party/terraform/services/networkservices/resource_network_services_http_route_test.go.erb index f94075ec67ee..2f0c54530c64 100644 --- a/mmv1/third_party/terraform/services/networkservices/resource_network_services_http_route_test.go.erb +++ b/mmv1/third_party/terraform/services/networkservices/resource_network_services_http_route_test.go.erb @@ -27,6 +27,7 @@ func TestAccNetworkServicesHttpRoute_update(t *testing.T) { ResourceName: "google_network_services_http_route.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkServicesHttpRoute_update(httpRouteName), @@ -35,6 +36,7 @@ func TestAccNetworkServicesHttpRoute_update(t *testing.T) { ResourceName: "google_network_services_http_route.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networkservices/resource_network_services_mesh_test.go.erb b/mmv1/third_party/terraform/services/networkservices/resource_network_services_mesh_test.go.erb index 240f5b94887e..87451e4ee1a0 100644 --- a/mmv1/third_party/terraform/services/networkservices/resource_network_services_mesh_test.go.erb +++ b/mmv1/third_party/terraform/services/networkservices/resource_network_services_mesh_test.go.erb @@ -27,6 +27,7 @@ func TestAccNetworkServicesMesh_update(t *testing.T) { ResourceName: "google_network_services_mesh.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkServicesMesh_update(meshName), @@ -35,6 +36,7 @@ func TestAccNetworkServicesMesh_update(t *testing.T) { ResourceName: "google_network_services_mesh.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networkservices/resource_network_services_tcp_route_test.go.erb b/mmv1/third_party/terraform/services/networkservices/resource_network_services_tcp_route_test.go.erb index 0b7aa52cfc9e..27f545faed8a 100644 --- a/mmv1/third_party/terraform/services/networkservices/resource_network_services_tcp_route_test.go.erb +++ b/mmv1/third_party/terraform/services/networkservices/resource_network_services_tcp_route_test.go.erb @@ -23,12 +23,13 @@ func TestAccNetworkServicesTcpRoute_update(t *testing.T) { CheckDestroy: testAccCheckNetworkServicesTcpRouteDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccNetworkServicesTcpRoute_basic(tcpServiceName, tcpHealthCheckName, tcpRouteName), + Config: testAccNetworkServicesTcpRoute_basic(tcpServiceName, tcpHealthCheckName, tcpRouteName), }, { ResourceName: "google_network_services_tcp_route.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkServicesTcpRoute_update(tcpServiceName, tcpHealthCheckName, tcpRouteName), @@ -37,6 +38,7 @@ func TestAccNetworkServicesTcpRoute_update(t *testing.T) { ResourceName: "google_network_services_tcp_route.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/privateca/resource_privateca_certificate_test.go b/mmv1/third_party/terraform/services/privateca/resource_privateca_certificate_test.go index 0e955d5ed745..e6c0c5f76c36 100644 --- a/mmv1/third_party/terraform/services/privateca/resource_privateca_certificate_test.go +++ b/mmv1/third_party/terraform/services/privateca/resource_privateca_certificate_test.go @@ -36,7 +36,7 @@ func TestAccPrivatecaCertificate_privatecaCertificateUpdate(t *testing.T) { ResourceName: "google_privateca_certificate.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"pool", "name", "location", "certificate_authority"}, + ImportStateVerifyIgnore: []string{"pool", "name", "location", "certificate_authority", "labels", "terraform_labels"}, }, { Config: testAccPrivatecaCertificate_privatecaCertificateStart(context), 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 5ac29b2b44b3..19f15a66fd45 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 @@ -51,10 +51,11 @@ func TestAccPubsubSubscription_basic(t *testing.T) { Config: testAccPubsubSubscription_basic(topic, subscription, "bar", 20, false), }, { - ResourceName: "google_pubsub_subscription.foo", - ImportStateId: subscription, - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_pubsub_subscription.foo", + ImportStateId: subscription, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -75,19 +76,21 @@ func TestAccPubsubSubscription_update(t *testing.T) { Config: testAccPubsubSubscription_basic(topic, subscriptionShort, "bar", 20, false), }, { - ResourceName: "google_pubsub_subscription.foo", - ImportStateId: subscriptionShort, - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_pubsub_subscription.foo", + ImportStateId: subscriptionShort, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccPubsubSubscription_basic(topic, subscriptionShort, "baz", 30, true), }, { - ResourceName: "google_pubsub_subscription.foo", - ImportStateId: subscriptionShort, - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_pubsub_subscription.foo", + ImportStateId: subscriptionShort, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) 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 059eee101f5f..41d8e7a58182 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 @@ -22,19 +22,21 @@ func TestAccPubsubTopic_update(t *testing.T) { Config: testAccPubsubTopic_update(topic, "foo", "bar"), }, { - ResourceName: "google_pubsub_topic.foo", - ImportStateId: topic, - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_pubsub_topic.foo", + ImportStateId: topic, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccPubsubTopic_updateWithRegion(topic, "wibble", "wobble", "us-central1"), }, { - ResourceName: "google_pubsub_topic.foo", - ImportStateId: topic, - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_pubsub_topic.foo", + ImportStateId: topic, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/redis/resource_redis_instance_test.go b/mmv1/third_party/terraform/services/redis/resource_redis_instance_test.go index f5f4e9fe8821..dd5579c54cf2 100644 --- a/mmv1/third_party/terraform/services/redis/resource_redis_instance_test.go +++ b/mmv1/third_party/terraform/services/redis/resource_redis_instance_test.go @@ -23,17 +23,19 @@ func TestAccRedisInstance_update(t *testing.T) { Config: testAccRedisInstance_update(name, true), }, { - ResourceName: "google_redis_instance.test", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_redis_instance.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccRedisInstance_update2(name, true), }, { - ResourceName: "google_redis_instance.test", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_redis_instance.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccRedisInstance_update2(name, false), diff --git a/mmv1/third_party/terraform/services/servicedirectory/resource_service_directory_namespace_test.go.erb b/mmv1/third_party/terraform/services/servicedirectory/resource_service_directory_namespace_test.go.erb index d056b18d33e7..5bf8e8868df9 100644 --- a/mmv1/third_party/terraform/services/servicedirectory/resource_service_directory_namespace_test.go.erb +++ b/mmv1/third_party/terraform/services/servicedirectory/resource_service_directory_namespace_test.go.erb @@ -53,6 +53,7 @@ func TestAccServiceDirectoryNamespace_serviceDirectoryNamespaceUpdateExample(t * ResourceName: "google_service_directory_namespace.example", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/spanner/resource_spanner_instance_test.go b/mmv1/third_party/terraform/services/spanner/resource_spanner_instance_test.go index 53a531ed99e4..9d753eaf7e79 100644 --- a/mmv1/third_party/terraform/services/spanner/resource_spanner_instance_test.go +++ b/mmv1/third_party/terraform/services/spanner/resource_spanner_instance_test.go @@ -95,17 +95,19 @@ func TestAccSpannerInstance_update(t *testing.T) { Config: testAccSpannerInstance_update(dName1, 1, false), }, { - ResourceName: "google_spanner_instance.updater", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_spanner_instance.updater", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccSpannerInstance_update(dName2, 2, true), }, { - ResourceName: "google_spanner_instance.updater", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_spanner_instance.updater", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/vertexai/data_source_vertex_ai_index_test.go b/mmv1/third_party/terraform/services/vertexai/data_source_vertex_ai_index_test.go index a1e4b56bfd6e..5813d9adfc7b 100644 --- a/mmv1/third_party/terraform/services/vertexai/data_source_vertex_ai_index_test.go +++ b/mmv1/third_party/terraform/services/vertexai/data_source_vertex_ai_index_test.go @@ -31,6 +31,8 @@ func TestAccDataSourceVertexAIIndex_basic(t *testing.T) { map[string]struct{}{ "metadata.0.contents_delta_uri": {}, "metadata.0.is_complete_overwrite": {}, + "labels.%": {}, + "terraform_labels.%": {}, }, ), ), diff --git a/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_endpoint_test.go b/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_endpoint_test.go index 2cde7c0a6862..e781551aa541 100644 --- a/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_endpoint_test.go +++ b/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_endpoint_test.go @@ -34,7 +34,7 @@ func TestAccVertexAIEndpoint_vertexAiEndpointNetwork(t *testing.T) { ResourceName: "google_vertex_ai_endpoint.endpoint", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "location", "region"}, + ImportStateVerifyIgnore: []string{"etag", "location", "region", "labels", "terraform_labels"}, }, { Config: testAccVertexAIEndpoint_vertexAiEndpointNetworkUpdate(context), @@ -43,7 +43,7 @@ func TestAccVertexAIEndpoint_vertexAiEndpointNetwork(t *testing.T) { ResourceName: "google_vertex_ai_endpoint.endpoint", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "location", "region"}, + ImportStateVerifyIgnore: []string{"etag", "location", "region", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_index_test.go b/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_index_test.go index 09964869d97a..bd8f8d7e005c 100644 --- a/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_index_test.go +++ b/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_index_test.go @@ -34,7 +34,7 @@ func TestAccVertexAIIndex_updated(t *testing.T) { ResourceName: "google_vertex_ai_index.index", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "region", "metadata.0.contents_delta_uri", "metadata.0.is_complete_overwrite"}, + ImportStateVerifyIgnore: []string{"etag", "region", "metadata.0.contents_delta_uri", "metadata.0.is_complete_overwrite", "labels", "terraform_labels"}, }, { Config: testAccVertexAIIndex_updated(context), @@ -43,7 +43,7 @@ func TestAccVertexAIIndex_updated(t *testing.T) { ResourceName: "google_vertex_ai_index.index", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "region", "metadata.0.contents_delta_uri", "metadata.0.is_complete_overwrite"}, + ImportStateVerifyIgnore: []string{"etag", "region", "metadata.0.contents_delta_uri", "metadata.0.is_complete_overwrite", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_tensorboard_test.go b/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_tensorboard_test.go index d620fdfdeee7..a684ba95b623 100644 --- a/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_tensorboard_test.go +++ b/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_tensorboard_test.go @@ -25,7 +25,7 @@ func TestAccVertexAITensorboard_Update(t *testing.T) { ResourceName: "google_vertex_ai_tensorboard.tensorboard", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"region", "project"}, + ImportStateVerifyIgnore: []string{"region", "project", "labels", "terraform_labels"}, }, { Config: testAccVertexAITensorboard_Update(random_suffix+"new", random_suffix, random_suffix, random_suffix), @@ -34,7 +34,7 @@ func TestAccVertexAITensorboard_Update(t *testing.T) { ResourceName: "google_vertex_ai_tensorboard.tensorboard", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"region", "project"}, + ImportStateVerifyIgnore: []string{"region", "project", "labels", "terraform_labels"}, }, { Config: testAccVertexAITensorboard_Update(random_suffix+"new", random_suffix+"new", random_suffix, random_suffix), @@ -43,7 +43,7 @@ func TestAccVertexAITensorboard_Update(t *testing.T) { ResourceName: "google_vertex_ai_tensorboard.tensorboard", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"region", "project"}, + ImportStateVerifyIgnore: []string{"region", "project", "labels", "terraform_labels"}, }, { Config: testAccVertexAITensorboard_Update(random_suffix+"new", random_suffix+"new", random_suffix+"new", random_suffix), @@ -52,7 +52,7 @@ func TestAccVertexAITensorboard_Update(t *testing.T) { ResourceName: "google_vertex_ai_tensorboard.tensorboard", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"region", "project"}, + ImportStateVerifyIgnore: []string{"region", "project", "labels", "terraform_labels"}, }, { Config: testAccVertexAITensorboard_Update(random_suffix+"new", random_suffix+"new", random_suffix+"new", random_suffix+"new"), @@ -61,7 +61,7 @@ func TestAccVertexAITensorboard_Update(t *testing.T) { ResourceName: "google_vertex_ai_tensorboard.tensorboard", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"region", "project"}, + ImportStateVerifyIgnore: []string{"region", "project", "labels", "terraform_labels"}, }, { Config: testAccVertexAITensorboard_Update(random_suffix, random_suffix, random_suffix, random_suffix), @@ -70,7 +70,7 @@ func TestAccVertexAITensorboard_Update(t *testing.T) { ResourceName: "google_vertex_ai_tensorboard.tensorboard", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"region", "project"}, + ImportStateVerifyIgnore: []string{"region", "project", "labels", "terraform_labels"}, }, }, }) 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 4a4984fae0d1..fa858b9ba2ad 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 @@ -28,7 +28,7 @@ func TestAccWorkstationsWorkstationConfig_basic(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "labels", "terraform_labels"}, }, }, }) @@ -95,7 +95,7 @@ func TestAccWorkstationsWorkstationConfig_displayName(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "labels", "terraform_labels"}, }, { Config: testAccWorkstationsWorkstationConfig_displayName(context, "2"), @@ -104,7 +104,7 @@ func TestAccWorkstationsWorkstationConfig_displayName(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "labels", "terraform_labels"}, }, }, }) @@ -172,7 +172,7 @@ func TestAccWorkstationsWorkstationConfig_persistentDirectories(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "labels", "terraform_labels"}, }, }, }) @@ -242,7 +242,7 @@ func TestAccWorkstationsWorkstationConfig_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "annotations"}, + ImportStateVerifyIgnore: []string{"etag", "annotations", "labels", "terraform_labels"}, }, { Config: testAccWorkstationsWorkstationConfig_update(context), @@ -251,7 +251,7 @@ func TestAccWorkstationsWorkstationConfig_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "annotations"}, + ImportStateVerifyIgnore: []string{"etag", "annotations", "labels", "terraform_labels"}, }, { Config: testAccWorkstationsWorkstationConfig_workstationConfigBasicExample(context), @@ -260,7 +260,7 @@ func TestAccWorkstationsWorkstationConfig_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "annotations"}, + ImportStateVerifyIgnore: []string{"etag", "annotations", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_test.go.erb b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_test.go.erb index 9e06368ceb1a..f1de41975189 100644 --- a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_test.go.erb +++ b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_test.go.erb @@ -28,7 +28,7 @@ func TestAccWorkstationsWorkstation_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "labels", "terraform_labels"}, }, { Config: testAccWorkstationsWorkstation_modified(context), @@ -37,7 +37,7 @@ func TestAccWorkstationsWorkstation_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/tgc/tests/data/example_compute_disk.tfplan.json b/mmv1/third_party/tgc/tests/data/example_compute_disk.tfplan.json index ebc95b4dca87..e80e5b6ee646 100644 --- a/mmv1/third_party/tgc/tests/data/example_compute_disk.tfplan.json +++ b/mmv1/third_party/tgc/tests/data/example_compute_disk.tfplan.json @@ -15,6 +15,9 @@ "description": null, "disk_encryption_key": [], "disk_encryption_key_raw": null, + "effective_labels": { + "environment": "dev" + }, "image": "projects/debian-cloud/global/images/debian-8-jessie-v20170523", "labels": { "environment": "dev" @@ -24,6 +27,9 @@ "snapshot": null, "source_image_encryption_key": [], "source_snapshot_encryption_key": [], + "terraform_labels": { + "environment": "dev" + }, "timeouts": null, "type": "pd-ssd", "zone": "us-central1-a" @@ -48,6 +54,9 @@ "description": null, "disk_encryption_key": [], "disk_encryption_key_raw": null, + "effective_labels": { + "environment": "dev" + }, "image": "projects/debian-cloud/global/images/debian-8-jessie-v20170523", "labels": { "environment": "dev" @@ -57,6 +66,9 @@ "snapshot": null, "source_image_encryption_key": [], "source_snapshot_encryption_key": [], + "terraform_labels": { + "environment": "dev" + }, "timeouts": null, "type": "pd-ssd", "zone": "us-central1-a" @@ -65,6 +77,7 @@ "creation_timestamp": true, "disk_encryption_key": [], "disk_encryption_key_sha256": true, + "effective_labels": {}, "id": true, "label_fingerprint": true, "labels": {}, @@ -77,6 +90,7 @@ "source_image_id": true, "source_snapshot_encryption_key": [], "source_snapshot_id": true, + "terraform_labels": {}, "users": true } } diff --git a/mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.tfplan.json b/mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.tfplan.json index e44bdfa8c85c..bd8ebb490d6f 100644 --- a/mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.tfplan.json +++ b/mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.tfplan.json @@ -15,6 +15,9 @@ "description": null, "disk_encryption_key": [], "disk_encryption_key_raw": null, + "effective_labels": { + "environment": "dev" + }, "image": "", "labels": { "environment": "dev" @@ -24,6 +27,9 @@ "snapshot": null, "source_image_encryption_key": [], "source_snapshot_encryption_key": [], + "terraform_labels": { + "environment": "dev" + }, "timeouts": null, "type": "pd-ssd", "zone": "us-central1-a" @@ -48,6 +54,9 @@ "description": null, "disk_encryption_key": [], "disk_encryption_key_raw": null, + "effective_labels": { + "environment": "dev" + }, "image": "", "labels": { "environment": "dev" @@ -57,6 +66,9 @@ "snapshot": null, "source_image_encryption_key": [], "source_snapshot_encryption_key": [], + "terraform_labels": { + "environment": "dev" + }, "timeouts": null, "type": "pd-ssd", "zone": "us-central1-a" @@ -65,6 +77,7 @@ "creation_timestamp": true, "disk_encryption_key": [], "disk_encryption_key_sha256": true, + "effective_labels": {}, "id": true, "label_fingerprint": true, "labels": {}, @@ -77,6 +90,7 @@ "source_image_id": true, "source_snapshot_encryption_key": [], "source_snapshot_id": true, + "terraform_labels": {}, "users": true } } diff --git a/mmv1/third_party/tgc/tests/data/example_compute_snapshot.tfplan.json b/mmv1/third_party/tgc/tests/data/example_compute_snapshot.tfplan.json index 18c079b12317..4f1e403b2434 100644 --- a/mmv1/third_party/tgc/tests/data/example_compute_snapshot.tfplan.json +++ b/mmv1/third_party/tgc/tests/data/example_compute_snapshot.tfplan.json @@ -14,6 +14,7 @@ "values": { "description": null, "disk_encryption_key": [], + "effective_labels": null, "image": "projects/debian-cloud/global/images/debian-8-jessie-v20170523", "labels": null, "name": "debian-disk", @@ -22,6 +23,7 @@ "snapshot": null, "source_image_encryption_key": [], "source_snapshot_encryption_key": [], + "terraform_labels": null, "timeouts": null, "type": "pd-ssd", "zone": "us-central1-a" @@ -42,6 +44,9 @@ "schema_version": 0, "values": { "description": null, + "effective_labels": { + "test-name": "test-value" + }, "labels": { "test-name": "test-value" }, @@ -52,17 +57,22 @@ "storage_locations": [ "us-central1" ], + "terraform_labels": { + "test-name": "test-value" + }, "timeouts": null, "zone": "us-central1-a" }, "sensitive_values": { + "effective_labels": {}, "labels": {}, "licenses": [], "snapshot_encryption_key": [], "source_disk_encryption_key": [], "storage_locations": [ false - ] + ], + "terraform_labels": {} } } ] @@ -83,6 +93,7 @@ "after": { "description": null, "disk_encryption_key": [], + "effective_labels": null, "image": "projects/debian-cloud/global/images/debian-8-jessie-v20170523", "labels": null, "name": "debian-disk", @@ -91,6 +102,7 @@ "snapshot": null, "source_image_encryption_key": [], "source_snapshot_encryption_key": [], + "terraform_labels": null, "timeouts": null, "type": "pd-ssd", "zone": "us-central1-a" @@ -133,6 +145,9 @@ "before": null, "after": { "description": null, + "effective_labels": { + "test-name": "test-value" + }, "labels": { "test-name": "test-value" }, @@ -143,12 +158,16 @@ "storage_locations": [ "us-central1" ], + "terraform_labels": { + "test-name": "test-value" + }, "timeouts": null, "zone": "us-central1-a" }, "after_unknown": { "creation_timestamp": true, "disk_size_gb": true, + "effective_labels": {}, "id": true, "label_fingerprint": true, "labels": {}, @@ -161,17 +180,20 @@ "storage_bytes": true, "storage_locations": [ false - ] + ], + "terraform_labels": {} }, "before_sensitive": false, "after_sensitive": { + "effective_labels": {}, "labels": {}, "licenses": [], "snapshot_encryption_key": [], "source_disk_encryption_key": [], "storage_locations": [ false - ] + ], + "terraform_labels": {} } } } diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription.tfplan.json b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription.tfplan.json index 28b2fa772da3..16cacd39e9bb 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription.tfplan.json +++ b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription.tfplan.json @@ -14,6 +14,9 @@ "values": { "ack_deadline_seconds": 20, "dead_letter_policy": [], + "effective_labels": { + "test-label2": "test-value2" + }, "enable_message_ordering": false, "expiration_policy": [ { @@ -33,6 +36,9 @@ "minimum_backoff": "10s" } ], + "terraform_labels": { + "test-label2": "test-value2" + }, "timeouts": null, "topic": "example-pubsub-topic" } @@ -47,6 +53,9 @@ "values": { "ack_deadline_seconds": 20, "dead_letter_policy": [], + "effective_labels": { + "test-label1": "test-value1" + }, "enable_message_ordering": null, "filter": null, "labels": { @@ -63,6 +72,9 @@ ], "retain_acked_messages": null, "retry_policy": [], + "terraform_labels": { + "test-label1": "test-value1" + }, "timeouts": null, "topic": "example-pubsub-topic" } @@ -85,6 +97,9 @@ "after": { "ack_deadline_seconds": 20, "dead_letter_policy": [], + "effective_labels": { + "test-label2": "test-value2" + }, "enable_message_ordering": false, "expiration_policy": [ { @@ -104,11 +119,15 @@ "minimum_backoff": "10s" } ], + "terraform_labels": { + "test-label2": "test-value2" + }, "timeouts": null, "topic": "example-pubsub-topic" }, "after_unknown": { "dead_letter_policy": [], + "effective_labels": {}, "expiration_policy": [ {} ], @@ -121,7 +140,8 @@ { "maximum_backoff": true } - ] + ], + "terraform_labels": {} } } }, @@ -139,6 +159,9 @@ "after": { "ack_deadline_seconds": 20, "dead_letter_policy": [], + "effective_labels": { + "test-label1": "test-value1" + }, "enable_message_ordering": null, "filter": null, "labels": { @@ -155,11 +178,15 @@ ], "retain_acked_messages": null, "retry_policy": [], + "terraform_labels": { + "test-label2": "test-value2" + }, "timeouts": null, "topic": "example-pubsub-topic" }, "after_unknown": { "dead_letter_policy": [], + "effective_labels": {}, "expiration_policy": true, "id": true, "labels": {}, @@ -170,7 +197,8 @@ "oidc_token": [] } ], - "retry_policy": [] + "retry_policy": [], + "terraform_labels": {} } } } diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.tfplan.json b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.tfplan.json index 0a730e6b809e..2de05102765e 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.tfplan.json +++ b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.tfplan.json @@ -14,6 +14,9 @@ "values": { "ack_deadline_seconds": 20, "dead_letter_policy": [], + "effective_labels": { + "test-label1": "test-value1" + }, "enable_message_ordering": null, "filter": null, "labels": { @@ -30,6 +33,9 @@ ], "retain_acked_messages": null, "retry_policy": [], + "terraform_labels": { + "test-label1": "test-value1" + }, "timeouts": null, "topic": "example-pubsub-topic" }, @@ -85,6 +91,9 @@ "after": { "ack_deadline_seconds": 20, "dead_letter_policy": [], + "effective_labels": { + "test-label1": "test-value1" + }, "enable_message_ordering": null, "filter": null, "labels": { @@ -101,11 +110,15 @@ ], "retain_acked_messages": null, "retry_policy": [], + "terraform_labels": { + "test-label1": "test-value1" + }, "timeouts": null, "topic": "example-pubsub-topic" }, "after_unknown": { "dead_letter_policy": [], + "effective_labels": {}, "expiration_policy": true, "id": true, "labels": {}, @@ -115,11 +128,13 @@ "oidc_token": [] } ], - "retry_policy": [] + "retry_policy": [], + "terraform_labels": {} }, "before_sensitive": false, "after_sensitive": { "dead_letter_policy": [], + "effective_labels": {}, "expiration_policy": [], "labels": {}, "push_config": [ @@ -127,7 +142,8 @@ "oidc_token": [] } ], - "retry_policy": [] + "retry_policy": [], + "terraform_labels": {} } } }, diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.tfplan.json b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.tfplan.json index 691e23ba6c4c..292f2c542161 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.tfplan.json +++ b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.tfplan.json @@ -14,6 +14,9 @@ "values": { "ack_deadline_seconds": 20, "dead_letter_policy": [], + "effective_labels": { + "test-label1": "test-value1" + }, "enable_message_ordering": null, "filter": null, "labels": { @@ -30,6 +33,9 @@ ], "retain_acked_messages": null, "retry_policy": [], + "terraform_labels": { + "test-label1": "test-value1" + }, "timeouts": null, "topic": "example-pubsub-topic" }, @@ -80,6 +86,9 @@ "after": { "ack_deadline_seconds": 20, "dead_letter_policy": [], + "effective_labels": { + "test-label1": "test-value1" + }, "enable_message_ordering": null, "filter": null, "labels": { @@ -96,11 +105,15 @@ ], "retain_acked_messages": null, "retry_policy": [], + "terraform_labels": { + "test-label1": "test-value1" + }, "timeouts": null, "topic": "example-pubsub-topic" }, "after_unknown": { "dead_letter_policy": [], + "effective_labels": {}, "expiration_policy": true, "id": true, "labels": {}, @@ -110,11 +123,13 @@ "oidc_token": [] } ], - "retry_policy": [] + "retry_policy": [], + "terraform_labels": {} }, "before_sensitive": false, "after_sensitive": { "dead_letter_policy": [], + "effective_labels": {}, "expiration_policy": [], "labels": {}, "push_config": [ @@ -122,7 +137,8 @@ "oidc_token": [] } ], - "retry_policy": [] + "retry_policy": [], + "terraform_labels": {} } } }, diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.tfplan.json index 281258b9501e..94478b15fee2 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.tfplan.json +++ b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.tfplan.json @@ -14,6 +14,9 @@ "values": { "ack_deadline_seconds": 20, "dead_letter_policy": [], + "effective_labels": { + "test-label1": "test-value1" + }, "enable_message_ordering": null, "filter": null, "labels": { @@ -30,6 +33,9 @@ ], "retain_acked_messages": null, "retry_policy": [], + "terraform_labels": { + "test-label1": "test-value1" + }, "timeouts": null, "topic": "example-pubsub-topic" }, @@ -76,6 +82,9 @@ "after": { "ack_deadline_seconds": 20, "dead_letter_policy": [], + "effective_labels": { + "test-label1": "test-value1" + }, "enable_message_ordering": null, "filter": null, "labels": { @@ -92,11 +101,15 @@ ], "retain_acked_messages": null, "retry_policy": [], + "terraform_labels": { + "test-label1": "test-value1" + }, "timeouts": null, "topic": "example-pubsub-topic" }, "after_unknown": { "dead_letter_policy": [], + "effective_labels": {}, "expiration_policy": true, "id": true, "labels": {}, @@ -106,11 +119,13 @@ "oidc_token": [] } ], - "retry_policy": [] + "retry_policy": [], + "terraform_labels": {} }, "before_sensitive": false, "after_sensitive": { "dead_letter_policy": [], + "effective_labels": {}, "expiration_policy": [], "labels": {}, "push_config": [ @@ -118,7 +133,8 @@ "oidc_token": [] } ], - "retry_policy": [] + "retry_policy": [], + "terraform_labels": {} } } }, diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_topic.tfplan.json b/mmv1/third_party/tgc/tests/data/example_pubsub_topic.tfplan.json index ec75e9e92203..740f394fc1b9 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_topic.tfplan.json +++ b/mmv1/third_party/tgc/tests/data/example_pubsub_topic.tfplan.json @@ -12,6 +12,9 @@ "provider_name": "registry.terraform.io/hashicorp/google", "schema_version": 0, "values": { + "effective_labels": { + "test-key": "test-value" + }, "kms_key_name": "projects/{{.Provider.project}}/locations/australia-southeast1/keyRings/default_kms_keyring_name/cryptoKeys/default_kms_key_name", "labels": { "test-key": "test-value" @@ -25,6 +28,9 @@ ], "name": "test", "project": "{{.Provider.project}}", + "terraform_labels": { + "test-key": "test-value" + }, "timeouts": null } } @@ -44,6 +50,9 @@ ], "before": null, "after": { + "effective_labels": { + "test-key": "test-value" + }, "kms_key_name": "projects/{{.Provider.project}}/locations/australia-southeast1/keyRings/default_kms_keyring_name/cryptoKeys/default_kms_key_name", "labels": { "test-key": "test-value" @@ -57,9 +66,13 @@ ], "name": "test", "project": "{{.Provider.project}}", + "terraform_labels": { + "test-key": "test-value" + }, "timeouts": null }, "after_unknown": { + "effective_labels": {}, "id": true, "labels": {}, "message_storage_policy": [ @@ -68,7 +81,8 @@ false ] } - ] + ], + "terraform_labels": {} } } } diff --git a/mmv1/third_party/tgc/tests/data/full_spanner_instance.tfplan.json b/mmv1/third_party/tgc/tests/data/full_spanner_instance.tfplan.json index ead499d7a4eb..ba82885d114d 100644 --- a/mmv1/third_party/tgc/tests/data/full_spanner_instance.tfplan.json +++ b/mmv1/third_party/tgc/tests/data/full_spanner_instance.tfplan.json @@ -14,6 +14,11 @@ "values": { "config": "regional-us-central1", "display_name": "spanner-instance", + "effective_labels": { + "label1": "value1", + "label2": "value2", + "label3": "value3" + }, "force_destroy": false, "labels": { "label1": "value1", @@ -22,6 +27,11 @@ }, "name": "spanner-instance", "num_nodes": 1, + "terraform_labels": { + "label1": "value1", + "label2": "value2", + "label3": "value3" + }, "timeouts": null } } @@ -43,6 +53,11 @@ "after": { "config": "regional-us-central1", "display_name": "spanner-instance", + "effective_labels": { + "label1": "value1", + "label2": "value2", + "label3": "value3" + }, "force_destroy": false, "labels": { "label1": "value1", @@ -51,13 +66,20 @@ }, "name": "spanner-instance", "num_nodes": 1, + "terraform_labels": { + "label1": "value1", + "label2": "value2", + "label3": "value3" + }, "timeouts": null }, "after_unknown": { + "effective_labels": {}, "id": true, "labels": {}, "project": true, - "state": true + "state": true, + "terraform_labels": {} } } } From 34cf135693b8006a1d315cc28d233c3f23701d48 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Mon, 18 Sep 2023 16:56:48 -0700 Subject: [PATCH 39/67] Apply provider default labels to handwritten resources (#8966) * Apply provider default labels to handwritten resources * Add terraform_labels and effective_labels to doc * New fun SetLabels instead of FlattenLabels * Add comment for func SetLabels --- .../bigquery/resource_bigquery_table.go | 14 +++++++++-- .../bigquery/resource_bigquery_table_test.go | 2 +- .../bigtable/resource_bigtable_instance.go | 21 ++++++++++++---- .../resource_bigtable_instance_test.go | 8 +++--- .../resource_cloudfunctions_function.go | 21 ++++++++++++---- .../resource_composer_environment.go.erb | 23 ++++++++++++----- .../resource_composer_environment_test.go.erb | 2 +- .../compute/resource_compute_instance.go.erb | 20 ++++++++++++--- .../resource_compute_instance_template.go.erb | 2 +- .../resource_compute_instance_test.go.erb | 4 +-- .../dataproc/resource_dataproc_job.go.erb | 18 ++++++++++--- .../resource_google_project.go | 25 +++++++++++++++---- .../resource_google_project_test.go | 2 +- .../terraform/tpgresource/labels.go | 11 +++++--- .../terraform/tpgresource/utils.go | 5 ++++ .../docs/r/bigquery_table.html.markdown | 6 +++++ .../docs/r/bigtable_instance.html.markdown | 5 ++++ .../r/cloudfunctions_function.html.markdown | 6 +++++ .../docs/r/composer_environment.html.markdown | 6 +++++ .../docs/r/compute_instance.html.markdown | 6 +++++ .../website/docs/r/dataproc_job.html.markdown | 6 +++++ .../docs/r/google_project.html.markdown | 6 +++++ 22 files changed, 176 insertions(+), 43 deletions(-) diff --git a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go index 3f9240d0a98b..4509b4c127f4 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go @@ -421,6 +421,7 @@ func ResourceBigQueryTable() *schema.Resource { CustomizeDiff: customdiff.All( tpgresource.DefaultProviderProject, resourceBigQueryTableSchemaCustomizeDiff, + tpgresource.SetLabelsDiff, ), Schema: map[string]*schema.Schema{ // TableId: [Required] The ID of the table. The ID must contain only @@ -796,6 +797,12 @@ func ResourceBigQueryTable() *schema.Resource { **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. Please refer to the field 'effective_labels' for all of the labels present on the resource.`, }, + "terraform_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `The combination of labels configured directly on the resource and default labels configured on the provider.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, "effective_labels": { Type: schema.TypeMap, Computed: true, @@ -1283,7 +1290,7 @@ func resourceTable(d *schema.ResourceData, meta interface{}) (*bigquery.Table, e } } - if v, ok := d.GetOk("labels"); ok { + if v, ok := d.GetOk("effective_labels"); ok { labels := map[string]string{} for k, v := range v.(map[string]interface{}) { @@ -1405,9 +1412,12 @@ func resourceBigQueryTableRead(d *schema.ResourceData, meta interface{}) error { if err := d.Set("max_staleness", res.MaxStaleness); err != nil { return fmt.Errorf("Error setting max_staleness: %s", err) } - if err := d.Set("labels", tpgresource.FlattenLabels(res.Labels, d)); err != nil { + if err := tpgresource.SetLabels(res.Labels, d, "labels"); err != nil { return fmt.Errorf("Error setting labels: %s", err) } + if err := tpgresource.SetLabels(res.Labels, d, "terraform_labels"); err != nil { + return fmt.Errorf("Error setting terraform_labels: %s", err) + } if err := d.Set("effective_labels", res.Labels); err != nil { return fmt.Errorf("Error setting effective_labels: %s", err) } diff --git a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go index cb3482a9532b..dfec546814bd 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go @@ -3098,7 +3098,7 @@ resource "google_bigquery_table" "test" { friendly_name = "bigquerytest" labels = { - "terrafrom_managed" = "true" + "terrafrom_managed" = "false" } schema = jsonencode( diff --git a/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance.go b/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance.go index 1863b8f3e8c9..e2d4f56238ca 100644 --- a/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance.go +++ b/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance.go @@ -37,6 +37,7 @@ func ResourceBigtableInstance() *schema.Resource { tpgresource.DefaultProviderProject, resourceBigtableInstanceClusterReorderTypeList, resourceBigtableInstanceUniqueClusterID, + tpgresource.SetLabelsDiff, ), SchemaVersion: 1, @@ -163,6 +164,13 @@ func ResourceBigtableInstance() *schema.Resource { Please refer to the field 'effective_labels' for all of the labels present on the resource.`, }, + "terraform_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `The combination of labels configured directly on the resource and default labels configured on the provider.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "effective_labels": { Type: schema.TypeMap, Computed: true, @@ -206,8 +214,8 @@ func resourceBigtableInstanceCreate(d *schema.ResourceData, meta interface{}) er } conf.DisplayName = displayName.(string) - if _, ok := d.GetOk("labels"); ok { - conf.Labels = tpgresource.ExpandLabels(d) + if _, ok := d.GetOk("effective_labels"); ok { + conf.Labels = tpgresource.ExpandEffectiveLabels(d) } switch d.Get("instance_type").(string) { @@ -312,9 +320,12 @@ func resourceBigtableInstanceRead(d *schema.ResourceData, meta interface{}) erro if err := d.Set("display_name", instance.DisplayName); err != nil { return fmt.Errorf("Error setting display_name: %s", err) } - if err := d.Set("labels", tpgresource.FlattenLabels(instance.Labels, d)); err != nil { + if err := tpgresource.SetLabels(instance.Labels, d, "labels"); err != nil { return fmt.Errorf("Error setting labels: %s", err) } + if err := tpgresource.SetLabels(instance.Labels, d, "terraform_labels"); err != nil { + return fmt.Errorf("Error setting terraform_labels: %s", err) + } if err := d.Set("effective_labels", instance.Labels); err != nil { return fmt.Errorf("Error setting effective_labels: %s", err) } @@ -353,8 +364,8 @@ func resourceBigtableInstanceUpdate(d *schema.ResourceData, meta interface{}) er } conf.DisplayName = displayName.(string) - if d.HasChange("labels") { - conf.Labels = tpgresource.ExpandLabels(d) + if d.HasChange("effective_labels") { + conf.Labels = tpgresource.ExpandEffectiveLabels(d) } switch d.Get("instance_type").(string) { diff --git a/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance_test.go b/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance_test.go index 12f21fee49ef..d95caecf849b 100644 --- a/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance_test.go +++ b/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance_test.go @@ -89,7 +89,7 @@ func TestAccBigtableInstance_cluster(t *testing.T) { ResourceName: "google_bigtable_instance.instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"deletion_protection", "instance_type", "cluster", "labels"}, // we don't read instance type back + ImportStateVerifyIgnore: []string{"deletion_protection", "instance_type", "cluster", "labels", "terraform_labels"}, // we don't read instance type back }, { Config: testAccBigtableInstance_clusterReordered(instanceName, 5), @@ -108,7 +108,7 @@ func TestAccBigtableInstance_cluster(t *testing.T) { ResourceName: "google_bigtable_instance.instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"deletion_protection", "instance_type", "cluster", "labels"}, // we don't read instance type back + ImportStateVerifyIgnore: []string{"deletion_protection", "instance_type", "cluster", "labels", "terraform_labels"}, // we don't read instance type back }, }, }) @@ -428,7 +428,7 @@ func TestAccBigtableInstance_MultipleClustersSameID(t *testing.T) { ResourceName: "google_bigtable_instance.instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"deletion_protection", "instance_type", "labels"}, // we don't read instance type back + ImportStateVerifyIgnore: []string{"deletion_protection", "instance_type", "labels", "terraform_labels"}, // we don't read instance type back }, { Config: testAccBigtableInstance_multipleClustersSameID(instanceName), @@ -644,7 +644,7 @@ resource "google_bigtable_instance" "instance" { deletion_protection = false labels = { - env = "default" + env = "test" } } `, instanceName, instanceName, numNodes, instanceName, numNodes, instanceName, numNodes, instanceName, numNodes, instanceName, numNodes) diff --git a/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function.go b/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function.go index 6cf41e153ef4..ac86bac73dbf 100644 --- a/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function.go +++ b/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function.go @@ -145,6 +145,7 @@ func ResourceCloudFunctionsFunction() *schema.Resource { CustomizeDiff: customdiff.All( tpgresource.DefaultProviderProject, tpgresource.DefaultProviderRegion, + tpgresource.SetLabelsDiff, ), Schema: map[string]*schema.Schema{ @@ -269,6 +270,13 @@ func ResourceCloudFunctionsFunction() *schema.Resource { Please refer to the field 'effective_labels' for all of the labels present on the resource.`, }, + "terraform_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `The combination of labels configured directly on the resource and default labels configured on the provider.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "effective_labels": { Type: schema.TypeMap, Computed: true, @@ -574,8 +582,8 @@ func resourceCloudFunctionsCreate(d *schema.ResourceData, meta interface{}) erro function.IngressSettings = v.(string) } - if _, ok := d.GetOk("labels"); ok { - function.Labels = tpgresource.ExpandLabels(d) + if _, ok := d.GetOk("effective_labels"); ok { + function.Labels = tpgresource.ExpandEffectiveLabels(d) } if _, ok := d.GetOk("environment_variables"); ok { @@ -686,9 +694,12 @@ func resourceCloudFunctionsRead(d *schema.ResourceData, meta interface{}) error if err := d.Set("ingress_settings", function.IngressSettings); err != nil { return fmt.Errorf("Error setting ingress_settings: %s", err) } - if err := d.Set("labels", tpgresource.FlattenLabels(function.Labels, d)); err != nil { + if err := tpgresource.SetLabels(function.Labels, d, "labels"); err != nil { return fmt.Errorf("Error setting labels: %s", err) } + if err := tpgresource.SetLabels(function.Labels, d, "terraform_labels"); err != nil { + return fmt.Errorf("Error setting terraform_labels: %s", err) + } if err := d.Set("effective_labels", function.Labels); err != nil { return fmt.Errorf("Error setting effective_labels: %s", err) } @@ -858,8 +869,8 @@ func resourceCloudFunctionsUpdate(d *schema.ResourceData, meta interface{}) erro updateMaskArr = append(updateMaskArr, "ingressSettings") } - if d.HasChange("labels") { - function.Labels = tpgresource.ExpandLabels(d) + if d.HasChange("effective_labels") { + function.Labels = tpgresource.ExpandEffectiveLabels(d) updateMaskArr = append(updateMaskArr, "labels") } 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 4dc1b2b86ce3..31ee4210c65d 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 @@ -160,6 +160,7 @@ func ResourceComposerEnvironment() *schema.Resource { CustomizeDiff: customdiff.All( tpgresource.DefaultProviderProject, tpgresource.DefaultProviderRegion, + tpgresource.SetLabelsDiff, ), Schema: map[string]*schema.Schema{ @@ -886,6 +887,13 @@ func ResourceComposerEnvironment() *schema.Resource { Please refer to the field 'effective_labels' for all of the labels present on the resource.`, }, + "terraform_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `The combination of labels configured directly on the resource and default labels configured on the provider.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "effective_labels": { Type: schema.TypeMap, Computed: true, @@ -916,7 +924,7 @@ func resourceComposerEnvironmentCreate(d *schema.ResourceData, meta interface{}) env := &composer.Environment{ Name: envName.ResourceName(), - Labels: tpgresource.ExpandLabels(d), + Labels: tpgresource.ExpandEffectiveLabels(d), Config: transformedConfig, } @@ -994,11 +1002,14 @@ func resourceComposerEnvironmentRead(d *schema.ResourceData, meta interface{}) e if err := d.Set("config", flattenComposerEnvironmentConfig(res.Config)); err != nil { return fmt.Errorf("Error setting Environment: %s", err) } - if err := d.Set("labels", tpgresource.FlattenLabels(res.Labels, d)); err != nil { - return fmt.Errorf("Error setting Environment: %s", err) + if err := tpgresource.SetLabels(res.Labels, d, "labels"); err != nil { + return fmt.Errorf("Error setting Environment labels: %s", err) + } + if err := tpgresource.SetLabels(res.Labels, d, "terraform_labels"); err != nil { + return fmt.Errorf("Error setting terraform_labels: %s", err) } if err := d.Set("effective_labels", res.Labels); err != nil { - return fmt.Errorf("Error setting Environment: %s", err) + return fmt.Errorf("Error setting Environment effective_labels: %s", err) } return nil } @@ -1241,8 +1252,8 @@ func resourceComposerEnvironmentUpdate(d *schema.ResourceData, meta interface{}) } } - if d.HasChange("labels") { - patchEnv := &composer.Environment{Labels: tpgresource.ExpandLabels(d)} + if d.HasChange("effective_labels") { + patchEnv := &composer.Environment{Labels: tpgresource.ExpandEffectiveLabels(d)} err := resourceComposerEnvironmentPatchField("labels", userAgent, patchEnv, d, tfConfig) if err != nil { return err 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 09ea214d14e4..d02d58f7e181 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 @@ -100,7 +100,7 @@ func TestAccComposerEnvironment_update(t *testing.T) { ResourceName: "google_composer_environment.test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"labels"}, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, // This is a terrible clean-up step in order to get destroy to succeed, // due to dangling firewall rules left by the Composer Environment blocking network deletion. diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb index b08a84d1ea1d..3e6b21b594a0 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb @@ -619,6 +619,13 @@ func ResourceComputeInstance() *schema.Resource { Please refer to the field 'effective_labels' for all of the labels present on the resource.`, }, + "terraform_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `The combination of labels configured directly on the resource and default labels configured on the provider.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "effective_labels": { Type: schema.TypeMap, Computed: true, @@ -1069,6 +1076,7 @@ be from 0 to 999,999,999 inclusive.`, ), desiredStatusDiff, forceNewIfNetworkIPNotUpdatable, + tpgresource.SetLabelsDiff, ), UseJSONNumber: true, } @@ -1202,7 +1210,7 @@ func expandComputeInstance(project string, d *schema.ResourceData, config *trans NetworkPerformanceConfig: networkPerformanceConfig, Tags: resourceInstanceTags(d), Params: params, - Labels: tpgresource.ExpandLabels(d), + Labels: tpgresource.ExpandEffectiveLabels(d), ServiceAccounts: expandServiceAccounts(d.Get("service_account").([]interface{})), GuestAccelerators: accels, MinCpuPlatform: d.Get("min_cpu_platform").(string), @@ -1402,7 +1410,11 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error } } - if err := d.Set("labels", tpgresource.FlattenLabels(instance.Labels, d)); err != nil { + if err := tpgresource.SetLabels(instance.Labels, d, "labels"); err != nil { + return err + } + + if err := tpgresource.SetLabels(instance.Labels, d, "terraform_labels"); err != nil { return err } @@ -1685,8 +1697,8 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err } } - if d.HasChange("labels") { - labels := tpgresource.ExpandLabels(d) + if d.HasChange("effective_labels") { + labels := tpgresource.ExpandEffectiveLabels(d) labelFingerprint := d.Get("label_fingerprint").(string) req := compute.InstancesSetLabelsRequest{Labels: labels, LabelFingerprint: labelFingerprint} diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb index 5bccff61705e..277825a3428b 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb @@ -1645,7 +1645,7 @@ func resourceComputeInstanceTemplateRead(d *schema.ResourceData, meta interface{ } } if instanceTemplate.Properties.Labels != nil { - if err := d.Set("labels", tpgresource.FlattenLabels(instanceTemplate.Properties.Labels, d)); err != nil { + if err := tpgresource.SetLabels(instanceTemplate.Properties.Labels, d, "labels"); err != nil { return fmt.Errorf("Error setting labels: %s", err) } } diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.erb index f4e1222a6992..b33511f682d4 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.erb @@ -139,7 +139,7 @@ func TestAccComputeInstance_basic1(t *testing.T) { testAccCheckComputeInstanceHasConfiguredDeletionProtection(&instance, false), ), }, - computeInstanceImportStep("us-central1-a", instanceName, []string{"metadata.baz", "metadata.foo", "desired_status", "current_status", "labels"}), + computeInstanceImportStep("us-central1-a", instanceName, []string{"metadata.baz", "metadata.foo", "desired_status", "current_status", "labels", "terraform_labels"}), }, }) } @@ -1426,7 +1426,7 @@ func TestAccComputeInstance_forceChangeMachineTypeManually(t *testing.T) { ), ExpectNonEmptyPlan: true, }, - computeInstanceImportStep("us-central1-a", instanceName, []string{"metadata.baz", "metadata.foo", "desired_status", "current_status", "labels"}), + computeInstanceImportStep("us-central1-a", instanceName, []string{"metadata.baz", "metadata.foo", "desired_status", "current_status", "labels", "terraform_labels"}), }, }) } diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_job.go.erb b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_job.go.erb index fc6c576a08c3..c51e7f5d19c5 100644 --- a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_job.go.erb +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_job.go.erb @@ -33,6 +33,7 @@ func ResourceDataprocJob() *schema.Resource { CustomizeDiff: customdiff.All( tpgresource.DefaultProviderProject, + tpgresource.SetLabelsDiff, ), Schema: map[string]*schema.Schema{ @@ -158,9 +159,17 @@ func ResourceDataprocJob() *schema.Resource { Elem: &schema.Schema{Type: schema.TypeString}, }, + "terraform_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `The combination of labels configured directly on the resource and default labels configured on the provider.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "effective_labels": { Type: schema.TypeMap, Computed: true, + ForceNew: true, Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, Elem: &schema.Schema{Type: schema.TypeString}, }, @@ -245,8 +254,8 @@ func resourceDataprocJobCreate(d *schema.ResourceData, meta interface{}) error { submitReq.Job.Scheduling = expandJobScheduling(config) } - if _, ok := d.GetOk("labels"); ok { - submitReq.Job.Labels = tpgresource.ExpandLabels(d) + if _, ok := d.GetOk("effective_labels"); ok { + submitReq.Job.Labels = tpgresource.ExpandEffectiveLabels(d) } if v, ok := d.GetOk("pyspark_config"); ok { @@ -326,9 +335,12 @@ func resourceDataprocJobRead(d *schema.ResourceData, meta interface{}) error { if err := d.Set("force_delete", d.Get("force_delete")); err != nil { return fmt.Errorf("Error setting force_delete: %s", err) } - if err := d.Set("labels", tpgresource.FlattenLabels(job.Labels, d)); err != nil { + if err := tpgresource.SetLabels(job.Labels, d, "labels"); err != nil { return fmt.Errorf("Error setting labels: %s", err) } + if err := tpgresource.SetLabels(job.Labels, d, "terraform_labels"); err != nil { + return fmt.Errorf("Error setting terraform_labels: %s", err) + } if err := d.Set("effective_labels", job.Labels); err != nil { return fmt.Errorf("Error setting effective_labels: %s", err) } diff --git a/mmv1/third_party/terraform/services/resourcemanager/resource_google_project.go b/mmv1/third_party/terraform/services/resourcemanager/resource_google_project.go index 629ab2b04c29..acf1db96fa56 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/resource_google_project.go +++ b/mmv1/third_party/terraform/services/resourcemanager/resource_google_project.go @@ -11,6 +11,7 @@ import ( "time" "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" tpgcompute "github.com/hashicorp/terraform-provider-google/google/services/compute" @@ -40,6 +41,10 @@ func ResourceGoogleProject() *schema.Resource { Update: resourceGoogleProjectUpdate, Delete: resourceGoogleProjectDelete, + CustomizeDiff: customdiff.All( + tpgresource.SetLabelsDiff, + ), + Importer: &schema.ResourceImporter{ State: resourceProjectImportState, }, @@ -112,6 +117,13 @@ func ResourceGoogleProject() *schema.Resource { Please refer to the field 'effective_labels' for all of the labels present on the resource.`, }, + "terraform_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `The combination of labels configured directly on the resource and default labels configured on the provider.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "effective_labels": { Type: schema.TypeMap, Computed: true, @@ -147,8 +159,8 @@ func resourceGoogleProjectCreate(d *schema.ResourceData, meta interface{}) error return err } - if _, ok := d.GetOk("labels"); ok { - project.Labels = tpgresource.ExpandLabels(d) + if _, ok := d.GetOk("effective_labels"); ok { + project.Labels = tpgresource.ExpandEffectiveLabels(d) } var op *cloudresourcemanager.Operation @@ -296,9 +308,12 @@ func resourceGoogleProjectRead(d *schema.ResourceData, meta interface{}) error { if err := d.Set("name", p.Name); err != nil { return fmt.Errorf("Error setting name: %s", err) } - if err := d.Set("labels", tpgresource.FlattenLabels(p.Labels, d)); err != nil { + if err := tpgresource.SetLabels(p.Labels, d, "labels"); err != nil { return fmt.Errorf("Error setting labels: %s", err) } + if err := tpgresource.SetLabels(p.Labels, d, "terraform_labels"); err != nil { + return fmt.Errorf("Error setting terraform_labels: %s", err) + } if err := d.Set("effective_labels", p.Labels); err != nil { return fmt.Errorf("Error setting effective_labels: %s", err) } @@ -444,8 +459,8 @@ func resourceGoogleProjectUpdate(d *schema.ResourceData, meta interface{}) error } // Project Labels have changed - if ok := d.HasChange("labels"); ok { - p.Labels = tpgresource.ExpandLabels(d) + if ok := d.HasChange("effective_labels"); ok { + p.Labels = tpgresource.ExpandEffectiveLabels(d) // Do Update on project if p, err = updateProject(config, d, project_name, userAgent, p); err != nil { diff --git a/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_test.go b/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_test.go index a531ad8a766f..12489e663f6e 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_test.go +++ b/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_test.go @@ -136,7 +136,7 @@ func TestAccProject_labels(t *testing.T) { ResourceName: "google_project.acceptance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"skip_delete", "labels"}, + ImportStateVerifyIgnore: []string{"skip_delete", "labels", "terraform_labels"}, }, // update project with labels { diff --git a/mmv1/third_party/terraform/tpgresource/labels.go b/mmv1/third_party/terraform/tpgresource/labels.go index a0b13c52b78d..c07cdfd486a5 100644 --- a/mmv1/third_party/terraform/tpgresource/labels.go +++ b/mmv1/third_party/terraform/tpgresource/labels.go @@ -8,10 +8,15 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" ) -func FlattenLabels(labels map[string]string, d *schema.ResourceData) map[string]interface{} { +// SetLabels is called in the READ method of the resources to set +// the field "labels" and "terraform_labels" in the state based on the labels field in the configuration. +// So the field "labels" and "terraform_labels" in the state will only have the user defined labels. +// param "labels" is all of labels returned from API read reqeust. +// param "lineage" is the terraform lineage of the field and could be "labels" or "terraform_labels". +func SetLabels(labels map[string]string, d *schema.ResourceData, lineage string) error { transformed := make(map[string]interface{}) - if v, ok := d.GetOk("labels"); ok { + if v, ok := d.GetOk(lineage); ok { if labels != nil { for k, _ := range v.(map[string]interface{}) { transformed[k] = labels[k] @@ -19,7 +24,7 @@ func FlattenLabels(labels map[string]string, d *schema.ResourceData) map[string] } } - return transformed + return d.Set(lineage, transformed) } func SetLabelsDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) error { diff --git a/mmv1/third_party/terraform/tpgresource/utils.go b/mmv1/third_party/terraform/tpgresource/utils.go index 3c8e391589a1..14603afe6786 100644 --- a/mmv1/third_party/terraform/tpgresource/utils.go +++ b/mmv1/third_party/terraform/tpgresource/utils.go @@ -204,6 +204,11 @@ func ExpandLabels(d TerraformResourceData) map[string]string { return ExpandStringMap(d, "labels") } +// ExpandEffectiveLabels pulls the value of "effective_labels" out of a TerraformResourceData as a map[string]string. +func ExpandEffectiveLabels(d TerraformResourceData) map[string]string { + return ExpandStringMap(d, "effective_labels") +} + // ExpandEnvironmentVariables pulls the value of "environment_variables" out of a schema.ResourceData as a map[string]string. func ExpandEnvironmentVariables(d *schema.ResourceData) map[string]string { return ExpandStringMap(d, "environment_variables") diff --git a/mmv1/third_party/terraform/website/docs/r/bigquery_table.html.markdown b/mmv1/third_party/terraform/website/docs/r/bigquery_table.html.markdown index 2fb0cd7fb3a7..78d4668a668c 100644 --- a/mmv1/third_party/terraform/website/docs/r/bigquery_table.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/bigquery_table.html.markdown @@ -114,6 +114,12 @@ The following arguments are supported: * `labels` - (Optional) A mapping of labels to assign to the resource. +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. + * `schema` - (Optional) A JSON schema for the table. ~>**NOTE:** Because this field expects a JSON string, any changes to the diff --git a/mmv1/third_party/terraform/website/docs/r/bigtable_instance.html.markdown b/mmv1/third_party/terraform/website/docs/r/bigtable_instance.html.markdown index 6536a90b7800..122449e39c73 100644 --- a/mmv1/third_party/terraform/website/docs/r/bigtable_instance.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/bigtable_instance.html.markdown @@ -102,6 +102,11 @@ in Terraform state, a `terraform destroy` or `terraform apply` that would delete * `labels` - (Optional) A set of key/value label pairs to assign to the resource. Label keys must follow the requirements at https://cloud.google.com/resource-manager/docs/creating-managing-labels#requirements. +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. ----- diff --git a/mmv1/third_party/terraform/website/docs/r/cloudfunctions_function.html.markdown b/mmv1/third_party/terraform/website/docs/r/cloudfunctions_function.html.markdown index 40d8a29bd42b..8d0ada5aa626 100644 --- a/mmv1/third_party/terraform/website/docs/r/cloudfunctions_function.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/cloudfunctions_function.html.markdown @@ -134,6 +134,12 @@ Eg. `"nodejs16"`, `"python39"`, `"dotnet3"`, `"go116"`, `"java11"`, `"ruby30"`, * `labels` - (Optional) A set of key/value label pairs to assign to the function. Label keys must follow the requirements at https://cloud.google.com/resource-manager/docs/creating-managing-labels#requirements. +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. + * `service_account_email` - (Optional) If provided, the self-provided service account to run the function with. * `environment_variables` - (Optional) A set of key/value environment variable pairs to assign to the function. 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 438b688d9f7c..792ff022fbb1 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 @@ -262,6 +262,12 @@ The following arguments are supported: No more than 64 labels can be associated with a given environment. Both keys and values must be <= 128 bytes in size. +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. + * `region` - (Optional) The location or Compute Engine region for the environment. diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown index aa1c929d2db8..53fc20e6a377 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown @@ -118,6 +118,12 @@ The following arguments are supported: * `labels` - (Optional) A map of key/value label pairs to assign to the instance. +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. + * `metadata` - (Optional) Metadata key/value pairs to make available from within the instance. Ssh keys attached in the Cloud Console will be removed. Add them to your config in order to keep them attached to your instance. A diff --git a/mmv1/third_party/terraform/website/docs/r/dataproc_job.html.markdown b/mmv1/third_party/terraform/website/docs/r/dataproc_job.html.markdown index 3c8b99fee706..0e9953079fbe 100644 --- a/mmv1/third_party/terraform/website/docs/r/dataproc_job.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/dataproc_job.html.markdown @@ -103,6 +103,12 @@ output "pyspark_status" { * `labels` - (Optional) The list of labels (key/value pairs) to add to the job. +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. + * `scheduling.max_failures_per_hour` - (Required) Maximum number of times per hour a driver may be restarted as a result of driver exiting with non-zero code before job is reported failed. * `scheduling.max_failures_total` - (Required) Maximum number of times in total a driver may be restarted as a result of driver exiting with non-zero code before job is reported failed. diff --git a/mmv1/third_party/terraform/website/docs/r/google_project.html.markdown b/mmv1/third_party/terraform/website/docs/r/google_project.html.markdown index 36f5eb06919c..e5139412d01c 100644 --- a/mmv1/third_party/terraform/website/docs/r/google_project.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/google_project.html.markdown @@ -83,6 +83,12 @@ The following arguments are supported: * `labels` - (Optional) A set of key/value label pairs to assign to the project. +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. + * `auto_create_network` - (Optional) Controls whether the 'default' network exists on the project. Defaults to `true`, where it is created. If set to `false`, the default network will still be created by GCP but will be deleted immediately by Terraform. Therefore, for quota purposes, you will still need to have 1 From 14abe6051c6f135b6142bfbb658c20e742917e74 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Tue, 19 Sep 2023 16:33:23 -0700 Subject: [PATCH 40/67] Apply new labels model to more resources (part 3) (#9000) * Apply new labels model to more resources (part 3) * Use the same format for labels fields * Ignore labels fileds in import state verify --- mmv1/products/cloudrun/DomainMapping.yaml | 4 +-- mmv1/products/cloudrun/Service.yaml | 8 +++--- mmv1/products/cloudrunv2/Job.yaml | 4 +-- mmv1/products/containerattached/Cluster.yaml | 2 +- mmv1/products/firebasehosting/Channel.yaml | 4 +-- mmv1/products/gkebackup/BackupPlan.yaml | 4 +-- mmv1/products/gkehub2/Feature.yaml | 4 +-- .../gkeonprem/BareMetalAdminCluster.yaml | 6 ++-- mmv1/products/gkeonprem/BareMetalCluster.yaml | 14 +++++----- mmv1/products/gkeonprem/VmwareNodePool.yaml | 4 +-- mmv1/products/healthcare/ConsentStore.yaml | 4 +-- mmv1/products/healthcare/DicomStore.yaml | 4 +-- mmv1/products/healthcare/FhirStore.yaml | 4 +-- mmv1/products/healthcare/Hl7V2Store.yaml | 4 +-- mmv1/products/logging/Metric.yaml | 2 +- mmv1/products/monitoring/AlertPolicy.yaml | 2 +- .../products/monitoring/MetricDescriptor.yaml | 2 +- .../monitoring/NotificationChannel.yaml | 2 +- .../monitoring/UptimeCheckConfig.yaml | 2 +- .../ServiceConnectionPolicies.yaml | 4 +-- .../networksecurity/AddressGroup.yaml | 4 +-- mmv1/products/privateca/CaPool.yaml | 4 +-- .../privateca/CertificateAuthority.yaml | 4 +-- mmv1/products/secretmanager/Secret.yaml | 6 ++-- mmv1/products/vertexai/Endpoint.yaml | 4 +-- .../workstations/WorkstationCluster.yaml | 6 ++-- ...ource_firebase_hosting_channel_test.go.erb | 4 +-- ...esource_gke_backup_backup_plan_test.go.erb | 8 ++++++ .../resource_gke_hub_feature_test.go.erb | 5 ++-- .../resource_healthcare_dicom_store_test.go | 21 ++++++++------ ...resource_healthcare_fhir_store_test.go.erb | 3 ++ ...source_healthcare_hl7_v2_store_test.go.erb | 3 ++ ...tivity_service_connection_policies_test.go | 21 ++++++++------ ...rce_network_security_address_group_test.go | 14 ++++++---- .../resource_privateca_ca_pool_test.go | 10 +++---- ...ce_privateca_certificate_authority_test.go | 6 ++-- .../data_source_secret_manager_secret_test.go | 6 +++- ...resource_secret_manager_secret_test.go.erb | 28 +++++++++---------- ...rkstations_workstation_cluster_test.go.erb | 8 +++--- 39 files changed, 138 insertions(+), 111 deletions(-) diff --git a/mmv1/products/cloudrun/DomainMapping.yaml b/mmv1/products/cloudrun/DomainMapping.yaml index 8eb9730a654c..7f8266c3acf7 100644 --- a/mmv1/products/cloudrun/DomainMapping.yaml +++ b/mmv1/products/cloudrun/DomainMapping.yaml @@ -158,7 +158,7 @@ properties: description: Metadata associated with this DomainMapping. properties: - !ruby/object:Api::Type::KeyValuePairs - name: labels + name: 'labels' description: |- Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers @@ -204,7 +204,7 @@ properties: project ID or project number. custom_flatten: templates/terraform/custom_flatten/set_to_project.go.erb - !ruby/object:Api::Type::KeyValuePairs - name: annotations + name: 'annotations' description: |- Annotations is a key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. More diff --git a/mmv1/products/cloudrun/Service.yaml b/mmv1/products/cloudrun/Service.yaml index 1160362ab594..d234a11ca494 100644 --- a/mmv1/products/cloudrun/Service.yaml +++ b/mmv1/products/cloudrun/Service.yaml @@ -240,7 +240,7 @@ properties: default_from_api: true properties: - !ruby/object:Api::Type::KeyValuePairs - name: labels + name: 'labels' description: |- Map of string keys and values that can be used to organize and categorize (scope and select) objects. @@ -279,7 +279,7 @@ properties: default_from_api: true custom_expand: 'templates/terraform/custom_expand/default_to_project.go.erb' - !ruby/object:Api::Type::KeyValuePairs - name: annotations + name: 'annotations' description: |- Annotations is a key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. More @@ -971,7 +971,7 @@ properties: default_from_api: true properties: - !ruby/object:Api::Type::KeyValuePairs - name: labels + name: 'labels' description: |- Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers @@ -1013,7 +1013,7 @@ properties: custom_flatten: templates/terraform/custom_flatten/set_to_project.go.erb custom_expand: 'templates/terraform/custom_expand/default_to_project.go.erb' - !ruby/object:Api::Type::KeyValuePairs - name: annotations + name: 'annotations' description: |- Annotations is a key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. More diff --git a/mmv1/products/cloudrunv2/Job.yaml b/mmv1/products/cloudrunv2/Job.yaml index 82bd0618fb85..11b047c73150 100644 --- a/mmv1/products/cloudrunv2/Job.yaml +++ b/mmv1/products/cloudrunv2/Job.yaml @@ -138,7 +138,7 @@ properties: Cloud Run API v2 does not support labels with `run.googleapis.com`, `cloud.googleapis.com`, `serving.knative.dev`, or `autoscaling.knative.dev` namespaces, and they will be rejected. All system labels in v1 now have a corresponding field in v2 Job. - !ruby/object:Api::Type::KeyValueAnnotations - name: "annotations" + name: 'annotations' description: |- Unstructured key value map that may be set by external tools to store and arbitrary metadata. They are not queryable and should be preserved when modifying objects. @@ -229,7 +229,7 @@ properties: Cloud Run API v2 does not support labels with `run.googleapis.com`, `cloud.googleapis.com`, `serving.knative.dev`, or `autoscaling.knative.dev` namespaces, and they will be rejected. All system labels in v1 now have a corresponding field in v2 ExecutionTemplate. - !ruby/object:Api::Type::KeyValuePairs - name: "annotations" + name: 'annotations' description: |- Unstructured key value map that may be set by external tools to store and arbitrary metadata. They are not queryable and should be preserved when modifying objects. diff --git a/mmv1/products/containerattached/Cluster.yaml b/mmv1/products/containerattached/Cluster.yaml index e27a70f9edbb..25e24de25699 100644 --- a/mmv1/products/containerattached/Cluster.yaml +++ b/mmv1/products/containerattached/Cluster.yaml @@ -203,7 +203,7 @@ properties: The Kubernetes version of the cluster. output: true - !ruby/object:Api::Type::KeyValueAnnotations - name: annotations + name: 'annotations' description: | Optional. Annotations on the cluster. This field has the same restrictions as Kubernetes annotations. The total size of all keys and diff --git a/mmv1/products/firebasehosting/Channel.yaml b/mmv1/products/firebasehosting/Channel.yaml index d94e4bef481b..5a1cc9648230 100644 --- a/mmv1/products/firebasehosting/Channel.yaml +++ b/mmv1/products/firebasehosting/Channel.yaml @@ -76,8 +76,8 @@ properties: The number of previous releases to retain on the channel for rollback or other purposes. Must be a number between 1-100. Defaults to 10 for new channels. default_from_api: true - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' description: Text labels used for extra metadata and/or filtering - !ruby/object:Api::Type::Time name: expireTime diff --git a/mmv1/products/gkebackup/BackupPlan.yaml b/mmv1/products/gkebackup/BackupPlan.yaml index 28172b41460f..92fc4ddb57b9 100644 --- a/mmv1/products/gkebackup/BackupPlan.yaml +++ b/mmv1/products/gkebackup/BackupPlan.yaml @@ -138,8 +138,8 @@ properties: If set to True, no further update is allowed on this policy, including the locked field itself. default_from_api: true - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' description: | Description: A set of custom labels supplied by the user. A list of key->value pairs. diff --git a/mmv1/products/gkehub2/Feature.yaml b/mmv1/products/gkehub2/Feature.yaml index e2621d30a24c..89bdd43b671d 100644 --- a/mmv1/products/gkehub2/Feature.yaml +++ b/mmv1/products/gkehub2/Feature.yaml @@ -105,8 +105,8 @@ properties: diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' custom_expand: templates/terraform/custom_expand/resource_from_self_link.go.erb custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' description: GCP labels for this Feature. - !ruby/object:Api::Type::NestedObject name: resourceState diff --git a/mmv1/products/gkeonprem/BareMetalAdminCluster.yaml b/mmv1/products/gkeonprem/BareMetalAdminCluster.yaml index 1d873319ed61..7dc763a8b3a9 100644 --- a/mmv1/products/gkeonprem/BareMetalAdminCluster.yaml +++ b/mmv1/products/gkeonprem/BareMetalAdminCluster.yaml @@ -134,7 +134,7 @@ properties: through optimistic concurrency control. output: true - !ruby/object:Api::Type::KeyValueAnnotations - name: "annotations" + name: 'annotations' description: | Annotations on the Bare Metal Admin Cluster. This field has the same restrictions as Kubernetes annotations. @@ -194,7 +194,7 @@ properties: The default IPv4 address for SSH access and Kubernetes node. Example: 192.168.0.1 - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + name: 'labels' description: | The map of Kubernetes labels (key/value pairs) to be applied to each node. These will added in addition to any default label(s) @@ -233,7 +233,7 @@ properties: - PREFER_NO_SCHEDULE - NO_EXECUTE - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + name: 'labels' description: | The map of Kubernetes labels (key/value pairs) to be applied to each node. These will added in addition to any default label(s) diff --git a/mmv1/products/gkeonprem/BareMetalCluster.yaml b/mmv1/products/gkeonprem/BareMetalCluster.yaml index a2648c7ef029..4aecba4e9b2d 100644 --- a/mmv1/products/gkeonprem/BareMetalCluster.yaml +++ b/mmv1/products/gkeonprem/BareMetalCluster.yaml @@ -86,7 +86,7 @@ properties: description: | A human readable description of this Bare Metal User Cluster. - !ruby/object:Api::Type::KeyValueAnnotations - name: "annotations" + name: 'annotations' description: | Annotations on the Bare Metal User Cluster. This field has the same restrictions as Kubernetes annotations. @@ -176,7 +176,7 @@ properties: The default IPv4 address for SSH access and Kubernetes node. Example: 192.168.0.1 - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + name: 'labels' description: | The map of Kubernetes labels (key/value pairs) to be applied to each node. These will added in addition to any default label(s) @@ -217,7 +217,7 @@ properties: - PREFER_NO_SCHEDULE - NO_EXECUTE - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + name: 'labels' description: | The map of Kubernetes labels (key/value pairs) to be applied to each node. These will added in addition to any default label(s) @@ -340,7 +340,7 @@ properties: The default IPv4 address for SSH access and Kubernetes node. Example: 192.168.0.1 - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + name: 'labels' description: | The map of Kubernetes labels (key/value pairs) to be applied to each node. These will added in addition to any default label(s) @@ -381,7 +381,7 @@ properties: - PREFER_NO_SCHEDULE - NO_EXECUTE - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + name: 'labels' description: | The map of Kubernetes labels (key/value pairs) to be applied to each node. These will added in addition to any default label(s) @@ -504,7 +504,7 @@ properties: The default IPv4 address for SSH access and Kubernetes node. Example: 192.168.0.1 - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + name: 'labels' description: | The map of Kubernetes labels (key/value pairs) to be applied to each node. These will added in addition to any default label(s) @@ -543,7 +543,7 @@ properties: - PREFER_NO_SCHEDULE - NO_EXECUTE - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + name: 'labels' description: | The map of Kubernetes labels (key/value pairs) to be applied to each node. These will added in addition to any default label(s) diff --git a/mmv1/products/gkeonprem/VmwareNodePool.yaml b/mmv1/products/gkeonprem/VmwareNodePool.yaml index 1579c1acff40..5afe0bb7859e 100644 --- a/mmv1/products/gkeonprem/VmwareNodePool.yaml +++ b/mmv1/products/gkeonprem/VmwareNodePool.yaml @@ -72,7 +72,7 @@ properties: name: "displayName" description: The display name for the node pool. - !ruby/object:Api::Type::KeyValueAnnotations - name: "annotations" + name: 'annotations' description: | Annotations on the node Pool. This field has the same restrictions as Kubernetes annotations. @@ -148,7 +148,7 @@ properties: - PREFER_NO_SCHEDULE - NO_EXECUTE - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + name: 'labels' description: | The map of Kubernetes labels (key/value pairs) to be applied to each node. These will added in addition to any default label(s) that diff --git a/mmv1/products/healthcare/ConsentStore.yaml b/mmv1/products/healthcare/ConsentStore.yaml index 7db49d2bcf38..75a56824809b 100644 --- a/mmv1/products/healthcare/ConsentStore.yaml +++ b/mmv1/products/healthcare/ConsentStore.yaml @@ -93,8 +93,8 @@ properties: required: false description: | If true, [consents.patch] [google.cloud.healthcare.v1.consent.UpdateConsent] creates the consent if it does not already exist. - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' required: false description: | User-supplied key-value pairs used to organize Consent stores. diff --git a/mmv1/products/healthcare/DicomStore.yaml b/mmv1/products/healthcare/DicomStore.yaml index 90ab6b2cbd86..98378ff2998e 100644 --- a/mmv1/products/healthcare/DicomStore.yaml +++ b/mmv1/products/healthcare/DicomStore.yaml @@ -73,8 +73,8 @@ properties: ** Changing this property may recreate the Dicom store (removing all data) ** required: true immutable: true - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' required: false description: | User-supplied key-value pairs used to organize DICOM stores. diff --git a/mmv1/products/healthcare/FhirStore.yaml b/mmv1/products/healthcare/FhirStore.yaml index d9bebcee2dbc..dc9100591bd7 100644 --- a/mmv1/products/healthcare/FhirStore.yaml +++ b/mmv1/products/healthcare/FhirStore.yaml @@ -166,8 +166,8 @@ properties: ** This property can be changed manually in the Google Cloud Healthcare admin console without recreating the FHIR store ** required: false immutable: true - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' required: false description: | User-supplied key-value pairs used to organize FHIR stores. diff --git a/mmv1/products/healthcare/Hl7V2Store.yaml b/mmv1/products/healthcare/Hl7V2Store.yaml index 931730c5e672..2c395e9a1338 100644 --- a/mmv1/products/healthcare/Hl7V2Store.yaml +++ b/mmv1/products/healthcare/Hl7V2Store.yaml @@ -129,8 +129,8 @@ properties: - :V1 - :V2 - :V3 - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' required: false description: | User-supplied key-value pairs used to organize HL7v2 stores. diff --git a/mmv1/products/logging/Metric.yaml b/mmv1/products/logging/Metric.yaml index 98b154070d22..5bcf2eae51bb 100644 --- a/mmv1/products/logging/Metric.yaml +++ b/mmv1/products/logging/Metric.yaml @@ -132,7 +132,7 @@ properties: - :CUMULATIVE required: true - !ruby/object:Api::Type::Array - name: labels + name: 'labels' description: | The set of labels that can be used to describe a specific instance of this metric type. For example, the appengine.googleapis.com/http/server/response_latencies metric type has a label diff --git a/mmv1/products/monitoring/AlertPolicy.yaml b/mmv1/products/monitoring/AlertPolicy.yaml index 6ec4e791e16f..d33ba8bd9764 100644 --- a/mmv1/products/monitoring/AlertPolicy.yaml +++ b/mmv1/products/monitoring/AlertPolicy.yaml @@ -859,7 +859,7 @@ properties: alerting rule, then this value should be taken from the enclosing rule group. - !ruby/object:Api::Type::KeyValuePairs - name: labels + name: 'labels' description: | Labels to add to or overwrite in the PromQL query result. Label names must be valid. diff --git a/mmv1/products/monitoring/MetricDescriptor.yaml b/mmv1/products/monitoring/MetricDescriptor.yaml index d83d04bc820b..b3b8f2c2b431 100644 --- a/mmv1/products/monitoring/MetricDescriptor.yaml +++ b/mmv1/products/monitoring/MetricDescriptor.yaml @@ -69,7 +69,7 @@ properties: the DNS name custom.googleapis.com, external.googleapis.com, or logging.googleapis.com/user/. - !ruby/object:Api::Type::Array - name: labels + name: 'labels' description: The set of labels that can be used to describe a specific instance of this metric type. In order to delete a label, the entire resource must be diff --git a/mmv1/products/monitoring/NotificationChannel.yaml b/mmv1/products/monitoring/NotificationChannel.yaml index fe021aa1ff00..88d7e54fb687 100644 --- a/mmv1/products/monitoring/NotificationChannel.yaml +++ b/mmv1/products/monitoring/NotificationChannel.yaml @@ -79,7 +79,7 @@ custom_diff: [ ] properties: - !ruby/object:Api::Type::KeyValuePairs - name: labels + name: 'labels' description: | Configuration fields that define the channel and its behavior. The permissible and required labels are specified in the diff --git a/mmv1/products/monitoring/UptimeCheckConfig.yaml b/mmv1/products/monitoring/UptimeCheckConfig.yaml index b1d923680ebc..3af431687199 100644 --- a/mmv1/products/monitoring/UptimeCheckConfig.yaml +++ b/mmv1/products/monitoring/UptimeCheckConfig.yaml @@ -402,7 +402,7 @@ properties: resource types (https://cloud.google.com/logging/docs/api/v2/resource-list). - !ruby/object:Api::Type::KeyValuePairs - name: labels + name: 'labels' immutable: true required: true description: diff --git a/mmv1/products/networkconnectivity/ServiceConnectionPolicies.yaml b/mmv1/products/networkconnectivity/ServiceConnectionPolicies.yaml index 174943e84a94..89551984b665 100644 --- a/mmv1/products/networkconnectivity/ServiceConnectionPolicies.yaml +++ b/mmv1/products/networkconnectivity/ServiceConnectionPolicies.yaml @@ -205,7 +205,7 @@ properties: output: true description: | The type of underlying resources used to create the connection. - - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' description: | User-defined labels. diff --git a/mmv1/products/networksecurity/AddressGroup.yaml b/mmv1/products/networksecurity/AddressGroup.yaml index 09177a4a472b..87d2b9a19951 100644 --- a/mmv1/products/networksecurity/AddressGroup.yaml +++ b/mmv1/products/networksecurity/AddressGroup.yaml @@ -95,8 +95,8 @@ properties: A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". output: true - - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' description: | Set of label tags associated with the AddressGroup resource. An object containing a list of "key": value pairs. Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }. diff --git a/mmv1/products/privateca/CaPool.yaml b/mmv1/products/privateca/CaPool.yaml index 6886aef18c94..5ffda3b7cacc 100644 --- a/mmv1/products/privateca/CaPool.yaml +++ b/mmv1/products/privateca/CaPool.yaml @@ -480,8 +480,8 @@ properties: values: - :PEM - :DER - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' description: | Labels with user-defined metadata. diff --git a/mmv1/products/privateca/CertificateAuthority.yaml b/mmv1/products/privateca/CertificateAuthority.yaml index 99d9e118c14f..85e8d98598c2 100644 --- a/mmv1/products/privateca/CertificateAuthority.yaml +++ b/mmv1/products/privateca/CertificateAuthority.yaml @@ -735,8 +735,8 @@ properties: A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". output: true - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' description: | Labels with user-defined metadata. diff --git a/mmv1/products/secretmanager/Secret.yaml b/mmv1/products/secretmanager/Secret.yaml index be039109d7b9..63d6315bf9aa 100644 --- a/mmv1/products/secretmanager/Secret.yaml +++ b/mmv1/products/secretmanager/Secret.yaml @@ -69,8 +69,8 @@ properties: output: true description: | The time at which the Secret was created. - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' description: | The labels assigned to this Secret. @@ -85,7 +85,7 @@ properties: An object containing a list of "key": value pairs. Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }. - !ruby/object:Api::Type::KeyValueAnnotations - name: annotations + name: 'annotations' description: | Custom metadata about the secret. diff --git a/mmv1/products/vertexai/Endpoint.yaml b/mmv1/products/vertexai/Endpoint.yaml index 900fd90ee5df..9bd52067d4e2 100644 --- a/mmv1/products/vertexai/Endpoint.yaml +++ b/mmv1/products/vertexai/Endpoint.yaml @@ -359,8 +359,8 @@ properties: "overwrite" update happens. output: true ignore_read: true - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' description: The labels with user-defined metadata to organize your Endpoints. Label keys and values can be no longer than 64 characters (Unicode codepoints), diff --git a/mmv1/products/workstations/WorkstationCluster.yaml b/mmv1/products/workstations/WorkstationCluster.yaml index e6013adaddbf..f06be329f74e 100644 --- a/mmv1/products/workstations/WorkstationCluster.yaml +++ b/mmv1/products/workstations/WorkstationCluster.yaml @@ -89,8 +89,8 @@ properties: output: true description: | The system-generated UID of the resource. - - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' description: "Client-specified labels that are applied to the resource and that are also propagated to the underlying Compute Engine resources." @@ -119,7 +119,7 @@ properties: Details can be found in the conditions field. output: true - !ruby/object:Api::Type::KeyValueAnnotations - name: "annotations" + name: 'annotations' description: "Client-specified annotations. This is distinct from labels." - !ruby/object:Api::Type::Fingerprint name: "etag" diff --git a/mmv1/third_party/terraform/services/firebasehosting/resource_firebase_hosting_channel_test.go.erb b/mmv1/third_party/terraform/services/firebasehosting/resource_firebase_hosting_channel_test.go.erb index 97dfe64fa86e..93169502da64 100644 --- a/mmv1/third_party/terraform/services/firebasehosting/resource_firebase_hosting_channel_test.go.erb +++ b/mmv1/third_party/terraform/services/firebasehosting/resource_firebase_hosting_channel_test.go.erb @@ -75,7 +75,7 @@ func TestAccFirebaseHostingChannel_firebasehostingChannelUpdate(t *testing.T) { ResourceName: "google_firebase_hosting_channel.update", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl", "site_id", "channel_id"}, + ImportStateVerifyIgnore: []string{"ttl", "site_id", "channel_id", "labels", "terraform_labels"}, }, { Config: testAccFirebaseHostingChannel_firebasehostingChannelMultipleFields(context), @@ -84,7 +84,7 @@ func TestAccFirebaseHostingChannel_firebasehostingChannelUpdate(t *testing.T) { ResourceName: "google_firebase_hosting_channel.update", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl", "site_id", "channel_id"}, + ImportStateVerifyIgnore: []string{"ttl", "site_id", "channel_id", "labels", "terraform_labels"}, }, { Config: testAccFirebaseHostingChannel_firebasehostingChannelBasic(context), diff --git a/mmv1/third_party/terraform/services/gkebackup/resource_gke_backup_backup_plan_test.go.erb b/mmv1/third_party/terraform/services/gkebackup/resource_gke_backup_backup_plan_test.go.erb index ea1059fd8dac..47650b4288f7 100644 --- a/mmv1/third_party/terraform/services/gkebackup/resource_gke_backup_backup_plan_test.go.erb +++ b/mmv1/third_party/terraform/services/gkebackup/resource_gke_backup_backup_plan_test.go.erb @@ -30,6 +30,7 @@ func TestAccGKEBackupBackupPlan_update(t *testing.T) { ResourceName: "google_gke_backup_backup_plan.backupplan", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccGKEBackupBackupPlan_full(context), @@ -38,6 +39,7 @@ func TestAccGKEBackupBackupPlan_update(t *testing.T) { ResourceName: "google_gke_backup_backup_plan.backupplan", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -68,6 +70,9 @@ resource "google_gke_backup_backup_plan" "backupplan" { include_secrets = false all_namespaces = true } + labels = { + "some-key-1": "some-value-1" + } } `, context) } @@ -113,6 +118,9 @@ resource "google_gke_backup_backup_plan" "backupplan" { } } } + labels = { + "some-key-2": "some-value-2" + } } `, context) } diff --git a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_feature_test.go.erb b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_feature_test.go.erb index b9d2dce61ccf..11580f7c3c63 100644 --- a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_feature_test.go.erb +++ b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_feature_test.go.erb @@ -231,7 +231,7 @@ func TestAccGKEHubFeature_gkehubFeatureMciUpdate(t *testing.T) { ResourceName: "google_gke_hub_feature.feature", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"update_time"}, + ImportStateVerifyIgnore: []string{"update_time", "labels", "terraform_labels"}, }, }, }) @@ -366,7 +366,7 @@ func TestAccGKEHubFeature_gkehubFeatureMcsd(t *testing.T) { ResourceName: "google_gke_hub_feature.feature", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"project"}, + ImportStateVerifyIgnore: []string{"project", "labels", "terraform_labels"}, }, { Config: testAccGKEHubFeature_gkehubFeatureMcsdUpdate(context), @@ -375,6 +375,7 @@ func TestAccGKEHubFeature_gkehubFeatureMcsd(t *testing.T) { ResourceName: "google_gke_hub_feature.feature", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/healthcare/resource_healthcare_dicom_store_test.go b/mmv1/third_party/terraform/services/healthcare/resource_healthcare_dicom_store_test.go index 4b7584d72d1a..39dd582532da 100644 --- a/mmv1/third_party/terraform/services/healthcare/resource_healthcare_dicom_store_test.go +++ b/mmv1/third_party/terraform/services/healthcare/resource_healthcare_dicom_store_test.go @@ -91,9 +91,10 @@ func TestAccHealthcareDicomStore_basic(t *testing.T) { Config: testGoogleHealthcareDicomStore_basic(dicomStoreName, datasetName), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testGoogleHealthcareDicomStore_update(dicomStoreName, datasetName, pubsubTopic), @@ -102,17 +103,19 @@ func TestAccHealthcareDicomStore_basic(t *testing.T) { ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testGoogleHealthcareDicomStore_basic(dicomStoreName, datasetName), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/healthcare/resource_healthcare_fhir_store_test.go.erb b/mmv1/third_party/terraform/services/healthcare/resource_healthcare_fhir_store_test.go.erb index 16fe33421493..470d123a5cde 100644 --- a/mmv1/third_party/terraform/services/healthcare/resource_healthcare_fhir_store_test.go.erb +++ b/mmv1/third_party/terraform/services/healthcare/resource_healthcare_fhir_store_test.go.erb @@ -95,6 +95,7 @@ func TestAccHealthcareFhirStore_basic(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testGoogleHealthcareFhirStore_update(fhirStoreName, datasetName, pubsubTopic), @@ -106,6 +107,7 @@ func TestAccHealthcareFhirStore_basic(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testGoogleHealthcareFhirStore_basic(fhirStoreName, datasetName), @@ -114,6 +116,7 @@ func TestAccHealthcareFhirStore_basic(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/healthcare/resource_healthcare_hl7_v2_store_test.go.erb b/mmv1/third_party/terraform/services/healthcare/resource_healthcare_hl7_v2_store_test.go.erb index e3b6468de56f..aec48d059681 100644 --- a/mmv1/third_party/terraform/services/healthcare/resource_healthcare_hl7_v2_store_test.go.erb +++ b/mmv1/third_party/terraform/services/healthcare/resource_healthcare_hl7_v2_store_test.go.erb @@ -95,6 +95,7 @@ func TestAccHealthcareHl7V2Store_basic(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testGoogleHealthcareHl7V2Store_update(hl7_v2StoreName, datasetName, pubsubTopic), @@ -106,6 +107,7 @@ func TestAccHealthcareHl7V2Store_basic(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testGoogleHealthcareHl7V2Store_basic(hl7_v2StoreName, datasetName), @@ -114,6 +116,7 @@ func TestAccHealthcareHl7V2Store_basic(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networkconnectivity/resource_network_connectivity_service_connection_policies_test.go b/mmv1/third_party/terraform/services/networkconnectivity/resource_network_connectivity_service_connection_policies_test.go index 6344f761585b..0894eeab35d5 100644 --- a/mmv1/third_party/terraform/services/networkconnectivity/resource_network_connectivity_service_connection_policies_test.go +++ b/mmv1/third_party/terraform/services/networkconnectivity/resource_network_connectivity_service_connection_policies_test.go @@ -27,25 +27,28 @@ func TestAccNetworkConnectivityServiceConnectionPolicy_update(t *testing.T) { Config: testAccNetworkConnectivityServiceConnectionPolicy_basic(context), }, { - ResourceName: "google_network_connectivity_service_connection_policy.default", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_network_connectivity_service_connection_policy.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkConnectivityServiceConnectionPolicy_update(context), }, { - ResourceName: "google_network_connectivity_service_connection_policy.default", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_network_connectivity_service_connection_policy.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkConnectivityServiceConnectionPolicy_basic(context), }, { - ResourceName: "google_network_connectivity_service_connection_policy.default", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_network_connectivity_service_connection_policy.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_address_group_test.go b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_address_group_test.go index 106848e01d65..15d35521d161 100644 --- a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_address_group_test.go +++ b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_address_group_test.go @@ -24,17 +24,19 @@ func TestAccNetworkSecurityAddressGroups_update(t *testing.T) { Config: testAccNetworkSecurityAddressGroups_basic(addressGroupsName, projectName), }, { - ResourceName: "google_network_security_address_group.foobar", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_network_security_address_group.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkSecurityAddressGroups_update(addressGroupsName, projectName), }, { - ResourceName: "google_network_security_address_group.foobar", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_network_security_address_group.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/privateca/resource_privateca_ca_pool_test.go b/mmv1/third_party/terraform/services/privateca/resource_privateca_ca_pool_test.go index b288d24fb7cb..8466df22a917 100644 --- a/mmv1/third_party/terraform/services/privateca/resource_privateca_ca_pool_test.go +++ b/mmv1/third_party/terraform/services/privateca/resource_privateca_ca_pool_test.go @@ -26,7 +26,7 @@ func TestAccPrivatecaCaPool_privatecaCapoolUpdate(t *testing.T) { ResourceName: "google_privateca_ca_pool.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "labels", "terraform_labels"}, }, { Config: testAccPrivatecaCaPool_privatecaCapoolEnd(context), @@ -35,7 +35,7 @@ func TestAccPrivatecaCaPool_privatecaCapoolUpdate(t *testing.T) { ResourceName: "google_privateca_ca_pool.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "labels", "terraform_labels"}, }, { Config: testAccPrivatecaCaPool_privatecaCapoolStart(context), @@ -44,7 +44,7 @@ func TestAccPrivatecaCaPool_privatecaCapoolUpdate(t *testing.T) { ResourceName: "google_privateca_ca_pool.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "labels", "terraform_labels"}, }, }, }) @@ -233,7 +233,7 @@ func TestAccPrivatecaCaPool_privatecaCapoolEmptyBaseline(t *testing.T) { ResourceName: "google_privateca_ca_pool.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "labels", "terraform_labels"}, }, }, }) @@ -297,7 +297,7 @@ func TestAccPrivatecaCaPool_privatecaCapoolEmptyPublishingOptions(t *testing.T) ResourceName: "google_privateca_ca_pool.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/privateca/resource_privateca_certificate_authority_test.go b/mmv1/third_party/terraform/services/privateca/resource_privateca_certificate_authority_test.go index b43ca328de94..44dafcc2edd9 100644 --- a/mmv1/third_party/terraform/services/privateca/resource_privateca_certificate_authority_test.go +++ b/mmv1/third_party/terraform/services/privateca/resource_privateca_certificate_authority_test.go @@ -34,7 +34,7 @@ func TestAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityUpdate(t ResourceName: "google_privateca_certificate_authority.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool", "deletion_protection", "skip_grace_period"}, + ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool", "deletion_protection", "skip_grace_period", "labels", "terraform_labels"}, }, { Config: testAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityEnd(context), @@ -43,7 +43,7 @@ func TestAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityUpdate(t ResourceName: "google_privateca_certificate_authority.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool", "deletion_protection", "skip_grace_period"}, + ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool", "deletion_protection", "skip_grace_period", "labels", "terraform_labels"}, }, { Config: testAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityBasicRoot(context), @@ -52,7 +52,7 @@ func TestAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityUpdate(t ResourceName: "google_privateca_certificate_authority.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool", "deletion_protection", "skip_grace_period"}, + ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool", "deletion_protection", "skip_grace_period", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_test.go b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_test.go index 413f69d98c7e..839b498ebbfa 100644 --- a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_test.go +++ b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_test.go @@ -22,7 +22,11 @@ func TestAccDataSourceSecretManagerSecret_basic(t *testing.T) { { Config: testAccDataSourceSecretManagerSecret_basic(context), Check: resource.ComposeTestCheckFunc( - acctest.CheckDataSourceStateMatchesResourceState("data.google_secret_manager_secret.foo", "google_secret_manager_secret.bar"), + acctest.CheckDataSourceStateMatchesResourceStateWithIgnores( + "data.google_secret_manager_secret.foo", + "google_secret_manager_secret.bar", + map[string]struct{}{"zone": {}, "labels.%": {}, "terraform_labels.%": {}}, + ), ), }, }, diff --git a/mmv1/third_party/terraform/services/secretmanager/resource_secret_manager_secret_test.go.erb b/mmv1/third_party/terraform/services/secretmanager/resource_secret_manager_secret_test.go.erb index da8d40853c23..8afa9364d95c 100644 --- a/mmv1/third_party/terraform/services/secretmanager/resource_secret_manager_secret_test.go.erb +++ b/mmv1/third_party/terraform/services/secretmanager/resource_secret_manager_secret_test.go.erb @@ -29,7 +29,7 @@ func TestAccSecretManagerSecret_import(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, }, }) @@ -58,7 +58,7 @@ func TestAccSecretManagerSecret_cmek(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, }, }) @@ -126,7 +126,7 @@ func TestAccSecretManagerSecret_versionAliasesUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, { Config: testAccSecretManagerSecret_versionAliasesBasic(context), @@ -135,7 +135,7 @@ func TestAccSecretManagerSecret_versionAliasesUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, { Config: testAccSecretManagerSecret_versionAliasesUpdate(context), @@ -144,7 +144,7 @@ func TestAccSecretManagerSecret_versionAliasesUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, { Config: testAccSecretManagerSecret_basicWithSecretVersions(context), @@ -153,7 +153,7 @@ func TestAccSecretManagerSecret_versionAliasesUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, }, }) @@ -184,7 +184,7 @@ func TestAccSecretManagerSecret_userManagedCmekUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, { Config: testAccSecretMangerSecret_userManagedCmekUpdate(context), @@ -193,7 +193,7 @@ func TestAccSecretManagerSecret_userManagedCmekUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, { Config: testAccSecretMangerSecret_userManagedCmekUpdate2(context), @@ -202,7 +202,7 @@ func TestAccSecretManagerSecret_userManagedCmekUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, { Config: testAccSecretMangerSecret_userManagedCmekBasic(context), @@ -211,7 +211,7 @@ func TestAccSecretManagerSecret_userManagedCmekUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, }, }) @@ -241,7 +241,7 @@ func TestAccSecretManagerSecret_automaticCmekUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, { Config: testAccSecretMangerSecret_automaticCmekUpdate(context), @@ -250,7 +250,7 @@ func TestAccSecretManagerSecret_automaticCmekUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, { Config: testAccSecretMangerSecret_automaticCmekUpdate2(context), @@ -259,7 +259,7 @@ func TestAccSecretManagerSecret_automaticCmekUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, { Config: testAccSecretMangerSecret_automaticCmekBasic(context), @@ -268,7 +268,7 @@ func TestAccSecretManagerSecret_automaticCmekUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_cluster_test.go.erb b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_cluster_test.go.erb index e544f9085579..57f5de6e6381 100644 --- a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_cluster_test.go.erb @@ -28,7 +28,7 @@ func TestAccWorkstationsWorkstationCluster_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "annotations"}, + ImportStateVerifyIgnore: []string{"etag", "annotations", "labels", "terraform_labels"}, }, { Config: testAccWorkstationsWorkstationCluster_update(context), @@ -37,7 +37,7 @@ func TestAccWorkstationsWorkstationCluster_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "annotations"}, + ImportStateVerifyIgnore: []string{"etag", "annotations", "labels", "terraform_labels"}, }, }, }) @@ -62,7 +62,7 @@ func TestAccWorkstationsWorkstationCluster_Private_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "annotations"}, + ImportStateVerifyIgnore: []string{"etag", "annotations", "labels", "terraform_labels"}, }, { Config: testAccWorkstationsWorkstationCluster_private_update(context), @@ -71,7 +71,7 @@ func TestAccWorkstationsWorkstationCluster_Private_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "annotations"}, + ImportStateVerifyIgnore: []string{"etag", "annotations", "labels", "terraform_labels"}, }, }, }) From 4f06425b923191040e0ce5c3213b14ae311a314f Mon Sep 17 00:00:00 2001 From: bobyu-google Date: Wed, 20 Sep 2023 13:10:57 -0700 Subject: [PATCH 41/67] Default ReconcileConnections from service attachment API (#9026) --- mmv1/products/compute/ServiceAttachment.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mmv1/products/compute/ServiceAttachment.yaml b/mmv1/products/compute/ServiceAttachment.yaml index 2eb28eac0dce..9b52db126f15 100644 --- a/mmv1/products/compute/ServiceAttachment.yaml +++ b/mmv1/products/compute/ServiceAttachment.yaml @@ -208,12 +208,10 @@ properties: create. - !ruby/object:Api::Type::Boolean name: reconcileConnections - default_value: true + default_from_api: true send_empty_value: true description: | This flag determines whether a consumer accept/reject list change can reconcile the statuses of existing ACCEPTED or REJECTED PSC endpoints. If false, connection policy update will only affect existing PENDING PSC endpoints. Existing ACCEPTED/REJECTED endpoints will remain untouched regardless how the connection policy is modified . If true, update will affect both PENDING and ACCEPTED/REJECTED PSC endpoints. For example, an ACCEPTED PSC endpoint will be moved to REJECTED if its project is added to the reject list. - - For newly created service attachment, this boolean defaults to true. From 4a03c32a355fb8e6ae7f306bbe67641e42ce6d1f Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Wed, 20 Sep 2023 15:39:37 -0500 Subject: [PATCH 42/67] remove container network policy provider default (#8965) --- .../services/container/resource_container_cluster.go.erb | 3 +-- .../terraform/website/docs/r/container_cluster.html.markdown | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb index 4c59e9675260..a8f50aab16a4 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb @@ -1368,11 +1368,10 @@ func ResourceContainerCluster() *schema.Resource { }, "provider": { Type: schema.TypeString, - Default: "PROVIDER_UNSPECIFIED", Optional: true, ValidateFunc: validation.StringInSlice([]string{"PROVIDER_UNSPECIFIED", "CALICO"}, false), DiffSuppressFunc: tpgresource.EmptyOrDefaultStringSuppress("PROVIDER_UNSPECIFIED"), - Description: `The selected network policy provider. Defaults to PROVIDER_UNSPECIFIED.`, + Description: `The selected network policy provider.`, }, }, }, diff --git a/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown b/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown index 5d8e237d4820..d29897479d2a 100644 --- a/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown @@ -454,8 +454,7 @@ addons_config { * `enabled` - (DEPRECATED) Enable Binary Authorization for this cluster. Deprecated in favor of `evaluation_mode`. * `evaluation_mode` - (Optional) Mode of operation for Binary Authorization policy evaluation. Valid values are `DISABLED` - and `PROJECT_SINGLETON_POLICY_ENFORCE`. `PROJECT_SINGLETON_POLICY_ENFORCE` is functionally equivalent to the - deprecated `enable_binary_authorization` parameter being set to `true`. + and `PROJECT_SINGLETON_POLICY_ENFORCE`. The `service_external_ips_config` block supports: From 7bef6de2e31ca58916956b4efa0c3423d64f0131 Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Thu, 21 Sep 2023 11:59:48 -0500 Subject: [PATCH 43/67] Change container node pool defaults (#8967) --- .../terraform/services/container/node_config.go.erb | 2 +- .../container/resource_container_node_pool.go.erb | 8 ++++---- .../container/resource_container_node_pool_test.go.erb | 1 + .../website/docs/r/container_node_pool.html.markdown | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/mmv1/third_party/terraform/services/container/node_config.go.erb b/mmv1/third_party/terraform/services/container/node_config.go.erb index 8db029040fad..8872ef39f07b 100644 --- a/mmv1/third_party/terraform/services/container/node_config.go.erb +++ b/mmv1/third_party/terraform/services/container/node_config.go.erb @@ -32,8 +32,8 @@ func schemaLoggingVariant() *schema.Schema { return &schema.Schema{ Type: schema.TypeString, Optional: true, + Computed: true, Description: `Type of logging agent that is used as the default value for node pools in the cluster. Valid values include DEFAULT and MAX_THROUGHPUT.`, - Default: "DEFAULT", ValidateFunc: validation.StringInSlice([]string{"DEFAULT", "MAX_THROUGHPUT"}, false), } } 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 648323e612b7..606a39f865d3 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 @@ -293,15 +293,15 @@ var schemaNodePool = map[string]*schema.Schema{ "auto_repair": { Type: schema.TypeBool, Optional: true, - Default: false, - Description: `Whether the nodes will be automatically repaired.`, + Default: true, + Description: `Whether the nodes will be automatically repaired. Enabled by default.`, }, "auto_upgrade": { Type: schema.TypeBool, Optional: true, - Default: false, - Description: `Whether the nodes will be automatically upgraded.`, + Default: true, + Description: `Whether the nodes will be automatically upgraded. Enabled by default.`, }, }, }, 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 0fb6f5ede53a..1f902075ec03 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 @@ -2614,6 +2614,7 @@ resource "google_container_node_pool" "with_kubelet_config" { "https://www.googleapis.com/auth/logging.write", "https://www.googleapis.com/auth/monitoring", ] + logging_variant = "DEFAULT" } } `, cluster, np, policy, quota, period, podPidsLimit) 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 523d2684a41f..bbf814662a88 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 @@ -201,9 +201,9 @@ cluster. The `management` block supports: -* `auto_repair` - (Optional) Whether the nodes will be automatically repaired. +* `auto_repair` - (Optional) Whether the nodes will be automatically repaired. Enabled by default. -* `auto_upgrade` - (Optional) Whether the nodes will be automatically upgraded. +* `auto_upgrade` - (Optional) Whether the nodes will be automatically upgraded. Enabled by default. The `network_config` block supports: From a98d8fba163e0c1f4ffd020465139aafe8d89f15 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Thu, 21 Sep 2023 11:09:46 -0700 Subject: [PATCH 44/67] Fix failed tests related to google_service_networking_connection (#8904) * Bootstrap service networking connection * Revert tests * Rename network names * Modify tests * Fix tests * Catch the error when deleteConnection fails * Fix test TestAccVertexAIIndexEndpoint_updated * Fix test TestAccAlloydbInstance_createInstanceWithNetworkConfigAndAllocatedIPRange * Fix test --- .../cloudbuild/BitbucketServerConfig.yaml | 2 - .../connectionprofile.yaml | 1 + mmv1/products/tpu/Node.yaml | 1 + mmv1/products/vertexai/IndexEndpoint.yaml | 2 - ...bucket_server_config_peered_network.tf.erb | 10 +- .../terraform/examples/tpu_node_full.tf.erb | 8 +- .../vertex_ai_endpoint_network.tf.erb | 8 +- .../examples/vertex_ai_index_endpoint.tf.erb | 8 +- .../terraform/acctest/bootstrap_test_utils.go | 131 ++++++++++++ .../alloydb/resource_alloydb_backup_test.go | 108 ++++------ .../resource_alloydb_cluster_restore_test.go | 184 +++------------- .../alloydb/resource_alloydb_instance_test.go | 193 ++++++----------- ...esource_cloudbuild_worker_pool_test.go.erb | 21 +- .../resource_cloudids_endpoint_test.go | 36 +--- ...gration_service_connection_profile_test.go | 67 ++++++ .../resource_memcache_instance_test.go | 42 +--- .../resource_service_networking_connection.go | 37 ++-- ...urce_service_networking_connection_test.go | 10 +- .../resource_sql_database_instance_test.go | 197 ++++++------------ .../resource_vertex_ai_endpoint_test.go | 36 +--- .../resource_vertex_ai_index_endpoint_test.go | 31 +-- 21 files changed, 450 insertions(+), 683 deletions(-) diff --git a/mmv1/products/cloudbuild/BitbucketServerConfig.yaml b/mmv1/products/cloudbuild/BitbucketServerConfig.yaml index d8b2f2763209..bd8bdd316f70 100644 --- a/mmv1/products/cloudbuild/BitbucketServerConfig.yaml +++ b/mmv1/products/cloudbuild/BitbucketServerConfig.yaml @@ -64,8 +64,6 @@ examples: config_id: 'bbs-config' network_name: 'vpc-network' global_address_name: 'private-ip-alloc' - test_vars_overrides: - network_name: 'acctest.BootstrapSharedTestNetwork(t, "peered-network")' custom_code: !ruby/object:Provider::Terraform::CustomCode encoder: templates/terraform/encoders/cloudbuild_bitbucketserver_config.go.erb post_create: templates/terraform/post_create/cloudbuild_bitbucketserver_config.go.erb diff --git a/mmv1/products/databasemigrationservice/connectionprofile.yaml b/mmv1/products/databasemigrationservice/connectionprofile.yaml index f9383453a7f0..535cbc4cee92 100644 --- a/mmv1/products/databasemigrationservice/connectionprofile.yaml +++ b/mmv1/products/databasemigrationservice/connectionprofile.yaml @@ -87,6 +87,7 @@ examples: profile: 'my-profileid' global_address_name: 'private-ip-alloc' network_name: 'vpc-network' + skip_test: true parameters: - !ruby/object:Api::Type::String name: 'connectionProfileId' diff --git a/mmv1/products/tpu/Node.yaml b/mmv1/products/tpu/Node.yaml index c1d08907589e..cd8e4a1136f7 100644 --- a/mmv1/products/tpu/Node.yaml +++ b/mmv1/products/tpu/Node.yaml @@ -36,6 +36,7 @@ examples: vars: node_name: 'test-tpu' global_address_name: 'my-global-address' + network_name: 'tpu-node-network' custom_code: !ruby/object:Provider::Terraform::CustomCode constants: 'templates/terraform/constants/tpu_node.erb' custom_diff: [ diff --git a/mmv1/products/vertexai/IndexEndpoint.yaml b/mmv1/products/vertexai/IndexEndpoint.yaml index ff10d04347eb..1fd415896a8e 100644 --- a/mmv1/products/vertexai/IndexEndpoint.yaml +++ b/mmv1/products/vertexai/IndexEndpoint.yaml @@ -51,8 +51,6 @@ examples: vars: address_name: "address-name" network_name: "network-name" - test_vars_overrides: - network_name: 'acctest.BootstrapSharedTestNetwork(t, "vertex-ai-index-endpoint")' - !ruby/object:Provider::Terraform::Examples name: "vertex_ai_index_endpoint_with_public_endpoint" primary_resource_id: "index_endpoint" diff --git a/mmv1/templates/terraform/examples/cloudbuild_bitbucket_server_config_peered_network.tf.erb b/mmv1/templates/terraform/examples/cloudbuild_bitbucket_server_config_peered_network.tf.erb index f59bc3278d77..bedb109901ee 100644 --- a/mmv1/templates/terraform/examples/cloudbuild_bitbucket_server_config_peered_network.tf.erb +++ b/mmv1/templates/terraform/examples/cloudbuild_bitbucket_server_config_peered_network.tf.erb @@ -4,8 +4,8 @@ resource "google_project_service" "servicenetworking" { service = "servicenetworking.googleapis.com" disable_on_destroy = false } - -data "google_compute_network" "vpc_network" { + +resource "google_compute_network" "vpc_network" { name = "<%= ctx[:vars]['network_name'] %>" depends_on = [google_project_service.servicenetworking] } @@ -15,11 +15,11 @@ resource "google_compute_global_address" "private_ip_alloc" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = data.google_compute_network.vpc_network.id + network = google_compute_network.vpc_network.id } resource "google_service_networking_connection" "default" { - network = data.google_compute_network.vpc_network.id + network = google_compute_network.vpc_network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] depends_on = [google_project_service.servicenetworking] @@ -36,7 +36,7 @@ resource "google_cloudbuild_bitbucket_server_config" "<%= ctx[:primary_resource_ } username = "test" api_key = "" - peered_network = replace(data.google_compute_network.vpc_network.id, data.google_project.project.name, data.google_project.project.number) + peered_network = replace(google_compute_network.vpc_network.id, data.google_project.project.name, data.google_project.project.number) ssl_ca = "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n" depends_on = [google_service_networking_connection.default] } diff --git a/mmv1/templates/terraform/examples/tpu_node_full.tf.erb b/mmv1/templates/terraform/examples/tpu_node_full.tf.erb index 0f88b33e3210..cebe528b24ac 100644 --- a/mmv1/templates/terraform/examples/tpu_node_full.tf.erb +++ b/mmv1/templates/terraform/examples/tpu_node_full.tf.erb @@ -34,8 +34,8 @@ resource "google_tpu_node" "<%= ctx[:primary_resource_id] %>" { } } -data "google_compute_network" "network" { - name = "default" +resource "google_compute_network" "network" { + name = "<%= ctx[:vars]['network_name'] %>" } resource "google_compute_global_address" "service_range" { @@ -43,11 +43,11 @@ resource "google_compute_global_address" "service_range" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = data.google_compute_network.network.id + network = google_compute_network.network.id } resource "google_service_networking_connection" "private_service_connection" { - network = data.google_compute_network.network.id + network = google_compute_network.network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.service_range.name] } \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/vertex_ai_endpoint_network.tf.erb b/mmv1/templates/terraform/examples/vertex_ai_endpoint_network.tf.erb index abe0b82b3080..752c25264502 100644 --- a/mmv1/templates/terraform/examples/vertex_ai_endpoint_network.tf.erb +++ b/mmv1/templates/terraform/examples/vertex_ai_endpoint_network.tf.erb @@ -7,7 +7,7 @@ resource "google_vertex_ai_endpoint" "<%= ctx[:primary_resource_id] %>" { labels = { label-one = "value-one" } - network = "projects/${data.google_project.project.number}/global/networks/${data.google_compute_network.vertex_network.name}" + network = "projects/${data.google_project.project.number}/global/networks/${google_compute_network.vertex_network.name}" encryption_spec { kms_key_name = "<%= ctx[:vars]['kms_key_name'] %>" } @@ -17,7 +17,7 @@ resource "google_vertex_ai_endpoint" "<%= ctx[:primary_resource_id] %>" { } resource "google_service_networking_connection" "vertex_vpc_connection" { - network = data.google_compute_network.vertex_network.id + network = google_compute_network.vertex_network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.vertex_range.name] } @@ -27,10 +27,10 @@ resource "google_compute_global_address" "vertex_range" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 24 - network = data.google_compute_network.vertex_network.id + network = google_compute_network.vertex_network.id } -data "google_compute_network" "vertex_network" { +resource "google_compute_network" "vertex_network" { name = "<%= ctx[:vars]['network_name'] %>" } diff --git a/mmv1/templates/terraform/examples/vertex_ai_index_endpoint.tf.erb b/mmv1/templates/terraform/examples/vertex_ai_index_endpoint.tf.erb index c15e65269e41..2c0b78e4e339 100644 --- a/mmv1/templates/terraform/examples/vertex_ai_index_endpoint.tf.erb +++ b/mmv1/templates/terraform/examples/vertex_ai_index_endpoint.tf.erb @@ -5,14 +5,14 @@ resource "google_vertex_ai_index_endpoint" "<%= ctx[:primary_resource_id] %>" { labels = { label-one = "value-one" } - network = "projects/${data.google_project.project.number}/global/networks/${data.google_compute_network.vertex_network.name}" + network = "projects/${data.google_project.project.number}/global/networks/${google_compute_network.vertex_network.name}" depends_on = [ google_service_networking_connection.vertex_vpc_connection ] } resource "google_service_networking_connection" "vertex_vpc_connection" { - network = data.google_compute_network.vertex_network.id + network = google_compute_network.vertex_network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.vertex_range.name] } @@ -22,10 +22,10 @@ resource "google_compute_global_address" "vertex_range" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 24 - network = data.google_compute_network.vertex_network.id + network = google_compute_network.vertex_network.id } -data "google_compute_network" "vertex_network" { +resource "google_compute_network" "vertex_network" { name = "<%= ctx[:vars]['network_name'] %>" } diff --git a/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go b/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go index 9f14e6d713c8..6e7fd8587405 100644 --- a/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go +++ b/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go @@ -13,6 +13,7 @@ import ( tpgcompute "github.com/hashicorp/terraform-provider-google/google/services/compute" "github.com/hashicorp/terraform-provider-google/google/services/privateca" "github.com/hashicorp/terraform-provider-google/google/services/resourcemanager" + tpgservicenetworking "github.com/hashicorp/terraform-provider-google/google/services/servicenetworking" "github.com/hashicorp/terraform-provider-google/google/services/sql" "github.com/hashicorp/terraform-provider-google/google/tpgiamresource" "github.com/hashicorp/terraform-provider-google/google/tpgresource" @@ -23,6 +24,7 @@ import ( cloudresourcemanager "google.golang.org/api/cloudresourcemanager/v1" iam "google.golang.org/api/iam/v1" "google.golang.org/api/iamcredentials/v1" + "google.golang.org/api/servicenetworking/v1" "google.golang.org/api/serviceusage/v1" sqladmin "google.golang.org/api/sqladmin/v1beta4" ) @@ -354,6 +356,135 @@ func BootstrapSharedTestNetwork(t *testing.T, testId string) string { return network.Name } +const SharedTestGlobalAddressPrefix = "tf-bootstrap-addr-" + +func BootstrapSharedTestGlobalAddress(t *testing.T, testId, networkId string) string { + project := envvar.GetTestProjectFromEnv() + addressName := SharedTestGlobalAddressPrefix + testId + + config := BootstrapConfig(t) + if config == nil { + return "" + } + + log.Printf("[DEBUG] Getting shared test global address %q", addressName) + _, err := config.NewComputeClient(config.UserAgent).GlobalAddresses.Get(project, addressName).Do() + if err != nil && transport_tpg.IsGoogleApiErrorWithCode(err, 404) { + log.Printf("[DEBUG] Global address %q not found, bootstrapping", addressName) + url := fmt.Sprintf("%sprojects/%s/global/addresses", config.ComputeBasePath, project) + netObj := map[string]interface{}{ + "name": addressName, + "address_type": "INTERNAL", + "purpose": "VPC_PEERING", + "prefix_length": 16, + "network": networkId, + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: project, + RawURL: url, + UserAgent: config.UserAgent, + Body: netObj, + Timeout: 4 * time.Minute, + }) + if err != nil { + t.Fatalf("Error bootstrapping shared test global address %q: %s", addressName, err) + } + + log.Printf("[DEBUG] Waiting for global address creation to finish") + err = tpgcompute.ComputeOperationWaitTime(config, res, project, "Error bootstrapping shared test global address", config.UserAgent, 4*time.Minute) + if err != nil { + t.Fatalf("Error bootstrapping shared test global address %q: %s", addressName, err) + } + } + + address, err := config.NewComputeClient(config.UserAgent).GlobalAddresses.Get(project, addressName).Do() + if err != nil { + t.Errorf("Error getting shared test global address %q: %s", addressName, err) + } + if address == nil { + t.Fatalf("Error getting shared test global address %q: is nil", addressName) + } + return address.Name +} + +// BootstrapSharedServiceNetworkingConnection will create a shared network +// if it hasn't been created in the test project, a global address +// if it hasn't been created in the test project, and a service networking connection +// if it hasn't been created in the test project. +// +// BootstrapSharedServiceNetworkingConnection returns a persistent compute network name +// for a test or set of tests. +// +// To delete a service networking conneciton, all of the service instances that use that connection +// must be deleted first. After the service instances are deleted, some service producers delay the deletion +// utnil a waiting period has passed. For example, after four days that you delete a SQL instance, +// the service networking connection can be deleted. +// That is the reason to use the shared service networking connection for thest resources. +// https://cloud.google.com/vpc/docs/configure-private-services-access#removing-connection +// +// testId specifies the test for which a shared network and a gobal address are used/initialized. +func BootstrapSharedServiceNetworkingConnection(t *testing.T, testId string) string { + parentService := "services/servicenetworking.googleapis.com" + project := envvar.GetTestProjectFromEnv() + projectNumber := envvar.GetTestProjectNumberFromEnv() + + config := BootstrapConfig(t) + if config == nil { + return "" + } + + networkName := BootstrapSharedTestNetwork(t, testId) + networkId := fmt.Sprintf("projects/%v/global/networks/%v", projectNumber, networkName) + globalAddressName := BootstrapSharedTestGlobalAddress(t, testId, networkId) + + readCall := config.NewServiceNetworkingClient(config.UserAgent).Services.Connections.List(parentService).Network(networkId) + if config.UserProjectOverride { + readCall.Header().Add("X-Goog-User-Project", project) + } + response, err := readCall.Do() + if err != nil { + t.Errorf("Error getting shared test service networking connection: %s", err) + } + + var connection *servicenetworking.Connection + for _, c := range response.Connections { + if c.Network == networkId { + connection = c + break + } + } + + if connection == nil { + log.Printf("[DEBUG] Service networking connection not found, bootstrapping") + + connection := &servicenetworking.Connection{ + Network: networkId, + ReservedPeeringRanges: []string{globalAddressName}, + } + + createCall := config.NewServiceNetworkingClient(config.UserAgent).Services.Connections.Create(parentService, connection) + if config.UserProjectOverride { + createCall.Header().Add("X-Goog-User-Project", project) + } + op, err := createCall.Do() + if err != nil { + t.Fatalf("Error bootstrapping shared test service networking connection: %s", err) + } + + log.Printf("[DEBUG] Waiting for service networking connection creation to finish") + if err := tpgservicenetworking.ServiceNetworkingOperationWaitTime(config, op, "Create Service Networking Connection", config.UserAgent, project, 4*time.Minute); err != nil { + t.Fatalf("Error bootstrapping shared test service networking connection: %s", err) + } + } + + log.Printf("[DEBUG] Getting shared test service networking connection") + + return networkName +} + var SharedServicePerimeterProjectPrefix = "tf-bootstrap-sp-" func BootstrapServicePerimeterProjects(t *testing.T, desiredProjects int) []*cloudresourcemanager.Project { diff --git a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_backup_test.go b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_backup_test.go index 4223e1a81555..6f5c9c6c8616 100644 --- a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_backup_test.go +++ b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_backup_test.go @@ -12,7 +12,7 @@ func TestAccAlloydbBackup_update(t *testing.T) { random_suffix := acctest.RandString(t, 10) context := map[string]interface{}{ - "network_name": "tf-test-alloydb-network" + random_suffix, + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "alloydb-backup-update-1"), "random_suffix": random_suffix, } @@ -22,7 +22,7 @@ func TestAccAlloydbBackup_update(t *testing.T) { CheckDestroy: testAccCheckAlloydbBackupDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccAlloydbBackup_alloydbBackupFullExample(context), + Config: testAccAlloydbBackup_alloydbBackupBasic(context), }, { ResourceName: "google_alloydb_backup.default", @@ -43,8 +43,7 @@ func TestAccAlloydbBackup_update(t *testing.T) { }) } -// Updates "label" field from testAccAlloydbBackup_alloydbBackupFullExample -func testAccAlloydbBackup_update(context map[string]interface{}) string { +func testAccAlloydbBackup_alloydbBackupBasic(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_alloydb_backup" "default" { location = "us-central1" @@ -53,8 +52,7 @@ resource "google_alloydb_backup" "default" { description = "example description" labels = { - "label" = "updated_key" - "label2" = "updated_key2" + "label" = "key" } depends_on = [google_alloydb_instance.default] } @@ -62,32 +60,50 @@ resource "google_alloydb_backup" "default" { resource "google_alloydb_cluster" "default" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id } resource "google_alloydb_instance" "default" { cluster = google_alloydb_cluster.default.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" +} + +data "google_compute_network" "default" { + name = "%{network_name}" +} +`, context) +} + +// Updates "label" field +func testAccAlloydbBackup_update(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_alloydb_backup" "default" { + location = "us-central1" + backup_id = "tf-test-alloydb-backup%{random_suffix}" + cluster_name = google_alloydb_cluster.default.name - depends_on = [google_service_networking_connection.vpc_connection] + description = "example description" + labels = { + "label" = "updated_key" + "label2" = "updated_key2" + } + depends_on = [google_alloydb_instance.default] } -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = google_compute_network.default.id +resource "google_alloydb_cluster" "default" { + cluster_id = "tf-test-alloydb-cluster%{random_suffix}" + location = "us-central1" + network = data.google_compute_network.default.id } -resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] +resource "google_alloydb_instance" "default" { + cluster = google_alloydb_cluster.default.name + instance_id = "tf-test-alloydb-instance%{random_suffix}" + instance_type = "PRIMARY" } -resource "google_compute_network" "default" { +data "google_compute_network" "default" { name = "%{network_name}" } `, context) @@ -99,7 +115,7 @@ func TestAccAlloydbBackup_createBackupWithMandatoryFields(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), - "network_name": "tf-test-" + acctest.RandString(t, 10), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "alloydb-backup-mandatory-1"), } acctest.VcrTest(t, resource.TestCase{ @@ -126,12 +142,12 @@ resource "google_alloydb_backup" "default" { resource "google_alloydb_cluster" "default" { location = "us-central1" cluster_id = "tf-test-alloydb-cluster%{random_suffix}" - network = google_compute_network.default.id + network = data.google_compute_network.default.id } data "google_project" "project" { } -resource "google_compute_network" "default" { +data "google_compute_network" "default" { name = "%{network_name}" } @@ -139,32 +155,6 @@ resource "google_alloydb_instance" "default" { cluster = google_alloydb_cluster.default.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - - depends_on = [google_service_networking_connection.vpc_connection] -} - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = google_compute_network.default.id - lifecycle { - ignore_changes = [ - address, - creation_timestamp, - id, - network, - project, - self_link - ] - } -} - -resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } `, context) } @@ -173,7 +163,7 @@ func TestAccAlloydbBackup_usingCMEK(t *testing.T) { t.Parallel() context := map[string]interface{}{ - "network_name": "tf-test-" + acctest.RandString(t, 10), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "alloydb-backup-cmek-1"), "random_suffix": acctest.RandString(t, 10), "key_name": "tf-test-key-" + acctest.RandString(t, 10), } @@ -216,32 +206,16 @@ resource "google_alloydb_backup" "default" { resource "google_alloydb_cluster" "default" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id } resource "google_alloydb_instance" "default" { cluster = google_alloydb_cluster.default.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - - depends_on = [google_service_networking_connection.vpc_connection] -} - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } -resource "google_compute_network" "default" { +data "google_compute_network" "default" { name = "%{network_name}" } data "google_project" "project" {} diff --git a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_restore_test.go b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_restore_test.go index 9e3d209581e0..5288d8ea62f8 100644 --- a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_restore_test.go +++ b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_restore_test.go @@ -19,7 +19,7 @@ func TestAccAlloydbCluster_restore(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), - "network_name": "tf-test-" + acctest.RandString(t, 10), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "alloydb-instance-restore-1"), } acctest.VcrTest(t, resource.TestCase{ @@ -86,15 +86,13 @@ func testAccAlloydbClusterAndInstanceAndBackup(context map[string]interface{}) s resource "google_alloydb_cluster" "source" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id } resource "google_alloydb_instance" "source" { cluster = google_alloydb_cluster.source.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_backup" "default" { @@ -107,23 +105,9 @@ resource "google_alloydb_backup" "default" { data "google_project" "project" {} -resource "google_compute_network" "default" { +data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -133,15 +117,13 @@ func testAccAlloydbClusterAndInstanceAndBackup_OnlyOneSourceAllowed(context map[ resource "google_alloydb_cluster" "source" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id } resource "google_alloydb_instance" "source" { cluster = google_alloydb_cluster.source.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_backup" "default" { @@ -155,7 +137,7 @@ resource "google_alloydb_backup" "default" { resource "google_alloydb_cluster" "restored" { cluster_id = "tf-test-alloydb-backup-restored-cluster-%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id restore_backup_source { backup_name = google_alloydb_backup.default.name } @@ -171,23 +153,9 @@ resource "google_alloydb_cluster" "restored" { data "google_project" "project" {} -resource "google_compute_network" "default" { +data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -197,15 +165,13 @@ func testAccAlloydbClusterAndInstanceAndBackup_SourceClusterAndPointInTimeRequir resource "google_alloydb_cluster" "source" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id } resource "google_alloydb_instance" "source" { cluster = google_alloydb_cluster.source.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_backup" "default" { @@ -219,7 +185,7 @@ resource "google_alloydb_backup" "default" { resource "google_alloydb_cluster" "restored" { cluster_id = "tf-test-alloydb-backup-restored-cluster-%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id restore_continuous_backup_source { cluster = google_alloydb_cluster.source.name @@ -232,23 +198,9 @@ resource "google_alloydb_cluster" "restored" { data "google_project" "project" {} -resource "google_compute_network" "default" { +data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -257,15 +209,13 @@ func testAccAlloydbClusterAndInstanceAndBackup_RestoredFromBackup(context map[st resource "google_alloydb_cluster" "source" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id } resource "google_alloydb_instance" "source" { cluster = google_alloydb_cluster.source.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_backup" "default" { @@ -279,7 +229,7 @@ resource "google_alloydb_backup" "default" { resource "google_alloydb_cluster" "restored_from_backup" { cluster_id = "tf-test-alloydb-backup-restored-cluster-%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id restore_backup_source { backup_name = google_alloydb_backup.default.name } @@ -291,23 +241,9 @@ resource "google_alloydb_cluster" "restored_from_backup" { data "google_project" "project" {} -resource "google_compute_network" "default" { +data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -318,15 +254,13 @@ func testAccAlloydbClusterAndInstanceAndBackup_RestoredFromBackupAndRestoredFrom resource "google_alloydb_cluster" "source" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id } resource "google_alloydb_instance" "source" { cluster = google_alloydb_cluster.source.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_backup" "default" { @@ -340,7 +274,7 @@ resource "google_alloydb_backup" "default" { resource "google_alloydb_cluster" "restored_from_backup" { cluster_id = "tf-test-alloydb-backup-restored-cluster-%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id restore_backup_source { backup_name = google_alloydb_backup.default.name } @@ -353,7 +287,7 @@ resource "google_alloydb_cluster" "restored_from_backup" { resource "google_alloydb_cluster" "restored_from_point_in_time" { cluster_id = "tf-test-alloydb-pitr-restored-cluster-%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id restore_continuous_backup_source { cluster = google_alloydb_cluster.source.name point_in_time = google_alloydb_backup.default.update_time @@ -366,23 +300,9 @@ resource "google_alloydb_cluster" "restored_from_point_in_time" { data "google_project" "project" {} -resource "google_compute_network" "default" { +data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -393,15 +313,13 @@ func testAccAlloydbClusterAndInstanceAndBackup_RestoredFromBackupAndRestoredFrom resource "google_alloydb_cluster" "source" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id } resource "google_alloydb_instance" "source" { cluster = google_alloydb_cluster.source.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_backup" "default" { @@ -415,7 +333,7 @@ resource "google_alloydb_backup" "default" { resource "google_alloydb_cluster" "restored_from_backup" { cluster_id = "tf-test-alloydb-backup-restored-cluster-%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id restore_backup_source { backup_name = google_alloydb_backup.default.name } @@ -433,7 +351,7 @@ resource "google_alloydb_cluster" "restored_from_backup" { resource "google_alloydb_cluster" "restored_from_point_in_time" { cluster_id = "tf-test-alloydb-pitr-restored-cluster-%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id restore_continuous_backup_source { cluster = google_alloydb_cluster.source.name point_in_time = google_alloydb_backup.default.update_time @@ -451,23 +369,9 @@ resource "google_alloydb_cluster" "restored_from_point_in_time" { data "google_project" "project" {} -resource "google_compute_network" "default" { +data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -478,15 +382,13 @@ func testAccAlloydbClusterAndInstanceAndBackup_RestoredFromBackupAndRestoredFrom resource "google_alloydb_cluster" "source" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id } resource "google_alloydb_instance" "source" { cluster = google_alloydb_cluster.source.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_backup" "default" { @@ -508,7 +410,7 @@ resource "google_alloydb_backup" "default2" { resource "google_alloydb_cluster" "restored_from_backup" { cluster_id = "tf-test-alloydb-backup-restored-cluster-%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id restore_backup_source { backup_name = google_alloydb_backup.default2.name } @@ -528,7 +430,7 @@ resource "google_alloydb_cluster" "restored_from_backup" { resource "google_alloydb_cluster" "restored_from_point_in_time" { cluster_id = "tf-test-alloydb-pitr-restored-cluster-%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id restore_continuous_backup_source { cluster = google_alloydb_cluster.restored_from_backup.name point_in_time = google_alloydb_backup.default.update_time @@ -546,23 +448,9 @@ resource "google_alloydb_cluster" "restored_from_point_in_time" { data "google_project" "project" {} -resource "google_compute_network" "default" { +data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -573,15 +461,13 @@ func testAccAlloydbClusterAndInstanceAndBackup_RestoredFromBackupAndRestoredFrom resource "google_alloydb_cluster" "source" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id } resource "google_alloydb_instance" "source" { cluster = google_alloydb_cluster.source.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_backup" "default" { @@ -595,7 +481,7 @@ resource "google_alloydb_backup" "default" { resource "google_alloydb_cluster" "restored_from_backup" { cluster_id = "tf-test-alloydb-backup-restored-cluster-%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id restore_backup_source { backup_name = google_alloydb_backup.default.name } @@ -604,7 +490,7 @@ resource "google_alloydb_cluster" "restored_from_backup" { resource "google_alloydb_cluster" "restored_from_point_in_time" { cluster_id = "tf-test-alloydb-pitr-restored-cluster-%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id restore_continuous_backup_source { cluster = google_alloydb_cluster.source.name point_in_time = google_alloydb_backup.default.update_time @@ -613,22 +499,8 @@ resource "google_alloydb_cluster" "restored_from_point_in_time" { data "google_project" "project" {} -resource "google_compute_network" "default" { +data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } diff --git a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_instance_test.go b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_instance_test.go index 98410de5431f..4d5d4f811568 100644 --- a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_instance_test.go +++ b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_instance_test.go @@ -1,10 +1,12 @@ package alloydb_test import ( + "fmt" "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 TestAccAlloydbInstance_update(t *testing.T) { @@ -12,8 +14,8 @@ func TestAccAlloydbInstance_update(t *testing.T) { random_suffix := acctest.RandString(t, 10) context := map[string]interface{}{ + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "alloydb-instance-update-1"), "random_suffix": random_suffix, - "network_name": "tf-test-alloydb-network" + random_suffix, } acctest.VcrTest(t, resource.TestCase{ @@ -22,7 +24,7 @@ func TestAccAlloydbInstance_update(t *testing.T) { CheckDestroy: testAccCheckAlloydbInstanceDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccAlloydbInstance_alloydbInstanceBasicExample(context), + Config: testAccAlloydbInstance_alloydbInstanceBasic(context), }, { ResourceName: "google_alloydb_instance.default", @@ -43,6 +45,34 @@ func TestAccAlloydbInstance_update(t *testing.T) { }) } +func testAccAlloydbInstance_alloydbInstanceBasic(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_alloydb_instance" "default" { + cluster = google_alloydb_cluster.default.name + instance_id = "tf-test-alloydb-instance%{random_suffix}" + instance_type = "PRIMARY" + + machine_config { + cpu_count = 2 + } +} + +resource "google_alloydb_cluster" "default" { + cluster_id = "tf-test-alloydb-cluster%{random_suffix}" + location = "us-central1" + network = data.google_compute_network.default.id + + initial_user { + password = "tf-test-alloydb-cluster%{random_suffix}" + } +} + +data "google_compute_network" "default" { + name = "%{network_name}" +} +`, context) +} + func testAccAlloydbInstance_update(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_alloydb_instance" "default" { @@ -57,40 +87,21 @@ resource "google_alloydb_instance" "default" { labels = { test = "tf-test-alloydb-instance%{random_suffix}" } - - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_cluster" "default" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id initial_user { password = "tf-test-alloydb-cluster%{random_suffix}" } } -data "google_project" "project" { -} - -resource "google_compute_network" "default" { +data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -100,7 +111,7 @@ func TestAccAlloydbInstance_createInstanceWithMandatoryFields(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), - "network_name": "tf-test-" + acctest.RandString(t, 10), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "alloydb-instance-mandatory-1"), } acctest.VcrTest(t, resource.TestCase{ @@ -121,35 +132,19 @@ resource "google_alloydb_instance" "default" { cluster = google_alloydb_cluster.default.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_cluster" "default" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id } data "google_project" "project" {} -resource "google_compute_network" "default" { +data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -159,7 +154,7 @@ func TestAccAlloydbInstance_createInstanceWithMaximumFields(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), - "network_name": "tf-test-" + acctest.RandString(t, 10), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "alloydb-instance-maximum-1"), } acctest.VcrTest(t, resource.TestCase{ @@ -194,7 +189,6 @@ resource "google_alloydb_instance" "default" { machine_config { cpu_count = 4 } - depends_on = [google_service_networking_connection.vpc_connection] lifecycle { ignore_changes = [ gce_zone, @@ -206,28 +200,14 @@ resource "google_alloydb_instance" "default" { resource "google_alloydb_cluster" "default" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id } data "google_project" "project" {} -resource "google_compute_network" "default" { +data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -237,7 +217,7 @@ func TestAccAlloydbInstance_createPrimaryAndReadPoolInstance(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), - "network_name": "tf-test-" + acctest.RandString(t, 10), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "alloydb-instance-readpool-1"), } acctest.VcrTest(t, resource.TestCase{ @@ -258,7 +238,6 @@ resource "google_alloydb_instance" "primary" { cluster = google_alloydb_cluster.default.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_instance" "read_pool" { @@ -268,34 +247,20 @@ resource "google_alloydb_instance" "read_pool" { read_pool_config { node_count = 4 } - depends_on = [google_service_networking_connection.vpc_connection, google_alloydb_instance.primary] + depends_on = [google_alloydb_instance.primary] } resource "google_alloydb_cluster" "default" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id } data "google_project" "project" {} -resource "google_compute_network" "default" { +data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -305,7 +270,7 @@ func TestAccAlloydbInstance_updateDatabaseFlagInPrimaryInstance(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), - "network_name": "tf-test-" + acctest.RandString(t, 10), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "alloydb-instance-updatedb-1"), } acctest.VcrTest(t, resource.TestCase{ @@ -337,34 +302,19 @@ resource "google_alloydb_instance" "primary" { database_flags = { "alloydb.enable_auto_explain" = "true" } - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_cluster" "default" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id } data "google_project" "project" {} -resource "google_compute_network" "default" { +data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -377,34 +327,19 @@ resource "google_alloydb_instance" "primary" { database_flags = { "alloydb.enable_auto_explain" = "false" } - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_cluster" "default" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id } data "google_project" "project" {} -resource "google_compute_network" "default" { +data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -412,9 +347,17 @@ resource "google_service_networking_connection" "vpc_connection" { func TestAccAlloydbInstance_createInstanceWithNetworkConfigAndAllocatedIPRange(t *testing.T) { t.Parallel() + projectNumber := envvar.GetTestProjectNumberFromEnv() + testId := "alloydbinstance-network-config-1" + networkName := acctest.BootstrapSharedTestNetwork(t, testId) + networkId := fmt.Sprintf("projects/%v/global/networks/%v", projectNumber, networkName) + addressName := acctest.BootstrapSharedTestGlobalAddress(t, testId, networkId) + acctest.BootstrapSharedServiceNetworkingConnection(t, testId) + context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), - "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydbinstance-network-config"), + "network_name": networkName, + "address_name": addressName, } acctest.VcrTest(t, resource.TestCase{ @@ -435,7 +378,6 @@ resource "google_alloydb_instance" "default" { cluster = google_alloydb_cluster.default.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_cluster" "default" { @@ -443,29 +385,16 @@ resource "google_alloydb_cluster" "default" { location = "us-central1" network_config { network = data.google_compute_network.default.id - allocated_ip_range = google_compute_global_address.private_ip_alloc.name + allocated_ip_range = data.google_compute_global_address.private_ip_alloc.name } - } -data "google_project" "project" {} - data "google_compute_network" "default" { name = "%{network_name}" } -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = data.google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] +data "google_compute_global_address" "private_ip_alloc" { + name = "%{address_name}" } `, context) } 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 6cc7a87dd96c..2954e203a654 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 @@ -104,7 +104,7 @@ func TestAccCloudbuildWorkerPool_withNetwork(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), "project": envvar.GetTestProjectFromEnv(), - "network_name": "tf-test-" + acctest.RandString(t, 10), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "cloudbuild-workerpool-1"), } acctest.VcrTest(t, resource.TestCase{ @@ -127,24 +127,10 @@ func TestAccCloudbuildWorkerPool_withNetwork(t *testing.T) { func testAccCloudbuildWorkerPool_withNetwork(context map[string]interface{}) string { return acctest.Nprintf(` -resource "google_compute_network" "network" { +data "google_compute_network" "network" { name = "%{network_name}" } -resource "google_compute_global_address" "worker_range" { - name = "tf-test-worker-pool-range%{random_suffix}" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 16 - network = google_compute_network.network.id -} - -resource "google_service_networking_connection" "worker_pool_conn" { - network = google_compute_network.network.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.worker_range.name] -} - resource "google_cloudbuild_worker_pool" "pool" { name = "pool%{random_suffix}" location = "europe-west1" @@ -154,10 +140,9 @@ resource "google_cloudbuild_worker_pool" "pool" { no_external_ip = false } network_config { - peered_network = google_compute_network.network.id + peered_network = data.google_compute_network.network.id peered_network_ip_range = "/29" } - depends_on = [google_service_networking_connection.worker_pool_conn] } `, context) } diff --git a/mmv1/third_party/terraform/services/cloudids/resource_cloudids_endpoint_test.go b/mmv1/third_party/terraform/services/cloudids/resource_cloudids_endpoint_test.go index 3e6f8a626c90..9983e66e0feb 100644 --- a/mmv1/third_party/terraform/services/cloudids/resource_cloudids_endpoint_test.go +++ b/mmv1/third_party/terraform/services/cloudids/resource_cloudids_endpoint_test.go @@ -18,7 +18,7 @@ func TestAccCloudIdsEndpoint_basic(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), - "network_name": "tf-test-key-" + acctest.RandString(t, 10), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "cloud-ids-endpoint-1"), } acctest.VcrTest(t, resource.TestCase{ @@ -48,58 +48,32 @@ func TestAccCloudIdsEndpoint_basic(t *testing.T) { func testCloudIds_basic(context map[string]interface{}) string { return acctest.Nprintf(` -resource "google_compute_network" "default" { +data "google_compute_network" "default" { name = "%{network_name}" } -resource "google_compute_global_address" "service_range" { - name = "tf-test-address%{random_suffix}" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 16 - network = google_compute_network.default.id -} -resource "google_service_networking_connection" "private_service_connection" { - network = google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.service_range.name] -} resource "google_cloud_ids_endpoint" "endpoint" { name = "cloud-ids-test-%{random_suffix}" location = "us-central1-f" - network = google_compute_network.default.id + network = data.google_compute_network.default.id severity = "INFORMATIONAL" threat_exceptions = ["12", "67"] - depends_on = [google_service_networking_connection.private_service_connection] } `, context) } func testCloudIds_basicUpdate(context map[string]interface{}) string { return acctest.Nprintf(` -resource "google_compute_network" "default" { +data "google_compute_network" "default" { name = "%{network_name}" } -resource "google_compute_global_address" "service_range" { - name = "tf-test-address%{random_suffix}" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 16 - network = google_compute_network.default.id -} -resource "google_service_networking_connection" "private_service_connection" { - network = google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.service_range.name] -} resource "google_cloud_ids_endpoint" "endpoint" { name = "cloud-ids-test-%{random_suffix}" location = "us-central1-f" - network = google_compute_network.default.id + network = data.google_compute_network.default.id severity = "INFORMATIONAL" threat_exceptions = ["33"] - depends_on = [google_service_networking_connection.private_service_connection] } `, context) } diff --git a/mmv1/third_party/terraform/services/databasemigrationservice/resource_database_migration_service_connection_profile_test.go b/mmv1/third_party/terraform/services/databasemigrationservice/resource_database_migration_service_connection_profile_test.go index 439c8b395198..a9f9c108574a 100644 --- a/mmv1/third_party/terraform/services/databasemigrationservice/resource_database_migration_service_connection_profile_test.go +++ b/mmv1/third_party/terraform/services/databasemigrationservice/resource_database_migration_service_connection_profile_test.go @@ -77,3 +77,70 @@ resource "google_database_migration_service_connection_profile" "default" { } `, context) } + +func TestAccDatabaseMigrationServiceConnectionProfile_databaseMigrationServiceConnectionProfileAlloydb(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "vpc-network-1"), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckDatabaseMigrationServiceConnectionProfileDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDatabaseMigrationServiceConnectionProfile_databaseMigrationServiceConnectionProfileAlloydb(context), + }, + { + ResourceName: "google_database_migration_service_connection_profile.alloydbprofile", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"connection_profile_id", "location", "alloydb.0.settings.0.initial_user.0.password", "labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccDatabaseMigrationServiceConnectionProfile_databaseMigrationServiceConnectionProfileAlloydb(context map[string]interface{}) string { + return acctest.Nprintf(` +data "google_compute_network" "default" { + name = "%{network_name}" +} + +resource "google_database_migration_service_connection_profile" "alloydbprofile" { + location = "us-central1" + connection_profile_id = "tf-test-my-profileid%{random_suffix}" + display_name = "tf-test-my-profileid%{random_suffix}_display" + labels = { + foo = "bar" + } + alloydb { + cluster_id = "tf-test-dbmsalloycluster%{random_suffix}" + settings { + initial_user { + user = "alloyuser%{random_suffix}" + password = "alloypass%{random_suffix}" + } + vpc_network = data.google_compute_network.default.id + labels = { + alloyfoo = "alloybar" + } + primary_instance_settings { + id = "priminstid" + machine_config { + cpu_count = 2 + } + database_flags = { + } + labels = { + alloysinstfoo = "allowinstbar" + } + } + } + } +} +`, context) +} diff --git a/mmv1/third_party/terraform/services/memcache/resource_memcache_instance_test.go b/mmv1/third_party/terraform/services/memcache/resource_memcache_instance_test.go index 7c42f5632e91..585f0f114603 100644 --- a/mmv1/third_party/terraform/services/memcache/resource_memcache_instance_test.go +++ b/mmv1/third_party/terraform/services/memcache/resource_memcache_instance_test.go @@ -13,7 +13,7 @@ func TestAccMemcacheInstance_update(t *testing.T) { prefix := fmt.Sprintf("%d", acctest.RandInt(t)) name := fmt.Sprintf("tf-test-%s", prefix) - network := "tf-test-" + acctest.RandString(t, 10) + network := acctest.BootstrapSharedServiceNetworkingConnection(t, "memcache-instance-update-1") acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -42,24 +42,10 @@ func TestAccMemcacheInstance_update(t *testing.T) { func testAccMemcacheInstance_update(prefix, name, network string) string { return fmt.Sprintf(` -resource "google_compute_global_address" "service_range" { - name = "tf-test%s" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 16 - network = google_compute_network.memcache_network.id -} - -resource "google_service_networking_connection" "private_service_connection" { - network = google_compute_network.memcache_network.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.service_range.name] -} - resource "google_memcache_instance" "test" { name = "%s" region = "us-central1" - authorized_network = google_service_networking_connection.private_service_connection.network + authorized_network = data.google_compute_network.memcache_network.id node_config { cpu_count = 1 @@ -75,32 +61,18 @@ resource "google_memcache_instance" "test" { } } -resource "google_compute_network" "memcache_network" { +data "google_compute_network" "memcache_network" { name = "%s" } -`, prefix, name, network) +`, name, network) } func testAccMemcacheInstance_update2(prefix, name, network string) string { return fmt.Sprintf(` -resource "google_compute_global_address" "service_range" { - name = "tf-test%s" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 16 - network = google_compute_network.memcache_network.id -} - -resource "google_service_networking_connection" "private_service_connection" { - network = google_compute_network.memcache_network.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.service_range.name] -} - resource "google_memcache_instance" "test" { name = "%s" region = "us-central1" - authorized_network = google_service_networking_connection.private_service_connection.network + authorized_network = data.google_compute_network.memcache_network.id node_config { cpu_count = 1 @@ -116,8 +88,8 @@ resource "google_memcache_instance" "test" { } } -resource "google_compute_network" "memcache_network" { +data "google_compute_network" "memcache_network" { name = "%s" } -`, prefix, name, network) +`, name, network) } diff --git a/mmv1/third_party/terraform/services/servicenetworking/resource_service_networking_connection.go b/mmv1/third_party/terraform/services/servicenetworking/resource_service_networking_connection.go index 249b268ba58f..8482083fbdd7 100644 --- a/mmv1/third_party/terraform/services/servicenetworking/resource_service_networking_connection.go +++ b/mmv1/third_party/terraform/services/servicenetworking/resource_service_networking_connection.go @@ -8,13 +8,11 @@ import ( "strings" "time" - tpgcompute "github.com/hashicorp/terraform-provider-google/google/services/compute" "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" "github.com/hashicorp/errwrap" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "google.golang.org/api/compute/v1" "google.golang.org/api/servicenetworking/v1" ) @@ -261,42 +259,35 @@ func resourceServiceNetworkingConnectionDelete(d *schema.ResourceData, meta inte return err } - obj := make(map[string]interface{}) - peering := d.Get("peering").(string) - obj["name"] = peering - url := fmt.Sprintf("%s%s/removePeering", config.ComputeBasePath, serviceNetworkingNetworkName) - networkFieldValue, err := tpgresource.ParseNetworkFieldValue(network, d, config) if err != nil { return errwrap.Wrapf("Failed to retrieve network field value, err: {{err}}", err) } project := networkFieldValue.Project - res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ - Config: config, - Method: "POST", - Project: project, - RawURL: url, - UserAgent: userAgent, - Body: obj, - Timeout: d.Timeout(schema.TimeoutDelete), - }) + connectionId, err := parseConnectionId(d.Id()) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("ServiceNetworkingConnection %q", d.Id())) + return errwrap.Wrapf("Unable to parse Service Networking Connection id, err: {{err}}", err) } + parentService := formatParentService(connectionId.Service) - op := &compute.Operation{} - err = tpgresource.Convert(res, op) - if err != nil { - return err + deleteConnectionRequest := &servicenetworking.DeleteConnectionRequest{ + ConsumerNetwork: serviceNetworkingNetworkName, } - err = tpgcompute.ComputeOperationWaitTime( - config, op, project, "Updating Network", userAgent, d.Timeout(schema.TimeoutDelete)) + deleteCall := config.NewServiceNetworkingClient(userAgent).Services.Connections.DeleteConnection(parentService+"/connections/servicenetworking-googleapis-com", deleteConnectionRequest) + if config.UserProjectOverride { + deleteCall.Header().Add("X-Goog-User-Project", project) + } + op, err := deleteCall.Do() if err != nil { return err } + if err := ServiceNetworkingOperationWaitTime(config, op, "Delete Service Networking Connection", userAgent, project, d.Timeout(schema.TimeoutCreate)); err != nil { + return errwrap.Wrapf("Unable to remove Service Networking Connection, err: {{err}}", err) + } + d.SetId("") log.Printf("[INFO] Service network connection removed.") diff --git a/mmv1/third_party/terraform/services/servicenetworking/resource_service_networking_connection_test.go b/mmv1/third_party/terraform/services/servicenetworking/resource_service_networking_connection_test.go index 374a8be52ac5..e5ee28383379 100644 --- a/mmv1/third_party/terraform/services/servicenetworking/resource_service_networking_connection_test.go +++ b/mmv1/third_party/terraform/services/servicenetworking/resource_service_networking_connection_test.go @@ -13,7 +13,7 @@ import ( func TestAccServiceNetworkingConnection_create(t *testing.T) { t.Parallel() - network := acctest.BootstrapSharedTestNetwork(t, "service-networking-connection-create") + network := fmt.Sprintf("tf-test-service-networking-connection-create-%s", acctest.RandString(t, 10)) addr := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) service := "servicenetworking.googleapis.com" @@ -37,7 +37,7 @@ func TestAccServiceNetworkingConnection_create(t *testing.T) { func TestAccServiceNetworkingConnection_update(t *testing.T) { t.Parallel() - network := acctest.BootstrapSharedTestNetwork(t, "service-networking-connection-update") + network := fmt.Sprintf("tf-test-service-networking-connection-update-%s", acctest.RandString(t, 10)) addr1 := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) addr2 := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) service := "servicenetworking.googleapis.com" @@ -94,7 +94,7 @@ func testServiceNetworkingConnectionDestroy(t *testing.T, parent, network string func testAccServiceNetworkingConnection(networkName, addressRangeName, serviceName string) string { return fmt.Sprintf(` -data "google_compute_network" "servicenet" { +resource "google_compute_network" "servicenet" { name = "%s" } @@ -103,11 +103,11 @@ resource "google_compute_global_address" "foobar" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = data.google_compute_network.servicenet.self_link + network = google_compute_network.servicenet.self_link } resource "google_service_networking_connection" "foobar" { - network = data.google_compute_network.servicenet.self_link + network = google_compute_network.servicenet.self_link service = "%s" reserved_peering_ranges = [google_compute_global_address.foobar.name] } diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go index acd91bc9aeef..b30fd88fe81c 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go @@ -178,8 +178,12 @@ func TestAccSqlDatabaseInstance_deleteDefaultUserBeforeSubsequentApiCalls(t *tes t.Parallel() databaseName := "tf-test-" + acctest.RandString(t, 10) - addressName := "tf-test-" + acctest.RandString(t, 10) - networkName := "tf-test-" + acctest.RandString(t, 10) + testId := "sql-instance-clone-2" + networkName := acctest.BootstrapSharedTestNetwork(t, testId) + projectNumber := envvar.GetTestProjectNumberFromEnv() + networkId := fmt.Sprintf("projects/%v/global/networks/%v", projectNumber, networkName) + addressName := acctest.BootstrapSharedTestGlobalAddress(t, testId, networkId) + acctest.BootstrapSharedServiceNetworkingConnection(t, testId) // 1. Create an instance. // 2. Add a root@'%' user. @@ -191,7 +195,7 @@ func TestAccSqlDatabaseInstance_deleteDefaultUserBeforeSubsequentApiCalls(t *tes CheckDestroy: testAccSqlDatabaseInstanceDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName, addressName, false, false), + Config: testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName, false, false), }, { PreConfig: func() { @@ -736,8 +740,7 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(t *te t.Parallel() databaseName := "tf-test-" + acctest.RandString(t, 10) - addressName := "tf-test-" + acctest.RandString(t, 10) - networkName := "tf-test-" + acctest.RandString(t, 10) + networkName := acctest.BootstrapSharedServiceNetworkingConnection(t, "sql-instance-1") acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -745,7 +748,7 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(t *te CheckDestroy: testAccSqlDatabaseInstanceDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName, addressName, false, false), + Config: testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName, false, false), }, { ResourceName: "google_sql_database_instance.instance", @@ -754,7 +757,7 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(t *te ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { - Config: testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName, addressName, true, false), + Config: testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName, true, false), }, { ResourceName: "google_sql_database_instance.instance", @@ -763,7 +766,7 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(t *te ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { - Config: testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName, addressName, true, true), + Config: testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName, true, true), }, { ResourceName: "google_sql_database_instance.instance", @@ -772,7 +775,7 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(t *te ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { - Config: testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName, addressName, true, false), + Config: testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName, true, false), }, { ResourceName: "google_sql_database_instance.instance", @@ -975,10 +978,19 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRange(t *testi t.Parallel() databaseName := "tf-test-" + acctest.RandString(t, 10) - addressName := "tf-test-" + acctest.RandString(t, 10) - networkName := "tf-test-" + acctest.RandString(t, 10) - addressName_update := "tf-test-" + acctest.RandString(t, 10) + "update" - networkName_update := "tf-test-" + acctest.RandString(t, 10) + "update" + + projectNumber := envvar.GetTestProjectNumberFromEnv() + testId := "sql-instance-allocated-1" + networkName := acctest.BootstrapSharedTestNetwork(t, testId) + networkId := fmt.Sprintf("projects/%v/global/networks/%v", projectNumber, networkName) + addressName := acctest.BootstrapSharedTestGlobalAddress(t, testId, networkId) + acctest.BootstrapSharedServiceNetworkingConnection(t, testId) + + updateTestId := "sql-instance-allocated-update-1" + networkName_update := acctest.BootstrapSharedTestNetwork(t, updateTestId) + networkId_update := fmt.Sprintf("projects/%v/global/networks/%v", projectNumber, networkName_update) + addressName_update := acctest.BootstrapSharedTestGlobalAddress(t, updateTestId, networkId_update) + acctest.BootstrapSharedServiceNetworkingConnection(t, updateTestId) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -1012,8 +1024,13 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRangeReplica(t t.Parallel() databaseName := "tf-test-" + acctest.RandString(t, 10) - addressName := "tf-test-" + acctest.RandString(t, 10) - networkName := "tf-test-" + acctest.RandString(t, 10) + + projectNumber := envvar.GetTestProjectNumberFromEnv() + testId := "sql-instance-replica-1" + networkName := acctest.BootstrapSharedTestNetwork(t, testId) + networkId := fmt.Sprintf("projects/%v/global/networks/%v", projectNumber, networkName) + addressName := acctest.BootstrapSharedTestGlobalAddress(t, testId, networkId) + acctest.BootstrapSharedServiceNetworkingConnection(t, testId) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -1044,8 +1061,12 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRangeClone(t * t.Parallel() databaseName := "tf-test-" + acctest.RandString(t, 10) - addressName := "tf-test-" + acctest.RandString(t, 10) - networkName := "tf-test-" + acctest.RandString(t, 10) + projectNumber := envvar.GetTestProjectNumberFromEnv() + testId := "sql-instance-clone-1" + networkName := acctest.BootstrapSharedTestNetwork(t, testId) + networkId := fmt.Sprintf("projects/%v/global/networks/%v", projectNumber, networkName) + addressName := acctest.BootstrapSharedTestGlobalAddress(t, testId, networkId) + acctest.BootstrapSharedServiceNetworkingConnection(t, testId) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -1445,8 +1466,7 @@ func TestAccSqlDatabaseInstance_ActiveDirectory(t *testing.T) { t.Parallel() databaseName := "tf-test-" + acctest.RandString(t, 10) - networkName := acctest.BootstrapSharedTestNetwork(t, "sql-instance-private-test-ad") - addressName := "tf-test-" + acctest.RandString(t, 10) + networkName := acctest.BootstrapSharedServiceNetworkingConnection(t, "sql-instance-ad-1") rootPassword := acctest.RandString(t, 15) adDomainName := acctest.BootstrapSharedTestADDomain(t, "test-domain", networkName) @@ -1456,7 +1476,7 @@ func TestAccSqlDatabaseInstance_ActiveDirectory(t *testing.T) { CheckDestroy: testAccSqlDatabaseInstanceDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testGoogleSqlDatabaseInstance_ActiveDirectoryConfig(databaseName, networkName, addressName, rootPassword, adDomainName), + Config: testGoogleSqlDatabaseInstance_ActiveDirectoryConfig(databaseName, networkName, rootPassword, adDomainName), }, { ResourceName: "google_sql_database_instance.instance-with-ad", @@ -2174,28 +2194,13 @@ resource "google_sql_database_instance" "instance" { } ` -func testGoogleSqlDatabaseInstance_ActiveDirectoryConfig(databaseName, networkName, addressRangeName, rootPassword, adDomainName string) string { +func testGoogleSqlDatabaseInstance_ActiveDirectoryConfig(databaseName, networkName, rootPassword, adDomainName string) string { return fmt.Sprintf(` data "google_compute_network" "servicenet" { name = "%s" } -resource "google_compute_global_address" "foobar" { - name = "%s" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 16 - network = data.google_compute_network.servicenet.self_link -} - -resource "google_service_networking_connection" "foobar" { - network = data.google_compute_network.servicenet.self_link - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.foobar.name] -} - resource "google_sql_database_instance" "instance-with-ad" { - depends_on = [google_service_networking_connection.foobar] name = "%s" region = "us-central1" database_version = "SQLSERVER_2017_STANDARD" @@ -2212,7 +2217,7 @@ resource "google_sql_database_instance" "instance-with-ad" { domain = "%s" } } -}`, networkName, addressRangeName, databaseName, rootPassword, adDomainName) +}`, networkName, databaseName, rootPassword, adDomainName) } func testGoogleSqlDatabaseInstance_DenyMaintenancePeriodConfig(databaseName, endDate, startDate, time string) string { @@ -2803,33 +2808,18 @@ func verifyPscOperation(resourceName string, isPscConfigExpected bool, expectedP } } -func testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName, addressRangeName string, specifyPrivatePathOption bool, enablePrivatePath bool) string { +func testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName string, specifyPrivatePathOption bool, enablePrivatePath bool) string { privatePathOption := "" if specifyPrivatePathOption { privatePathOption = fmt.Sprintf("enable_private_path_for_google_cloud_services = %t", enablePrivatePath) } return fmt.Sprintf(` -resource "google_compute_network" "servicenet" { +data "google_compute_network" "servicenet" { name = "%s" } -resource "google_compute_global_address" "foobar" { - name = "%s" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 16 - network = google_compute_network.servicenet.self_link -} - -resource "google_service_networking_connection" "foobar" { - network = google_compute_network.servicenet.self_link - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.foobar.name] -} - resource "google_sql_database_instance" "instance" { - depends_on = [google_service_networking_connection.foobar] name = "%s" region = "us-central1" database_version = "MYSQL_5_7" @@ -2838,36 +2828,21 @@ resource "google_sql_database_instance" "instance" { tier = "db-f1-micro" ip_configuration { ipv4_enabled = "false" - private_network = google_compute_network.servicenet.self_link + private_network = data.google_compute_network.servicenet.self_link %s } } } -`, networkName, addressRangeName, databaseName, privatePathOption) +`, networkName, databaseName, privatePathOption) } func testAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRange(databaseName, networkName, addressRangeName string) string { return fmt.Sprintf(` -resource "google_compute_network" "servicenet" { +data "google_compute_network" "servicenet" { name = "%s" } -resource "google_compute_global_address" "foobar" { - name = "%s" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 16 - network = google_compute_network.servicenet.self_link -} - -resource "google_service_networking_connection" "foobar" { - network = google_compute_network.servicenet.self_link - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.foobar.name] -} - resource "google_sql_database_instance" "instance" { - depends_on = [google_service_networking_connection.foobar] name = "%s" region = "us-central1" database_version = "MYSQL_5_7" @@ -2876,36 +2851,21 @@ resource "google_sql_database_instance" "instance" { tier = "db-f1-micro" ip_configuration { ipv4_enabled = "false" - private_network = google_compute_network.servicenet.self_link - allocated_ip_range = google_compute_global_address.foobar.name + private_network = data.google_compute_network.servicenet.self_link + allocated_ip_range = "%s" } } } -`, networkName, addressRangeName, databaseName) +`, networkName, databaseName, addressRangeName) } func testAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRangeReplica(databaseName, networkName, addressRangeName string) string { return fmt.Sprintf(` -resource "google_compute_network" "servicenet" { +data "google_compute_network" "servicenet" { name = "%s" } -resource "google_compute_global_address" "foobar" { - name = "%s" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 16 - network = google_compute_network.servicenet.self_link -} - -resource "google_service_networking_connection" "foobar" { - network = google_compute_network.servicenet.self_link - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.foobar.name] -} - resource "google_sql_database_instance" "instance" { - depends_on = [google_service_networking_connection.foobar] name = "%s" region = "us-central1" database_version = "MYSQL_5_7" @@ -2914,7 +2874,7 @@ resource "google_sql_database_instance" "instance" { tier = "db-f1-micro" ip_configuration { ipv4_enabled = "false" - private_network = google_compute_network.servicenet.self_link + private_network = data.google_compute_network.servicenet.self_link } backup_configuration { enabled = true @@ -2924,7 +2884,6 @@ resource "google_sql_database_instance" "instance" { } } resource "google_sql_database_instance" "replica1" { - depends_on = [google_service_networking_connection.foobar] name = "%s-replica1" region = "us-central1" database_version = "MYSQL_5_7" @@ -2933,8 +2892,8 @@ resource "google_sql_database_instance" "replica1" { tier = "db-f1-micro" ip_configuration { ipv4_enabled = "false" - private_network = google_compute_network.servicenet.self_link - allocated_ip_range = google_compute_global_address.foobar.name + private_network = data.google_compute_network.servicenet.self_link + allocated_ip_range = "%s" } } @@ -2949,31 +2908,16 @@ resource "google_sql_database_instance" "replica1" { verify_server_certificate = false } } -`, networkName, addressRangeName, databaseName, databaseName) +`, networkName, databaseName, databaseName, addressRangeName) } func testAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRangeClone(databaseName, networkName, addressRangeName string) string { return fmt.Sprintf(` -resource "google_compute_network" "servicenet" { +data "google_compute_network" "servicenet" { name = "%s" } -resource "google_compute_global_address" "foobar" { - name = "%s" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 16 - network = google_compute_network.servicenet.self_link -} - -resource "google_service_networking_connection" "foobar" { - network = google_compute_network.servicenet.self_link - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.foobar.name] -} - resource "google_sql_database_instance" "instance" { - depends_on = [google_service_networking_connection.foobar] name = "%s" region = "us-central1" database_version = "MYSQL_5_7" @@ -2982,7 +2926,7 @@ resource "google_sql_database_instance" "instance" { tier = "db-f1-micro" ip_configuration { ipv4_enabled = "false" - private_network = google_compute_network.servicenet.self_link + private_network = data.google_compute_network.servicenet.self_link } backup_configuration { enabled = true @@ -3000,35 +2944,20 @@ resource "google_sql_database_instance" "clone1" { clone { source_instance_name = google_sql_database_instance.instance.name - allocated_ip_range = google_compute_global_address.foobar.name + allocated_ip_range = "%s" } } -`, networkName, addressRangeName, databaseName, databaseName) +`, networkName, databaseName, databaseName, addressRangeName) } func testAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRangeClone_withSettings(databaseName, networkName, addressRangeName string) string { return fmt.Sprintf(` -resource "google_compute_network" "servicenet" { +data "google_compute_network" "servicenet" { name = "%s" } -resource "google_compute_global_address" "foobar" { - name = "%s" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 16 - network = google_compute_network.servicenet.self_link -} - -resource "google_service_networking_connection" "foobar" { - network = google_compute_network.servicenet.self_link - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.foobar.name] -} - resource "google_sql_database_instance" "instance" { - depends_on = [google_service_networking_connection.foobar] name = "%s" region = "us-central1" database_version = "MYSQL_5_7" @@ -3037,7 +2966,7 @@ resource "google_sql_database_instance" "instance" { tier = "db-f1-micro" ip_configuration { ipv4_enabled = "false" - private_network = google_compute_network.servicenet.self_link + private_network = data.google_compute_network.servicenet.self_link } backup_configuration { enabled = true @@ -3055,7 +2984,7 @@ resource "google_sql_database_instance" "clone1" { clone { source_instance_name = google_sql_database_instance.instance.name - allocated_ip_range = google_compute_global_address.foobar.name + allocated_ip_range = "%s" } settings { @@ -3065,7 +2994,7 @@ resource "google_sql_database_instance" "clone1" { } } } -`, networkName, addressRangeName, databaseName, databaseName) +`, networkName, databaseName, databaseName, addressRangeName) } var testGoogleSqlDatabaseInstance_settings = ` diff --git a/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_endpoint_test.go b/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_endpoint_test.go index e781551aa541..09ca7ccc3c05 100644 --- a/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_endpoint_test.go +++ b/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_endpoint_test.go @@ -18,7 +18,7 @@ func TestAccVertexAIEndpoint_vertexAiEndpointNetwork(t *testing.T) { context := map[string]interface{}{ "endpoint_name": fmt.Sprint(acctest.RandInt(t) % 9999999999), "kms_key_name": acctest.BootstrapKMSKeyInLocation(t, "us-central1").CryptoKey.Name, - "network_name": acctest.BootstrapSharedTestNetwork(t, "vertex-ai-endpoint-update"), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "vertex-ai-endpoint-update-1"), "random_suffix": acctest.RandString(t, 10), } @@ -64,23 +64,6 @@ resource "google_vertex_ai_endpoint" "endpoint" { encryption_spec { kms_key_name = "%{kms_key_name}" } - depends_on = [ - google_service_networking_connection.vertex_vpc_connection - ] -} - -resource "google_service_networking_connection" "vertex_vpc_connection" { - network = data.google_compute_network.vertex_network.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.vertex_range.name] -} - -resource "google_compute_global_address" "vertex_range" { - name = "tf-test-address-name%{random_suffix}" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 24 - network = data.google_compute_network.vertex_network.id } data "google_compute_network" "vertex_network" { @@ -112,23 +95,6 @@ resource "google_vertex_ai_endpoint" "endpoint" { encryption_spec { kms_key_name = "%{kms_key_name}" } - depends_on = [ - google_service_networking_connection.vertex_vpc_connection - ] -} - -resource "google_service_networking_connection" "vertex_vpc_connection" { - network = data.google_compute_network.vertex_network.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.vertex_range.name] -} - -resource "google_compute_global_address" "vertex_range" { - name = "tf-test-address-name%{random_suffix}" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 24 - network = data.google_compute_network.vertex_network.id } data "google_compute_network" "vertex_network" { diff --git a/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_index_endpoint_test.go b/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_index_endpoint_test.go index 1e9aa0eb6f22..aac5eb5eeb8d 100644 --- a/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_index_endpoint_test.go +++ b/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_index_endpoint_test.go @@ -12,7 +12,7 @@ func TestAccVertexAIIndexEndpoint_updated(t *testing.T) { t.Parallel() context := map[string]interface{}{ - "network_name": acctest.BootstrapSharedTestNetwork(t, "vertex-ai-index-endpoint-update"), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "vertex-ai-index-endpoint-update-1"), "random_suffix": acctest.RandString(t, 10), } @@ -28,7 +28,7 @@ func TestAccVertexAIIndexEndpoint_updated(t *testing.T) { ResourceName: "google_vertex_ai_index_endpoint.index_endpoint", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "region"}, + ImportStateVerifyIgnore: []string{"etag", "region", "labels", "terraform_labels"}, }, { Config: testAccVertexAIIndexEndpoint_updated(context), @@ -37,7 +37,7 @@ func TestAccVertexAIIndexEndpoint_updated(t *testing.T) { ResourceName: "google_vertex_ai_index_endpoint.index_endpoint", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "region"}, + ImportStateVerifyIgnore: []string{"etag", "region", "labels", "terraform_labels"}, }, }, }) @@ -53,15 +53,8 @@ resource "google_vertex_ai_index_endpoint" "index_endpoint" { label-one = "value-one" } network = "projects/${data.google_project.project.number}/global/networks/${data.google_compute_network.vertex_network.name}" - depends_on = [ - google_service_networking_connection.vertex_vpc_connection - ] -} -resource "google_service_networking_connection" "vertex_vpc_connection" { - network = data.google_compute_network.vertex_network.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.vertex_range.name] } + resource "google_compute_global_address" "vertex_range" { name = "tf-test-address-name%{random_suffix}" purpose = "VPC_PEERING" @@ -87,22 +80,8 @@ resource "google_vertex_ai_index_endpoint" "index_endpoint" { label-two = "value-two" } network = "projects/${data.google_project.project.number}/global/networks/${data.google_compute_network.vertex_network.name}" - depends_on = [ - google_service_networking_connection.vertex_vpc_connection - ] -} -resource "google_service_networking_connection" "vertex_vpc_connection" { - network = data.google_compute_network.vertex_network.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.vertex_range.name] -} -resource "google_compute_global_address" "vertex_range" { - name = "tf-test-address-name%{random_suffix}" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 24 - network = data.google_compute_network.vertex_network.id } + data "google_compute_network" "vertex_network" { name = "%{network_name}" } From 63fe3778348945c1245b1f44c59d7614ed4e5739 Mon Sep 17 00:00:00 2001 From: Scott Suarez Date: Thu, 21 Sep 2023 14:25:53 -0700 Subject: [PATCH 45/67] Unblock Feature branch by no merging main if BASE_BRANCH != main (#9040) --- .ci/gcb-community-checker.yml | 25 +++++++++++----------- .ci/gcb-contributor-membership-checker.yml | 25 +++++++++++----------- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/.ci/gcb-community-checker.yml b/.ci/gcb-community-checker.yml index b7032b5c6148..08712995646b 100644 --- a/.ci/gcb-community-checker.yml +++ b/.ci/gcb-community-checker.yml @@ -22,13 +22,6 @@ steps: - user.name - "Modular Magician Diff Process" - # Fetch main (only if it's not already present) - - name: "gcr.io/cloud-builders/git" - args: - - fetch - - origin - - main - # Display commit log for clarity - name: "gcr.io/cloud-builders/git" args: @@ -36,18 +29,24 @@ steps: - "--oneline" - "-n 10" - # Find common ancestor commit and apply diff for the .ci folder + # Find common ancestor commit and apply diff for the .ci folder. - name: "gcr.io/cloud-builders/git" id: findMergeBase entrypoint: "bash" args: - "-c" - | - base_commit=$(git merge-base origin/main HEAD) - echo "Common ancestor commit: $base_commit" - git diff $base_commit origin/main -- .ci/ - git diff $base_commit origin/main -- .ci/ > /workspace/ci.diff - git apply /workspace/ci.diff --allow-empty + git fetch origin main + if [ "$_BASE_BRANCH" != "main" ]; then + echo "Checking out .ci/ folder from main" + git checkout origin/main -- .ci/ + else + base_commit=$(git merge-base origin/main HEAD) + echo "Common ancestor commit: $base_commit" + git diff $base_commit upstream/main -- .ci/ + git diff $base_commit upstream/main -- .ci/ > /workspace/ci.diff + git apply ./ci.diff --allow-empty + fi - name: 'gcr.io/graphite-docker-images/go-plus' entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' diff --git a/.ci/gcb-contributor-membership-checker.yml b/.ci/gcb-contributor-membership-checker.yml index d44ea5a4b4a2..3164a75a5cf8 100644 --- a/.ci/gcb-contributor-membership-checker.yml +++ b/.ci/gcb-contributor-membership-checker.yml @@ -22,13 +22,6 @@ steps: - user.name - "Modular Magician Diff Process" - # Fetch main (only if it's not already present) - - name: "gcr.io/cloud-builders/git" - args: - - fetch - - origin - - main - # Display commit log for clarity - name: "gcr.io/cloud-builders/git" args: @@ -36,18 +29,24 @@ steps: - "--oneline" - "-n 10" - # Find common ancestor commit and apply diff for the .ci folder + # Find common ancestor commit and apply diff for the .ci folder. - name: "gcr.io/cloud-builders/git" id: findMergeBase entrypoint: "bash" args: - "-c" - | - base_commit=$(git merge-base origin/main HEAD) - echo "Common ancestor commit: $base_commit" - git diff $base_commit origin/main -- .ci/ - git diff $base_commit origin/main -- .ci/ > /workspace/ci.diff - git apply /workspace/ci.diff --allow-empty + git fetch origin main + if [ "$_BASE_BRANCH" != "main" ]; then + echo "Checking out .ci/ folder from main" + git checkout origin/main -- .ci/ + else + base_commit=$(git merge-base origin/main HEAD) + echo "Common ancestor commit: $base_commit" + git diff $base_commit upstream/main -- .ci/ + git diff $base_commit upstream/main -- .ci/ > /workspace/ci.diff + git apply ./ci.diff --allow-empty + fi - name: "gcr.io/graphite-docker-images/go-plus" entrypoint: "/workspace/.ci/scripts/go-plus/magician/exec.sh" From 4aa41b7df2ba403302fa7ea6dfe5f77f3809e805 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Thu, 21 Sep 2023 17:20:03 -0700 Subject: [PATCH 46/67] Check if labels field exists in customDiff function (#9043) --- .../terraform/tpgresource/annotations.go | 10 ++++++++++ mmv1/third_party/terraform/tpgresource/labels.go | 14 ++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/mmv1/third_party/terraform/tpgresource/annotations.go b/mmv1/third_party/terraform/tpgresource/annotations.go index f6a14211c8e8..183356e1cb44 100644 --- a/mmv1/third_party/terraform/tpgresource/annotations.go +++ b/mmv1/third_party/terraform/tpgresource/annotations.go @@ -8,6 +8,11 @@ import ( ) func SetAnnotationsDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) error { + raw := d.Get("annotations") + if raw == nil { + return nil + } + o, n := d.GetChange("annotations") effectiveAnnotations := d.Get("effective_annotations").(map[string]interface{}) @@ -34,6 +39,11 @@ func SetMetadataAnnotationsDiff(_ context.Context, d *schema.ResourceDiff, meta return nil } + raw := d.Get("metadata.0.annotations") + if raw == nil { + return nil + } + o, n := d.GetChange("metadata.0.annotations") effectiveAnnotations := d.Get("metadata.0.effective_annotations").(map[string]interface{}) diff --git a/mmv1/third_party/terraform/tpgresource/labels.go b/mmv1/third_party/terraform/tpgresource/labels.go index c07cdfd486a5..0a241e14e1fe 100644 --- a/mmv1/third_party/terraform/tpgresource/labels.go +++ b/mmv1/third_party/terraform/tpgresource/labels.go @@ -36,7 +36,12 @@ func SetLabelsDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) terraformLabels[k] = v } - labels := d.Get("labels").(map[string]interface{}) + raw := d.Get("labels") + if raw == nil { + return nil + } + + labels := raw.(map[string]interface{}) for k, v := range labels { terraformLabels[k] = v.(string) } @@ -71,6 +76,11 @@ func SetMetadataLabelsDiff(_ context.Context, d *schema.ResourceDiff, meta inter return nil } + raw := d.Get("metadata.0.labels") + if raw == nil { + return nil + } + config := meta.(*transport_tpg.Config) // Merge provider default labels with the user defined labels in the resource to get terraform managed labels @@ -79,7 +89,7 @@ func SetMetadataLabelsDiff(_ context.Context, d *schema.ResourceDiff, meta inter terraformLabels[k] = v } - labels := d.Get("metadata.0.labels").(map[string]interface{}) + labels := raw.(map[string]interface{}) for k, v := range labels { terraformLabels[k] = v.(string) } From e225a61dd37cbfcbe2967556100d3ec34ade1494 Mon Sep 17 00:00:00 2001 From: Mauricio Alvarez Leon <65101411+BBBmau@users.noreply.github.com> Date: Fri, 22 Sep 2023 07:43:43 -0700 Subject: [PATCH 47/67] Fix Inconsistent logic when getting zone/region/location (#8587) * fix inconsistencies in GetLocation test * fix inconsistencies in GetRegion test * fix default value in provider using region over zone * update test keys * add zone selflink check to SDK tests * add location selflink check * Update mmv1/third_party/terraform/fwresource/framework_location_test.go Co-authored-by: Sarah French <15078782+SarahFrench@users.noreply.github.com> * Update mmv1/third_party/terraform/fwresource/framework_location_test.go Co-authored-by: Sarah French <15078782+SarahFrench@users.noreply.github.com> * remove unnecessary test case checking that region is not set in provider * update GetLocation and tests to include region provider value * refactor selflink zone code * add test cases that handles region/zone values from provider when self link * add test cases checking region value in provider config with self link value * refactor tests in GetRegion function * add StringValue func --------- Co-authored-by: Sarah French <15078782+SarahFrench@users.noreply.github.com> --- .../fwresource/framework_location.go | 30 +++++++++---- .../fwresource/framework_location_test.go | 45 ++++++++++++------- .../terraform/tpgresource/field_helpers.go | 3 +- .../terraform/tpgresource/regional_utils.go | 20 ++++++--- .../terraform/tpgresource/utils_test.go | 41 +++++++++++------ 5 files changed, 93 insertions(+), 46 deletions(-) diff --git a/mmv1/third_party/terraform/fwresource/framework_location.go b/mmv1/third_party/terraform/fwresource/framework_location.go index 5a0559a290ef..609ab65b98b1 100644 --- a/mmv1/third_party/terraform/fwresource/framework_location.go +++ b/mmv1/third_party/terraform/fwresource/framework_location.go @@ -32,12 +32,14 @@ type LocationDescription struct { func (ld *LocationDescription) GetLocation() (types.String, error) { // Location from resource config if !ld.ResourceLocation.IsNull() && !ld.ResourceLocation.IsUnknown() && !ld.ResourceLocation.Equal(types.StringValue("")) { - return ld.ResourceLocation, nil + location := tpgresource.GetResourceNameFromSelfLink(ld.ResourceLocation.ValueString()) // Location could be a self link + return types.StringValue(location), nil } // Location from region in resource config if !ld.ResourceRegion.IsNull() && !ld.ResourceRegion.IsUnknown() && !ld.ResourceRegion.Equal(types.StringValue("")) { - return ld.ResourceRegion, nil + region := tpgresource.GetResourceNameFromSelfLink(ld.ResourceRegion.ValueString()) // Region could be a self link + return types.StringValue(region), nil } // Location from zone in resource config @@ -46,9 +48,16 @@ func (ld *LocationDescription) GetLocation() (types.String, error) { return types.StringValue(location), nil } + // Location from region in provider config + if !ld.ProviderRegion.IsNull() && !ld.ProviderRegion.IsUnknown() && !ld.ProviderRegion.Equal(types.StringValue("")) { + location := tpgresource.GetResourceNameFromSelfLink(ld.ProviderRegion.ValueString()) // Region could be a self link + return types.StringValue(location), nil + } + // Location from zone in provider config if !ld.ProviderZone.IsNull() && !ld.ProviderZone.IsUnknown() && !ld.ProviderZone.Equal(types.StringValue("")) { - return ld.ProviderZone, nil + location := tpgresource.GetResourceNameFromSelfLink(ld.ProviderZone.ValueString()) // Zone could be a self link + return types.StringValue(location), nil } var err error @@ -71,17 +80,18 @@ func (ld *LocationDescription) GetRegion() (types.String, error) { } // Region from zone in resource config if !ld.ResourceZone.IsNull() && !ld.ResourceZone.IsUnknown() && !ld.ResourceZone.Equal(types.StringValue("")) { - region := tpgresource.GetRegionFromZone(ld.ResourceZone.ValueString()) - return types.StringValue(region), nil + region := tpgresource.GetResourceNameFromSelfLink(ld.ResourceZone.ValueString()) // Region could be a self link + return types.StringValue(tpgresource.GetRegionFromZone(region)), nil } // Region from provider config if !ld.ProviderRegion.IsNull() && !ld.ProviderRegion.IsUnknown() && !ld.ProviderRegion.Equal(types.StringValue("")) { - return ld.ProviderRegion, nil + region := tpgresource.GetResourceNameFromSelfLink(ld.ProviderRegion.ValueString()) // Region could be a self link + return types.StringValue(region), nil } // Region from zone in provider config if !ld.ProviderZone.IsNull() && !ld.ProviderZone.IsUnknown() && !ld.ProviderZone.Equal(types.StringValue("")) { - region := tpgresource.GetRegionFromZone(ld.ProviderZone.ValueString()) - return types.StringValue(region), nil + region := tpgresource.GetResourceNameFromSelfLink(ld.ProviderZone.ValueString()) // Region could be a self link + return types.StringValue(tpgresource.GetRegionFromZone(region)), nil } var err error @@ -103,7 +113,9 @@ func (ld *LocationDescription) GetZone() (types.String, error) { return types.StringValue(zone), nil } if !ld.ProviderZone.IsNull() && !ld.ProviderZone.IsUnknown() && !ld.ProviderZone.Equal(types.StringValue("")) { - return ld.ProviderZone, nil + // Zone could be a self link + zone := tpgresource.GetResourceNameFromSelfLink(ld.ProviderZone.ValueString()) + return types.StringValue(zone), nil } var err error diff --git a/mmv1/third_party/terraform/fwresource/framework_location_test.go b/mmv1/third_party/terraform/fwresource/framework_location_test.go index 8204030d68e1..1e5c5026715a 100644 --- a/mmv1/third_party/terraform/fwresource/framework_location_test.go +++ b/mmv1/third_party/terraform/fwresource/framework_location_test.go @@ -126,11 +126,23 @@ func TestLocationDescription_GetRegion(t *testing.T) { }, ExpectedRegion: types.StringValue("provider-zone"), // is truncated }, - "does not shorten region values when derived from a zone self link set in the resource config": { + "shortens region values when derived from a zone self link set in the resource config": { ld: LocationDescription{ ResourceZone: types.StringValue("https://www.googleapis.com/compute/v1/projects/my-project/zones/us-central1-a"), }, - ExpectedRegion: types.StringValue("https://www.googleapis.com/compute/v1/projects/my-project/zones/us-central1"), // Value isn't shortened from URI to name + ExpectedRegion: types.StringValue("us-central1"), + }, + "shortens region values set as self links in the provider config": { + ld: LocationDescription{ + ProviderRegion: types.StringValue("https://www.googleapis.com/compute/v1/projects/my-project/regions/us-central1"), + }, + ExpectedRegion: types.StringValue("us-central1"), + }, + "shortens region values when derived from a zone self link set in the provider config": { + ld: LocationDescription{ + ProviderZone: types.StringValue("https://www.googleapis.com/compute/v1/projects/my-project/zones/us-central1-a"), + }, + ExpectedRegion: types.StringValue("us-central1"), }, "returns the value of the region field in provider config when region/zone is unset in resource config": { ld: LocationDescription{ @@ -228,11 +240,11 @@ func TestLocationDescription_GetLocation(t *testing.T) { }, ExpectedLocation: types.StringValue("resource-location"), }, - "does not shorten the location value when it is set as a self link in the resource config": { + "shortens the location value when it is set as a self link in the resource config": { ld: LocationDescription{ ResourceLocation: types.StringValue("https://www.googleapis.com/compute/v1/projects/my-project/locations/resource-location"), }, - ExpectedLocation: types.StringValue("https://www.googleapis.com/compute/v1/projects/my-project/locations/resource-location"), + ExpectedLocation: types.StringValue("resource-location"), }, "returns the region value set in the resource config when location is not in the schema": { ld: LocationDescription{ @@ -241,11 +253,11 @@ func TestLocationDescription_GetLocation(t *testing.T) { }, ExpectedLocation: types.StringValue("resource-region"), }, - "does not shorten the region value when it is set as a self link in the resource config": { + "shortens the region value when it is set as a self link in the resource config": { ld: LocationDescription{ ResourceRegion: types.StringValue("https://www.googleapis.com/compute/v1/projects/my-project/regions/resource-region"), }, - ExpectedLocation: types.StringValue("https://www.googleapis.com/compute/v1/projects/my-project/regions/resource-region"), + ExpectedLocation: types.StringValue("resource-region"), }, "returns the zone value set in the resource config when neither location nor region in the schema": { ld: LocationDescription{ @@ -259,18 +271,24 @@ func TestLocationDescription_GetLocation(t *testing.T) { }, ExpectedLocation: types.StringValue("resource-zone-a"), }, - "returns the zone value from the provider config when none of location/region/zone are set in the resource config": { + "returns the region value from the provider config when none of location/region/zone are set in the resource config": { ld: LocationDescription{ - ProviderRegion: types.StringValue("provider-region"), // unused + ProviderRegion: types.StringValue("provider-region"), // Preferred to use region value over zone value if both are set ProviderZone: types.StringValue("provider-zone-a"), }, + ExpectedLocation: types.StringValue("provider-region"), + }, + "returns the zone value from the provider config when none of location/region/zone are set in the resource config and region is not set in the provider config": { + ld: LocationDescription{ + ProviderZone: types.StringValue("provider-zone-a"), + }, ExpectedLocation: types.StringValue("provider-zone-a"), }, - "does not shorten the zone value when it is set as a self link in the provider config": { + "shortens the zone value when it is set as a self link in the provider config": { ld: LocationDescription{ ProviderZone: types.StringValue("https://www.googleapis.com/compute/v1/projects/my-project/zones/provider-zone-a"), }, - ExpectedLocation: types.StringValue("https://www.googleapis.com/compute/v1/projects/my-project/zones/provider-zone-a"), + ExpectedLocation: types.StringValue("provider-zone-a"), }, // Handling of empty strings "returns the region value set in the resource config when location is an empty string": { @@ -297,13 +315,6 @@ func TestLocationDescription_GetLocation(t *testing.T) { }, ExpectedLocation: types.StringValue("provider-zone-a"), }, - // Error states - "does not use the region value set in the provider config": { - ld: LocationDescription{ - ProviderRegion: types.StringValue("provider-region"), - }, - ExpectedError: true, - }, "returns an error when none of location/region/zone are set on the resource, and neither region or zone is set on the provider": { ExpectedError: true, }, diff --git a/mmv1/third_party/terraform/tpgresource/field_helpers.go b/mmv1/third_party/terraform/tpgresource/field_helpers.go index a6e700c71ba4..919b04cd6898 100644 --- a/mmv1/third_party/terraform/tpgresource/field_helpers.go +++ b/mmv1/third_party/terraform/tpgresource/field_helpers.go @@ -387,7 +387,8 @@ func GetRegionFromSchema(regionSchemaField, zoneSchemaField string, d TerraformR return GetResourceNameFromSelfLink(v.(string)), nil } if v, ok := d.GetOk(zoneSchemaField); ok && zoneSchemaField != "" { - return GetRegionFromZone(v.(string)), nil + zone := GetResourceNameFromSelfLink(v.(string)) + return GetRegionFromZone(zone), nil } if config.Region != "" { return config.Region, nil diff --git a/mmv1/third_party/terraform/tpgresource/regional_utils.go b/mmv1/third_party/terraform/tpgresource/regional_utils.go index e9c98e615b90..b771a84c8bea 100644 --- a/mmv1/third_party/terraform/tpgresource/regional_utils.go +++ b/mmv1/third_party/terraform/tpgresource/regional_utils.go @@ -17,17 +17,25 @@ func IsZone(location string) bool { // - location argument in the resource config // - region argument in the resource config // - zone argument in the resource config +// - region argument in the provider config // - zone argument set in the provider config func GetLocation(d TerraformResourceData, config *transport_tpg.Config) (string, error) { if v, ok := d.GetOk("location"); ok { - return v.(string), nil + return GetResourceNameFromSelfLink(v.(string)), nil } else if v, isRegionalCluster := d.GetOk("region"); isRegionalCluster { - return v.(string), nil + return GetResourceNameFromSelfLink(v.(string)), nil } else { - // If region is not explicitly set, use "zone" (or fall back to the provider-level zone). - // For now, to avoid confusion, we require region to be set in the config to create a regional - // cluster rather than falling back to the provider-level region. - return GetZone(d, config) + if v, ok := d.GetOk("zone"); ok { + return GetResourceNameFromSelfLink(v.(string)), nil + } else { + if config.Region != "" { + return GetResourceNameFromSelfLink(config.Region), nil + } else if config.Zone != "" { + return GetResourceNameFromSelfLink(config.Zone), nil + } else { + return "", fmt.Errorf("Unable to determine location: region/zone not configured in resource/provider config") + } + } } } diff --git a/mmv1/third_party/terraform/tpgresource/utils_test.go b/mmv1/third_party/terraform/tpgresource/utils_test.go index f5b5a6ccf825..b815ff762473 100644 --- a/mmv1/third_party/terraform/tpgresource/utils_test.go +++ b/mmv1/third_party/terraform/tpgresource/utils_test.go @@ -239,11 +239,11 @@ func TestGetLocation(t *testing.T) { }, ExpectedLocation: "resource-location", }, - "does not shorten the location value when it is set as a self link in the resource config": { + "shortens the location value when it is set as a self link in the resource config": { ResourceConfig: map[string]interface{}{ "location": "https://www.googleapis.com/compute/v1/projects/my-project/locations/resource-location", }, - ExpectedLocation: "https://www.googleapis.com/compute/v1/projects/my-project/locations/resource-location", // No shortening takes place + ExpectedLocation: "resource-location", }, "returns the region value set in the resource config when location is not in the schema": { ResourceConfig: map[string]interface{}{ @@ -252,11 +252,11 @@ func TestGetLocation(t *testing.T) { }, ExpectedLocation: "resource-region", }, - "does not shorten the region value when it is set as a self link in the resource config": { + "shortens the region value when it is set as a self link in the resource config": { ResourceConfig: map[string]interface{}{ "region": "https://www.googleapis.com/compute/v1/projects/my-project/region/resource-region", }, - ExpectedLocation: "https://www.googleapis.com/compute/v1/projects/my-project/region/resource-region", // No shortening takes place + ExpectedLocation: "resource-region", }, "returns the zone value set in the resource config when neither location nor region in the schema": { ResourceConfig: map[string]interface{}{ @@ -278,13 +278,23 @@ func TestGetLocation(t *testing.T) { }, ExpectedLocation: "provider-zone-a", }, - "does not shorten the zone value when it is set as a self link in the provider config": { - // This behaviour makes sense because provider config values don't originate from APIs - // Users should always configure the provider with the short names of regions/zones + "returns the region value from the provider config when none of location/region/zone are set in the resource config": { + ProviderConfig: map[string]string{ + "region": "provider-region", + }, + ExpectedLocation: "provider-region", + }, + "shortens the region value when it is set as a self link in the provider config": { + ProviderConfig: map[string]string{ + "region": "https://www.googleapis.com/compute/v1/projects/my-project/region/provider-region", + }, + ExpectedLocation: "provider-region", + }, + "shortens the zone value when it is set as a self link in the provider config": { ProviderConfig: map[string]string{ "zone": "https://www.googleapis.com/compute/v1/projects/my-project/zones/provider-zone-a", }, - ExpectedLocation: "https://www.googleapis.com/compute/v1/projects/my-project/zones/provider-zone-a", + ExpectedLocation: "provider-zone-a", }, // Handling of empty strings "returns the region value set in the resource config when location is an empty string": { @@ -313,13 +323,18 @@ func TestGetLocation(t *testing.T) { }, ExpectedLocation: "provider-zone-a", }, - // Error states - "returns an error when only a region value is set in the the provider config and none of location/region/zone are set in the resource config": { + "returns the region value when only a region value is set in the the provider config and none of location/region/zone are set in the resource config": { + ResourceConfig: map[string]interface{}{ + "location": "", + "region": "", + "zone": "", + }, ProviderConfig: map[string]string{ "region": "provider-region", }, - ExpectError: true, + ExpectedLocation: "provider-region", }, + // Error states "returns an error when none of location/region/zone are set on the resource, and neither region or zone is set on the provider": { ExpectError: true, }, @@ -498,11 +513,11 @@ func TestGetRegion(t *testing.T) { }, ExpectedRegion: "resource-zone", // is truncated }, - "does not shorten region values when derived from a zone self link set in the resource config": { + "shortens region values when derived from a zone self link set in the resource config": { ResourceConfig: map[string]interface{}{ "zone": "https://www.googleapis.com/compute/v1/projects/my-project/zones/us-central1-a", }, - ExpectedRegion: "https://www.googleapis.com/compute/v1/projects/my-project/zones/us-central1", // Value is not shortenedfrom URI to name + ExpectedRegion: "us-central1", }, "returns the value of the region field in provider config when region/zone is unset in resource config": { ProviderConfig: map[string]string{ From 83df04114dd8f94bff865079d04b37dd0979f2fa Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Fri, 22 Sep 2023 15:47:28 +0100 Subject: [PATCH 48/67] Unignore empty values in the `provider` configuration block in 5.0.0 (#9014) * Stop validating `""` as valid `credentials` value in the PF provider config * Remove code that makes PF ignore empty values * Update PF config code tests to match change in PF config code behaviour * Update remaining PF config code tests * Update test for the PF version of credentials validator * Make not on SDK version of credentials validator that it cannot distinguish between `""` in config vs zero values --- .../framework_provider_internal_test.go | 3 +- .../fwprovider/framework_validators.go | 3 +- .../fwtransport/framework_config.go.erb | 81 -------- .../fwtransport/framework_config_test.go.erb | 188 +++++++++--------- .../terraform/provider/provider.go.erb | 2 + .../provider/provider_internal_test.go | 4 +- 6 files changed, 99 insertions(+), 182 deletions(-) diff --git a/mmv1/third_party/terraform/fwprovider/framework_provider_internal_test.go b/mmv1/third_party/terraform/fwprovider/framework_provider_internal_test.go index e81196794205..aa866ac10451 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_provider_internal_test.go +++ b/mmv1/third_party/terraform/fwprovider/framework_provider_internal_test.go @@ -44,10 +44,11 @@ func TestFrameworkProvider_CredentialsValidator(t *testing.T) { return types.StringValue(stringContents) }, }, - "configuring credentials as an empty string is valid": { + "configuring credentials as an empty string is not valid": { ConfigValue: func(t *testing.T) types.String { return types.StringValue("") }, + ExpectedErrorCount: 1, }, "leaving credentials unconfigured is valid": { ConfigValue: func(t *testing.T) types.String { diff --git a/mmv1/third_party/terraform/fwprovider/framework_validators.go b/mmv1/third_party/terraform/fwprovider/framework_validators.go index 31bf849d0368..3a0af4733d92 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_validators.go +++ b/mmv1/third_party/terraform/fwprovider/framework_validators.go @@ -7,7 +7,6 @@ import ( "time" "github.com/hashicorp/terraform-plugin-framework/schema/validator" - "github.com/hashicorp/terraform-plugin-framework/types" googleoauth "golang.org/x/oauth2/google" ) @@ -31,7 +30,7 @@ func (v credentialsValidator) MarkdownDescription(ctx context.Context) string { // ValidateString performs the validation. func (v credentialsValidator) ValidateString(ctx context.Context, request validator.StringRequest, response *validator.StringResponse) { - if request.ConfigValue.IsNull() || request.ConfigValue.IsUnknown() || request.ConfigValue.Equal(types.StringValue("")) { + if request.ConfigValue.IsNull() || request.ConfigValue.IsUnknown() { return } diff --git a/mmv1/third_party/terraform/fwtransport/framework_config.go.erb b/mmv1/third_party/terraform/fwtransport/framework_config.go.erb index 8a1bc8c7b6ba..8c510cbe155c 100644 --- a/mmv1/third_party/terraform/fwtransport/framework_config.go.erb +++ b/mmv1/third_party/terraform/fwtransport/framework_config.go.erb @@ -17,7 +17,6 @@ import ( "google.golang.org/grpc" "github.com/hashicorp/go-cleanhttp" - "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -56,15 +55,6 @@ type FrameworkProviderConfig struct { // LoadAndValidateFramework handles the bulk of configuring the provider // it is pulled out so that we can manually call this from our testing provider as well func (p *FrameworkProviderConfig) LoadAndValidateFramework(ctx context.Context, data *fwmodels.ProviderModel, tfVersion string, diags *diag.Diagnostics, providerversion string) { - - - // Make the plugin framwork code behave like the SDK by ignoring zero values. This means re-setting zero values to null. - // This is added to fix https://github.com/hashicorp/terraform-provider-google/issues/14255 in a v4.x.x release - // TODO(SarahFrench) remove as part of https://github.com/hashicorp/terraform-provider-google/issues/14447 in 5.0.0 - p.HandleZeroValues(ctx, data, diags) - if diags.HasError() { - return - } // Set defaults if needed p.HandleDefaults(ctx, data, diags) @@ -115,77 +105,6 @@ func (p *FrameworkProviderConfig) LoadAndValidateFramework(ctx context.Context, p.RequestBatcherIam = transport_tpg.NewRequestBatcher("IAM", ctx, batchingConfig) } -// HandleZeroValues will make the plugin framework act like the SDK; zero value, particularly empty strings, are converted to null. -// This causes the plugin framework to treat the field as unset, just like how the SDK ignores empty strings. -func (p *FrameworkProviderConfig) HandleZeroValues(ctx context.Context, data *fwmodels.ProviderModel, diags *diag.Diagnostics) { - - // Change empty strings to null values - if data.AccessToken.Equal(types.StringValue("")) { - data.AccessToken = types.StringNull() - } - if data.BillingProject.Equal(types.StringValue("")) { - data.BillingProject = types.StringNull() - } - if data.Credentials.Equal(types.StringValue("")) { - data.Credentials = types.StringNull() - } - if data.ImpersonateServiceAccount.Equal(types.StringValue("")) { - data.ImpersonateServiceAccount = types.StringNull() - } - if data.Project.Equal(types.StringValue("")) { - data.Project = types.StringNull() - } - if data.Region.Equal(types.StringValue("")) { - data.Region = types.StringNull() - } - if data.RequestReason.Equal(types.StringValue("")) { - data.RequestReason = types.StringNull() - } - if data.RequestTimeout.Equal(types.StringValue("")) { - data.RequestTimeout = types.StringNull() - } - if data.Zone.Equal(types.StringValue("")) { - data.Zone = types.StringNull() - } - - // Change lists that aren't null or unknown with length of zero to null lists - if !data.Scopes.IsNull() && !data.Scopes.IsUnknown() && (len(data.Scopes.Elements()) == 0) { - data.Scopes = types.ListNull(types.StringType) - } - if !data.ImpersonateServiceAccountDelegates.IsNull() && !data.ImpersonateServiceAccountDelegates.IsUnknown() && (len(data.ImpersonateServiceAccountDelegates.Elements()) == 0) { - data.ImpersonateServiceAccountDelegates = types.ListNull(types.StringType) - } - - // Batching implementation will change in future, but this code will be removed in 5.0.0 so may be unaffected - if !data.Batching.IsNull() && !data.Batching.IsUnknown() && (len(data.Batching.Elements()) > 0) { - var pbConfigs []fwmodels.ProviderBatching - d := data.Batching.ElementsAs(ctx, &pbConfigs, true) - diags.Append(d...) - if diags.HasError() { - return - } - if pbConfigs[0].SendAfter.Equal(types.StringValue("")) { - pbConfigs[0].SendAfter = types.StringNull() // Convert empty string to null - } - b, _ := types.ObjectValue( - map[string]attr.Type{ - "enable_batching": types.BoolType, - "send_after": types.StringType, - }, - map[string]attr.Value{ - "enable_batching": pbConfigs[0].EnableBatching, - "send_after": pbConfigs[0].SendAfter, - }, - ) - newBatching, d := types.ListValue(types.ObjectType{}.WithAttributeTypes(fwmodels.ProviderBatchingAttributes), []attr.Value{b}) - diags.Append(d...) - if diags.HasError() { - return - } - data.Batching = newBatching - } -} - // HandleDefaults will handle all the defaults necessary in the provider func (p *FrameworkProviderConfig) HandleDefaults(ctx context.Context, data *fwmodels.ProviderModel, diags *diag.Diagnostics) { if (data.AccessToken.IsNull() || data.AccessToken.IsUnknown()) && (data.Credentials.IsNull() || data.Credentials.IsUnknown()) { diff --git a/mmv1/third_party/terraform/fwtransport/framework_config_test.go.erb b/mmv1/third_party/terraform/fwtransport/framework_config_test.go.erb index 37c11069bd51..07e1accd25de 100644 --- a/mmv1/third_party/terraform/fwtransport/framework_config_test.go.erb +++ b/mmv1/third_party/terraform/fwtransport/framework_config_test.go.erb @@ -102,22 +102,22 @@ func TestFrameworkProvider_LoadAndValidateFramework_project(t *testing.T) { ExpectedConfigStructValue: types.StringNull(), }, // Handling empty strings in config - "when project is set as an empty string the field is treated as if it's unset, without error": { + "when project is set as an empty string the empty string is used and not ignored": { ConfigValues: fwmodels.ProviderModel{ Project: types.StringValue(""), }, - ExpectedDataModelValue: types.StringNull(), - ExpectedConfigStructValue: types.StringNull(), + ExpectedDataModelValue: types.StringValue(""), + ExpectedConfigStructValue: types.StringValue(""), }, - "when project is set as an empty string an environment variable will be used": { + "when project is set as an empty string, the empty string is not ignored in favor of an environment variable": { ConfigValues: fwmodels.ProviderModel{ Project: types.StringValue(""), }, EnvVariables: map[string]string{ "GOOGLE_PROJECT": "project-from-GOOGLE_PROJECT", }, - ExpectedDataModelValue: types.StringValue("project-from-GOOGLE_PROJECT"), - ExpectedConfigStructValue: types.StringValue("project-from-GOOGLE_PROJECT"), + ExpectedDataModelValue: types.StringValue(""), + ExpectedConfigStructValue: types.StringValue(""), }, // Handling unknown values "when project is an unknown value, the provider treats it as if it's unset and uses an environment variable instead": { @@ -143,7 +143,7 @@ func TestFrameworkProvider_LoadAndValidateFramework_project(t *testing.T) { tfVersion := "foobar" providerversion := "999" diags := diag.Diagnostics{} - + data := tc.ConfigValues data.Credentials = types.StringValue(transport_tpg.TestFakeCredentialsPath) impersonateServiceAccountDelegates, _ := types.ListValue(types.StringType, []attr.Value{}) // empty list @@ -194,40 +194,40 @@ func TestFrameworkProvider_LoadAndValidateFramework_credentials(t *testing.T) { }{ "credentials can be configured as a path to a credentials JSON file": { ConfigValues: fwmodels.ProviderModel{ - Credentials: types.StringValue(transport_tpg.TestFakeCredentialsPath), - }, - ExpectedDataModelValue: types.StringValue(transport_tpg.TestFakeCredentialsPath), - }, - "configuring credentials as a path to a non-existent file results in an error": { - ConfigValues: fwmodels.ProviderModel{ - Credentials: types.StringValue(pathToMissingFile), - }, - ExpectError: true, - }, - "credentials set in the config are not overridden by environment variables": { - ConfigValues: fwmodels.ProviderModel{ - Credentials: types.StringValue(acctest.GenerateFakeCredentialsJson("test")), - }, - EnvVariables: map[string]string{ - "GOOGLE_CREDENTIALS": acctest.GenerateFakeCredentialsJson("GOOGLE_CREDENTIALS"), - "GOOGLE_CLOUD_KEYFILE_JSON": acctest.GenerateFakeCredentialsJson("GOOGLE_CLOUD_KEYFILE_JSON"), - "GCLOUD_KEYFILE_JSON": acctest.GenerateFakeCredentialsJson("GCLOUD_KEYFILE_JSON"), - "GOOGLE_APPLICATION_CREDENTIALS": acctest.GenerateFakeCredentialsJson("GOOGLE_APPLICATION_CREDENTIALS"), - }, - ExpectedDataModelValue: types.StringValue(acctest.GenerateFakeCredentialsJson("test")), - }, - "when credentials is unset in the config, environment variables are used: GOOGLE_CREDENTIALS used first": { - ConfigValues: fwmodels.ProviderModel{ - Credentials: types.StringNull(), // unset - }, - EnvVariables: map[string]string{ - "GOOGLE_CREDENTIALS": acctest.GenerateFakeCredentialsJson("GOOGLE_CREDENTIALS"), - "GOOGLE_CLOUD_KEYFILE_JSON": acctest.GenerateFakeCredentialsJson("GOOGLE_CLOUD_KEYFILE_JSON"), - "GCLOUD_KEYFILE_JSON": acctest.GenerateFakeCredentialsJson("GCLOUD_KEYFILE_JSON"), - "GOOGLE_APPLICATION_CREDENTIALS": acctest.GenerateFakeCredentialsJson("GOOGLE_APPLICATION_CREDENTIALS"), - }, - ExpectedDataModelValue: types.StringValue(acctest.GenerateFakeCredentialsJson("GOOGLE_CREDENTIALS")), + Credentials: types.StringValue(transport_tpg.TestFakeCredentialsPath), + }, + ExpectedDataModelValue: types.StringValue(transport_tpg.TestFakeCredentialsPath), + }, + "configuring credentials as a path to a non-existent file results in an error": { + ConfigValues: fwmodels.ProviderModel{ + Credentials: types.StringValue(pathToMissingFile), + }, + ExpectError: true, + }, + "credentials set in the config are not overridden by environment variables": { + ConfigValues: fwmodels.ProviderModel{ + Credentials: types.StringValue(acctest.GenerateFakeCredentialsJson("test")), + }, + EnvVariables: map[string]string{ + "GOOGLE_CREDENTIALS": acctest.GenerateFakeCredentialsJson("GOOGLE_CREDENTIALS"), + "GOOGLE_CLOUD_KEYFILE_JSON": acctest.GenerateFakeCredentialsJson("GOOGLE_CLOUD_KEYFILE_JSON"), + "GCLOUD_KEYFILE_JSON": acctest.GenerateFakeCredentialsJson("GCLOUD_KEYFILE_JSON"), + "GOOGLE_APPLICATION_CREDENTIALS": acctest.GenerateFakeCredentialsJson("GOOGLE_APPLICATION_CREDENTIALS"), + }, + ExpectedDataModelValue: types.StringValue(acctest.GenerateFakeCredentialsJson("test")), + }, + "when credentials is unset in the config, environment variables are used: GOOGLE_CREDENTIALS used first": { + ConfigValues: fwmodels.ProviderModel{ + Credentials: types.StringNull(), // unset + }, + EnvVariables: map[string]string{ + "GOOGLE_CREDENTIALS": acctest.GenerateFakeCredentialsJson("GOOGLE_CREDENTIALS"), + "GOOGLE_CLOUD_KEYFILE_JSON": acctest.GenerateFakeCredentialsJson("GOOGLE_CLOUD_KEYFILE_JSON"), + "GCLOUD_KEYFILE_JSON": acctest.GenerateFakeCredentialsJson("GCLOUD_KEYFILE_JSON"), + "GOOGLE_APPLICATION_CREDENTIALS": acctest.GenerateFakeCredentialsJson("GOOGLE_APPLICATION_CREDENTIALS"), }, + ExpectedDataModelValue: types.StringValue(acctest.GenerateFakeCredentialsJson("GOOGLE_CREDENTIALS")), + }, "when credentials is unset in the config, environment variables are used: GOOGLE_CLOUD_KEYFILE_JSON used second": { ConfigValues: fwmodels.ProviderModel{ Credentials: types.StringNull(), // unset @@ -264,15 +264,15 @@ func TestFrameworkProvider_LoadAndValidateFramework_credentials(t *testing.T) { }, ExpectedDataModelValue: types.StringNull(), }, - // Handling empty strings in config - "when credentials is set to an empty string in the config (and access_token unset), GOOGLE_APPLICATION_CREDENTIALS is used": { + // Error states + "when credentials is set to an empty string in the config the value isn't ignored and results in an error": { ConfigValues: fwmodels.ProviderModel{ Credentials: types.StringValue(""), }, EnvVariables: map[string]string{ "GOOGLE_APPLICATION_CREDENTIALS": transport_tpg.TestFakeCredentialsPath, // needs to be a path to a file when used by code }, - ExpectedDataModelValue: types.StringNull(), + ExpectError: true, }, // NOTE: these tests can't run in Cloud Build due to ADC locating credentials despite `GOOGLE_APPLICATION_CREDENTIALS` being unset // See https://cloud.google.com/docs/authentication/application-default-credentials#search_order @@ -433,22 +433,22 @@ func TestFrameworkProvider_LoadAndValidateFramework_billingProject(t *testing.T) ExpectedConfigStructValue: types.StringNull(), }, // Handling empty strings in config - "when billing_project is set as an empty string the field is treated as if it's unset, without error": { + "when billing_project is set as an empty string the empty string is used and not ignored": { ConfigValues: fwmodels.ProviderModel{ BillingProject: types.StringValue(""), }, - ExpectedDataModelValue: types.StringNull(), - ExpectedConfigStructValue: types.StringNull(), + ExpectedDataModelValue: types.StringValue(""), + ExpectedConfigStructValue: types.StringValue(""), }, - "when billing_project is set as an empty string an environment variable will be used": { + "when billing_project is set as an empty string, the empty string is not ignored in favor of an environment variable": { ConfigValues: fwmodels.ProviderModel{ BillingProject: types.StringValue(""), }, EnvVariables: map[string]string{ "GOOGLE_BILLING_PROJECT": "billing-project-from-env", }, - ExpectedDataModelValue: types.StringValue("billing-project-from-env"), - ExpectedConfigStructValue: types.StringValue("billing-project-from-env"), + ExpectedDataModelValue: types.StringValue(""), + ExpectedConfigStructValue: types.StringValue(""), }, } @@ -496,7 +496,6 @@ func TestFrameworkProvider_LoadAndValidateFramework_billingProject(t *testing.T) } } - func TestFrameworkProvider_LoadAndValidateFramework_region(t *testing.T) { // Note: In the test function we need to set the below fields in test case's fwmodels.ProviderModel value @@ -548,22 +547,22 @@ func TestFrameworkProvider_LoadAndValidateFramework_region(t *testing.T) { ExpectedConfigStructValue: types.StringNull(), }, // Handling empty strings in config - "when region is set as an empty string the field is treated as if it's unset, without error": { + "when region is set as an empty string the empty string is used and not ignored": { ConfigValues: fwmodels.ProviderModel{ Region: types.StringValue(""), }, - ExpectedDataModelValue: types.StringNull(), - ExpectedConfigStructValue: types.StringNull(), + ExpectedDataModelValue: types.StringValue(""), + ExpectedConfigStructValue: types.StringValue(""), }, - "when region is set as an empty string an environment variable will be used": { + "when region is set as an empty string, the empty string is not ignored in favor of an environment variable": { ConfigValues: fwmodels.ProviderModel{ Region: types.StringValue(""), }, EnvVariables: map[string]string{ "GOOGLE_REGION": "region-from-env", }, - ExpectedDataModelValue: types.StringValue("region-from-env"), - ExpectedConfigStructValue: types.StringValue("region-from-env"), + ExpectedDataModelValue: types.StringValue(""), + ExpectedConfigStructValue: types.StringValue(""), }, // Handling unknown values "when region is an unknown value, the provider treats it as if it's unset and uses an environment variable instead": { @@ -698,22 +697,22 @@ func TestFrameworkProvider_LoadAndValidateFramework_zone(t *testing.T) { ExpectedConfigStructValue: types.StringNull(), }, // Handling empty strings in config - "when zone is set as an empty string the field is treated as if it's unset, without error": { + "when zone is set as an empty string the empty string is used and not ignored": { ConfigValues: fwmodels.ProviderModel{ Zone: types.StringValue(""), }, - ExpectedDataModelValue: types.StringNull(), - ExpectedConfigStructValue: types.StringNull(), + ExpectedDataModelValue: types.StringValue(""), + ExpectedConfigStructValue: types.StringValue(""), }, - "when zone is set as an empty string an environment variable will be used": { + "when zone is set as an empty string, the empty string is not ignored in favor of an environment variable": { ConfigValues: fwmodels.ProviderModel{ Zone: types.StringValue(""), }, EnvVariables: map[string]string{ "GOOGLE_ZONE": "zone-from-env", }, - ExpectedDataModelValue: types.StringValue("zone-from-env"), - ExpectedConfigStructValue: types.StringValue("zone-from-env"), + ExpectedDataModelValue: types.StringValue(""), + ExpectedConfigStructValue: types.StringValue(""), }, // Handling unknown values "when zone is an unknown value, the provider treats it as if it's unset and uses an environment variable instead": { @@ -780,11 +779,11 @@ func TestFrameworkProvider_LoadAndValidateFramework_accessToken(t *testing.T) { // - ImpersonateServiceAccountDelegates: If we don't set this, we get a nil pointer exception ¯\_(ツ)_/¯ cases := map[string]struct { - ConfigValues fwmodels.ProviderModel - EnvVariables map[string]string - ExpectedDataModelValue basetypes.StringValue // Sometimes the value is mutated, and no longer matches the original value we supply + ConfigValues fwmodels.ProviderModel + EnvVariables map[string]string + ExpectedDataModelValue basetypes.StringValue // Sometimes the value is mutated, and no longer matches the original value we supply // ExpectedConfigStructValue not used here, as credentials info isn't stored in the config struct - ExpectError bool + ExpectError bool }{ "access_token configured in the provider can be invalid without resulting in errors": { ConfigValues: fwmodels.ProviderModel{ @@ -815,21 +814,20 @@ func TestFrameworkProvider_LoadAndValidateFramework_accessToken(t *testing.T) { ExpectedDataModelValue: types.StringNull(), }, // Handling empty strings in config - "when access_token is set as an empty string the field is treated as if it's unset, without error (as long as credentials supplied in its absence)": { + "when access_token is set as an empty string the empty string is used and not ignored": { ConfigValues: fwmodels.ProviderModel{ AccessToken: types.StringValue(""), - Credentials: types.StringValue(transport_tpg.TestFakeCredentialsPath), }, - ExpectedDataModelValue: types.StringNull(), + ExpectedDataModelValue: types.StringValue(""), }, - "when access_token is set as an empty string in the config, an environment variable is used": { + "when access_token is set as an empty string, the empty string is not ignored in favor of an environment variable": { ConfigValues: fwmodels.ProviderModel{ AccessToken: types.StringValue(""), }, EnvVariables: map[string]string{ "GOOGLE_OAUTH_ACCESS_TOKEN": "value-from-GOOGLE_OAUTH_ACCESS_TOKEN", }, - ExpectedDataModelValue: types.StringValue("value-from-GOOGLE_OAUTH_ACCESS_TOKEN"), + ExpectedDataModelValue: types.StringValue(""), }, // Handling unknown values "when access_token is an unknown value, the provider treats it as if it's unset and uses an environment variable instead": { @@ -1058,20 +1056,20 @@ func TestFrameworkProvider_LoadAndValidateFramework_impersonateServiceAccount(t ExpectedDataModelValue: types.StringNull(), }, // Handling empty strings in config - "when impersonate_service_account is set as an empty string the field is treated as if it's unset, without error": { + "when impersonate_service_account is set as an empty string the empty string is used and not ignored": { ConfigValues: fwmodels.ProviderModel{ ImpersonateServiceAccount: types.StringValue(""), }, - ExpectedDataModelValue: types.StringNull(), + ExpectedDataModelValue: types.StringValue(""), }, - "when impersonate_service_account is set as an empty string in the config, an environment variable is used": { + "when impersonate_service_account is set as an empty string, the empty string is not ignored in favor of an environment variable": { ConfigValues: fwmodels.ProviderModel{ ImpersonateServiceAccount: types.StringValue(""), }, EnvVariables: map[string]string{ "GOOGLE_IMPERSONATE_SERVICE_ACCOUNT": "value-from-env@example.com", }, - ExpectedDataModelValue: types.StringValue("value-from-env@example.com"), + ExpectedDataModelValue: types.StringValue(""), }, // Handling unknown values "when impersonate_service_account is an unknown value, the provider treats it as if it's unset and uses an environment variable instead": { @@ -1158,13 +1156,13 @@ func TestFrameworkProvider_LoadAndValidateFramework_impersonateServiceAccountDel }, // Note: no environment variables can be used for impersonate_service_account_delegates "when no impersonate_service_account_delegates value is provided via config, the field remains unset without error": { - SetAsNull: true, // not setting impersonate_service_account_delegates + SetAsNull: true, // not setting impersonate_service_account_delegates ExpectedNull: true, }, // Handling empty values in config - "when impersonate_service_account_delegates is set as an empty array the field is treated as if it's unset, without error": { + "when impersonate_service_account_delegates is set as an empty array, that value isn't ignored": { ImpersonateServiceAccountDelegatesValue: []string{}, - ExpectedDataModelValue: nil, + ExpectedDataModelValue: []string{}, }, // Handling unknown values "when impersonate_service_account_delegates is an unknown value, the provider treats it as if it's unset, without error": { @@ -1371,20 +1369,20 @@ func TestFrameworkProvider_LoadAndValidateFramework_requestReason(t *testing.T) ExpectedDataModelValue: types.StringNull(), }, // Handling empty strings in config - "when request_reason is set as an empty string in the config it is overridden by environment variables": { + "when request_reason is set as an empty string, the empty string is not ignored in favor of an environment variable": { ConfigValues: fwmodels.ProviderModel{ RequestReason: types.StringValue(""), }, EnvVariables: map[string]string{ "CLOUDSDK_CORE_REQUEST_REASON": "foo", }, - ExpectedDataModelValue: types.StringValue("foo"), + ExpectedDataModelValue: types.StringValue(""), }, - "when request_reason is set as an empty string in the config the field is treated as if it's unset, without error": { + "when request_reason is set as an empty string the empty string is used and not ignored": { ConfigValues: fwmodels.ProviderModel{ RequestReason: types.StringValue(""), }, - ExpectedDataModelValue: types.StringNull(), + ExpectedDataModelValue: types.StringValue(""), }, // Handling unknown values "when request_reason is an unknown value, the provider treats it as if it's unset and uses an environment variable instead": { @@ -1466,6 +1464,12 @@ func TestFrameworkProvider_LoadAndValidateFramework_requestTimeout(t *testing.T) }, ExpectError: true, }, + "when request_timeout is set as an empty string, the empty string isn't ignored and an error will occur": { + ConfigValues: fwmodels.ProviderModel{ + RequestTimeout: types.StringValue(""), + }, + ExpectError: true, + }, // In the SDK version of the provider config code, this scenario results in a value of "0s" // instead of "120s", but the final 'effective' value is also "120s" // See : https://github.com/hashicorp/terraform-provider-google/blob/09cb850ee64bcd78e4457df70905530c1ed75f19/google/transport/config.go#L1228-L1233 @@ -1475,13 +1479,6 @@ func TestFrameworkProvider_LoadAndValidateFramework_requestTimeout(t *testing.T) }, ExpectedDataModelValue: types.StringValue("120s"), }, - // Handling empty strings in config - "when request_timeout is set as an empty string, the default value is 120s.": { - ConfigValues: fwmodels.ProviderModel{ - RequestTimeout: types.StringValue(""), - }, - ExpectedDataModelValue: types.StringValue("120s"), - }, // Handling unknown values "when request_timeout is an unknown value, the provider treats it as if it's unset and uses the default value 120s": { ConfigValues: fwmodels.ProviderModel{ @@ -1585,13 +1582,6 @@ func TestFrameworkProvider_LoadAndValidateFramework_batching(t *testing.T) { ExpectEnableBatchingValue: types.BoolValue(true), ExpectSendAfterValue: types.StringValue("3s"), }, - // Handling empty strings in config - "when batching is configured with send_after as an empty string, send_after will be set to a default value": { - EnableBatchingValue: types.BoolValue(true), - SendAfterValue: types.StringValue(""), - ExpectEnableBatchingValue: types.BoolValue(true), - ExpectSendAfterValue: types.StringValue("10s"), // When batching block is present but has missing arguments inside, default is 10s - }, // Handling unknown values "when batching is an unknown value, the provider treats it as if it's unset (align to SDK behaviour)": { SetBatchingAsUnknown: true, @@ -1611,6 +1601,11 @@ func TestFrameworkProvider_LoadAndValidateFramework_batching(t *testing.T) { ExpectSendAfterValue: types.StringValue("45s"), }, // Error states + "when batching is configured with send_after as an empty string, the empty string is not ignored and results in an error": { + EnableBatchingValue: types.BoolValue(true), + SendAfterValue: types.StringValue(""), + ExpectError: true, + }, "if batching is configured with send_after as an invalid value, there's an error": { SendAfterValue: types.StringValue("invalid value"), ExpectError: true, @@ -1716,4 +1711,3 @@ func TestFrameworkProvider_LoadAndValidateFramework_batching(t *testing.T) { }) } } - diff --git a/mmv1/third_party/terraform/provider/provider.go.erb b/mmv1/third_party/terraform/provider/provider.go.erb index 82a2fe84ca80..271bda2397f2 100644 --- a/mmv1/third_party/terraform/provider/provider.go.erb +++ b/mmv1/third_party/terraform/provider/provider.go.erb @@ -774,6 +774,8 @@ func ValidateCredentials(v interface{}, k string) (warnings []string, errors []e if v == nil || v.(string) == "" { return } + // NOTE: Above we have to allow empty string as valid because we don't know if it's a zero value or not + creds := v.(string) // if this is a path and we can stat it, assume it's ok if _, err := os.Stat(creds); err == nil { diff --git a/mmv1/third_party/terraform/provider/provider_internal_test.go b/mmv1/third_party/terraform/provider/provider_internal_test.go index 27a15710ffda..00bcac3d5926 100644 --- a/mmv1/third_party/terraform/provider/provider_internal_test.go +++ b/mmv1/third_party/terraform/provider/provider_internal_test.go @@ -42,7 +42,9 @@ func TestProvider_ValidateCredentials(t *testing.T) { return string(contents) }, }, - "configuring credentials as an empty string is valid": { + // There's a risk of changing the validator to saying "" is invalid, as it may mean that + // everyone not using the credentials field would get validation errors. + "configuring credentials as an empty string is not identified as invalid by the function, as it can't distinguish from zero values ": { ConfigValue: func(t *testing.T) interface{} { return "" }, From 637451103ddbee94521b6f58bce788894dbfd158 Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Fri, 22 Sep 2023 11:49:51 -0500 Subject: [PATCH 49/67] Sync 5.0.0 with main (#9039) --- .../membership-checker/membership.go | 1 + .ci/magician/github/membership.go | 2 +- mmv1/products/identityplatform/Config.yaml | 2 +- mmv1/products/osconfig/PatchDeployment.yaml | 13 +- mmv1/products/secretmanager/Secret.yaml | 6 +- .../securitycenter/ProjectCustomModule.yaml | 197 +++ .../constants/secret_manager_secret.go | 25 + .../identity_platform_config_minimal.tf.erb | 4 + .../os_config_patch_deployment_full.tf.erb | 3 +- .../scc_project_custom_module_basic.tf.erb | 17 + .../scc_project_custom_module_full.tf.erb | 31 + .../fwtransport/framework_config_test.go.erb | 112 +- .../terraform/provider/provider.go.erb | 1 + ...gle_certificate_manager_certificate_map.go | 44 + ...ertificate_manager_certificate_map_test.go | 109 ++ .../pubsub/resource_pubsub_schema_test.go | 22 - ...resource_scc_project_custom_module_test.go | 77 ++ ...cate_manager_certificate_map.html.markdown | 30 + .../d/compute_instance_template.html.markdown | 2 + .../guides/version_5_upgrade.html.markdown | 6 + .../r/compute_instance_template.html.markdown | 2 + tools/diff-processor/cmd/breaking_changes.go | 37 +- .../cmd/breaking_changes_test.go | 106 ++ tools/diff-processor/cmd/root.go | 8 +- tools/diff-processor/diff/comparison.go | 134 --- tools/diff-processor/diff/comparison_test.go | 344 ------ tools/diff-processor/diff/diff.go | 222 ++++ tools/diff-processor/diff/diff_test.go | 1072 +++++++++++++++++ tools/diff-processor/go.mod | 14 +- tools/diff-processor/go.sum | 7 +- .../diff-processor/rules/breaking_changes.go | 52 + .../rules/breaking_changes_test.go | 344 ++++++ tools/diff-processor/rules/rules_field.go | 28 + .../diff-processor/rules/rules_field_test.go | 116 ++ .../rules/rules_resource_inventory.go | 24 +- .../rules/rules_resource_inventory_test.go | 123 +- .../rules/rules_resource_schema.go | 21 +- .../rules/rules_resource_schema_test.go | 98 +- 38 files changed, 2689 insertions(+), 767 deletions(-) create mode 100644 mmv1/products/securitycenter/ProjectCustomModule.yaml create mode 100644 mmv1/templates/terraform/constants/secret_manager_secret.go create mode 100644 mmv1/templates/terraform/examples/scc_project_custom_module_basic.tf.erb create mode 100644 mmv1/templates/terraform/examples/scc_project_custom_module_full.tf.erb create mode 100644 mmv1/third_party/terraform/services/certificatemanager/data_source_google_certificate_manager_certificate_map.go create mode 100644 mmv1/third_party/terraform/services/certificatemanager/data_source_google_certificate_manager_certificate_map_test.go create mode 100644 mmv1/third_party/terraform/services/securitycenter/resource_scc_project_custom_module_test.go create mode 100644 mmv1/third_party/terraform/website/docs/d/certificate_manager_certificate_map.html.markdown create mode 100644 tools/diff-processor/cmd/breaking_changes_test.go delete mode 100644 tools/diff-processor/diff/comparison.go delete mode 100644 tools/diff-processor/diff/comparison_test.go create mode 100644 tools/diff-processor/diff/diff.go create mode 100644 tools/diff-processor/diff/diff_test.go create mode 100644 tools/diff-processor/rules/breaking_changes.go create mode 100644 tools/diff-processor/rules/breaking_changes_test.go diff --git a/.ci/containers/membership-checker/membership.go b/.ci/containers/membership-checker/membership.go index 1dcd332721f8..848408bbfb8d 100644 --- a/.ci/containers/membership-checker/membership.go +++ b/.ci/containers/membership-checker/membership.go @@ -30,6 +30,7 @@ var ( // 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{ + "melinath", "roaks3", } ) diff --git a/.ci/magician/github/membership.go b/.ci/magician/github/membership.go index 6ed6a6da7395..296da0b65a7a 100644 --- a/.ci/magician/github/membership.go +++ b/.ci/magician/github/membership.go @@ -31,7 +31,7 @@ var ( // 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{ - "slevenick", + "melinath", "roaks3", } ) diff --git a/mmv1/products/identityplatform/Config.yaml b/mmv1/products/identityplatform/Config.yaml index 55a2c57347b0..19de848c6ca6 100644 --- a/mmv1/products/identityplatform/Config.yaml +++ b/mmv1/products/identityplatform/Config.yaml @@ -59,7 +59,6 @@ examples: org_id: :ORG_ID billing_acct: :BILLING_ACCT - skip_vcr: true skip_docs: true custom_code: !ruby/object:Provider::Terraform::CustomCode custom_create: 'templates/terraform/custom_create/identity_platform_config.go' @@ -77,6 +76,7 @@ properties: name: 'signIn' description: | Configuration related to local sign in methods. + default_from_api: true properties: - !ruby/object:Api::Type::NestedObject name: email diff --git a/mmv1/products/osconfig/PatchDeployment.yaml b/mmv1/products/osconfig/PatchDeployment.yaml index b2c994585e21..10485867be82 100644 --- a/mmv1/products/osconfig/PatchDeployment.yaml +++ b/mmv1/products/osconfig/PatchDeployment.yaml @@ -396,10 +396,12 @@ properties: properties: - !ruby/object:Api::Type::Array name: 'classifications' - exactly_one_of: + at_least_one_of: - patch_config.0.windows_update.0.classifications - patch_config.0.windows_update.0.excludes - patch_config.0.windows_update.0.exclusive_patches + conflicts: + - patch_config.0.windows_update.0.exclusive_patches description: | Only apply updates of these windows update classifications. If empty, all updates are applied. item_type: !ruby/object:Api::Type::Enum @@ -417,19 +419,24 @@ properties: - :UPDATE - !ruby/object:Api::Type::Array name: 'excludes' - exactly_one_of: + at_least_one_of: - patch_config.0.windows_update.0.classifications - patch_config.0.windows_update.0.excludes - patch_config.0.windows_update.0.exclusive_patches + conflicts: + - patch_config.0.windows_update.0.exclusive_patches description: | List of KBs to exclude from update. item_type: Api::Type::String - !ruby/object:Api::Type::Array name: 'exclusivePatches' - exactly_one_of: + at_least_one_of: - patch_config.0.windows_update.0.classifications - patch_config.0.windows_update.0.excludes - patch_config.0.windows_update.0.exclusive_patches + conflicts: + - patch_config.0.windows_update.0.classifications + - patch_config.0.windows_update.0.excludes description: | An exclusive list of kbs to be updated. These are the only patches that will be updated. This field must not be used with other patch configurations. diff --git a/mmv1/products/secretmanager/Secret.yaml b/mmv1/products/secretmanager/Secret.yaml index 63d6315bf9aa..e96497b776f7 100644 --- a/mmv1/products/secretmanager/Secret.yaml +++ b/mmv1/products/secretmanager/Secret.yaml @@ -49,6 +49,8 @@ examples: import_format: ['projects/{{project}}/secrets/{{secret_id}}'] custom_code: !ruby/object:Provider::Terraform::CustomCode pre_update: templates/terraform/pre_update/secret_manager_secret.go.erb + constants: templates/terraform/constants/secret_manager_secret.go +custom_diff: ['secretManagerSecretAutoCustomizeDiff'] parameters: - !ruby/object:Api::Type::String name: secretId @@ -70,7 +72,7 @@ properties: description: | The time at which the Secret was created. - !ruby/object:Api::Type::KeyValueLabels - name: 'labels' + name: labels description: | The labels assigned to this Secret. @@ -85,7 +87,7 @@ properties: An object containing a list of "key": value pairs. Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }. - !ruby/object:Api::Type::KeyValueAnnotations - name: 'annotations' + name: annotations description: | Custom metadata about the secret. diff --git a/mmv1/products/securitycenter/ProjectCustomModule.yaml b/mmv1/products/securitycenter/ProjectCustomModule.yaml new file mode 100644 index 000000000000..c723c8c710a5 --- /dev/null +++ b/mmv1/products/securitycenter/ProjectCustomModule.yaml @@ -0,0 +1,197 @@ +# Copyright 2023 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: 'ProjectCustomModule' +description: | + Represents an instance of a Security Health Analytics custom module, including + its full module name, display name, enablement state, and last updated time. + You can create a custom module at the organization, folder, or project level. + Custom modules that you create at the organization or folder level are inherited + by the child folders and projects. +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Overview of custom modules for Security Health Analytics': 'https://cloud.google.com/security-command-center/docs/custom-modules-sha-overview' + api: 'https://cloud.google.com/security-command-center/docs/reference/rest/v1/projects.securityHealthAnalyticsSettings.customModules' +base_url: 'projects/{{project}}/securityHealthAnalyticsSettings/customModules' +self_link: 'projects/{{project}}/securityHealthAnalyticsSettings/customModules/{{name}}' +mutex: 'projects/{{project}}/securityHealthAnalyticsSettings/customModules' +update_verb: :PATCH +update_mask: true +examples: + - !ruby/object:Provider::Terraform::Examples + name: "scc_project_custom_module_basic" + primary_resource_id: "example" + - !ruby/object:Provider::Terraform::Examples + name: "scc_project_custom_module_full" + primary_resource_id: "example" + +properties: + - !ruby/object:Api::Type::String + name: 'name' + output: true + custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb + description: | + The resource name of the custom module. Its format is "projects/{project}/securityHealthAnalyticsSettings/customModules/{customModule}". + The id {customModule} is server-generated and is not user settable. It will be a numeric id containing 1-20 digits. + - !ruby/object:Api::Type::String + name: 'displayName' + immutable: true + required: true + # API error for invalid display names is just "INVALID_ARGUMENT" with no details + validation: !ruby/object:Provider::Terraform::Validation + function: 'verify.ValidateRegexp(`^[a-z][\w_]{0,127}$`)' + description: | + The display name of the Security Health Analytics custom module. This + display name becomes the finding category for all findings that are + returned by this custom module. The display name must be between 1 and + 128 characters, start with a lowercase letter, and contain alphanumeric + characters or underscores only. + - !ruby/object:Api::Type::Enum + name: 'enablementState' + required: true + description: | + The enablement state of the custom module. + values: + - :ENABLED + - :DISABLED + - !ruby/object:Api::Type::String + name: 'updateTime' + output: true + description: | + The time at which the custom module was last updated. + + A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and + up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". + - !ruby/object:Api::Type::String + name: 'lastEditor' + output: true + description: | + The editor that last updated the custom module. + - !ruby/object:Api::Type::String + name: 'ancestorModule' + output: true + description: | + If empty, indicates that the custom module was created in the organization,folder, + or project in which you are viewing the custom module. Otherwise, ancestor_module + specifies the organization or folder from which the custom module is inherited. + - !ruby/object:Api::Type::NestedObject + name: 'customConfig' + required: true + description: | + The user specified custom configuration for the module. + properties: + - !ruby/object:Api::Type::NestedObject + name: 'predicate' + required: true + description: | + The CEL expression to evaluate to produce findings. When the expression evaluates + to true against a resource, a finding is generated. + properties: + - !ruby/object:Api::Type::String + name: 'expression' + required: true + description: | + Textual representation of an expression in Common Expression Language syntax. + - !ruby/object:Api::Type::String + name: 'title' + description: | + Title for the expression, i.e. a short string describing its purpose. This can + be used e.g. in UIs which allow to enter the expression. + - !ruby/object:Api::Type::String + name: 'description' + description: | + Description of the expression. This is a longer text which describes the + expression, e.g. when hovered over it in a UI. + - !ruby/object:Api::Type::String + name: 'location' + description: | + String indicating the location of the expression for error reporting, e.g. a + file name and a position in the file. + - !ruby/object:Api::Type::NestedObject + name: 'customOutput' + description: | + Custom output properties. + properties: + - !ruby/object:Api::Type::Array + name: 'properties' + description: | + A list of custom output properties to add to the finding. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'name' + description: | + Name of the property for the custom output. + - !ruby/object:Api::Type::NestedObject + name: 'valueExpression' + description: | + The CEL expression for the custom output. A resource property can be specified + to return the value of the property or a text string enclosed in quotation marks. + properties: + - !ruby/object:Api::Type::String + name: 'expression' + required: true + description: | + Textual representation of an expression in Common Expression Language syntax. + - !ruby/object:Api::Type::String + name: 'title' + description: | + Title for the expression, i.e. a short string describing its purpose. This can + be used e.g. in UIs which allow to enter the expression. + - !ruby/object:Api::Type::String + name: 'description' + description: | + Description of the expression. This is a longer text which describes the + expression, e.g. when hovered over it in a UI. + - !ruby/object:Api::Type::String + name: 'location' + description: | + String indicating the location of the expression for error reporting, e.g. a + file name and a position in the file. + - !ruby/object:Api::Type::NestedObject + name: 'resourceSelector' + required: true + description: | + The resource types that the custom module operates on. Each custom module + can specify up to 5 resource types. + properties: + - !ruby/object:Api::Type::Array + name: 'resourceTypes' + required: true + description: | + The resource types to run the detector on. + item_type: Api::Type::String + - !ruby/object:Api::Type::Enum + name: 'severity' + required: true + description: | + The severity to assign to findings generated by the module. + values: + - :CRITICAL + - :HIGH + - :MEDIUM + - :LOW + - !ruby/object:Api::Type::String + name: 'description' + description: | + Text that describes the vulnerability or misconfiguration that the custom + module detects. This explanation is returned with each finding instance to + help investigators understand the detected issue. The text must be enclosed in quotation marks. + - !ruby/object:Api::Type::String + name: 'recommendation' + required: true + description: | + An explanation of the recommended steps that security teams can take to resolve + the detected issue. This explanation is returned with each finding generated by + this module in the nextSteps property of the finding JSON. diff --git a/mmv1/templates/terraform/constants/secret_manager_secret.go b/mmv1/templates/terraform/constants/secret_manager_secret.go new file mode 100644 index 000000000000..13db855f5e7e --- /dev/null +++ b/mmv1/templates/terraform/constants/secret_manager_secret.go @@ -0,0 +1,25 @@ +// Prevent ForceNew when upgrading replication.automatic -> replication.auto +func secretManagerSecretAutoCustomizeDiff(_ context.Context, diff *schema.ResourceDiff, meta interface{}) error { + oAutomatic, nAutomatic := diff.GetChange("replication.0.automatic") + _, nAuto := diff.GetChange("replication.0.auto") + autoLen := len(nAuto.([]interface{})) + + // Do not ForceNew if we are removing "automatic" while adding "auto" + if oAutomatic == true && nAutomatic == false && autoLen > 0 { + return nil + } + + if diff.HasChange("replication.0.automatic") { + if err := diff.ForceNew("replication.0.automatic"); err != nil { + return err + } + } + + if diff.HasChange("replication.0.auto") { + if err := diff.ForceNew("replication.0.auto"); err != nil { + return err + } + } + + return nil +} diff --git a/mmv1/templates/terraform/examples/identity_platform_config_minimal.tf.erb b/mmv1/templates/terraform/examples/identity_platform_config_minimal.tf.erb index 4a9299dec8c8..c026f04822fc 100644 --- a/mmv1/templates/terraform/examples/identity_platform_config_minimal.tf.erb +++ b/mmv1/templates/terraform/examples/identity_platform_config_minimal.tf.erb @@ -16,4 +16,8 @@ resource "google_project_service" "identitytoolkit" { resource "google_identity_platform_config" "default" { project = google_project.default.project_id + + depends_on = [ + google_project_service.identitytoolkit + ] } diff --git a/mmv1/templates/terraform/examples/os_config_patch_deployment_full.tf.erb b/mmv1/templates/terraform/examples/os_config_patch_deployment_full.tf.erb index d95d70b62e0c..161ab079be8a 100644 --- a/mmv1/templates/terraform/examples/os_config_patch_deployment_full.tf.erb +++ b/mmv1/templates/terraform/examples/os_config_patch_deployment_full.tf.erb @@ -16,7 +16,7 @@ resource "google_os_config_patch_deployment" "<%= ctx[:primary_resource_id] %>" patch_config { mig_instances_allowed = true - + reboot_config = "ALWAYS" apt { @@ -40,6 +40,7 @@ resource "google_os_config_patch_deployment" "<%= ctx[:primary_resource_id] %>" windows_update { classifications = ["CRITICAL", "SECURITY", "UPDATE"] + excludes = ["5012170"] } pre_step { diff --git a/mmv1/templates/terraform/examples/scc_project_custom_module_basic.tf.erb b/mmv1/templates/terraform/examples/scc_project_custom_module_basic.tf.erb new file mode 100644 index 000000000000..f52bff0780da --- /dev/null +++ b/mmv1/templates/terraform/examples/scc_project_custom_module_basic.tf.erb @@ -0,0 +1,17 @@ +resource "google_scc_project_custom_module" "<%= ctx[:primary_resource_id] %>" { + display_name = "basic_custom_module" + enablement_state = "ENABLED" + custom_config { + predicate { + expression = "resource.rotationPeriod > duration(\"2592000s\")" + } + resource_selector { + resource_types = [ + "cloudkms.googleapis.com/CryptoKey", + ] + } + description = "The rotation period of the identified cryptokey resource exceeds 30 days." + recommendation = "Set the rotation period to at most 30 days." + severity = "MEDIUM" + } +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/scc_project_custom_module_full.tf.erb b/mmv1/templates/terraform/examples/scc_project_custom_module_full.tf.erb new file mode 100644 index 000000000000..2fa6803b27e7 --- /dev/null +++ b/mmv1/templates/terraform/examples/scc_project_custom_module_full.tf.erb @@ -0,0 +1,31 @@ +resource "google_scc_project_custom_module" "<%= ctx[:primary_resource_id] %>" { + display_name = "full_custom_module" + enablement_state = "ENABLED" + custom_config { + predicate { + expression = "resource.rotationPeriod > duration(\"2592000s\")" + title = "Purpose of the expression" + description = "description of the expression" + location = "location of the expression" + } + custom_output { + properties { + name = "duration" + value_expression { + expression = "resource.rotationPeriod" + title = "Purpose of the expression" + description = "description of the expression" + location = "location of the expression" + } + } + } + resource_selector { + resource_types = [ + "cloudkms.googleapis.com/CryptoKey", + ] + } + severity = "LOW" + description = "Description of the custom module" + recommendation = "Steps to resolve violation" + } +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/fwtransport/framework_config_test.go.erb b/mmv1/third_party/terraform/fwtransport/framework_config_test.go.erb index 07e1accd25de..6a273183d4ad 100644 --- a/mmv1/third_party/terraform/fwtransport/framework_config_test.go.erb +++ b/mmv1/third_party/terraform/fwtransport/framework_config_test.go.erb @@ -335,61 +335,63 @@ func TestFrameworkProvider_LoadAndValidateFramework_credentials(t *testing.T) { } } -func TestFrameworkProvider_LoadAndValidateFramework_credentials_unknown(t *testing.T) { - // This test case is kept separate from other credentials tests, as it requires comparing - // error messages returned by two different error states: - // - When credentials = Null - // - When credentials = Unknown - - t.Run("the same error is returned whether credentials is set as a null or unknown value (and access_token isn't set)", func(t *testing.T) { - - // Arrange - acctest.UnsetTestProviderConfigEnvs(t) - - ctx := context.Background() - tfVersion := "foobar" - providerversion := "999" - - impersonateServiceAccountDelegates, _ := types.ListValue(types.StringType, []attr.Value{}) // empty list - - // Null data and error collection - diagsNull := diag.Diagnostics{} - dataNull := fwmodels.ProviderModel{ - Credentials: types.StringNull(), - } - dataNull.ImpersonateServiceAccountDelegates = impersonateServiceAccountDelegates - - // Unknown data and error collection - diagsUnknown := diag.Diagnostics{} - dataUnknown := fwmodels.ProviderModel{ - Credentials: types.StringUnknown(), - } - dataUnknown.ImpersonateServiceAccountDelegates = impersonateServiceAccountDelegates - - pNull := fwtransport.FrameworkProviderConfig{} - pUnknown := fwtransport.FrameworkProviderConfig{} - - // Act - pNull.LoadAndValidateFramework(ctx, &dataNull, tfVersion, &diagsNull, providerversion) - pUnknown.LoadAndValidateFramework(ctx, &dataUnknown, tfVersion, &diagsUnknown, providerversion) - - // Assert - if !diagsNull.HasError() { - t.Fatalf("expect errors when credentials is null, but [%d] errors occurred", diagsNull.ErrorsCount()) - } - if !diagsUnknown.HasError() { - t.Fatalf("expect errors when credentials is unknown, but [%d] errors occurred", diagsUnknown.ErrorsCount()) - } - - errNull := diagsNull.Errors() - errUnknown := diagsUnknown.Errors() - for i := 0; i < len(errNull); i++ { - if errNull[i] != errUnknown[i] { - t.Fatalf("expect errors to be the same for null and unknown credentials values, instead got \nnull=`%s` \nunknown=%s", errNull[i], errUnknown[i]) - } - } - }) -} +// NOTE: these tests can't run in Cloud Build due to ADC locating credentials despite `GOOGLE_APPLICATION_CREDENTIALS` being unset +// See https://cloud.google.com/docs/authentication/application-default-credentials#search_order +// Also, when running these tests locally you need to run `gcloud auth application-default revoke` to ensure your machine isn't supplying ADCs +// func TestFrameworkProvider_LoadAndValidateFramework_credentials_unknown(t *testing.T) { +// // This test case is kept separate from other credentials tests, as it requires comparing +// // error messages returned by two different error states: +// // - When credentials = Null +// // - When credentials = Unknown + +// t.Run("the same error is returned whether credentials is set as a null or unknown value (and access_token isn't set)", func(t *testing.T) { +// // Arrange +// acctest.UnsetTestProviderConfigEnvs(t) + +// ctx := context.Background() +// tfVersion := "foobar" +// providerversion := "999" + +// impersonateServiceAccountDelegates, _ := types.ListValue(types.StringType, []attr.Value{}) // empty list + +// // Null data and error collection +// diagsNull := diag.Diagnostics{} +// dataNull := fwmodels.ProviderModel{ +// Credentials: types.StringNull(), +// } +// dataNull.ImpersonateServiceAccountDelegates = impersonateServiceAccountDelegates + +// // Unknown data and error collection +// diagsUnknown := diag.Diagnostics{} +// dataUnknown := fwmodels.ProviderModel{ +// Credentials: types.StringUnknown(), +// } +// dataUnknown.ImpersonateServiceAccountDelegates = impersonateServiceAccountDelegates + +// pNull := fwtransport.FrameworkProviderConfig{} +// pUnknown := fwtransport.FrameworkProviderConfig{} + +// // Act +// pNull.LoadAndValidateFramework(ctx, &dataNull, tfVersion, &diagsNull, providerversion) +// pUnknown.LoadAndValidateFramework(ctx, &dataUnknown, tfVersion, &diagsUnknown, providerversion) + +// // Assert +// if !diagsNull.HasError() { +// t.Fatalf("expect errors when credentials is null, but [%d] errors occurred", diagsNull.ErrorsCount()) +// } +// if !diagsUnknown.HasError() { +// t.Fatalf("expect errors when credentials is unknown, but [%d] errors occurred", diagsUnknown.ErrorsCount()) +// } + +// errNull := diagsNull.Errors() +// errUnknown := diagsUnknown.Errors() +// for i := 0; i < len(errNull); i++ { +// if errNull[i] != errUnknown[i] { +// t.Fatalf("expect errors to be the same for null and unknown credentials values, instead got \nnull=`%s` \nunknown=%s", errNull[i], errUnknown[i]) +// } +// } +// }) +// } func TestFrameworkProvider_LoadAndValidateFramework_billingProject(t *testing.T) { diff --git a/mmv1/third_party/terraform/provider/provider.go.erb b/mmv1/third_party/terraform/provider/provider.go.erb index 271bda2397f2..530ef450cb61 100644 --- a/mmv1/third_party/terraform/provider/provider.go.erb +++ b/mmv1/third_party/terraform/provider/provider.go.erb @@ -219,6 +219,7 @@ func DatasourceMapWithErrors() (map[string]*schema.Resource, error) { "google_beyondcorp_app_gateway": beyondcorp.DataSourceGoogleBeyondcorpAppGateway(), "google_billing_account": billing.DataSourceGoogleBillingAccount(), "google_bigquery_default_service_account": bigquery.DataSourceGoogleBigqueryDefaultServiceAccount(), + "google_certificate_manager_certificate_map": certificatemanager.DataSourceGoogleCertificateManagerCertificateMap(), "google_cloudbuild_trigger": cloudbuild.DataSourceGoogleCloudBuildTrigger(), "google_cloudfunctions_function": cloudfunctions.DataSourceGoogleCloudFunctionsFunction(), "google_cloudfunctions2_function": cloudfunctions2.DataSourceGoogleCloudFunctions2Function(), diff --git a/mmv1/third_party/terraform/services/certificatemanager/data_source_google_certificate_manager_certificate_map.go b/mmv1/third_party/terraform/services/certificatemanager/data_source_google_certificate_manager_certificate_map.go new file mode 100644 index 000000000000..0c87129f0d06 --- /dev/null +++ b/mmv1/third_party/terraform/services/certificatemanager/data_source_google_certificate_manager_certificate_map.go @@ -0,0 +1,44 @@ +package certificatemanager + +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 DataSourceGoogleCertificateManagerCertificateMap() *schema.Resource { + + dsSchema := tpgresource.DatasourceSchemaFromResourceSchema(ResourceCertificateManagerCertificateMap().Schema) + tpgresource.AddRequiredFieldsToSchema(dsSchema, "name") + tpgresource.AddOptionalFieldsToSchema(dsSchema, "project") + + return &schema.Resource{ + Read: dataSourceGoogleCertificateManagerCertificateMapRead, + Schema: dsSchema, + } +} + +func dataSourceGoogleCertificateManagerCertificateMapRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + + name := d.Get("name").(string) + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return err + } + + id := fmt.Sprintf("projects/%s/locations/global/certificateMaps/%s", project, name) + d.SetId(id) + err = resourceCertificateManagerCertificateMapRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil +} diff --git a/mmv1/third_party/terraform/services/certificatemanager/data_source_google_certificate_manager_certificate_map_test.go b/mmv1/third_party/terraform/services/certificatemanager/data_source_google_certificate_manager_certificate_map_test.go new file mode 100644 index 000000000000..7ca8c9c1f20d --- /dev/null +++ b/mmv1/third_party/terraform/services/certificatemanager/data_source_google_certificate_manager_certificate_map_test.go @@ -0,0 +1,109 @@ +package certificatemanager_test + +import ( + "fmt" + "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 TestAccDataSourceGoogleCertificateManagerCertificateMap_basic(t *testing.T) { + t.Parallel() + + project := envvar.GetTestProjectFromEnv() + + description := "My acceptance data source test certificate map" + name := fmt.Sprintf("tf-test-certificate-map-%d", acctest.RandInt(t)) + id := fmt.Sprintf("projects/%s/locations/global/certificateMaps/%s", project, name) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccDataSourceGoogleCertificateManagerCertificateMap_basic(name, description), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.google_certificate_manager_certificate_map.cert_map_data", "id", id), + resource.TestCheckResourceAttr("data.google_certificate_manager_certificate_map.cert_map_data", "description", description), + resource.TestCheckResourceAttr("data.google_certificate_manager_certificate_map.cert_map_data", "name", name), + ), + }, + }, + }) +} + +func testAccDataSourceGoogleCertificateManagerCertificateMap_basic(certificateMapName, certificateMapDescription string) string { + return fmt.Sprintf(` +resource "google_certificate_manager_certificate_map" "cert_map" { + name = "%s" + description = "%s" + labels = { + "terraform" : true, + "acc-test" : true, + } +} +data "google_certificate_manager_certificate_map" "cert_map_data" { + name = google_certificate_manager_certificate_map.cert_map.name +} +`, certificateMapName, certificateMapDescription) +} + +func TestAccDataSourceGoogleCertificateManagerCertificateMap_certificateMapEntryUsingMapDatasource(t *testing.T) { + t.Parallel() + + project := envvar.GetTestProjectFromEnv() + + certName := fmt.Sprintf("tf-test-certificate-%d", acctest.RandInt(t)) + mapEntryName := fmt.Sprintf("tf-test-certificate-map-entry-%d", acctest.RandInt(t)) + mapName := fmt.Sprintf("tf-test-certificate-map-%d", acctest.RandInt(t)) + id := fmt.Sprintf("projects/%s/locations/global/certificateMaps/%s", project, mapName) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccDataSourceGoogleCertificateManagerCertificateMap_certificateMapEntryUsingMapDatasource(mapName, mapEntryName, certName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.google_certificate_manager_certificate_map.cert_map_data", "id", id), + resource.TestCheckResourceAttr("data.google_certificate_manager_certificate_map.cert_map_data", "name", mapName), + resource.TestCheckResourceAttr("google_certificate_manager_certificate_map_entry.cert_map_entry", "map", mapName), // check that the certificate map entry is referencing the data source + + ), + }, + }, + }) +} + +func testAccDataSourceGoogleCertificateManagerCertificateMap_certificateMapEntryUsingMapDatasource(certificateMapName, certificateMapEntryName, certificateName string) string { + return fmt.Sprintf(` +resource "google_certificate_manager_certificate_map" "cert_map" { + name = "%s" + description = "certificate map example created for testing data sources in TF" + labels = { + "terraform" : true, + "acc-test" : true, + } +} +data "google_certificate_manager_certificate_map" "cert_map_data" { + name = google_certificate_manager_certificate_map.cert_map.name +} +resource "google_certificate_manager_certificate" "certificate" { + name = "%s" + description = "Global cert" + self_managed { + pem_certificate = file("test-fixtures/cert.pem") + pem_private_key = file("test-fixtures/private-key.pem") + } +} +resource "google_certificate_manager_certificate_map_entry" "cert_map_entry" { + name = "%s" + description = "certificate map entry that reference a data source of certificate map and a self managed certificate" + map = data.google_certificate_manager_certificate_map.cert_map_data.name + certificates = [google_certificate_manager_certificate.certificate.id] + matcher = "PRIMARY" +} +`, certificateMapName, certificateName, certificateMapEntryName) +} diff --git a/mmv1/third_party/terraform/services/pubsub/resource_pubsub_schema_test.go b/mmv1/third_party/terraform/services/pubsub/resource_pubsub_schema_test.go index abd7ad5a212e..68b193d71afd 100644 --- a/mmv1/third_party/terraform/services/pubsub/resource_pubsub_schema_test.go +++ b/mmv1/third_party/terraform/services/pubsub/resource_pubsub_schema_test.go @@ -48,17 +48,6 @@ func testAccPubsubSchema_basic(schema string) string { type = "PROTOCOL_BUFFER" definition = "syntax = \"proto3\";\nmessage Results {\nstring message_request = 1;\nstring message_response = 2;\n}" } - - # Need to introduce delay for updates in order for tests to complete - # successfully due to caching effects. - resource "time_sleep" "wait_121_seconds" { - create_duration = "121s" - lifecycle { - replace_triggered_by = [ - google_pubsub_schema.foo - ] - } - } `, schema) } @@ -69,16 +58,5 @@ func testAccPubsubSchema_updated(schema string) string { type = "PROTOCOL_BUFFER" definition = "syntax = \"proto3\";\nmessage Results {\nstring message_request = 1;\nstring message_response = 2;\nstring timestamp_request = 3;\n}" } - - # Need to introduce delay for updates in order for tests to complete - # successfully due to caching effects. - resource "time_sleep" "wait_121_seconds" { - create_duration = "121s" - lifecycle { - replace_triggered_by = [ - google_pubsub_schema.foo - ] - } - } `, schema) } diff --git a/mmv1/third_party/terraform/services/securitycenter/resource_scc_project_custom_module_test.go b/mmv1/third_party/terraform/services/securitycenter/resource_scc_project_custom_module_test.go new file mode 100644 index 000000000000..37e73a4e6cce --- /dev/null +++ b/mmv1/third_party/terraform/services/securitycenter/resource_scc_project_custom_module_test.go @@ -0,0 +1,77 @@ +package securitycenter_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccSecurityCenterProjectCustomModule_sccProjectCustomModuleUpdate(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: testAccCheckSecurityCenterProjectCustomModuleDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccSecurityCenterProjectCustomModule_sccProjectCustomModuleFullExample(context), + }, + { + ResourceName: "google_scc_project_custom_module.example", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccSecurityCenterProjectCustomModule_sccProjectCustomModuleUpdate(context), + }, + { + ResourceName: "google_scc_project_custom_module.example", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccSecurityCenterProjectCustomModule_sccProjectCustomModuleUpdate(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_scc_project_custom_module" "example" { + display_name = "full_custom_module" + enablement_state = "DISABLED" + custom_config { + predicate { + expression = "resource.name == \"updated-name\"" + title = "Updated expression title" + description = "Updated description of the expression" + location = "Updated location of the expression" + } + custom_output { + properties { + name = "violation" + value_expression { + expression = "resource.name" + title = "Updated expression title" + description = "Updated description of the expression" + location = "Updated location of the expression" + } + } + } + resource_selector { + resource_types = [ + "compute.googleapis.com/Instance", + ] + } + severity = "CRITICAL" + description = "Updated description of the custom module" + recommendation = "Updated steps to resolve violation" + } +} +`, context) +} diff --git a/mmv1/third_party/terraform/website/docs/d/certificate_manager_certificate_map.html.markdown b/mmv1/third_party/terraform/website/docs/d/certificate_manager_certificate_map.html.markdown new file mode 100644 index 000000000000..20e2e4fe5b0c --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/certificate_manager_certificate_map.html.markdown @@ -0,0 +1,30 @@ +--- +subcategory: "Certificate manager" +description: |- + Contains the data that describes a Certificate Map +--- +# google_certificate_manager_certificate_map + +Get info about a Google Certificate Manager Certificate Map resource. + +## Example Usage + +```tf +data "google_certificate_manager_certificate_map" "default" { + name = "cert-map" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the certificate map. + +- - - +* `project` - (Optional) The ID of the project in which the resource belongs. If it + is not provided, the provider project is used. + +## Attributes Reference + +See [google_certificate_manager_certificate_map](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/certificate_manager_certificate_map) resource for details of the available attributes. diff --git a/mmv1/third_party/terraform/website/docs/d/compute_instance_template.html.markdown b/mmv1/third_party/terraform/website/docs/d/compute_instance_template.html.markdown index 2af65eaae691..e771c3be87c5 100644 --- a/mmv1/third_party/terraform/website/docs/d/compute_instance_template.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/compute_instance_template.html.markdown @@ -6,6 +6,8 @@ description: |- # google\_compute\_instance\_template +-> **Note**: Global instance templates can be used in any region. To lower the impact of outages outside your region and gain data residency within your region, use [google_compute_region_instance_template](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_region_instance_template). + Get information about a VM instance template resource within GCE. For more information see [the official documentation](https://cloud.google.com/compute/docs/instance-templates) and diff --git a/mmv1/third_party/terraform/website/docs/guides/version_5_upgrade.html.markdown b/mmv1/third_party/terraform/website/docs/guides/version_5_upgrade.html.markdown index d3fb8647f90c..3845211cd374 100644 --- a/mmv1/third_party/terraform/website/docs/guides/version_5_upgrade.html.markdown +++ b/mmv1/third_party/terraform/website/docs/guides/version_5_upgrade.html.markdown @@ -525,3 +525,9 @@ resource "google_secret_manager_secret" "my-secret" { ### `google_identity_platform_project_default_config` has been removed from the provider Use the `google_identity_platform_config` resource instead. It contains a more comprehensive list of fields, and was created before `google_identity_platform_project_default_config` was added. + +## Resource: `google_compute_service_attachment` + +### `reconcile_connections` now defaults from API + +`reconcile_connections` previously defaults to true. Now it will default from the API. diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown index 2d08f340fb6f..c04c64137d4d 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown @@ -6,6 +6,8 @@ description: |- # google\_compute\_instance\_template +-> **Note**: Global instance templates can be used in any region. To lower the impact of outages outside your region and gain data residency within your region, use [google_compute_region_instance_template](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_region_instance_template). + Manages a VM instance template resource within GCE. For more information see [the official documentation](https://cloud.google.com/compute/docs/instance-templates) and diff --git a/tools/diff-processor/cmd/breaking_changes.go b/tools/diff-processor/cmd/breaking_changes.go index 7d9957234449..1544f6529a00 100644 --- a/tools/diff-processor/cmd/breaking_changes.go +++ b/tools/diff-processor/cmd/breaking_changes.go @@ -1,18 +1,33 @@ package cmd + import ( - "fmt" + newProvider "google/provider/new/google/provider" + oldProvider "google/provider/old/google/provider" + + "io" + "os" "sort" - "github.com/spf13/cobra" "github.com/GoogleCloudPlatform/magic-modules/.ci/diff-processor/diff" + "github.com/GoogleCloudPlatform/magic-modules/.ci/diff-processor/rules" + "github.com/spf13/cobra" ) + const breakingChangesDesc = `Check for breaking changes between the new / old Terraform provider versions.` + type breakingChangesOptions struct { - rootOptions *rootOptions + rootOptions *rootOptions + computeSchemaDiff func() diff.SchemaDiff + stdout io.Writer } + func newBreakingChangesCmd(rootOptions *rootOptions) *cobra.Command { o := &breakingChangesOptions{ - rootOptions: rootOptions, + rootOptions: rootOptions, + computeSchemaDiff: func() diff.SchemaDiff { + return diff.ComputeSchemaDiff(oldProvider.ResourceMap(), newProvider.ResourceMap()) + }, + stdout: os.Stdout, } cmd := &cobra.Command{ Use: "breaking-changes", @@ -25,10 +40,14 @@ func newBreakingChangesCmd(rootOptions *rootOptions) *cobra.Command { return cmd } func (o *breakingChangesOptions) run() error { - breakages := diff.Compare() - sort.Strings(breakages) - for _, breakage := range breakages { - fmt.Println(breakage) + schemaDiff := o.computeSchemaDiff() + breakingChanges := rules.ComputeBreakingChanges(schemaDiff) + sort.Strings(breakingChanges) + for _, breakingChange := range breakingChanges { + _, err := o.stdout.Write([]byte(breakingChange + "\n")) + if err != nil { + return err + } } return nil -} \ No newline at end of file +} diff --git a/tools/diff-processor/cmd/breaking_changes_test.go b/tools/diff-processor/cmd/breaking_changes_test.go new file mode 100644 index 000000000000..f4e25966b4b8 --- /dev/null +++ b/tools/diff-processor/cmd/breaking_changes_test.go @@ -0,0 +1,106 @@ +package cmd + +import ( + "bytes" + "github.com/GoogleCloudPlatform/magic-modules/.ci/diff-processor/diff" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "strings" + "testing" +) + +func TestBreakingChangesCmd(t *testing.T) { + cases := map[string]struct { + oldResourceMap map[string]*schema.Resource + newResourceMap map[string]*schema.Resource + expectedViolations int + }{ + "no breaking changes": { + oldResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep", Optional: true}, + "field-b": {Description: "beep", Optional: true}, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep", Optional: true}, + "field-b": {Description: "beep", Optional: true}, + }, + }, + }, + expectedViolations: 0, + }, + "resource missing": { + oldResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep"}, + "field-b": {Description: "beep"}, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{}, + expectedViolations: 1, + }, + "field missing, resource missing, and optional to required": { + oldResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep", Optional: true}, + "field-b": {Description: "beep", Optional: true}, + }, + }, + "google-y": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep", Optional: true}, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep", Required: true}, + }, + }, + }, + expectedViolations: 3, + }, + } + + for tn, tc := range cases { + tc := tc + t.Run(tn, func(t *testing.T) { + t.Parallel() + + var buf bytes.Buffer + o := breakingChangesOptions{ + computeSchemaDiff: func() diff.SchemaDiff { + return diff.ComputeSchemaDiff(tc.oldResourceMap, tc.newResourceMap) + }, + stdout: &buf, + } + + err := o.run() + if err != nil { + t.Errorf("Error running command: %s", err) + } + + out := make([]byte, buf.Len()) + buf.Read(out) + + lines := strings.Split(string(out), "\n") + nonemptyLines := []string{} + for _, line := range lines { + if line != "" { + nonemptyLines = append(nonemptyLines, line) + } + } + if len(nonemptyLines) != tc.expectedViolations { + t.Errorf("Unexpected number of violations. Want %d, got %d. Output: %s", tc.expectedViolations, len(nonemptyLines), out) + } + }) + } +} diff --git a/tools/diff-processor/cmd/root.go b/tools/diff-processor/cmd/root.go index c749e0e31b52..ffa8c6dc71b1 100644 --- a/tools/diff-processor/cmd/root.go +++ b/tools/diff-processor/cmd/root.go @@ -1,10 +1,13 @@ package cmd + import ( "fmt" - "os" "github.com/spf13/cobra" + "os" ) + const rootCmdDesc = "Utilities for interacting with diffs between Terraform schema versions." + type rootOptions struct { } @@ -20,6 +23,7 @@ func newRootCmd() (*cobra.Command, *rootOptions, error) { cmd.AddCommand(newBreakingChangesCmd(o)) return cmd, o, nil } + // Execute is the entry-point for all commands. // This lets us keep all new command functions private. func Execute() { @@ -35,4 +39,4 @@ func Execute() { fmt.Println(err.Error()) os.Exit(1) } -} \ No newline at end of file +} diff --git a/tools/diff-processor/diff/comparison.go b/tools/diff-processor/diff/comparison.go deleted file mode 100644 index 26ad10122f38..000000000000 --- a/tools/diff-processor/diff/comparison.go +++ /dev/null @@ -1,134 +0,0 @@ -package diff - -import ( - newProvider "google/provider/new/google/provider" - oldProvider "google/provider/old/google/provider" - "strings" - - "github.com/GoogleCloudPlatform/magic-modules/.ci/diff-processor/rules" - "github.com/golang/glog" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" -) - -func Compare() []string { - resourceMapOld := oldProvider.ResourceMap() - resourceMapNew := newProvider.ResourceMap() - - return compareResourceMaps(resourceMapOld, resourceMapNew) -} - -func compareResourceMaps(old, new map[string]*schema.Resource) []string { - messages := []string{} - - for _, rule := range rules.ResourceInventoryRules { - violatingResources := rule.IsRuleBreak(old, new) - if len(violatingResources) > 0 { - for _, resourceName := range violatingResources { - newMessage := rule.Message(resourceName) - messages = append(messages, newMessage) - } - } - - } - - for resourceName, resource := range new { - oldResource, ok := old[resourceName] - if ok { - newMessages := compareResourceSchema(resourceName, oldResource.Schema, resource.Schema) - messages = append(messages, newMessages...) - } - } - - return messages -} - -func compareResourceSchema(resourceName string, old, new map[string]*schema.Schema) []string { - messages := []string{} - oldCompressed := flattenSchema(old) - newCompressed := flattenSchema(new) - - for _, rule := range rules.ResourceSchemaRules { - violatingFields := rule.IsRuleBreak(oldCompressed, newCompressed) - if len(violatingFields) > 0 { - for _, fieldName := range violatingFields { - newMessage := rule.Message(resourceName, fieldName) - messages = append(messages, newMessage) - } - } - } - - for fieldName, field := range newCompressed { - oldField, ok := oldCompressed[fieldName] - if ok { - newMessages := compareField(resourceName, fieldName, oldField, field) - messages = append(messages, newMessages...) - } - } - - return messages -} - -func compareField(resourceName, fieldName string, old, new *schema.Schema) []string { - messages := []string{} - fieldRules := rules.FieldRules - - for _, rule := range fieldRules { - breakageMessage := rule.IsRuleBreak( - old, - new, - rules.MessageContext{ - Resource: resourceName, - Field: fieldName, - }, - ) - if breakageMessage != "" { - messages = append(messages, breakageMessage) - } - } - return messages -} - -func flattenSchema(schemaObj map[string]*schema.Schema) map[string]*schema.Schema { - return flattenSchemaRecursive(nil, schemaObj) -} - -func flattenSchemaRecursive(parentLineage []string, schemaObj map[string]*schema.Schema) map[string]*schema.Schema { - compressed := make(map[string]*schema.Schema) - - // prepare prefix to bring nested entries up - parentPrefix := strings.Join(parentLineage, ".") - if len(parentPrefix) > 0 { - parentPrefix += "." - } - - // add entry to output and call - // flattenSchemaRecursive for any children - for fieldName, field := range schemaObj { - compressed[parentPrefix+fieldName] = field - casted, typeConverted := field.Elem.(*schema.Resource) - if field.Elem != nil && typeConverted { - newLineage := append([]string{}, parentLineage...) - newLineage = append(newLineage, fieldName) - compressedChild := flattenSchemaRecursive(newLineage, casted.Schema) - compressed = mergeSchemaMaps(compressed, compressedChild) - } - } - - return compressed -} - -func mergeSchemaMaps(map1, map2 map[string]*schema.Schema) map[string]*schema.Schema { - merged := make(map[string]*schema.Schema) - for key, value := range map1 { - merged[key] = value - } - - for key, value := range map2 { - if _, alreadyExists := merged[key]; alreadyExists { - glog.Errorf("error when trying to merge maps key " + key + " was found in both maps.. please ensure the children you are merging up have the prefix on the key names.") - } - merged[key] = value - } - - return merged -} diff --git a/tools/diff-processor/diff/comparison_test.go b/tools/diff-processor/diff/comparison_test.go deleted file mode 100644 index 5554148b07ed..000000000000 --- a/tools/diff-processor/diff/comparison_test.go +++ /dev/null @@ -1,344 +0,0 @@ -package diff - -import ( - "strings" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" -) - -func TestComparisonEngine(t *testing.T) { - for _, tc := range comparisonEngineTestCases { - tc.check(t) - } -} - -type comparisonEngineTestCase struct { - name string - oldResourceMap map[string]*schema.Resource - newResourceMap map[string]*schema.Resource - expectedViolations int -} - -var comparisonEngineTestCases = []comparisonEngineTestCase{ - { - name: "control", - oldResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - }, - }, - }, - expectedViolations: 0, - }, - { - name: "adding resources", - oldResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - }, - }, - "google-y": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - }, - }, - }, - expectedViolations: 0, - }, - { - name: "adding fields", - oldResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - "field-c": {Description: "beep", Optional: true}, - }, - }, - }, - expectedViolations: 0, - }, - { - name: "resource missing", - oldResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep"}, - "field-b": {Description: "beep"}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{}, - expectedViolations: 1, - }, - { - name: "field missing", - oldResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - }, - }, - }, - expectedViolations: 1, - }, - { - name: "optional field to required", - oldResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Required: true}, - "field-b": {Description: "beep", Optional: true}, - }, - }, - }, - expectedViolations: 1, - }, - { - name: "field missing and optional to required", - oldResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Required: true}, - }, - }, - }, - expectedViolations: 2, - }, - { - name: "field missing, resource missing, and optional to required", - oldResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - }, - }, - "google-y": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Required: true}, - }, - }, - }, - expectedViolations: 3, - }, - { - name: "removing a subfield", - oldResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": { - Description: "beep", - Optional: true, - Type: schema.TypeList, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "sub-field-1": {Description: "beep", Optional: true}, - "sub-field-2": {Description: "beep", Optional: true}, - }, - }, - }, - "field-b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": { - Description: "beep", - Optional: true, - Type: schema.TypeList, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "sub-field-1": {Description: "beep", Optional: true}, - }, - }, - }, - "field-b": {Description: "beep", Optional: true}, - }, - }, - }, - expectedViolations: 1, - }, - { - name: "subfield max shrinking", - oldResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": { - Description: "beep", - Optional: true, - Type: schema.TypeList, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "sub-field-1": {Description: "beep", Optional: true, MaxItems: 100}, - }, - }, - }, - "field-b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": { - Description: "beep", - Optional: true, - Type: schema.TypeList, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "sub-field-1": {Description: "beep", Optional: true, MaxItems: 25}, - }, - }, - }, - "field-b": {Description: "beep", Optional: true}, - }, - }, - }, - expectedViolations: 1, - }, - { - name: "subfield max shrinking", - oldResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": { - Description: "beep", - Optional: true, - Type: schema.TypeList, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "sub-field-1": {Description: "beep", Optional: true, MaxItems: 100}, - }, - }, - }, - "field-b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": { - Description: "beep", - Optional: true, - Type: schema.TypeList, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "sub-field-1": {Description: "beep", Optional: true, MaxItems: 25}, - }, - }, - }, - "field-b": {Description: "beep", Optional: true}, - }, - }, - }, - expectedViolations: 1, - }, - { - name: "min growing", - oldResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": { - Description: "beep", - Optional: true, - MinItems: 1, - }, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": { - Description: "beep", - Optional: true, - MinItems: 4, - }, - }, - }, - }, - expectedViolations: 1, - }, -} - -func (tc *comparisonEngineTestCase) check(t *testing.T) { - violations := compareResourceMaps(tc.oldResourceMap, tc.newResourceMap) - for _, v := range violations { - if strings.Contains(v, "{{") || strings.Contains(v, "}}") { - t.Errorf("Test `%s` failed: found unreplaced characters in string - %s", tc.name, v) - } - } - if tc.expectedViolations != len(violations) { - t.Errorf("Test `%s` failed: expected %d violations, got %d", tc.name, tc.expectedViolations, len(violations)) - } -} diff --git a/tools/diff-processor/diff/diff.go b/tools/diff-processor/diff/diff.go new file mode 100644 index 000000000000..51b3de6002dd --- /dev/null +++ b/tools/diff-processor/diff/diff.go @@ -0,0 +1,222 @@ +package diff + +import ( + "reflect" + + "golang.org/x/exp/maps" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +// SchemaDiff is a nested map with field names as keys and Field objects +// as bottom-level values. +// Fields are assumed not to be covered until detected in a test. +type SchemaDiff map[string]ResourceDiff + +type ResourceDiff struct { + ResourceConfig ResourceConfigDiff + Fields map[string]FieldDiff +} + +type ResourceConfigDiff struct { + Old *schema.Resource + New *schema.Resource +} + +type FieldDiff struct { + Old *schema.Schema + New *schema.Schema +} + +func ComputeSchemaDiff(oldResourceMap, newResourceMap map[string]*schema.Resource) SchemaDiff { + schemaDiff := make(SchemaDiff) + for resource, _ := range union(maps.Keys(oldResourceMap), maps.Keys(newResourceMap)) { + // Compute diff between old and new resources and fields. + // TODO: add support for computing diff between resource configs, not just whether the + // resource was added/removed. b/300114839 + resourceDiff := ResourceDiff{} + var flattenedOldSchema map[string]*schema.Schema + if oldResource, ok := oldResourceMap[resource]; ok { + flattenedOldSchema = flattenSchema("", oldResource.Schema) + resourceDiff.ResourceConfig.Old = &schema.Resource{} + } + + var flattenedNewSchema map[string]*schema.Schema + if newResource, ok := newResourceMap[resource]; ok { + flattenedNewSchema = flattenSchema("", newResource.Schema) + resourceDiff.ResourceConfig.New = &schema.Resource{} + } + + resourceDiff.Fields = make(map[string]FieldDiff) + for key, _ := range union(maps.Keys(flattenedOldSchema), maps.Keys(flattenedNewSchema)) { + oldField := flattenedOldSchema[key] + newField := flattenedNewSchema[key] + if fieldChanged(oldField, newField) { + resourceDiff.Fields[key] = FieldDiff{ + Old: oldField, + New: newField, + } + } + } + if len(resourceDiff.Fields) > 0 || !cmp.Equal(resourceDiff.ResourceConfig.Old, resourceDiff.ResourceConfig.New) { + schemaDiff[resource] = resourceDiff + } + } + return schemaDiff +} + +func union(keys1, keys2 []string) map[string]struct{} { + allKeys := make(map[string]struct{}) + for _, key := range keys1 { + allKeys[key] = struct{}{} + } + for _, key := range keys2 { + allKeys[key] = struct{}{} + } + return allKeys +} + +func flattenSchema(parentKey string, schemaObj map[string]*schema.Schema) map[string]*schema.Schema { + flattened := make(map[string]*schema.Schema) + + if parentKey != "" { + parentKey += "." + } + + for fieldName, field := range schemaObj { + key := parentKey + fieldName + flattened[key] = field + childResource, hasNestedFields := field.Elem.(*schema.Resource) + if field.Elem != nil && hasNestedFields { + for childKey, childField := range flattenSchema(key, childResource.Schema) { + flattened[childKey] = childField + } + } + } + + return flattened +} + +func fieldChanged(oldField, newField *schema.Schema) bool { + // If either field is nil, it is changed; if both are nil (which should never happen) it's not + if oldField == nil && newField == nil { + return false + } + if oldField == nil || newField == nil { + return true + } + // Check if any basic Schema struct fields have changed. + // https://github.com/hashicorp/terraform-plugin-sdk/blob/v2.24.0/helper/schema/schema.go#L44 + if oldField.Type != newField.Type { + return true + } + if oldField.ConfigMode != newField.ConfigMode { + return true + } + if oldField.Required != newField.Required { + return true + } + if oldField.Optional != newField.Optional { + return true + } + if oldField.Computed != newField.Computed { + return true + } + if oldField.ForceNew != newField.ForceNew { + return true + } + if oldField.DiffSuppressOnRefresh != newField.DiffSuppressOnRefresh { + return true + } + if oldField.Default != newField.Default { + return true + } + if oldField.Description != newField.Description { + return true + } + if oldField.InputDefault != newField.InputDefault { + return true + } + if oldField.MaxItems != newField.MaxItems { + return true + } + if oldField.MinItems != newField.MinItems { + return true + } + if oldField.Deprecated != newField.Deprecated { + return true + } + if oldField.Sensitive != newField.Sensitive { + return true + } + + // Compare slices + less := func(a, b string) bool { return a < b } + + if (len(oldField.ConflictsWith) > 0 || len(newField.ConflictsWith) > 0) && !cmp.Equal(oldField.ConflictsWith, newField.ConflictsWith, cmpopts.SortSlices(less)) { + return true + } + + if (len(oldField.ExactlyOneOf) > 0 || len(newField.ExactlyOneOf) > 0) && !cmp.Equal(oldField.ExactlyOneOf, newField.ExactlyOneOf, cmpopts.SortSlices(less)) { + return true + } + + if (len(oldField.AtLeastOneOf) > 0 || len(newField.AtLeastOneOf) > 0) && !cmp.Equal(oldField.AtLeastOneOf, newField.AtLeastOneOf, cmpopts.SortSlices(less)) { + return true + } + + if (len(oldField.RequiredWith) > 0 || len(newField.RequiredWith) > 0) && !cmp.Equal(oldField.RequiredWith, newField.RequiredWith, cmpopts.SortSlices(less)) { + return true + } + + // Check if Elem changed (unless old and new both represent nested fields) + if (oldField.Elem == nil || newField.Elem == nil) && !(oldField.Elem == nil && newField.Elem == nil) { + return true + } + _, oldHasChildren := oldField.Elem.(*schema.Resource) + _, newHasChildren := newField.Elem.(*schema.Resource) + if !oldHasChildren && !newHasChildren { + if !reflect.DeepEqual(oldField.Elem, newField.Elem) { + return true + } + } else if (oldHasChildren || newHasChildren) && !(oldHasChildren && newHasChildren) { + return true + } + + // Check if any Schema struct fields that are functions have changed + if funcChanged(oldField.DiffSuppressFunc, newField.DiffSuppressFunc) { + return true + } + if funcChanged(oldField.DefaultFunc, newField.DefaultFunc) { + return true + } + if funcChanged(oldField.StateFunc, newField.StateFunc) { + return true + } + if funcChanged(oldField.Set, newField.Set) { + return true + } + if funcChanged(oldField.ValidateFunc, newField.ValidateFunc) { + return true + } + if funcChanged(oldField.ValidateDiagFunc, newField.ValidateDiagFunc) { + return true + } + + return false +} + +func funcChanged(oldFunc, newFunc interface{}) bool { + // If it changed to/from nil, it changed + oldFuncIsNil := reflect.ValueOf(oldFunc).IsNil() + newFuncIsNil := reflect.ValueOf(newFunc).IsNil() + if (oldFuncIsNil && !newFuncIsNil) || (!oldFuncIsNil && newFuncIsNil) { + return true + } + + // If a func is set before and after we don't currently have a way to reliably + // determine whether the function changed, so we assume that it has not changed. + // b/300157205 + return false +} diff --git a/tools/diff-processor/diff/diff_test.go b/tools/diff-processor/diff/diff_test.go new file mode 100644 index 000000000000..2d5896228dd5 --- /dev/null +++ b/tools/diff-processor/diff/diff_test.go @@ -0,0 +1,1072 @@ +package diff + +import ( + "fmt" + "testing" + + newProvider "google/provider/new/google/provider" + newTpgresource "google/provider/new/google/tpgresource" + oldTpgresource "google/provider/new/google/tpgresource" + newVerify "google/provider/new/google/verify" + oldProvider "google/provider/old/google/provider" + oldVerify "google/provider/old/google/verify" + + "github.com/google/go-cmp/cmp" + "github.com/davecgh/go-spew/spew" + "github.com/hashicorp/go-cty/cty" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/stretchr/testify/assert" +) + +func TestNewProviderOldProviderChanges(t *testing.T) { + changes := ComputeSchemaDiff(oldProvider.ResourceMap(), newProvider.ResourceMap()) + + t.Logf("Changes between old and new providers: %s", spew.Sdump(changes)) +} + +func TestFlattenSchema(t *testing.T) { + cases := map[string]struct { + resourceSchema map[string]*schema.Schema + expectFlattened map[string]*schema.Schema + }{ + "primitive fields": { + resourceSchema: map[string]*schema.Schema{ + "bool": { + Type: schema.TypeBool, + }, + "int": { + Type: schema.TypeInt, + }, + "float": { + Type: schema.TypeFloat, + }, + "string": { + Type: schema.TypeString, + }, + }, + expectFlattened: map[string]*schema.Schema{ + "bool": { + Type: schema.TypeBool, + }, + "int": { + Type: schema.TypeInt, + }, + "float": { + Type: schema.TypeFloat, + }, + "string": { + Type: schema.TypeString, + }, + }, + }, + "map field": { + resourceSchema: map[string]*schema.Schema{ + "map": { + Type: schema.TypeMap, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + expectFlattened: map[string]*schema.Schema{ + "map": { + Type: schema.TypeMap, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + "simple list field": { + resourceSchema: map[string]*schema.Schema{ + "list": { + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + expectFlattened: map[string]*schema.Schema{ + "list": { + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + "simple set field": { + resourceSchema: map[string]*schema.Schema{ + "set": { + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + expectFlattened: map[string]*schema.Schema{ + "set": { + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + "nested list field": { + resourceSchema: map[string]*schema.Schema{ + "list": { + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "nested_string": { + Type: schema.TypeString, + }, + }, + }, + }, + }, + expectFlattened: map[string]*schema.Schema{ + "list": { + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "nested_string": { + Type: schema.TypeString, + }, + }, + }, + }, + "list.nested_string": { + Type: schema.TypeString, + }, + }, + }, + "nested set field": { + resourceSchema: map[string]*schema.Schema{ + "set": { + Type: schema.TypeSet, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "nested_string": { + Type: schema.TypeString, + }, + }, + }, + }, + }, + expectFlattened: map[string]*schema.Schema{ + "set": { + Type: schema.TypeSet, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "nested_string": { + Type: schema.TypeString, + }, + }, + }, + }, + "set.nested_string": { + Type: schema.TypeString, + }, + }, + }, + } + + for tn, tc := range cases { + tc := tc + t.Run(tn, func(t *testing.T) { + t.Parallel() + flattened := flattenSchema("", tc.resourceSchema) + assert.Equal(t, tc.expectFlattened, flattened) + }) + } +} + +func testDefaultFunc1() (interface{}, error) { + return "default1", nil +} +func testDefaultFunc2() (interface{}, error) { + return "default2", nil +} +func testStateFunc1(interface{}) string { + return "state1" +} +func testStateFunc2(interface{}) string { + return "state2" +} +func testValidateDiagFunc1(v interface{}, p cty.Path) diag.Diagnostics { + return diag.Diagnostics{} +} +func testValidateDiagFunc2(v interface{}, p cty.Path) diag.Diagnostics { + return diag.Diagnostics{} +} + +func TestFieldChanged(t *testing.T) { + cases := map[string]struct { + oldField *schema.Schema + newField *schema.Schema + expectChanged bool + }{ + "both nil": { + oldField: nil, + newField: nil, + expectChanged: false, + }, + "old nil": { + oldField: nil, + newField: &schema.Schema{ + Type: schema.TypeString, + }, + expectChanged: true, + }, + "new nil": { + oldField: &schema.Schema{ + Type: schema.TypeString, + }, + newField: nil, + expectChanged: true, + }, + "not changed": { + oldField: &schema.Schema{}, + newField: &schema.Schema{}, + expectChanged: false, + }, + "Type changed": { + oldField: &schema.Schema{ + Type: schema.TypeString, + }, + newField: &schema.Schema{ + Type: schema.TypeInt, + }, + expectChanged: true, + }, + "ConfigMode changed": { + oldField: &schema.Schema{ + ConfigMode: schema.SchemaConfigModeAttr, + }, + newField: &schema.Schema{ + ConfigMode: schema.SchemaConfigModeBlock, + }, + expectChanged: true, + }, + "Required changed": { + oldField: &schema.Schema{ + Required: false, + }, + newField: &schema.Schema{ + Required: true, + }, + expectChanged: true, + }, + "Optional changed": { + oldField: &schema.Schema{ + Optional: false, + }, + newField: &schema.Schema{ + Optional: true, + }, + expectChanged: true, + }, + "Computed changed": { + oldField: &schema.Schema{ + Computed: false, + }, + newField: &schema.Schema{ + Computed: true, + }, + expectChanged: true, + }, + "ForceNew changed": { + oldField: &schema.Schema{ + ForceNew: false, + }, + newField: &schema.Schema{ + ForceNew: true, + }, + expectChanged: true, + }, + "DiffSuppressOnRefresh changed": { + oldField: &schema.Schema{ + DiffSuppressOnRefresh: false, + }, + newField: &schema.Schema{ + DiffSuppressOnRefresh: true, + }, + expectChanged: true, + }, + "Default changed": { + oldField: &schema.Schema{ + Default: 10, + }, + newField: &schema.Schema{ + Default: 20, + }, + expectChanged: true, + }, + "Description changed": { + oldField: &schema.Schema{ + Description: "Hello", + }, + newField: &schema.Schema{ + Description: "Goodbye", + }, + expectChanged: true, + }, + "InputDefault changed": { + oldField: &schema.Schema{ + InputDefault: "Hello", + }, + newField: &schema.Schema{ + InputDefault: "Goodbye", + }, + expectChanged: true, + }, + "MaxItems changed": { + oldField: &schema.Schema{ + MaxItems: 10, + }, + newField: &schema.Schema{ + MaxItems: 20, + }, + expectChanged: true, + }, + "MinItems changed": { + oldField: &schema.Schema{ + MinItems: 10, + }, + newField: &schema.Schema{ + MinItems: 20, + }, + expectChanged: true, + }, + "Deprecated changed": { + oldField: &schema.Schema{ + Deprecated: "Hello", + }, + newField: &schema.Schema{ + Deprecated: "Goodbye", + }, + expectChanged: true, + }, + "Sensitive changed": { + oldField: &schema.Schema{ + Sensitive: false, + }, + newField: &schema.Schema{ + Sensitive: true, + }, + expectChanged: true, + }, + "ConflictsWith reordered": { + oldField: &schema.Schema{ + ConflictsWith: []string{"field_one", "field_two"}, + }, + newField: &schema.Schema{ + ConflictsWith: []string{"field_two", "field_one"}, + }, + expectChanged: false, + }, + "ConflictsWith changed": { + oldField: &schema.Schema{ + ConflictsWith: []string{"field_one", "field_two"}, + }, + newField: &schema.Schema{ + ConflictsWith: []string{"field_two", "field_three"}, + }, + expectChanged: true, + }, + "ExactlyOneOf reordered": { + oldField: &schema.Schema{ + ExactlyOneOf: []string{"field_one", "field_two"}, + }, + newField: &schema.Schema{ + ExactlyOneOf: []string{"field_two", "field_one"}, + }, + expectChanged: false, + }, + "ExactlyOneOf changed": { + oldField: &schema.Schema{ + ExactlyOneOf: []string{"field_one", "field_two"}, + }, + newField: &schema.Schema{ + ExactlyOneOf: []string{"field_two", "field_three"}, + }, + expectChanged: true, + }, + "AtLeastOneOf reordered": { + oldField: &schema.Schema{ + AtLeastOneOf: []string{"field_one", "field_two"}, + }, + newField: &schema.Schema{ + AtLeastOneOf: []string{"field_two", "field_one"}, + }, + expectChanged: false, + }, + "AtLeastOneOf changed": { + oldField: &schema.Schema{ + AtLeastOneOf: []string{"field_one", "field_two"}, + }, + newField: &schema.Schema{ + AtLeastOneOf: []string{"field_two", "field_three"}, + }, + expectChanged: true, + }, + "RequiredWith reordered": { + oldField: &schema.Schema{ + RequiredWith: []string{"field_one", "field_two"}, + }, + newField: &schema.Schema{ + RequiredWith: []string{"field_two", "field_one"}, + }, + expectChanged: false, + }, + "RequiredWith changed": { + oldField: &schema.Schema{ + RequiredWith: []string{"field_one", "field_two"}, + }, + newField: &schema.Schema{ + RequiredWith: []string{"field_two", "field_three"}, + }, + expectChanged: true, + }, + "simple Elem unset -> set": { + oldField: &schema.Schema{}, + newField: &schema.Schema{ + Elem: &schema.Schema{Type: schema.TypeInt}, + }, + expectChanged: true, + }, + "simple Elem set -> unset": { + oldField: &schema.Schema{ + Elem: &schema.Schema{Type: schema.TypeInt}, + }, + newField: &schema.Schema{}, + expectChanged: true, + }, + "simple Elem unchanged": { + oldField: &schema.Schema{ + Elem: &schema.Schema{Type: schema.TypeString}, + }, + newField: &schema.Schema{ + Elem: &schema.Schema{Type: schema.TypeString}, + }, + expectChanged: false, + }, + "simple Elem changed": { + oldField: &schema.Schema{ + Elem: &schema.Schema{Type: schema.TypeString}, + }, + newField: &schema.Schema{ + Elem: &schema.Schema{Type: schema.TypeInt}, + }, + expectChanged: true, + }, + "nested Elem unset -> set": { + oldField: &schema.Schema{}, + newField: &schema.Schema{ + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "foobar": { + Type: schema.TypeInt, + }, + }, + }, + }, + expectChanged: true, + }, + "nested Elem set -> unset": { + oldField: &schema.Schema{ + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "foobar": { + Type: schema.TypeInt, + }, + }, + }, + }, + newField: &schema.Schema{}, + expectChanged: true, + }, + "nested Elem unchanged": { + oldField: &schema.Schema{ + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "foobar": { + Type: schema.TypeInt, + }, + }, + }, + }, + newField: &schema.Schema{ + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "foobar": { + Type: schema.TypeInt, + }, + }, + }, + }, + expectChanged: false, + }, + "nested Elem changing is ignored": { + oldField: &schema.Schema{ + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "foobar": { + Type: schema.TypeInt, + }, + }, + }, + }, + newField: &schema.Schema{ + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "barbaz": { + Type: schema.TypeString, + }, + }, + }, + }, + expectChanged: false, + }, + "Elem simple -> nested": { + oldField: &schema.Schema{ + Elem: &schema.Schema{Type: schema.TypeString}, + }, + newField: &schema.Schema{ + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "foobar": { + Type: schema.TypeInt, + }, + }, + }, + }, + expectChanged: true, + }, + "Elem nested -> simple": { + oldField: &schema.Schema{ + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "foobar": { + Type: schema.TypeInt, + }, + }, + }, + }, + newField: &schema.Schema{ + Elem: &schema.Schema{Type: schema.TypeString}, + }, + expectChanged: true, + }, + + "DiffSuppressFunc added": { + oldField: &schema.Schema{}, + newField: &schema.Schema{ + DiffSuppressFunc: newTpgresource.CaseDiffSuppress, + }, + expectChanged: true, + }, + "DiffSuppressFunc removed": { + oldField: &schema.Schema{ + DiffSuppressFunc: oldTpgresource.CaseDiffSuppress, + }, + newField: &schema.Schema{}, + expectChanged: true, + }, + "DiffSuppressFunc remains set": { + oldField: &schema.Schema{ + DiffSuppressFunc: oldTpgresource.CaseDiffSuppress, + }, + newField: &schema.Schema{ + DiffSuppressFunc: newTpgresource.CaseDiffSuppress, + }, + expectChanged: false, + }, + + "DefaultFunc added": { + oldField: &schema.Schema{}, + newField: &schema.Schema{ + DefaultFunc: testDefaultFunc1, + }, + expectChanged: true, + }, + "DefaultFunc removed": { + oldField: &schema.Schema{ + DefaultFunc: testDefaultFunc1, + }, + newField: &schema.Schema{}, + expectChanged: true, + }, + "DefaultFunc remains set": { + oldField: &schema.Schema{ + DefaultFunc: testDefaultFunc1, + }, + newField: &schema.Schema{ + DefaultFunc: testDefaultFunc2, + }, + expectChanged: false, + }, + + "StateFunc added": { + oldField: &schema.Schema{}, + newField: &schema.Schema{ + StateFunc: testStateFunc1, + }, + expectChanged: true, + }, + "StateFunc removed": { + oldField: &schema.Schema{ + StateFunc: testStateFunc1, + }, + newField: &schema.Schema{}, + expectChanged: true, + }, + "StateFunc remains set": { + oldField: &schema.Schema{ + StateFunc: testStateFunc1, + }, + newField: &schema.Schema{ + StateFunc: testStateFunc2, + }, + expectChanged: false, + }, + + "Set added": { + oldField: &schema.Schema{}, + newField: &schema.Schema{ + Set: newTpgresource.SelfLinkRelativePathHash, + }, + expectChanged: true, + }, + "Set removed": { + oldField: &schema.Schema{ + Set: oldTpgresource.SelfLinkRelativePathHash, + }, + newField: &schema.Schema{}, + expectChanged: true, + }, + "Set remains set": { + oldField: &schema.Schema{ + Set: oldTpgresource.SelfLinkRelativePathHash, + }, + newField: &schema.Schema{ + Set: newTpgresource.SelfLinkRelativePathHash, + }, + expectChanged: false, + }, + + "ValidateFunc added": { + oldField: &schema.Schema{}, + newField: &schema.Schema{ + ValidateFunc: newVerify.ValidateBase64String, + }, + expectChanged: true, + }, + "ValidateFunc removed": { + oldField: &schema.Schema{ + ValidateFunc: oldVerify.ValidateBase64String, + }, + newField: &schema.Schema{}, + expectChanged: true, + }, + "ValidateFunc remains set": { + oldField: &schema.Schema{ + ValidateFunc: oldVerify.ValidateBase64String, + }, + newField: &schema.Schema{ + ValidateFunc: newVerify.ValidateBase64String, + }, + expectChanged: false, + }, + + "ValidateDiagFunc added": { + oldField: &schema.Schema{}, + newField: &schema.Schema{ + ValidateDiagFunc: testValidateDiagFunc1, + }, + expectChanged: true, + }, + "ValidateDiagFunc removed": { + oldField: &schema.Schema{ + ValidateDiagFunc: testValidateDiagFunc1, + }, + newField: &schema.Schema{}, + expectChanged: true, + }, + "ValidateDiagFunc remains set": { + oldField: &schema.Schema{ + ValidateDiagFunc: testValidateDiagFunc1, + }, + newField: &schema.Schema{ + ValidateDiagFunc: testValidateDiagFunc2, + }, + expectChanged: false, + }, + } + + for tn, tc := range cases { + tc := tc + t.Run(tn, func(t *testing.T) { + t.Parallel() + changed := fieldChanged(tc.oldField, tc.newField) + assert.Equal( + t, + tc.expectChanged, + changed, + fmt.Sprintf( + "want %t; got %t.\nOld field: %s\nNew field: %s\n", + tc.expectChanged, + changed, + spew.Sdump(tc.oldField), + spew.Sdump(tc.newField), + ), + ) + }) + } +} + +func TestComputeSchemaDiff(t *testing.T) { + cases := map[string]struct { + oldResourceMap map[string]*schema.Resource + newResourceMap map[string]*schema.Resource + expectedSchemaDiff SchemaDiff + }{ + "empty-maps": { + oldResourceMap: map[string]*schema.Resource{}, + newResourceMap: map[string]*schema.Resource{}, + expectedSchemaDiff: SchemaDiff{}, + }, + "empty-resources": { + oldResourceMap: map[string]*schema.Resource{ + "google_service_one_resource_one": {}, + "google_service_one_resource_two": {}, + }, + newResourceMap: map[string]*schema.Resource{ + "google_service_one_resource_one": {}, + "google_service_one_resource_two": {}, + }, + expectedSchemaDiff: SchemaDiff{}, + }, + "unchanged-nested-field": { + oldResourceMap: map[string]*schema.Resource{ + "google_service_one_resource_one": { + Schema: map[string]*schema.Schema{ + "field_one": { + Type: schema.TypeString, + }, + "field_two": { + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "field_three": { + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google_service_one_resource_one": { + Schema: map[string]*schema.Schema{ + "field_one": { + Type: schema.TypeString, + }, + "field_two": { + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "field_three": { + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, + expectedSchemaDiff: SchemaDiff{}, + }, + "new-nested-field": { + oldResourceMap: map[string]*schema.Resource{ + "google_service_one_resource_one": { + Schema: map[string]*schema.Schema{ + "field_one": { + Type: schema.TypeString, + }, + "field_two": { + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "field_three": { + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + "google_service_one_resource_two": { + Schema: map[string]*schema.Schema{ + "field_one": { + Type: schema.TypeString, + }, + "field_two": { + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "field_three": { + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google_service_one_resource_one": { + Schema: map[string]*schema.Schema{ + "field_one": { + Type: schema.TypeString, + }, + "field_two": { + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "field_three": { + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + "google_service_one_resource_two": { + Schema: map[string]*schema.Schema{ + "field_one": { + Type: schema.TypeString, + }, + "field_two": { + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "field_three": { + Type: schema.TypeString, + }, + "field_four": { + Type: schema.TypeInt, + }, + }, + }, + }, + }, + }, + }, + expectedSchemaDiff: SchemaDiff{ + "google_service_one_resource_two": ResourceDiff{ + ResourceConfig: ResourceConfigDiff{ + Old: &schema.Resource{}, + New: &schema.Resource{}, + }, + Fields: map[string]FieldDiff{ + "field_two.field_four": FieldDiff{ + Old: nil, + New: &schema.Schema{ + Type: schema.TypeInt, + }, + }, + }, + }, + }, + }, + "new-field-in-two-resources": { + oldResourceMap: map[string]*schema.Resource{ + "google_service_one_resource_one": { + Schema: map[string]*schema.Schema{ + "field_one": { + Type: schema.TypeString, + }, + "field_two": { + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "field_three": { + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + "google_service_one_resource_two": { + Schema: map[string]*schema.Schema{ + "field_one": { + Type: schema.TypeString, + }, + "field_two": { + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "field_three": { + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google_service_one_resource_one": { + Schema: map[string]*schema.Schema{ + "field_one": { + Type: schema.TypeString, + }, + "field_two": { + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "field_three": { + Type: schema.TypeString, + }, + "field_four": { + Type: schema.TypeInt, + }, + }, + }, + }, + }, + }, + "google_service_one_resource_two": { + Schema: map[string]*schema.Schema{ + "field_one": { + Type: schema.TypeString, + }, + "field_two": { + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "field_three": { + Type: schema.TypeString, + }, + "field_four": { + Type: schema.TypeInt, + }, + }, + }, + }, + }, + }, + }, + expectedSchemaDiff: SchemaDiff{ + "google_service_one_resource_one": ResourceDiff{ + ResourceConfig: ResourceConfigDiff{ + Old: &schema.Resource{}, + New: &schema.Resource{}, + }, + Fields: map[string]FieldDiff{ + "field_two.field_four": FieldDiff{ + Old: nil, + New: &schema.Schema{Type: schema.TypeInt}, + }, + }, + }, + "google_service_one_resource_two": ResourceDiff{ + ResourceConfig: ResourceConfigDiff{ + Old: &schema.Resource{}, + New: &schema.Resource{}, + }, + Fields: map[string]FieldDiff{ + "field_two.field_four": FieldDiff{ + Old: nil, + New: &schema.Schema{Type: schema.TypeInt}, + }, + }, + }, + }, + }, + "deleted-field": { + oldResourceMap: map[string]*schema.Resource{ + "google_service_one_resource_one": { + Schema: map[string]*schema.Schema{ + "field_one": { + Type: schema.TypeString, + }, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google_service_one_resource_one": { + Schema: map[string]*schema.Schema{}, + }, + }, + expectedSchemaDiff: SchemaDiff{ + "google_service_one_resource_one": ResourceDiff{ + ResourceConfig: ResourceConfigDiff{ + Old: &schema.Resource{}, + New: &schema.Resource{}, + }, + Fields: map[string]FieldDiff{ + "field_one": FieldDiff{ + Old: &schema.Schema{Type: schema.TypeString}, + New: nil, + }, + }, + }, + }, + }, + "deleted-resource": { + oldResourceMap: map[string]*schema.Resource{ + "google_service_one_resource_one": { + Schema: map[string]*schema.Schema{ + "field_one": { + Type: schema.TypeString, + }, + }, + }, + }, + expectedSchemaDiff: SchemaDiff{ + "google_service_one_resource_one": ResourceDiff{ + ResourceConfig: ResourceConfigDiff{ + Old: &schema.Resource{}, + New: nil, + }, + Fields: map[string]FieldDiff{ + "field_one": FieldDiff{ + Old: &schema.Schema{Type: schema.TypeString}, + New: nil, + }, + }, + }, + }, + }, + "new-resource": { + newResourceMap: map[string]*schema.Resource{ + "google_service_one_resource_one": { + Schema: map[string]*schema.Schema{ + "field_one": { + Type: schema.TypeString, + }, + }, + }, + }, + expectedSchemaDiff: SchemaDiff{ + "google_service_one_resource_one": ResourceDiff{ + ResourceConfig: ResourceConfigDiff{ + Old: nil, + New: &schema.Resource{}, + }, + Fields: map[string]FieldDiff{ + "field_one": FieldDiff{ + Old: nil, + New: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + }, + } + for tn, tc := range cases { + tc := tc + t.Run(tn, func(t *testing.T) { + t.Parallel() + schemaDiff := ComputeSchemaDiff(tc.oldResourceMap, tc.newResourceMap) + if diff := cmp.Diff(tc.expectedSchemaDiff, schemaDiff); diff != "" { + t.Errorf("schema diff not equal (-want, +got):\n%s", diff) + } + }) + } +} diff --git a/tools/diff-processor/go.mod b/tools/diff-processor/go.mod index 92d513b193cd..88bcd44634ca 100644 --- a/tools/diff-processor/go.mod +++ b/tools/diff-processor/go.mod @@ -9,9 +9,13 @@ replace google/provider/new => ./new replace github.com/GoogleCloudPlatform/magic-modules/.ci/diff-processor => ./ require ( - github.com/golang/glog v1.1.0 + github.com/davecgh/go-spew v1.1.1 + github.com/google/go-cmp v0.5.9 + github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0 github.com/spf13/cobra v1.7.0 + github.com/stretchr/testify v1.8.3 + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 google/provider/new v0.0.0-00010101000000-000000000000 google/provider/old v0.0.0-00010101000000-000000000000 ) @@ -33,15 +37,14 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe // indirect github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f // indirect github.com/envoyproxy/protoc-gen-validate v0.10.1 // 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/glog v1.1.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/google/go-cmp v0.5.9 // indirect github.com/google/go-cpy v0.0.0-20211218193943-a9c933c06932 // indirect github.com/google/s2a-go v0.1.4 // indirect github.com/google/uuid v1.3.0 // indirect @@ -51,7 +54,6 @@ require ( 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.8 // indirect @@ -82,6 +84,7 @@ require ( 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/pmezard/go-difflib v1.0.0 // indirect github.com/sirupsen/logrus v1.8.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect @@ -93,7 +96,7 @@ require ( golang.org/x/net v0.12.0 // indirect golang.org/x/oauth2 v0.10.0 // indirect golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.10.0 // indirect + golang.org/x/sys v0.12.0 // indirect golang.org/x/text v0.11.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/api v0.135.0 // indirect @@ -103,4 +106,5 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20230726155614-23370e0ffb3e // indirect google.golang.org/grpc v1.57.0 // indirect google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/tools/diff-processor/go.sum b/tools/diff-processor/go.sum index 8e301bf72f63..42705ad96cf3 100644 --- a/tools/diff-processor/go.sum +++ b/tools/diff-processor/go.sum @@ -280,6 +280,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.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/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= @@ -317,6 +318,8 @@ golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= 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= @@ -383,8 +386,8 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/tools/diff-processor/rules/breaking_changes.go b/tools/diff-processor/rules/breaking_changes.go new file mode 100644 index 000000000000..2adaf4192720 --- /dev/null +++ b/tools/diff-processor/rules/breaking_changes.go @@ -0,0 +1,52 @@ +package rules + +import ( + "github.com/GoogleCloudPlatform/magic-modules/.ci/diff-processor/diff" +) + +func ComputeBreakingChanges(schemaDiff diff.SchemaDiff) []string { + messages := []string{} + for resource, resourceDiff := range schemaDiff { + for _, rule := range ResourceInventoryRules { + if rule.isRuleBreak(resourceDiff.ResourceConfig.Old, resourceDiff.ResourceConfig.New) { + messages = append(messages, rule.Message(resource)) + } + } + + // If the resource was added or removed, don't check field schema diffs. + if resourceDiff.ResourceConfig.Old == nil || resourceDiff.ResourceConfig.New == nil { + continue + } + + // TODO: Move field removal to field_rules and merge resource schema / resource inventory rules + // b/300124253 + for _, rule := range ResourceSchemaRules { + violatingFields := rule.IsRuleBreak(resourceDiff) + if len(violatingFields) > 0 { + for _, field := range violatingFields { + newMessage := rule.Message(resource, field) + messages = append(messages, newMessage) + } + } + } + + for field, fieldDiff := range resourceDiff.Fields { + for _, rule := range FieldRules { + // TODO: refactor rules to use interface-based implementation that separates checking whether + // a rule broke from composing a message for a rule break. + breakageMessage := rule.IsRuleBreak( + fieldDiff.Old, + fieldDiff.New, + MessageContext{ + Resource: resource, + Field: field, + }, + ) + if breakageMessage != "" { + messages = append(messages, breakageMessage) + } + } + } + } + return messages +} diff --git a/tools/diff-processor/rules/breaking_changes_test.go b/tools/diff-processor/rules/breaking_changes_test.go new file mode 100644 index 000000000000..5c11cf63287e --- /dev/null +++ b/tools/diff-processor/rules/breaking_changes_test.go @@ -0,0 +1,344 @@ +package rules + +import ( + "strings" + "testing" + + "github.com/GoogleCloudPlatform/magic-modules/.ci/diff-processor/diff" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func TestComputeBreakingChanges(t *testing.T) { + cases := []struct { + name string + oldResourceMap map[string]*schema.Resource + newResourceMap map[string]*schema.Resource + expectedViolations int + }{ + { + name: "control", + oldResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep", Optional: true}, + "field-b": {Description: "beep", Optional: true}, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep", Optional: true}, + "field-b": {Description: "beep", Optional: true}, + }, + }, + }, + expectedViolations: 0, + }, + { + name: "adding resources", + oldResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep", Optional: true}, + "field-b": {Description: "beep", Optional: true}, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep", Optional: true}, + "field-b": {Description: "beep", Optional: true}, + }, + }, + "google-y": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep", Optional: true}, + }, + }, + }, + expectedViolations: 0, + }, + { + name: "adding fields", + oldResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep", Optional: true}, + "field-b": {Description: "beep", Optional: true}, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep", Optional: true}, + "field-b": {Description: "beep", Optional: true}, + "field-c": {Description: "beep", Optional: true}, + }, + }, + }, + expectedViolations: 0, + }, + { + name: "resource missing", + oldResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep"}, + "field-b": {Description: "beep"}, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{}, + expectedViolations: 1, + }, + { + name: "field missing", + oldResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep", Optional: true}, + "field-b": {Description: "beep", Optional: true}, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep", Optional: true}, + }, + }, + }, + expectedViolations: 1, + }, + { + name: "optional field to required", + oldResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep", Optional: true}, + "field-b": {Description: "beep", Optional: true}, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep", Required: true}, + "field-b": {Description: "beep", Optional: true}, + }, + }, + }, + expectedViolations: 1, + }, + { + name: "field missing and optional to required", + oldResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep", Optional: true}, + "field-b": {Description: "beep", Optional: true}, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep", Required: true}, + }, + }, + }, + expectedViolations: 2, + }, + { + name: "field missing, resource missing, and optional to required", + oldResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep", Optional: true}, + "field-b": {Description: "beep", Optional: true}, + }, + }, + "google-y": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep", Optional: true}, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": {Description: "beep", Required: true}, + }, + }, + }, + expectedViolations: 3, + }, + { + name: "removing a subfield", + oldResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": { + Description: "beep", + Optional: true, + Type: schema.TypeList, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "sub-field-1": {Description: "beep", Optional: true}, + "sub-field-2": {Description: "beep", Optional: true}, + }, + }, + }, + "field-b": {Description: "beep", Optional: true}, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": { + Description: "beep", + Optional: true, + Type: schema.TypeList, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "sub-field-1": {Description: "beep", Optional: true}, + }, + }, + }, + "field-b": {Description: "beep", Optional: true}, + }, + }, + }, + expectedViolations: 1, + }, + { + name: "subfield max shrinking", + oldResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": { + Description: "beep", + Optional: true, + Type: schema.TypeList, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "sub-field-1": {Description: "beep", Optional: true, MaxItems: 100}, + }, + }, + }, + "field-b": {Description: "beep", Optional: true}, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": { + Description: "beep", + Optional: true, + Type: schema.TypeList, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "sub-field-1": {Description: "beep", Optional: true, MaxItems: 25}, + }, + }, + }, + "field-b": {Description: "beep", Optional: true}, + }, + }, + }, + expectedViolations: 1, + }, + { + name: "subfield max shrinking", + oldResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": { + Description: "beep", + Optional: true, + Type: schema.TypeList, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "sub-field-1": {Description: "beep", Optional: true, MaxItems: 100}, + }, + }, + }, + "field-b": {Description: "beep", Optional: true}, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": { + Description: "beep", + Optional: true, + Type: schema.TypeList, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "sub-field-1": {Description: "beep", Optional: true, MaxItems: 25}, + }, + }, + }, + "field-b": {Description: "beep", Optional: true}, + }, + }, + }, + expectedViolations: 1, + }, + { + name: "min growing", + oldResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": { + Description: "beep", + Optional: true, + MinItems: 1, + }, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google-x": { + Schema: map[string]*schema.Schema{ + "field-a": { + Description: "beep", + Optional: true, + MinItems: 4, + }, + }, + }, + }, + expectedViolations: 1, + }, + } + + for _, tc := range cases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + schemaDiff := diff.ComputeSchemaDiff(tc.oldResourceMap, tc.newResourceMap) + violations := ComputeBreakingChanges(schemaDiff) + for _, v := range violations { + if strings.Contains(v, "{{") || strings.Contains(v, "}}") { + t.Errorf("Test `%s` failed: found unreplaced characters in string - %s", tc.name, v) + } + } + if tc.expectedViolations != len(violations) { + t.Errorf("Test `%s` failed: expected %d violations, got %d", tc.name, tc.expectedViolations, len(violations)) + } + }) + } +} diff --git a/tools/diff-processor/rules/rules_field.go b/tools/diff-processor/rules/rules_field.go index be79462b10e4..1b5645571731 100644 --- a/tools/diff-processor/rules/rules_field.go +++ b/tools/diff-processor/rules/rules_field.go @@ -45,6 +45,10 @@ var fieldRule_ChangingType = FieldRule{ } func fieldRule_ChangingType_func(old, new *schema.Schema, mc MessageContext) string { + // Type change doesn't matter for added / removed fields + if old == nil || new == nil { + return "" + } message := mc.message if old.Type != new.Type { oldType := getValueType(old.Type) @@ -76,6 +80,10 @@ var fieldRule_BecomingRequired = FieldRule{ } func fieldRule_BecomingRequired_func(old, new *schema.Schema, mc MessageContext) string { + // Ignore for added / removed fields + if old == nil || new == nil { + return "" + } message := mc.message if !old.Required && new.Required { return populateMessageContext(message, mc) @@ -93,6 +101,10 @@ var fieldRule_BecomingComputedOnly = FieldRule{ } func fieldRule_BecomingComputedOnly_func(old, new *schema.Schema, mc MessageContext) string { + // ignore for added / removed fields + if old == nil || new == nil { + return "" + } message := mc.message // if the field is computed only already // this rule doesn't apply @@ -115,6 +127,10 @@ var fieldRule_OptionalComputedToOptional = FieldRule{ } func fieldRule_OptionalComputedToOptional_func(old, new *schema.Schema, mc MessageContext) string { + // ignore for added / removed fields + if old == nil || new == nil { + return "" + } message := mc.message if (old.Computed && old.Optional) && (new.Optional && !new.Computed) { return populateMessageContext(message, mc) @@ -131,6 +147,10 @@ var fieldRule_DefaultModification = FieldRule{ } func fieldRule_DefaultModification_func(old, new *schema.Schema, mc MessageContext) string { + // ignore for added / removed fields + if old == nil || new == nil { + return "" + } message := mc.message if old.Default != new.Default { oldDefault := fmt.Sprintf("%v", old.Default) @@ -152,6 +172,10 @@ var fieldRule_GrowingMin = FieldRule{ } func fieldRule_GrowingMin_func(old, new *schema.Schema, mc MessageContext) string { + // ignore for added / removed fields + if old == nil || new == nil { + return "" + } message := mc.message if old.MinItems < new.MinItems { oldMin := fmt.Sprint(old.MinItems) @@ -172,6 +196,10 @@ var fieldRule_ShrinkingMax = FieldRule{ } func fieldRule_ShrinkingMax_func(old, new *schema.Schema, mc MessageContext) string { + // ignore for added / removed fields + if old == nil || new == nil { + return "" + } message := mc.message if old.MaxItems > new.MaxItems { oldMax := fmt.Sprint(old.MinItems) diff --git a/tools/diff-processor/rules/rules_field_test.go b/tools/diff-processor/rules/rules_field_test.go index 1b485d62c195..e19fd13cbc4f 100644 --- a/tools/diff-processor/rules/rules_field_test.go +++ b/tools/diff-processor/rules/rules_field_test.go @@ -71,6 +71,25 @@ var fieldRule_BecomingRequiredTestCases = []fieldTestCase{ }, expectedViolation: true, }, + { + // TODO: detect this as violation b/300515447 + name: "field added as required", + oldField: nil, + newField: &schema.Schema{ + Description: "beep", + Required: true, + }, + expectedViolation: false, + }, + { + name: "field removed", + oldField: &schema.Schema{ + Description: "beep", + Optional: true, + }, + newField: nil, + expectedViolation: false, + }, } // !! min max ? @@ -93,6 +112,22 @@ var fieldRule_ChangingTypeTestCases = []fieldTestCase{ }, expectedViolation: false, }, + { + name: "field added", + oldField: nil, + newField: &schema.Schema{ + Type: schema.TypeBool, + }, + expectedViolation: false, + }, + { + name: "field removed", + oldField: &schema.Schema{ + Type: schema.TypeBool, + }, + newField: nil, + expectedViolation: false, + }, { name: "field sub-element type control", oldField: &schema.Schema{ @@ -222,6 +257,22 @@ var fieldRule_DefaultModificationTestCases = []fieldTestCase{ }, expectedViolation: true, }, + { + name: "field added", + oldField: nil, + newField: &schema.Schema{ + Default: "same", + }, + expectedViolation: false, + }, + { + name: "field removed", + oldField: &schema.Schema{ + Default: "same", + }, + newField: nil, + expectedViolation: false, + }, } func TestFieldRule_BecomingComputedOnly(t *testing.T) { @@ -294,6 +345,22 @@ var fieldRule_BecomingComputedOnlyTestCases = []fieldTestCase{ }, expectedViolation: true, }, + { + name: "added computed field", + oldField: nil, + newField: &schema.Schema{ + Computed: true, + }, + expectedViolation: false, + }, + { + name: "removed computed field", + oldField: &schema.Schema{ + Computed: true, + }, + newField: nil, + expectedViolation: false, + }, } func TestFieldRule_OptionalComputedToOptional(t *testing.T) { @@ -336,6 +403,23 @@ var fieldRule_OptionalComputedToOptionalTestCases = []fieldTestCase{ }, expectedViolation: true, }, + { + name: "field added", + oldField: nil, + newField: &schema.Schema{ + Optional: true, + }, + expectedViolation: false, + }, + { + name: "field removed", + oldField: &schema.Schema{ + Optional: true, + Computed: true, + }, + newField: nil, + expectedViolation: false, + }, } func TestFieldRule_GrowingMin(t *testing.T) { @@ -381,6 +465,22 @@ var fieldRule_GrowingMinTestCases = []fieldTestCase{ }, expectedViolation: true, }, + { + name: "field added", + oldField: nil, + newField: &schema.Schema{ + MaxItems: 1, + }, + expectedViolation: false, + }, + { + name: "field removed", + oldField: &schema.Schema{ + MinItems: 1, + }, + newField: nil, + expectedViolation: false, + }, } func TestFieldRule_ShrinkingMax(t *testing.T) { @@ -426,6 +526,22 @@ var fieldRule_ShrinkingMaxTestCases = []fieldTestCase{ }, expectedViolation: true, }, + { + name: "field added", + oldField: nil, + newField: &schema.Schema{ + MaxItems: 2, + }, + expectedViolation: false, + }, + { + name: "field removed", + oldField: &schema.Schema{ + MinItems: 2, + }, + newField: nil, + expectedViolation: false, + }, } func (tc *fieldTestCase) check(rule FieldRule, t *testing.T) { diff --git a/tools/diff-processor/rules/rules_resource_inventory.go b/tools/diff-processor/rules/rules_resource_inventory.go index 8e1d6083f50c..f3664625725e 100644 --- a/tools/diff-processor/rules/rules_resource_inventory.go +++ b/tools/diff-processor/rules/rules_resource_inventory.go @@ -15,7 +15,7 @@ type ResourceInventoryRule struct { definition string message string identifier string - isRuleBreak func(old, new map[string]*schema.Resource) []string + isRuleBreak func(old, new *schema.Resource) bool } // ResourceInventoryRules is a list of ResourceInventoryRule @@ -27,18 +27,11 @@ var resourceInventoryRule_RemovingAResource = ResourceInventoryRule{ definition: "In terraform resources should be retained whenever possible. A removable of an resource will result in a configuration breakage wherever a dependency on that resource exists. Renaming or Removing a resources are functionally equivalent in terms of configuration breakages.", message: "Resource {{resource}} was either removed or renamed", identifier: "resource-map-resource-removal-or-rename", - isRuleBreak: resourceInventoryRule_RemovingAField_func, + isRuleBreak: resourceInventoryRule_RemovingAResource_func, } -func resourceInventoryRule_RemovingAField_func(old, new map[string]*schema.Resource) []string { - keysNotPresent := []string{} - for key := range old { - _, exists := new[key] - if !exists { - keysNotPresent = append(keysNotPresent, key) - } - } - return keysNotPresent +func resourceInventoryRule_RemovingAResource_func(old, new *schema.Resource) bool { + return new == nil && old != nil } func resourceInventoryRulesToRuleArray(rms []ResourceInventoryRule) []Rule { @@ -73,15 +66,6 @@ func (rm ResourceInventoryRule) Message(resource string) string { return msg + documentationReference(rm.identifier) } -// IsRuleBreak - compares resource entries and returns -// a list of resources violating the rule -func (rm ResourceInventoryRule) IsRuleBreak(old, new map[string]*schema.Resource) []string { - if rm.isRuleBreak == nil { - return []string{} - } - return rm.isRuleBreak(old, new) -} - // Undetectable - informs if there are functions in place // to detect this rule. func (rm ResourceInventoryRule) Undetectable() bool { diff --git a/tools/diff-processor/rules/rules_resource_inventory_test.go b/tools/diff-processor/rules/rules_resource_inventory_test.go index d8a33167f552..2bc309bfdda4 100644 --- a/tools/diff-processor/rules/rules_resource_inventory_test.go +++ b/tools/diff-processor/rules/rules_resource_inventory_test.go @@ -7,10 +7,10 @@ import ( ) type resourceInventoryTestCase struct { - name string - oldResourceMap map[string]*schema.Resource - newResourceMap map[string]*schema.Resource - expectedViolations int + name string + old *schema.Resource + new *schema.Resource + expected bool } func TestResourceInventoryRule_RemovingAResource(t *testing.T) { @@ -21,113 +21,28 @@ func TestResourceInventoryRule_RemovingAResource(t *testing.T) { var resourceInventoryRule_RemovingAResourceTestCases = []resourceInventoryTestCase{ { - name: "control", - oldResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - }, - }, - }, - expectedViolations: 0, + name: "control", + old: &schema.Resource{}, + new: &schema.Resource{}, + expected: false, }, { - name: "adding a resource", - oldResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - }, - }, - "google-y": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - }, - }, - }, - expectedViolations: 0, + name: "resource added", + old: nil, + new: &schema.Resource{}, + expected: false, }, { - name: "resource missing", - oldResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep"}, - "field-b": {Description: "beep"}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{}, - expectedViolations: 1, - }, - { - name: "resource renamed", - oldResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google-y": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - }, - }, - }, - expectedViolations: 1, - }, - { - name: "resource renamed and another removed", - oldResourceMap: map[string]*schema.Resource{ - "google-x": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - }, - }, - "google-z": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google-y": { - Schema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - }, - }, - }, - expectedViolations: 2, + name: "resource removed", + old: &schema.Resource{}, + new: nil, + expected: true, }, } func (tc *resourceInventoryTestCase) check(rule ResourceInventoryRule, t *testing.T) { - violations := rule.isRuleBreak(tc.oldResourceMap, tc.newResourceMap) - if tc.expectedViolations != len(violations) { - t.Errorf("Test `%s` failed: expected %d violations, got %d", tc.name, tc.expectedViolations, len(violations)) + got := rule.isRuleBreak(tc.old, tc.new) + if tc.expected != got { + t.Errorf("Test `%s` failed: want %t, got %t", tc.name, tc.expected, got) } } diff --git a/tools/diff-processor/rules/rules_resource_schema.go b/tools/diff-processor/rules/rules_resource_schema.go index 3929238afc94..5cf6ca11915a 100644 --- a/tools/diff-processor/rules/rules_resource_schema.go +++ b/tools/diff-processor/rules/rules_resource_schema.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/GoogleCloudPlatform/magic-modules/.ci/diff-processor/diff" ) // ResourceSchemaRule provides structure for @@ -14,7 +14,7 @@ type ResourceSchemaRule struct { definition string message string identifier string - isRuleBreak func(old, new map[string]*schema.Schema) []string + isRuleBreak func(resourceDiff diff.ResourceDiff) []string } // ResourceSchemaRules is a list of ResourceInventoryRule @@ -41,15 +41,14 @@ var resourceSchemaRule_RemovingAField = ResourceSchemaRule{ isRuleBreak: resourceSchemaRule_RemovingAField_func, } -func resourceSchemaRule_RemovingAField_func(old, new map[string]*schema.Schema) []string { - keysNotPresent := []string{} - for key := range old { - _, exists := new[key] - if !exists { - keysNotPresent = append(keysNotPresent, key) +func resourceSchemaRule_RemovingAField_func(resourceDiff diff.ResourceDiff) []string { + fieldsRemoved := []string{} + for field, fieldDiff := range resourceDiff.Fields { + if fieldDiff.Old != nil && fieldDiff.New == nil { + fieldsRemoved = append(fieldsRemoved, field) } } - return keysNotPresent + return fieldsRemoved } func resourceSchemaRulesToRuleArray(rss []ResourceSchemaRule) []Rule { @@ -88,11 +87,11 @@ func (rs ResourceSchemaRule) Message(resource, field string) string { // IsRuleBreak - compares the field entries and returns // a list of fields violating the rule -func (rs ResourceSchemaRule) IsRuleBreak(old, new map[string]*schema.Schema) []string { +func (rs ResourceSchemaRule) IsRuleBreak(resourceDiff diff.ResourceDiff) []string { if rs.isRuleBreak == nil { return []string{} } - return rs.isRuleBreak(old, new) + return rs.isRuleBreak(resourceDiff) } // Undetectable - informs if there are functions in place diff --git a/tools/diff-processor/rules/rules_resource_schema_test.go b/tools/diff-processor/rules/rules_resource_schema_test.go index 01d40676649d..ea92c9740c6c 100644 --- a/tools/diff-processor/rules/rules_resource_schema_test.go +++ b/tools/diff-processor/rules/rules_resource_schema_test.go @@ -3,6 +3,9 @@ package rules import ( "testing" + "github.com/GoogleCloudPlatform/magic-modules/.ci/diff-processor/diff" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -13,77 +16,70 @@ func TestResourceSchemaRule_RemovingAField(t *testing.T) { } type resourceSchemaTestCase struct { - name string - oldResourceSchema map[string]*schema.Schema - newResourceSchema map[string]*schema.Schema - expectedViolations int + name string + resourceDiff diff.ResourceDiff + expectedFields []string } var resourceSchemaRule_RemovingAField_TestCases = []resourceSchemaTestCase{ { name: "control", - oldResourceSchema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, + resourceDiff: diff.ResourceDiff{ + Fields: map[string]diff.FieldDiff{ + "field-a": diff.FieldDiff{ + Old: &schema.Schema{Description: "beep", Optional: true}, + New: &schema.Schema{Description: "beep", Optional: true}, + }, + }, }, - newResourceSchema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - }, - expectedViolations: 0, + expectedFields: []string{}, }, { name: "adding a field", - oldResourceSchema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - }, - newResourceSchema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - "field-c": {Description: "beep", Optional: true}, - }, - expectedViolations: 0, - }, - { - name: "renaming a field", - oldResourceSchema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - }, - newResourceSchema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-d": {Description: "beep", Optional: true}, + resourceDiff: diff.ResourceDiff{ + Fields: map[string]diff.FieldDiff{ + "field-a": diff.FieldDiff{ + Old: nil, + New: &schema.Schema{Description: "beep", Optional: true}, + }, + }, }, - expectedViolations: 1, + expectedFields: []string{}, }, { name: "removing a field", - oldResourceSchema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, + resourceDiff: diff.ResourceDiff{ + Fields: map[string]diff.FieldDiff{ + "field-a": diff.FieldDiff{ + Old: &schema.Schema{Description: "beep", Optional: true}, + New: nil, + }, + }, }, - newResourceSchema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - }, - expectedViolations: 1, + expectedFields: []string{"field-a"}, }, { - name: "renaming a field and removing a field", - oldResourceSchema: map[string]*schema.Schema{ - "field-a": {Description: "beep", Optional: true}, - "field-b": {Description: "beep", Optional: true}, - }, - newResourceSchema: map[string]*schema.Schema{ - "field-z": {Description: "beep", Optional: true}, + name: "removing multiple fields", + resourceDiff: diff.ResourceDiff{ + Fields: map[string]diff.FieldDiff{ + "field-a": diff.FieldDiff{ + Old: &schema.Schema{Description: "beep", Optional: true}, + New: nil, + }, + "field-b": diff.FieldDiff{ + Old: &schema.Schema{Description: "beep", Optional: true}, + New: nil, + }, + }, }, - expectedViolations: 2, + expectedFields: []string{"field-a", "field-b"}, }, } func (tc *resourceSchemaTestCase) check(rule ResourceSchemaRule, t *testing.T) { - violations := rule.isRuleBreak(tc.oldResourceSchema, tc.newResourceSchema) - if tc.expectedViolations != len(violations) { - t.Errorf("Test `%s` failed: expected %d violations, got %d", tc.name, tc.expectedViolations, len(violations)) + fields := rule.IsRuleBreak(tc.resourceDiff) + less := func(a, b string) bool { return a < b } + if !cmp.Equal(fields, tc.expectedFields, cmpopts.SortSlices(less)) { + t.Errorf("Test `%s` failed: wanted %v , got %v", tc.name, tc.expectedFields, fields) } } From 756e2d9f58a6bdbf8090b2378a859d9d5f3ea2f5 Mon Sep 17 00:00:00 2001 From: efe Date: Fri, 22 Sep 2023 13:55:48 -0500 Subject: [PATCH 50/67] Update Instance.yaml to remove LOOKER_MODELER edition (#9033) --- mmv1/products/looker/Instance.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/mmv1/products/looker/Instance.yaml b/mmv1/products/looker/Instance.yaml index b830b54c7ac8..5aa64984ab7e 100644 --- a/mmv1/products/looker/Instance.yaml +++ b/mmv1/products/looker/Instance.yaml @@ -344,14 +344,12 @@ properties: - LOOKER_CORE_STANDARD_ANNUAL: subscription standard instance - LOOKER_CORE_ENTERPRISE_ANNUAL: subscription enterprise instance - LOOKER_CORE_EMBED_ANNUAL: subscription embed instance - - LOOKER_MODELER: standalone modeling service values: - :LOOKER_CORE_TRIAL - :LOOKER_CORE_STANDARD - :LOOKER_CORE_STANDARD_ANNUAL - :LOOKER_CORE_ENTERPRISE_ANNUAL - :LOOKER_CORE_EMBED_ANNUAL - - :LOOKER_MODELER default_value: :LOOKER_CORE_TRIAL immutable: true - !ruby/object:Api::Type::Boolean From fe5076457e66f02b9816e753d771aecd1f91027e Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Fri, 22 Sep 2023 12:13:48 -0700 Subject: [PATCH 51/67] Make labels field have all labels in data sources (#9037) --- ...ata_source_artifact_registry_repository.go | 4 +++ ...ource_artifact_registry_repository_test.go | 4 +-- ...source_google_beyondcorp_app_connection.go | 4 +++ ...e_google_beyondcorp_app_connection_test.go | 3 +++ ..._source_google_beyondcorp_app_connector.go | 4 +++ ...ce_google_beyondcorp_app_connector_test.go | 3 +++ ...ta_source_google_beyondcorp_app_gateway.go | 4 +++ ...urce_google_beyondcorp_app_gateway_test.go | 3 +++ ...a_source_google_cloudfunctions_function.go | 4 +++ ...rce_google_cloudfunctions_function_test.go | 3 +++ ..._source_google_cloudfunctions2_function.go | 4 +++ ...ce_google_cloudfunctions2_function_test.go | 4 +-- ...data_source_google_composer_environment.go | 4 +++ ...source_google_composer_environment_test.go | 5 ++++ .../data_source_google_compute_disk.go | 4 +++ .../data_source_google_compute_disk_test.go | 5 +++- ...a_source_google_compute_forwarding_rule.go | 4 +++ ...rce_google_compute_forwarding_rule_test.go | 3 +++ ...data_source_google_compute_instance.go.erb | 4 +++ ...data_source_google_compute_snapshot.go.erb | 5 +++- ...ata_source_google_compute_snapshot_test.go | 6 ++--- ...e_google_global_compute_forwarding_rule.go | 4 +++ ...gle_global_compute_forwarding_rule_test.go | 3 +++ ...a_source_dataproc_metastore_service.go.erb | 4 +++ ...rce_dataproc_metastore_service_test.go.erb | 4 +++ ...rce_google_firebase_hosting_channel.go.erb | 4 +++ ...oogle_firebase_hosting_channel_test.go.erb | 4 +++ .../kms/data_source_google_kms_crypto_key.go | 4 +++ .../data_source_certificate_authority.go | 4 +++ .../data_source_certificate_authority_test.go | 3 +++ .../pubsub/data_source_pubsub_subscription.go | 4 +++ .../data_source_pubsub_subscription_test.go | 3 +++ .../pubsub/data_source_pubsub_topic.go | 4 +++ .../pubsub/data_source_pubsub_topic_test.go | 3 +++ .../redis/data_source_redis_instance.go | 4 +++ .../redis/data_source_redis_instance_test.go | 4 +++ .../data_source_google_project.go | 4 +++ .../data_source_google_project_test.go | 3 +++ .../data_source_secret_manager_secret.go | 8 ++++++ .../data_source_secret_manager_secret_test.go | 6 ++++- .../spanner/data_source_spanner_instance.go | 4 +++ .../vertexai/data_source_vertex_ai_index.go | 4 +++ .../data_source_vertex_ai_index_test.go | 2 -- .../terraform/tpgresource/annotations.go | 19 ++++++++++++++ .../terraform/tpgresource/labels.go | 26 +++++++++++++++++++ .../d/cloudfunctions_function.html.markdown | 2 +- .../website/docs/d/compute_disk.html.markdown | 2 +- .../docs/d/compute_image.html.markdown | 2 +- .../docs/d/compute_instance.html.markdown | 2 +- .../d/compute_instance_template.html.markdown | 3 +-- .../r/cloudfunctions_function.html.markdown | 3 +++ .../docs/r/composer_environment.html.markdown | 3 +++ .../docs/r/compute_instance.html.markdown | 2 ++ .../r/compute_instance_template.html.markdown | 6 +++++ .../website/docs/r/dataproc_job.html.markdown | 2 ++ .../docs/r/google_project.html.markdown | 2 ++ 56 files changed, 227 insertions(+), 18 deletions(-) diff --git a/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository.go b/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository.go index fb0271a17040..272ec3411b70 100644 --- a/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository.go +++ b/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository.go @@ -46,6 +46,10 @@ func dataSourceArtifactRegistryRepositoryRead(d *schema.ResourceData, meta inter return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + if d.Id() == "" { return fmt.Errorf("%s not found", id) } diff --git a/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository_test.go b/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository_test.go index 735bec2d3beb..22c2f610e1e8 100644 --- a/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository_test.go +++ b/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository_test.go @@ -23,8 +23,8 @@ func TestAccDataSourceGoogleArtifactRegistryRepositoryConfig(t *testing.T) { { Config: testAccDataSourceGoogleArtifactRegistryRepositoryConfig(context), Check: resource.ComposeTestCheckFunc( - acctest.CheckDataSourceStateMatchesResourceStateWithIgnores(funcDataName, - "google_artifact_registry_repository.my-repo", map[string]struct{}{"labels.%": {}, "terraform_labels.%": {}}), + acctest.CheckDataSourceStateMatchesResourceState(funcDataName, + "google_artifact_registry_repository.my-repo"), ), }, }, diff --git a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection.go b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection.go index 13d16ca2c5de..38240dbb8e5f 100644 --- a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection.go +++ b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection.go @@ -46,6 +46,10 @@ func dataSourceGoogleBeyondcorpAppConnectionRead(d *schema.ResourceData, meta in return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + if d.Id() == "" { return fmt.Errorf("%s not found", id) } diff --git a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection_test.go b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection_test.go index 66a488a29163..44288c2a5eca 100644 --- a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection_test.go +++ b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection_test.go @@ -76,6 +76,9 @@ resource "google_beyondcorp_app_connection" "foo" { port = 8080 } connectors = [google_beyondcorp_app_connector.app_connector.id] + labels = { + my-label = "my-label-value" + } } data "google_beyondcorp_app_connection" "foo" { diff --git a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connector.go b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connector.go index b06bc5f4fbbe..1f4132bababc 100644 --- a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connector.go +++ b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connector.go @@ -46,6 +46,10 @@ func dataSourceGoogleBeyondcorpAppConnectorRead(d *schema.ResourceData, meta int return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + if d.Id() == "" { return fmt.Errorf("%s not found", id) } diff --git a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connector_test.go b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connector_test.go index 5bf5acf3b67a..4a8274f905bc 100644 --- a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connector_test.go +++ b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connector_test.go @@ -179,6 +179,9 @@ resource "google_beyondcorp_app_connector" "foo" { email = google_service_account.service_account.email } } + labels = { + my-label = "my-label-value" + } } data "google_beyondcorp_app_connector" "foo" { diff --git a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_gateway.go b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_gateway.go index 104f2798482e..6f31635a2954 100644 --- a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_gateway.go +++ b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_gateway.go @@ -46,6 +46,10 @@ func dataSourceGoogleBeyondcorpAppGatewayRead(d *schema.ResourceData, meta inter return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + if d.Id() == "" { return fmt.Errorf("%s not found", id) } diff --git a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_gateway_test.go b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_gateway_test.go index c7c8f943d446..ca345530c263 100644 --- a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_gateway_test.go +++ b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_gateway_test.go @@ -101,6 +101,9 @@ resource "google_beyondcorp_app_gateway" "foo" { name = "tf-test-appgateway-%{random_suffix}" type = "TCP_PROXY" host_type = "GCP_REGIONAL_MIG" + labels = { + my-label = "my-label-value" + } } data "google_beyondcorp_app_gateway" "foo" { diff --git a/mmv1/third_party/terraform/services/cloudfunctions/data_source_google_cloudfunctions_function.go b/mmv1/third_party/terraform/services/cloudfunctions/data_source_google_cloudfunctions_function.go index 5255c37268df..7d019ed5e2f0 100644 --- a/mmv1/third_party/terraform/services/cloudfunctions/data_source_google_cloudfunctions_function.go +++ b/mmv1/third_party/terraform/services/cloudfunctions/data_source_google_cloudfunctions_function.go @@ -50,6 +50,10 @@ func dataSourceGoogleCloudFunctionsFunctionRead(d *schema.ResourceData, meta int return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + if d.Id() == "" { return fmt.Errorf("%s not found", cloudFuncId.CloudFunctionId()) } diff --git a/mmv1/third_party/terraform/services/cloudfunctions/data_source_google_cloudfunctions_function_test.go b/mmv1/third_party/terraform/services/cloudfunctions/data_source_google_cloudfunctions_function_test.go index 68dd233c3584..ee1d0bd66f10 100644 --- a/mmv1/third_party/terraform/services/cloudfunctions/data_source_google_cloudfunctions_function_test.go +++ b/mmv1/third_party/terraform/services/cloudfunctions/data_source_google_cloudfunctions_function_test.go @@ -61,6 +61,9 @@ resource "google_cloudfunctions_function" "function_http" { trigger_http = true timeout = 61 entry_point = "helloGET" + labels = { + my-label = "my-label-value" + } } data "google_cloudfunctions_function" "function_http" { diff --git a/mmv1/third_party/terraform/services/cloudfunctions2/data_source_google_cloudfunctions2_function.go b/mmv1/third_party/terraform/services/cloudfunctions2/data_source_google_cloudfunctions2_function.go index 6769c2701231..b04f0f692bb9 100644 --- a/mmv1/third_party/terraform/services/cloudfunctions2/data_source_google_cloudfunctions2_function.go +++ b/mmv1/third_party/terraform/services/cloudfunctions2/data_source_google_cloudfunctions2_function.go @@ -40,6 +40,10 @@ func dataSourceGoogleCloudFunctions2FunctionRead(d *schema.ResourceData, meta in return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + if d.Id() == "" { return fmt.Errorf("%s not found", id) } diff --git a/mmv1/third_party/terraform/services/cloudfunctions2/data_source_google_cloudfunctions2_function_test.go b/mmv1/third_party/terraform/services/cloudfunctions2/data_source_google_cloudfunctions2_function_test.go index 7f4d5db5baf7..a1f842ea9fc3 100644 --- a/mmv1/third_party/terraform/services/cloudfunctions2/data_source_google_cloudfunctions2_function_test.go +++ b/mmv1/third_party/terraform/services/cloudfunctions2/data_source_google_cloudfunctions2_function_test.go @@ -24,8 +24,8 @@ func TestAccDataSourceGoogleCloudFunctions2Function_basic(t *testing.T) { { Config: testAccDataSourceGoogleCloudFunctions2FunctionConfig(functionName, bucketName, zipFilePath), - // As the value of "labels" and "terraform_labels" in the state is dependent on the configuration, - // and these fields are not set in the configuration of the data source, so these fields are empty in the state of the data source. + // As the value of "labels" and "terraform_labels" in the state of the data source are all labels, + // but the "labels" field in resource are user defined labels, which is the reason for the mismatch. Check: resource.ComposeTestCheckFunc( acctest.CheckDataSourceStateMatchesResourceStateWithIgnores(funcDataNameHttp, "google_cloudfunctions2_function.function_http_v2", map[string]struct{}{"build_config.0.source.0.storage_source.0.bucket": {}, "build_config.0.source.0.storage_source.0.object": {}, "labels.%": {}, "terraform_labels.%": {}}), diff --git a/mmv1/third_party/terraform/services/composer/data_source_google_composer_environment.go b/mmv1/third_party/terraform/services/composer/data_source_google_composer_environment.go index 5b37ab9ad17a..cf52d32638d6 100644 --- a/mmv1/third_party/terraform/services/composer/data_source_google_composer_environment.go +++ b/mmv1/third_party/terraform/services/composer/data_source_google_composer_environment.go @@ -42,6 +42,10 @@ func dataSourceGoogleComposerEnvironmentRead(d *schema.ResourceData, meta interf return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + if d.Id() == "" { return fmt.Errorf("%s not found", id) } diff --git a/mmv1/third_party/terraform/services/composer/data_source_google_composer_environment_test.go b/mmv1/third_party/terraform/services/composer/data_source_google_composer_environment_test.go index b01db3b3e114..a81eff7b2284 100644 --- a/mmv1/third_party/terraform/services/composer/data_source_google_composer_environment_test.go +++ b/mmv1/third_party/terraform/services/composer/data_source_google_composer_environment_test.go @@ -25,6 +25,8 @@ func TestAccDataSourceComposerEnvironment_basic(t *testing.T) { { Config: testAccDataSourceComposerEnvironment_basic(context), Check: resource.ComposeTestCheckFunc( + acctest.CheckDataSourceStateMatchesResourceState("data.google_composer_environment.test", + "google_composer_environment.test"), testAccCheckGoogleComposerEnvironmentMeta("data.google_composer_environment.test"), ), }, @@ -91,6 +93,9 @@ resource "google_composer_environment" "test" { image_version = "composer-1-airflow-2" } } + labels = { + my-label = "my-label-value" + } } // use a separate network to avoid conflicts with other tests running in parallel diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_disk.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_disk.go index 7a68c1fa9f7c..d96674df17d7 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_disk.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_disk.go @@ -34,6 +34,10 @@ func dataSourceGoogleComputeDiskRead(d *schema.ResourceData, meta interface{}) e return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + if d.Id() == "" { return fmt.Errorf("%s not found", id) } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_disk_test.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_disk_test.go index 3ab5cb82b9eb..b978a3834c4c 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_disk_test.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_disk_test.go @@ -32,7 +32,10 @@ func TestAccDataSourceGoogleComputeDisk_basic(t *testing.T) { func testAccDataSourceGoogleComputeDisk_basic(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_compute_disk" "foo" { - name = "tf-test-compute-disk-%{random_suffix}" + name = "tf-test-compute-disk-%{random_suffix}" + labels = { + my-label = "my-label-value" + } } data "google_compute_disk" "foo" { diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rule.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rule.go index 555748f1064e..3e7abe2278d1 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rule.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rule.go @@ -47,6 +47,10 @@ func dataSourceGoogleComputeForwardingRuleRead(d *schema.ResourceData, meta inte return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + if d.Id() == "" { return fmt.Errorf("%s not found", id) } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rule_test.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rule_test.go index 1238648064a5..b30bb8ce3056 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rule_test.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rule_test.go @@ -40,6 +40,9 @@ resource "google_compute_forwarding_rule" "foobar-fr" { name = "%s" port_range = "80-81" target = google_compute_target_pool.foobar-tp.self_link + labels = { + my-label = "my-label-value" + } } data "google_compute_forwarding_rule" "my_forwarding_rule" { diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance.go.erb b/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance.go.erb index 0c885da98bd8..7b0734cf6455 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance.go.erb +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance.go.erb @@ -98,6 +98,10 @@ func dataSourceGoogleComputeInstanceRead(d *schema.ResourceData, meta interface{ return err } + if err := d.Set("terraform_labels", instance.Labels); err != nil { + return err + } + if instance.LabelFingerprint != "" { if err := d.Set("label_fingerprint", instance.LabelFingerprint); err != nil { return fmt.Errorf("Error setting label_fingerprint: %s", err) diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_snapshot.go.erb b/mmv1/third_party/terraform/services/compute/data_source_google_compute_snapshot.go.erb index ea1d893715c2..a226612788c3 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_snapshot.go.erb +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_snapshot.go.erb @@ -107,7 +107,10 @@ func dataSourceGoogleComputeSnapshotRead(d *schema.ResourceData, meta interface{ func retrieveSnapshot(d *schema.ResourceData, meta interface{}, project, name string) error { d.SetId("projects/" + project + "/global/snapshots/" + name) d.Set("name", name) - return resourceComputeSnapshotRead(d, meta) + if err := resourceComputeSnapshotRead(d, meta); err != nil { + return err + } + return tpgresource.SetDataSourceLabels(d) } // ByCreationTimestamp implements sort.Interface for []*Snapshot based on diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_snapshot_test.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_snapshot_test.go index 2706ad32c8f2..97c0c1111646 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_snapshot_test.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_snapshot_test.go @@ -21,7 +21,7 @@ func TestAccSnapshotDatasource_name(t *testing.T) { acctest.CheckDataSourceStateMatchesResourceStateWithIgnores( "data.google_compute_snapshot.default", "google_compute_snapshot.default", - map[string]struct{}{"zone": {}, "labels.%": {}, "terraform_labels.%": {}}, + map[string]struct{}{"zone": {}}, ), ), }, @@ -42,7 +42,7 @@ func TestAccSnapshotDatasource_filter(t *testing.T) { acctest.CheckDataSourceStateMatchesResourceStateWithIgnores( "data.google_compute_snapshot.default", "google_compute_snapshot.c", - map[string]struct{}{"zone": {}, "labels.%": {}, "terraform_labels.%": {}}, + map[string]struct{}{"zone": {}}, ), ), }, @@ -63,7 +63,7 @@ func TestAccSnapshotDatasource_filterMostRecent(t *testing.T) { acctest.CheckDataSourceStateMatchesResourceStateWithIgnores( "data.google_compute_snapshot.default", "google_compute_snapshot.c", - map[string]struct{}{"zone": {}, "labels.%": {}, "terraform_labels.%": {}}, + map[string]struct{}{"zone": {}}, ), ), }, diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_global_compute_forwarding_rule.go b/mmv1/third_party/terraform/services/compute/data_source_google_global_compute_forwarding_rule.go index ed1bad56b537..24b840a9383e 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_global_compute_forwarding_rule.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_global_compute_forwarding_rule.go @@ -41,6 +41,10 @@ func dataSourceGoogleComputeGlobalForwardingRuleRead(d *schema.ResourceData, met return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + if d.Id() == "" { return fmt.Errorf("%s not found", id) } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_global_compute_forwarding_rule_test.go b/mmv1/third_party/terraform/services/compute/data_source_google_global_compute_forwarding_rule_test.go index 70e2f3e6099d..bfb94ba7d822 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_global_compute_forwarding_rule_test.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_global_compute_forwarding_rule_test.go @@ -32,6 +32,9 @@ resource "google_compute_global_forwarding_rule" "foobar-fr" { name = "%s" target = google_compute_target_http_proxy.default.id port_range = "80" + labels = { + my-label = "my-label-value" + } } resource "google_compute_target_http_proxy" "default" { diff --git a/mmv1/third_party/terraform/services/dataprocmetastore/data_source_dataproc_metastore_service.go.erb b/mmv1/third_party/terraform/services/dataprocmetastore/data_source_dataproc_metastore_service.go.erb index 76b166edfa33..38225a1d54ad 100644 --- a/mmv1/third_party/terraform/services/dataprocmetastore/data_source_dataproc_metastore_service.go.erb +++ b/mmv1/third_party/terraform/services/dataprocmetastore/data_source_dataproc_metastore_service.go.erb @@ -33,6 +33,10 @@ func dataSourceDataprocMetastoreServiceRead(d *schema.ResourceData, meta interfa return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + if d.Id() == "" { return fmt.Errorf("%s not found", id) } diff --git a/mmv1/third_party/terraform/services/dataprocmetastore/data_source_dataproc_metastore_service_test.go.erb b/mmv1/third_party/terraform/services/dataprocmetastore/data_source_dataproc_metastore_service_test.go.erb index 23832fffb79c..bb8ef1bcabdc 100644 --- a/mmv1/third_party/terraform/services/dataprocmetastore/data_source_dataproc_metastore_service_test.go.erb +++ b/mmv1/third_party/terraform/services/dataprocmetastore/data_source_dataproc_metastore_service_test.go.erb @@ -38,6 +38,10 @@ resource "google_dataproc_metastore_service" "my_metastore" { hive_metastore_config { version = "2.3.6" } + + labels = { + env = "test" + } } data "google_dataproc_metastore_service" "my_metastore" { diff --git a/mmv1/third_party/terraform/services/firebasehosting/data_source_google_firebase_hosting_channel.go.erb b/mmv1/third_party/terraform/services/firebasehosting/data_source_google_firebase_hosting_channel.go.erb index 993392fd2b1c..1a888cbd4f6c 100644 --- a/mmv1/third_party/terraform/services/firebasehosting/data_source_google_firebase_hosting_channel.go.erb +++ b/mmv1/third_party/terraform/services/firebasehosting/data_source_google_firebase_hosting_channel.go.erb @@ -36,6 +36,10 @@ func dataSourceGoogleFirebaseHostingChannelRead(d *schema.ResourceData, meta int return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + if d.Id() == "" { return fmt.Errorf("%s not found", id) } diff --git a/mmv1/third_party/terraform/services/firebasehosting/data_source_google_firebase_hosting_channel_test.go.erb b/mmv1/third_party/terraform/services/firebasehosting/data_source_google_firebase_hosting_channel_test.go.erb index ecb0f42ddd07..dc9adf02ea9e 100644 --- a/mmv1/third_party/terraform/services/firebasehosting/data_source_google_firebase_hosting_channel_test.go.erb +++ b/mmv1/third_party/terraform/services/firebasehosting/data_source_google_firebase_hosting_channel_test.go.erb @@ -44,6 +44,10 @@ resource "google_firebase_hosting_site" "default" { resource "google_firebase_hosting_channel" "channel" { site_id = google_firebase_hosting_site.default.site_id channel_id = "tf-test-channel%{random_suffix}" + + labels = { + foo = "bar" + } } data "google_firebase_hosting_channel" "channel" { diff --git a/mmv1/third_party/terraform/services/kms/data_source_google_kms_crypto_key.go b/mmv1/third_party/terraform/services/kms/data_source_google_kms_crypto_key.go index 0d39492d0f27..670d67f40e66 100644 --- a/mmv1/third_party/terraform/services/kms/data_source_google_kms_crypto_key.go +++ b/mmv1/third_party/terraform/services/kms/data_source_google_kms_crypto_key.go @@ -41,6 +41,10 @@ func dataSourceGoogleKmsCryptoKeyRead(d *schema.ResourceData, meta interface{}) return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + if d.Id() == "" { return fmt.Errorf("%s not found", id) } diff --git a/mmv1/third_party/terraform/services/privateca/data_source_certificate_authority.go b/mmv1/third_party/terraform/services/privateca/data_source_certificate_authority.go index b2beeb943b01..062930dca191 100644 --- a/mmv1/third_party/terraform/services/privateca/data_source_certificate_authority.go +++ b/mmv1/third_party/terraform/services/privateca/data_source_certificate_authority.go @@ -45,6 +45,10 @@ func dataSourcePrivatecaCertificateAuthorityRead(d *schema.ResourceData, meta in return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + // pem_csr is only applicable for SUBORDINATE CertificateAuthorities when their state is AWAITING_USER_ACTIVATION if d.Get("type") == "SUBORDINATE" && d.Get("state") == "AWAITING_USER_ACTIVATION" { url, err := tpgresource.ReplaceVars(d, config, "{{PrivatecaBasePath}}projects/{{project}}/locations/{{location}}/caPools/{{pool}}/certificateAuthorities/{{certificate_authority_id}}:fetch") diff --git a/mmv1/third_party/terraform/services/privateca/data_source_certificate_authority_test.go b/mmv1/third_party/terraform/services/privateca/data_source_certificate_authority_test.go index 2a7cdfb4c2d1..e50ba6119073 100644 --- a/mmv1/third_party/terraform/services/privateca/data_source_certificate_authority_test.go +++ b/mmv1/third_party/terraform/services/privateca/data_source_certificate_authority_test.go @@ -81,6 +81,9 @@ resource "google_privateca_certificate_authority" "default" { key_spec { algorithm = "RSA_PKCS1_4096_SHA256" } + labels = { + my-label = "my-label-value" + } } data "google_privateca_certificate_authority" "default" { diff --git a/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_subscription.go b/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_subscription.go index 2e0b49ecb368..dde9618c8327 100644 --- a/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_subscription.go +++ b/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_subscription.go @@ -33,6 +33,10 @@ func dataSourceGooglePubsubSubscriptionRead(d *schema.ResourceData, meta interfa return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + if d.Id() == "" { return fmt.Errorf("%s not found", id) } diff --git a/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_subscription_test.go b/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_subscription_test.go index a5c976e9241e..ffe48a0bae3a 100644 --- a/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_subscription_test.go +++ b/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_subscription_test.go @@ -60,6 +60,9 @@ resource "google_pubsub_topic" "foo" { resource "google_pubsub_subscription" "foo" { name = "tf-test-pubsub-subscription-%{random_suffix}" topic = google_pubsub_topic.foo.name + labels = { + my-label = "my-label-value" + } } data "google_pubsub_subscription" "foo" { diff --git a/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_topic.go b/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_topic.go index 158d1c600535..a813bc152dca 100644 --- a/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_topic.go +++ b/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_topic.go @@ -33,6 +33,10 @@ func dataSourceGooglePubsubTopicRead(d *schema.ResourceData, meta interface{}) e return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + if d.Id() == "" { return fmt.Errorf("%s not found", id) } diff --git a/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_topic_test.go b/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_topic_test.go index b5f6efa8504c..e3b4614d1ca6 100644 --- a/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_topic_test.go +++ b/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_topic_test.go @@ -55,6 +55,9 @@ func testAccDataSourceGooglePubsubTopic_basic(context map[string]interface{}) st return acctest.Nprintf(` resource "google_pubsub_topic" "foo" { name = "tf-test-pubsub-%{random_suffix}" + labels = { + my-label = "my-label-value" + } } data "google_pubsub_topic" "foo" { diff --git a/mmv1/third_party/terraform/services/redis/data_source_redis_instance.go b/mmv1/third_party/terraform/services/redis/data_source_redis_instance.go index 2dd7ad098b71..1d16a177a860 100644 --- a/mmv1/third_party/terraform/services/redis/data_source_redis_instance.go +++ b/mmv1/third_party/terraform/services/redis/data_source_redis_instance.go @@ -36,6 +36,10 @@ func dataSourceGoogleRedisInstanceRead(d *schema.ResourceData, meta interface{}) return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + if d.Id() == "" { return fmt.Errorf("%s not found", id) } diff --git a/mmv1/third_party/terraform/services/redis/data_source_redis_instance_test.go b/mmv1/third_party/terraform/services/redis/data_source_redis_instance_test.go index 0c03762b0021..35942e513aec 100644 --- a/mmv1/third_party/terraform/services/redis/data_source_redis_instance_test.go +++ b/mmv1/third_party/terraform/services/redis/data_source_redis_instance_test.go @@ -30,6 +30,10 @@ func testAccRedisInstanceDatasourceConfig(suffix string) string { resource "google_redis_instance" "redis" { name = "redis-test-%s" memory_size_gb = 1 + + labels = { + my-label = "my-label-value" + } } data "google_redis_instance" "redis" { diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project.go index 03584ed4b02a..d5cd9c738087 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project.go @@ -42,6 +42,10 @@ func datasourceGoogleProjectRead(d *schema.ResourceData, meta interface{}) error return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + if d.Id() == "" { return fmt.Errorf("%s not found or not in ACTIVE state", id) } diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_test.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_test.go index 033ce759d4fb..513be054caaa 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_test.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_test.go @@ -41,6 +41,9 @@ resource "google_project" "project" { project_id = "%s" name = "%s" org_id = "%s" + labels = { + my-label = "my-label-value" + } } data "google_project" "project" { diff --git a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret.go b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret.go index a7a725dccfa5..007bd1e2a8f1 100644 --- a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret.go +++ b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret.go @@ -31,6 +31,14 @@ func dataSourceSecretManagerSecretRead(d *schema.ResourceData, meta interface{}) return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + + if err := tpgresource.SetDataSourceAnnotations(d); err != nil { + return err + } + if d.Id() == "" { return fmt.Errorf("%s not found", id) } diff --git a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_test.go b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_test.go index 839b498ebbfa..d175df4012a8 100644 --- a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_test.go +++ b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_test.go @@ -25,7 +25,7 @@ func TestAccDataSourceSecretManagerSecret_basic(t *testing.T) { acctest.CheckDataSourceStateMatchesResourceStateWithIgnores( "data.google_secret_manager_secret.foo", "google_secret_manager_secret.bar", - map[string]struct{}{"zone": {}, "labels.%": {}, "terraform_labels.%": {}}, + map[string]struct{}{"zone": {}}, ), ), }, @@ -42,6 +42,10 @@ resource "google_secret_manager_secret" "bar" { label = "my-label" } + annotations = { + annotation = "my-annotation" + } + replication { user_managed { replicas { diff --git a/mmv1/third_party/terraform/services/spanner/data_source_spanner_instance.go b/mmv1/third_party/terraform/services/spanner/data_source_spanner_instance.go index 4c1fb9a0c563..afdbce7f040d 100644 --- a/mmv1/third_party/terraform/services/spanner/data_source_spanner_instance.go +++ b/mmv1/third_party/terraform/services/spanner/data_source_spanner_instance.go @@ -37,6 +37,10 @@ func dataSourceSpannerInstanceRead(d *schema.ResourceData, meta interface{}) err return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + if d.Id() == "" { return fmt.Errorf("%s not found", id) } diff --git a/mmv1/third_party/terraform/services/vertexai/data_source_vertex_ai_index.go b/mmv1/third_party/terraform/services/vertexai/data_source_vertex_ai_index.go index 8cd28fdb7044..8353f7598327 100644 --- a/mmv1/third_party/terraform/services/vertexai/data_source_vertex_ai_index.go +++ b/mmv1/third_party/terraform/services/vertexai/data_source_vertex_ai_index.go @@ -34,6 +34,10 @@ func dataSourceVertexAIIndexRead(d *schema.ResourceData, meta interface{}) error return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + if d.Id() == "" { return fmt.Errorf("%s not found", id) } diff --git a/mmv1/third_party/terraform/services/vertexai/data_source_vertex_ai_index_test.go b/mmv1/third_party/terraform/services/vertexai/data_source_vertex_ai_index_test.go index 5813d9adfc7b..a1e4b56bfd6e 100644 --- a/mmv1/third_party/terraform/services/vertexai/data_source_vertex_ai_index_test.go +++ b/mmv1/third_party/terraform/services/vertexai/data_source_vertex_ai_index_test.go @@ -31,8 +31,6 @@ func TestAccDataSourceVertexAIIndex_basic(t *testing.T) { map[string]struct{}{ "metadata.0.contents_delta_uri": {}, "metadata.0.is_complete_overwrite": {}, - "labels.%": {}, - "terraform_labels.%": {}, }, ), ), diff --git a/mmv1/third_party/terraform/tpgresource/annotations.go b/mmv1/third_party/terraform/tpgresource/annotations.go index 183356e1cb44..3739a0cea62b 100644 --- a/mmv1/third_party/terraform/tpgresource/annotations.go +++ b/mmv1/third_party/terraform/tpgresource/annotations.go @@ -66,3 +66,22 @@ func SetMetadataAnnotationsDiff(_ context.Context, d *schema.ResourceDiff, meta return nil } + +// Sets the "annotations" field with the value of the field "effective_annotations" for data sources. +// When reading data source, as the annotations field is unavailable in the configuration of the data source, +// the "annotations" field will be empty. With this funciton, the labels "annotations" will have all of annotations in the resource. +func SetDataSourceAnnotations(d *schema.ResourceData) error { + effectiveAnnotations := d.Get("effective_annotations") + if effectiveAnnotations == nil { + return nil + } + + if d.Get("annotations") == nil { + return fmt.Errorf("`annotations` field is not present in the resource schema.") + } + if err := d.Set("annotations", effectiveAnnotations); err != nil { + return fmt.Errorf("Error setting annotations in data source: %s", err) + } + + return nil +} diff --git a/mmv1/third_party/terraform/tpgresource/labels.go b/mmv1/third_party/terraform/tpgresource/labels.go index 0a241e14e1fe..7b80869a972a 100644 --- a/mmv1/third_party/terraform/tpgresource/labels.go +++ b/mmv1/third_party/terraform/tpgresource/labels.go @@ -27,6 +27,32 @@ func SetLabels(labels map[string]string, d *schema.ResourceData, lineage string) return d.Set(lineage, transformed) } +// Sets the "labels" field and "terraform_labels" with the value of the field "effective_labels" for data sources. +// When reading data source, as the labels field is unavailable in the configuration of the data source, +// the "labels" field will be empty. With this funciton, the labels "field" will have all of labels in the resource. +func SetDataSourceLabels(d *schema.ResourceData) error { + effectiveLabels := d.Get("effective_labels") + if effectiveLabels == nil { + return nil + } + + if d.Get("labels") == nil { + return fmt.Errorf("`labels` field is not present in the resource schema.") + } + if err := d.Set("labels", effectiveLabels); err != nil { + return fmt.Errorf("Error setting labels in data source: %s", err) + } + + if d.Get("terraform_labels") == nil { + return fmt.Errorf("`terraform_labels` field is not present in the resource schema.") + } + if err := d.Set("terraform_labels", effectiveLabels); err != nil { + return fmt.Errorf("Error setting terraform_labels in data source: %s", err) + } + + return nil +} + func SetLabelsDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) error { config := meta.(*transport_tpg.Config) diff --git a/mmv1/third_party/terraform/website/docs/d/cloudfunctions_function.html.markdown b/mmv1/third_party/terraform/website/docs/d/cloudfunctions_function.html.markdown index e3ca05447d0c..1b4e2f7dd5b2 100644 --- a/mmv1/third_party/terraform/website/docs/d/cloudfunctions_function.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/cloudfunctions_function.html.markdown @@ -49,7 +49,7 @@ exported: * `event_trigger` - A source that fires events in response to a condition in another service. Structure is [documented below](#nested_event_trigger). * `https_trigger_url` - If function is triggered by HTTP, trigger URL is set here. * `ingress_settings` - Controls what traffic can reach the function. -* `labels` - A map of labels applied to this function. +* `labels` - All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. * `service_account_email` - The service account email to be assumed by the cloud function. * `vpc_connector` - The VPC Network Connector that this cloud function can connect to. * `vpc_connector_egress_settings` - The egress settings for the connector, controlling what traffic is diverted through it. diff --git a/mmv1/third_party/terraform/website/docs/d/compute_disk.html.markdown b/mmv1/third_party/terraform/website/docs/d/compute_disk.html.markdown index 65596b090bfa..33ad9dc772af 100644 --- a/mmv1/third_party/terraform/website/docs/d/compute_disk.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/compute_disk.html.markdown @@ -82,7 +82,7 @@ In addition to the arguments listed above, the following computed attributes are * `description` - The optional description of this resource. -* `labels` - A map of labels applied to this disk. +* `labels` - All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. * `size` - Size of the persistent disk, specified in GB. diff --git a/mmv1/third_party/terraform/website/docs/d/compute_image.html.markdown b/mmv1/third_party/terraform/website/docs/d/compute_image.html.markdown index e9cdc9616ad6..883e99fc0bfd 100644 --- a/mmv1/third_party/terraform/website/docs/d/compute_image.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/compute_image.html.markdown @@ -71,7 +71,7 @@ exported: * `source_disk_id` - The ID value of the disk used to create this image. * `creation_timestamp` - The creation timestamp in RFC3339 text format. * `description` - An optional description of this image. -* `labels` - A map of labels applied to this image. +* `labels` - All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. * `label_fingerprint` - A fingerprint for the labels being applied to this image. * `licenses` - A list of applicable license URI. * `status` - The status of the image. Possible values are **FAILED**, **PENDING**, or **READY**. diff --git a/mmv1/third_party/terraform/website/docs/d/compute_instance.html.markdown b/mmv1/third_party/terraform/website/docs/d/compute_instance.html.markdown index d478a3eca5ae..1d3e8dc06205 100644 --- a/mmv1/third_party/terraform/website/docs/d/compute_instance.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/compute_instance.html.markdown @@ -57,7 +57,7 @@ The following arguments are supported: * `guest_accelerator` - List of the type and count of accelerator cards attached to the instance. Structure is [documented below](#nested_guest_accelerator). -* `labels` - A set of key/value label pairs assigned to the instance. +* `labels` - All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. * `metadata` - Metadata key/value pairs made available within the instance. diff --git a/mmv1/third_party/terraform/website/docs/d/compute_instance_template.html.markdown b/mmv1/third_party/terraform/website/docs/d/compute_instance_template.html.markdown index e771c3be87c5..3142f0af8932 100644 --- a/mmv1/third_party/terraform/website/docs/d/compute_instance_template.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/compute_instance_template.html.markdown @@ -78,8 +78,7 @@ The following arguments are supported: * `instance_description` - A brief description to use for instances created from this template. -* `labels` - A set of key/value label pairs to assign to instances - created from this template, +* `labels` - All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. * `metadata` - Metadata key/value pairs to make available from within instances created from this template. diff --git a/mmv1/third_party/terraform/website/docs/r/cloudfunctions_function.html.markdown b/mmv1/third_party/terraform/website/docs/r/cloudfunctions_function.html.markdown index 8d0ada5aa626..c73d6561aab6 100644 --- a/mmv1/third_party/terraform/website/docs/r/cloudfunctions_function.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/cloudfunctions_function.html.markdown @@ -134,6 +134,9 @@ Eg. `"nodejs16"`, `"python39"`, `"dotnet3"`, `"go116"`, `"java11"`, `"ruby30"`, * `labels` - (Optional) A set of key/value label pairs to assign to the function. Label keys must follow the requirements at https://cloud.google.com/resource-manager/docs/creating-managing-labels#requirements. +**Note**: This field is non-authoritative, and will only manage the labels present in your configuration. +Please refer to the field 'effective_labels' for all of the labels present on the resource. + * `terraform_labels` - The combination of labels configured directly on the resource and default labels configured on the provider. 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 792ff022fbb1..94c3fb60920d 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 @@ -262,6 +262,9 @@ The following arguments are supported: No more than 64 labels can be associated with a given environment. Both keys and values must be <= 128 bytes in size. + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field 'effective_labels' for all of the labels present on the resource. + * `terraform_labels` - The combination of labels configured directly on the resource and default labels configured on the provider. diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown index 53fc20e6a377..965f0d80a9d6 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown @@ -117,6 +117,8 @@ The following arguments are supported: For more details about this behavior, see [this section](https://www.terraform.io/docs/configuration/attr-as-blocks.html#defining-a-fixed-object-collection-value). * `labels` - (Optional) A map of key/value label pairs to assign to the instance. + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field 'effective_labels' for all of the labels present on the resource. * `terraform_labels` - The combination of labels configured directly on the resource and default labels configured on the provider. diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown index c04c64137d4d..b6c5fe8b88d1 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown @@ -308,6 +308,12 @@ The following arguments are supported: * `labels` - (Optional) A set of key/value label pairs to assign to instances created from this template. + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field 'effective_labels' for all of the labels present on the resource. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. + * `metadata` - (Optional) Metadata key/value pairs to make available from within instances created from this template. diff --git a/mmv1/third_party/terraform/website/docs/r/dataproc_job.html.markdown b/mmv1/third_party/terraform/website/docs/r/dataproc_job.html.markdown index 0e9953079fbe..84094a189b4a 100644 --- a/mmv1/third_party/terraform/website/docs/r/dataproc_job.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/dataproc_job.html.markdown @@ -102,6 +102,8 @@ output "pyspark_status" { job is first cancelled before issuing the delete. * `labels` - (Optional) The list of labels (key/value pairs) to add to the job. + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field 'effective_labels' for all of the labels present on the resource. * `terraform_labels` - The combination of labels configured directly on the resource and default labels configured on the provider. diff --git a/mmv1/third_party/terraform/website/docs/r/google_project.html.markdown b/mmv1/third_party/terraform/website/docs/r/google_project.html.markdown index e5139412d01c..1f3a4dff8368 100644 --- a/mmv1/third_party/terraform/website/docs/r/google_project.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/google_project.html.markdown @@ -82,6 +82,8 @@ The following arguments are supported: without deleting the Project via the Google API. * `labels` - (Optional) A set of key/value label pairs to assign to the project. + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field 'effective_labels' for all of the labels present on the resource. * `terraform_labels` - The combination of labels configured directly on the resource and default labels configured on the provider. From c896b4638940f18e32a80e651cde14383cadfd35 Mon Sep 17 00:00:00 2001 From: Riley Karson Date: Fri, 22 Sep 2023 12:34:10 -0700 Subject: [PATCH 52/67] Breaking change: Rework taint model in GKE (#9011) --- .../services/container/node_config.go.erb | 182 ++++++++---------- .../resource_container_cluster.go.erb | 2 +- .../resource_container_cluster_test.go.erb | 16 +- .../resource_container_node_pool.go.erb | 2 +- .../resource_container_node_pool_test.go.erb | 87 +-------- .../docs/r/container_cluster.html.markdown | 17 +- 6 files changed, 106 insertions(+), 200 deletions(-) diff --git a/mmv1/third_party/terraform/services/container/node_config.go.erb b/mmv1/third_party/terraform/services/container/node_config.go.erb index 8872ef39f07b..9c08293391be 100644 --- a/mmv1/third_party/terraform/services/container/node_config.go.erb +++ b/mmv1/third_party/terraform/services/container/node_config.go.erb @@ -411,18 +411,10 @@ func schemaNodeConfig() *schema.Schema { }, "taint": { - Type: schema.TypeList, - Optional: true, - // Computed=true because GKE Sandbox will automatically add taints to nodes that can/cannot run sandboxed pods. - Computed: true, - ForceNew: true, - // Legacy config mode allows explicitly defining an empty taint. - // See https://www.terraform.io/docs/configuration/attr-as-blocks.html - ConfigMode: schema.SchemaConfigModeAttr, + Type: schema.TypeList, + Optional: true, + ForceNew: true, Description: `List of Kubernetes taints to be applied to each node.`, - <% unless version.nil? || version == 'ga' -%> - DiffSuppressFunc: containerNodePoolTaintSuppress, - <% end -%> Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "key": { @@ -448,6 +440,31 @@ func schemaNodeConfig() *schema.Schema { }, }, + "effective_taints": { + Type: schema.TypeList, + Computed: true, + Description: `List of kubernetes taints applied to each node.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": { + Type: schema.TypeString, + Computed: true, + Description: `Key for taint.`, + }, + "value": { + Type: schema.TypeString, + Computed: true, + Description: `Value for taint.`, + }, + "effect": { + Type: schema.TypeString, + Computed: true, + Description: `Effect for taint.`, + }, + }, + }, + }, + "workload_metadata_config": { Computed: true, Type: schema.TypeList, @@ -897,12 +914,13 @@ func expandNodeConfig(v interface{}) *container.NodeConfig { Value: data["value"].(string), Effect: data["effect"].(string), } + nodeTaints = append(nodeTaints, taint) } + nc.Taints = nodeTaints } - if v, ok := nodeConfig["workload_metadata_config"]; ok { nc.WorkloadMetadataConfig = expandWorkloadMetadataConfig(v) } @@ -1081,11 +1099,11 @@ func expandConfidentialNodes(configured interface{}) *container.ConfidentialNode } func flattenNodeConfigDefaults(c *container.NodeConfigDefaults) []map[string]interface{} { - result := make([]map[string]interface{}, 0, 1) + result := make([]map[string]interface{}, 0, 1) - if c == nil { - return result - } + if c == nil { + return result + } result = append(result, map[string]interface{}{}) @@ -1094,16 +1112,27 @@ func flattenNodeConfigDefaults(c *container.NodeConfigDefaults) []map[string]int <% unless version == 'ga' -%> result[0]["gcfs_config"] = flattenGcfsConfig(c.GcfsConfig) <% end -%> - return result + return result } -func flattenNodeConfig(c *container.NodeConfig) []map[string]interface{} { +// v == old state of `node_config` +func flattenNodeConfig(c *container.NodeConfig, v interface{}) []map[string]interface{} { config := make([]map[string]interface{}, 0, 1) if c == nil { return config } + // default to no prior taint state if there are any issues + oldTaints := []interface{}{} + oldNodeConfigSchemaContainer := v.([]interface{}) + if len(oldNodeConfigSchemaContainer) != 0 { + oldNodeConfigSchema := oldNodeConfigSchemaContainer[0].(map[string]interface{}) + if vt, ok := oldNodeConfigSchema["taint"]; ok && len(vt.([]interface{})) > 0 { + oldTaints = vt.([]interface{}) + } + } + config = append(config, map[string]interface{}{ "machine_type": c.MachineType, "disk_size_gb": c.DiskSizeGb, @@ -1123,26 +1152,27 @@ func flattenNodeConfig(c *container.NodeConfig) []map[string]interface{} { "metadata": c.Metadata, "image_type": c.ImageType, "labels": c.Labels, - "resource_labels": c.ResourceLabels, + "resource_labels": c.ResourceLabels, "tags": c.Tags, "preemptible": c.Preemptible, "spot": c.Spot, "min_cpu_platform": c.MinCpuPlatform, "shielded_instance_config": flattenShieldedInstanceConfig(c.ShieldedInstanceConfig), - "taint": flattenTaints(c.Taints), + "taint": flattenTaints(c.Taints, oldTaints), + "effective_taints": flattenEffectiveTaints(c.Taints), "workload_metadata_config": flattenWorkloadMetadataConfig(c.WorkloadMetadataConfig), <% unless version == 'ga' -%> - "sandbox_config": flattenSandboxConfig(c.SandboxConfig), + "sandbox_config": flattenSandboxConfig(c.SandboxConfig), "host_maintenance_policy": flattenHostMaintenancePolicy(c.HostMaintenancePolicy), <% end -%> "confidential_nodes": flattenConfidentialNodes(c.ConfidentialNodes), - "boot_disk_kms_key": c.BootDiskKmsKey, - "kubelet_config": flattenKubeletConfig(c.KubeletConfig), - "linux_node_config": flattenLinuxNodeConfig(c.LinuxNodeConfig), - "node_group": c.NodeGroup, + "boot_disk_kms_key": c.BootDiskKmsKey, + "kubelet_config": flattenKubeletConfig(c.KubeletConfig), + "linux_node_config": flattenLinuxNodeConfig(c.LinuxNodeConfig), + "node_group": c.NodeGroup, "advanced_machine_features": flattenAdvancedMachineFeaturesConfig(c.AdvancedMachineFeatures), - "sole_tenant_config": flattenSoleTenantConfig(c.SoleTenantConfig), - "fast_socket": flattenFastSocket(c.FastSocket), + "sole_tenant_config": flattenSoleTenantConfig(c.SoleTenantConfig), + "fast_socket": flattenFastSocket(c.FastSocket), }) if len(c.OauthScopes) > 0 { @@ -1273,7 +1303,31 @@ func flattenGKEReservationAffinity(c *container.ReservationAffinity) []map[strin return result } -func flattenTaints(c []*container.NodeTaint) []map[string]interface{} { +// flattenTaints records the set of taints already present in state. +func flattenTaints(c []*container.NodeTaint, oldTaints []interface{}) []map[string]interface{} { + taintKeys := map[string]struct{}{} + for _, raw := range oldTaints { + data := raw.(map[string]interface{}) + taintKey := data["key"].(string) + taintKeys[taintKey] = struct{}{} + } + + result := []map[string]interface{}{} + for _, taint := range c { + if _, ok := taintKeys[taint.Key]; ok { + result = append(result, map[string]interface{}{ + "key": taint.Key, + "value": taint.Value, + "effect": taint.Effect, + }) + } + } + + return result +} + +// flattenEffectiveTaints records the complete set of taints returned from GKE. +func flattenEffectiveTaints(c []*container.NodeTaint) []map[string]interface{} { result := []map[string]interface{}{} for _, taint := range c { result = append(result, map[string]interface{}{ @@ -1282,10 +1336,10 @@ func flattenTaints(c []*container.NodeTaint) []map[string]interface{} { "effect": taint.Effect, }) } + return result } - func flattenWorkloadMetadataConfig(c *container.WorkloadMetadataConfig) []map[string]interface{} { result := []map[string]interface{}{} if c != nil { @@ -1352,74 +1406,6 @@ func containerNodePoolLabelsSuppress(k, old, new string, d *schema.ResourceData) return true } - -func containerNodePoolTaintSuppress(k, old, new string, d *schema.ResourceData) bool { - // Node configs are embedded into multiple resources (container cluster and - // container node pool) so we determine the node config key dynamically. - idx := strings.Index(k, ".taint.") - if idx < 0 { - return false - } - - root := k[:idx] - - // Right now, GKE only applies its own out-of-band labels when you enable - // Sandbox. We only need to perform diff suppression in this case; - // otherwise, the default Terraform behavior is fine. - o, n := d.GetChange(root + ".sandbox_config.0.sandbox_type") - if o == nil || n == nil { - return false - } - - // Pull the entire changeset as a list rather than trying to deal with each - // element individually. - o, n = d.GetChange(root + ".taint") - if o == nil || n == nil { - return false - } - - type taintType struct { - Key, Value, Effect string - } - - taintSet := make(map[taintType]struct{}) - - // Add all new taints to set. - for _, raw := range n.([]interface{}) { - data := raw.(map[string]interface{}) - taint := taintType{ - Key: data["key"].(string), - Value: data["value"].(string), - Effect: data["effect"].(string), - } - taintSet[taint] = struct{}{} - } - - // Remove all current taints, skipping GKE-managed keys if not present in - // the new configuration. - for _, raw := range o.([]interface{}) { - data := raw.(map[string]interface{}) - taint := taintType{ - Key: data["key"].(string), - Value: data["value"].(string), - Effect: data["effect"].(string), - } - if _, ok := taintSet[taint]; ok { - delete(taintSet, taint) - } else if !strings.HasPrefix(taint.Key, "sandbox.gke.io/") && taint.Key != "kubernetes.io/arch" { - // User-provided taint removed in new configuration. - return false - } - } - - // If, at this point, the set still has elements, the new configuration - // added an additional taint. - if len(taintSet) > 0 { - return false - } - - return true -} <% end -%> func flattenKubeletConfig(c *container.NodeKubeletConfig) []map[string]interface{} { @@ -1494,4 +1480,4 @@ func flattenHostMaintenancePolicy(c *container.HostMaintenancePolicy) []map[stri return result } -<% end -%> \ No newline at end of file +<% end -%> diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb index a8f50aab16a4..1ed34d7f5b91 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb @@ -2682,7 +2682,7 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro return fmt.Errorf("Error setting default_max_pods_per_node: %s", err) } } - if err := d.Set("node_config", flattenNodeConfig(cluster.NodeConfig)); err != nil { + if err := d.Set("node_config", flattenNodeConfig(cluster.NodeConfig, d.Get("node_config"))); err != nil { return err } if err := d.Set("project", project); err != nil { diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb index 8e0ef285d4b4..c30d5538b362 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb @@ -1235,17 +1235,19 @@ func TestAccContainerCluster_withNodeConfig(t *testing.T) { Config: testAccContainerCluster_withNodeConfig(clusterName), }, { - ResourceName: "google_container_cluster.with_node_config", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_container_cluster.with_node_config", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"node_config.0.taint"}, }, { Config: testAccContainerCluster_withNodeConfigUpdate(clusterName), }, { - ResourceName: "google_container_cluster.with_node_config", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_container_cluster.with_node_config", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"node_config.0.taint"}, }, }, }) @@ -1541,7 +1543,7 @@ func TestAccContainerCluster_withSandboxConfig(t *testing.T) { ResourceName: "google_container_cluster.with_sandbox_config", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "node_config.0.taint"}, }, { // GKE sets automatic labels and taints on nodes. This makes 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 606a39f865d3..06078da73d3b 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 @@ -1112,7 +1112,7 @@ func flattenNodePool(d *schema.ResourceData, config *transport_tpg.Config, np *c "initial_node_count": np.InitialNodeCount, "node_locations": schema.NewSet(schema.HashString, tpgresource.ConvertStringArrToInterface(np.Locations)), "node_count": nodeCount, - "node_config": flattenNodeConfig(np.Config), + "node_config": flattenNodeConfig(np.Config, d.Get(prefix + "node_config")), "instance_group_urls": igmUrls, "managed_instance_group_urls": managedIgmUrls, "version": np.Version, 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 1f902075ec03..893e312951f7 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 @@ -215,7 +215,7 @@ func TestAccContainerNodePool_withNodeConfig(t *testing.T) { ImportStateVerify: true, // autoscaling.# = 0 is equivalent to no autoscaling at all, // but will still cause an import diff - ImportStateVerifyIgnore: []string{"autoscaling.#"}, + ImportStateVerifyIgnore: []string{"autoscaling.#", "node_config.0.taint"}, }, resource.TestStep{ Config: testAccContainerNodePool_withNodeConfigUpdate(cluster, nodePool), @@ -226,7 +226,7 @@ func TestAccContainerNodePool_withNodeConfig(t *testing.T) { ImportStateVerify: true, // autoscaling.# = 0 is equivalent to no autoscaling at all, // but will still cause an import diff - ImportStateVerifyIgnore: []string{"autoscaling.#"}, + ImportStateVerifyIgnore: []string{"autoscaling.#", "node_config.0.taint"}, }, }, }) @@ -361,32 +361,6 @@ func TestAccContainerNodePool_withSandboxConfig(t *testing.T) { ImportState: true, ImportStateVerify: true, }, - { - // GKE sets automatic labels and taints on nodes. This makes - // sure we ignore the automatic ones and keep our own. - Config: testAccContainerNodePool_withSandboxConfig(cluster, np), - // When we use PlanOnly without ExpectNonEmptyPlan, we're - // guaranteeing that the computed fields of the resources don't - // force an unintentional change to the plan. That is, we - // expect this part of the test to pass only if the plan - // doesn't change. - PlanOnly: true, - }, - { - // Now we'll modify the taints, which should force a change to - // the plan. We make sure we don't over-suppress and end up - // eliminating the labels or taints we asked for. This will - // destroy and recreate the node pool as taints are immutable. - Config: testAccContainerNodePool_withSandboxConfig_changeTaints(cluster, np), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("google_container_node_pool.with_sandbox_config", - "node_config.0.labels.test.terraform.io/gke-sandbox", "true"), - resource.TestCheckResourceAttr("google_container_node_pool.with_sandbox_config", - "node_config.0.taint.0.key", "test.terraform.io/gke-sandbox"), - resource.TestCheckResourceAttr("google_container_node_pool.with_sandbox_config", - "node_config.0.taint.1.key", "test.terraform.io/gke-sandbox-amended"), - ), - }, }, }) } @@ -2515,63 +2489,6 @@ resource "google_container_node_pool" "with_sandbox_config" { "test.terraform.io/gke-sandbox" = "true" } - taint { - key = "test.terraform.io/gke-sandbox" - value = "true" - effect = "NO_SCHEDULE" - } - - oauth_scopes = [ - "https://www.googleapis.com/auth/logging.write", - "https://www.googleapis.com/auth/monitoring", - ] - } -} -`, cluster, np) -} - -func testAccContainerNodePool_withSandboxConfig_changeTaints(cluster, np string) string { - return fmt.Sprintf(` -data "google_container_engine_versions" "central1a" { - location = "us-central1-a" -} - -resource "google_container_cluster" "cluster" { - name = "%s" - location = "us-central1-a" - initial_node_count = 1 - min_master_version = data.google_container_engine_versions.central1a.latest_master_version -} - -resource "google_container_node_pool" "with_sandbox_config" { - name = "%s" - location = "us-central1-a" - cluster = google_container_cluster.cluster.name - initial_node_count = 1 - node_config { - machine_type = "n1-standard-1" // can't be e2 because of gvisor - image_type = "COS_CONTAINERD" - - sandbox_config { - sandbox_type = "gvisor" - } - - labels = { - "test.terraform.io/gke-sandbox" = "true" - } - - taint { - key = "test.terraform.io/gke-sandbox" - value = "true" - effect = "NO_SCHEDULE" - } - - taint { - key = "test.terraform.io/gke-sandbox-amended" - value = "also-true" - effect = "NO_SCHEDULE" - } - oauth_scopes = [ "https://www.googleapis.com/auth/logging.write", "https://www.googleapis.com/auth/monitoring", diff --git a/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown b/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown index d29897479d2a..5a1c9688de2b 100644 --- a/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown @@ -888,14 +888,13 @@ gvnic { * `tags` - (Optional) The list of instance tags applied to all nodes. Tags are used to identify valid sources or targets for network firewalls. -* `taint` - (Optional) A list of [Kubernetes taints](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) -to apply to nodes. GKE's API can only set this field on cluster creation. -However, GKE will add taints to your nodes if you enable certain features such -as GPUs. If this field is set, any diffs on this field will cause Terraform to -recreate the underlying resource. Taint values can be updated safely in -Kubernetes (eg. through `kubectl`), and it's recommended that you do not use -this field to manage taints. If you do, `lifecycle.ignore_changes` is -recommended. Structure is [documented below](#nested_taint). +* `taint` - (Optional) A list of +[Kubernetes taints](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) +to apply to nodes. This field will only report drift on taint keys that are +already managed with Terraform, use `effective_taints` to view the list of +GKE-managed taints on the node pool from all sources. Importing this resource +will not record any taints as being Terraform-managed, and will cause drift with +any configured taints. Structure is [documented below](#nested_taint). * `workload_metadata_config` - (Optional) Metadata configuration to expose to workloads on the node pool. Structure is [documented below](#nested_workload_metadata_config). @@ -1310,6 +1309,8 @@ exported: * `cluster_autoscaling.0.auto_provisioning_defaults.0.management.0.upgrade_options` - Specifies the [Auto Upgrade knobs](https://cloud.google.com/kubernetes-engine/docs/reference/rest/v1beta1/NodeManagement#AutoUpgradeOptions) for the node pool. +* `node_config.0.effective_taints` - List of kubernetes taints applied to each node. Structure is [documented above](#nested_taint). + ## Timeouts This resource provides the following From 18480ba1c4d41638ea5aec6cc5fa004fdcbbc5aa Mon Sep 17 00:00:00 2001 From: Nick Elliot Date: Fri, 22 Sep 2023 14:13:17 -0700 Subject: [PATCH 53/67] update google_dataflow_flex_template_job to send sdkpipeline parameters via environment field (#9031) * updated dataflow problem with sdkpipelineresources * removing leftover comments, removing unused diffsuppressfunc that was not implemented in final fix * functionized repeated code * formatting/bugs * extra line * bad var * comments + update test --- ...resource_dataflow_flex_template_job.go.erb | 261 +++++++++++++++--- ...rce_dataflow_flex_template_job_test.go.erb | 6 +- 2 files changed, 234 insertions(+), 33 deletions(-) diff --git a/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job.go.erb b/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job.go.erb index 01632223d44b..ee9b855f3dee 100644 --- a/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job.go.erb +++ b/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job.go.erb @@ -6,13 +6,14 @@ import ( "context" "fmt" "log" + "strconv" "strings" "time" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" - "github.com/hashicorp/terraform-provider-google/google/tpgresource" - transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" "google.golang.org/api/googleapi" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -111,6 +112,7 @@ func ResourceDataflowFlexTemplateJob() *schema.Resource { Optional: true, // ForceNew applies to both stream and batch jobs ForceNew: true, + Computed: true, Description: `The initial number of Google Compute Engine instances for the job.`, }, @@ -119,6 +121,7 @@ func ResourceDataflowFlexTemplateJob() *schema.Resource { Optional: true, // ForceNew applies to both stream and batch jobs ForceNew: true, + Computed: true, Description: `The maximum number of Google Compute Engine instances to be made available to your pipeline during execution, from 1 to 1000.`, }, @@ -146,12 +149,14 @@ func ResourceDataflowFlexTemplateJob() *schema.Resource { "sdk_container_image": { Type: schema.TypeString, Optional: true, + Computed: true, Description: `Docker registry location of container image to use for the 'worker harness. Default is the container for the version of the SDK. Note this field is only valid for portable pipelines.`, }, "network": { Type: schema.TypeString, Optional: true, + Computed: true, DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, Description: `The network to which VMs will be assigned. If it is not provided, "default" will be used.`, }, @@ -159,6 +164,7 @@ func ResourceDataflowFlexTemplateJob() *schema.Resource { "subnetwork": { Type: schema.TypeString, Optional: true, + Computed: true, DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, Description: `The subnetwork to which VMs will be assigned. Should be of the form "regions/REGION/subnetworks/SUBNETWORK".`, }, @@ -166,12 +172,14 @@ func ResourceDataflowFlexTemplateJob() *schema.Resource { "machine_type": { Type: schema.TypeString, Optional: true, + Computed: true, Description: `The machine type to use for the job.`, }, "kms_key_name": { Type: schema.TypeString, Optional: true, + Computed: true, Description: `The name for the Cloud KMS key for the job. Key format is: projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY`, }, @@ -202,12 +210,14 @@ func ResourceDataflowFlexTemplateJob() *schema.Resource { "autoscaling_algorithm": { Type: schema.TypeString, Optional: true, + Computed: true, Description: `The algorithm to use for autoscaling`, }, "launcher_machine_type": { Type: schema.TypeString, Optional: true, + Computed: true, Description: `The machine type to use for launching the job. The default is n1-standard-1.`, }, @@ -225,7 +235,7 @@ func ResourceDataflowFlexTemplateJob() *schema.Resource { // resourceDataflowFlexTemplateJobCreate creates a Flex Template Job from TF code. func resourceDataflowFlexTemplateJobCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) - userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) if err != nil { return err } @@ -240,7 +250,7 @@ func resourceDataflowFlexTemplateJobCreate(d *schema.ResourceData, meta interfac return err } - env, err := resourceDataflowFlexJobSetupEnv(d, config) + env, updatedParameters, err := resourceDataflowFlexJobSetupEnv(d, config) if err != nil { return err } @@ -249,7 +259,7 @@ func resourceDataflowFlexTemplateJobCreate(d *schema.ResourceData, meta interfac LaunchParameter: &dataflow.LaunchFlexTemplateParameter{ ContainerSpecGcsPath: d.Get("container_spec_gcs_path").(string), JobName: d.Get("name").(string), - Parameters: tpgresource.ExpandStringMap(d, "parameters"), + Parameters: updatedParameters, Environment: &env, }, } @@ -275,35 +285,98 @@ func resourceDataflowFlexTemplateJobCreate(d *schema.ResourceData, meta interfac return resourceDataflowFlexTemplateJobRead(d, meta) } -func resourceDataflowFlexJobSetupEnv(d *schema.ResourceData, config *transport_tpg.Config) (dataflow.FlexTemplateRuntimeEnvironment, error) { +func resourceDataflowFlexJobSetupEnv(d *schema.ResourceData, config *transport_tpg.Config) (dataflow.FlexTemplateRuntimeEnvironment, map[string]string, error) { + + updatedParameters := tpgresource.ExpandStringMap(d, "parameters") additionalExperiments := tpgresource.ConvertStringSet(d.Get("additional_experiments").(*schema.Set)) + var autoscalingAlgorithm string + autoscalingAlgorithm, updatedParameters = dataflowFlexJobTypeTransferVar("autoscaling_algorithm", "autoscalingAlgorithm", updatedParameters, d) + + var numWorkers int + if p, ok := d.GetOk("parameters.numWorkers"); ok { + number, err := strconv.Atoi(p.(string)) + if err != nil { + return dataflow.FlexTemplateRuntimeEnvironment{}, updatedParameters, fmt.Errorf("parameters.numWorkers must have a valid integer assigned to it, current value is %s", p.(string)) + } + delete(updatedParameters, "numWorkers") + numWorkers = number + } else { + if v, ok := d.GetOk("num_workers"); ok { + numWorkers = v.(int) + } + } + + var maxNumWorkers int + if p, ok := d.GetOk("parameters.maxNumWorkers"); ok { + number, err := strconv.Atoi(p.(string)) + if err != nil { + return dataflow.FlexTemplateRuntimeEnvironment{}, updatedParameters, fmt.Errorf("parameters.maxNumWorkers must have a valid integer assigned to it, current value is %s", p.(string)) + } + delete(updatedParameters, "maxNumWorkers") + maxNumWorkers = number + } else { + if v, ok := d.GetOk("max_workers"); ok { + maxNumWorkers = v.(int) + } + } + + network, updatedParameters := dataflowFlexJobTypeTransferVar("network", "network", updatedParameters, d) + + serviceAccountEmail, updatedParameters := dataflowFlexJobTypeTransferVar("service_account_email", "serviceAccountEmail", updatedParameters, d) + + subnetwork, updatedParameters := dataflowFlexJobTypeTransferVar("subnetwork", "subnetwork", updatedParameters, d) + + tempLocation, updatedParameters := dataflowFlexJobTypeTransferVar("temp_location", "tempLocation", updatedParameters, d) + + stagingLocation, updatedParameters := dataflowFlexJobTypeTransferVar("staging_location", "stagingLocation", updatedParameters, d) + + machineType, updatedParameters := dataflowFlexJobTypeTransferVar("machine_type", "workerMachineType", updatedParameters, d) + + kmsKeyName, updatedParameters := dataflowFlexJobTypeTransferVar("kms_key_name", "kmsKeyName", updatedParameters, d) + + ipConfiguration, updatedParameters := dataflowFlexJobTypeTransferVar("ip_configuration", "ipConfiguration", updatedParameters, d) + + var enableStreamingEngine bool + if p, ok := d.GetOk("parameters.enableStreamingEngine"); ok { + delete(updatedParameters, "enableStreamingEngine") + enableStreamingEngine = p.(bool) + } else { + if v, ok := d.GetOk("enable_streaming_engine"); ok { + enableStreamingEngine = v.(bool) + } + } + + sdkContainerImage, updatedParameters := dataflowFlexJobTypeTransferVar("sdk_container_image", "sdkContainerImage", updatedParameters, d) + + launcherMachineType, updatedParameters := dataflowFlexJobTypeTransferVar("launcher_machine_type", "launcherMachineType", updatedParameters, d) + env := dataflow.FlexTemplateRuntimeEnvironment{ AdditionalUserLabels: tpgresource.ExpandStringMap(d, "labels"), - AutoscalingAlgorithm: d.Get("autoscaling_algorithm").(string), - NumWorkers: int64(d.Get("num_workers").(int)), - MaxWorkers: int64(d.Get("max_workers").(int)), - Network: d.Get("network").(string), - ServiceAccountEmail: d.Get("service_account_email").(string), - Subnetwork: d.Get("subnetwork").(string), - TempLocation: d.Get("temp_location").(string), - StagingLocation: d.Get("staging_location").(string), - MachineType: d.Get("machine_type").(string), - KmsKeyName: d.Get("kms_key_name").(string), - IpConfiguration: d.Get("ip_configuration").(string), - EnableStreamingEngine: d.Get("enable_streaming_engine").(bool), + AutoscalingAlgorithm: autoscalingAlgorithm, + NumWorkers: int64(numWorkers), + MaxWorkers: int64(maxNumWorkers), + Network: network, + ServiceAccountEmail: serviceAccountEmail, + Subnetwork: subnetwork, + TempLocation: tempLocation, + StagingLocation: stagingLocation, + MachineType: machineType, + KmsKeyName: kmsKeyName, + IpConfiguration: ipConfiguration, + EnableStreamingEngine: enableStreamingEngine, AdditionalExperiments: additionalExperiments, - SdkContainerImage: d.Get("sdk_container_image").(string), - LauncherMachineType: d.Get("launcher_machine_type").(string), + SdkContainerImage: sdkContainerImage, + LauncherMachineType: launcherMachineType, } - return env, nil + return env, updatedParameters, nil } // resourceDataflowFlexTemplateJobRead reads a Flex Template Job resource. func resourceDataflowFlexTemplateJobRead(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) - userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) if err != nil { return err } @@ -365,7 +438,7 @@ func resourceDataflowFlexTemplateJobRead(d *schema.ResourceData, meta interface{ if err := d.Set("num_workers", optionsMap["numWorkers"]); err != nil { return fmt.Errorf("Error setting num_workers: %s", err) } - if err := d.Set("max_workers", optionsMap["maxWorkers"]); err != nil { + if err := d.Set("max_workers", optionsMap["maxNumWorkers"]); err != nil { return fmt.Errorf("Error setting max_workers: %s", err) } if err := d.Set("staging_location", optionsMap["stagingLocation"]); err != nil { @@ -439,7 +512,7 @@ func resourceDataflowFlexTemplateJobUpdate(d *schema.ResourceData, meta interfac } config := meta.(*transport_tpg.Config) - userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) if err != nil { return err } @@ -456,7 +529,7 @@ func resourceDataflowFlexTemplateJobUpdate(d *schema.ResourceData, meta interfac tnamemapping := tpgresource.ExpandStringMap(d, "transform_name_mapping") - env, err := resourceDataflowFlexJobSetupEnv(d, config) + env, updatedParameters, err := resourceDataflowFlexJobSetupEnv(d, config) if err != nil { return err } @@ -470,12 +543,12 @@ func resourceDataflowFlexTemplateJobUpdate(d *schema.ResourceData, meta interfac request := dataflow.LaunchFlexTemplateRequest{ LaunchParameter: &dataflow.LaunchFlexTemplateParameter{ - ContainerSpecGcsPath: d.Get("container_spec_gcs_path").(string), - JobName: d.Get("name").(string), - Parameters: tpgresource.ExpandStringMap(d, "parameters"), + ContainerSpecGcsPath: d.Get("container_spec_gcs_path").(string), + JobName: d.Get("name").(string), + Parameters: updatedParameters, TransformNameMappings: tnamemapping, - Environment: &env, - Update: true, + Environment: &env, + Update: true, }, } @@ -503,7 +576,7 @@ func resourceDataflowFlexTemplateJobUpdate(d *schema.ResourceData, meta interfac func resourceDataflowFlexTemplateJobDelete(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) - userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) if err != nil { return err } @@ -585,6 +658,100 @@ func resourceDataflowFlexTemplateJobDelete(d *schema.ResourceData, meta interfac } func resourceDataflowFlexJobTypeCustomizeDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) error { + + err := dataflowFlexJobTypeParameterOverride("autoscaling_algorithm", "autoscalingAlgorithm", d) + if err != nil { + return err + } + + if p, ok := d.GetOk("parameters.numWorkers"); ok { + if d.HasChange("num_workers") { + e := d.Get("num_workers") + return fmt.Errorf("Error setting num_workers, value is supplied twice: num_workers=%d, parameters.numWorkers=%d", e.(int), p.(int)) + } else { + p := d.Get("parameters.numWorkers") + number, err := strconv.Atoi(p.(string)) + if err != nil { + return fmt.Errorf("parameters.maxNumWorkers must have a valid integer assigned to it, current value is %s", p.(string)) + } + d.SetNew("num_workers", number) + } + } + + if p, ok := d.GetOk("parameters.maxNumWorkers"); ok { + if d.HasChange("max_workers") { + e := d.Get("max_workers") + return fmt.Errorf("Error setting max_workers, value is supplied twice: max_workers=%d, parameters.maxNumWorkers=%d", e.(int), p.(int)) + } else { + p := d.Get("parameters.maxNumWorkers") + number, err := strconv.Atoi(p.(string)) + if err != nil { + return fmt.Errorf("parameters.maxNumWorkers must have a valid integer assigned to it, current value is %s", p.(string)) + } + d.SetNew("max_workers", number) + } + } + + err = dataflowFlexJobTypeParameterOverride("network", "network", d) + if err != nil { + return err + } + + err = dataflowFlexJobTypeParameterOverride("service_account_email", "serviceAccountEmail", d) + if err != nil { + return err + } + + err = dataflowFlexJobTypeParameterOverride("subnetwork", "subnetwork", d) + if err != nil { + return err + } + + err = dataflowFlexJobTypeParameterOverride("temp_location", "tempLocation", d) + if err != nil { + return err + } + + err = dataflowFlexJobTypeParameterOverride("staging_location", "stagingLocation", d) + if err != nil { + return err + } + + err = dataflowFlexJobTypeParameterOverride("machine_type", "workerMachineType", d) + if err != nil { + return err + } + + err = dataflowFlexJobTypeParameterOverride("kms_key_name", "kmsKeyName", d) + if err != nil { + return err + } + + err = dataflowFlexJobTypeParameterOverride("ip_configuration", "ipConfiguration", d) + if err != nil { + return err + } + + if p, ok := d.GetOk("parameters.enableStreamingEngine"); ok { + if d.HasChange("enable_streaming_engine") { + e := d.Get("enable_streaming_engine") + return fmt.Errorf("Error setting enable_streaming_engine, value is supplied twice: enable_streaming_engine=%t, parameters.enableStreamingEngine=%t", e.(bool), p.(bool)) + } else { + p := d.Get("parameters.enableStreamingEngine") + d.SetNew("enable_streaming_engine", p.(string)) + } + } + + err = dataflowFlexJobTypeParameterOverride("sdk_container_image", "sdkContainerImage", d) + if err != nil { + return err + } + + err = dataflowFlexJobTypeParameterOverride("launcher_machine_type", "launcherMachineType", d) + if err != nil { + return err + } + // All non-virtual fields are ForceNew for batch jobs if d.Get("type") == "JOB_TYPE_BATCH" { resourceSchema := ResourceDataflowFlexTemplateJob().Schema @@ -608,4 +775,36 @@ func resourceDataflowFlexJobTypeCustomizeDiff(_ context.Context, d *schema.Resou return nil } +func dataflowFlexJobTypeTransferVar(ename, pname string, updatedParameters map[string]string, d *schema.ResourceData) (string, map[string]string) { + + pstring := fmt.Sprintf("parameters.%s", pname) + + if p, ok := d.GetOk(pstring); ok { + delete(updatedParameters, pname) + return p.(string), updatedParameters + } else { + if v, ok := d.GetOk(ename); ok { + return v.(string), updatedParameters + } else { + return "", updatedParameters + } + } +} + +func dataflowFlexJobTypeParameterOverride(ename, pname string, d *schema.ResourceDiff) error { + + pstring := fmt.Sprintf("parameters.%s", pname) + + if p, ok := d.GetOk(pstring); ok { + if d.HasChange(ename) { + e := d.Get(ename) + return fmt.Errorf("Error setting %s, value is supplied twice: %s=\"%s\", %s=\"%s\"", ename, ename, e.(string), pstring, p.(string)) + } else { + p := d.Get(pstring) + d.SetNew(ename, p.(string)) + } + } + return nil +} + <% end -%> diff --git a/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job_test.go.erb b/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job_test.go.erb index 577ec7f63de8..cfeb2af3cbed 100644 --- a/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job_test.go.erb +++ b/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job_test.go.erb @@ -635,12 +635,13 @@ resource "google_dataflow_flex_template_job" "flex_job_fullupdate" { schemaLocation = "gs://${google_storage_bucket_object.schema.bucket}/schema.json" qps = "1" topic = google_pubsub_topic.example.id + workerMachineType = "n1-standard-2" + maxNumWorkers = 2 } labels = { "my_labels" = "value-1" } service_account_email = google_service_account.dataflow-sa[0].email - machine_type = "n1-standard-2" } `, topicName, bucket, job) } @@ -705,16 +706,17 @@ resource "google_dataflow_flex_template_job" "flex_job_fullupdate" { name = "%s" container_spec_gcs_path = "gs://${data.google_storage_bucket_object.flex_template.bucket}/${data.google_storage_bucket_object.flex_template.name}" on_delete = "cancel" + machine_type = "n2-standard-2" parameters = { schemaLocation = "gs://${google_storage_bucket_object.schema.bucket}/schema.json" qps = "1" topic = google_pubsub_topic.example.id + maxNumWorkers = 3 } labels = { "my_labels" = "value-update" } service_account_email = google_service_account.dataflow-sa[1].email - machine_type = "n2-standard-2" } `, topicName, bucket, job) } From 99bfccd3de006fed214a61a6ea00415a26746f39 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Sat, 23 Sep 2023 02:20:22 +0100 Subject: [PATCH 54/67] Add validation to provider fields in both SDK and PF implementations of provider schema (#9050) * Add empty-string validator for PF provider * Add empty-string validator for SDK provider, move SDK validators to separate file * Add empty string validators to : credentials, access_token, impersonate_service_account, project, billing_project, region, zone * Add unit tests for `ValidateEmptyStrings` * Remove empty string test case from `ValidateCredentials` * Add acceptace tests showing that empty strings in provider block results in a validation error, and empty provider blocks have no validation errors * Make the SDK provider's `ValidateCredentials` validator reject empty strings * Update acceptance test after change in `credentials` validation * Fix test definitions to avoid fall-through * Update validation error message in code and tests --- .../fwprovider/framework_provider.go.erb | 17 ++++ .../fwprovider/framework_validators.go | 31 +++++++ .../terraform/provider/provider.go.erb | 57 +++++-------- .../provider/provider_internal_test.go | 65 +++++++++++++-- .../terraform/provider/provider_test.go.erb | 82 +++++++++++++++++++ .../provider/provider_validators.go.erb | 48 +++++++++++ 6 files changed, 257 insertions(+), 43 deletions(-) create mode 100644 mmv1/third_party/terraform/provider/provider_validators.go.erb diff --git a/mmv1/third_party/terraform/fwprovider/framework_provider.go.erb b/mmv1/third_party/terraform/fwprovider/framework_provider.go.erb index c749a011c13b..dffa3d43f30f 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_provider.go.erb +++ b/mmv1/third_party/terraform/fwprovider/framework_provider.go.erb @@ -71,6 +71,7 @@ func (p *FrameworkProvider) Schema(_ context.Context, _ provider.SchemaRequest, path.MatchRoot("access_token"), }...), CredentialsValidator(), + NonEmptyStringValidator(), }, }, "access_token": schema.StringAttribute{ @@ -79,10 +80,14 @@ func (p *FrameworkProvider) Schema(_ context.Context, _ provider.SchemaRequest, stringvalidator.ConflictsWith(path.Expressions{ path.MatchRoot("credentials"), }...), + NonEmptyStringValidator(), }, }, "impersonate_service_account": schema.StringAttribute{ Optional: true, + Validators: []validator.String{ + NonEmptyStringValidator(), + }, }, "impersonate_service_account_delegates": schema.ListAttribute{ Optional: true, @@ -90,15 +95,27 @@ func (p *FrameworkProvider) Schema(_ context.Context, _ provider.SchemaRequest, }, "project": schema.StringAttribute{ Optional: true, + Validators: []validator.String{ + NonEmptyStringValidator(), + }, }, "billing_project": schema.StringAttribute{ Optional: true, + Validators: []validator.String{ + NonEmptyStringValidator(), + }, }, "region": schema.StringAttribute{ Optional: true, + Validators: []validator.String{ + NonEmptyStringValidator(), + }, }, "zone": schema.StringAttribute{ Optional: true, + Validators: []validator.String{ + NonEmptyStringValidator(), + }, }, "scopes": schema.ListAttribute{ Optional: true, diff --git a/mmv1/third_party/terraform/fwprovider/framework_validators.go b/mmv1/third_party/terraform/fwprovider/framework_validators.go index 3a0af4733d92..3af98fd9db92 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_validators.go +++ b/mmv1/third_party/terraform/fwprovider/framework_validators.go @@ -84,3 +84,34 @@ func (v nonnegativedurationValidator) ValidateString(ctx context.Context, reques func NonNegativeDurationValidator() validator.String { return nonnegativedurationValidator{} } + +// Non Empty String Validator +type nonEmptyStringValidator struct { +} + +// Description describes the validation in plain text formatting. +func (v nonEmptyStringValidator) Description(_ context.Context) string { + return "value expected to be a string that isn't an empty string" +} + +// MarkdownDescription describes the validation in Markdown formatting. +func (v nonEmptyStringValidator) MarkdownDescription(ctx context.Context) string { + return v.Description(ctx) +} + +// ValidateString performs the validation. +func (v nonEmptyStringValidator) ValidateString(ctx context.Context, request validator.StringRequest, response *validator.StringResponse) { + if request.ConfigValue.IsNull() || request.ConfigValue.IsUnknown() { + return + } + + value := request.ConfigValue.ValueString() + + if value == "" { + response.Diagnostics.AddError("expected a non-empty string", fmt.Sprintf("%s was set to `%s`", request.Path, value)) + } +} + +func NonEmptyStringValidator() validator.String { + return nonEmptyStringValidator{} +} diff --git a/mmv1/third_party/terraform/provider/provider.go.erb b/mmv1/third_party/terraform/provider/provider.go.erb index 530ef450cb61..c8eb25e8b554 100644 --- a/mmv1/third_party/terraform/provider/provider.go.erb +++ b/mmv1/third_party/terraform/provider/provider.go.erb @@ -39,8 +39,6 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgiamresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" "github.com/hashicorp/terraform-provider-google/google/verify" - - googleoauth "golang.org/x/oauth2/google" ) // Provider returns a *schema.Provider. @@ -60,21 +58,23 @@ func Provider() *schema.Provider { provider := &schema.Provider{ Schema: map[string]*schema.Schema{ "credentials": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: ValidateCredentials, + Type: schema.TypeString, + Optional: true, + ValidateFunc: ValidateCredentials, ConflictsWith: []string{"access_token"}, }, "access_token": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: ValidateEmptyStrings, ConflictsWith: []string{"credentials"}, }, "impersonate_service_account": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: ValidateEmptyStrings, }, "impersonate_service_account_delegates": { @@ -84,23 +84,27 @@ func Provider() *schema.Provider { }, "project": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: ValidateEmptyStrings, }, "billing_project": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: ValidateEmptyStrings, }, "region": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: ValidateEmptyStrings, }, "zone": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: ValidateEmptyStrings, }, "scopes": { @@ -771,25 +775,6 @@ func ProviderConfigure(ctx context.Context, d *schema.ResourceData, p *schema.Pr return transport_tpg.ProviderDCLConfigure(d, &config), nil } -func ValidateCredentials(v interface{}, k string) (warnings []string, errors []error) { - if v == nil || v.(string) == "" { - return - } - // NOTE: Above we have to allow empty string as valid because we don't know if it's a zero value or not - - creds := v.(string) - // if this is a path and we can stat it, assume it's ok - if _, err := os.Stat(creds); err == nil { - return - } - if _, err := googleoauth.CredentialsFromJSON(context.Background(), []byte(creds)); err != nil { - errors = append(errors, - fmt.Errorf("JSON credentials are not valid: %s", err)) - } - - return -} - func mergeResourceMaps(ms ...map[string]*schema.Resource) (map[string]*schema.Resource, error) { merged := make(map[string]*schema.Resource) duplicates := []string{} diff --git a/mmv1/third_party/terraform/provider/provider_internal_test.go b/mmv1/third_party/terraform/provider/provider_internal_test.go index 00bcac3d5926..5bf88ff03983 100644 --- a/mmv1/third_party/terraform/provider/provider_internal_test.go +++ b/mmv1/third_party/terraform/provider/provider_internal_test.go @@ -42,12 +42,13 @@ func TestProvider_ValidateCredentials(t *testing.T) { return string(contents) }, }, - // There's a risk of changing the validator to saying "" is invalid, as it may mean that - // everyone not using the credentials field would get validation errors. - "configuring credentials as an empty string is not identified as invalid by the function, as it can't distinguish from zero values ": { + "configuring credentials as an empty string is not valid": { ConfigValue: func(t *testing.T) interface{} { return "" }, + ExpectedErrors: []error{ + errors.New("expected a non-empty string"), + }, }, "leaving credentials unconfigured is valid": { ValueNotProvided: true, @@ -69,15 +70,65 @@ func TestProvider_ValidateCredentials(t *testing.T) { // Assert if len(ws) != len(tc.ExpectedWarnings) { - t.Errorf("Expected %d warnings, got %d: %v", len(tc.ExpectedWarnings), len(ws), ws) + t.Fatalf("Expected %d warnings, got %d: %v", len(tc.ExpectedWarnings), len(ws), ws) + } + if len(es) != len(tc.ExpectedErrors) { + t.Fatalf("Expected %d errors, got %d: %v", len(tc.ExpectedErrors), len(es), es) + } + + if len(tc.ExpectedErrors) > 0 && len(es) > 0 { + if es[0].Error() != tc.ExpectedErrors[0].Error() { + t.Fatalf("Expected first error to be \"%s\", got \"%s\"", tc.ExpectedErrors[0], es[0]) + } + } + }) + } +} + +func TestProvider_ValidateEmptyStrings(t *testing.T) { + cases := map[string]struct { + ConfigValue interface{} + ValueNotProvided bool + ExpectedWarnings []string + ExpectedErrors []error + }{ + "non-empty strings are valid": { + ConfigValue: "foobar", + }, + "unconfigured values are valid": { + ValueNotProvided: true, + }, + "empty strings are not valid": { + ConfigValue: "", + ExpectedErrors: []error{ + errors.New("expected a non-empty string"), + }, + }, + } + for tn, tc := range cases { + t.Run(tn, func(t *testing.T) { + + // Arrange + var configValue interface{} + if !tc.ValueNotProvided { + configValue = tc.ConfigValue + } + + // Act + // Note: second argument is currently unused by the function but is necessary to fulfill the SchemaValidateFunc type's function signature + ws, es := provider.ValidateEmptyStrings(configValue, "") + + // Assert + if len(ws) != len(tc.ExpectedWarnings) { + t.Fatalf("Expected %d warnings, got %d: %v", len(tc.ExpectedWarnings), len(ws), ws) } if len(es) != len(tc.ExpectedErrors) { - t.Errorf("Expected %d errors, got %d: %v", len(tc.ExpectedErrors), len(es), es) + t.Fatalf("Expected %d errors, got %d: %v", len(tc.ExpectedErrors), len(es), es) } - if len(tc.ExpectedErrors) > 0 { + if len(tc.ExpectedErrors) > 0 && len(es) > 0 { if es[0].Error() != tc.ExpectedErrors[0].Error() { - t.Errorf("Expected first error to be \"%s\", got \"%s\"", tc.ExpectedErrors[0], es[0]) + t.Fatalf("Expected first error to be \"%s\", got \"%s\"", tc.ExpectedErrors[0], es[0]) } } }) diff --git a/mmv1/third_party/terraform/provider/provider_test.go.erb b/mmv1/third_party/terraform/provider/provider_test.go.erb index ad0744de45ca..83186a25949e 100644 --- a/mmv1/third_party/terraform/provider/provider_test.go.erb +++ b/mmv1/third_party/terraform/provider/provider_test.go.erb @@ -294,6 +294,75 @@ func TestAccProviderCredentialsUnknownValue(t *testing.T) { }) } +func TestAccProviderEmptyStrings(t *testing.T) { + t.Parallel() + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + // No TestDestroy since that's not really the point of this test + Steps: []resource.TestStep{ + // When no values are set in the provider block there are no errors + // This test case is a control to show validation doesn't accidentally flag unset fields + // The "" argument is a lack of key = value being passed into the provider block + { + Config: testAccProvider_checkPlanTimeErrors("", acctest.RandString(t, 10)), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + // credentials as an empty string causes a validation error + { + Config: testAccProvider_checkPlanTimeErrors(`credentials = ""`, acctest.RandString(t, 10)), + PlanOnly: true, + ExpectNonEmptyPlan: true, + ExpectError: regexp.MustCompile(`expected a non-empty string`), + }, + // access_token as an empty string causes a validation error + { + Config: testAccProvider_checkPlanTimeErrors(`access_token = ""`, acctest.RandString(t, 10)), + PlanOnly: true, + ExpectNonEmptyPlan: true, + ExpectError: regexp.MustCompile(`expected a non-empty string`), + }, + // impersonate_service_account as an empty string causes a validation error + { + Config: testAccProvider_checkPlanTimeErrors(`impersonate_service_account = ""`, acctest.RandString(t, 10)), + PlanOnly: true, + ExpectNonEmptyPlan: true, + ExpectError: regexp.MustCompile(`expected a non-empty string`), + }, + // project as an empty string causes a validation error + { + Config: testAccProvider_checkPlanTimeErrors(`project = ""`, acctest.RandString(t, 10)), + PlanOnly: true, + ExpectNonEmptyPlan: true, + ExpectError: regexp.MustCompile(`expected a non-empty string`), + }, + // billing_project as an empty string causes a validation error + { + Config: testAccProvider_checkPlanTimeErrors(`billing_project = ""`, acctest.RandString(t, 10)), + PlanOnly: true, + ExpectNonEmptyPlan: true, + ExpectError: regexp.MustCompile(`expected a non-empty string`), + }, + // region as an empty string causes a validation error + { + Config: testAccProvider_checkPlanTimeErrors(`region = ""`, acctest.RandString(t, 10)), + PlanOnly: true, + ExpectNonEmptyPlan: true, + ExpectError: regexp.MustCompile(`expected a non-empty string`), + }, + // zone as an empty string causes a validation error + { + Config: testAccProvider_checkPlanTimeErrors(`zone = ""`, acctest.RandString(t, 10)), + PlanOnly: true, + ExpectNonEmptyPlan: true, + ExpectError: regexp.MustCompile(`expected a non-empty string`), + }, + }, + }) +} + func testAccProviderBasePath_setBasePath(endpoint, name string) string { return fmt.Sprintf(` provider "google" { @@ -541,3 +610,16 @@ resource "google_firebase_project" "this" { ] }`, credentials, pid, pid, pid, org, billing) } + +func testAccProvider_checkPlanTimeErrors(providerArgument, randString string) string { + return fmt.Sprintf(` +provider "google" { + %s +} + +# A random resource so that the test can generate a plan (can't check validation errors when plan is empty) +resource "google_pubsub_topic" "example" { + name = "tf-test-planned-resource-%s" +} +`, providerArgument, randString) +} diff --git a/mmv1/third_party/terraform/provider/provider_validators.go.erb b/mmv1/third_party/terraform/provider/provider_validators.go.erb new file mode 100644 index 000000000000..25b7825f0703 --- /dev/null +++ b/mmv1/third_party/terraform/provider/provider_validators.go.erb @@ -0,0 +1,48 @@ +<% autogen_exception -%> +package provider + +import ( + "context" + "fmt" + "os" + + googleoauth "golang.org/x/oauth2/google" +) + +func ValidateCredentials(v interface{}, k string) (warnings []string, errors []error) { + if v == nil { + return + } + creds := v.(string) + + // reject empty strings + if v.(string) == "" { + errors = append(errors, + fmt.Errorf("expected a non-empty string")) + return + } + + // if this is a path and we can stat it, assume it's ok + if _, err := os.Stat(creds); err == nil { + return + } + if _, err := googleoauth.CredentialsFromJSON(context.Background(), []byte(creds)); err != nil { + errors = append(errors, + fmt.Errorf("JSON credentials are not valid: %s", err)) + } + + return +} + +func ValidateEmptyStrings(v interface{}, k string) (warnings []string, errors []error) { + if v == nil { + return + } + + if v.(string) == "" { + errors = append(errors, + fmt.Errorf("expected a non-empty string")) + } + + return +} \ No newline at end of file From ca2f0da4fc1a90dc62a3b64c45de8d269e098800 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Fri, 22 Sep 2023 18:27:41 -0700 Subject: [PATCH 55/67] Labels state upgrader (#8996) * Add state upgrader to migrate some resources with labels * Address Comments * Move DSF to state migration files --- mmv1/api/resource.rb | 5 + mmv1/products/cloudrun/DomainMapping.yaml | 15 +- mmv1/products/cloudrun/Service.yaml | 12 +- mmv1/products/notebooks/Instance.yaml | 7 +- .../constants/cloud_run_domain_mapping.go.erb | 24 +- .../constants/cloud_run_service.go.erb | 38 - .../terraform/constants/notebooks_instance.go | 16 - mmv1/templates/terraform/resource.erb | 2 +- .../cloud_run_domain_mapping.go.erb | 276 +++++ .../state_migrations/cloud_run_service.go.erb | 1099 +++++++++++++++++ .../notebooks_instance.go.erb | 407 ++++++ .../resource_cloud_run_domain_mapping_test.go | 4 +- .../resource_cloud_run_service_test.go.erb | 346 +++++- ...resource_dataflow_flex_template_job.go.erb | 45 +- ..._dataflow_flex_template_job_migrate.go.erb | 205 +++ ...rce_dataflow_flex_template_job_test.go.erb | 356 +++++- .../dataflow/resource_dataflow_job.go.erb | 54 +- .../dataflow/resource_dataflow_job_migrate.go | 180 +++ .../resource_dataflow_job_test.go.erb | 222 +++- ...er.go.erb => resource_dataproc_cluster.go} | 137 +- .../resource_dataproc_cluster_migrate.go | 981 +++++++++++++++ .../resource_dataproc_cluster_test.go.erb | 58 +- .../resource_dataproc_cluster_upgrade_test.go | 212 ++++ .../resource_notebooks_instance_test.go.erb | 4 +- .../storage/resource_storage_bucket.go.erb | 46 +- .../resource_storage_bucket_migrate.go | 415 +++++++ .../resource_storage_bucket_test.go.erb | 6 +- .../terraform/tpgresource/labels.go | 33 + .../dataflow_flex_template_job.html.markdown | 10 +- .../website/docs/r/dataflow_job.html.markdown | 7 +- .../docs/r/dataproc_cluster.html.markdown | 9 +- .../example_cloud_run_service.tfplan.json | 7 + 32 files changed, 5017 insertions(+), 221 deletions(-) delete mode 100644 mmv1/templates/terraform/constants/notebooks_instance.go create mode 100644 mmv1/templates/terraform/state_migrations/cloud_run_domain_mapping.go.erb create mode 100644 mmv1/templates/terraform/state_migrations/cloud_run_service.go.erb create mode 100644 mmv1/templates/terraform/state_migrations/notebooks_instance.go.erb create mode 100644 mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job_migrate.go.erb create mode 100644 mmv1/third_party/terraform/services/dataflow/resource_dataflow_job_migrate.go rename mmv1/third_party/terraform/services/dataproc/{resource_dataproc_cluster.go.erb => resource_dataproc_cluster.go} (96%) create mode 100644 mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_migrate.go create mode 100644 mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_upgrade_test.go create mode 100644 mmv1/third_party/terraform/services/storage/resource_storage_bucket_migrate.go diff --git a/mmv1/api/resource.rb b/mmv1/api/resource.rb index cf4f9d45542b..71c16a4200ac 100644 --- a/mmv1/api/resource.rb +++ b/mmv1/api/resource.rb @@ -201,6 +201,10 @@ module Properties # mmv1/templates/terraform/state_migrations/ # used for maintaining state stability with resources first provisioned on older api versions. attr_reader :schema_version + # From this schema version on, state_upgrader code is generated for the resource. + # When unset, state_upgrade_base_schema_version defauts to 0. + # Normally, it is not needed to be set. + attr_reader :state_upgrade_base_schema_version attr_reader :state_upgraders # This block inserts the named function and its attribute into the # resource schema -- the code for the migrate_state function must @@ -322,6 +326,7 @@ def validate check :error_retry_predicates, type: Array, item_type: String check :error_abort_predicates, type: Array, item_type: String check :schema_version, type: Integer + check :state_upgrade_base_schema_version, type: Integer, default: 0 check :state_upgraders, type: :boolean, default: false check :migrate_state, type: String check :skip_delete, type: :boolean, default: false diff --git a/mmv1/products/cloudrun/DomainMapping.yaml b/mmv1/products/cloudrun/DomainMapping.yaml index 7f8266c3acf7..82aa8c386dd3 100644 --- a/mmv1/products/cloudrun/DomainMapping.yaml +++ b/mmv1/products/cloudrun/DomainMapping.yaml @@ -42,6 +42,11 @@ custom_code: !ruby/object:Provider::Terraform::CustomCode encoder: 'templates/terraform/encoders/cloud_run_domain_mapping.go.erb' decoder: 'templates/terraform/decoders/cloud_run.go.erb' constants: templates/terraform/constants/cloud_run_domain_mapping.go.erb +custom_diff: [ + 'hasMetadata', +] +state_upgraders: true +schema_version: 1 parameters: - !ruby/object:Api::Type::String name: location @@ -154,18 +159,16 @@ properties: default_value: :AUTOMATIC - !ruby/object:Api::Type::NestedObject name: metadata - required: true + default_from_api: true description: Metadata associated with this DomainMapping. properties: - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: |- Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and routes. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels - default_from_api: true - diff_suppress_func: 'DomainMappingLabelDiffSuppress' - !ruby/object:Api::Type::Integer name: generation description: |- @@ -203,7 +206,7 @@ properties: In Cloud Run the namespace must be equal to either the project ID or project number. custom_flatten: templates/terraform/custom_flatten/set_to_project.go.erb - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueAnnotations name: 'annotations' description: |- Annotations is a key value map stored with a resource that @@ -213,5 +216,3 @@ properties: **Note**: The Cloud Run API may add additional annotations that were not provided in your config. If terraform plan shows a diff where a server-side annotation is added, you can add it to your config or apply the lifecycle.ignore_changes rule to the metadata.0.annotations field. - default_from_api: true - diff_suppress_func: 'cloudrunAnnotationDiffSuppress' diff --git a/mmv1/products/cloudrun/Service.yaml b/mmv1/products/cloudrun/Service.yaml index d234a11ca494..99dd210064f2 100644 --- a/mmv1/products/cloudrun/Service.yaml +++ b/mmv1/products/cloudrun/Service.yaml @@ -152,7 +152,9 @@ custom_code: !ruby/object:Provider::Terraform::CustomCode custom_diff: [ 'revisionNameCustomizeDiff', ] -schema_version: 1 +state_upgraders: true +state_upgrade_base_schema_version: 1 +schema_version: 2 parameters: - !ruby/object:Api::Type::String name: location @@ -970,14 +972,12 @@ properties: and annotations. default_from_api: true properties: - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: |- Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and routes. - default_from_api: true - diff_suppress_func: 'cloudrunLabelDiffSuppress' - !ruby/object:Api::Type::Integer name: generation description: |- @@ -1012,7 +1012,7 @@ properties: default_from_api: true custom_flatten: templates/terraform/custom_flatten/set_to_project.go.erb custom_expand: 'templates/terraform/custom_expand/default_to_project.go.erb' - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueAnnotations name: 'annotations' description: |- Annotations is a key value map stored with a resource that @@ -1036,5 +1036,3 @@ properties: for the Service. For example, `"run.googleapis.com/ingress" = "all"`. - `run.googleapis.com/launch-stage` sets the [launch stage](https://cloud.google.com/run/docs/troubleshooting#launch-stage-validation) when a preview feature is used. For example, `"run.googleapis.com/launch-stage": "BETA"` - default_from_api: true - diff_suppress_func: 'cloudrunAnnotationDiffSuppress' diff --git a/mmv1/products/notebooks/Instance.yaml b/mmv1/products/notebooks/Instance.yaml index 6986b560e77e..c6fc8de89d4c 100644 --- a/mmv1/products/notebooks/Instance.yaml +++ b/mmv1/products/notebooks/Instance.yaml @@ -80,8 +80,9 @@ examples: test_env_vars: service_account: :SERVICE_ACCT custom_code: !ruby/object:Provider::Terraform::CustomCode - constants: templates/terraform/constants/notebooks_instance.go update_encoder: templates/terraform/update_encoder/notebooks_instance.go +state_upgraders: true +schema_version: 1 parameters: - !ruby/object:Api::Type::ResourceRef name: 'location' @@ -344,15 +345,13 @@ properties: Format: projects/{project_id}/regions/{region}/subnetworks/{subnetwork_id} diff_suppress_func: tpgresource.CompareSelfLinkOrResourceName default_from_api: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels to apply to this instance. These can be later modified by the setLabels method. An object containing a list of "key": value pairs. Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }. update_verb: :PATCH update_url: 'projects/{{project}}/locations/{{location}}/instances/{{name}}:setLabels' - default_from_api: true - diff_suppress_func: NotebooksInstanceLabelDiffSuppress - !ruby/object:Api::Type::Array name: 'tags' description: | diff --git a/mmv1/templates/terraform/constants/cloud_run_domain_mapping.go.erb b/mmv1/templates/terraform/constants/cloud_run_domain_mapping.go.erb index 7ae3d75f1a55..eacab2177f96 100644 --- a/mmv1/templates/terraform/constants/cloud_run_domain_mapping.go.erb +++ b/mmv1/templates/terraform/constants/cloud_run_domain_mapping.go.erb @@ -1,21 +1,9 @@ -var domainMappingGoogleProvidedLabels = []string{ - "cloud.googleapis.com/location", - "run.googleapis.com/overrideAt", -} +func hasMetadata(_ context.Context, diff *schema.ResourceDiff, meta interface{}) error { + newCount := diff.Get("metadata.#") -func DomainMappingLabelDiffSuppress(k, old, new string, d *schema.ResourceData) bool { - // Suppress diffs for the labels provided by Google - for _, label := range domainMappingGoogleProvidedLabels { - if strings.Contains(k, label) && new == "" { - return true - } + if newCount.(int) < 1 { + return fmt.Errorf("Insufficient \"metadata\" blocks. 1 \"metadata\" block is required.") } - // Let diff be determined by labels (above) - if strings.Contains(k, "labels.%") { - return true - } - - // For other keys, don't suppress diff. - return false -} + return nil +} \ No newline at end of file diff --git a/mmv1/templates/terraform/constants/cloud_run_service.go.erb b/mmv1/templates/terraform/constants/cloud_run_service.go.erb index eb4bd8e2c22b..0b748a4b3ba6 100644 --- a/mmv1/templates/terraform/constants/cloud_run_service.go.erb +++ b/mmv1/templates/terraform/constants/cloud_run_service.go.erb @@ -7,27 +7,6 @@ func revisionNameCustomizeDiff(_ context.Context, diff *schema.ResourceDiff, v i return nil } -var cloudRunGoogleProvidedAnnotations = regexp.MustCompile(`serving\.knative\.dev/(?:(?:creator)|(?:lastModifier))$|run\.googleapis\.com/(?:(?:ingress-status)|(?:operation-id))$|cloud\.googleapis\.com/(?:(?:location))`) - -func cloudrunAnnotationDiffSuppress(k, old, new string, d *schema.ResourceData) bool { - // Suppress diffs for the annotations provided by Google - if cloudRunGoogleProvidedAnnotations.MatchString(k) && new == "" { - return true - } - - if strings.HasSuffix(k, "run.googleapis.com/ingress") { - return old == "all" && new == "" - } - - // Let diff be determined by annotations (above) - if strings.Contains(k, "annotations.%") { - return true - } - - // For other keys, don't suppress diff. - return false -} - var cloudRunGoogleProvidedTemplateAnnotations = regexp.MustCompile(`template\.0\.metadata\.0\.annotations\.run\.googleapis\.com/sandbox`) var cloudRunGoogleProvidedTemplateAnnotations_autoscaling_maxscale = regexp.MustCompile(`template\.0\.metadata\.0\.annotations\.autoscaling\.knative\.dev/maxScale`) @@ -46,23 +25,6 @@ func cloudrunTemplateAnnotationDiffSuppress(k, old, new string, d *schema.Resour return false } -var cloudRunGoogleProvidedLabels = regexp.MustCompile(`cloud\.googleapis\.com/(?:(?:location))`) - -func cloudrunLabelDiffSuppress(k, old, new string, d *schema.ResourceData) bool { - // Suppress diffs for the labels provided by Google - if cloudRunGoogleProvidedLabels.MatchString(k) && new == "" { - return true - } - - // Let diff be determined by labels (above) - if strings.Contains(k, "labels.%") { - return true - } - - // For other keys, don't suppress diff. - return false -} - var cloudRunGoogleProvidedTemplateLabels = []string{ "run.googleapis.com/startupProbeType", } diff --git a/mmv1/templates/terraform/constants/notebooks_instance.go b/mmv1/templates/terraform/constants/notebooks_instance.go deleted file mode 100644 index 11fc19272311..000000000000 --- a/mmv1/templates/terraform/constants/notebooks_instance.go +++ /dev/null @@ -1,16 +0,0 @@ -const notebooksInstanceGoogleProvidedLabel = "goog-caip-notebook" - -func NotebooksInstanceLabelDiffSuppress(k, old, new string, d *schema.ResourceData) bool { - // Suppress diffs for the label provided by Google - if strings.Contains(k, notebooksInstanceGoogleProvidedLabel) && new == "" { - return true - } - - // Let diff be determined by labels (above) - if strings.Contains(k, "labels.%") { - return true - } - - // For other keys, don't suppress diff. - return false -} diff --git a/mmv1/templates/terraform/resource.erb b/mmv1/templates/terraform/resource.erb index f24f763b02f3..67ec3ed00150 100644 --- a/mmv1/templates/terraform/resource.erb +++ b/mmv1/templates/terraform/resource.erb @@ -105,7 +105,7 @@ func Resource<%= resource_name -%>() *schema.Resource { <% if object.state_upgraders -%> StateUpgraders: []schema.StateUpgrader{ -<% for v in 0..object.schema_version-1 -%> +<% for v in object.state_upgrade_base_schema_version..object.schema_version-1 -%> { Type: resource<%= "#{resource_name}ResourceV#{v}" -%>().CoreConfigSchema().ImpliedType(), Upgrade: Resource<%= "#{resource_name}UpgradeV#{v}" -%>, diff --git a/mmv1/templates/terraform/state_migrations/cloud_run_domain_mapping.go.erb b/mmv1/templates/terraform/state_migrations/cloud_run_domain_mapping.go.erb new file mode 100644 index 000000000000..865a0a95c905 --- /dev/null +++ b/mmv1/templates/terraform/state_migrations/cloud_run_domain_mapping.go.erb @@ -0,0 +1,276 @@ +var domainMappingGoogleProvidedLocationLabel = "cloud.googleapis.com/location" +var domainMappingGoogleProvidedOverrideLabel = "run.googleapis.com/overrideAt" + +var domainMappingGoogleProvidedLabels = []string{ + domainMappingGoogleProvidedLocationLabel, + domainMappingGoogleProvidedOverrideLabel, +} + +func DomainMappingLabelDiffSuppress(k, old, new string, d *schema.ResourceData) bool { + // Suppress diffs for the labels provided by Google + for _, label := range domainMappingGoogleProvidedLabels { + if strings.Contains(k, label) && new == "" { + return true + } + } + + // Let diff be determined by labels (above) + if strings.Contains(k, "labels.%") { + return true + } + + // For other keys, don't suppress diff. + return false +} + +func resourceCloudRunDomainMappingResourceV0() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "location": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The location of the cloud run instance. eg us-central1`, + }, + "metadata": { + Type: schema.TypeList, + Required: true, + ForceNew: true, + Description: `Metadata associated with this DomainMapping.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "namespace": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `In Cloud Run the namespace must be equal to either the +project ID or project number.`, + }, + "annotations": { + Type: schema.TypeMap, + Computed: true, + Optional: true, + ForceNew: true, + DiffSuppressFunc: cloudrunAnnotationDiffSuppress, + Description: `Annotations is a key value map stored with a resource that +may be set by external tools to store and retrieve arbitrary metadata. More +info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations + +**Note**: The Cloud Run API may add additional annotations that were not provided in your config. +If terraform plan shows a diff where a server-side annotation is added, you can add it to your config +or apply the lifecycle.ignore_changes rule to the metadata.0.annotations field.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "labels": { + Type: schema.TypeMap, + Computed: true, + Optional: true, + ForceNew: true, + DiffSuppressFunc: DomainMappingLabelDiffSuppress, + Description: `Map of string keys and values that can be used to organize and categorize +(scope and select) objects. May match selectors of replication controllers +and routes. +More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "generation": { + Type: schema.TypeInt, + Computed: true, + Description: `A sequence number representing a specific generation of the desired state.`, + }, + "resource_version": { + Type: schema.TypeString, + Computed: true, + Description: `An opaque value that represents the internal version of this object that +can be used by clients to determine when objects have changed. May be used +for optimistic concurrency, change detection, and the watch operation on a +resource or set of resources. They may only be valid for a +particular resource or set of resources. + +More info: +https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency`, + }, + "self_link": { + Type: schema.TypeString, + Computed: true, + Description: `SelfLink is a URL representing this object.`, + }, + "uid": { + Type: schema.TypeString, + Computed: true, + Description: `UID is a unique id generated by the server on successful creation of a resource and is not +allowed to change on PUT operations. + +More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#uids`, + }, + }, + }, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `Name should be a [verified](https://support.google.com/webmasters/answer/9008080) domain`, + }, + "spec": { + Type: schema.TypeList, + Required: true, + ForceNew: true, + Description: `The spec for this DomainMapping.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "route_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `The name of the Cloud Run Service that this DomainMapping applies to. +The route must exist.`, + }, + "certificate_mode": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: verify.ValidateEnum([]string{"NONE", "AUTOMATIC", ""}), + Description: `The mode of the certificate. Default value: "AUTOMATIC" Possible values: ["NONE", "AUTOMATIC"]`, + Default: "AUTOMATIC", + }, + "force_override": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `If set, the mapping will override any mapping set before this spec was set. +It is recommended that the user leaves this empty to receive an error +warning about a potential conflict and only set it once the respective UI +has given such a warning.`, + }, + }, + }, + }, + "status": { + Type: schema.TypeList, + Computed: true, + Description: `The current status of the DomainMapping.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "resource_records": { + Type: schema.TypeList, + Optional: true, + Description: `The resource records required to configure this domain mapping. These +records must be added to the domain's DNS configuration in order to +serve the application via this domain mapping.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: verify.ValidateEnum([]string{"A", "AAAA", "CNAME", ""}), + Description: `Resource record type. Example: 'AAAA'. Possible values: ["A", "AAAA", "CNAME"]`, + }, + "name": { + Type: schema.TypeString, + Computed: true, + Description: `Relative name of the object affected by this record. Only applicable for +'CNAME' records. Example: 'www'.`, + }, + "rrdata": { + Type: schema.TypeString, + Computed: true, + Description: `Data for this record. Values vary by record type, as defined in RFC 1035 +(section 5) and RFC 1034 (section 3.6.1).`, + }, + }, + }, + }, + "conditions": { + Type: schema.TypeList, + Computed: true, + Description: `Array of observed DomainMappingConditions, indicating the current state +of the DomainMapping.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "message": { + Type: schema.TypeString, + Computed: true, + Description: `Human readable message indicating details about the current status.`, + }, + "reason": { + Type: schema.TypeString, + Computed: true, + Description: `One-word CamelCase reason for the condition's current status.`, + }, + "status": { + Type: schema.TypeString, + Computed: true, + Description: `Status of the condition, one of True, False, Unknown.`, + }, + "type": { + Type: schema.TypeString, + Computed: true, + Description: `Type of domain mapping condition.`, + }, + }, + }, + }, + "mapped_route_name": { + Type: schema.TypeString, + Computed: true, + Description: `The name of the route that the mapping currently points to.`, + }, + "observed_generation": { + Type: schema.TypeInt, + Computed: true, + Description: `ObservedGeneration is the 'Generation' of the DomainMapping that +was last processed by the controller.`, + }, + }, + }, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + UseJSONNumber: true, + } +} + +func ResourceCloudRunDomainMappingUpgradeV0(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { + log.Printf("[DEBUG] Attributes before migration: %#v", rawState) + + if rawState["metadata"] != nil { + rawMetadatas := rawState["metadata"].([]interface{}) + if len(rawMetadatas) > 0 && rawMetadatas[0] != nil { + // Upgrade labels fields + rawMetadata := rawMetadatas[0].(map[string]interface{}) + + rawLabels := rawMetadata["labels"] + if rawLabels != nil { + labels := make(map[string]interface{}) + effectiveLabels := make(map[string]interface{}) + + for k, v := range rawLabels.(map[string]interface{}) { + effectiveLabels[k] = v + + if !strings.Contains(k, domainMappingGoogleProvidedLocationLabel) && !strings.Contains(k, domainMappingGoogleProvidedOverrideLabel) { + labels[k] = v + } + } + + rawMetadata["labels"] = labels + rawMetadata["effective_labels"] = effectiveLabels + } + + upgradeAnnotations(rawMetadata) + + rawState["metadata"] = []interface{}{rawMetadata} + } + } + + log.Printf("[DEBUG] Attributes after migration: %#v", rawState) + return rawState, nil +} diff --git a/mmv1/templates/terraform/state_migrations/cloud_run_service.go.erb b/mmv1/templates/terraform/state_migrations/cloud_run_service.go.erb new file mode 100644 index 000000000000..9c807cef403f --- /dev/null +++ b/mmv1/templates/terraform/state_migrations/cloud_run_service.go.erb @@ -0,0 +1,1099 @@ +var cloudRunGoogleProvidedAnnotations = regexp.MustCompile(`serving\.knative\.dev/(?:(?:creator)|(?:lastModifier))$|run\.googleapis\.com/(?:(?:ingress-status)|(?:operation-id))$|cloud\.googleapis\.com/(?:(?:location))`) + +func cloudrunAnnotationDiffSuppress(k, old, new string, d *schema.ResourceData) bool { + // Suppress diffs for the annotations provided by Google + if cloudRunGoogleProvidedAnnotations.MatchString(k) && new == "" { + return true + } + + if strings.HasSuffix(k, "run.googleapis.com/ingress") { + return old == "all" && new == "" + } + + // Let diff be determined by annotations (above) + if strings.Contains(k, "annotations.%") { + return true + } + + // For other keys, don't suppress diff. + return false +} + +var cloudRunGoogleProvidedLabels = regexp.MustCompile(`cloud\.googleapis\.com/(?:(?:location))`) + +func cloudrunLabelDiffSuppress(k, old, new string, d *schema.ResourceData) bool { + // Suppress diffs for the labels provided by Google + if cloudRunGoogleProvidedLabels.MatchString(k) && new == "" { + return true + } + + // Let diff be determined by labels (above) + if strings.Contains(k, "labels.%") { + return true + } + + // For other keys, don't suppress diff. + return false +} + +func resourceCloudRunServiceResourceV1() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "location": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The location of the cloud run instance. eg us-central1`, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `Name must be unique within a Google Cloud project and region. +Is required when creating resources. Name is primarily intended +for creation idempotence and configuration definition. Cannot be updated. +More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names`, + }, + "template": { + Type: schema.TypeList, + Optional: true, + Description: `template holds the latest specification for the Revision to +be stamped out. The template references the container image, and may also +include labels and annotations that should be attached to the Revision. +To correlate a Revision, and/or to force a Revision to be created when the +spec doesn't otherwise change, a nonce label may be provided in the +template metadata. For more details, see: +https://github.com/knative/serving/blob/main/docs/client-conventions.md#associate-modifications-with-revisions + +Cloud Run does not currently support referencing a build that is +responsible for materializing the container image from source.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "spec": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Description: `RevisionSpec holds the desired state of the Revision (from the client).`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "containers": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Description: `Containers defines the unit of execution for this Revision.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "image": { + Type: schema.TypeString, + Required: true, + Description: `Docker image name. This is most often a reference to a container located +in the container registry, such as gcr.io/cloudrun/hello`, + }, + "args": { + Type: schema.TypeList, + Optional: true, + Description: `Arguments to the entrypoint. +The docker image's CMD is used if this is not provided.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "command": { + Type: schema.TypeList, + Optional: true, + Description: `Entrypoint array. Not executed within a shell. +The docker image's ENTRYPOINT is used if this is not provided.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "env": { + Type: schema.TypeSet, + Optional: true, + Description: `List of environment variables to set in the container.`, + Elem: cloudrunServiceSpecTemplateSpecContainersContainersEnvSchema(), + // Default schema.HashSchema is used. + }, + "env_from": { + Type: schema.TypeList, + Optional: true, + Deprecated: "`env_from` is deprecated and will be removed in a future major release. This field is not supported by the Cloud Run API.", + ForceNew: true, + Description: `List of sources to populate environment variables in the container. +All invalid keys will be reported as an event when the container is starting. +When a key exists in multiple sources, the value associated with the last source will +take precedence. Values defined by an Env with a duplicate key will take +precedence.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "config_map_ref": { + Type: schema.TypeList, + Optional: true, + Description: `The ConfigMap to select from.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "local_object_reference": { + Type: schema.TypeList, + Optional: true, + Description: `The ConfigMap to select from.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: `Name of the referent.`, + }, + }, + }, + }, + "optional": { + Type: schema.TypeBool, + Optional: true, + Description: `Specify whether the ConfigMap must be defined`, + }, + }, + }, + }, + "prefix": { + Type: schema.TypeString, + Optional: true, + Description: `An optional identifier to prepend to each key in the ConfigMap.`, + }, + "secret_ref": { + Type: schema.TypeList, + Optional: true, + Description: `The Secret to select from.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "local_object_reference": { + Type: schema.TypeList, + Optional: true, + Description: `The Secret to select from.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: `Name of the referent.`, + }, + }, + }, + }, + "optional": { + Type: schema.TypeBool, + Optional: true, + Description: `Specify whether the Secret must be defined`, + }, + }, + }, + }, + }, + }, + }, + "liveness_probe": { + Type: schema.TypeList, + Optional: true, + Description: `Periodic probe of container liveness. Container will be restarted if the probe fails.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "failure_threshold": { + Type: schema.TypeInt, + Optional: true, + Description: `Minimum consecutive failures for the probe to be considered failed after +having succeeded. Defaults to 3. Minimum value is 1.`, + Default: 3, + }, + "grpc": { + Type: schema.TypeList, + Optional: true, + Description: `GRPC specifies an action involving a GRPC port.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "port": { + Type: schema.TypeInt, + Computed: true, + Optional: true, + Description: `Port number to access on the container. Number must be in the range 1 to 65535. +If not specified, defaults to the same value as container.ports[0].containerPort.`, + }, + "service": { + Type: schema.TypeString, + Optional: true, + Description: `The name of the service to place in the gRPC HealthCheckRequest +(see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). +If this is not specified, the default behavior is defined by gRPC.`, + }, + }, + }, + ExactlyOneOf: []string{}, + }, + "http_get": { + Type: schema.TypeList, + Optional: true, + Description: `HttpGet specifies the http request to perform.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "http_headers": { + Type: schema.TypeList, + Optional: true, + Description: `Custom headers to set in the request. HTTP allows repeated headers.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: `The header field name.`, + }, + "value": { + Type: schema.TypeString, + Optional: true, + Description: `The header field value.`, + Default: "", + }, + }, + }, + }, + "path": { + Type: schema.TypeString, + Optional: true, + Description: `Path to access on the HTTP server. If set, it should not be empty string.`, + Default: "/", + }, + "port": { + Type: schema.TypeInt, + Computed: true, + Optional: true, + Description: `Port number to access on the container. Number must be in the range 1 to 65535. +If not specified, defaults to the same value as container.ports[0].containerPort.`, + }, + }, + }, + ExactlyOneOf: []string{}, + }, + "initial_delay_seconds": { + Type: schema.TypeInt, + Optional: true, + Description: `Number of seconds after the container has started before the probe is +initiated. +Defaults to 0 seconds. Minimum value is 0. Maximum value is 3600.`, + Default: 0, + }, + "period_seconds": { + Type: schema.TypeInt, + Optional: true, + Description: `How often (in seconds) to perform the probe. +Default to 10 seconds. Minimum value is 1. Maximum value is 3600.`, + Default: 10, + }, + "timeout_seconds": { + Type: schema.TypeInt, + Optional: true, + Description: `Number of seconds after which the probe times out. +Defaults to 1 second. Minimum value is 1. Maximum value is 3600. +Must be smaller than period_seconds.`, + Default: 1, + }, + }, + }, + }, + "name": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `Name of the container`, + }, + "ports": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Description: `List of open ports in the container.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "container_port": { + Type: schema.TypeInt, + Optional: true, + Description: `Port number the container listens on. This must be a valid port number (between 1 and 65535). Defaults to "8080".`, + }, + "name": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `If specified, used to specify which protocol to use. Allowed values are "http1" (HTTP/1) and "h2c" (HTTP/2 end-to-end). Defaults to "http1".`, + }, + "protocol": { + Type: schema.TypeString, + Optional: true, + Description: `Protocol for port. Must be "TCP". Defaults to "TCP".`, + }, + }, + }, + }, + "resources": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Description: `Compute Resources required by this container. Used to set values such as max memory`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "limits": { + Type: schema.TypeMap, + Computed: true, + Optional: true, + Description: `Limits describes the maximum amount of compute resources allowed. +The values of the map is string form of the 'quantity' k8s type: +https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity.go`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "requests": { + Type: schema.TypeMap, + Optional: true, + Description: `Requests describes the minimum amount of compute resources required. +If Requests is omitted for a container, it defaults to Limits if that is +explicitly specified, otherwise to an implementation-defined value. +The values of the map is string form of the 'quantity' k8s type: +https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity.go`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "startup_probe": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Description: `Startup probe of application within the container. +All other probes are disabled if a startup probe is provided, until it +succeeds. Container will not be added to service endpoints if the probe fails.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "failure_threshold": { + Type: schema.TypeInt, + Optional: true, + Description: `Minimum consecutive failures for the probe to be considered failed after +having succeeded. Defaults to 3. Minimum value is 1.`, + Default: 3, + }, + "grpc": { + Type: schema.TypeList, + Optional: true, + Description: `GRPC specifies an action involving a GRPC port.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "port": { + Type: schema.TypeInt, + Computed: true, + Optional: true, + Description: `Port number to access on the container. Number must be in the range 1 to 65535. +If not specified, defaults to the same value as container.ports[0].containerPort.`, + }, + "service": { + Type: schema.TypeString, + Optional: true, + Description: `The name of the service to place in the gRPC HealthCheckRequest +(see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). +If this is not specified, the default behavior is defined by gRPC.`, + }, + }, + }, + ExactlyOneOf: []string{}, + }, + "http_get": { + Type: schema.TypeList, + Optional: true, + Description: `HttpGet specifies the http request to perform.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "http_headers": { + Type: schema.TypeList, + Optional: true, + Description: `Custom headers to set in the request. HTTP allows repeated headers.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: `The header field name.`, + }, + "value": { + Type: schema.TypeString, + Optional: true, + Description: `The header field value.`, + Default: "", + }, + }, + }, + }, + "path": { + Type: schema.TypeString, + Optional: true, + Description: `Path to access on the HTTP server. If set, it should not be empty string.`, + Default: "/", + }, + "port": { + Type: schema.TypeInt, + Computed: true, + Optional: true, + Description: `Port number to access on the container. Number must be in the range 1 to 65535. +If not specified, defaults to the same value as container.ports[0].containerPort.`, + }, + }, + }, + ExactlyOneOf: []string{}, + }, + "initial_delay_seconds": { + Type: schema.TypeInt, + Optional: true, + Description: `Number of seconds after the container has started before the probe is +initiated. +Defaults to 0 seconds. Minimum value is 0. Maximum value is 240.`, + Default: 0, + }, + "period_seconds": { + Type: schema.TypeInt, + Optional: true, + Description: `How often (in seconds) to perform the probe. +Default to 10 seconds. Minimum value is 1. Maximum value is 240.`, + Default: 10, + }, + "tcp_socket": { + Type: schema.TypeList, + Optional: true, + Description: `TcpSocket specifies an action involving a TCP port.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "port": { + Type: schema.TypeInt, + Computed: true, + Optional: true, + Description: `Port number to access on the container. Number must be in the range 1 to 65535. +If not specified, defaults to the same value as container.ports[0].containerPort.`, + }, + }, + }, + ExactlyOneOf: []string{}, + }, + "timeout_seconds": { + Type: schema.TypeInt, + Optional: true, + Description: `Number of seconds after which the probe times out. +Defaults to 1 second. Minimum value is 1. Maximum value is 3600. +Must be smaller than periodSeconds.`, + Default: 1, + }, + }, + }, + }, + "volume_mounts": { + Type: schema.TypeList, + Optional: true, + Description: `Volume to mount into the container's filesystem. +Only supports SecretVolumeSources.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mount_path": { + Type: schema.TypeString, + Required: true, + Description: `Path within the container at which the volume should be mounted. Must +not contain ':'.`, + }, + "name": { + Type: schema.TypeString, + Required: true, + Description: `This must match the Name of a Volume.`, + }, + }, + }, + }, + "working_dir": { + Type: schema.TypeString, + Optional: true, + Deprecated: "`working_dir` is deprecated and will be removed in a future major release. This field is not supported by the Cloud Run API.", + ForceNew: true, + Description: `Container's working directory. +If not specified, the container runtime's default will be used, which +might be configured in the container image.`, + }, + }, + }, + }, + "container_concurrency": { + Type: schema.TypeInt, + Computed: true, + Optional: true, + Description: `ContainerConcurrency specifies the maximum allowed in-flight (concurrent) +requests per container of the Revision. Values are: +- '0' thread-safe, the system should manage the max concurrency. This is + the default value. +- '1' not-thread-safe. Single concurrency +- '2-N' thread-safe, max concurrency of N`, + }, + "service_account_name": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `Email address of the IAM service account associated with the revision of the +service. The service account represents the identity of the running revision, +and determines what permissions the revision has. If not provided, the revision +will use the project's default service account.`, + }, + "timeout_seconds": { + Type: schema.TypeInt, + Computed: true, + Optional: true, + Description: `TimeoutSeconds holds the max duration the instance is allowed for responding to a request.`, + }, + "volumes": { + Type: schema.TypeList, + Optional: true, + Description: `Volume represents a named volume in a container.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: `Volume's name.`, + }, +<% unless version == "ga" -%> + "empty_dir": { + Type: schema.TypeList, + Optional: true, + Description: `Ephemeral storage which can be backed by real disks (HD, SSD), network storage or memory (i.e. tmpfs). For now only in memory (tmpfs) is supported. It is ephemeral in the sense that when the sandbox is taken down, the data is destroyed with it (it does not persist across sandbox runs).`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "medium": { + Type: schema.TypeString, + Optional: true, + Description: `The medium on which the data is stored. The default is "" which means to use the node's default medium. Must be an empty string (default) or Memory.`, + }, + "size_limit": { + Type: schema.TypeString, + Optional: true, + 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.`, + }, + }, + }, + }, +<% end -%> + "secret": { + Type: schema.TypeList, + Optional: true, + Description: `The secret's value will be presented as the content of a file whose +name is defined in the item path. If no items are defined, the name of +the file is the secret_name.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "secret_name": { + Type: schema.TypeString, + Required: true, + Description: `The name of the secret in Cloud Secret Manager. By default, the secret +is assumed to be in the same project. +If the secret is in another project, you must define an alias. +An alias definition has the form: +{alias}:projects/{project-id|project-number}/secrets/{secret-name}. +If multiple alias definitions are needed, they must be separated by +commas. +The alias definitions must be set on the run.googleapis.com/secrets +annotation.`, + }, + "default_mode": { + Type: schema.TypeInt, + Optional: true, + Description: `Mode bits to use on created files by default. Must be a value between 0000 +and 0777. Defaults to 0644. Directories within the path are not affected by +this setting. This might be in conflict with other options that affect the +file mode, like fsGroup, and the result can be other mode bits set.`, + }, + "items": { + Type: schema.TypeList, + Optional: true, + Description: `If unspecified, the volume will expose a file whose name is the +secret_name. +If specified, the key will be used as the version to fetch from Cloud +Secret Manager and the path will be the name of the file exposed in the +volume. When items are defined, they must specify a key and a path.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": { + Type: schema.TypeString, + Required: true, + Description: `The Cloud Secret Manager secret version. +Can be 'latest' for the latest value or an integer for a specific version.`, + }, + "path": { + Type: schema.TypeString, + Required: true, + Description: `The relative path of the file to map the key to. +May not be an absolute path. +May not contain the path element '..'. +May not start with the string '..'.`, + }, + "mode": { + Type: schema.TypeInt, + Optional: true, + Description: `Mode bits to use on this file, must be a value between 0000 and 0777. If +not specified, the volume defaultMode will be used. This might be in +conflict with other options that affect the file mode, like fsGroup, and +the result can be other mode bits set.`, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "serving_state": { + Type: schema.TypeString, + Computed: true, + Deprecated: "`serving_state` is deprecated and will be removed in a future major release. This field is not supported by the Cloud Run API.", + Description: `ServingState holds a value describing the state the resources +are in for this Revision. +It is expected +that the system will manipulate this based on routability and load.`, + }, + }, + }, + }, + "metadata": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Description: `Optional metadata for this Revision, including labels and annotations. +Name will be generated by the Configuration. To set minimum instances +for this revision, use the "autoscaling.knative.dev/minScale" annotation +key. To set maximum instances for this revision, use the +"autoscaling.knative.dev/maxScale" annotation key. To set Cloud SQL +connections for the revision, use the "run.googleapis.com/cloudsql-instances" +annotation key.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "annotations": { + Type: schema.TypeMap, + Computed: true, + Optional: true, + DiffSuppressFunc: cloudrunTemplateAnnotationDiffSuppress, + Description: `Annotations is a key value map stored with a resource that +may be set by external tools to store and retrieve arbitrary metadata. More +info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations + +**Note**: The Cloud Run API may add additional annotations that were not provided in your config. +If terraform plan shows a diff where a server-side annotation is added, you can add it to your config +or apply the lifecycle.ignore_changes rule to the metadata.0.annotations field. + +Annotations with 'run.googleapis.com/' and 'autoscaling.knative.dev' are restricted. Use the following annotation +keys to configure features on a Revision template: + +- 'autoscaling.knative.dev/maxScale' sets the [maximum number of container + instances](https://cloud.google.com/sdk/gcloud/reference/run/deploy#--max-instances) of the Revision to run. +- 'autoscaling.knative.dev/minScale' sets the [minimum number of container + instances](https://cloud.google.com/sdk/gcloud/reference/run/deploy#--min-instances) of the Revision to run. +- 'run.googleapis.com/client-name' sets the client name calling the Cloud Run API. +- 'run.googleapis.com/cloudsql-instances' sets the [Cloud SQL + instances](https://cloud.google.com/sdk/gcloud/reference/run/deploy#--add-cloudsql-instances) the Revision connects to. +- 'run.googleapis.com/cpu-throttling' sets whether to throttle the CPU when the container is not actively serving + requests. See https://cloud.google.com/sdk/gcloud/reference/run/deploy#--[no-]cpu-throttling. +- 'run.googleapis.com/encryption-key-shutdown-hours' sets the number of hours to wait before an automatic shutdown + server after CMEK key revocation is detected. +- 'run.googleapis.com/encryption-key' sets the [CMEK key](https://cloud.google.com/run/docs/securing/using-cmek) + reference to encrypt the container with. +- 'run.googleapis.com/execution-environment' sets the [execution + environment](https://cloud.google.com/sdk/gcloud/reference/run/deploy#--execution-environment) + where the application will run. +- 'run.googleapis.com/post-key-revocation-action-type' sets the + [action type](https://cloud.google.com/sdk/gcloud/reference/run/deploy#--post-key-revocation-action-type) + after CMEK key revocation. +- 'run.googleapis.com/secrets' sets a list of key-value pairs to set as + [secrets](https://cloud.google.com/run/docs/configuring/secrets#yaml). +- 'run.googleapis.com/sessionAffinity' sets whether to enable + [session affinity](https://cloud.google.com/sdk/gcloud/reference/beta/run/deploy#--[no-]session-affinity) + for connections to the Revision. +- 'run.googleapis.com/startup-cpu-boost' sets whether to allocate extra CPU to containers on startup. + See https://cloud.google.com/sdk/gcloud/reference/run/deploy#--[no-]cpu-boost. +- 'run.googleapis.com/vpc-access-connector' sets a [VPC connector](https://cloud.google.com/run/docs/configuring/connecting-vpc#terraform_1) + for the Revision. +- 'run.googleapis.com/vpc-access-egress' sets the outbound traffic to send through the VPC connector for this resource. + See https://cloud.google.com/sdk/gcloud/reference/run/deploy#--vpc-egress.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "labels": { + Type: schema.TypeMap, + Computed: true, + Optional: true, + DiffSuppressFunc: cloudrunTemplateLabelDiffSuppress, + Description: `Map of string keys and values that can be used to organize and categorize +(scope and select) objects.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "name": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `Name must be unique within a Google Cloud project and region. +Is required when creating resources. Name is primarily intended +for creation idempotence and configuration definition. Cannot be updated.`, + }, + "namespace": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `In Cloud Run the namespace must be equal to either the +project ID or project number. It will default to the resource's project.`, + }, + "generation": { + Type: schema.TypeInt, + Computed: true, + Description: `A sequence number representing a specific generation of the desired state.`, + }, + "resource_version": { + Type: schema.TypeString, + Computed: true, + Description: `An opaque value that represents the internal version of this object that +can be used by clients to determine when objects have changed. May be used +for optimistic concurrency, change detection, and the watch operation on a +resource or set of resources. They may only be valid for a +particular resource or set of resources.`, + }, + "self_link": { + Type: schema.TypeString, + Computed: true, + Description: `SelfLink is a URL representing this object.`, + }, + "uid": { + Type: schema.TypeString, + Computed: true, + Description: `UID is a unique id generated by the server on successful creation of a resource and is not +allowed to change on PUT operations.`, + }, + }, + }, + }, + }, + }, + }, + "traffic": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Description: `Traffic specifies how to distribute traffic over a collection of Knative Revisions +and Configurations`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "percent": { + Type: schema.TypeInt, + Required: true, + Description: `Percent specifies percent of the traffic to this Revision or Configuration.`, + }, + "latest_revision": { + Type: schema.TypeBool, + Optional: true, + Description: `LatestRevision may be optionally provided to indicate that the latest ready +Revision of the Configuration should be used for this traffic target. When +provided LatestRevision must be true if RevisionName is empty; it must be +false when RevisionName is non-empty.`, + }, + "revision_name": { + Type: schema.TypeString, + Optional: true, + Description: `RevisionName of a specific revision to which to send this portion of traffic.`, + }, + "tag": { + Type: schema.TypeString, + Optional: true, + Description: `Tag is optionally used to expose a dedicated url for referencing this target exclusively.`, + }, + "url": { + Type: schema.TypeString, + Computed: true, + Description: `URL displays the URL for accessing tagged traffic targets. URL is displayed in status, +and is disallowed on spec. URL must contain a scheme (e.g. http://) and a hostname, +but may not contain anything else (e.g. basic auth, url path, etc.)`, + }, + }, + }, + }, + + "metadata": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Description: `Metadata associated with this Service, including name, namespace, labels, +and annotations.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "annotations": { + Type: schema.TypeMap, + Computed: true, + Optional: true, + DiffSuppressFunc: cloudrunAnnotationDiffSuppress, + Description: `Annotations is a key value map stored with a resource that +may be set by external tools to store and retrieve arbitrary metadata. More +info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations + +**Note**: The Cloud Run API may add additional annotations that were not provided in your config. +If terraform plan shows a diff where a server-side annotation is added, you can add it to your config +or apply the lifecycle.ignore_changes rule to the metadata.0.annotations field. + +Annotations with 'run.googleapis.com/' and 'autoscaling.knative.dev' are restricted. Use the following annotation +keys to configure features on a Service: + +- 'run.googleapis.com/binary-authorization-breakglass' sets the [Binary Authorization breakglass](https://cloud.google.com/sdk/gcloud/reference/run/deploy#--breakglass). +- 'run.googleapis.com/binary-authorization' sets the [Binary Authorization](https://cloud.google.com/sdk/gcloud/reference/run/deploy#--binary-authorization). +- 'run.googleapis.com/client-name' sets the client name calling the Cloud Run API. +- 'run.googleapis.com/custom-audiences' sets the [custom audiences](https://cloud.google.com/sdk/gcloud/reference/alpha/run/deploy#--add-custom-audiences) + that can be used in the audience field of ID token for authenticated requests. +- 'run.googleapis.com/description' sets a user defined description for the Service. +- 'run.googleapis.com/ingress' sets the [ingress settings](https://cloud.google.com/sdk/gcloud/reference/run/deploy#--ingress) + for the Service. For example, '"run.googleapis.com/ingress" = "all"'. +- 'run.googleapis.com/launch-stage' sets the [launch stage](https://cloud.google.com/run/docs/troubleshooting#launch-stage-validation) + when a preview feature is used. For example, '"run.googleapis.com/launch-stage": "BETA"'`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "labels": { + Type: schema.TypeMap, + Computed: true, + Optional: true, + DiffSuppressFunc: cloudrunLabelDiffSuppress, + Description: `Map of string keys and values that can be used to organize and categorize +(scope and select) objects. May match selectors of replication controllers +and routes.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "namespace": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `In Cloud Run the namespace must be equal to either the +project ID or project number.`, + }, + "generation": { + Type: schema.TypeInt, + Computed: true, + Description: `A sequence number representing a specific generation of the desired state.`, + }, + "resource_version": { + Type: schema.TypeString, + Computed: true, + Description: `An opaque value that represents the internal version of this object that +can be used by clients to determine when objects have changed. May be used +for optimistic concurrency, change detection, and the watch operation on a +resource or set of resources. They may only be valid for a +particular resource or set of resources.`, + }, + "self_link": { + Type: schema.TypeString, + Computed: true, + Description: `SelfLink is a URL representing this object.`, + }, + "uid": { + Type: schema.TypeString, + Computed: true, + Description: `UID is a unique id generated by the server on successful creation of a resource and is not +allowed to change on PUT operations.`, + }, + }, + }, + }, + "status": { + Type: schema.TypeList, + Computed: true, + Description: `The current status of the Service.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "conditions": { + Type: schema.TypeList, + Computed: true, + Description: `Array of observed Service Conditions, indicating the current ready state of the service.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "message": { + Type: schema.TypeString, + Computed: true, + Description: `Human readable message indicating details about the current status.`, + }, + "reason": { + Type: schema.TypeString, + Computed: true, + Description: `One-word CamelCase reason for the condition's current status.`, + }, + "status": { + Type: schema.TypeString, + Computed: true, + Description: `Status of the condition, one of True, False, Unknown.`, + }, + "type": { + Type: schema.TypeString, + Computed: true, + Description: `Type of domain mapping condition.`, + }, + }, + }, + }, + "latest_created_revision_name": { + Type: schema.TypeString, + Computed: true, + Description: `From ConfigurationStatus. LatestCreatedRevisionName is the last revision that was created +from this Service's Configuration. It might not be ready yet, for that use +LatestReadyRevisionName.`, + }, + "latest_ready_revision_name": { + Type: schema.TypeString, + Computed: true, + Description: `From ConfigurationStatus. LatestReadyRevisionName holds the name of the latest Revision +stamped out from this Service's Configuration that has had its "Ready" condition become +"True".`, + }, + "observed_generation": { + Type: schema.TypeInt, + Computed: true, + Description: `ObservedGeneration is the 'Generation' of the Route that was last processed by the +controller. + +Clients polling for completed reconciliation should poll until observedGeneration = +metadata.generation and the Ready condition's status is True or False.`, + }, + "traffic": { + Type: schema.TypeList, + Computed: true, + Description: `Traffic specifies how to distribute traffic over a collection of Knative Revisions +and Configurations`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "latest_revision": { + Type: schema.TypeBool, + Computed: true, + Description: `LatestRevision may be optionally provided to indicate that the latest ready +Revision of the Configuration should be used for this traffic target. When +provided LatestRevision must be true if RevisionName is empty; it must be +false when RevisionName is non-empty.`, + }, + "percent": { + Type: schema.TypeInt, + Computed: true, + Description: `Percent specifies percent of the traffic to this Revision or Configuration.`, + }, + "revision_name": { + Type: schema.TypeString, + Computed: true, + Description: `RevisionName of a specific revision to which to send this portion of traffic.`, + }, + "tag": { + Type: schema.TypeString, + Computed: true, + Description: `Tag is optionally used to expose a dedicated url for referencing this target exclusively.`, + }, + "url": { + Type: schema.TypeString, + Computed: true, + Description: `URL displays the URL for accessing tagged traffic targets. URL is displayed in status, +and is disallowed on spec. URL must contain a scheme (e.g. http://) and a hostname, +but may not contain anything else (e.g. basic auth, url path, etc.)`, + }, + }, + }, + }, + "url": { + Type: schema.TypeString, + Computed: true, + Description: `From RouteStatus. URL holds the url that will distribute traffic over the provided traffic +targets. It generally has the form +https://{route-hash}-{project-hash}-{cluster-level-suffix}.a.run.app`, + }, + }, + }, + }, + "autogenerate_revision_name": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: `If set to 'true', the revision name (template.metadata.name) will be omitted and +autogenerated by Cloud Run. This cannot be set to 'true' while 'template.metadata.name' +is also set. +(For legacy support, if 'template.metadata.name' is unset in state while +this field is set to false, the revision name will still autogenerate.)`, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + UseJSONNumber: true, + } +} + +func upgradeAnnotations(rawMetadata map[string]interface{}) { + rawAnnotations := rawMetadata["annotations"] + if rawAnnotations != nil { + annotations := make(map[string]interface{}) + effectiveAnnotations := make(map[string]interface{}) + + for k, v := range rawAnnotations.(map[string]interface{}) { + effectiveAnnotations[k] = v + + if !(cloudRunGoogleProvidedAnnotations.MatchString(k) || (strings.HasSuffix(k, "run.googleapis.com/ingress") && v == "all")) { + annotations[k] = v + } + } + + rawMetadata["annotations"] = annotations + rawMetadata["effective_annotations"] = effectiveAnnotations + } +} + +func ResourceCloudRunServiceUpgradeV1(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { + log.Printf("[DEBUG] Attributes before migration: %#v", rawState) + + if rawState["metadata"] != nil { + rawMetadatas := rawState["metadata"].([]interface{}) + + // Upgrade labels fields + if len(rawMetadatas) > 0 && rawMetadatas[0] != nil { + rawMetadata := rawMetadatas[0].(map[string]interface{}) + + rawLabels := rawMetadata["labels"] + if rawLabels != nil { + labels := make(map[string]interface{}) + effectiveLabels := make(map[string]interface{}) + + for k, v := range rawLabels.(map[string]interface{}) { + effectiveLabels[k] = v + + if !cloudRunGoogleProvidedLabels.MatchString(k) { + labels[k] = v + } + } + + rawMetadata["labels"] = labels + rawMetadata["effective_labels"] = effectiveLabels + } + + upgradeAnnotations(rawMetadata) + + rawState["metadata"] = []interface{}{rawMetadata} + } + } + + log.Printf("[DEBUG] Attributes after migration: %#v", rawState) + return rawState, nil +} diff --git a/mmv1/templates/terraform/state_migrations/notebooks_instance.go.erb b/mmv1/templates/terraform/state_migrations/notebooks_instance.go.erb new file mode 100644 index 000000000000..069dacdd5216 --- /dev/null +++ b/mmv1/templates/terraform/state_migrations/notebooks_instance.go.erb @@ -0,0 +1,407 @@ +const notebooksInstanceGoogleProvidedLabel = "goog-caip-notebook" + +func NotebooksInstanceLabelDiffSuppress(k, old, new string, d *schema.ResourceData) bool { + // Suppress diffs for the label provided by Google + if strings.Contains(k, notebooksInstanceGoogleProvidedLabel) && new == "" { + return true + } + + // Let diff be determined by labels (above) + if strings.Contains(k, "labels.%") { + return true + } + + // For other keys, don't suppress diff. + return false +} + +func resourceNotebooksInstanceResourceV0() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "location": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `A reference to the zone where the machine resides.`, + }, + "machine_type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `A reference to a machine type which defines VM kind.`, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The name specified for the Notebook instance.`, + }, + "accelerator_config": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `The hardware accelerator used on this instance. If you use accelerators, +make sure that your configuration has enough vCPUs and memory to support the +machineType you have selected.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "core_count": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + Description: `Count of cores of this accelerator.`, + }, + "type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: verify.ValidateEnum([]string{"ACCELERATOR_TYPE_UNSPECIFIED", "NVIDIA_TESLA_K80", "NVIDIA_TESLA_P100", "NVIDIA_TESLA_V100", "NVIDIA_TESLA_P4", "NVIDIA_TESLA_T4", "NVIDIA_TESLA_T4_VWS", "NVIDIA_TESLA_P100_VWS", "NVIDIA_TESLA_P4_VWS", "NVIDIA_TESLA_A100", "TPU_V2", "TPU_V3"}), + Description: `Type of this accelerator. Possible values: ["ACCELERATOR_TYPE_UNSPECIFIED", "NVIDIA_TESLA_K80", "NVIDIA_TESLA_P100", "NVIDIA_TESLA_V100", "NVIDIA_TESLA_P4", "NVIDIA_TESLA_T4", "NVIDIA_TESLA_T4_VWS", "NVIDIA_TESLA_P100_VWS", "NVIDIA_TESLA_P4_VWS", "NVIDIA_TESLA_A100", "TPU_V2", "TPU_V3"]`, + }, + }, + }, + }, + "boot_disk_size_gb": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Description: `The size of the boot disk in GB attached to this instance, +up to a maximum of 64000 GB (64 TB). The minimum recommended value is 100 GB. +If not specified, this defaults to 100.`, + }, + "boot_disk_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: verify.ValidateEnum([]string{"DISK_TYPE_UNSPECIFIED", "PD_STANDARD", "PD_SSD", "PD_BALANCED", "PD_EXTREME", ""}), + Description: `Possible disk types for notebook instances. Possible values: ["DISK_TYPE_UNSPECIFIED", "PD_STANDARD", "PD_SSD", "PD_BALANCED", "PD_EXTREME"]`, + }, + "container_image": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `Use a container image to start the notebook instance.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "repository": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The path to the container image repository. +For example: gcr.io/{project_id}/{imageName}`, + }, + "tag": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `The tag of the container image. If not specified, this defaults to the latest tag.`, + }, + }, + }, + ExactlyOneOf: []string{"vm_image", "container_image"}, + }, + "custom_gpu_driver_path": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `Specify a custom Cloud Storage path where the GPU driver is stored. +If not specified, we'll automatically choose from official GPU drivers.`, + }, + "data_disk_size_gb": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Description: `The size of the data disk in GB attached to this instance, +up to a maximum of 64000 GB (64 TB). +You can choose the size of the data disk based on how big your notebooks and data are. +If not specified, this defaults to 100.`, + }, + "data_disk_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: verify.ValidateEnum([]string{"DISK_TYPE_UNSPECIFIED", "PD_STANDARD", "PD_SSD", "PD_BALANCED", "PD_EXTREME", ""}), + Description: `Possible disk types for notebook instances. Possible values: ["DISK_TYPE_UNSPECIFIED", "PD_STANDARD", "PD_SSD", "PD_BALANCED", "PD_EXTREME"]`, + }, + "disk_encryption": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: verify.ValidateEnum([]string{"DISK_ENCRYPTION_UNSPECIFIED", "GMEK", "CMEK", ""}), + DiffSuppressFunc: tpgresource.EmptyOrDefaultStringSuppress("DISK_ENCRYPTION_UNSPECIFIED"), + Description: `Disk encryption method used on the boot and data disks, defaults to GMEK. Possible values: ["DISK_ENCRYPTION_UNSPECIFIED", "GMEK", "CMEK"]`, + }, + "install_gpu_driver": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `Whether the end user authorizes Google Cloud to install GPU driver +on this instance. If this field is empty or set to false, the GPU driver +won't be installed. Only applicable to instances with GPUs.`, + }, + "instance_owners": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `The list of owners of this instance after creation. +Format: alias@example.com. +Currently supports one owner only. +If not specified, all of the service account users of +your VM instance's service account can use the instance.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "kms_key": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `The KMS key used to encrypt the disks, only applicable if diskEncryption is CMEK. +Format: projects/{project_id}/locations/{location}/keyRings/{key_ring_id}/cryptoKeys/{key_id}`, + }, + "labels": { + Type: schema.TypeMap, + Computed: true, + Optional: true, + DiffSuppressFunc: NotebooksInstanceLabelDiffSuppress, + Description: `Labels to apply to this instance. These can be later modified by the setLabels method. +An object containing a list of "key": value pairs. Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "metadata": { + Type: schema.TypeMap, + Optional: true, + Description: `Custom metadata to apply to this instance. +An object containing a list of "key": value pairs. Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "network": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `The name of the VPC that this instance is in. +Format: projects/{project_id}/global/networks/{network_id}`, + }, + "nic_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: verify.ValidateEnum([]string{"UNSPECIFIED_NIC_TYPE", "VIRTIO_NET", "GVNIC", ""}), + Description: `The type of vNIC driver. Possible values: ["UNSPECIFIED_NIC_TYPE", "VIRTIO_NET", "GVNIC"]`, + }, + "no_proxy_access": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `The notebook instance will not register with the proxy..`, + }, + "no_public_ip": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `No public IP will be assigned to this instance.`, + }, + "no_remove_data_disk": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `If true, the data disk will not be auto deleted when deleting the instance.`, + }, + "post_startup_script": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `Path to a Bash script that automatically runs after a +notebook instance fully boots up. The path must be a URL +or Cloud Storage path (gs://path-to-file/file-name).`, + }, + "reservation_affinity": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `Reservation Affinity for consuming Zonal reservation.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "consume_reservation_type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: verify.ValidateEnum([]string{"NO_RESERVATION", "ANY_RESERVATION", "SPECIFIC_RESERVATION"}), + Description: `The type of Compute Reservation. Possible values: ["NO_RESERVATION", "ANY_RESERVATION", "SPECIFIC_RESERVATION"]`, + }, + "key": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `Corresponds to the label key of reservation resource.`, + }, + "values": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `Corresponds to the label values of reservation resource.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "service_account": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + Description: `The service account on this instance, giving access to other +Google Cloud services. You can use any service account within +the same project, but you must have the service account user +permission to use the instance. If not specified, +the Compute Engine default service account is used.`, + }, + "service_account_scopes": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `Optional. The URIs of service account scopes to be included in Compute Engine instances. +If not specified, the following scopes are defined: +- https://www.googleapis.com/auth/cloud-platform +- https://www.googleapis.com/auth/userinfo.email`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "shielded_instance_config": { + Type: schema.TypeList, + Computed: true, + Optional: true, + ForceNew: true, + Description: `A set of Shielded Instance options. Check [Images using supported Shielded VM features] +Not all combinations are valid`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_integrity_monitoring": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `Defines whether the instance has integrity monitoring enabled. Enables monitoring and attestation of the +boot integrity of the instance. The attestation is performed against the integrity policy baseline. +This baseline is initially derived from the implicitly trusted boot image when the instance is created. +Enabled by default.`, + Default: true, + }, + "enable_secure_boot": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `Defines whether the instance has Secure Boot enabled. Secure Boot helps ensure that the system only runs +authentic software by verifying the digital signature of all boot components, and halting the boot process +if signature verification fails. +Disabled by default.`, + }, + "enable_vtpm": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `Defines whether the instance has the vTPM enabled. +Enabled by default.`, + Default: true, + }, + }, + }, + }, + "subnet": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `The name of the subnet that this instance is in. +Format: projects/{project_id}/regions/{region}/subnetworks/{subnetwork_id}`, + }, + "tags": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `The Compute Engine tags to add to instance.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "vm_image": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `Use a Compute Engine VM image to start the notebook instance.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "project": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The name of the Google Cloud project that this VM image belongs to. +Format: projects/{project_id}`, + }, + "image_family": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `Use this VM image family to find the image; the newest image in this family will be used.`, + }, + "image_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `Use VM image name to find the image.`, + }, + }, + }, + ExactlyOneOf: []string{"vm_image", "container_image"}, + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `Instance creation time`, + }, + "proxy_uri": { + Type: schema.TypeString, + Computed: true, + Description: `The proxy endpoint that is used to access the Jupyter notebook. +Only returned when the resource is in a 'PROVISIONED' state. If +needed you can utilize 'terraform apply -refresh-only' to await +the population of this value.`, + }, + "state": { + Type: schema.TypeString, + Computed: true, + Description: `The state of this instance.`, + }, + "update_time": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `Instance update time.`, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + UseJSONNumber: true, + } +} + +func ResourceNotebooksInstanceUpgradeV0(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { + return tpgresource.LabelsStateUpgrade(rawState, notebooksInstanceGoogleProvidedLabel) +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/cloudrun/resource_cloud_run_domain_mapping_test.go b/mmv1/third_party/terraform/services/cloudrun/resource_cloud_run_domain_mapping_test.go index 743143b46db2..85232bd55fe3 100644 --- a/mmv1/third_party/terraform/services/cloudrun/resource_cloud_run_domain_mapping_test.go +++ b/mmv1/third_party/terraform/services/cloudrun/resource_cloud_run_domain_mapping_test.go @@ -29,7 +29,7 @@ func TestAccCloudRunDomainMapping_foregroundDeletion(t *testing.T) { ResourceName: "google_cloud_run_domain_mapping.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location", "status", "metadata.0.resource_version"}, + ImportStateVerifyIgnore: []string{"name", "location", "status", "metadata.0.labels", "metadata.0.terraform_labels", "metadata.0.resource_version"}, }, { Config: testAccCloudRunDomainMapping_cloudRunDomainMappingUpdated2(context), @@ -38,7 +38,7 @@ func TestAccCloudRunDomainMapping_foregroundDeletion(t *testing.T) { ResourceName: "google_cloud_run_domain_mapping.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location", "status", "metadata.0.resource_version"}, + ImportStateVerifyIgnore: []string{"name", "location", "status", "metadata.0.labels", "metadata.0.terraform_labels", "metadata.0.resource_version"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/cloudrun/resource_cloud_run_service_test.go.erb b/mmv1/third_party/terraform/services/cloudrun/resource_cloud_run_service_test.go.erb index a0f84d5ebb97..7dcd04a4a01c 100644 --- a/mmv1/third_party/terraform/services/cloudrun/resource_cloud_run_service_test.go.erb +++ b/mmv1/third_party/terraform/services/cloudrun/resource_cloud_run_service_test.go.erb @@ -27,7 +27,7 @@ func TestAccCloudRunService_cloudRunServiceUpdate(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, { Config: testAccCloudRunService_cloudRunServiceUpdate(name, project, "50", "300"), @@ -36,7 +36,7 @@ func TestAccCloudRunService_cloudRunServiceUpdate(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, }, }) @@ -61,7 +61,7 @@ func TestAccCloudRunService_cloudRunServiceCreateHasStatus(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels"}, }, }, }) @@ -85,7 +85,7 @@ func TestAccCloudRunService_foregroundDeletion(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, { Config: " ", // very explicitly add a space, as the test runner fails if this is just "" @@ -97,7 +97,7 @@ func TestAccCloudRunService_foregroundDeletion(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, }, }) @@ -110,10 +110,14 @@ resource "google_cloud_run_service" "default" { location = "us-central1" metadata { - namespace = "%s" - annotations = { + namespace = "%s" + annotations = { generated-by = "magic-modules" } + labels = { + env = "foo" + default_expiration_ms = 3600000 + } } template { @@ -161,7 +165,7 @@ func TestAccCloudRunService_secretVolume(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, { Config: testAccCloudRunService_cloudRunServiceUpdateWithSecretVolume(name, project, "secret-"+acctest.RandString(t, 10), "secret-"+acctest.RandString(t, 11), "google_secret_manager_secret.secret2.secret_id"), @@ -170,7 +174,7 @@ func TestAccCloudRunService_secretVolume(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, }, }) @@ -285,7 +289,7 @@ func TestAccCloudRunService_secretEnvironmentVariable(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, { Config: testAccCloudRunService_cloudRunServiceUpdateWithSecretEnvVar(name, project, "secret-"+acctest.RandString(t, 10), "secret-"+acctest.RandString(t, 11), "google_secret_manager_secret.secret2.secret_id"), @@ -294,7 +298,7 @@ func TestAccCloudRunService_secretEnvironmentVariable(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, }, }) @@ -387,6 +391,314 @@ resource "google_cloud_run_service" "default" { `, secretName1, secretName2, name, secretRef, project) } +func TestAccCloudRunService_withProviderDefaultLabels(t *testing.T) { + // The test failed if VCR testing is enabled, because the cached provider config is used. + // With the cached provider config, any changes in the provider default labels will not be applied. + acctest.SkipIfVcr(t) + t.Parallel() + + context := map[string]interface{}{ + "project": envvar.GetTestProjectFromEnv(), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccCloudRunService_withProviderDefaultLabels(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.%", "2"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.env", "foo"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.%", "3"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.default_key1", "default_value1"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.env", "foo"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.effective_labels.%", "4"), + + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.annotations.%", "1"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.annotations.generated-by", "magic-modules"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.effective_annotations.%", "6"), + ), + }, + { + ResourceName: "google_cloud_run_service.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, + }, + { + Config: testAccCloudRunService_resourceLabelsOverridesProviderDefaultLabels(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.%", "3"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.env", "foo"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.default_expiration_ms", "3600000"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.default_key1", "value1"), + + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.%", "3"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.default_key1", "value1"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.env", "foo"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.effective_labels.%", "4"), + + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.annotations.%", "1"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.annotations.generated-by", "magic-modules-update"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.effective_annotations.%", "6"), + ), + }, + { + ResourceName: "google_cloud_run_service.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, + }, + { + Config: testAccCloudRunService_moveResourceLabelToProviderDefaultLabels(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.%", "2"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.default_expiration_ms", "3600000"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.default_key1", "value1"), + + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.%", "3"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.default_key1", "value1"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.env", "foo"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.effective_labels.%", "4"), + ), + }, + { + ResourceName: "google_cloud_run_service.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, + }, + { + Config: testAccCloudRunService_resourceLabelsOverridesProviderDefaultLabels(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.%", "3"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.env", "foo"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.default_expiration_ms", "3600000"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.default_key1", "value1"), + + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.%", "3"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.default_key1", "value1"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.env", "foo"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.effective_labels.%", "4"), + ), + }, + { + ResourceName: "google_cloud_run_service.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, + }, + { + Config: testAccCloudRunService_cloudRunServiceBasic(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckNoResourceAttr("google_cloud_run_service.default", "metadata.0.labels.%"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.effective_labels.%", "1"), + + resource.TestCheckNoResourceAttr("google_cloud_run_service.default", "metadata.0.annotations.%"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.effective_annotations.%", "5"), + ), + }, + { + ResourceName: "google_cloud_run_service.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, + }, + }, + }) +} + +func TestAccCloudRunServiceMigration_withLabels(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + name := "tftest-cloudrun-" + acctest.RandString(t, 6) + project := envvar.GetTestProjectFromEnv() + oldVersion := map[string]resource.ExternalProvider{ + "google": { + VersionConstraint: "4.83.0", // a version that doesn't separate user defined labels and system labels + Source: "registry.terraform.io/hashicorp/google", + }, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + Steps: []resource.TestStep{ + { + Config: testAccCloudRunService_cloudRunServiceUpdate(name, project, "10", "600"), + ExternalProviders: oldVersion, + }, + { + Config: testAccCloudRunService_cloudRunServiceUpdate(name, project, "10", "600"), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.%", "2"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.effective_labels.%", "3"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.annotations.%", "1"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.effective_annotations.%", "6"), + ), + }, + }, + }) +} + +func testAccCloudRunService_withProviderDefaultLabels(context map[string]interface{}) string { + return acctest.Nprintf(` +provider "google" { + default_labels = { + default_key1 = "default_value1" + } +} + +resource "google_cloud_run_service" "default" { + name = "tf-test-cloudrun-srv%{random_suffix}" + location = "us-central1" + + template { + spec { + containers { + image = "us-docker.pkg.dev/cloudrun/container/hello" + } + } + } + + metadata { + namespace = "%{project}" + annotations = { + generated-by = "magic-modules" + } + labels = { + env = "foo" + default_expiration_ms = 3600000 + } + } + + traffic { + percent = 100 + latest_revision = true + } +} +`, context) +} + +func testAccCloudRunService_resourceLabelsOverridesProviderDefaultLabels(context map[string]interface{}) string { + return acctest.Nprintf(` +provider "google" { + default_labels = { + default_key1 = "default_value1" + } +} + +resource "google_cloud_run_service" "default" { + name = "tf-test-cloudrun-srv%{random_suffix}" + location = "us-central1" + + template { + spec { + containers { + image = "us-docker.pkg.dev/cloudrun/container/hello" + } + } + } + + metadata { + namespace = "%{project}" + annotations = { + generated-by = "magic-modules-update" + } + labels = { + env = "foo" + default_expiration_ms = 3600000 + default_key1 = "value1" + } + } + + traffic { + percent = 100 + latest_revision = true + } +} +`, context) +} + +func testAccCloudRunService_moveResourceLabelToProviderDefaultLabels(context map[string]interface{}) string { + return acctest.Nprintf(` +provider "google" { + default_labels = { + default_key1 = "default_value1" + env = "foo" + } +} + +resource "google_cloud_run_service" "default" { + name = "tf-test-cloudrun-srv%{random_suffix}" + location = "us-central1" + + template { + spec { + containers { + image = "us-docker.pkg.dev/cloudrun/container/hello" + } + } + } + + metadata { + namespace = "%{project}" + annotations = { + generated-by = "magic-modules" + } + labels = { + default_expiration_ms = 3600000 + default_key1 = "value1" + } + } + + traffic { + percent = 100 + latest_revision = true + } +} +`, context) +} + +func testAccCloudRunService_cloudRunServiceBasic(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_cloud_run_service" "default" { + name = "tf-test-cloudrun-srv%{random_suffix}" + location = "us-central1" + + template { + spec { + containers { + image = "us-docker.pkg.dev/cloudrun/container/hello" + } + } + } + + metadata { + namespace = "%{project}" + } + + traffic { + percent = 100 + latest_revision = true + } +} +`, context) +} + <% unless version == 'ga' -%> func TestAccCloudRunService_probes(t *testing.T) { @@ -406,7 +718,7 @@ func TestAccCloudRunService_probes(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, { Config: testAccCloudRunService_cloudRunServiceUpdateWithTCPStartupProbeAndHTTPLivenessProbe(name, project, "2", "1", "5", "2"), @@ -415,7 +727,7 @@ func TestAccCloudRunService_probes(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, { Config: testAccCloudRunService_cloudRunServiceUpdateWithEmptyHTTPStartupProbe(name, project), @@ -424,7 +736,7 @@ func TestAccCloudRunService_probes(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, { Config: testAccCloudRunService_cloudRunServiceUpdateWithHTTPStartupProbe(name, project), @@ -433,7 +745,7 @@ func TestAccCloudRunService_probes(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, { Config: testAccCloudRunService_cloudRunServiceUpdateWithEmptyGRPCLivenessProbe(name, project), @@ -442,7 +754,7 @@ func TestAccCloudRunService_probes(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, { Config: testAccCloudRunService_cloudRunServiceUpdateWithGRPCLivenessProbe(name, project), @@ -451,7 +763,7 @@ func TestAccCloudRunService_probes(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job.go.erb b/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job.go.erb index ee9b855f3dee..5d3e995c83b8 100644 --- a/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job.go.erb +++ b/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job.go.erb @@ -33,11 +33,20 @@ func ResourceDataflowFlexTemplateJob() *schema.Resource { Update: resourceDataflowFlexTemplateJobUpdate, Delete: resourceDataflowFlexTemplateJobDelete, CustomizeDiff: customdiff.All( + tpgresource.SetLabelsDiff, resourceDataflowFlexJobTypeCustomizeDiff, ), Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, + SchemaVersion: 1, + StateUpgraders: []schema.StateUpgrader{ + { + Type: resourceDataflowFlexTemplateJobResourceV0().CoreConfigSchema().ImpliedType(), + Upgrade: ResourceDataflowFlexTemplateJobStateUpgradeV0, + Version: 0, + }, + }, Schema: map[string]*schema.Schema{ "container_spec_gcs_path": { @@ -75,8 +84,22 @@ func ResourceDataflowFlexTemplateJob() *schema.Resource { "labels": { Type: schema.TypeMap, Optional: true, - DiffSuppressFunc: resourceDataflowJobLabelDiffSuppress, - Description: `User labels to be specified for the job. Keys and values should follow the restrictions specified in the labeling restrictions page. NOTE: Google-provided Dataflow templates often provide default labels that begin with goog-dataflow-provided. Unless explicitly set in config, these labels will be ignored to prevent diffs on re-apply.`, + Description: `User labels to be specified for the job. Keys and values should follow the restrictions specified in the labeling restrictions page. NOTE: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field 'effective_labels' for all of the labels present on the resource.`, + }, + + "terraform_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `The combination of labels configured directly on the resource and default labels configured on the provider.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + + "effective_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, + Elem: &schema.Schema{Type: schema.TypeString}, }, "parameters": { @@ -353,7 +376,7 @@ func resourceDataflowFlexJobSetupEnv(d *schema.ResourceData, config *transport_t launcherMachineType, updatedParameters := dataflowFlexJobTypeTransferVar("launcher_machine_type", "launcherMachineType", updatedParameters, d) env := dataflow.FlexTemplateRuntimeEnvironment{ - AdditionalUserLabels: tpgresource.ExpandStringMap(d, "labels"), + AdditionalUserLabels: tpgresource.ExpandStringMap(d, "effective_labels"), AutoscalingAlgorithm: autoscalingAlgorithm, NumWorkers: int64(numWorkers), MaxWorkers: int64(maxNumWorkers), @@ -413,9 +436,15 @@ func resourceDataflowFlexTemplateJobRead(d *schema.ResourceData, meta interface{ if err := d.Set("project", project); err != nil { return fmt.Errorf("Error setting project: %s", err) } - if err := d.Set("labels", job.Labels); err != nil { + if err := tpgresource.SetLabels(job.Labels, d, "labels"); err != nil { return fmt.Errorf("Error setting labels: %s", err) } + if err := tpgresource.SetLabels(job.Labels, d, "terraform_labels"); err != nil { + return fmt.Errorf("Error setting terraform_labels: %s", err) + } + if err := d.Set("effective_labels", job.Labels); err != nil { + return fmt.Errorf("Error setting effective_labels: %s", err) + } if err := d.Set("kms_key_name", job.Environment.ServiceKmsKeyName); err != nil { return fmt.Errorf("Error setting kms_key_name: %s", err) } @@ -759,12 +788,8 @@ func resourceDataflowFlexJobTypeCustomizeDiff(_ context.Context, d *schema.Resou if field == "on_delete" { continue } - // Labels map will likely have suppressed changes, so we check each key instead of the parent field - if field == "labels" { - if err := resourceDataflowJobIterateMapForceNew(field, d); err != nil { - return err - } - } else if d.HasChange(field) { + + if field != "labels" && field != "terraform_labels" && d.HasChange(field) { if err := d.ForceNew(field); err != nil { return err } diff --git a/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job_migrate.go.erb b/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job_migrate.go.erb new file mode 100644 index 000000000000..aa0c11361713 --- /dev/null +++ b/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job_migrate.go.erb @@ -0,0 +1,205 @@ +<% autogen_exception -%> +package dataflow +<% unless version == 'ga' -%> + +import ( + "context" + + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func resourceDataflowFlexTemplateJobResourceV0() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "container_spec_gcs_path": { + Type: schema.TypeString, + Required: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "region": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + Description: `The region in which the created job should run.`, + }, + + "transform_name_mapping": { + Type: schema.TypeMap, + Optional: true, + Description: `Only applicable when updating a pipeline. Map of transform name prefixes of the job to be replaced with the corresponding name prefixes of the new job.`, + }, + + "on_delete": { + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{"cancel", "drain"}, false), + Optional: true, + Default: "cancel", + }, + + "labels": { + Type: schema.TypeMap, + Optional: true, + DiffSuppressFunc: resourceDataflowJobLabelDiffSuppress, + Description: `User labels to be specified for the job. Keys and values should follow the restrictions specified in the labeling restrictions page. NOTE: Google-provided Dataflow templates often provide default labels that begin with goog-dataflow-provided. Unless explicitly set in config, these labels will be ignored to prevent diffs on re-apply.`, + }, + + "parameters": { + Type: schema.TypeMap, + Optional: true, + }, + + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + + "job_id": { + Type: schema.TypeString, + Computed: true, + }, + + "state": { + Type: schema.TypeString, + Computed: true, + }, + + "type": { + Type: schema.TypeString, + Computed: true, + Description: `The type of this job, selected from the JobType enum.`, + }, + + "num_workers": { + Type: schema.TypeInt, + Optional: true, + // ForceNew applies to both stream and batch jobs + ForceNew: true, + Description: `The initial number of Google Compute Engine instances for the job.`, + }, + + "max_workers": { + Type: schema.TypeInt, + Optional: true, + // ForceNew applies to both stream and batch jobs + ForceNew: true, + Description: `The maximum number of Google Compute Engine instances to be made available to your pipeline during execution, from 1 to 1000.`, + }, + + "service_account_email": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `The Service Account email used to create the job.`, + }, + + "temp_location": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `The Cloud Storage path to use for temporary files. Must be a valid Cloud Storage URL, beginning with gs://.`, + }, + + "staging_location": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `The Cloud Storage path to use for staging files. Must be a valid Cloud Storage URL, beginning with gs://.`, + }, + + "sdk_container_image": { + Type: schema.TypeString, + Optional: true, + Description: `Docker registry location of container image to use for the 'worker harness. Default is the container for the version of the SDK. Note this field is only valid for portable pipelines.`, + }, + + "network": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `The network to which VMs will be assigned. If it is not provided, "default" will be used.`, + }, + + "subnetwork": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `The subnetwork to which VMs will be assigned. Should be of the form "regions/REGION/subnetworks/SUBNETWORK".`, + }, + + "machine_type": { + Type: schema.TypeString, + Optional: true, + Description: `The machine type to use for the job.`, + }, + + "kms_key_name": { + Type: schema.TypeString, + Optional: true, + Description: `The name for the Cloud KMS key for the job. Key format is: projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY`, + }, + + "ip_configuration": { + Type: schema.TypeString, + Optional: true, + Description: `The configuration for VM IPs. Options are "WORKER_IP_PUBLIC" or "WORKER_IP_PRIVATE".`, + ValidateFunc: validation.StringInSlice([]string{"WORKER_IP_PUBLIC", "WORKER_IP_PRIVATE"}, false), + }, + + "additional_experiments": { + Type: schema.TypeSet, + Optional: true, + Computed: true, + Description: `List of experiments that should be used by the job. An example value is ["enable_stackdriver_agent_metrics"].`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "enable_streaming_engine": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `Indicates if the job should use the streaming engine feature.`, + }, + + "autoscaling_algorithm": { + Type: schema.TypeString, + Optional: true, + Description: `The algorithm to use for autoscaling`, + }, + + "launcher_machine_type": { + Type: schema.TypeString, + Optional: true, + Description: `The machine type to use for launching the job. The default is n1-standard-1.`, + }, + + "skip_wait_on_job_termination": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: `If true, treat DRAINING and CANCELLING as terminal job states and do not wait for further changes before removing from terraform state and moving on. WARNING: this will lead to job name conflicts if you do not ensure that the job names are different, e.g. by embedding a release ID or by using a random_id.`, + }, + }, + UseJSONNumber: true, + } +} + +func ResourceDataflowFlexTemplateJobStateUpgradeV0(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { + return tpgresource.LabelsStateUpgrade(rawState, resourceDataflowJobGoogleLabelPrefix) +} + +<% end -%> \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job_test.go.erb b/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job_test.go.erb index cfeb2af3cbed..2c29df864833 100644 --- a/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job_test.go.erb +++ b/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job_test.go.erb @@ -44,7 +44,7 @@ func TestAccDataflowFlexTemplateJob_basic(t *testing.T) { ResourceName: "google_dataflow_flex_template_job.flex_job", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path"}, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, }, }, }) @@ -83,7 +83,7 @@ func TestAccDataflowFlexTemplateJob_streamUpdate(t *testing.T) { ResourceName: "google_dataflow_flex_template_job.flex_job", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "transform_name_mapping", "state", "container_spec_gcs_path"}, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "transform_name_mapping", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, }, }, }) @@ -145,7 +145,7 @@ func TestAccDataflowFlexTemplateJob_FullUpdate(t *testing.T) { ResourceName: "google_dataflow_flex_template_job.flex_job_fullupdate", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path"}, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, }, { Config: testAccDataflowFlexTemplateJob_dataflowFlexTemplateJobFullUpdate(job, bucket, topic), @@ -154,7 +154,7 @@ func TestAccDataflowFlexTemplateJob_FullUpdate(t *testing.T) { ResourceName: "google_dataflow_flex_template_job.flex_job_fullupdate", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path"}, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, }, }, }) @@ -189,7 +189,7 @@ func TestAccDataflowFlexTemplateJob_withNetwork(t *testing.T) { ResourceName: "google_dataflow_flex_template_job.flex_job_network", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path"}, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, }, { Config: testAccDataflowFlexTemplateJob_networkUpdate(job, network1, network2, bucket, topic), @@ -202,7 +202,7 @@ func TestAccDataflowFlexTemplateJob_withNetwork(t *testing.T) { ResourceName: "google_dataflow_flex_template_job.flex_job_network", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path"}, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, }, }, }) @@ -238,7 +238,7 @@ func TestAccDataflowFlexTemplateJob_withSubNetwork(t *testing.T) { ResourceName: "google_dataflow_flex_template_job.flex_job_subnetwork", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path"}, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, }, { Config: testAccDataflowFlexTemplateJob_subnetworkUpdate(job, network, subnetwork1, subnetwork2, bucket, topic), @@ -251,7 +251,7 @@ func TestAccDataflowFlexTemplateJob_withSubNetwork(t *testing.T) { ResourceName: "google_dataflow_flex_template_job.flex_job_subnetwork", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path"}, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, }, }, }) @@ -285,7 +285,7 @@ func TestAccDataflowFlexTemplateJob_withIpConfig(t *testing.T) { ResourceName: "google_dataflow_flex_template_job.flex_job_ipconfig", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "ip_configuration", "state", "container_spec_gcs_path"}, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "ip_configuration", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, }, }, }) @@ -319,7 +319,7 @@ func TestAccDataflowFlexTemplateJob_withKmsKey(t *testing.T) { ResourceName: "google_dataflow_flex_template_job.flex_job_kms", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path"}, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, }, }, }) @@ -353,7 +353,87 @@ func TestAccDataflowFlexTemplateJob_withAdditionalExperiments(t *testing.T) { ResourceName: "google_dataflow_flex_template_job.flex_job_experiments", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "additional_experiments", "container_spec_gcs_path"}, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "additional_experiments", "container_spec_gcs_path", "labels", "terraform_labels"}, + }, + }, + }) +} + +func TestAccDataflowFlexTemplateJob_withProviderDefaultLabels(t *testing.T) { + // This resource uses custom retry logic that cannot be sped up without + // modifying the actual resource + acctest.SkipIfVcr(t) + t.Parallel() + + randStr := acctest.RandString(t, 10) + job := "tf-test-dataflow-job-" + randStr + bucket := "tf-test-dataflow-bucket-" + randStr + topic := "tf-test-topic" + randStr + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckDataflowJobDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDataflowFlexTemplateJob_withProviderDefaultLabels(job, bucket, topic), + Check: resource.ComposeTestCheckFunc( + testAccDataflowFlexJobExists(t, "google_dataflow_flex_template_job.flex_job_fullupdate", false), + ), + }, + { + ResourceName: "google_dataflow_flex_template_job.flex_job_fullupdate", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, + }, + { + Config: testAccComputeAddress_resourceLabelsOverridesProviderDefaultLabels(job, bucket, topic), + Check: resource.ComposeTestCheckFunc( + testAccDataflowFlexJobExists(t, "google_dataflow_flex_template_job.flex_job_fullupdate", false), + ), + }, + { + ResourceName: "google_dataflow_flex_template_job.flex_job_fullupdate", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, + }, + { + Config: testAccComputeAddress_moveResourceLabelToProviderDefaultLabels(job, bucket, topic), + Check: resource.ComposeTestCheckFunc( + testAccDataflowFlexJobExists(t, "google_dataflow_flex_template_job.flex_job_fullupdate", false), + ), + }, + { + ResourceName: "google_dataflow_flex_template_job.flex_job_fullupdate", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, + }, + { + Config: testAccComputeAddress_resourceLabelsOverridesProviderDefaultLabels(job, bucket, topic), + Check: resource.ComposeTestCheckFunc( + testAccDataflowFlexJobExists(t, "google_dataflow_flex_template_job.flex_job_fullupdate", false), + ), + }, + { + ResourceName: "google_dataflow_flex_template_job.flex_job_fullupdate", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, + }, + { + Config: testAccDataflowFlexTemplateJob_dataflowFlexTemplateJobFull(job, bucket, topic), + Check: resource.ComposeTestCheckFunc( + testAccDataflowFlexJobExists(t, "google_dataflow_flex_template_job.flex_job_fullupdate", false), + ), + }, + { + ResourceName: "google_dataflow_flex_template_job.flex_job_fullupdate", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, }, }, }) @@ -1187,6 +1267,260 @@ resource "google_dataflow_flex_template_job" "flex_job_experiments" { `, topicName, bucket, job, strings.Join(experiments, `", "`)) } +func testAccDataflowFlexTemplateJob_withProviderDefaultLabels(job, bucket, topicName string) string { + return fmt.Sprintf(` + +provider "google" { + default_labels = { + default_key1 = "default_value1" + } +} + +data "google_project" "project" {} + +resource "google_pubsub_topic" "example" { + name = "%s" +} + +resource "google_service_account" "dataflow-sa" { + count = 2 + account_id = "dataflow-sa-${count.index}" + display_name = "DataFlow Service Account" +} + +resource "google_project_iam_member" "dataflow-worker" { + count = 2 + project = data.google_project.project.project_id + role = "roles/dataflow.worker" + member = "serviceAccount:${google_service_account.dataflow-sa[count.index].email}" +} + +resource "google_project_iam_member" "dataflow-storage" { + count = 2 + project = data.google_project.project.project_id + role = "roles/storage.admin" + member = "serviceAccount:${google_service_account.dataflow-sa[count.index].email}" +} + +data "google_storage_bucket_object" "flex_template" { + name = "latest/flex/Streaming_Data_Generator" + bucket = "dataflow-templates" +} + +resource "google_storage_bucket" "bucket" { + name = "%s" + location = "US-CENTRAL1" + force_destroy = true + uniform_bucket_level_access = true +} + +resource "google_storage_bucket_object" "schema" { + name = "schema.json" + bucket = google_storage_bucket.bucket.name + content = < package dataproc import ( @@ -117,7 +116,8 @@ var ( } ) -const resourceDataprocGoogleProvidedLabelPrefix = "labels.goog-dataproc" +const resourceDataprocGoogleLabelPrefix = "goog-dataproc" +const resourceDataprocGoogleProvidedLabelPrefix = "labels." + resourceDataprocGoogleLabelPrefix func resourceDataprocLabelDiffSuppress(k, old, new string, d *schema.ResourceData) bool { if strings.HasPrefix(k, resourceDataprocGoogleProvidedLabelPrefix) && new == "" { @@ -165,8 +165,18 @@ func ResourceDataprocCluster() *schema.Resource { CustomizeDiff: customdiff.All( tpgresource.DefaultProviderProject, + tpgresource.SetLabelsDiff, ), + SchemaVersion: 1, + StateUpgraders: []schema.StateUpgrader{ + { + Type: resourceDataprocClusterResourceV0().CoreConfigSchema().ImpliedType(), + Upgrade: ResourceDataprocClusterStateUpgradeV0, + Version: 0, + }, + }, + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, @@ -223,10 +233,24 @@ func ResourceDataprocCluster() *schema.Resource { Type: schema.TypeMap, Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, - // GCP automatically adds labels - DiffSuppressFunc: resourceDataprocLabelDiffSuppress, + Description: `The list of the labels (key/value pairs) configured on the resource and to be applied to instances in the cluster. + + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field 'effective_labels' for all of the labels present on the resource.`, + }, + + "terraform_labels": { + Type: schema.TypeMap, Computed: true, - Description: `The list of labels (key/value pairs) to be applied to instances in the cluster. GCP generates some itself including goog-dataproc-cluster-name which is the name of the cluster.`, + Description: `The combination of labels configured directly on the resource and default labels configured on the provider.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + + "effective_labels": { + Type: schema.TypeMap, + Elem: &schema.Schema{Type: schema.TypeString}, + Computed: true, + Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, }, "virtual_cluster_config": { @@ -701,10 +725,10 @@ func ResourceDataprocCluster() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "node_group_uri": { - Type: schema.TypeString, - ForceNew: true, - Required: true, - Description: `The URI of a sole-tenant that the cluster will be created on.`, + Type: schema.TypeString, + ForceNew: true, + Required: true, + Description: `The URI of a sole-tenant that the cluster will be created on.`, DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, }, }, @@ -743,8 +767,8 @@ func ResourceDataprocCluster() *schema.Resource { // "machine_type": { ... } // "min_cpu_platform": { ... } "preemptibility": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, Description: `Specifies the preemptibility of the secondary nodes. Defaults to PREEMPTIBLE.`, AtLeastOneOf: []string{ "cluster_config.0.preemptible_worker_config.0.num_instances", @@ -1025,22 +1049,22 @@ by Dataproc`, }, }, "metastore_config": { - Type: schema.TypeList, - Optional: true, - AtLeastOneOf: clusterConfigKeys, - MaxItems: 1, - Description: `Specifies a Metastore configuration.`, + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: clusterConfigKeys, + MaxItems: 1, + Description: `Specifies a Metastore configuration.`, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "dataproc_metastore_service": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - Description: `Resource name of an existing Dataproc Metastore service.`, + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `Resource name of an existing Dataproc Metastore service.`, }, }, }, - }, + }, "lifecycle_config": { Type: schema.TypeList, Optional: true, @@ -1105,18 +1129,18 @@ by Dataproc`, }, "dataproc_metric_config": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Description: `The config for Dataproc metrics.`, + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: `The config for Dataproc metrics.`, AtLeastOneOf: clusterConfigKeys, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "metrics": { - Type: schema.TypeList, - Required: true, - Description: `Metrics sources to enable.`, - Elem: metricsSchema(), + Type: schema.TypeList, + Required: true, + Description: `Metrics sources to enable.`, + Elem: metricsSchema(), }, }, }, @@ -1131,7 +1155,7 @@ by Dataproc`, // We need to pull metrics' schema out so we can use it to make a set hash func func metricsSchema() *schema.Resource { - return &schema.Resource{ + return &schema.Resource{ Schema: map[string]*schema.Schema{ "metric_source": { Type: schema.TypeString, @@ -1141,11 +1165,11 @@ func metricsSchema() *schema.Resource { Description: `A source for the collection of Dataproc OSS metrics (see [available OSS metrics] (https://cloud.google.com//dataproc/docs/guides/monitoring#available_oss_metrics)).`, }, "metric_overrides": { - Type: schema.TypeSet, - Elem: &schema.Schema{Type: schema.TypeString}, - Optional: true, - ForceNew: true, - Description: `Specify one or more [available OSS metrics] (https://cloud.google.com/dataproc/docs/guides/monitoring#available_oss_metrics) to collect.`, + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + ForceNew: true, + Description: `Specify one or more [available OSS metrics] (https://cloud.google.com/dataproc/docs/guides/monitoring#available_oss_metrics) to collect.`, }, }, } @@ -1252,8 +1276,8 @@ func instanceConfigSchema(parent string) *schema.Schema { "cluster_config.0." + parent + ".0.disk_config.0.boot_disk_size_gb", "cluster_config.0." + parent + ".0.disk_config.0.boot_disk_type", }, - ForceNew: true, - Default: "pd-standard", + ForceNew: true, + Default: "pd-standard", }, }, }, @@ -1303,7 +1327,7 @@ func acceleratorsSchema() *schema.Resource { func resourceDataprocClusterCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) - userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) if err != nil { return err } @@ -1329,8 +1353,8 @@ func resourceDataprocClusterCreate(d *schema.ResourceData, meta interface{}) err return err } - if _, ok := d.GetOk("labels"); ok { - cluster.Labels = tpgresource.ExpandLabels(d) + if _, ok := d.GetOk("effective_labels"); ok { + cluster.Labels = tpgresource.ExpandEffectiveLabels(d) } // Checking here caters for the case where the user does not specify cluster_config @@ -1834,7 +1858,7 @@ func expandDataprocMetricConfig(cfg map[string]interface{}) *dataproc.DataprocMe for _, raw := range metricsConfigs { data := raw.(map[string]interface{}) metric := dataproc.Metric{ - MetricSource: data["metric_source"].(string), + MetricSource: data["metric_source"].(string), MetricOverrides: tpgresource.ConvertStringSet(data["metric_overrides"].(*schema.Set)), } metricsSet = append(metricsSet, &metric) @@ -1953,7 +1977,7 @@ func expandAccelerators(configured []interface{}) []*dataproc.AcceleratorConfig func resourceDataprocClusterUpdate(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) - userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) if err != nil { return err } @@ -1974,8 +1998,8 @@ func resourceDataprocClusterUpdate(d *schema.ResourceData, meta interface{}) err updMask := []string{} - if d.HasChange("labels") { - v := d.Get("labels") + if d.HasChange("effective_labels") { + v := d.Get("effective_labels") m := make(map[string]string) for k, val := range v.(map[string]interface{}) { m[k] = val.(string) @@ -2060,7 +2084,7 @@ func resourceDataprocClusterUpdate(d *schema.ResourceData, meta interface{}) err func resourceDataprocClusterRead(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) - userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) if err != nil { return err } @@ -2088,10 +2112,19 @@ func resourceDataprocClusterRead(d *schema.ResourceData, meta interface{}) error if err := d.Set("region", region); err != nil { return fmt.Errorf("Error setting region: %s", err) } - if err := d.Set("labels", cluster.Labels); err != nil { + + if err := tpgresource.SetLabels(cluster.Labels, d, "labels"); err != nil { return fmt.Errorf("Error setting labels: %s", err) } + if err := tpgresource.SetLabels(cluster.Labels, d, "terraform_labels"); err != nil { + return fmt.Errorf("Error setting terraform_labels: %s", err) + } + + if err := d.Set("effective_labels", cluster.Labels); err != nil { + return fmt.Errorf("Error setting effective_labels: %s", err) + } + var cfg []map[string]interface{} cfg, err = flattenClusterConfig(d, cluster.Config) @@ -2372,7 +2405,7 @@ func flattenDataprocMetricConfig(d *schema.ResourceData, dmc *dataproc.DataprocM metricsTypeList := schema.NewSet(schema.HashResource(metricsSchema()), []interface{}{}).List() for _, metric := range dmc.Metrics { data := map[string]interface{}{ - "metric_source": metric.MetricSource, + "metric_source": metric.MetricSource, "metric_overrides": metric.MetricOverrides, } @@ -2464,16 +2497,16 @@ func flattenGceClusterConfig(d *schema.ResourceData, gcc *dataproc.GceClusterCon if gcc.ReservationAffinity != nil { gceConfig["reservation_affinity"] = []map[string]interface{}{ { - "consume_reservation_type": gcc.ReservationAffinity.ConsumeReservationType, - "key": gcc.ReservationAffinity.Key, - "values": gcc.ReservationAffinity.Values, + "consume_reservation_type": gcc.ReservationAffinity.ConsumeReservationType, + "key": gcc.ReservationAffinity.Key, + "values": gcc.ReservationAffinity.Values, }, } } if gcc.NodeGroupAffinity != nil { gceConfig["node_group_affinity"] = []map[string]interface{}{ { - "node_group_uri": gcc.NodeGroupAffinity.NodeGroupUri, + "node_group_uri": gcc.NodeGroupAffinity.NodeGroupUri, }, } } @@ -2549,7 +2582,7 @@ func extractInitTimeout(t string) (int, error) { func resourceDataprocClusterDelete(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) - userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) if err != nil { return err } diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_migrate.go b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_migrate.go new file mode 100644 index 000000000000..11a640e76c69 --- /dev/null +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_migrate.go @@ -0,0 +1,981 @@ +package dataproc + +import ( + "context" + "fmt" + "regexp" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + + "github.com/hashicorp/terraform-provider-google/google/tpgresource" +) + +func resourceDataprocClusterResourceV0() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The name of the cluster, unique within the project and zone.`, + ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + + if len(value) > 55 { + errors = append(errors, fmt.Errorf( + "%q cannot be longer than 55 characters", k)) + } + if !regexp.MustCompile("^[a-z0-9-]+$").MatchString(value) { + errors = append(errors, fmt.Errorf( + "%q can only contain lowercase letters, numbers and hyphens", k)) + } + if !regexp.MustCompile("^[a-z]").MatchString(value) { + errors = append(errors, fmt.Errorf( + "%q must start with a letter", k)) + } + if !regexp.MustCompile("[a-z0-9]$").MatchString(value) { + errors = append(errors, fmt.Errorf( + "%q must end with a number or a letter", k)) + } + return + }, + }, + + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: `The ID of the project in which the cluster will exist. If it is not provided, the provider project is used.`, + }, + + "region": { + Type: schema.TypeString, + Optional: true, + Default: "global", + ForceNew: true, + Description: `The region in which the cluster and associated nodes will be created in. Defaults to global.`, + }, + + "graceful_decommission_timeout": { + Type: schema.TypeString, + Optional: true, + Default: "0s", + Description: `The timeout duration which allows graceful decomissioning when you change the number of worker nodes directly through a terraform apply`, + }, + + "labels": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + // GCP automatically adds labels + DiffSuppressFunc: resourceDataprocLabelDiffSuppress, + Computed: true, + Description: `The list of labels (key/value pairs) to be applied to instances in the cluster. GCP generates some itself including goog-dataproc-cluster-name which is the name of the cluster.`, + }, + + "virtual_cluster_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `The virtual cluster config is used when creating a Dataproc cluster that does not directly control the underlying compute resources, for example, when creating a Dataproc-on-GKE cluster. Dataproc may set default values, and values may change when clusters are updated. Exactly one of config or virtualClusterConfig must be specified.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "staging_bucket": { + Type: schema.TypeString, + Optional: true, + AtLeastOneOf: virtualClusterConfigKeys, + ForceNew: true, + Description: `A Cloud Storage bucket used to stage job dependencies, config files, and job driver console output. If you do not specify a staging bucket, Cloud Dataproc will determine a Cloud Storage location (US, ASIA, or EU) for your cluster's staging bucket according to the Compute Engine zone where your cluster is deployed, and then create and manage this project-level, per-location bucket.`, + }, + + "auxiliary_services_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + AtLeastOneOf: virtualClusterConfigKeys, + Description: `Auxiliary services configuration for a Cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "metastore_config": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + AtLeastOneOf: auxiliaryServicesConfigKeys, + Description: `The Hive Metastore configuration for this workload.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "dataproc_metastore_service": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + AtLeastOneOf: auxiliaryServicesMetastoreConfigKeys, + Description: `The Hive Metastore configuration for this workload.`, + }, + }, + }, + }, + + "spark_history_server_config": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + AtLeastOneOf: auxiliaryServicesConfigKeys, + Description: `The Spark History Server configuration for the workload.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "dataproc_cluster": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + AtLeastOneOf: auxiliaryServicesSparkHistoryServerConfigKeys, + Description: `Resource name of an existing Dataproc Cluster to act as a Spark History Server for the workload.`, + }, + }, + }, + }, + }, + }, + }, + + "kubernetes_cluster_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + AtLeastOneOf: virtualClusterConfigKeys, + Description: `The configuration for running the Dataproc cluster on Kubernetes.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "kubernetes_namespace": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + AtLeastOneOf: kubernetesClusterConfigKeys, + Description: `A namespace within the Kubernetes cluster to deploy into. If this namespace does not exist, it is created. If it exists, Dataproc verifies that another Dataproc VirtualCluster is not installed into it. If not specified, the name of the Dataproc Cluster is used.`, + }, + + "kubernetes_software_config": { + Type: schema.TypeList, + MaxItems: 1, + Required: true, + Description: `The software configuration for this Dataproc cluster running on Kubernetes.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "component_version": { + Type: schema.TypeMap, + Required: true, + ForceNew: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `The components that should be installed in this Dataproc cluster. The key must be a string from the KubernetesComponent enumeration. The value is the version of the software to be installed.`, + }, + + "properties": { + Type: schema.TypeMap, + Optional: true, + ForceNew: true, + DiffSuppressFunc: resourceDataprocPropertyDiffSuppress, + Elem: &schema.Schema{Type: schema.TypeString}, + Computed: true, + Description: `The properties to set on daemon config files. Property keys are specified in prefix:property format, for example spark:spark.kubernetes.container.image.`, + }, + }, + }, + }, + + "gke_cluster_config": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Description: `The configuration for running the Dataproc cluster on GKE.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "gke_cluster_target": { + Type: schema.TypeString, + ForceNew: true, + Optional: true, + AtLeastOneOf: gkeClusterConfigKeys, + Description: `A target GKE cluster to deploy to. It must be in the same project and region as the Dataproc cluster (the GKE cluster can be zonal or regional). Format: 'projects/{project}/locations/{location}/clusters/{cluster_id}'`, + }, + + "node_pool_target": { + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: gkeClusterConfigKeys, + MinItems: 1, + Description: `GKE node pools where workloads will be scheduled. At least one node pool must be assigned the DEFAULT GkeNodePoolTarget.Role. If a GkeNodePoolTarget is not specified, Dataproc constructs a DEFAULT GkeNodePoolTarget.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "node_pool": { + Type: schema.TypeString, + ForceNew: true, + Required: true, + Description: `The target GKE node pool. Format: 'projects/{project}/locations/{location}/clusters/{cluster}/nodePools/{nodePool}'`, + }, + + "roles": { + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, + ForceNew: true, + Required: true, + Description: `The roles associated with the GKE node pool.`, + }, + + "node_pool_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Input only. The configuration for the GKE node pool.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `The node pool configuration.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "machine_type": { + Type: schema.TypeString, + ForceNew: true, + Optional: true, + Description: `The name of a Compute Engine machine type.`, + }, + + "local_ssd_count": { + Type: schema.TypeInt, + ForceNew: true, + Optional: true, + Description: `The minimum number of nodes in the node pool. Must be >= 0 and <= maxNodeCount.`, + }, + + "preemptible": { + Type: schema.TypeBool, + ForceNew: true, + Optional: true, + Description: `Whether the nodes are created as preemptible VM instances. Preemptible nodes cannot be used in a node pool with the CONTROLLER role or in the DEFAULT node pool if the CONTROLLER role is not assigned (the DEFAULT node pool will assume the CONTROLLER role).`, + }, + + "min_cpu_platform": { + Type: schema.TypeString, + ForceNew: true, + Optional: true, + Description: `Minimum CPU platform to be used by this instance. The instance may be scheduled on the specified or a newer CPU platform. Specify the friendly names of CPU platforms, such as "Intel Haswell" or "Intel Sandy Bridge".`, + }, + + "spot": { + Type: schema.TypeBool, + ForceNew: true, + Optional: true, + Description: `Spot flag for enabling Spot VM, which is a rebrand of the existing preemptible flag.`, + }, + }, + }, + }, + + "locations": { + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, + ForceNew: true, + Required: true, + Description: `The list of Compute Engine zones where node pool nodes associated with a Dataproc on GKE virtual cluster will be located.`, + }, + + "autoscaling": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `The autoscaler configuration for this node pool. The autoscaler is enabled only when a valid configuration is present.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "min_node_count": { + Type: schema.TypeInt, + ForceNew: true, + Optional: true, + Description: `The minimum number of nodes in the node pool. Must be >= 0 and <= maxNodeCount.`, + }, + + "max_node_count": { + Type: schema.TypeInt, + ForceNew: true, + Optional: true, + Description: `The maximum number of nodes in the node pool. Must be >= minNodeCount, and must be > 0.`, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + + "cluster_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Allows you to configure various aspects of the cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "staging_bucket": { + Type: schema.TypeString, + Optional: true, + AtLeastOneOf: clusterConfigKeys, + ForceNew: true, + Description: `The Cloud Storage staging bucket used to stage files, such as Hadoop jars, between client machines and the cluster. Note: If you don't explicitly specify a staging_bucket then GCP will auto create / assign one for you. However, you are not guaranteed an auto generated bucket which is solely dedicated to your cluster; it may be shared with other clusters in the same region/zone also choosing to use the auto generation option.`, + }, + // If the user does not specify a staging bucket, GCP will allocate one automatically. + // The staging_bucket field provides a way for the user to supply their own + // staging bucket. The bucket field is purely a computed field which details + // the definitive bucket allocated and in use (either the user supplied one via + // staging_bucket, or the GCP generated one) + "bucket": { + Type: schema.TypeString, + Computed: true, + Description: ` The name of the cloud storage bucket ultimately used to house the staging data for the cluster. If staging_bucket is specified, it will contain this value, otherwise it will be the auto generated name.`, + }, + + "temp_bucket": { + Type: schema.TypeString, + Optional: true, + Computed: true, + AtLeastOneOf: clusterConfigKeys, + ForceNew: true, + Description: `The Cloud Storage temp bucket used to store ephemeral cluster and jobs data, such as Spark and MapReduce history files. Note: If you don't explicitly specify a temp_bucket then GCP will auto create / assign one for you.`, + }, + + "gce_cluster_config": { + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: clusterConfigKeys, + Computed: true, + MaxItems: 1, + Description: `Common config settings for resources of Google Compute Engine cluster instances, applicable to all instances in the cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "zone": { + Type: schema.TypeString, + Optional: true, + Computed: true, + AtLeastOneOf: gceClusterConfigKeys, + ForceNew: true, + Description: `The GCP zone where your data is stored and used (i.e. where the master and the worker nodes will be created in). If region is set to 'global' (default) then zone is mandatory, otherwise GCP is able to make use of Auto Zone Placement to determine this automatically for you. Note: This setting additionally determines and restricts which computing resources are available for use with other configs such as cluster_config.master_config.machine_type and cluster_config.worker_config.machine_type.`, + }, + + "network": { + Type: schema.TypeString, + Optional: true, + Computed: true, + AtLeastOneOf: gceClusterConfigKeys, + ForceNew: true, + ConflictsWith: []string{"cluster_config.0.gce_cluster_config.0.subnetwork"}, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `The name or self_link of the Google Compute Engine network to the cluster will be part of. Conflicts with subnetwork. If neither is specified, this defaults to the "default" network.`, + }, + + "subnetwork": { + Type: schema.TypeString, + Optional: true, + AtLeastOneOf: gceClusterConfigKeys, + ForceNew: true, + ConflictsWith: []string{"cluster_config.0.gce_cluster_config.0.network"}, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `The name or self_link of the Google Compute Engine subnetwork the cluster will be part of. Conflicts with network.`, + }, + + "tags": { + Type: schema.TypeSet, + Optional: true, + AtLeastOneOf: gceClusterConfigKeys, + ForceNew: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `The list of instance tags applied to instances in the cluster. Tags are used to identify valid sources or targets for network firewalls.`, + }, + + "service_account": { + Type: schema.TypeString, + Optional: true, + AtLeastOneOf: gceClusterConfigKeys, + ForceNew: true, + Description: `The service account to be used by the Node VMs. If not specified, the "default" service account is used.`, + }, + + "service_account_scopes": { + Type: schema.TypeSet, + Optional: true, + Computed: true, + AtLeastOneOf: gceClusterConfigKeys, + ForceNew: true, + Description: `The set of Google API scopes to be made available on all of the node VMs under the service_account specified. These can be either FQDNs, or scope aliases.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + StateFunc: func(v interface{}) string { + return tpgresource.CanonicalizeServiceScope(v.(string)) + }, + }, + Set: tpgresource.StringScopeHashcode, + }, + + "internal_ip_only": { + Type: schema.TypeBool, + Optional: true, + AtLeastOneOf: gceClusterConfigKeys, + ForceNew: true, + Default: false, + Description: `By default, clusters are not restricted to internal IP addresses, and will have ephemeral external IP addresses assigned to each instance. If set to true, all instances in the cluster will only have internal IP addresses. Note: Private Google Access (also known as privateIpGoogleAccess) must be enabled on the subnetwork that the cluster will be launched in.`, + }, + + "metadata": { + Type: schema.TypeMap, + Optional: true, + AtLeastOneOf: gceClusterConfigKeys, + Elem: &schema.Schema{Type: schema.TypeString}, + ForceNew: true, + Description: `A map of the Compute Engine metadata entries to add to all instances`, + }, + + "shielded_instance_config": { + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: gceClusterConfigKeys, + Computed: true, + MaxItems: 1, + Description: `Shielded Instance Config for clusters using Compute Engine Shielded VMs.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_secure_boot": { + Type: schema.TypeBool, + Optional: true, + Default: false, + AtLeastOneOf: schieldedInstanceConfigKeys, + ForceNew: true, + Description: `Defines whether instances have Secure Boot enabled.`, + }, + "enable_vtpm": { + Type: schema.TypeBool, + Optional: true, + Default: false, + AtLeastOneOf: schieldedInstanceConfigKeys, + ForceNew: true, + Description: `Defines whether instances have the vTPM enabled.`, + }, + "enable_integrity_monitoring": { + Type: schema.TypeBool, + Optional: true, + Default: false, + AtLeastOneOf: schieldedInstanceConfigKeys, + ForceNew: true, + Description: `Defines whether instances have integrity monitoring enabled.`, + }, + }, + }, + }, + + "reservation_affinity": { + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: gceClusterConfigKeys, + Computed: true, + MaxItems: 1, + Description: `Reservation Affinity for consuming Zonal reservation.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "consume_reservation_type": { + Type: schema.TypeString, + Optional: true, + AtLeastOneOf: reservationAffinityKeys, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"NO_RESERVATION", "ANY_RESERVATION", "SPECIFIC_RESERVATION"}, false), + Description: `Type of reservation to consume.`, + }, + "key": { + Type: schema.TypeString, + Optional: true, + AtLeastOneOf: reservationAffinityKeys, + ForceNew: true, + Description: `Corresponds to the label key of reservation resource.`, + }, + "values": { + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + AtLeastOneOf: reservationAffinityKeys, + ForceNew: true, + Description: `Corresponds to the label values of reservation resource.`, + }, + }, + }, + }, + + "node_group_affinity": { + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: gceClusterConfigKeys, + Computed: true, + MaxItems: 1, + Description: `Node Group Affinity for sole-tenant clusters.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "node_group_uri": { + Type: schema.TypeString, + ForceNew: true, + Required: true, + Description: `The URI of a sole-tenant that the cluster will be created on.`, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + }, + }, + }, + }, + }, + }, + }, + + "master_config": instanceConfigSchema("master_config"), + "worker_config": instanceConfigSchema("worker_config"), + // preemptible_worker_config has a slightly different config + "preemptible_worker_config": { + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: clusterConfigKeys, + Computed: true, + MaxItems: 1, + Description: `The Google Compute Engine config settings for the additional (aka preemptible) instances in a cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "num_instances": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + Description: `Specifies the number of preemptible nodes to create. Defaults to 0.`, + AtLeastOneOf: []string{ + "cluster_config.0.preemptible_worker_config.0.num_instances", + "cluster_config.0.preemptible_worker_config.0.preemptibility", + "cluster_config.0.preemptible_worker_config.0.disk_config", + }, + }, + + // API does not honour this if set ... + // It always uses whatever is specified for the worker_config + // "machine_type": { ... } + // "min_cpu_platform": { ... } + "preemptibility": { + Type: schema.TypeString, + Optional: true, + Description: `Specifies the preemptibility of the secondary nodes. Defaults to PREEMPTIBLE.`, + AtLeastOneOf: []string{ + "cluster_config.0.preemptible_worker_config.0.num_instances", + "cluster_config.0.preemptible_worker_config.0.preemptibility", + "cluster_config.0.preemptible_worker_config.0.disk_config", + }, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"PREEMPTIBILITY_UNSPECIFIED", "NON_PREEMPTIBLE", "PREEMPTIBLE", "SPOT"}, false), + Default: "PREEMPTIBLE", + }, + + "disk_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Description: `Disk Config`, + AtLeastOneOf: []string{ + "cluster_config.0.preemptible_worker_config.0.num_instances", + "cluster_config.0.preemptible_worker_config.0.preemptibility", + "cluster_config.0.preemptible_worker_config.0.disk_config", + }, + MaxItems: 1, + + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "num_local_ssds": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + AtLeastOneOf: preemptibleWorkerDiskConfigKeys, + ForceNew: true, + Description: `The amount of local SSD disks that will be attached to each preemptible worker node. Defaults to 0.`, + }, + + "boot_disk_size_gb": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + AtLeastOneOf: preemptibleWorkerDiskConfigKeys, + ForceNew: true, + ValidateFunc: validation.IntAtLeast(10), + Description: `Size of the primary disk attached to each preemptible worker node, specified in GB. The smallest allowed disk size is 10GB. GCP will default to a predetermined computed value if not set (currently 500GB). Note: If SSDs are not attached, it also contains the HDFS data blocks and Hadoop working directories.`, + }, + + "boot_disk_type": { + Type: schema.TypeString, + Optional: true, + AtLeastOneOf: preemptibleWorkerDiskConfigKeys, + ForceNew: true, + Default: "pd-standard", + Description: `The disk type of the primary disk attached to each preemptible worker node. Such as "pd-ssd" or "pd-standard". Defaults to "pd-standard".`, + }, + }, + }, + }, + + "instance_names": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `List of preemptible instance names which have been assigned to the cluster.`, + }, + }, + }, + }, + + "security_config": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: `Security related configuration.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "kerberos_config": { + Type: schema.TypeList, + Required: true, + Description: "Kerberos related configuration", + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "cross_realm_trust_admin_server": { + Type: schema.TypeString, + Optional: true, + Description: `The admin server (IP or hostname) for the remote trusted realm in a cross realm trust relationship.`, + }, + "cross_realm_trust_kdc": { + Type: schema.TypeString, + Optional: true, + Description: `The KDC (IP or hostname) for the remote trusted realm in a cross realm trust relationship.`, + }, + "cross_realm_trust_realm": { + Type: schema.TypeString, + Optional: true, + Description: `The remote realm the Dataproc on-cluster KDC will trust, should the user enable cross realm trust.`, + }, + "cross_realm_trust_shared_password_uri": { + Type: schema.TypeString, + Optional: true, + Description: `The Cloud Storage URI of a KMS encrypted file containing the shared password between the on-cluster +Kerberos realm and the remote trusted realm, in a cross realm trust relationship.`, + }, + "enable_kerberos": { + Type: schema.TypeBool, + Optional: true, + Description: `Flag to indicate whether to Kerberize the cluster.`, + }, + "kdc_db_key_uri": { + Type: schema.TypeString, + Optional: true, + Description: `The Cloud Storage URI of a KMS encrypted file containing the master key of the KDC database.`, + }, + "key_password_uri": { + Type: schema.TypeString, + Optional: true, + Description: `The Cloud Storage URI of a KMS encrypted file containing the password to the user provided key. For the self-signed certificate, this password is generated by Dataproc.`, + }, + "keystore_uri": { + Type: schema.TypeString, + Optional: true, + Description: `The Cloud Storage URI of the keystore file used for SSL encryption. If not provided, Dataproc will provide a self-signed certificate.`, + }, + "keystore_password_uri": { + Type: schema.TypeString, + Optional: true, + Description: `The Cloud Storage URI of a KMS encrypted file containing +the password to the user provided keystore. For the self-signed certificate, this password is generated +by Dataproc`, + }, + "kms_key_uri": { + Type: schema.TypeString, + Required: true, + Description: `The uri of the KMS key used to encrypt various sensitive files.`, + }, + "realm": { + Type: schema.TypeString, + Optional: true, + Description: `The name of the on-cluster Kerberos realm. If not specified, the uppercased domain of hostnames will be the realm.`, + }, + "root_principal_password_uri": { + Type: schema.TypeString, + Required: true, + Description: `The cloud Storage URI of a KMS encrypted file containing the root principal password.`, + }, + "tgt_lifetime_hours": { + Type: schema.TypeInt, + Optional: true, + Description: `The lifetime of the ticket granting ticket, in hours.`, + }, + "truststore_password_uri": { + Type: schema.TypeString, + Optional: true, + Description: `The Cloud Storage URI of a KMS encrypted file containing the password to the user provided truststore. For the self-signed certificate, this password is generated by Dataproc.`, + }, + "truststore_uri": { + Type: schema.TypeString, + Optional: true, + Description: `The Cloud Storage URI of the truststore file used for SSL encryption. If not provided, Dataproc will provide a self-signed certificate.`, + }, + }, + }, + }, + }, + }, + }, + + "software_config": { + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: clusterConfigKeys, + Computed: true, + MaxItems: 1, + Description: `The config settings for software inside the cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "image_version": { + Type: schema.TypeString, + Optional: true, + Computed: true, + AtLeastOneOf: clusterSoftwareConfigKeys, + ForceNew: true, + DiffSuppressFunc: dataprocImageVersionDiffSuppress, + Description: `The Cloud Dataproc image version to use for the cluster - this controls the sets of software versions installed onto the nodes when you create clusters. If not specified, defaults to the latest version.`, + }, + "override_properties": { + Type: schema.TypeMap, + Optional: true, + AtLeastOneOf: clusterSoftwareConfigKeys, + ForceNew: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `A list of override and additional properties (key/value pairs) used to modify various aspects of the common configuration files used when creating a cluster.`, + }, + + "properties": { + Type: schema.TypeMap, + Computed: true, + Description: `A list of the properties used to set the daemon config files. This will include any values supplied by the user via cluster_config.software_config.override_properties`, + }, + + // We have two versions of the properties field here because by default + // dataproc will set a number of default properties for you out of the + // box. If you want to override one or more, if we only had one field, + // you would need to add in all these values as well otherwise you would + // get a diff. To make this easier, 'properties' simply contains the computed + // values (including overrides) for all properties, whilst override_properties + // is only for properties the user specifically wants to override. If nothing + // is overridden, this will be empty. + + "optional_components": { + Type: schema.TypeSet, + Optional: true, + AtLeastOneOf: clusterSoftwareConfigKeys, + Description: `The set of optional components to activate on the cluster.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + + "initialization_action": { + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: clusterConfigKeys, + ForceNew: true, + Description: `Commands to execute on each node after config is completed. You can specify multiple versions of these.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "script": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The script to be executed during initialization of the cluster. The script must be a GCS file with a gs:// prefix.`, + }, + + "timeout_sec": { + Type: schema.TypeInt, + Optional: true, + Default: 300, + ForceNew: true, + Description: `The maximum duration (in seconds) which script is allowed to take to execute its action. GCP will default to a predetermined computed value if not set (currently 300).`, + }, + }, + }, + }, + "encryption_config": { + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: clusterConfigKeys, + MaxItems: 1, + Description: `The Customer managed encryption keys settings for the cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "kms_key_name": { + Type: schema.TypeString, + Required: true, + Description: `The Cloud KMS key name to use for PD disk encryption for all instances in the cluster.`, + }, + }, + }, + }, + "autoscaling_config": { + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: clusterConfigKeys, + MaxItems: 1, + Description: `The autoscaling policy config associated with the cluster.`, + DiffSuppressFunc: tpgresource.EmptyOrUnsetBlockDiffSuppress, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "policy_uri": { + Type: schema.TypeString, + Required: true, + Description: `The autoscaling policy used by the cluster.`, + DiffSuppressFunc: tpgresource.LocationDiffSuppress, + }, + }, + }, + }, + "metastore_config": { + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: clusterConfigKeys, + MaxItems: 1, + Description: `Specifies a Metastore configuration.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dataproc_metastore_service": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `Resource name of an existing Dataproc Metastore service.`, + }, + }, + }, + }, + "lifecycle_config": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + AtLeastOneOf: clusterConfigKeys, + Description: `The settings for auto deletion cluster schedule.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "idle_delete_ttl": { + Type: schema.TypeString, + Optional: true, + Description: `The duration to keep the cluster alive while idling (no jobs running). After this TTL, the cluster will be deleted. Valid range: [10m, 14d].`, + AtLeastOneOf: []string{ + "cluster_config.0.lifecycle_config.0.idle_delete_ttl", + "cluster_config.0.lifecycle_config.0.auto_delete_time", + }, + }, + "idle_start_time": { + Type: schema.TypeString, + Computed: true, + Description: `Time when the cluster became idle (most recent job finished) and became eligible for deletion due to idleness.`, + }, + // the API also has the auto_delete_ttl option in its request, however, + // the value is not returned in the response, rather the auto_delete_time + // after calculating ttl with the update time is returned, thus, for now + // we will only allow auto_delete_time to updated. + "auto_delete_time": { + Type: schema.TypeString, + Optional: true, + Description: `The time when cluster will be auto-deleted. A timestamp in RFC3339 UTC "Zulu" format, accurate to nanoseconds. Example: "2014-10-02T15:01:23.045123456Z".`, + DiffSuppressFunc: tpgresource.TimestampDiffSuppress(time.RFC3339Nano), + AtLeastOneOf: []string{ + "cluster_config.0.lifecycle_config.0.idle_delete_ttl", + "cluster_config.0.lifecycle_config.0.auto_delete_time", + }, + }, + }, + }, + }, + "endpoint_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `The config settings for port access on the cluster. Structure defined below.`, + AtLeastOneOf: clusterConfigKeys, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_http_port_access": { + Type: schema.TypeBool, + Required: true, + ForceNew: true, + Description: `The flag to enable http access to specific ports on the cluster from external sources (aka Component Gateway). Defaults to false.`, + }, + "http_ports": { + Type: schema.TypeMap, + Computed: true, + Description: `The map of port descriptions to URLs. Will only be populated if enable_http_port_access is true.`, + }, + }, + }, + }, + + "dataproc_metric_config": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: `The config for Dataproc metrics.`, + AtLeastOneOf: clusterConfigKeys, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metrics": { + Type: schema.TypeList, + Required: true, + Description: `Metrics sources to enable.`, + Elem: metricsSchema(), + }, + }, + }, + }, + }, + }, + }, + }, + UseJSONNumber: true, + } +} + +func ResourceDataprocClusterStateUpgradeV0(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { + return tpgresource.LabelsStateUpgrade(rawState, resourceDataprocGoogleLabelPrefix) +} 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 4e0f97060275..6bfe91fdfba7 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 @@ -686,14 +686,46 @@ func TestAccDataprocCluster_withLabels(t *testing.T) { ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccCheckDataprocClusterDestroy(t), Steps: []resource.TestStep{ + { + Config: testAccDataprocCluster_withoutLabels(rnd), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), + + resource.TestCheckNoResourceAttr("google_dataproc_cluster.with_labels", "labels.%"), + // We don't provide any, but GCP adds three and goog-dataproc-autozone is added internally, so expect 4. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.%", "4"), + ), + }, { Config: testAccDataprocCluster_withLabels(rnd), Check: resource.ComposeTestCheckFunc( testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), - // We only provide one, but GCP adds three and we added goog-dataproc-autozone internally, so expect 5. - resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.%", "5"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.%", "1"), resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.key1", "value1"), + // We only provide one, but GCP adds three and goog-dataproc-autozone is added internally, so expect 5. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.%", "5"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.key1", "value1"), + ), + }, + { + Config: testAccDataprocCluster_withLabelsUpdate(rnd), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), + + // We only provide two, so expect 2. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.%", "1"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.key2", "value2"), + ), + }, + { + Config: testAccDataprocCluster_withoutLabels(rnd), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), + + resource.TestCheckNoResourceAttr("google_dataproc_cluster.with_labels", "labels.%"), + // We don't provide any, but GCP adds three and goog-dataproc-autozone is added internally, so expect 4. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.%", "4"), ), }, }, @@ -1723,6 +1755,28 @@ resource "google_dataproc_cluster" "with_labels" { `, rnd) } +func testAccDataprocCluster_withLabelsUpdate(rnd string) string { + return fmt.Sprintf(` +resource "google_dataproc_cluster" "with_labels" { + name = "tf-test-dproc-%s" + region = "us-central1" + + labels = { + key2 = "value2" + } +} +`, rnd) +} + +func testAccDataprocCluster_withoutLabels(rnd string) string { + return fmt.Sprintf(` +resource "google_dataproc_cluster" "with_labels" { + name = "tf-test-dproc-%s" + region = "us-central1" +} +`, rnd) +} + func testAccDataprocCluster_withEndpointConfig(rnd string) string { return fmt.Sprintf(` resource "google_dataproc_cluster" "with_endpoint_config" { diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_upgrade_test.go b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_upgrade_test.go new file mode 100644 index 000000000000..57e11de4a1b8 --- /dev/null +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_upgrade_test.go @@ -0,0 +1,212 @@ +package dataproc_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "google.golang.org/api/dataproc/v1" + + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +// Tests schema version migration by creating a cluster with an old version of the provider (4.65.0) +// and then updating it with the current version the provider. +func TestAccDataprocClusterLabelsMigration_withoutLabels_withoutChanges(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + rnd := acctest.RandString(t, 10) + var cluster dataproc.Cluster + oldVersion := map[string]resource.ExternalProvider{ + "google": { + VersionConstraint: "4.65.0", // a version that doesn't separate user defined labels and system labels + Source: "registry.terraform.io/hashicorp/google", + }, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + CheckDestroy: testAccCheckDataprocClusterDestroy(t), + Steps: []resource.TestStep{ + { + Config: testAccDataprocCluster_withoutLabels(rnd), + ExternalProviders: oldVersion, + }, + { + Config: testAccDataprocCluster_withoutLabels(rnd), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), + + resource.TestCheckNoResourceAttr("google_dataproc_cluster.with_labels", "labels.%"), + // GCP adds three and goog-dataproc-autozone is added internally, so expect 4. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.%", "4"), + ), + }, + { + Config: testAccDataprocCluster_withLabels(rnd), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), + + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.%", "1"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.key1", "value1"), + // We only provide one, but GCP adds three and goog-dataproc-autozone is added internally, so expect 5. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.%", "5"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.key1", "value1"), + ), + }, + }, + }) +} + +func TestAccDataprocClusterLabelsMigration_withLabels_withoutChanges(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + rnd := acctest.RandString(t, 10) + var cluster dataproc.Cluster + oldVersion := map[string]resource.ExternalProvider{ + "google": { + VersionConstraint: "4.65.0", // a version that doesn't separate user defined labels and system labels + Source: "registry.terraform.io/hashicorp/google", + }, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + CheckDestroy: testAccCheckDataprocClusterDestroy(t), + Steps: []resource.TestStep{ + { + Config: testAccDataprocCluster_withLabels(rnd), + ExternalProviders: oldVersion, + }, + { + Config: testAccDataprocCluster_withLabels(rnd), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), + + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.%", "1"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.key1", "value1"), + // We only provide one, but GCP adds three and goog-dataproc-autozone is added internally, so expect 5. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.%", "5"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.key1", "value1"), + ), + }, + { + Config: testAccDataprocCluster_withLabelsUpdate(rnd), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), + + // We only provide one, so expect 1. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.%", "1"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.key2", "value2"), + // We only provide one, but GCP adds three and goog-dataproc-autozone is added internally, so expect 5. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.%", "5"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.key2", "value2"), + ), + }, + }, + }) +} + +func TestAccDataprocClusterLabelsMigration_withUpdate(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + rnd := acctest.RandString(t, 10) + var cluster dataproc.Cluster + oldVersion := map[string]resource.ExternalProvider{ + "google": { + VersionConstraint: "4.65.0", // a version that doesn't separate user defined labels and system labels + Source: "registry.terraform.io/hashicorp/google", + }, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + CheckDestroy: testAccCheckDataprocClusterDestroy(t), + Steps: []resource.TestStep{ + { + Config: testAccDataprocCluster_withoutLabels(rnd), + ExternalProviders: oldVersion, + }, + { + Config: testAccDataprocCluster_withLabels(rnd), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), + + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.%", "1"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.key1", "value1"), + // We only provide one, but GCP adds three and goog-dataproc-autozone is added internally, so expect 5. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.%", "5"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.key1", "value1"), + ), + }, + { + Config: testAccDataprocCluster_withoutLabels(rnd), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), + + resource.TestCheckNoResourceAttr("google_dataproc_cluster.with_labels", "labels.%"), + // We only provide one, but GCP adds three and goog-dataproc-autozone is added internally, so expect 4. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.%", "4"), + ), + }, + }, + }) +} + +func TestAccDataprocClusterLabelsMigration_withRemoval(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + rnd := acctest.RandString(t, 10) + var cluster dataproc.Cluster + oldVersion := map[string]resource.ExternalProvider{ + "google": { + VersionConstraint: "4.65.0", // a version that doesn't separate user defined labels and system labels + Source: "registry.terraform.io/hashicorp/google", + }, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + CheckDestroy: testAccCheckDataprocClusterDestroy(t), + Steps: []resource.TestStep{ + { + Config: testAccDataprocCluster_withLabels(rnd), + ExternalProviders: oldVersion, + }, + { + Config: testAccDataprocCluster_withoutLabels(rnd), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), + + resource.TestCheckNoResourceAttr("google_dataproc_cluster.with_labels", "labels.%"), + // We only provide one, but GCP adds three and goog-dataproc-autozone is added internally, so expect 4. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.%", "4"), + ), + }, + { + Config: testAccDataprocCluster_withLabels(rnd), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), + + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.%", "1"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.key1", "value1"), + // We only provide one, but GCP adds three and goog-dataproc-autozone is added internally, so expect 5. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.%", "5"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.key1", "value1"), + ), + }, + }, + }) +} diff --git a/mmv1/third_party/terraform/services/notebooks/resource_notebooks_instance_test.go.erb b/mmv1/third_party/terraform/services/notebooks/resource_notebooks_instance_test.go.erb index 63857df18d57..90749f4dc35e 100644 --- a/mmv1/third_party/terraform/services/notebooks/resource_notebooks_instance_test.go.erb +++ b/mmv1/third_party/terraform/services/notebooks/resource_notebooks_instance_test.go.erb @@ -56,7 +56,7 @@ func TestAccNotebooksInstance_update(t *testing.T) { ResourceName: "google_notebooks_instance.instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"vm_image", "metadata"}, + ImportStateVerifyIgnore: []string{"vm_image", "metadata", "labels", "terraform_labels"}, }, { Config: testAccNotebooksInstance_update(context, false), @@ -65,7 +65,7 @@ func TestAccNotebooksInstance_update(t *testing.T) { ResourceName: "google_notebooks_instance.instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"vm_image", "metadata"}, + ImportStateVerifyIgnore: []string{"vm_image", "metadata", "labels", "terraform_labels"}, }, }, }) 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 fcfc331523d7..b823ef308c30 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 @@ -37,6 +37,7 @@ func ResourceStorageBucket() *schema.Resource { }, CustomizeDiff: customdiff.All( customdiff.ForceNewIfChange("retention_policy.0.is_locked", isPolicyLocked), + tpgresource.SetLabelsDiff, ), Timeouts: &schema.ResourceTimeout{ @@ -45,6 +46,15 @@ func ResourceStorageBucket() *schema.Resource { Read: schema.DefaultTimeout(4 * time.Minute), }, + SchemaVersion: 1, + StateUpgraders: []schema.StateUpgrader{ + { + Type: resourceStorageBucketV0().CoreConfigSchema().ImpliedType(), + Upgrade: ResourceStorageBucketStateUpgradeV0, + Version: 0, + }, + }, + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, @@ -85,13 +95,24 @@ func ResourceStorageBucket() *schema.Resource { "labels": { Type: schema.TypeMap, Optional: true, - Computed: true, - // GCP (Dataplex) automatically adds labels - DiffSuppressFunc: resourceDataplexLabelDiffSuppress, Elem: &schema.Schema{Type: schema.TypeString}, Description: `A set of key/value label pairs to assign to the bucket.`, }, + "terraform_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `The combination of labels configured directly on the resource and default labels configured on the provider.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + + "effective_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "location": { Type: schema.TypeString, Required: true, @@ -442,7 +463,8 @@ func ResourceStorageBucket() *schema.Resource { } } -const resourceDataplexGoogleProvidedLabelPrefix = "labels.goog-dataplex" +const resourceDataplexGoogleLabelPrefix = "goog-dataplex" +const resourceDataplexGoogleProvidedLabelPrefix = "labels." + resourceDataplexGoogleLabelPrefix func resourceDataplexLabelDiffSuppress(k, old, new string, d *schema.ResourceData) bool { if strings.HasPrefix(k, resourceDataplexGoogleProvidedLabelPrefix) && new == "" { @@ -494,7 +516,7 @@ func resourceStorageBucketCreate(d *schema.ResourceData, meta interface{}) error // Create a bucket, setting the labels, location and name. sb := &storage.Bucket{ Name: bucket, - Labels: tpgresource.ExpandLabels(d), + Labels: tpgresource.ExpandEffectiveLabels(d), Location: location, IamConfiguration: expandIamConfiguration(d), } @@ -695,15 +717,15 @@ func resourceStorageBucketUpdate(d *schema.ResourceData, meta interface{}) error } } - if d.HasChange("labels") { - sb.Labels = tpgresource.ExpandLabels(d) + if d.HasChange("effective_labels") { + sb.Labels = tpgresource.ExpandEffectiveLabels(d) if len(sb.Labels) == 0 { sb.NullFields = append(sb.NullFields, "Labels") } // To delete a label using PATCH, we have to explicitly set its value // to null. - old, _ := d.GetChange("labels") + old, _ := d.GetChange("effective_labels") for k := range old.(map[string]interface{}) { if _, ok := sb.Labels[k]; !ok { sb.NullFields = append(sb.NullFields, fmt.Sprintf("Labels.%s", k)) @@ -1597,7 +1619,13 @@ func setStorageBucket(d *schema.ResourceData, config *transport_tpg.Config, res if err := d.Set("lifecycle_rule", flattenBucketLifecycle(res.Lifecycle)); err != nil { return fmt.Errorf("Error setting lifecycle_rule: %s", err) } - if err := d.Set("labels", res.Labels); err != nil { + if err := tpgresource.SetLabels(res.Labels, d, "labels"); err != nil { + return fmt.Errorf("Error setting labels: %s", err) + } + if err := tpgresource.SetLabels(res.Labels, d, "terraform_labels"); err != nil { + return fmt.Errorf("Error setting terraform_labels: %s", err) + } + if err := d.Set("effective_labels", res.Labels); err != nil { return fmt.Errorf("Error setting labels: %s", err) } if err := d.Set("website", flattenBucketWebsite(res.Website)); err != nil { diff --git a/mmv1/third_party/terraform/services/storage/resource_storage_bucket_migrate.go b/mmv1/third_party/terraform/services/storage/resource_storage_bucket_migrate.go new file mode 100644 index 000000000000..f59f8adba0c8 --- /dev/null +++ b/mmv1/third_party/terraform/services/storage/resource_storage_bucket_migrate.go @@ -0,0 +1,415 @@ +package storage + +import ( + "context" + "math" + "strings" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + + "github.com/hashicorp/terraform-provider-google/google/tpgresource" +) + +func resourceStorageBucketV0() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The name of the bucket.`, + }, + + "encryption": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "default_kms_key_name": { + Type: schema.TypeString, + Required: true, + Description: `A Cloud KMS key that will be used to encrypt objects inserted into this bucket, if no encryption method is specified. You must pay attention to whether the crypto key is available in the location that this bucket is created in. See the docs for more details.`, + }, + }, + }, + Description: `The bucket's encryption configuration.`, + }, + + "requester_pays": { + Type: schema.TypeBool, + Optional: true, + Description: `Enables Requester Pays on a storage bucket.`, + }, + + "force_destroy": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: `When deleting a bucket, this boolean option will delete all contained objects. If you try to delete a bucket that contains objects, Terraform will fail that run.`, + }, + + "labels": { + Type: schema.TypeMap, + Optional: true, + Computed: true, + // GCP (Dataplex) automatically adds labels + DiffSuppressFunc: resourceDataplexLabelDiffSuppress, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `A set of key/value label pairs to assign to the bucket.`, + }, + + "location": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + StateFunc: func(s interface{}) string { + return strings.ToUpper(s.(string)) + }, + Description: `The Google Cloud Storage location`, + }, + + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: `The ID of the project in which the resource belongs. If it is not provided, the provider project is used.`, + }, + + "self_link": { + Type: schema.TypeString, + Computed: true, + Description: `The URI of the created resource.`, + }, + + "url": { + Type: schema.TypeString, + Computed: true, + Description: `The base URL of the bucket, in the format gs://.`, + }, + + "storage_class": { + Type: schema.TypeString, + Optional: true, + Default: "STANDARD", + Description: `The Storage Class of the new bucket. Supported values include: STANDARD, MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, ARCHIVE.`, + }, + + "lifecycle_rule": { + Type: schema.TypeList, + Optional: true, + MaxItems: 100, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + MaxItems: 1, + Set: resourceGCSBucketLifecycleRuleActionHash, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Required: true, + Description: `The type of the action of this Lifecycle Rule. Supported values include: Delete, SetStorageClass and AbortIncompleteMultipartUpload.`, + }, + "storage_class": { + Type: schema.TypeString, + Optional: true, + Description: `The target Storage Class of objects affected by this Lifecycle Rule. Supported values include: MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, ARCHIVE.`, + }, + }, + }, + Description: `The Lifecycle Rule's action configuration. A single block of this type is supported.`, + }, + "condition": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + MaxItems: 1, + Set: resourceGCSBucketLifecycleRuleConditionHash, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "age": { + Type: schema.TypeInt, + Optional: true, + Description: `Minimum age of an object in days to satisfy this condition.`, + }, + "created_before": { + Type: schema.TypeString, + Optional: true, + Description: `Creation date of an object in RFC 3339 (e.g. 2017-06-13) to satisfy this condition.`, + }, + "custom_time_before": { + Type: schema.TypeString, + Optional: true, + Description: `Creation date of an object in RFC 3339 (e.g. 2017-06-13) to satisfy this condition.`, + }, + "days_since_custom_time": { + Type: schema.TypeInt, + Optional: true, + Description: `Number of days elapsed since the user-specified timestamp set on an object.`, + }, + "days_since_noncurrent_time": { + Type: schema.TypeInt, + Optional: true, + Description: `Number of days elapsed since the noncurrent timestamp of an object. This + condition is relevant only for versioned objects.`, + }, + "noncurrent_time_before": { + Type: schema.TypeString, + Optional: true, + Description: `Creation date of an object in RFC 3339 (e.g. 2017-06-13) to satisfy this condition.`, + }, + "with_state": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"LIVE", "ARCHIVED", "ANY", ""}, false), + Description: `Match to live and/or archived objects. Unversioned buckets have only live objects. Supported values include: "LIVE", "ARCHIVED", "ANY".`, + }, + "matches_storage_class": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `Storage Class of objects to satisfy this condition. Supported values include: MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, ARCHIVE, STANDARD, DURABLE_REDUCED_AVAILABILITY.`, + }, + "num_newer_versions": { + Type: schema.TypeInt, + Optional: true, + Description: `Relevant only for versioned objects. The number of newer versions of an object to satisfy this condition.`, + }, + "matches_prefix": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `One or more matching name prefixes to satisfy this condition.`, + }, + "matches_suffix": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `One or more matching name suffixes to satisfy this condition.`, + }, + }, + }, + Description: `The Lifecycle Rule's condition configuration.`, + }, + }, + }, + Description: `The bucket's Lifecycle Rules configuration.`, + }, + + "versioning": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `While set to true, versioning is fully enabled for this bucket.`, + }, + }, + }, + Description: `The bucket's Versioning configuration.`, + }, + + "autoclass": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `While set to true, autoclass automatically transitions objects in your bucket to appropriate storage classes based on each object's access pattern.`, + }, + }, + }, + Description: `The bucket's autoclass configuration.`, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + _, n := d.GetChange(strings.TrimSuffix(k, ".#")) + if !strings.HasSuffix(k, ".#") { + return false + } + var l []interface{} + if new == "1" && old == "0" { + l = n.([]interface{}) + contents, ok := l[0].(map[string]interface{}) + if !ok { + return false + } + if contents["enabled"] == false { + return true + } + } + return false + }, + }, + "website": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "main_page_suffix": { + Type: schema.TypeString, + Optional: true, + AtLeastOneOf: []string{"website.0.not_found_page", "website.0.main_page_suffix"}, + Description: `Behaves as the bucket's directory index where missing objects are treated as potential directories.`, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + return old != "" && new == "" + }, + }, + "not_found_page": { + Type: schema.TypeString, + Optional: true, + AtLeastOneOf: []string{"website.0.main_page_suffix", "website.0.not_found_page"}, + Description: `The custom object to return when a requested resource is not found.`, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + return old != "" && new == "" + }, + }, + }, + }, + Description: `Configuration if the bucket acts as a website.`, + }, + + "retention_policy": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "is_locked": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: `If set to true, the bucket will be locked and permanently restrict edits to the bucket's retention policy. Caution: Locking a bucket is an irreversible action.`, + }, + "retention_period": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntBetween(1, math.MaxInt32), + Description: `The period of time, in seconds, that objects in the bucket must be retained and cannot be deleted, overwritten, or archived. The value must be less than 3,155,760,000 seconds.`, + }, + }, + }, + Description: `Configuration of the bucket's data retention policy for how long objects in the bucket should be retained.`, + }, + + "cors": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "origin": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Description: `The list of Origins eligible to receive CORS response headers. Note: "*" is permitted in the list of origins, and means "any Origin".`, + }, + "method": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Description: `The list of HTTP methods on which to include CORS response headers, (GET, OPTIONS, POST, etc) Note: "*" is permitted in the list of methods, and means "any method".`, + }, + "response_header": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Description: `The list of HTTP headers other than the simple response headers to give permission for the user-agent to share across domains.`, + }, + "max_age_seconds": { + Type: schema.TypeInt, + Optional: true, + Description: `The value, in seconds, to return in the Access-Control-Max-Age header used in preflight responses.`, + }, + }, + }, + Description: `The bucket's Cross-Origin Resource Sharing (CORS) configuration.`, + }, + + "default_event_based_hold": { + Type: schema.TypeBool, + Optional: true, + Description: `Whether or not to automatically apply an eventBasedHold to new objects added to the bucket.`, + }, + + "logging": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "log_bucket": { + Type: schema.TypeString, + Required: true, + Description: `The bucket that will receive log objects.`, + }, + "log_object_prefix": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `The object prefix for log objects. If it's not provided, by default Google Cloud Storage sets this to this bucket's name.`, + }, + }, + }, + Description: `The bucket's Access & Storage Logs configuration.`, + }, + "uniform_bucket_level_access": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + Description: `Enables uniform bucket-level access on a bucket.`, + }, + "custom_placement_config": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "data_locations": { + Type: schema.TypeSet, + Required: true, + ForceNew: true, + MaxItems: 2, + MinItems: 2, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Description: `The list of individual regions that comprise a dual-region bucket. See the docs for a list of acceptable regions. Note: If any of the data_locations changes, it will recreate the bucket.`, + }, + }, + }, + Description: `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.`, + }, + "public_access_prevention": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `Prevents public access to a bucket.`, + }, + }, + UseJSONNumber: true, + } +} + +func ResourceStorageBucketStateUpgradeV0(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { + return tpgresource.LabelsStateUpgrade(rawState, resourceDataplexGoogleLabelPrefix) +} 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 fb04f1bfa88c..ec4802c16148 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 @@ -978,7 +978,7 @@ func TestAccStorageBucket_labels(t *testing.T) { ResourceName: "google_storage_bucket.bucket", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"force_destroy"}, + ImportStateVerifyIgnore: []string{"force_destroy", "labels", "terraform_labels"}, }, // Down to only one label (test single label deletion) { @@ -988,7 +988,7 @@ func TestAccStorageBucket_labels(t *testing.T) { ResourceName: "google_storage_bucket.bucket", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"force_destroy"}, + ImportStateVerifyIgnore: []string{"force_destroy", "labels", "terraform_labels"}, }, // And make sure deleting all labels work { @@ -998,7 +998,7 @@ func TestAccStorageBucket_labels(t *testing.T) { ResourceName: "google_storage_bucket.bucket", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"force_destroy"}, + ImportStateVerifyIgnore: []string{"force_destroy", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/tpgresource/labels.go b/mmv1/third_party/terraform/tpgresource/labels.go index 7b80869a972a..29b40a4c3ca8 100644 --- a/mmv1/third_party/terraform/tpgresource/labels.go +++ b/mmv1/third_party/terraform/tpgresource/labels.go @@ -3,6 +3,8 @@ package tpgresource import ( "context" "fmt" + "log" + "strings" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" @@ -147,3 +149,34 @@ func SetMetadataLabelsDiff(_ context.Context, d *schema.ResourceDiff, meta inter return nil } + +// Upgrade the field "labels" in the state to exclude the labels with the labels prefix +// and the field "effective_labels" to have all of labels, including the labels with the labels prefix +func LabelsStateUpgrade(rawState map[string]interface{}, labesPrefix string) (map[string]interface{}, error) { + log.Printf("[DEBUG] Attributes before migration: %#v", rawState) + log.Printf("[DEBUG] Attributes before migration labels: %#v", rawState["labels"]) + log.Printf("[DEBUG] Attributes before migration effective_labels: %#v", rawState["effective_labels"]) + + if rawState["labels"] != nil { + rawLabels := rawState["labels"].(map[string]interface{}) + labels := make(map[string]interface{}) + effectiveLabels := make(map[string]interface{}) + + for k, v := range rawLabels { + effectiveLabels[k] = v + + if !strings.HasPrefix(k, labesPrefix) { + labels[k] = v + } + } + + rawState["labels"] = labels + rawState["effective_labels"] = effectiveLabels + } + + log.Printf("[DEBUG] Attributes after migration: %#v", rawState) + log.Printf("[DEBUG] Attributes after migration labels: %#v", rawState["labels"]) + log.Printf("[DEBUG] Attributes after migration effective_labels: %#v", rawState["effective_labels"]) + + return rawState, nil +} diff --git a/mmv1/third_party/terraform/website/docs/r/dataflow_flex_template_job.html.markdown b/mmv1/third_party/terraform/website/docs/r/dataflow_flex_template_job.html.markdown index 4064c913467c..d592b3fdb39c 100644 --- a/mmv1/third_party/terraform/website/docs/r/dataflow_flex_template_job.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/dataflow_flex_template_job.html.markdown @@ -98,9 +98,13 @@ such as `serviceAccount`, `workerMachineType`, etc can be specified here. * `labels` - (Optional) User labels to be specified for the job. Keys and values should follow the restrictions specified in the [labeling restrictions](https://cloud.google.com/compute/docs/labeling-resources#restrictions) page. -**NOTE**: Google-provided Dataflow templates often provide default labels -that begin with `goog-dataflow-provided`. Unless explicitly set in config, these -labels will be ignored to prevent diffs on re-apply. +**Note**: This field is non-authoritative, and will only manage the labels present in your configuration. Please refer to the field `effective_labels` for all of the labels present on the resource. + +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. * `on_delete` - (Optional) One of "drain" or "cancel". Specifies behavior of deletion during `terraform destroy`. See above note. diff --git a/mmv1/third_party/terraform/website/docs/r/dataflow_job.html.markdown b/mmv1/third_party/terraform/website/docs/r/dataflow_job.html.markdown index 6000b964995a..a3acbcfcaa75 100644 --- a/mmv1/third_party/terraform/website/docs/r/dataflow_job.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/dataflow_job.html.markdown @@ -102,8 +102,11 @@ The following arguments are supported: * `parameters` - (Optional) Key/Value pairs to be passed to the Dataflow job (as used in the template). * `labels` - (Optional) User labels to be specified for the job. Keys and values should follow the restrictions specified in the [labeling restrictions](https://cloud.google.com/compute/docs/labeling-resources#restrictions) page. - **NOTE**: Google-provided Dataflow templates often provide default labels that begin with `goog-dataflow-provided`. - Unless explicitly set in config, these labels will be ignored to prevent diffs on re-apply. + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. Please refer to the field `effective_labels` for all of the labels present on the resource. +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. * `transform_name_mapping` - (Optional) Only applicable when updating a pipeline. Map of transform name prefixes of the job to be replaced with the corresponding name prefixes of the new job. This field is not used outside of update. * `max_workers` - (Optional) The number of workers permitted to work on the job. More workers may improve processing speed at additional cost. * `on_delete` - (Optional) One of "drain" or "cancel". Specifies behavior of deletion during `terraform destroy`. See above note. 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 1aa6310d0b12..e4efda5aa41b 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 @@ -129,7 +129,14 @@ resource "google_dataproc_cluster" "accelerated_cluster" { * `region` - (Optional) The region in which the cluster and associated nodes will be created in. Defaults to `global`. -* `labels` - (Optional, Computed) The list of labels (key/value pairs) to be applied to +* `labels` - (Optional) The list of labels (key/value pairs) configured on the resource through Terraform and to be applied to + instances in the cluster. + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. Please refer to the field `effective_labels` for all of the labels present on the resource. + +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. + +* `effective_labels` - (Computed) The list of labels (key/value pairs) to be applied to instances in the cluster. GCP generates some itself including `goog-dataproc-cluster-name` which is the name of the cluster. diff --git a/mmv1/third_party/tgc/tests/data/example_cloud_run_service.tfplan.json b/mmv1/third_party/tgc/tests/data/example_cloud_run_service.tfplan.json index 830211d59cad..1adfddbe14c4 100644 --- a/mmv1/third_party/tgc/tests/data/example_cloud_run_service.tfplan.json +++ b/mmv1/third_party/tgc/tests/data/example_cloud_run_service.tfplan.json @@ -19,6 +19,9 @@ "annotations": { "generated-by": "magic-modules" }, + "effective_annotations": { + "generated-by": "magic-modules" + }, "namespace": "{{.Provider.project}}" } ], @@ -86,6 +89,9 @@ "annotations": { "generated-by": "magic-modules" }, + "effective_annotations": { + "generated-by": "magic-modules" + }, "namespace": "{{.Provider.project}}" } ], @@ -134,6 +140,7 @@ "metadata": [ { "annotations": {}, + "effective_annotations": {}, "generation": true, "labels": true, "resource_version": true, From 6cdbf4d42c5f254c57bdf57724e159a20f07e6c9 Mon Sep 17 00:00:00 2001 From: Nick Elliot Date: Mon, 25 Sep 2023 10:11:46 -0700 Subject: [PATCH 56/67] Update to wrap generated import format regex in ^ and $ (#8913) * updated regex * removing prefix fron vpntunnel text, updating billing info for allowing supplied uris wth a trailing * replacing importstateid, skipping import in generated sample * incorrect var --- mmv1/products/billing/ProjectInfo.yaml | 3 ++- mmv1/templates/terraform/resource.erb | 2 +- .../services/compute/resource_compute_vpn_tunnel_test.go | 1 - .../corebilling/resource_google_billing_project_info_test.go | 3 +++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/mmv1/products/billing/ProjectInfo.yaml b/mmv1/products/billing/ProjectInfo.yaml index b55634709d98..e941f6aaaee7 100644 --- a/mmv1/products/billing/ProjectInfo.yaml +++ b/mmv1/products/billing/ProjectInfo.yaml @@ -28,11 +28,12 @@ custom_code: !ruby/object:Provider::Terraform::CustomCode encoder: templates/terraform/encoders/billing_project_info.go.erb test_check_destroy: templates/terraform/custom_check_destroy/billing_project_info.go.erb import_format: - ['projects/{{project}}', '{{project}}'] + ['projects/{{%project}}', '{{%project}}'] examples: - !ruby/object:Provider::Terraform::Examples name: 'billing_project_info_basic' primary_resource_id: 'default' + skip_import_test: true test_env_vars: billing_account: :BILLING_ACCT org_id: :ORG_ID diff --git a/mmv1/templates/terraform/resource.erb b/mmv1/templates/terraform/resource.erb index 67ec3ed00150..38461737ca95 100644 --- a/mmv1/templates/terraform/resource.erb +++ b/mmv1/templates/terraform/resource.erb @@ -1150,7 +1150,7 @@ func resource<%= resource_name -%>Import(d *schema.ResourceData, meta interface{ config := meta.(*transport_tpg.Config) if err := tpgresource.ParseImportId([]string{ <% for import_id in import_id_formats_from_resource(object) -%> - "<%= format2regex(import_id) %>", + "^<%= format2regex(import_id) %>$", <% end -%> }, d, config); err != nil { return nil, err diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_vpn_tunnel_test.go b/mmv1/third_party/terraform/services/compute/resource_compute_vpn_tunnel_test.go index 5c23da0895eb..1f67d5adf3b5 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_vpn_tunnel_test.go +++ b/mmv1/third_party/terraform/services/compute/resource_compute_vpn_tunnel_test.go @@ -31,7 +31,6 @@ func TestAccComputeVpnTunnel_regionFromGateway(t *testing.T) { ResourceName: "google_compute_vpn_tunnel.foobar", ImportState: true, ImportStateVerify: true, - ImportStateIdPrefix: fmt.Sprintf("%s/%s/", envvar.GetTestProjectFromEnv(), region), ImportStateVerifyIgnore: []string{"shared_secret", "detailed_status"}, }, }, diff --git a/mmv1/third_party/terraform/services/corebilling/resource_google_billing_project_info_test.go b/mmv1/third_party/terraform/services/corebilling/resource_google_billing_project_info_test.go index 67ea5ce04e93..feb75b3d7ad6 100644 --- a/mmv1/third_party/terraform/services/corebilling/resource_google_billing_project_info_test.go +++ b/mmv1/third_party/terraform/services/corebilling/resource_google_billing_project_info_test.go @@ -29,6 +29,7 @@ func TestAccBillingProjectInfo_update(t *testing.T) { ResourceName: "google_billing_project_info.info", ImportState: true, ImportStateVerify: true, + ImportStateId: fmt.Sprintf("projects/%s", projectId), }, { Config: testAccBillingProjectInfo_basic(projectId, orgId, ""), @@ -37,6 +38,7 @@ func TestAccBillingProjectInfo_update(t *testing.T) { ResourceName: "google_billing_project_info.info", ImportState: true, ImportStateVerify: true, + ImportStateId: fmt.Sprintf("projects/%s", projectId), }, { Config: testAccBillingProjectInfo_basic(projectId, orgId, billingAccount), @@ -45,6 +47,7 @@ func TestAccBillingProjectInfo_update(t *testing.T) { ResourceName: "google_billing_project_info.info", ImportState: true, ImportStateVerify: true, + ImportStateId: fmt.Sprintf("projects/%s", projectId), }, }, }) From f190b2c20d5a19423c8c9cefac3cdda963bf32f9 Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Mon, 25 Sep 2023 16:10:05 -0500 Subject: [PATCH 57/67] Change `consumer_accept_lists` to a set (#9058) --- mmv1/products/compute/ServiceAttachment.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/mmv1/products/compute/ServiceAttachment.yaml b/mmv1/products/compute/ServiceAttachment.yaml index 9b52db126f15..f913840817a1 100644 --- a/mmv1/products/compute/ServiceAttachment.yaml +++ b/mmv1/products/compute/ServiceAttachment.yaml @@ -193,6 +193,7 @@ properties: An array of projects that are allowed to connect to this service attachment. send_empty_value: true + is_set: true item_type: !ruby/object:Api::Type::NestedObject properties: - !ruby/object:Api::Type::String From f3f7fb0d32472358f0bd76e63dee4baa3c965204 Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Mon, 25 Sep 2023 16:30:39 -0500 Subject: [PATCH 58/67] Make `google_monitoring_metric_descriptor.labels` ForceNew (#8914) --- .../products/monitoring/MetricDescriptor.yaml | 2 +- ...ource_monitoring_metric_descriptor_test.go | 19 +++++++------------ 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/mmv1/products/monitoring/MetricDescriptor.yaml b/mmv1/products/monitoring/MetricDescriptor.yaml index b3b8f2c2b431..721677e7eba7 100644 --- a/mmv1/products/monitoring/MetricDescriptor.yaml +++ b/mmv1/products/monitoring/MetricDescriptor.yaml @@ -74,6 +74,7 @@ properties: The set of labels that can be used to describe a specific instance of this metric type. In order to delete a label, the entire resource must be deleted, then created with the desired labels. + immutable: true is_set: true item_type: !ruby/object:Api::Type::NestedObject properties: @@ -161,7 +162,6 @@ properties: Use sentence case without an ending period, for example "Request count". - !ruby/object:Api::Type::NestedObject name: metadata - immutable: true description: Metadata which can be used to guide usage of the metric. ignore_read: true properties: diff --git a/mmv1/third_party/terraform/services/monitoring/resource_monitoring_metric_descriptor_test.go b/mmv1/third_party/terraform/services/monitoring/resource_monitoring_metric_descriptor_test.go index a34cc21f54db..53ad4f17478e 100644 --- a/mmv1/third_party/terraform/services/monitoring/resource_monitoring_metric_descriptor_test.go +++ b/mmv1/third_party/terraform/services/monitoring/resource_monitoring_metric_descriptor_test.go @@ -9,8 +9,6 @@ import ( ) func TestAccMonitoringMetricDescriptor_update(t *testing.T) { - // TODO: Fix requires a breaking change https://github.com/hashicorp/terraform-provider-google/issues/12139 - t.Skip() t.Parallel() acctest.VcrTest(t, resource.TestCase{ @@ -19,8 +17,7 @@ func TestAccMonitoringMetricDescriptor_update(t *testing.T) { CheckDestroy: testAccCheckMonitoringMetricDescriptorDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccMonitoringMetricDescriptor_update("key1", "STRING", - "description1", "30s", "30s"), + Config: testAccMonitoringMetricDescriptor_update("30s", "30s"), }, { ResourceName: "google_monitoring_metric_descriptor.basic", @@ -29,8 +26,7 @@ func TestAccMonitoringMetricDescriptor_update(t *testing.T) { ImportStateVerifyIgnore: []string{"metadata", "launch_stage"}, }, { - Config: testAccMonitoringMetricDescriptor_update("key2", "INT64", - "description2", "60s", "60s"), + Config: testAccMonitoringMetricDescriptor_update("60s", "60s"), }, { ResourceName: "google_monitoring_metric_descriptor.basic", @@ -42,8 +38,7 @@ func TestAccMonitoringMetricDescriptor_update(t *testing.T) { }) } -func testAccMonitoringMetricDescriptor_update(key, valueType, description, - samplePeriod, ingestDelay string) string { +func testAccMonitoringMetricDescriptor_update(samplePeriod, ingestDelay string) string { return fmt.Sprintf(` resource "google_monitoring_metric_descriptor" "basic" { description = "Daily sales records from all branch stores." @@ -53,9 +48,9 @@ resource "google_monitoring_metric_descriptor" "basic" { value_type = "DOUBLE" unit = "{USD}" labels { - key = "%s" - value_type = "%s" - description = "%s" + key = "key" + value_type = "STRING" + description = "description" } launch_stage = "BETA" metadata { @@ -63,6 +58,6 @@ resource "google_monitoring_metric_descriptor" "basic" { ingest_delay = "%s" } } -`, key, valueType, description, samplePeriod, ingestDelay, +`, samplePeriod, ingestDelay, ) } From fc2e34e6d54b2f843ed14d6f4987fd01bdeb5daf Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Mon, 25 Sep 2023 16:38:31 -0500 Subject: [PATCH 59/67] 5.0.0 - Upgrade DCL to 1.52 (#9055) --- mmv1/third_party/terraform/go.mod.erb | 2 +- mmv1/third_party/terraform/go.sum | 4 ++-- tpgtools/go.mod | 2 +- tpgtools/go.sum | 2 ++ tpgtools/handwritten/tpgtools_utils.go | 22 +++++++++++++++++++ .../containeraws/beta/node_pool.yaml | 1 + .../cluster/beta_basic_enum_update.tf.tmpl | 4 ++++ .../samples/nodepool/beta_basic.tf.tmpl | 7 ++++++ .../nodepool/beta_basic_update.tf.tmpl | 7 ++++++ .../samples/release/firestore_release.yaml | 2 -- .../release/firestore_release_update.tf.tmpl | 22 ------------------- 11 files changed, 47 insertions(+), 28 deletions(-) delete mode 100644 tpgtools/overrides/firebaserules/samples/release/firestore_release_update.tf.tmpl diff --git a/mmv1/third_party/terraform/go.mod.erb b/mmv1/third_party/terraform/go.mod.erb index 544dd16ee673..1ff9b52ae7a9 100644 --- a/mmv1/third_party/terraform/go.mod.erb +++ b/mmv1/third_party/terraform/go.mod.erb @@ -4,7 +4,7 @@ go 1.19 require ( cloud.google.com/go/bigtable v1.19.0 - github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0 + github.com/GoogleCloudPlatform/declarative-resource-client-library v1.52.0 github.com/apparentlymart/go-cidr v1.1.0 github.com/davecgh/go-spew v1.1.1 github.com/dnaeon/go-vcr v1.0.1 diff --git a/mmv1/third_party/terraform/go.sum b/mmv1/third_party/terraform/go.sum index dab59d4c04e6..69175dcd310e 100644 --- a/mmv1/third_party/terraform/go.sum +++ b/mmv1/third_party/terraform/go.sum @@ -17,6 +17,8 @@ cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHS 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/GoogleCloudPlatform/declarative-resource-client-library v1.52.0 h1:KswxXF4E5iWv2ggktqv265zOvwmXA3mgma3UQfYA4tU= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.52.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= @@ -428,5 +430,3 @@ 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.51.0 h1:YhWTPhOf6gVpA9mSfnLOuL8Y6j8W5pzmHE7flXjTke4= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= diff --git a/tpgtools/go.mod b/tpgtools/go.mod index edb1c068553e..07832d3e80b4 100644 --- a/tpgtools/go.mod +++ b/tpgtools/go.mod @@ -4,7 +4,7 @@ go 1.19 require ( bitbucket.org/creachadair/stringset v0.0.11 - github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0 + github.com/GoogleCloudPlatform/declarative-resource-client-library v1.52.0 github.com/golang/glog v1.1.2 github.com/hashicorp/errwrap v1.0.0 github.com/hashicorp/hcl v1.0.0 diff --git a/tpgtools/go.sum b/tpgtools/go.sum index e0e118ffa9fc..981174d17fd5 100644 --- a/tpgtools/go.sum +++ b/tpgtools/go.sum @@ -45,6 +45,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 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/GoogleCloudPlatform/declarative-resource-client-library v1.52.0 h1:KswxXF4E5iWv2ggktqv265zOvwmXA3mgma3UQfYA4tU= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.52.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= diff --git a/tpgtools/handwritten/tpgtools_utils.go b/tpgtools/handwritten/tpgtools_utils.go index 68fa33e1d0e7..2e60238e3daa 100644 --- a/tpgtools/handwritten/tpgtools_utils.go +++ b/tpgtools/handwritten/tpgtools_utils.go @@ -1,6 +1,7 @@ package tpgdclresource import ( + "context" "fmt" "log" @@ -24,3 +25,24 @@ func HandleNotFoundDCLError(err error, d *schema.ResourceData, resourceName stri return errwrap.Wrapf( fmt.Sprintf("Error when reading or editing %s: {{err}}", resourceName), err) } + +func ResourceContainerAwsNodePoolCustomizeDiffFunc(_ context.Context, diff *schema.ResourceDiff, meta interface{}) error { + count := diff.Get("update_settings.#").(int) + if count < 1 { + return nil + } + + oMaxSurge, nMaxSurge := diff.GetChange("update_settings.0.surge_settings.0.max_surge") + oMaxUnavailable, nMaxUnavailable := diff.GetChange("update_settings.0.surge_settings.0.max_unavailable") + + // Server default of maxSurge = 1 and maxUnavailable = 0 is not returned + // Clear the diff if trying to resolve these specific values + if oMaxSurge == 0 && nMaxSurge == 1 && oMaxUnavailable == 0 && nMaxUnavailable == 0 { + err := diff.Clear("update_settings") + if err != nil { + return err + } + } + + return nil +} diff --git a/tpgtools/overrides/containeraws/beta/node_pool.yaml b/tpgtools/overrides/containeraws/beta/node_pool.yaml index 94a7935a2354..9a25ea0089a2 100644 --- a/tpgtools/overrides/containeraws/beta/node_pool.yaml +++ b/tpgtools/overrides/containeraws/beta/node_pool.yaml @@ -2,6 +2,7 @@ details: functions: - tpgresource.DefaultProviderProject + - tpgdclresource.ResourceContainerAwsNodePoolCustomizeDiffFunc - type: DIFF_SUPPRESS_FUNC field: config.root_volume.volume_type details: diff --git a/tpgtools/overrides/containeraws/samples/cluster/beta_basic_enum_update.tf.tmpl b/tpgtools/overrides/containeraws/samples/cluster/beta_basic_enum_update.tf.tmpl index e77928ece260..73b33d002742 100644 --- a/tpgtools/overrides/containeraws/samples/cluster/beta_basic_enum_update.tf.tmpl +++ b/tpgtools/overrides/containeraws/samples/cluster/beta_basic_enum_update.tf.tmpl @@ -14,6 +14,10 @@ resource "google_container_aws_cluster" "primary" { aws_region = "{{aws_region}}" + binary_authorization { + evaluation_mode = "PROJECT_SINGLETON_POLICY_ENFORCE" + } + control_plane { aws_services_authentication { role_arn = "arn:aws:iam::{{aws_account_id}}:role/{{byo_multicloud_prefix}}-1p-dev-oneplatform" diff --git a/tpgtools/overrides/containeraws/samples/nodepool/beta_basic.tf.tmpl b/tpgtools/overrides/containeraws/samples/nodepool/beta_basic.tf.tmpl index cc4db2389621..48e57734a938 100644 --- a/tpgtools/overrides/containeraws/samples/nodepool/beta_basic.tf.tmpl +++ b/tpgtools/overrides/containeraws/samples/nodepool/beta_basic.tf.tmpl @@ -159,6 +159,13 @@ resource "google_container_aws_node_pool" "primary" { label-one = "value-one" } + update_settings { + surge_settings { + max_surge = 1 + max_unavailable = 0 + } + } + project = "{{project}}" } diff --git a/tpgtools/overrides/containeraws/samples/nodepool/beta_basic_update.tf.tmpl b/tpgtools/overrides/containeraws/samples/nodepool/beta_basic_update.tf.tmpl index 42d8c055dbef..1afdb2e909b1 100644 --- a/tpgtools/overrides/containeraws/samples/nodepool/beta_basic_update.tf.tmpl +++ b/tpgtools/overrides/containeraws/samples/nodepool/beta_basic_update.tf.tmpl @@ -158,6 +158,13 @@ resource "google_container_aws_node_pool" "primary" { label-two = "value-two" } + update_settings { + surge_settings { + max_surge = 1 + max_unavailable = 0 + } + } + project = "{{project}}" } diff --git a/tpgtools/overrides/firebaserules/samples/release/firestore_release.yaml b/tpgtools/overrides/firebaserules/samples/release/firestore_release.yaml index 4ae842c1d411..814b4c37d22a 100644 --- a/tpgtools/overrides/firebaserules/samples/release/firestore_release.yaml +++ b/tpgtools/overrides/firebaserules/samples/release/firestore_release.yaml @@ -18,8 +18,6 @@ versions: - ga - beta resource: ./firestore_release.tf.tmpl -updates: -- resource: ./firestore_release_update.tf.tmpl variables: - name: project type: project \ No newline at end of file diff --git a/tpgtools/overrides/firebaserules/samples/release/firestore_release_update.tf.tmpl b/tpgtools/overrides/firebaserules/samples/release/firestore_release_update.tf.tmpl deleted file mode 100644 index d279c25e2a58..000000000000 --- a/tpgtools/overrides/firebaserules/samples/release/firestore_release_update.tf.tmpl +++ /dev/null @@ -1,22 +0,0 @@ -resource "google_firebaserules_release" "primary" { - name = "cloud.firestore" - ruleset_name = "projects/{{project}}/rulesets/${google_firebaserules_ruleset.firestore.name}" - project = "{{project}}" - - lifecycle { - replace_triggered_by = [ - google_firebaserules_ruleset.firestore - ] - } -} - -resource "google_firebaserules_ruleset" "firestore" { - source { - files { - content = "service cloud.firestore {match /databases/{database}/documents { match /{document=**} { allow read, write: if request.auth != null; } } }" - name = "firestore.rules" - } - } - - project = "{{project}}" -} From e59be4fa46b5fc77f612f52cdec8a9bb1aa7ba88 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Mon, 25 Sep 2023 15:07:15 -0700 Subject: [PATCH 60/67] Labels compute instance template (#9051) * Apply labels model to compute instance template * Check if terraform_labels and effective_labels are in schema * Test out of band labels --- mmv1/api/resource.rb | 7 ++ mmv1/api/type.rb | 2 +- mmv1/products/bigquery/Dataset.yaml | 5 +- mmv1/products/compute/Address.yaml | 3 - .../resource_bigquery_dataset_test.go | 81 +++++++++++++++++++ ...ce_google_compute_instance_template.go.erb | 10 ++- ...e_google_compute_instance_template_test.go | 3 + ...le_compute_region_instance_template.go.erb | 5 +- ...mpute_region_instance_template_test.go.erb | 3 + .../resource_compute_instance_template.go.erb | 18 ++++- ...urce_compute_instance_template_test.go.erb | 12 +-- ...ce_compute_region_instance_template.go.erb | 35 +++++++- ...mpute_region_instance_template_test.go.erb | 5 ++ .../terraform/tpgresource/annotations.go | 8 ++ .../terraform/tpgresource/labels.go | 28 +++++-- .../docs/r/bigquery_table.html.markdown | 3 + .../docs/r/bigtable_instance.html.markdown | 3 + .../r/compute_instance_template.html.markdown | 7 +- ...ute_region_instance_template.html.markdown | 9 +++ 19 files changed, 216 insertions(+), 31 deletions(-) diff --git a/mmv1/api/resource.rb b/mmv1/api/resource.rb index 71c16a4200ac..f586196428d3 100644 --- a/mmv1/api/resource.rb +++ b/mmv1/api/resource.rb @@ -474,6 +474,7 @@ def add_labels_related_fields(props, parent) def add_labels_fields(props, parent, 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)}" @custom_diff ||= [] if parent.nil? || parent.flatten_object @@ -547,6 +548,12 @@ def ignore_read_labels_fields(props) 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 # ==================== diff --git a/mmv1/api/type.rb b/mmv1/api/type.rb index 0d81c8335929..130cd2cec617 100644 --- a/mmv1/api/type.rb +++ b/mmv1/api/type.rb @@ -23,7 +23,7 @@ module Fields include Api::Object::Named::Properties attr_reader :default_value - attr_reader :description + attr_accessor :description attr_reader :exclude # Add a deprecation message for a field that's been deprecated in the API diff --git a/mmv1/products/bigquery/Dataset.yaml b/mmv1/products/bigquery/Dataset.yaml index 2fb36dfc2c06..41c0fbf1491d 100644 --- a/mmv1/products/bigquery/Dataset.yaml +++ b/mmv1/products/bigquery/Dataset.yaml @@ -294,10 +294,7 @@ properties: name: 'labels' description: | The labels associated with this dataset. You can use these to - organize and group your datasets - - **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. - Please refer to the field `effective_labels` for all of the labels present on the resource. + organize and group your datasets. - !ruby/object:Api::Type::Integer name: 'lastModifiedTime' description: | diff --git a/mmv1/products/compute/Address.yaml b/mmv1/products/compute/Address.yaml index ddf3a7f329ba..43ac9b0420a6 100644 --- a/mmv1/products/compute/Address.yaml +++ b/mmv1/products/compute/Address.yaml @@ -198,9 +198,6 @@ properties: name: 'labels' description: | Labels to apply to this address. A list of key->value pairs. - - **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. - Please refer to the field `effective_labels` for all of the labels present on the resource. update_verb: :POST update_url: 'projects/{{project}}/regions/{{region}}/addresses/{{name}}/setLabels' min_version: beta 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 e7aa05f777d4..11c14014ace9 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 @@ -137,6 +137,49 @@ func TestAccBigQueryDataset_withProvider5(t *testing.T) { }) } +func TestAccBigQueryDataset_withOutOfBandLabels(t *testing.T) { + 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), + CheckDestroy: testAccCheckBigQueryDatasetDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigQueryDataset(datasetID), + Check: addOutOfBandLabels(t, datasetID), + }, + { + ResourceName: "google_bigquery_dataset.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"delete_contents_on_destroy", "labels", "terraform_labels"}, + }, + { + Config: testAccBigQueryDatasetUpdated(datasetID), + }, + { + ResourceName: "google_bigquery_dataset.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"delete_contents_on_destroy", "labels", "terraform_labels"}, + }, + { + Config: testAccBigQueryDatasetUpdated_withOutOfBandLabels(datasetID), + }, + { + ResourceName: "google_bigquery_dataset.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"delete_contents_on_destroy", "labels", "terraform_labels"}, + }, + }, + }) +} + func TestAccBigQueryDataset_datasetWithContents(t *testing.T) { t.Parallel() @@ -302,6 +345,25 @@ func testAccAddTable(t *testing.T, datasetID string, tableID string) resource.Te } } +func addOutOfBandLabels(t *testing.T, datasetID string) resource.TestCheckFunc { + // Not actually a check, but adds labels independently of terraform + return func(s *terraform.State) error { + config := acctest.GoogleProviderConfig(t) + + dataset, err := config.NewBigQueryClient(config.UserAgent).Datasets.Get(config.Project, datasetID).Do() + if err != nil { + return fmt.Errorf("Could not get dataset with ID %s", datasetID) + } + + dataset.Labels["outband_key"] = "test" + _, err = config.NewBigQueryClient(config.UserAgent).Datasets.Patch(config.Project, datasetID, dataset).Do() + if err != nil { + return fmt.Errorf("Could not update labele for the dataset") + } + return nil + } +} + func testAccBigQueryDataset_withoutLabels(datasetID string) string { return fmt.Sprintf(` resource "google_bigquery_dataset" "test" { @@ -351,6 +413,25 @@ resource "google_bigquery_dataset" "test" { `, datasetID) } +func testAccBigQueryDatasetUpdated_withOutOfBandLabels(datasetID string) string { + return fmt.Sprintf(` +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 = "bar" + default_table_expiration_ms = 7200000 + outband_key = "test-update" + } +} +`, datasetID) +} + func testAccBigQueryDatasetUpdated2(datasetID string) string { return fmt.Sprintf(` resource "google_bigquery_dataset" "test" { diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_template.go.erb b/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_template.go.erb index ee82da732187..bd0cdca09643 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_template.go.erb +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_template.go.erb @@ -92,7 +92,10 @@ func datasourceComputeInstanceTemplateRead(d *schema.ResourceData, meta interfac func retrieveInstance(d *schema.ResourceData, meta interface{}, project, name string) error { d.SetId("projects/" + project + "/global/instanceTemplates/" + name) - return resourceComputeInstanceTemplateRead(d, meta) + if err := resourceComputeInstanceTemplateRead(d, meta); err != nil { + return err + } + return tpgresource.SetDataSourceLabels(d) } func retrieveInstanceFromUniqueId(d *schema.ResourceData, meta interface{}, project, self_link_unique string) error { @@ -100,7 +103,10 @@ func retrieveInstanceFromUniqueId(d *schema.ResourceData, meta interface{}, proj d.SetId(normalId) d.Set("self_link_unique", self_link_unique) - return resourceComputeInstanceTemplateRead(d, meta) + if err := resourceComputeInstanceTemplateRead(d, meta); err != nil { + return err + } + return tpgresource.SetDataSourceLabels(d) } // ByCreationTimestamp implements sort.Interface for []*InstanceTemplate based on diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_template_test.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_template_test.go index 9ed0dffc7f67..ef8e82a26180 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_template_test.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_template_test.go @@ -115,6 +115,9 @@ resource "google_compute_instance_template" "default" { network_interface { network = "default" } + labels = { + my-label = "my-label-value" + } } data "google_compute_instance_template" "default" { diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_template.go.erb b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_template.go.erb index 6ebe245ba3ae..e69a2857ff38 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_template.go.erb +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_template.go.erb @@ -124,5 +124,8 @@ func datasourceComputeRegionInstanceTemplateRead(d *schema.ResourceData, meta in func retrieveInstances(d *schema.ResourceData, meta interface{}, project, region, name string) error { d.SetId("projects/" + project + "/regions/" + region + "/instanceTemplates/" + name) - return resourceComputeRegionInstanceTemplateRead(d, meta) + if err := resourceComputeRegionInstanceTemplateRead(d, meta); err != nil { + return err + } + return tpgresource.SetDataSourceLabels(d) } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_template_test.go.erb b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_template_test.go.erb index 6c32fddcb0d6..73a4d1fa09f0 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_template_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_template_test.go.erb @@ -91,6 +91,9 @@ resource "google_compute_region_instance_template" "default" { network_interface { network = "default" } + labels = { + my-label = "my-label-value" + } } data "google_compute_region_instance_template" "default" { project = "%{project}" diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb index 277825a3428b..d20b70d5b532 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb @@ -66,6 +66,7 @@ func ResourceComputeInstanceTemplate() *schema.Resource { resourceComputeInstanceTemplateSourceImageCustomizeDiff, resourceComputeInstanceTemplateScratchDiskCustomizeDiff, resourceComputeInstanceTemplateBootDiskCustomizeDiff, + tpgresource.SetLabelsDiff, ), MigrateState: resourceComputeInstanceTemplateMigrateState, @@ -927,9 +928,19 @@ be from 0 to 999,999,999 inclusive.`, Please refer to the field 'effective_labels' for all of the labels present on the resource.`, }, + "terraform_labels": { + Type: schema.TypeMap, + Computed: true, + Set: schema.HashString, + Description: `The combination of labels configured directly on the resource and default labels configured on the provider.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "effective_labels": { Type: schema.TypeMap, Computed: true, + ForceNew: true, + Set: schema.HashString, Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, Elem: &schema.Schema{Type: schema.TypeString}, }, @@ -1320,8 +1331,8 @@ func resourceComputeInstanceTemplateCreate(d *schema.ResourceData, meta interfac ReservationAffinity: reservationAffinity, } - if _, ok := d.GetOk("labels"); ok { - instanceProperties.Labels = tpgresource.ExpandLabels(d) + if _, ok := d.GetOk("effective_labels"); ok { + instanceProperties.Labels = tpgresource.ExpandEffectiveLabels(d) } var itName string @@ -1649,6 +1660,9 @@ func resourceComputeInstanceTemplateRead(d *schema.ResourceData, meta interface{ return fmt.Errorf("Error setting labels: %s", err) } } + if err := tpgresource.SetLabels(instanceTemplate.Properties.Labels, d, "terraform_labels"); err != nil { + return fmt.Errorf("Error setting terraform_labels: %s", err) + } if err := d.Set("effective_labels", instanceTemplate.Properties.Labels); err != nil { return fmt.Errorf("Error setting effective_labels: %s", err) } diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.erb index eabe9c303cb4..d5e7c5470303 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.erb @@ -51,7 +51,7 @@ func TestAccComputeInstanceTemplate_basic(t *testing.T) { ResourceName: "google_compute_instance_template.foobar", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"labels"}, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -78,7 +78,7 @@ func TestAccComputeInstanceTemplate_imageShorthand(t *testing.T) { ResourceName: "google_compute_instance_template.foobar", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"labels"}, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -135,7 +135,7 @@ func TestAccComputeInstanceTemplate_maintenance_interval(t *testing.T) { ResourceName: "google_compute_instance_template.foobar", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"labels"}, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccComputeInstanceTemplate_basic(acctest.RandString(t, 10)), @@ -612,7 +612,7 @@ func TestAccComputeInstanceTemplate_EncryptKMS(t *testing.T) { ResourceName: "google_compute_instance_template.foobar", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"labels"}, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -944,7 +944,7 @@ func TestAccComputeInstanceTemplate_diskResourcePolicies(t *testing.T) { ResourceName: "google_compute_instance_template.foobar", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"labels"}, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -1022,7 +1022,7 @@ func TestAccComputeInstanceTemplate_managedEnvoy(t *testing.T) { ResourceName: "google_compute_instance_template.foobar", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"labels"}, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.erb index ada53db8730c..e2a2182a2e6f 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.erb @@ -39,6 +39,7 @@ func ResourceComputeRegionInstanceTemplate() *schema.Resource { resourceComputeInstanceTemplateSourceImageCustomizeDiff, resourceComputeInstanceTemplateScratchDiskCustomizeDiff, resourceComputeInstanceTemplateBootDiskCustomizeDiff, + tpgresource.SetLabelsDiff, ), Timeouts: &schema.ResourceTimeout{ @@ -877,7 +878,27 @@ be from 0 to 999,999,999 inclusive.`, ForceNew: true, Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, - Description: `A set of key/value label pairs to assign to instances created from this template,`, + Description: `A set of key/value label pairs to assign to instances created from this template, + + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field 'effective_labels' for all of the labels present on the resource.`, + }, + + "terraform_labels": { + Type: schema.TypeMap, + Computed: true, + Set: schema.HashString, + Description: `The combination of labels configured directly on the resource and default labels configured on the provider.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + + "effective_labels": { + Type: schema.TypeMap, + Computed: true, + ForceNew: true, + Set: schema.HashString, + Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, + Elem: &schema.Schema{Type: schema.TypeString}, }, "resource_policies": { @@ -1010,8 +1031,8 @@ func resourceComputeRegionInstanceTemplateCreate(d *schema.ResourceData, meta in ReservationAffinity: reservationAffinity, } - if _, ok := d.GetOk("labels"); ok { - instanceProperties.Labels = tpgresource.ExpandLabels(d) + if _, ok := d.GetOk("effective_labels"); ok { + instanceProperties.Labels = tpgresource.ExpandEffectiveLabels(d) } var itName string @@ -1137,10 +1158,16 @@ func resourceComputeRegionInstanceTemplateRead(d *schema.ResourceData, meta inte } } if instanceProperties.Labels != nil { - if err := d.Set("labels", instanceProperties.Labels); err != nil { + if err := tpgresource.SetLabels(instanceProperties.Labels, d, "labels"); err != nil { return fmt.Errorf("Error setting labels: %s", err) } } + if err := tpgresource.SetLabels(instanceProperties.Labels, d, "terraform_labels"); err != nil { + return fmt.Errorf("Error setting terraform_labels: %s", err) + } + if err := d.Set("effective_labels", instanceProperties.Labels); err != nil { + return fmt.Errorf("Error setting effective_labels: %s", err) + } if err = d.Set("self_link", instanceTemplate["selfLink"]); err != nil { return fmt.Errorf("Error setting self_link: %s", err) } diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.erb index f53fdba3c3c6..bef9e29f4526 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.erb @@ -50,6 +50,7 @@ func TestAccComputeRegionInstanceTemplate_basic(t *testing.T) { ResourceName: "google_compute_region_instance_template.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -76,6 +77,7 @@ func TestAccComputeRegionInstanceTemplate_imageShorthand(t *testing.T) { ResourceName: "google_compute_region_instance_template.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -767,6 +769,7 @@ func TestAccComputeRegionInstanceTemplate_maintenance_interval(t *testing.T) { ResourceName: "google_compute_region_instance_template.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccComputeRegionInstanceTemplate_basic(acctest.RandString(t, 10)), @@ -894,6 +897,7 @@ func TestAccComputeRegionInstanceTemplate_diskResourcePolicies(t *testing.T) { ResourceName: "google_compute_region_instance_template.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -971,6 +975,7 @@ func TestAccComputeRegionInstanceTemplate_managedEnvoy(t *testing.T) { ResourceName: "google_compute_region_instance_template.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/tpgresource/annotations.go b/mmv1/third_party/terraform/tpgresource/annotations.go index 3739a0cea62b..410fbd2355d4 100644 --- a/mmv1/third_party/terraform/tpgresource/annotations.go +++ b/mmv1/third_party/terraform/tpgresource/annotations.go @@ -13,6 +13,10 @@ func SetAnnotationsDiff(_ context.Context, d *schema.ResourceDiff, meta interfac return nil } + if d.Get("effective_annotations") == nil { + return fmt.Errorf("`effective_annotations` field is not present in the resource schema.") + } + o, n := d.GetChange("annotations") effectiveAnnotations := d.Get("effective_annotations").(map[string]interface{}) @@ -44,6 +48,10 @@ func SetMetadataAnnotationsDiff(_ context.Context, d *schema.ResourceDiff, meta return nil } + if d.Get("metadata.0.effective_annotations") == nil { + return fmt.Errorf("`metadata.0.effective_annotations` field is not present in the resource schema.") + } + o, n := d.GetChange("metadata.0.annotations") effectiveAnnotations := d.Get("metadata.0.effective_annotations").(map[string]interface{}) diff --git a/mmv1/third_party/terraform/tpgresource/labels.go b/mmv1/third_party/terraform/tpgresource/labels.go index 29b40a4c3ca8..d8ff6bab6f43 100644 --- a/mmv1/third_party/terraform/tpgresource/labels.go +++ b/mmv1/third_party/terraform/tpgresource/labels.go @@ -20,7 +20,7 @@ func SetLabels(labels map[string]string, d *schema.ResourceData, lineage string) if v, ok := d.GetOk(lineage); ok { if labels != nil { - for k, _ := range v.(map[string]interface{}) { + for k := range v.(map[string]interface{}) { transformed[k] = labels[k] } } @@ -56,6 +56,19 @@ func SetDataSourceLabels(d *schema.ResourceData) error { } func SetLabelsDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) error { + raw := d.Get("labels") + if raw == nil { + return nil + } + + if d.Get("terraform_labels") == nil { + return fmt.Errorf("`terraform_labels` field is not present in the resource schema.") + } + + if d.Get("effective_labels") == nil { + return fmt.Errorf("`effective_labels` field is not present in the resource schema.") + } + config := meta.(*transport_tpg.Config) // Merge provider default labels with the user defined labels in the resource to get terraform managed labels @@ -64,11 +77,6 @@ func SetLabelsDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) terraformLabels[k] = v } - raw := d.Get("labels") - if raw == nil { - return nil - } - labels := raw.(map[string]interface{}) for k, v := range labels { terraformLabels[k] = v.(string) @@ -109,6 +117,14 @@ func SetMetadataLabelsDiff(_ context.Context, d *schema.ResourceDiff, meta inter return nil } + if d.Get("metadata.0.terraform_labels") == nil { + return fmt.Errorf("`metadata.0.terraform_labels` field is not present in the resource schema.") + } + + if d.Get("metadata.0.effective_labels") == nil { + return fmt.Errorf("`metadata.0.effective_labels` field is not present in the resource schema.") + } + config := meta.(*transport_tpg.Config) // Merge provider default labels with the user defined labels in the resource to get terraform managed labels diff --git a/mmv1/third_party/terraform/website/docs/r/bigquery_table.html.markdown b/mmv1/third_party/terraform/website/docs/r/bigquery_table.html.markdown index 78d4668a668c..929a8e8f2c70 100644 --- a/mmv1/third_party/terraform/website/docs/r/bigquery_table.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/bigquery_table.html.markdown @@ -114,6 +114,9 @@ The following arguments are supported: * `labels` - (Optional) A mapping of labels to assign to the resource. + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field 'effective_labels' for all of the labels present on the resource. + * `terraform_labels` - The combination of labels configured directly on the resource and default labels configured on the provider. diff --git a/mmv1/third_party/terraform/website/docs/r/bigtable_instance.html.markdown b/mmv1/third_party/terraform/website/docs/r/bigtable_instance.html.markdown index 0a9b88877615..9f64f4873d6d 100644 --- a/mmv1/third_party/terraform/website/docs/r/bigtable_instance.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/bigtable_instance.html.markdown @@ -102,6 +102,9 @@ in Terraform state, a `terraform destroy` or `terraform apply` that would delete * `labels` - (Optional) A set of key/value label pairs to assign to the resource. Label keys must follow the requirements at https://cloud.google.com/resource-manager/docs/creating-managing-labels#requirements. + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field 'effective_labels' for all of the labels present on the resource. + * `terraform_labels` - The combination of labels configured directly on the resource and default labels configured on the provider. diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown index b6c5fe8b88d1..a1c450d39ccf 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown @@ -308,8 +308,11 @@ The following arguments are supported: * `labels` - (Optional) A set of key/value label pairs to assign to instances created from this template. - **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. - Please refer to the field 'effective_labels' for all of the labels present on the resource. + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field 'effective_labels' for all of the labels present on the resource. + +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. * `effective_labels` - All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. diff --git a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown index 4e1c3a29838f..5364b3197115 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown @@ -320,6 +320,15 @@ The following arguments are supported: * `labels` - (Optional) A set of key/value label pairs to assign to instances created from this template. + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field 'effective_labels' for all of the labels present on the resource. + +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. + * `metadata` - (Optional) Metadata key/value pairs to make available from within instances created from this template. From e19357fe69c9fc02fe1be4836302a68fa7e6195f Mon Sep 17 00:00:00 2001 From: Nick Elliot Date: Tue, 26 Sep 2023 07:38:43 -0700 Subject: [PATCH 61/67] improve autoscaling_policy support in google_compute_node_group (#9044) --- mmv1/products/compute/NodeGroup.yaml | 25 ++--- .../examples/node_group_basic.tf.erb | 2 +- .../examples/node_group_share_settings.tf.erb | 2 +- .../compute_node_group_url_replace.go.erb | 10 +- .../resource_compute_instance_test.go.erb | 8 +- .../resource_compute_node_group_test.go.erb | 95 ++++++++++++++++--- .../resource_container_cluster_test.go.erb | 2 +- .../resource_container_node_pool_test.go.erb | 2 +- .../resource_dataproc_cluster_test.go.erb | 2 +- 9 files changed, 107 insertions(+), 41 deletions(-) diff --git a/mmv1/products/compute/NodeGroup.yaml b/mmv1/products/compute/NodeGroup.yaml index 63e3ab1a8f8d..fbc77e550ea5 100644 --- a/mmv1/products/compute/NodeGroup.yaml +++ b/mmv1/products/compute/NodeGroup.yaml @@ -16,10 +16,11 @@ name: 'NodeGroup' kind: 'compute#NodeGroup' base_url: projects/{{project}}/zones/{{zone}}/nodeGroups create_url: projects/{{project}}/zones/{{zone}}/nodeGroups?initialNodeCount=PRE_CREATE_REPLACE_ME +update_verb: :PATCH +update_mask: true has_self_link: true description: | Represents a NodeGroup resource to manage a group of sole-tenant nodes. -immutable: true references: !ruby/object:Api::Resource::ReferenceLinks guides: 'Sole-Tenant Nodes': 'https://cloud.google.com/compute/docs/nodes/' @@ -43,12 +44,6 @@ async: !ruby/object:Api::OpAsync error: !ruby/object:Api::OpAsync::Error path: 'error/errors' message: 'message' -docs: !ruby/object:Provider::Terraform::Docs - warning: | - Due to limitations of the API, Terraform cannot update the - number of nodes in a node group and changes to node group size either - through Terraform config or through external changes will cause - Terraform to delete and recreate the node group. examples: - !ruby/object:Provider::Terraform::Examples name: 'node_group_basic' @@ -112,21 +107,13 @@ properties: - !ruby/object:Api::Type::Integer name: 'size' description: | - The total number of nodes in the node group. One of `initial_size` or `size` must be specified. - immutable: true - send_empty_value: true - default_from_api: true - exactly_one_of: - - size - - initial_size + The total number of nodes in the node group. + output: true - !ruby/object:Api::Type::Integer name: 'initialSize' description: | - The initial number of nodes in the node group. One of `initial_size` or `size` must be specified. + The initial number of nodes in the node group. One of `initial_size` or `autoscaling_policy` must be configured on resource creation. url_param_only: true - exactly_one_of: - - size - - initial_size - !ruby/object:Api::Type::String name: 'maintenancePolicy' description: | @@ -147,6 +134,8 @@ properties: description: | If you use sole-tenant nodes for your workloads, you can use the node group autoscaler to automatically manage the sizes of your node groups. + + One of `initial_size` or `autoscaling_policy` must be configured on resource creation. default_from_api: true properties: - !ruby/object:Api::Type::Enum diff --git a/mmv1/templates/terraform/examples/node_group_basic.tf.erb b/mmv1/templates/terraform/examples/node_group_basic.tf.erb index 39b32a385c4d..3ed5b02dd02b 100644 --- a/mmv1/templates/terraform/examples/node_group_basic.tf.erb +++ b/mmv1/templates/terraform/examples/node_group_basic.tf.erb @@ -9,6 +9,6 @@ resource "google_compute_node_group" "<%= ctx[:primary_resource_id] %>" { zone = "us-central1-f" description = "example google_compute_node_group for Terraform Google Provider" - size = 1 + initial_size = 1 node_template = google_compute_node_template.soletenant-tmpl.id } diff --git a/mmv1/templates/terraform/examples/node_group_share_settings.tf.erb b/mmv1/templates/terraform/examples/node_group_share_settings.tf.erb index 278cd3f0ffbb..b2658a831187 100644 --- a/mmv1/templates/terraform/examples/node_group_share_settings.tf.erb +++ b/mmv1/templates/terraform/examples/node_group_share_settings.tf.erb @@ -15,7 +15,7 @@ resource "google_compute_node_group" "<%= ctx[:primary_resource_id] %>" { zone = "us-central1-f" description = "example google_compute_node_group for Terraform Google Provider" - size = 1 + initial_size = 1 node_template = google_compute_node_template.soletenant-tmpl.id share_settings { diff --git a/mmv1/templates/terraform/pre_create/compute_node_group_url_replace.go.erb b/mmv1/templates/terraform/pre_create/compute_node_group_url_replace.go.erb index 62e4828bb500..a85b927ba68a 100644 --- a/mmv1/templates/terraform/pre_create/compute_node_group_url_replace.go.erb +++ b/mmv1/templates/terraform/pre_create/compute_node_group_url_replace.go.erb @@ -1,8 +1,12 @@ var sizeParam string -if v, ok := d.GetOkExists("size"); ok { - sizeParam = fmt.Sprintf("%v", v) -} else if v, ok := d.GetOkExists("initial_size"); ok { +if v, ok := d.GetOkExists("initial_size"); ok { sizeParam = fmt.Sprintf("%v", v) +}else{ + if _, ok := d.GetOkExists("autoscaling_policy"); ok{ + sizeParam = fmt.Sprintf("%v", d.Get("autoscaling_policy.min_nodes")) + }else{ + return errors.New("An initial_size or autoscaling_policy must be configured on node group creation.") + } } url = regexp.MustCompile("PRE_CREATE_REPLACE_ME").ReplaceAllLiteralString(url, sizeParam) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.erb index b33511f682d4..a0ca3490284d 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.erb @@ -5996,7 +5996,7 @@ resource "google_compute_node_group" "nodes" { name = "%s" zone = "us-central1-a" - size = 1 + initial_size = 1 node_template = google_compute_node_template.nodetmpl.self_link } `, instance, nodeTemplate, nodeGroup) @@ -6065,7 +6065,7 @@ resource "google_compute_node_group" "nodes" { name = "%s" zone = "us-central1-a" - size = 1 + initial_size = 1 node_template = google_compute_node_template.nodetmpl.self_link } `, instance, nodeTemplate, nodeGroup) @@ -6134,7 +6134,7 @@ resource "google_compute_node_group" "nodes" { name = "%s" zone = "us-central1-a" - size = 1 + initial_size = 1 node_template = google_compute_node_template.nodetmpl.self_link } `, instance, nodeTemplate, nodeGroup) @@ -6197,7 +6197,7 @@ resource "google_compute_node_group" "nodes" { name = "%s" zone = "us-central1-a" - size = 1 + initial_size = 1 node_template = google_compute_node_template.nodetmpl.self_link } `, instance, nodeTemplate, nodeGroup) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_node_group_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_node_group_test.go.erb index a09008450907..a713c5e78e49 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_node_group_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_node_group_test.go.erb @@ -8,12 +8,14 @@ import ( "strings" "time" + "regexp" + "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" ) -func TestAccComputeNodeGroup_updateNodeTemplate(t *testing.T) { +func TestAccComputeNodeGroup_update(t *testing.T) { t.Parallel() groupName := fmt.Sprintf("group--%d", acctest.RandInt(t)) @@ -26,26 +28,47 @@ func TestAccComputeNodeGroup_updateNodeTemplate(t *testing.T) { CheckDestroy: testAccCheckComputeNodeGroupDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccComputeNodeGroup_updateNodeTemplate(groupName, tmplPrefix, "tmpl1"), + Config: testAccComputeNodeGroup_update(groupName, tmplPrefix, "tmpl1"), Check: resource.ComposeTestCheckFunc( testAccCheckComputeNodeGroupCreationTimeBefore(&timeCreated), ), }, { - ResourceName: "google_compute_node_group.nodes", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_compute_node_group.nodes", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"initial_size"}, }, { - Config: testAccComputeNodeGroup_updateNodeTemplate(groupName, tmplPrefix, "tmpl2"), + Config: testAccComputeNodeGroup_update2(groupName, tmplPrefix, "tmpl2"), Check: resource.ComposeTestCheckFunc( testAccCheckComputeNodeGroupCreationTimeBefore(&timeCreated), ), }, { - ResourceName: "google_compute_node_group.nodes", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_compute_node_group.nodes", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"initial_size"}, + }, + }, + }) +} + +func TestAccComputeNodeGroup_fail(t *testing.T) { + t.Parallel() + + groupName := fmt.Sprintf("group--%d", acctest.RandInt(t)) + tmplPrefix := fmt.Sprintf("tmpl--%d", acctest.RandInt(t)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeNodeGroupDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeNodeGroup_fail(groupName, tmplPrefix, "tmpl1"), + ExpectError: regexp.MustCompile("An initial_size or autoscaling_policy must be configured on node group creation."), }, }, }) @@ -86,7 +109,7 @@ func testAccCheckComputeNodeGroupCreationTimeBefore(prevTimeCreated *time.Time) } } -func testAccComputeNodeGroup_updateNodeTemplate(groupName, tmplPrefix, tmplToUse string) string { +func testAccComputeNodeGroup_update(groupName, tmplPrefix, tmplToUse string) string { return fmt.Sprintf(` resource "google_compute_node_template" "tmpl1" { name = "%s-first" @@ -105,8 +128,58 @@ resource "google_compute_node_group" "nodes" { zone = "us-central1-a" description = "example google_compute_node_group for Terraform Google Provider" - size = 0 + initial_size = 1 node_template = google_compute_node_template.%s.self_link } + `, tmplPrefix, tmplPrefix, groupName, tmplToUse) } + +func testAccComputeNodeGroup_update2(groupName, tmplPrefix, tmplToUse string) string { + return fmt.Sprintf(` +resource "google_compute_node_template" "tmpl1" { + name = "%s-first" + region = "us-central1" + node_type = "n1-node-96-624" +} + +resource "google_compute_node_template" "tmpl2" { + name = "%s-second" + region = "us-central1" + node_type = "n1-node-96-624" +} + +resource "google_compute_node_group" "nodes" { + name = "%s" + zone = "us-central1-a" + description = "example google_compute_node_group for Terraform Google Provider" + + autoscaling_policy { + mode = "ONLY_SCALE_OUT" + min_nodes = 1 + max_nodes = 10 + } + node_template = google_compute_node_template.%s.self_link +} + +`, tmplPrefix, tmplPrefix, groupName, tmplToUse) +} + +func testAccComputeNodeGroup_fail(groupName, tmplPrefix, tmplToUse string) string { + return fmt.Sprintf(` +resource "google_compute_node_template" "tmpl1" { + name = "%s-first" + region = "us-central1" + node_type = "n1-node-96-624" +} + +resource "google_compute_node_group" "nodes" { + name = "%s" + zone = "us-central1-a" + description = "example google_compute_node_group for Terraform Google Provider" + + node_template = google_compute_node_template.%s.self_link +} + +`, tmplPrefix, groupName, tmplToUse) +} diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb index c30d5538b362..d3d0cad4e982 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb @@ -7963,7 +7963,7 @@ resource "google_compute_node_group" "group" { zone = "us-central1-f" description = "example google_compute_node_group for Terraform Google Provider" - size = 1 + initial_size = 1 node_template = google_compute_node_template.soletenant-tmpl.id } 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 893e312951f7..11a4f1d43c61 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 @@ -3246,7 +3246,7 @@ resource "google_compute_node_template" "soletenant-tmpl" { resource "google_compute_node_group" "nodes" { name = "tf-test-soletenant-group" zone = "us-central1-a" - size = 1 + initial_size = 1 node_template = google_compute_node_template.soletenant-tmpl.id } 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 6bfe91fdfba7..7f0ffe052456 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 @@ -1429,7 +1429,7 @@ resource "google_compute_node_group" "nodes" { name = "test-nodegroup-%s" zone = "us-central1-f" - size = 3 + initial_size = 3 node_template = google_compute_node_template.nodetmpl.self_link } From 2257c1963612202f1a6c42c1adca118c3272f312 Mon Sep 17 00:00:00 2001 From: Naitian Liu <83430653+naitianliu-google@users.noreply.github.com> Date: Tue, 26 Sep 2023 13:20:47 -0700 Subject: [PATCH 62/67] Disable delete for bare metal admin cluster resource (#8823) --- mmv1/products/gkeonprem/BareMetalAdminCluster.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mmv1/products/gkeonprem/BareMetalAdminCluster.yaml b/mmv1/products/gkeonprem/BareMetalAdminCluster.yaml index 7dc763a8b3a9..38df22b5972e 100644 --- a/mmv1/products/gkeonprem/BareMetalAdminCluster.yaml +++ b/mmv1/products/gkeonprem/BareMetalAdminCluster.yaml @@ -16,17 +16,16 @@ min_version: beta base_url: "projects/{{project}}/locations/{{location}}/bareMetalAdminClusters" create_url: "projects/{{project}}/locations/{{location}}/bareMetalAdminClusters?bare_metal_admin_cluster_id={{name}}" update_url: "projects/{{project}}/locations/{{location}}/bareMetalAdminClusters/{{name}}" -delete_url: "projects/{{project}}/locations/{{location}}/bareMetalAdminClusters/{{name}}:unenroll?ignore_errors=true" self_link: "projects/{{project}}/locations/{{location}}/bareMetalAdminClusters/{{name}}" update_verb: :PATCH update_mask: true autogen_async: false id_format: "projects/{{project}}/locations/{{location}}/bareMetalAdminClusters/{{name}}" import_format: ["projects/{{project}}/locations/{{location}}/bareMetalAdminClusters/{{name}}"] +skip_delete: true taint_resource_on_failed_create: true timeouts: !ruby/object:Api::Timeouts insert_minutes: 60 - delete_minutes: 60 update_minutes: 60 description: "A Google Bare Metal Admin Cluster." examples: From 887cf20361e24219d0e428add36083d9b6c151f8 Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Tue, 26 Sep 2023 16:48:51 -0500 Subject: [PATCH 63/67] Add deletion_protection to container cluster (#9013) --- .../compute/InstanceGroupNamedPort.yaml | 5 + .../compute/NetworkPeeringRoutesConfig.yaml | 5 + mmv1/products/dns/ManagedZone.yaml | 5 + mmv1/products/dns/ResponsePolicy.yaml | 5 + mmv1/products/gkebackup/BackupPlan.yaml | 20 + mmv1/products/gkebackup/RestorePlan.yaml | 30 + mmv1/products/gkehub/Membership.yaml | 10 + mmv1/products/gkehub2/MembershipBinding.yaml | 5 + .../gkehub2/MembershipRBACRoleBinding.yaml | 5 + .../dns_managed_zone_private_gke.tf.erb | 1 + .../examples/dns_response_policy_basic.tf.erb | 1 + .../gkebackup_backupplan_autopilot.tf.erb | 1 + .../gkebackup_backupplan_basic.tf.erb | 1 + .../examples/gkebackup_backupplan_cmek.tf.erb | 1 + .../examples/gkebackup_backupplan_full.tf.erb | 1 + ...p_restoreplan_all_cluster_resources.tf.erb | 1 + ...kebackup_restoreplan_all_namespaces.tf.erb | 1 + ...p_restoreplan_protected_application.tf.erb | 1 + ...backup_restoreplan_rename_namespace.tf.erb | 1 + ...ckup_restoreplan_rollback_namespace.tf.erb | 1 + ...p_restoreplan_second_transformation.tf.erb | 1 + .../examples/gkehub_membership_basic.tf.erb | 1 + .../gkehub_membership_binding_basic.tf.erb | 1 + .../examples/gkehub_membership_issuer.tf.erb | 1 + ..._membership_rbac_role_binding_basic.tf.erb | 1 + .../instance_group_named_port_gke.tf.erb | 1 + .../network_peering_routes_config_gke.tf.erb | 1 + ...ta_source_google_container_cluster_test.go | 4 + .../resource_container_cluster.go.erb | 24 +- .../resource_container_cluster_migrate.go | 3 + ...esource_container_cluster_migratev1.go.erb | 1844 +++++++++++++++++ .../resource_container_cluster_test.go.erb | 554 ++++- .../resource_container_node_pool_test.go.erb | 61 +- .../resource_dataproc_cluster_test.go.erb | 1 + .../dns/resource_dns_managed_zone_test.go.erb | 1 + .../resource_dns_response_policy_test.go.erb | 2 + ...esource_gke_backup_backup_plan_test.go.erb | 2 + ...rce_gke_hub_feature_membership_test.go.erb | 11 + .../resource_gke_hub_feature_test.go.erb | 4 + ...esource_gke_hub_membership_binding_test.go | 2 + .../docs/r/container_cluster.html.markdown | 8 + 41 files changed, 2514 insertions(+), 115 deletions(-) create mode 100644 mmv1/third_party/terraform/services/container/resource_container_cluster_migratev1.go.erb diff --git a/mmv1/products/compute/InstanceGroupNamedPort.yaml b/mmv1/products/compute/InstanceGroupNamedPort.yaml index 2cc5e2a69e49..be2ae5f63aa8 100644 --- a/mmv1/products/compute/InstanceGroupNamedPort.yaml +++ b/mmv1/products/compute/InstanceGroupNamedPort.yaml @@ -71,6 +71,11 @@ examples: network_name: 'container-network' subnetwork_name: 'container-subnetwork' gke_cluster_name: 'my-cluster' + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' custom_code: !ruby/object:Provider::Terraform::CustomCode encoder: 'templates/terraform/encoders/normalize_group.go.erb' parameters: diff --git a/mmv1/products/compute/NetworkPeeringRoutesConfig.yaml b/mmv1/products/compute/NetworkPeeringRoutesConfig.yaml index b939c63a33c8..bece6c506399 100644 --- a/mmv1/products/compute/NetworkPeeringRoutesConfig.yaml +++ b/mmv1/products/compute/NetworkPeeringRoutesConfig.yaml @@ -74,6 +74,11 @@ examples: network_name: 'container-network' subnetwork_name: 'container-subnetwork' gke_cluster_name: 'private-cluster' + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' custom_code: !ruby/object:Provider::Terraform::CustomCode encoder: 'templates/terraform/encoders/network_peering_routes_config.go.erb' parameters: diff --git a/mmv1/products/dns/ManagedZone.yaml b/mmv1/products/dns/ManagedZone.yaml index 9c2bf3c3c201..4498bf699485 100644 --- a/mmv1/products/dns/ManagedZone.yaml +++ b/mmv1/products/dns/ManagedZone.yaml @@ -97,6 +97,11 @@ examples: zone_name: 'private-zone' network_1_name: 'network-1' cluster_1_name: 'cluster-1' + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' - !ruby/object:Provider::Terraform::Examples name: 'dns_managed_zone_private_peering' primary_resource_id: 'peering-zone' diff --git a/mmv1/products/dns/ResponsePolicy.yaml b/mmv1/products/dns/ResponsePolicy.yaml index cf2d2a7681fb..9f14ffdd65e3 100644 --- a/mmv1/products/dns/ResponsePolicy.yaml +++ b/mmv1/products/dns/ResponsePolicy.yaml @@ -31,6 +31,11 @@ examples: network_1_name: 'network-1' network_2_name: 'network-2' cluster_1_name: 'cluster-1' + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' custom_code: !ruby/object:Provider::Terraform::CustomCode pre_delete: templates/terraform/pre_delete/response_policy_detach_network_gke.erb properties: diff --git a/mmv1/products/gkebackup/BackupPlan.yaml b/mmv1/products/gkebackup/BackupPlan.yaml index 92fc4ddb57b9..0f66592368ff 100644 --- a/mmv1/products/gkebackup/BackupPlan.yaml +++ b/mmv1/products/gkebackup/BackupPlan.yaml @@ -44,6 +44,11 @@ examples: vars: name: 'basic-plan' cluster_name: 'basic-cluster' + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' test_env_vars: project: :PROJECT_NAME - !ruby/object:Provider::Terraform::Examples @@ -52,6 +57,11 @@ examples: vars: name: 'autopilot-plan' cluster_name: 'autopilot-cluster' + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' - !ruby/object:Provider::Terraform::Examples name: 'gkebackup_backupplan_cmek' primary_resource_id: 'cmek' @@ -59,6 +69,11 @@ examples: name: 'cmek-plan' cluster_name: 'cmek-cluster' key_name: 'backup-key' + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' test_env_vars: project: :PROJECT_NAME - !ruby/object:Provider::Terraform::Examples @@ -67,6 +82,11 @@ examples: vars: name: 'full-plan' cluster_name: 'full-cluster' + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' test_env_vars: project: :PROJECT_NAME skip_sweeper: true diff --git a/mmv1/products/gkebackup/RestorePlan.yaml b/mmv1/products/gkebackup/RestorePlan.yaml index b457a450fcb2..556eca8574e9 100644 --- a/mmv1/products/gkebackup/RestorePlan.yaml +++ b/mmv1/products/gkebackup/RestorePlan.yaml @@ -45,6 +45,11 @@ examples: name: 'restore-all-ns' test_env_vars: project: :PROJECT_NAME + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' - !ruby/object:Provider::Terraform::Examples name: 'gkebackup_restoreplan_rollback_namespace' primary_resource_id: 'rollback_ns' @@ -52,6 +57,11 @@ examples: name: 'rollback-ns' test_env_vars: project: :PROJECT_NAME + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' - !ruby/object:Provider::Terraform::Examples name: 'gkebackup_restoreplan_protected_application' primary_resource_id: 'rollback_app' @@ -59,6 +69,11 @@ examples: name: 'rollback-app' test_env_vars: project: :PROJECT_NAME + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' - !ruby/object:Provider::Terraform::Examples name: 'gkebackup_restoreplan_all_cluster_resources' primary_resource_id: 'all_cluster_resources' @@ -66,6 +81,11 @@ examples: name: 'all-groupkinds' test_env_vars: project: :PROJECT_NAME + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' - !ruby/object:Provider::Terraform::Examples name: 'gkebackup_restoreplan_rename_namespace' primary_resource_id: 'rename_ns' @@ -73,6 +93,11 @@ examples: name: 'rename-ns' test_env_vars: project: :PROJECT_NAME + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' - !ruby/object:Provider::Terraform::Examples name: 'gkebackup_restoreplan_second_transformation' primary_resource_id: 'transform_rule' @@ -80,6 +105,11 @@ examples: name: 'transform-rule' test_env_vars: project: :PROJECT_NAME + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' skip_sweeper: true parameters: - !ruby/object:Api::Type::String diff --git a/mmv1/products/gkehub/Membership.yaml b/mmv1/products/gkehub/Membership.yaml index a828c70a6713..8d235c069c1b 100644 --- a/mmv1/products/gkehub/Membership.yaml +++ b/mmv1/products/gkehub/Membership.yaml @@ -60,12 +60,22 @@ examples: vars: name: 'basic' cluster_name: 'basiccluster' + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' - !ruby/object:Provider::Terraform::Examples name: 'gkehub_membership_issuer' primary_resource_id: 'membership' vars: name: 'basic' cluster_name: 'basiccluster' + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' test_env_vars: project: :PROJECT_NAME # Skip sweeper gen since this is a child resource. diff --git a/mmv1/products/gkehub2/MembershipBinding.yaml b/mmv1/products/gkehub2/MembershipBinding.yaml index 54126ff200a0..e2d76ec60865 100644 --- a/mmv1/products/gkehub2/MembershipBinding.yaml +++ b/mmv1/products/gkehub2/MembershipBinding.yaml @@ -51,6 +51,11 @@ examples: primary_resource_id: "example" vars: cluster_name: "basiccluster" + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' test_env_vars: project: :PROJECT_NAME location: :REGION diff --git a/mmv1/products/gkehub2/MembershipRBACRoleBinding.yaml b/mmv1/products/gkehub2/MembershipRBACRoleBinding.yaml index 53d8d3d52c5b..2301d208bc6d 100644 --- a/mmv1/products/gkehub2/MembershipRBACRoleBinding.yaml +++ b/mmv1/products/gkehub2/MembershipRBACRoleBinding.yaml @@ -51,6 +51,11 @@ examples: min_version: beta vars: cluster_name: "basiccluster" + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' test_env_vars: project: :PROJECT_NAME location: 'global' diff --git a/mmv1/templates/terraform/examples/dns_managed_zone_private_gke.tf.erb b/mmv1/templates/terraform/examples/dns_managed_zone_private_gke.tf.erb index 667677b48b57..5c58fb5e6b71 100644 --- a/mmv1/templates/terraform/examples/dns_managed_zone_private_gke.tf.erb +++ b/mmv1/templates/terraform/examples/dns_managed_zone_private_gke.tf.erb @@ -65,5 +65,6 @@ resource "google_container_cluster" "cluster-1" { cluster_secondary_range_name = google_compute_subnetwork.subnetwork-1.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.subnetwork-1.secondary_ip_range[1].range_name } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } # [END dns_managed_zone_private_gke] \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/dns_response_policy_basic.tf.erb b/mmv1/templates/terraform/examples/dns_response_policy_basic.tf.erb index 6bfde1fe8964..767f8706638c 100644 --- a/mmv1/templates/terraform/examples/dns_response_policy_basic.tf.erb +++ b/mmv1/templates/terraform/examples/dns_response_policy_basic.tf.erb @@ -53,6 +53,7 @@ resource "google_container_cluster" "cluster-1" { cluster_secondary_range_name = google_compute_subnetwork.subnetwork-1.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.subnetwork-1.secondary_ip_range[1].range_name } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_dns_response_policy" "<%= ctx[:primary_resource_id] %>" { diff --git a/mmv1/templates/terraform/examples/gkebackup_backupplan_autopilot.tf.erb b/mmv1/templates/terraform/examples/gkebackup_backupplan_autopilot.tf.erb index 333a6cfc9863..cd0bd7803090 100644 --- a/mmv1/templates/terraform/examples/gkebackup_backupplan_autopilot.tf.erb +++ b/mmv1/templates/terraform/examples/gkebackup_backupplan_autopilot.tf.erb @@ -12,6 +12,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_backup_backup_plan" "autopilot" { diff --git a/mmv1/templates/terraform/examples/gkebackup_backupplan_basic.tf.erb b/mmv1/templates/terraform/examples/gkebackup_backupplan_basic.tf.erb index e3f834662ab7..1377aca5ed77 100644 --- a/mmv1/templates/terraform/examples/gkebackup_backupplan_basic.tf.erb +++ b/mmv1/templates/terraform/examples/gkebackup_backupplan_basic.tf.erb @@ -10,6 +10,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_backup_backup_plan" "basic" { diff --git a/mmv1/templates/terraform/examples/gkebackup_backupplan_cmek.tf.erb b/mmv1/templates/terraform/examples/gkebackup_backupplan_cmek.tf.erb index 6f2a715b7901..d9ed2a434a39 100644 --- a/mmv1/templates/terraform/examples/gkebackup_backupplan_cmek.tf.erb +++ b/mmv1/templates/terraform/examples/gkebackup_backupplan_cmek.tf.erb @@ -10,6 +10,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_backup_backup_plan" "cmek" { diff --git a/mmv1/templates/terraform/examples/gkebackup_backupplan_full.tf.erb b/mmv1/templates/terraform/examples/gkebackup_backupplan_full.tf.erb index 231727fabb35..cce561f53bad 100644 --- a/mmv1/templates/terraform/examples/gkebackup_backupplan_full.tf.erb +++ b/mmv1/templates/terraform/examples/gkebackup_backupplan_full.tf.erb @@ -10,6 +10,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_backup_backup_plan" "full" { diff --git a/mmv1/templates/terraform/examples/gkebackup_restoreplan_all_cluster_resources.tf.erb b/mmv1/templates/terraform/examples/gkebackup_restoreplan_all_cluster_resources.tf.erb index 4578aba10489..4f633dcada2e 100644 --- a/mmv1/templates/terraform/examples/gkebackup_restoreplan_all_cluster_resources.tf.erb +++ b/mmv1/templates/terraform/examples/gkebackup_restoreplan_all_cluster_resources.tf.erb @@ -10,6 +10,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_backup_backup_plan" "basic" { diff --git a/mmv1/templates/terraform/examples/gkebackup_restoreplan_all_namespaces.tf.erb b/mmv1/templates/terraform/examples/gkebackup_restoreplan_all_namespaces.tf.erb index 94c5d25f55ba..f431cda66270 100644 --- a/mmv1/templates/terraform/examples/gkebackup_restoreplan_all_namespaces.tf.erb +++ b/mmv1/templates/terraform/examples/gkebackup_restoreplan_all_namespaces.tf.erb @@ -10,6 +10,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_backup_backup_plan" "basic" { diff --git a/mmv1/templates/terraform/examples/gkebackup_restoreplan_protected_application.tf.erb b/mmv1/templates/terraform/examples/gkebackup_restoreplan_protected_application.tf.erb index 64585c3f89a0..25b7a878e78a 100644 --- a/mmv1/templates/terraform/examples/gkebackup_restoreplan_protected_application.tf.erb +++ b/mmv1/templates/terraform/examples/gkebackup_restoreplan_protected_application.tf.erb @@ -10,6 +10,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_backup_backup_plan" "basic" { diff --git a/mmv1/templates/terraform/examples/gkebackup_restoreplan_rename_namespace.tf.erb b/mmv1/templates/terraform/examples/gkebackup_restoreplan_rename_namespace.tf.erb index 11179e2afee6..7a3496f87c85 100644 --- a/mmv1/templates/terraform/examples/gkebackup_restoreplan_rename_namespace.tf.erb +++ b/mmv1/templates/terraform/examples/gkebackup_restoreplan_rename_namespace.tf.erb @@ -10,6 +10,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_backup_backup_plan" "basic" { diff --git a/mmv1/templates/terraform/examples/gkebackup_restoreplan_rollback_namespace.tf.erb b/mmv1/templates/terraform/examples/gkebackup_restoreplan_rollback_namespace.tf.erb index e2b76bae6d28..61081b246b51 100644 --- a/mmv1/templates/terraform/examples/gkebackup_restoreplan_rollback_namespace.tf.erb +++ b/mmv1/templates/terraform/examples/gkebackup_restoreplan_rollback_namespace.tf.erb @@ -10,6 +10,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_backup_backup_plan" "basic" { diff --git a/mmv1/templates/terraform/examples/gkebackup_restoreplan_second_transformation.tf.erb b/mmv1/templates/terraform/examples/gkebackup_restoreplan_second_transformation.tf.erb index 1392a5997f74..e0dbd69e4f73 100644 --- a/mmv1/templates/terraform/examples/gkebackup_restoreplan_second_transformation.tf.erb +++ b/mmv1/templates/terraform/examples/gkebackup_restoreplan_second_transformation.tf.erb @@ -10,6 +10,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_backup_backup_plan" "basic" { diff --git a/mmv1/templates/terraform/examples/gkehub_membership_basic.tf.erb b/mmv1/templates/terraform/examples/gkehub_membership_basic.tf.erb index 382cce899950..61478e731374 100644 --- a/mmv1/templates/terraform/examples/gkehub_membership_basic.tf.erb +++ b/mmv1/templates/terraform/examples/gkehub_membership_basic.tf.erb @@ -2,6 +2,7 @@ resource "google_container_cluster" "primary" { name = "<%= ctx[:vars]['cluster_name'] %>" location = "us-central1-a" initial_node_count = 1 + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_hub_membership" "membership" { diff --git a/mmv1/templates/terraform/examples/gkehub_membership_binding_basic.tf.erb b/mmv1/templates/terraform/examples/gkehub_membership_binding_basic.tf.erb index e99bb4ec5577..f7899210e7bb 100644 --- a/mmv1/templates/terraform/examples/gkehub_membership_binding_basic.tf.erb +++ b/mmv1/templates/terraform/examples/gkehub_membership_binding_basic.tf.erb @@ -2,6 +2,7 @@ resource "google_container_cluster" "primary" { name = "<%= ctx[:vars]['cluster_name'] %>" location = "us-central1-a" initial_node_count = 1 + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_hub_membership" "<%= ctx[:primary_resource_id] %>" { diff --git a/mmv1/templates/terraform/examples/gkehub_membership_issuer.tf.erb b/mmv1/templates/terraform/examples/gkehub_membership_issuer.tf.erb index 159ae9de7067..a6b6c55c682b 100644 --- a/mmv1/templates/terraform/examples/gkehub_membership_issuer.tf.erb +++ b/mmv1/templates/terraform/examples/gkehub_membership_issuer.tf.erb @@ -5,6 +5,7 @@ resource "google_container_cluster" "primary" { workload_identity_config { workload_pool = "<%= ctx[:test_env_vars]['project'] %>.svc.id.goog" } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_hub_membership" "membership" { diff --git a/mmv1/templates/terraform/examples/gkehub_membership_rbac_role_binding_basic.tf.erb b/mmv1/templates/terraform/examples/gkehub_membership_rbac_role_binding_basic.tf.erb index 7c117e3f2426..eddcf586da05 100644 --- a/mmv1/templates/terraform/examples/gkehub_membership_rbac_role_binding_basic.tf.erb +++ b/mmv1/templates/terraform/examples/gkehub_membership_rbac_role_binding_basic.tf.erb @@ -3,6 +3,7 @@ resource "google_container_cluster" "primary" { name = "<%= ctx[:vars]['cluster_name'] %>" location = "us-central1-a" initial_node_count = 1 + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_hub_membership" "<%= ctx[:primary_resource_id] %>" { diff --git a/mmv1/templates/terraform/examples/instance_group_named_port_gke.tf.erb b/mmv1/templates/terraform/examples/instance_group_named_port_gke.tf.erb index 3a4b492eca8a..32d2d23c876e 100644 --- a/mmv1/templates/terraform/examples/instance_group_named_port_gke.tf.erb +++ b/mmv1/templates/terraform/examples/instance_group_named_port_gke.tf.erb @@ -38,4 +38,5 @@ resource "google_container_cluster" "my_cluster" { cluster_ipv4_cidr_block = "/19" services_ipv4_cidr_block = "/22" } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } diff --git a/mmv1/templates/terraform/examples/network_peering_routes_config_gke.tf.erb b/mmv1/templates/terraform/examples/network_peering_routes_config_gke.tf.erb index bd6ef2cd8a7b..a75f44cafcb9 100644 --- a/mmv1/templates/terraform/examples/network_peering_routes_config_gke.tf.erb +++ b/mmv1/templates/terraform/examples/network_peering_routes_config_gke.tf.erb @@ -49,4 +49,5 @@ resource "google_container_cluster" "private_cluster" { cluster_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[1].range_name } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } diff --git a/mmv1/third_party/terraform/services/container/data_source_google_container_cluster_test.go b/mmv1/third_party/terraform/services/container/data_source_google_container_cluster_test.go index a4725f5c2a61..81fa64c14c9f 100644 --- a/mmv1/third_party/terraform/services/container/data_source_google_container_cluster_test.go +++ b/mmv1/third_party/terraform/services/container/data_source_google_container_cluster_test.go @@ -26,6 +26,7 @@ func TestAccContainerClusterDatasource_zonal(t *testing.T) { "enable_autopilot": {}, "enable_tpu": {}, "pod_security_policy_config.#": {}, + "deletion_protection": {}, }, ), ), @@ -52,6 +53,7 @@ func TestAccContainerClusterDatasource_regional(t *testing.T) { "enable_autopilot": {}, "enable_tpu": {}, "pod_security_policy_config.#": {}, + "deletion_protection": {}, }, ), ), @@ -66,6 +68,7 @@ resource "google_container_cluster" "kubes" { name = "tf-test-cluster-%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } data "google_container_cluster" "kubes" { @@ -81,6 +84,7 @@ resource "google_container_cluster" "kubes" { name = "tf-test-cluster-%s" location = "us-central1" initial_node_count = 1 + deletion_protection = false } data "google_container_cluster" "kubes" { diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb index 1ed34d7f5b91..3dd35e96e752 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb @@ -205,8 +205,15 @@ func ResourceContainerCluster() *schema.Resource { Delete: schema.DefaultTimeout(40 * time.Minute), }, - SchemaVersion: 1, + SchemaVersion: 2, MigrateState: resourceContainerClusterMigrateState, + StateUpgraders: []schema.StateUpgrader{ + { + Type: resourceContainerClusterResourceV1().CoreConfigSchema().ImpliedType(), + Upgrade: ResourceContainerClusterUpgradeV1, + Version: 1, + }, + }, Importer: &schema.ResourceImporter{ State: resourceContainerClusterStateImporter, @@ -262,6 +269,13 @@ func ResourceContainerCluster() *schema.Resource { Description: `The list of zones in which the cluster's nodes are located. Nodes must be in the region of their regional cluster or in the same region as their cluster's zone for zonal clusters. If this is specified for a zonal cluster, omit the cluster's zone.`, }, + "deletion_protection": { + Type: schema.TypeBool, + Optional: true, + Default: true, + Description: `Whether or not to allow Terraform to destroy the instance. Defaults to true. Unless this field is set to false in Terraform state, a terraform destroy or terraform apply that would delete the cluster will fail.`, + }, + "addons_config": { Type: schema.TypeList, Optional: true, @@ -4064,6 +4078,9 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er } func resourceContainerClusterDelete(d *schema.ResourceData, meta interface{}) error { + if d.Get("deletion_protection").(bool) { + return fmt.Errorf("Cannot destroy cluster because deletion_protection is set to true. Set it to false to proceed with instance deletion.") + } config := meta.(*transport_tpg.Config) userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) if err != nil { @@ -6018,6 +6035,11 @@ func resourceContainerClusterStateImporter(d *schema.ResourceData, meta interfac if err := d.Set("location", location); err != nil { return nil, fmt.Errorf("Error setting location: %s", err) } + + if err := d.Set("deletion_protection", true); err != nil { + return nil, fmt.Errorf("Error setting deletion_protection: %s", err) + } + if _, err := containerClusterAwaitRestingState(config, project, location, clusterName, userAgent, d.Timeout(schema.TimeoutCreate)); err != nil { return nil, err } diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_migrate.go b/mmv1/third_party/terraform/services/container/resource_container_cluster_migrate.go index 2b088ce0321f..58f986e29309 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster_migrate.go +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_migrate.go @@ -21,6 +21,9 @@ func resourceContainerClusterMigrateState( case 0: log.Println("[INFO] Found Container Cluster State v0; migrating to v1") return migrateClusterStateV0toV1(is) + case 1: + log.Println("[INFO] Found Container Cluster State v1 in legacy migration function; returning as non-op") + return is, nil default: return is, fmt.Errorf("Unexpected schema version: %d", v) } diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_migratev1.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster_migratev1.go.erb new file mode 100644 index 000000000000..2693e43a8f54 --- /dev/null +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_migratev1.go.erb @@ -0,0 +1,1844 @@ +<% autogen_exception -%> +package container + +import ( + "context" + "fmt" + "log" + "regexp" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + "github.com/hashicorp/terraform-provider-google/google/verify" +) + +func ResourceContainerClusterUpgradeV1(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { + log.Printf("[DEBUG] Applying container cluster migration to schema version V2.") + + rawState["deletion_protection"] = true + return rawState, nil +} + + +func resourceContainerClusterResourceV1() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The name of the cluster, unique within the project and location.`, + ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + + if len(value) > 40 { + errors = append(errors, fmt.Errorf( + "%q cannot be longer than 40 characters", k)) + } + if !regexp.MustCompile("^[a-z0-9-]+$").MatchString(value) { + errors = append(errors, fmt.Errorf( + "%q can only contain lowercase letters, numbers and hyphens", k)) + } + if !regexp.MustCompile("^[a-z]").MatchString(value) { + errors = append(errors, fmt.Errorf( + "%q must start with a letter", k)) + } + if !regexp.MustCompile("[a-z0-9]$").MatchString(value) { + errors = append(errors, fmt.Errorf( + "%q must end with a number or a letter", k)) + } + return + }, + }, + + "operation": { + Type: schema.TypeString, + Computed: true, + }, + + "location": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: `The location (region or zone) in which the cluster master will be created, as well as the default node location. If you specify a zone (such as us-central1-a), the cluster will be a zonal cluster with a single cluster master. If you specify a region (such as us-west1), the cluster will be a regional cluster with multiple masters spread across zones in the region, and with default node locations in those zones as well.`, + }, + + "node_locations": { + Type: schema.TypeSet, + Optional: true, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `The list of zones in which the cluster's nodes are located. Nodes must be in the region of their regional cluster or in the same region as their cluster's zone for zonal clusters. If this is specified for a zonal cluster, omit the cluster's zone.`, + }, + + "addons_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `The configuration for addons supported by GKE.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "http_load_balancing": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `The status of the HTTP (L7) load balancing controller addon, which makes it easy to set up HTTP load balancers for services in a cluster. It is enabled by default; set disabled = true to disable.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "disabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + "horizontal_pod_autoscaling": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `The status of the Horizontal Pod Autoscaling addon, which increases or decreases the number of replica pods a replication controller has based on the resource usage of the existing pods. It ensures that a Heapster pod is running in the cluster, which is also used by the Cloud Monitoring service. It is enabled by default; set disabled = true to disable.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "disabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + "network_policy_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `Whether we should enable the network policy addon for the master. This must be enabled in order to enable network policy for the nodes. To enable this, you must also define a network_policy block, otherwise nothing will happen. It can only be disabled if the nodes already do not have network policies enabled. Defaults to disabled; set disabled = false to enable.`, + ConflictsWith: []string{"enable_autopilot"}, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "disabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + "gcp_filestore_csi_driver_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `The status of the Filestore CSI driver addon, which allows the usage of filestore instance as volumes. Defaults to disabled; set enabled = true to enable.`, + ConflictsWith: []string{"enable_autopilot"}, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + "cloudrun_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `The status of the CloudRun addon. It is disabled by default. Set disabled = false to enable.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "disabled": { + Type: schema.TypeBool, + Required: true, + }, + "load_balancer_type": { + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{"LOAD_BALANCER_TYPE_INTERNAL"}, false), + Optional: true, + }, + }, + }, + }, + "dns_cache_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `The status of the NodeLocal DNSCache addon. It is disabled by default. Set enabled = true to enable.`, + ConflictsWith: []string{"enable_autopilot"}, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + "gce_persistent_disk_csi_driver_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `Whether this cluster should enable the Google Compute Engine Persistent Disk Container Storage Interface (CSI) Driver. Set enabled = true to enable. The Compute Engine persistent disk CSI Driver is enabled by default on newly created clusters for the following versions: Linux clusters: GKE version 1.18.10-gke.2100 or later, or 1.19.3-gke.2100 or later.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + "gke_backup_agent_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `The status of the Backup for GKE Agent addon. It is disabled by default. Set enabled = true to enable.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + "gcs_fuse_csi_driver_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `The status of the GCS Fuse CSI driver addon, which allows the usage of gcs bucket as volumes. Defaults to disabled; set enabled = true to enable.`, + ConflictsWith: []string{"enable_autopilot"}, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + <% unless version == 'ga' -%> + "istio_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `The status of the Istio addon.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "disabled": { + Type: schema.TypeBool, + Required: true, + Description: `The status of the Istio addon, which makes it easy to set up Istio for services in a cluster. It is disabled by default. Set disabled = false to enable.`, + }, + "auth": { + Type: schema.TypeString, + Optional: true, + // We can't use a Terraform-level default because it won't be true when the block is disabled: true + DiffSuppressFunc: tpgresource.EmptyOrDefaultStringSuppress("AUTH_NONE"), + ValidateFunc: validation.StringInSlice([]string{"AUTH_NONE", "AUTH_MUTUAL_TLS"}, false), + Description: `The authentication type between services in Istio. Available options include AUTH_MUTUAL_TLS.`, + }, + }, + }, + }, + "kalm_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `Configuration for the KALM addon, which manages the lifecycle of k8s. It is disabled by default; Set enabled = true to enable.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + <% end -%> + "config_connector_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `The of the Config Connector addon.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + }, + }, + }, + + "cluster_autoscaling": { + Type: schema.TypeList, + MaxItems: 1, + // This field is Optional + Computed because we automatically set the + // enabled value to false if the block is not returned in API responses. + Optional: true, + Computed: true, + Description: `Per-cluster configuration of Node Auto-Provisioning with Cluster Autoscaler to automatically adjust the size of the cluster and create/delete node pools based on the current needs of the cluster's workload. See the guide to using Node Auto-Provisioning for more details.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + ConflictsWith: []string{"enable_autopilot"}, + Description: `Whether node auto-provisioning is enabled. Resource limits for cpu and memory must be defined to enable node auto-provisioning.`, + }, + "resource_limits": { + Type: schema.TypeList, + Optional: true, + ConflictsWith: []string{"enable_autopilot"}, + DiffSuppressFunc: suppressDiffForAutopilot, + Description: `Global constraints for machine resources in the cluster. Configuring the cpu and memory types is required if node auto-provisioning is enabled. These limits will apply to node pool autoscaling in addition to node auto-provisioning.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "resource_type": { + Type: schema.TypeString, + Required: true, + Description: `The type of the resource. For example, cpu and memory. See the guide to using Node Auto-Provisioning for a list of types.`, + }, + "minimum": { + Type: schema.TypeInt, + Optional: true, + Description: `Minimum amount of the resource in the cluster.`, + }, + "maximum": { + Type: schema.TypeInt, + Optional: true, + Description: `Maximum amount of the resource in the cluster.`, + }, + }, + }, + }, + "auto_provisioning_defaults": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: `Contains defaults for a node pool created by NAP.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "oauth_scopes": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + DiffSuppressFunc: containerClusterAddedScopesSuppress, + Description: `Scopes that are used by NAP when creating node pools.`, + }, + "service_account": { + Type: schema.TypeString, + Optional: true, + Default: "default", + Description: `The Google Cloud Platform Service Account to be used by the node VMs.`, + }, + "disk_size": { + Type: schema.TypeInt, + Optional: true, + Default: 100, + Description: `Size of the disk attached to each node, specified in GB. The smallest allowed disk size is 10GB.`, + DiffSuppressFunc: suppressDiffForAutopilot, + ValidateFunc: validation.IntAtLeast(10), + }, + "disk_type": { + Type: schema.TypeString, + Optional: true, + Default: "pd-standard", + Description: `Type of the disk attached to each node.`, + DiffSuppressFunc: suppressDiffForAutopilot, + ValidateFunc: validation.StringInSlice([]string{"pd-standard", "pd-ssd", "pd-balanced"}, false), + }, + "image_type": { + Type: schema.TypeString, + Optional: true, + Default: "COS_CONTAINERD", + Description: `The default image type used by NAP once a new node pool is being created.`, + DiffSuppressFunc: suppressDiffForAutopilot, + ValidateFunc: validation.StringInSlice([]string{"COS_CONTAINERD", "COS", "UBUNTU_CONTAINERD", "UBUNTU"}, false), + }, + "min_cpu_platform": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: tpgresource.EmptyOrDefaultStringSuppress("automatic"), + Description: `Minimum CPU platform to be used by this instance. The instance may be scheduled on the specified or newer CPU platform. Applicable values are the friendly names of CPU platforms, such as Intel Haswell.`, + }, + "boot_disk_kms_key": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `The Customer Managed Encryption Key used to encrypt the boot disk attached to each node in the node pool.`, + }, + "shielded_instance_config": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: `Shielded Instance options.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_secure_boot": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: `Defines whether the instance has Secure Boot enabled.`, + AtLeastOneOf: []string{ + "cluster_autoscaling.0.auto_provisioning_defaults.0.shielded_instance_config.0.enable_secure_boot", + "cluster_autoscaling.0.auto_provisioning_defaults.0.shielded_instance_config.0.enable_integrity_monitoring", + }, + }, + "enable_integrity_monitoring": { + Type: schema.TypeBool, + Optional: true, + Default: true, + Description: `Defines whether the instance has integrity monitoring enabled.`, + AtLeastOneOf: []string{ + "cluster_autoscaling.0.auto_provisioning_defaults.0.shielded_instance_config.0.enable_secure_boot", + "cluster_autoscaling.0.auto_provisioning_defaults.0.shielded_instance_config.0.enable_integrity_monitoring", + }, + }, + }, + }, + }, + "management": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `NodeManagement configuration for this NodePool.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "auto_upgrade": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + Description: `Specifies whether node auto-upgrade is enabled for the node pool. If enabled, node auto-upgrade helps keep the nodes in your node pool up to date with the latest release version of Kubernetes.`, + }, + "auto_repair": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + Description: `Specifies whether the node auto-repair is enabled for the node pool. If enabled, the nodes in this node pool will be monitored and, if they fail health checks too many times, an automatic repair action will be triggered.`, + }, + "upgrade_options": { + Type: schema.TypeList, + Computed: true, + Description: `Specifies the Auto Upgrade knobs for the node pool.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "auto_upgrade_start_time": { + Type: schema.TypeString, + Computed: true, + Description: `This field is set when upgrades are about to commence with the approximate start time for the upgrades, in RFC3339 text format.`, + }, + "description": { + Type: schema.TypeString, + Computed: true, + Description: `This field is set when upgrades are about to commence with the description of the upgrade.`, + }, + }, + }, + }, + }, + }, + }, + "upgrade_settings": { + Type: schema.TypeList, + Optional: true, + Description: `Specifies the upgrade settings for NAP created node pools`, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "max_surge": { + Type: schema.TypeInt, + Optional: true, + Description: `The maximum number of nodes that can be created beyond the current size of the node pool during the upgrade process.`, + }, + "max_unavailable": { + Type: schema.TypeInt, + Optional: true, + Description: `The maximum number of nodes that can be simultaneously unavailable during the upgrade process.`, + }, + "strategy": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `Update strategy of the node pool.`, + ValidateFunc: validation.StringInSlice([]string{"NODE_POOL_UPDATE_STRATEGY_UNSPECIFIED", "BLUE_GREEN", "SURGE"}, false), + }, + "blue_green_settings": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Settings for blue-green upgrade strategy.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "node_pool_soak_duration": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `Time needed after draining entire blue pool. After this period, blue pool will be cleaned up. + + A duration in seconds with up to nine fractional digits, ending with 's'. Example: "3.5s".`, + }, + "standard_rollout_policy": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Standard policy for the blue-green upgrade.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "batch_percentage": { + Type: schema.TypeFloat, + Optional: true, + Computed: true, + ValidateFunc: validation.FloatBetween(0.0, 1.0), + ExactlyOneOf: []string{ + "cluster_autoscaling.0.auto_provisioning_defaults.0.upgrade_settings.0.blue_green_settings.0.standard_rollout_policy.0.batch_percentage", + "cluster_autoscaling.0.auto_provisioning_defaults.0.upgrade_settings.0.blue_green_settings.0.standard_rollout_policy.0.batch_node_count", + }, + Description: `Percentage of the bool pool nodes to drain in a batch. The range of this field should be (0.0, 1.0].`, + }, + "batch_node_count": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + ExactlyOneOf: []string{ + "cluster_autoscaling.0.auto_provisioning_defaults.0.upgrade_settings.0.blue_green_settings.0.standard_rollout_policy.0.batch_percentage", + "cluster_autoscaling.0.auto_provisioning_defaults.0.upgrade_settings.0.blue_green_settings.0.standard_rollout_policy.0.batch_node_count", + }, + Description: `Number of blue nodes to drain in a batch.`, + }, + "batch_soak_duration": { + Type: schema.TypeString, + Optional: true, + Default: "0s", + Description: `Soak time after each batch gets drained. + + A duration in seconds with up to nine fractional digits, ending with 's'. Example: "3.5s".`, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + <% unless version == 'ga' -%> + "autoscaling_profile": { + Type: schema.TypeString, + Default: "BALANCED", + Optional: true, + DiffSuppressFunc: suppressDiffForAutopilot, + ValidateFunc: validation.StringInSlice([]string{"BALANCED", "OPTIMIZE_UTILIZATION"}, false), + Description: `Configuration options for the Autoscaling profile feature, which lets you choose whether the cluster autoscaler should optimize for resource utilization or resource availability when deciding to remove nodes from a cluster. Can be BALANCED or OPTIMIZE_UTILIZATION. Defaults to BALANCED.`, + }, + <% end -%> + }, + }, + }, + + "cluster_ipv4_cidr": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ValidateFunc: verify.OrEmpty(verify.ValidateRFC1918Network(8, 32)), + ConflictsWith: []string{"ip_allocation_policy"}, + Description: `The IP address range of the Kubernetes pods in this cluster in CIDR notation (e.g. 10.96.0.0/14). Leave blank to have one automatically chosen or specify a /14 block in 10.0.0.0/8. This field will only work for routes-based clusters, where ip_allocation_policy is not defined.`, + }, + + "description": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: ` Description of the cluster.`, + }, + + "binary_authorization": { + Type: schema.TypeList, + Optional: true, + DiffSuppressFunc: BinaryAuthorizationDiffSuppress, + MaxItems: 1, + Description: "Configuration options for the Binary Authorization feature.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Optional: true, + Deprecated: "Deprecated in favor of evaluation_mode.", + Description: "Enable Binary Authorization for this cluster.", + ConflictsWith: []string{"enable_autopilot", "binary_authorization.0.evaluation_mode"}, + }, + "evaluation_mode": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"DISABLED", "PROJECT_SINGLETON_POLICY_ENFORCE"}, false), + Description: "Mode of operation for Binary Authorization policy evaluation.", + ConflictsWith: []string{"binary_authorization.0.enabled"}, + }, + }, + }, + }, + + "enable_kubernetes_alpha": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Default: false, + Description: `Whether to enable Kubernetes Alpha features for this cluster. Note that when this option is enabled, the cluster cannot be upgraded and will be automatically deleted after 30 days.`, + }, + + "enable_k8s_beta_apis": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: `Configuration for Kubernetes Beta APIs.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled_apis": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `Enabled Kubernetes Beta APIs.`, + }, + }, + }, + }, + + "enable_tpu": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `Whether to enable Cloud TPU resources in this cluster.`, +<% unless version == 'ga' -%> + ConflictsWith: []string{"tpu_config"}, + Computed: true, + // TODO: deprecate when tpu_config is correctly returned by the API + // Deprecated: "Deprecated in favor of tpu_config", +<% end -%> + }, + +<% unless version == 'ga' -%> + "tpu_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `TPU configuration for the cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + ForceNew: true, + Description: `Whether Cloud TPU integration is enabled or not`, + }, + "ipv4_cidr_block": { + Type: schema.TypeString, + Computed: true, + Description: `IPv4 CIDR block reserved for Cloud TPU in the VPC.`, + }, + "use_service_networking": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `Whether to use service networking for Cloud TPU or not`, + }, + }, + }, + }, +<% end -%> + + "enable_legacy_abac": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: `Whether the ABAC authorizer is enabled for this cluster. When enabled, identities in the system, including service accounts, nodes, and controllers, will have statically granted permissions beyond those provided by the RBAC configuration or IAM. Defaults to false.`, + }, + + "enable_shielded_nodes": { + Type: schema.TypeBool, + Optional: true, + Default: true, + Description: `Enable Shielded Nodes features on all nodes in this cluster. Defaults to true.`, + ConflictsWith: []string{"enable_autopilot"}, + }, + + "enable_autopilot": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `Enable Autopilot for this cluster.`, + // ConflictsWith: many fields, see https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-overview#comparison. The conflict is only set one-way, on other fields w/ this field. + }, + + "allow_net_admin": { + Type: schema.TypeBool, + Optional: true, + Description: `Enable NET_ADMIN for this cluster.`, + }, + + "authenticator_groups_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Configuration for the Google Groups for GKE feature.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "security_group": { + Type: schema.TypeString, + Required: true, + Description: `The name of the RBAC security group for use with Google security groups in Kubernetes RBAC. Group name must be in format gke-security-groups@yourdomain.com.`, + }, + }, + }, + }, + + "initial_node_count": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Description: `The number of nodes to create in this cluster's default node pool. In regional or multi-zonal clusters, this is the number of nodes per zone. Must be set if node_pool is not set. If you're using google_container_node_pool objects with no default node pool, you'll need to set this to a value of at least 1, alongside setting remove_default_node_pool to true.`, + }, + + "logging_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Logging configuration for the cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_components": { + Type: schema.TypeList, + Required: true, + Description: `GKE components exposing logs. Valid values include SYSTEM_COMPONENTS, APISERVER, CONTROLLER_MANAGER, SCHEDULER, and WORKLOADS.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{"SYSTEM_COMPONENTS", "APISERVER", "CONTROLLER_MANAGER", "SCHEDULER", "WORKLOADS"}, false), + }, + }, + }, + }, + }, + + "logging_service": { + Type: schema.TypeString, + Optional: true, + Computed: true, +<% unless version == 'ga' -%> + ConflictsWith: []string{"cluster_telemetry"}, +<% end -%> + ValidateFunc: validation.StringInSlice([]string{"logging.googleapis.com", "logging.googleapis.com/kubernetes", "none"}, false), + Description: `The logging service that the cluster should write logs to. Available options include logging.googleapis.com(Legacy Stackdriver), logging.googleapis.com/kubernetes(Stackdriver Kubernetes Engine Logging), and none. Defaults to logging.googleapis.com/kubernetes.`, + }, + + "maintenance_policy": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: `The maintenance policy to use for the cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "daily_maintenance_window": { + Type: schema.TypeList, + Optional: true, + ExactlyOneOf: []string{ + "maintenance_policy.0.daily_maintenance_window", + "maintenance_policy.0.recurring_window", + }, + MaxItems: 1, + Description: `Time window specified for daily maintenance operations. Specify start_time in RFC3339 format "HH:MM”, where HH : [00-23] and MM : [00-59] GMT.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "start_time": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidateRFC3339Time, + DiffSuppressFunc: tpgresource.Rfc3339TimeDiffSuppress, + }, + "duration": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "recurring_window": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + ExactlyOneOf: []string{ + "maintenance_policy.0.daily_maintenance_window", + "maintenance_policy.0.recurring_window", + }, + Description: `Time window for recurring maintenance operations.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "start_time": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidateRFC3339Date, + }, + "end_time": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidateRFC3339Date, + }, + "recurrence": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: rfc5545RecurrenceDiffSuppress, + }, + }, + }, + }, + "maintenance_exclusion": { + Type: schema.TypeSet, + Optional: true, + MaxItems: 20, + Description: `Exceptions to maintenance window. Non-emergency maintenance should not occur in these windows.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "exclusion_name": { + Type: schema.TypeString, + Required: true, + }, + "start_time": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidateRFC3339Date, + }, + "end_time": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidateRFC3339Date, + }, + "exclusion_options": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: `Maintenance exclusion related options.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "scope": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"NO_UPGRADES", "NO_MINOR_UPGRADES", "NO_MINOR_OR_NODE_UPGRADES"}, false), + Description: `The scope of automatic upgrades to restrict in the exclusion window.`, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + +<% unless version == 'ga' -%> + "protect_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Enable/Disable Protect API features for the cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "workload_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `WorkloadConfig defines which actions are enabled for a cluster's workload configurations.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "audit_mode": { + Type: schema.TypeString, + Required: true, + Description: `Sets which mode of auditing should be used for the cluster's workloads. Accepted values are DISABLED, BASIC.`, + }, + }, + }, + AtLeastOneOf: []string{ + "protect_config.0.workload_config", + "protect_config.0.workload_vulnerability_mode", + }, + }, + "workload_vulnerability_mode": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `Sets which mode to use for Protect workload vulnerability scanning feature. Accepted values are DISABLED, BASIC.`, + AtLeastOneOf: []string{ + "protect_config.0.workload_config", + "protect_config.0.workload_vulnerability_mode", + }, + }, + }, + }, + }, +<% end -%> + + "security_posture_config": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Computed: true, + Description: `Defines the config needed to enable/disable features for the Security Posture API`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mode": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice([]string{"DISABLED", "BASIC", "MODE_UNSPECIFIED"}, false), + Description: `Sets the mode of the Kubernetes security posture API's off-cluster features. Available options include DISABLED and BASIC.`, + DiffSuppressFunc: tpgresource.EmptyOrDefaultStringSuppress("MODE_UNSPECIFIED"), + }, + "vulnerability_mode": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice([]string{"VULNERABILITY_DISABLED", "VULNERABILITY_BASIC", "VULNERABILITY_MODE_UNSPECIFIED"}, false), + Description: `Sets the mode of the Kubernetes security posture API's workload vulnerability scanning. Available options include VULNERABILITY_DISABLED and VULNERABILITY_BASIC.`, + DiffSuppressFunc: tpgresource.EmptyOrDefaultStringSuppress("VULNERABILITY_MODE_UNSPECIFIED"), + }, + }, + }, + }, + "monitoring_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Monitoring configuration for the cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_components": { + Type: schema.TypeList, + Optional: true, + Computed: true, +<% if version == "ga" -%> + Description: `GKE components exposing metrics. Valid values include SYSTEM_COMPONENTS, APISERVER, SCHEDULER, CONTROLLER_MANAGER, STORAGE, HPA, POD, DAEMONSET, DEPLOYMENT and STATEFULSET.`, +<% else -%> + Description: `GKE components exposing metrics. Valid values include SYSTEM_COMPONENTS, APISERVER, SCHEDULER, CONTROLLER_MANAGER, STORAGE, HPA, POD, DAEMONSET, DEPLOYMENT, STATEFULSET and WORKLOADS.`, +<% end -%> + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "managed_prometheus": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Configuration for Google Cloud Managed Services for Prometheus.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `Whether or not the managed collection is enabled.`, + }, + }, + }, + }, + "advanced_datapath_observability_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 2, + Description: `Configuration of Advanced Datapath Observability features.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_metrics": { + Type: schema.TypeBool, + Required: true, + Description: `Whether or not the advanced datapath metrics are enabled.`, + }, + "relay_mode": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `Mode used to make Relay available.`, + ValidateFunc: validation.StringInSlice([]string{"DISABLED", "INTERNAL_VPC_LB", "EXTERNAL_LB"}, false), + }, + }, + }, + }, + }, + }, + }, + + "notification_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `The notification config for sending cluster upgrade notifications`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "pubsub": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Description: `Notification config for Cloud Pub/Sub`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `Whether or not the notification config is enabled`, + }, + "topic": { + Type: schema.TypeString, + Optional: true, + Description: `The pubsub topic to push upgrade notifications to. Must be in the same project as the cluster. Must be in the format: projects/{project}/topics/{topic}.`, + }, + "filter": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: `Allows filtering to one or more specific event types. If event types are present, those and only those event types will be transmitted to the cluster. Other types will be skipped. If no filter is specified, or no event types are present, all event types will be sent`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "event_type": { + Type: schema.TypeList, + Required: true, + Description: `Can be used to filter what notifications are sent. Valid values include include UPGRADE_AVAILABLE_EVENT, UPGRADE_EVENT and SECURITY_BULLETIN_EVENT`, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{"UPGRADE_AVAILABLE_EVENT", "UPGRADE_EVENT", "SECURITY_BULLETIN_EVENT"}, false), + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + + "confidential_nodes": { + Type: schema.TypeList, + Optional: true, + Computed: true, + ForceNew: true, + MaxItems: 1, + Description: `Configuration for the confidential nodes feature, which makes nodes run on confidential VMs. Warning: This configuration can't be changed (or added/removed) after cluster creation without deleting and recreating the entire cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + ForceNew: true, + Description: `Whether Confidential Nodes feature is enabled for all nodes in this cluster.`, + }, + }, + }, + }, + + "master_auth": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Computed: true, + Description: `The authentication information for accessing the Kubernetes master. Some values in this block are only returned by the API if your service account has permission to get credentials for your GKE cluster. If you see an unexpected diff unsetting your client cert, ensure you have the container.clusters.getCredentials permission.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "client_certificate_config": { + Type: schema.TypeList, + MaxItems: 1, + Required: true, + ForceNew: true, + Description: `Whether client certificate authorization is enabled for this cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "issue_client_certificate": { + Type: schema.TypeBool, + Required: true, + ForceNew: true, + Description: `Whether client certificate authorization is enabled for this cluster.`, + }, + }, + }, + }, + + "client_certificate": { + Type: schema.TypeString, + Computed: true, + Description: `Base64 encoded public certificate used by clients to authenticate to the cluster endpoint.`, + }, + + "client_key": { + Type: schema.TypeString, + Computed: true, + Sensitive: true, + Description: `Base64 encoded private key used by clients to authenticate to the cluster endpoint.`, + }, + + "cluster_ca_certificate": { + Type: schema.TypeString, + Computed: true, + Description: `Base64 encoded public certificate that is the root of trust for the cluster.`, + }, + }, + }, + }, + + "master_authorized_networks_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: masterAuthorizedNetworksConfig, + Description: `The desired configuration options for master authorized networks. Omit the nested cidr_blocks attribute to disallow external access (except the cluster node IPs, which GKE automatically whitelists).`, + }, + + "min_master_version": { + Type: schema.TypeString, + Optional: true, + Description: `The minimum version of the master. GKE will auto-update the master to new versions, so this does not guarantee the current master version--use the read-only master_version field to obtain that. If unset, the cluster's version will be set by GKE to the version of the most recent official release (which is not necessarily the latest version).`, + }, + + "monitoring_service": { + Type: schema.TypeString, + Optional: true, + Computed: true, +<% unless version == 'ga' -%> + ConflictsWith: []string{"cluster_telemetry"}, +<% end -%> + ValidateFunc: validation.StringInSlice([]string{"monitoring.googleapis.com", "monitoring.googleapis.com/kubernetes", "none"}, false), + Description: `The monitoring service that the cluster should write metrics to. Automatically send metrics from pods in the cluster to the Google Cloud Monitoring API. VM metrics will be collected by Google Compute Engine regardless of this setting Available options include monitoring.googleapis.com(Legacy Stackdriver), monitoring.googleapis.com/kubernetes(Stackdriver Kubernetes Engine Monitoring), and none. Defaults to monitoring.googleapis.com/kubernetes.`, + }, + + "network": { + Type: schema.TypeString, + Optional: true, + Default: "default", + ForceNew: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `The name or self_link of the Google Compute Engine network to which the cluster is connected. For Shared VPC, set this to the self link of the shared network.`, + }, + + "network_policy": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: `Configuration options for the NetworkPolicy feature.`, + ConflictsWith: []string{"enable_autopilot"}, + DiffSuppressFunc: containerClusterNetworkPolicyDiffSuppress, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `Whether network policy is enabled on the cluster.`, + }, + "provider": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"PROVIDER_UNSPECIFIED", "CALICO"}, false), + DiffSuppressFunc: tpgresource.EmptyOrDefaultStringSuppress("PROVIDER_UNSPECIFIED"), + Description: `The selected network policy provider.`, + }, + }, + }, + }, + + "node_config": clusterSchemaNodeConfig(), + + "node_pool": { + Type: schema.TypeList, + Optional: true, + Computed: true, + ForceNew: true, // TODO: Add ability to add/remove nodePools + Elem: &schema.Resource{ + Schema: schemaNodePool, + }, + Description: `List of node pools associated with this cluster. See google_container_node_pool for schema. Warning: node pools defined inside a cluster can't be changed (or added/removed) after cluster creation without deleting and recreating the entire cluster. Unless you absolutely need the ability to say "these are the only node pools associated with this cluster", use the google_container_node_pool resource instead of this property.`, + ConflictsWith: []string{"enable_autopilot"}, + }, + + "node_pool_defaults": clusterSchemaNodePoolDefaults(), + + "node_pool_auto_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Node pool configs that apply to all auto-provisioned node pools in autopilot clusters and node auto-provisioning enabled clusters.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "network_tags": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: `Collection of Compute Engine network tags that can be applied to a node's underlying VM instance.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "tags": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `List of network tags applied to auto-provisioned node pools.`, + }, + }, + }, + }, + }, + }, + }, + + "node_version": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `The Kubernetes version on the nodes. Must either be unset or set to the same value as min_master_version on create. Defaults to the default version set by GKE which is not necessarily the latest version. This only affects nodes in the default node pool. While a fuzzy version can be specified, it's recommended that you specify explicit versions as Terraform will see spurious diffs when fuzzy versions are used. See the google_container_engine_versions data source's version_prefix field to approximate fuzzy versions in a Terraform-compatible way. To update nodes in other node pools, use the version attribute on the node pool.`, + }, + +<% unless version == "ga" -%> + "pod_security_policy_config": { + Type: schema.TypeList, + Optional: true, + Description: `Configuration for the PodSecurityPolicy feature.`, + MaxItems: 1, + DiffSuppressFunc: podSecurityPolicyCfgSuppress, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `Enable the PodSecurityPolicy controller for this cluster. If enabled, pods must be valid under a PodSecurityPolicy to be created.`, + }, + }, + }, + }, +<% end -%> + + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: `The ID of the project in which the resource belongs. If it is not provided, the provider project is used.`, + }, + + "subnetwork": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `The name or self_link of the Google Compute Engine subnetwork in which the cluster's instances are launched.`, + }, + + "self_link": { + Type: schema.TypeString, + Computed: true, + Description: `Server-defined URL for the resource.`, + }, + + "endpoint": { + Type: schema.TypeString, + Computed: true, + Description: `The IP address of this cluster's Kubernetes master.`, + }, + + "master_version": { + Type: schema.TypeString, + Computed: true, + Description: `The current version of the master in the cluster. This may be different than the min_master_version set in the config if the master has been updated by GKE.`, + }, + + "services_ipv4_cidr": { + Type: schema.TypeString, + Computed: true, + Description: `The IP address range of the Kubernetes services in this cluster, in CIDR notation (e.g. 1.2.3.4/29). Service addresses are typically put in the last /16 from the container CIDR.`, + }, + + "ip_allocation_policy": { + Type: schema.TypeList, + MaxItems: 1, + ForceNew: true, + Computed: true, + Optional: true, + ConflictsWith: []string{"cluster_ipv4_cidr"}, + Description: `Configuration of cluster IP allocation for VPC-native clusters. Adding this block enables IP aliasing, making the cluster VPC-native instead of routes-based.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + // GKE creates/deletes secondary ranges in VPC + "cluster_ipv4_cidr_block": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ConflictsWith: ipAllocationRangeFields, + DiffSuppressFunc: tpgresource.CidrOrSizeDiffSuppress, + Description: `The IP address range for the cluster pod IPs. Set to blank to have a range chosen with the default size. Set to /netmask (e.g. /14) to have a range chosen with a specific netmask. Set to a CIDR notation (e.g. 10.96.0.0/14) from the RFC-1918 private networks (e.g. 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) to pick a specific range to use.`, + }, + + "services_ipv4_cidr_block": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ConflictsWith: ipAllocationRangeFields, + DiffSuppressFunc: tpgresource.CidrOrSizeDiffSuppress, + Description: `The IP address range of the services IPs in this cluster. Set to blank to have a range chosen with the default size. Set to /netmask (e.g. /14) to have a range chosen with a specific netmask. Set to a CIDR notation (e.g. 10.96.0.0/14) from the RFC-1918 private networks (e.g. 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) to pick a specific range to use.`, + }, + + // User manages secondary ranges manually + "cluster_secondary_range_name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ConflictsWith: ipAllocationCidrBlockFields, + Description: `The name of the existing secondary range in the cluster's subnetwork to use for pod IP addresses. Alternatively, cluster_ipv4_cidr_block can be used to automatically create a GKE-managed one.`, + }, + + "services_secondary_range_name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ConflictsWith: ipAllocationCidrBlockFields, + Description: `The name of the existing secondary range in the cluster's subnetwork to use for service ClusterIPs. Alternatively, services_ipv4_cidr_block can be used to automatically create a GKE-managed one.`, + }, + + "stack_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "IPV4", + ValidateFunc: validation.StringInSlice([]string{"IPV4", "IPV4_IPV6"}, false), + Description: `The IP Stack type of the cluster. Choose between IPV4 and IPV4_IPV6. Default type is IPV4 Only if not set`, + }, + "pod_cidr_overprovision_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + ForceNew: true, + MaxItems: 1, + Description: `Configuration for cluster level pod cidr overprovision. Default is disabled=false.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "disabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + "additional_pod_ranges_config": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: `AdditionalPodRangesConfig is the configuration for additional pod secondary ranges supporting the ClusterUpdate message.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "pod_range_names": { + Type: schema.TypeSet, + MinItems: 1, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `Name for pod secondary ipv4 range which has the actual range defined ahead.`, + }, + }, + }, + }, + }, + }, + }, + + "networking_mode": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"VPC_NATIVE", "ROUTES"}, false), + Description: `Determines whether alias IPs or routes will be used for pod IPs in the cluster.`, + }, + + "remove_default_node_pool": { + Type: schema.TypeBool, + Optional: true, + Description: `If true, deletes the default node pool upon cluster creation. If you're using google_container_node_pool resources with no default node pool, this should be set to true, alongside setting initial_node_count to at least 1.`, + ConflictsWith: []string{"enable_autopilot"}, + }, + + "private_cluster_config": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + DiffSuppressFunc: containerClusterPrivateClusterConfigSuppress, + Description: `Configuration for private clusters, clusters with private nodes.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + // enable_private_endpoint is orthogonal to private_endpoint_subnetwork. + // User can create a private_cluster_config block without including + // either one of those two fields. Both fields are optional. + // At the same time, we use 'AtLeastOneOf' to prevent an empty block + // like 'private_cluster_config{}' + "enable_private_endpoint": { + Type: schema.TypeBool, + Optional: true, + AtLeastOneOf: privateClusterConfigKeys, + DiffSuppressFunc: containerClusterPrivateClusterConfigSuppress, + Description: `When true, the cluster's private endpoint is used as the cluster endpoint and access through the public endpoint is disabled. When false, either endpoint can be used.`, + }, + "enable_private_nodes": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + AtLeastOneOf: privateClusterConfigKeys, + DiffSuppressFunc: containerClusterPrivateClusterConfigSuppress, + Description: `Enables the private cluster feature, creating a private endpoint on the cluster. In a private cluster, nodes only have RFC 1918 private addresses and communicate with the master's private endpoint via private networking.`, + }, + "master_ipv4_cidr_block": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + AtLeastOneOf: privateClusterConfigKeys, + ValidateFunc: verify.OrEmpty(validation.IsCIDRNetwork(28, 28)), + Description: `The IP range in CIDR notation to use for the hosted master network. This range will be used for assigning private IP addresses to the cluster master(s) and the ILB VIP. This range must not overlap with any other ranges in use within the cluster's network, and it must be a /28 subnet. See Private Cluster Limitations for more details. This field only applies to private clusters, when enable_private_nodes is true.`, + }, + "peering_name": { + Type: schema.TypeString, + Computed: true, + Description: `The name of the peering between this cluster and the Google owned VPC.`, + }, + "private_endpoint": { + Type: schema.TypeString, + Computed: true, + Description: `The internal IP address of this cluster's master endpoint.`, + }, + "private_endpoint_subnetwork": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + AtLeastOneOf: privateClusterConfigKeys, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `Subnetwork in cluster's network where master's endpoint will be provisioned.`, + }, + "public_endpoint": { + Type: schema.TypeString, + Computed: true, + Description: `The external IP address of this cluster's master endpoint.`, + }, + "master_global_access_config": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + AtLeastOneOf: privateClusterConfigKeys, + Description: "Controls cluster master global access settings.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `Whether the cluster master is accessible globally or not.`, + }, + }, + }, + }, + }, + }, + }, + + "resource_labels": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `The GCE resource labels (a map of key/value pairs) to be applied to the cluster.`, + }, + + "label_fingerprint": { + Type: schema.TypeString, + Computed: true, + Description: `The fingerprint of the set of labels for this cluster.`, + }, + + "default_max_pods_per_node": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Computed: true, + Description: `The default maximum number of pods per node in this cluster. This doesn't work on "routes-based" clusters, clusters that don't have IP Aliasing enabled.`, + ConflictsWith: []string{"enable_autopilot"}, + }, + + "vertical_pod_autoscaling": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: `Vertical Pod Autoscaling automatically adjusts the resources of pods controlled by it.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `Enables vertical pod autoscaling.`, + }, + }, + }, + }, + "workload_identity_config": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + // Computed is unsafe to remove- this API may return `"workloadIdentityConfig": {},` or omit the key entirely + // and both will be valid. Note that we don't handle the case where the API returns nothing & the user has defined + // workload_identity_config today. + Computed: true, + Description: `Configuration for the use of Kubernetes Service Accounts in GCP IAM policies.`, + ConflictsWith: []string{"enable_autopilot"}, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "workload_pool": { + Type: schema.TypeString, + Optional: true, + Description: "The workload pool to attach all Kubernetes service accounts to.", + }, + }, + }, + }, + +<% unless version == 'ga' -%> + "identity_service_config": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: `Configuration for Identity Service which allows customers to use external identity providers with the K8S API.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Optional: true, + Description: "Whether to enable the Identity Service component.", + }, + }, + }, + }, +<% end -%> + + "service_external_ips_config": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: `If set, and enabled=true, services with external ips field will not be blocked`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `When enabled, services with exterenal ips specified will be allowed.`, + }, + }, + }, + }, + + "mesh_certificates": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: `If set, and enable_certificates=true, the GKE Workload Identity Certificates controller and node agent will be deployed in the cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_certificates": { + Type: schema.TypeBool, + Required: true, + Description: `When enabled the GKE Workload Identity Certificates controller and node agent will be deployed in the cluster.`, + }, + }, + }, + }, + + "database_encryption": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: `Application-layer Secrets Encryption settings. The object format is {state = string, key_name = string}. Valid values of state are: "ENCRYPTED"; "DECRYPTED". key_name is the name of a CloudKMS key.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "state": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"ENCRYPTED", "DECRYPTED"}, false), + Description: `ENCRYPTED or DECRYPTED.`, + }, + "key_name": { + Type: schema.TypeString, + Optional: true, + Description: `The key to use to encrypt/decrypt secrets.`, + }, + }, + }, + }, + + "release_channel": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Configuration options for the Release channel feature, which provide more control over automatic upgrades of your GKE clusters. Note that removing this field from your config will not unenroll it. Instead, use the "UNSPECIFIED" channel.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "channel": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"UNSPECIFIED", "RAPID", "REGULAR", "STABLE"}, false), + Description: `The selected release channel. Accepted values are: +* UNSPECIFIED: Not set. +* RAPID: Weekly upgrade cadence; Early testers and developers who requires new features. +* REGULAR: Multiple per month upgrade cadence; Production users who need features not yet offered in the Stable channel. +* STABLE: Every few months upgrade cadence; Production users who need stability above all else, and for whom frequent upgrades are too risky.`, + }, + }, + }, + }, + + "tpu_ipv4_cidr_block": { + Computed: true, + Type: schema.TypeString, + Description: `The IP address range of the Cloud TPUs in this cluster, in CIDR notation (e.g. 1.2.3.4/29).`, + }, + +<% unless version == 'ga' -%> + "cluster_telemetry": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Description: `Telemetry integration for the cluster.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"DISABLED","ENABLED","SYSTEM_ONLY"}, false), + Description: `Type of the integration.`, + }, + }, + }, + }, +<% end -%> + + "default_snat_status": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: `Whether the cluster disables default in-node sNAT rules. In-node sNAT rules will be disabled when defaultSnatStatus is disabled.`, + Elem: &schema.Resource { + Schema: map[string]*schema.Schema { + "disabled": { + Type: schema.TypeBool, + Required: true, + Description: `When disabled is set to false, default IP masquerade rules will be applied to the nodes to prevent sNAT on cluster internal traffic.`, + }, + }, + }, + }, + + "datapath_provider": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + Description: `The desired datapath provider for this cluster. By default, uses the IPTables-based kube-proxy implementation.`, + ValidateFunc: validation.StringInSlice([]string{"DATAPATH_PROVIDER_UNSPECIFIED", "LEGACY_DATAPATH", "ADVANCED_DATAPATH"}, false), + DiffSuppressFunc: tpgresource.EmptyOrDefaultStringSuppress("DATAPATH_PROVIDER_UNSPECIFIED"), + }, + + "enable_intranode_visibility": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + Description: `Whether Intra-node visibility is enabled for this cluster. This makes same node pod to pod traffic visible for VPC network.`, + ConflictsWith: []string{"enable_autopilot"}, + }, + "enable_l4_ilb_subsetting": { + Type: schema.TypeBool, + Optional: true, + Description: `Whether L4ILB Subsetting is enabled for this cluster.`, + Default: false, + }, +<% unless version == 'ga' -%> + "enable_multi_networking": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `Whether multi-networking is enabled for this cluster.`, + Default: false, + }, + "enable_fqdn_network_policy": { + Type: schema.TypeBool, + Optional: true, + Description: `Whether FQDN Network Policy is enabled on this cluster.`, + Default: false, + }, +<% end -%> + "private_ipv6_google_access": { + Type: schema.TypeString, + Optional: true, + Description: `The desired state of IPv6 connectivity to Google Services. By default, no private IPv6 access to or from Google Services (all access will be via IPv4).`, + Computed: true, + }, + + "cost_management_config": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: `Cost management configuration for the cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `Whether to enable GKE cost allocation. When you enable GKE cost allocation, the cluster name and namespace of your GKE workloads appear in the labels field of the billing export to BigQuery. Defaults to false.`, + }, + }, + }, + }, + + "resource_usage_export_config": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: `Configuration for the ResourceUsageExportConfig feature.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_network_egress_metering": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: `Whether to enable network egress metering for this cluster. If enabled, a daemonset will be created in the cluster to meter network egress traffic.`, + }, + "enable_resource_consumption_metering": { + Type: schema.TypeBool, + Optional: true, + Default: true, + Description: `Whether to enable resource consumption metering on this cluster. When enabled, a table will be created in the resource export BigQuery dataset to store resource consumption data. The resulting table can be joined with the resource usage table or with BigQuery billing export. Defaults to true.`, + }, + "bigquery_destination": { + Type: schema.TypeList, + MaxItems: 1, + Required: true, + Description: `Parameters for using BigQuery as the destination of resource usage export.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dataset_id": { + Type: schema.TypeString, + Required: true, + Description: `The ID of a BigQuery Dataset.`, + }, + }, + }, + }, + }, + }, + }, + "dns_config": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + ForceNew: true, + DiffSuppressFunc: suppressDiffForAutopilot, + Description: `Configuration for Cloud DNS for Kubernetes Engine.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "cluster_dns": { + Type: schema.TypeString, + Default: "PROVIDER_UNSPECIFIED", + ValidateFunc: validation.StringInSlice([]string{"PROVIDER_UNSPECIFIED", "PLATFORM_DEFAULT", "CLOUD_DNS"}, false), + Description: `Which in-cluster DNS provider should be used.`, + Optional: true, + }, + "cluster_dns_scope": { + Type: schema.TypeString, + Default: "DNS_SCOPE_UNSPECIFIED", + ValidateFunc: validation.StringInSlice([]string{"DNS_SCOPE_UNSPECIFIED", "CLUSTER_SCOPE", "VPC_SCOPE"}, false), + Description: `The scope of access to cluster DNS records.`, + Optional: true, + }, + "cluster_dns_domain": { + Type: schema.TypeString, + Description: `The suffix used for all cluster service records.`, + Optional: true, + }, + }, + }, + }, + "gateway_api_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Configuration for GKE Gateway API controller.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "channel": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"CHANNEL_DISABLED", "CHANNEL_EXPERIMENTAL", "CHANNEL_STANDARD"}, false), + Description: `The Gateway API release channel to use for Gateway API.`, + }, + }, + }, + }, + }, + } +} diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb index d3d0cad4e982..08f43aa6063a 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb @@ -34,17 +34,20 @@ func TestAccContainerCluster_basic(t *testing.T) { ImportStateId: fmt.Sprintf("us-central1-a/%s", clusterName), ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { ResourceName: "google_container_cluster.primary", ImportStateId: fmt.Sprintf("%s/us-central1-a/%s", envvar.GetTestProjectFromEnv(), clusterName), ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -66,6 +69,7 @@ func TestAccContainerCluster_networkingModeRoutes(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -91,7 +95,7 @@ func TestAccContainerCluster_misc(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, { Config: testAccContainerCluster_misc_update(clusterName), @@ -100,7 +104,7 @@ func TestAccContainerCluster_misc(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, }, }) @@ -125,7 +129,7 @@ func TestAccContainerCluster_withAddons(t *testing.T) { ImportState: true, ImportStateVerify: true, // TODO: clean up this list in `4.0.0`, remove both `workload_identity_config` fields (same for below) - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_updateAddons(pid, clusterName), @@ -134,7 +138,7 @@ func TestAccContainerCluster_withAddons(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, // Issue with cloudrun_config addon: https://github.com/hashicorp/terraform-provider-google/issues/11943 // { @@ -144,12 +148,44 @@ func TestAccContainerCluster_withAddons(t *testing.T) { // ResourceName: "google_container_cluster.primary", // ImportState: true, // ImportStateVerify: true, - // ImportStateVerifyIgnore: []string{"min_master_version"}, + // ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, // }, }, }) } +func TestAccContainerCluster_withDeletionProtection(t *testing.T) { + t.Parallel() + clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerCluster_withDeletionProtection(clusterName, "false"), + }, + { + ResourceName: "google_container_cluster.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + { + Config: testAccContainerCluster_withDeletionProtection(clusterName, "true"), + }, + { + Config: testAccContainerCluster_withDeletionProtection(clusterName, "true"), + Destroy: true, + ExpectError: regexp.MustCompile("Cannot destroy cluster because deletion_protection is set to true. Set it to false to proceed with instance deletion."), + }, + { + Config: testAccContainerCluster_withDeletionProtection(clusterName, "false"), + }, + }, + }) +} + func TestAccContainerCluster_withNotificationConfig(t *testing.T) { t.Parallel() @@ -169,6 +205,7 @@ func TestAccContainerCluster_withNotificationConfig(t *testing.T) { ResourceName: "google_container_cluster.notification_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withNotificationConfig(clusterName, newTopic), @@ -177,6 +214,7 @@ func TestAccContainerCluster_withNotificationConfig(t *testing.T) { ResourceName: "google_container_cluster.notification_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_disableNotificationConfig(clusterName), @@ -185,6 +223,7 @@ func TestAccContainerCluster_withNotificationConfig(t *testing.T) { ResourceName: "google_container_cluster.notification_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withNotificationConfig(clusterName, newTopic), @@ -193,6 +232,7 @@ func TestAccContainerCluster_withNotificationConfig(t *testing.T) { ResourceName: "google_container_cluster.notification_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -217,6 +257,7 @@ func TestAccContainerCluster_withFilteredNotificationConfig(t *testing.T) { ResourceName: "google_container_cluster.filtered_notification_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withFilteredNotificationConfigUpdate(clusterName, newTopic), @@ -225,6 +266,7 @@ func TestAccContainerCluster_withFilteredNotificationConfig(t *testing.T) { ResourceName: "google_container_cluster.filtered_notification_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_disableFilteredNotificationConfig(clusterName, newTopic), @@ -233,6 +275,7 @@ func TestAccContainerCluster_withFilteredNotificationConfig(t *testing.T) { ResourceName: "google_container_cluster.filtered_notification_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -256,6 +299,7 @@ func TestAccContainerCluster_withConfidentialNodes(t *testing.T) { ResourceName: "google_container_cluster.confidential_nodes", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_disableConfidentialNodes(clusterName, npName), @@ -264,6 +308,7 @@ func TestAccContainerCluster_withConfidentialNodes(t *testing.T) { ResourceName: "google_container_cluster.confidential_nodes", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withConfidentialNodes(clusterName, npName), @@ -272,6 +317,7 @@ func TestAccContainerCluster_withConfidentialNodes(t *testing.T) { ResourceName: "google_container_cluster.confidential_nodes", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -295,6 +341,7 @@ func TestAccContainerCluster_withILBSubsetting(t *testing.T) { ResourceName: "google_container_cluster.confidential_nodes", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withILBSubSetting(clusterName, npName), @@ -303,6 +350,7 @@ func TestAccContainerCluster_withILBSubsetting(t *testing.T) { ResourceName: "google_container_cluster.confidential_nodes", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_disableILBSubSetting(clusterName, npName), @@ -311,6 +359,7 @@ func TestAccContainerCluster_withILBSubsetting(t *testing.T) { ResourceName: "google_container_cluster.confidential_nodes", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -334,6 +383,7 @@ func TestAccContainerCluster_withMultiNetworking(t *testing.T) { ResourceName: "google_container_cluster.cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -358,7 +408,7 @@ func TestAccContainerCluster_withFQDNNetworkPolicy(t *testing.T) { ResourceName: "google_container_cluster.cluster", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withFQDNNetworkPolicy(clusterName, true), @@ -367,7 +417,7 @@ func TestAccContainerCluster_withFQDNNetworkPolicy(t *testing.T) { ResourceName: "google_container_cluster.cluster", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -394,6 +444,7 @@ func TestAccContainerCluster_withMasterAuthConfig_NoCert(t *testing.T) { ResourceName: "google_container_cluster.with_master_auth_no_cert", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -419,6 +470,7 @@ func TestAccContainerCluster_withAuthenticatorGroupsConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withAuthenticatorGroupsConfigUpdate(clusterName, orgDomain), @@ -431,6 +483,7 @@ func TestAccContainerCluster_withAuthenticatorGroupsConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withAuthenticatorGroupsConfigUpdate2(clusterName), @@ -443,6 +496,7 @@ func TestAccContainerCluster_withAuthenticatorGroupsConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -502,6 +556,7 @@ resource "google_container_cluster" "cluster" { } enable_multi_networking = true datapath_provider = "ADVANCED_DATAPATH" + deletion_protection = false } `, clusterName, clusterName) } @@ -565,6 +620,7 @@ resource "google_container_cluster" "cluster" { enable_fqdn_network_policy = %t datapath_provider = "ADVANCED_DATAPATH" + deletion_protection = false } `, clusterName, clusterName, enabled) } @@ -591,7 +647,7 @@ func TestAccContainerCluster_withNetworkPolicyEnabled(t *testing.T) { ResourceName: "google_container_cluster.with_network_policy_enabled", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, { Config: testAccContainerCluster_removeNetworkPolicy(clusterName), @@ -604,7 +660,7 @@ func TestAccContainerCluster_withNetworkPolicyEnabled(t *testing.T) { ResourceName: "google_container_cluster.with_network_policy_enabled", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, { Config: testAccContainerCluster_withNetworkPolicyDisabled(clusterName), @@ -617,7 +673,7 @@ func TestAccContainerCluster_withNetworkPolicyEnabled(t *testing.T) { ResourceName: "google_container_cluster.with_network_policy_enabled", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, { Config: testAccContainerCluster_withNetworkPolicyConfigDisabled(clusterName), @@ -630,7 +686,7 @@ func TestAccContainerCluster_withNetworkPolicyEnabled(t *testing.T) { ResourceName: "google_container_cluster.with_network_policy_enabled", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, { Config: testAccContainerCluster_withNetworkPolicyConfigDisabled(clusterName), @@ -658,7 +714,7 @@ func TestAccContainerCluster_withReleaseChannelEnabled(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withReleaseChannelEnabled(clusterName, "UNSPECIFIED"), @@ -668,7 +724,7 @@ func TestAccContainerCluster_withReleaseChannelEnabled(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -690,7 +746,7 @@ func TestAccContainerCluster_withReleaseChannelEnabledDefaultVersion(t *testing. ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withReleaseChannelEnabled(clusterName, "REGULAR"), @@ -700,7 +756,7 @@ func TestAccContainerCluster_withReleaseChannelEnabledDefaultVersion(t *testing. ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withReleaseChannelEnabled(clusterName, "UNSPECIFIED"), @@ -710,7 +766,7 @@ func TestAccContainerCluster_withReleaseChannelEnabledDefaultVersion(t *testing. ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -751,7 +807,7 @@ func TestAccContainerCluster_withTelemetryEnabled(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withTelemetryEnabled(clusterName, "DISABLED"), @@ -761,7 +817,7 @@ func TestAccContainerCluster_withTelemetryEnabled(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withTelemetryEnabled(clusterName, "SYSTEM_ONLY"), @@ -771,7 +827,7 @@ func TestAccContainerCluster_withTelemetryEnabled(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -805,17 +861,19 @@ func TestAccContainerCluster_withMasterAuthorizedNetworksConfig(t *testing.T) { ), }, { - ResourceName: "google_container_cluster.with_master_authorized_networks", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_container_cluster.with_master_authorized_networks", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withMasterAuthorizedNetworksConfig(clusterName, []string{"10.0.0.0/8", "8.8.8.8/32"}, ""), }, { - ResourceName: "google_container_cluster.with_master_authorized_networks", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_container_cluster.with_master_authorized_networks", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withMasterAuthorizedNetworksConfig(clusterName, []string{}, ""), @@ -825,17 +883,19 @@ func TestAccContainerCluster_withMasterAuthorizedNetworksConfig(t *testing.T) { ), }, { - ResourceName: "google_container_cluster.with_master_authorized_networks", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_container_cluster.with_master_authorized_networks", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_removeMasterAuthorizedNetworksConfig(clusterName), }, { - ResourceName: "google_container_cluster.with_master_authorized_networks", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_container_cluster.with_master_authorized_networks", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -862,7 +922,7 @@ func TestAccContainerCluster_withGcpPublicCidrsAccessEnabledToggle(t *testing.T) ResourceName: "google_container_cluster.with_gcp_public_cidrs_access_enabled", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withGcpPublicCidrsAccessEnabled(clusterName, "false"), @@ -875,7 +935,7 @@ func TestAccContainerCluster_withGcpPublicCidrsAccessEnabledToggle(t *testing.T) ResourceName: "google_container_cluster.with_gcp_public_cidrs_access_enabled", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withGcpPublicCidrsAccessEnabled(clusterName, "true"), @@ -904,6 +964,7 @@ resource "google_container_cluster" "with_gcp_public_cidrs_access_enabled" { master_authorized_networks_config { gcp_public_cidrs_access_enabled = %s } + deletion_protection = false } `, clusterName, flag) } @@ -920,6 +981,7 @@ resource "google_container_cluster" "with_gcp_public_cidrs_access_enabled" { location = "us-central1-a" min_master_version = data.google_container_engine_versions.uscentral1a.release_channel_latest_version["STABLE"] initial_node_count = 1 + deletion_protection = false } `, clusterName) } @@ -941,6 +1003,7 @@ func TestAccContainerCluster_regional(t *testing.T) { ResourceName: "google_container_cluster.regional", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -964,6 +1027,7 @@ func TestAccContainerCluster_regionalWithNodePool(t *testing.T) { ResourceName: "google_container_cluster.regional", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -986,6 +1050,7 @@ func TestAccContainerCluster_regionalWithNodeLocations(t *testing.T) { ResourceName: "google_container_cluster.with_node_locations", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_regionalUpdateNodeLocations(clusterName), @@ -994,6 +1059,7 @@ func TestAccContainerCluster_regionalWithNodeLocations(t *testing.T) { ResourceName: "google_container_cluster.with_node_locations", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1021,6 +1087,7 @@ func TestAccContainerCluster_withTpu(t *testing.T) { ResourceName: "google_container_cluster.with_tpu", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1045,6 +1112,7 @@ func TestAccContainerCluster_withPrivateClusterConfigBasic(t *testing.T) { ResourceName: "google_container_cluster.with_private_cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withPrivateClusterConfig(containerNetName, clusterName, true), @@ -1053,6 +1121,7 @@ func TestAccContainerCluster_withPrivateClusterConfigBasic(t *testing.T) { ResourceName: "google_container_cluster.with_private_cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1095,6 +1164,7 @@ func TestAccContainerCluster_withPrivateClusterConfigMissingCidrBlock_withAutopi ResourceName: "google_container_cluster.with_private_cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1117,6 +1187,7 @@ func TestAccContainerCluster_withPrivateClusterConfigGlobalAccessEnabledOnly(t * ResourceName: "google_container_cluster.with_private_cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withPrivateClusterConfigGlobalAccessEnabledOnly(clusterName, false), @@ -1125,6 +1196,7 @@ func TestAccContainerCluster_withPrivateClusterConfigGlobalAccessEnabledOnly(t * ResourceName: "google_container_cluster.with_private_cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1150,6 +1222,7 @@ func TestAccContainerCluster_withIntraNodeVisibility(t *testing.T) { ResourceName: "google_container_cluster.with_intranode_visibility", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_updateIntraNodeVisibility(clusterName), @@ -1161,6 +1234,7 @@ func TestAccContainerCluster_withIntraNodeVisibility(t *testing.T) { ResourceName: "google_container_cluster.with_intranode_visibility", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1183,7 +1257,7 @@ func TestAccContainerCluster_withVersion(t *testing.T) { ResourceName: "google_container_cluster.with_version", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -1206,7 +1280,7 @@ func TestAccContainerCluster_updateVersion(t *testing.T) { ResourceName: "google_container_cluster.with_version", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_updateVersion(clusterName), @@ -1215,7 +1289,7 @@ func TestAccContainerCluster_updateVersion(t *testing.T) { ResourceName: "google_container_cluster.with_version", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -1238,7 +1312,7 @@ func TestAccContainerCluster_withNodeConfig(t *testing.T) { ResourceName: "google_container_cluster.with_node_config", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"node_config.0.taint"}, + ImportStateVerifyIgnore: []string{"node_config.0.taint", "deletion_protection"}, }, { Config: testAccContainerCluster_withNodeConfigUpdate(clusterName), @@ -1247,7 +1321,7 @@ func TestAccContainerCluster_withNodeConfig(t *testing.T) { ResourceName: "google_container_cluster.with_node_config", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"node_config.0.taint"}, + ImportStateVerifyIgnore: []string{"node_config.0.taint", "deletion_protection"}, }, }, }) @@ -1268,6 +1342,7 @@ func TestAccContainerCluster_withLoggingVariantInNodeConfig(t *testing.T) { ResourceName: "google_container_cluster.with_logging_variant_in_node_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1289,6 +1364,7 @@ func TestAccContainerCluster_withLoggingVariantInNodePool(t *testing.T) { ResourceName: "google_container_cluster.with_logging_variant_in_node_pool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1309,6 +1385,7 @@ func TestAccContainerCluster_withLoggingVariantUpdates(t *testing.T) { ResourceName: "google_container_cluster.with_logging_variant_node_pool_default", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withLoggingVariantNodePoolDefault(clusterName, "MAX_THROUGHPUT"), @@ -1317,6 +1394,7 @@ func TestAccContainerCluster_withLoggingVariantUpdates(t *testing.T) { ResourceName: "google_container_cluster.with_logging_variant_node_pool_default", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withLoggingVariantNodePoolDefault(clusterName, "DEFAULT"), @@ -1325,6 +1403,7 @@ func TestAccContainerCluster_withLoggingVariantUpdates(t *testing.T) { ResourceName: "google_container_cluster.with_logging_variant_node_pool_default", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1351,6 +1430,7 @@ func TestAccContainerCluster_withNodePoolDefaults(t *testing.T) { ImportStateId: fmt.Sprintf("us-central1-a/%s", clusterName), ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withNodePoolDefaults(clusterName, "true"), @@ -1365,6 +1445,7 @@ func TestAccContainerCluster_withNodePoolDefaults(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool_defaults", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withNodePoolDefaults(clusterName, "false"), @@ -1379,6 +1460,7 @@ func TestAccContainerCluster_withNodePoolDefaults(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool_defaults", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1402,6 +1484,7 @@ func TestAccContainerCluster_withNodeConfigScopeAlias(t *testing.T) { ResourceName: "google_container_cluster.with_node_config_scope_alias", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1424,6 +1507,7 @@ func TestAccContainerCluster_withNodeConfigShieldedInstanceConfig(t *testing.T) ResourceName: "google_container_cluster.with_node_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1452,6 +1536,7 @@ func TestAccContainerCluster_withNodeConfigReservationAffinity(t *testing.T) { ResourceName: "google_container_cluster.with_node_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1487,6 +1572,7 @@ func TestAccContainerCluster_withNodeConfigReservationAffinitySpecific(t *testin ResourceName: "google_container_cluster.with_node_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1513,7 +1599,7 @@ func TestAccContainerCluster_withWorkloadMetadataConfig(t *testing.T) { ResourceName: "google_container_cluster.with_workload_metadata_config", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -1543,7 +1629,7 @@ func TestAccContainerCluster_withSandboxConfig(t *testing.T) { ResourceName: "google_container_cluster.with_sandbox_config", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version", "node_config.0.taint"}, + ImportStateVerifyIgnore: []string{"min_master_version", "node_config.0.taint", "deletion_protection"}, }, { // GKE sets automatic labels and taints on nodes. This makes @@ -1598,7 +1684,7 @@ func TestAccContainerCluster_withBootDiskKmsKey(t *testing.T) { ResourceName: "google_container_cluster.with_boot_disk_kms_key", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -1619,14 +1705,16 @@ func TestAccContainerCluster_network(t *testing.T) { Config: testAccContainerCluster_networkRef(clusterName, network), }, { - ResourceName: "google_container_cluster.with_net_ref_by_url", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_container_cluster.with_net_ref_by_url", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { - ResourceName: "google_container_cluster.with_net_ref_by_name", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_container_cluster.with_net_ref_by_name", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1649,6 +1737,7 @@ func TestAccContainerCluster_backend(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1672,6 +1761,7 @@ func TestAccContainerCluster_withNodePoolBasic(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1695,7 +1785,7 @@ func TestAccContainerCluster_withNodePoolUpdateVersion(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withNodePoolUpdateVersion(clusterName, npName), @@ -1704,7 +1794,7 @@ func TestAccContainerCluster_withNodePoolUpdateVersion(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -1730,6 +1820,7 @@ func TestAccContainerCluster_withNodePoolResize(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withNodePoolResize(clusterName, npName), @@ -1741,6 +1832,7 @@ func TestAccContainerCluster_withNodePoolResize(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1768,6 +1860,7 @@ func TestAccContainerCluster_withNodePoolAutoscaling(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, resource.TestStep{ Config: testAccContainerCluster_withNodePoolUpdateAutoscaling(clusterName, npName), @@ -1780,6 +1873,7 @@ func TestAccContainerCluster_withNodePoolAutoscaling(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, resource.TestStep{ Config: testAccContainerCluster_withNodePoolBasic(clusterName, npName), @@ -1792,6 +1886,7 @@ func TestAccContainerCluster_withNodePoolAutoscaling(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1822,7 +1917,7 @@ func TestAccContainerCluster_withNodePoolCIA(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, resource.TestStep{ Config: testAccContainerRegionalClusterUpdate_withNodePoolCIA(clusterName, npName), @@ -1838,7 +1933,7 @@ func TestAccContainerCluster_withNodePoolCIA(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, resource.TestStep{ Config: testAccContainerRegionalCluster_withNodePoolBasic(clusterName, npName), @@ -1853,7 +1948,7 @@ func TestAccContainerCluster_withNodePoolCIA(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -1879,7 +1974,7 @@ func TestAccContainerCluster_withNodePoolNamePrefix(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool_name_prefix", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"node_pool.0.name_prefix"}, + ImportStateVerifyIgnore: []string{"node_pool.0.name_prefix", "deletion_protection"}, }, }, }) @@ -1903,6 +1998,7 @@ func TestAccContainerCluster_withNodePoolMultiple(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool_multiple", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1945,6 +2041,7 @@ func TestAccContainerCluster_withNodePoolNodeConfig(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool_node_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1968,6 +2065,7 @@ func TestAccContainerCluster_withMaintenanceWindow(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withMaintenanceWindow(clusterName, ""), @@ -1982,7 +2080,7 @@ func TestAccContainerCluster_withMaintenanceWindow(t *testing.T) { ImportStateVerify: true, // maintenance_policy.# = 0 is equivalent to no maintenance policy at all, // but will still cause an import diff - ImportStateVerifyIgnore: []string{"maintenance_policy.#"}, + ImportStateVerifyIgnore: []string{"maintenance_policy.#", "deletion_protection"}, }, }, }) @@ -2010,6 +2108,8 @@ func TestAccContainerCluster_withRecurringMaintenanceWindow(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, { Config: testAccContainerCluster_withRecurringMaintenanceWindow(cluster, "", ""), @@ -2027,7 +2127,7 @@ func TestAccContainerCluster_withRecurringMaintenanceWindow(t *testing.T) { ImportStateVerify: true, // maintenance_policy.# = 0 is equivalent to no maintenance policy at all, // but will still cause an import diff - ImportStateVerifyIgnore: []string{"maintenance_policy.#"}, + ImportStateVerifyIgnore: []string{"maintenance_policy.#", "deletion_protection"}, }, }, }) @@ -2051,6 +2151,7 @@ func TestAccContainerCluster_withMaintenanceExclusionWindow(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withExclusion_DailyMaintenanceWindow(cluster, "2020-01-01T00:00:00Z", "2020-01-02T00:00:00Z"), @@ -2060,6 +2161,7 @@ func TestAccContainerCluster_withMaintenanceExclusionWindow(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2090,6 +2192,7 @@ func TestAccContainerCluster_withMaintenanceExclusionOptions(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2120,6 +2223,7 @@ func TestAccContainerCluster_deleteMaintenanceExclusionOptions(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_NoExclusionOptions_RecurringMaintenanceWindow( @@ -2136,6 +2240,7 @@ func TestAccContainerCluster_deleteMaintenanceExclusionOptions(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2169,6 +2274,7 @@ func TestAccContainerCluster_updateMaintenanceExclusionOptions(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withExclusionOptions_RecurringMaintenanceWindow( @@ -2185,6 +2291,7 @@ func TestAccContainerCluster_updateMaintenanceExclusionOptions(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_updateExclusionOptions_RecurringMaintenanceWindow( @@ -2201,6 +2308,7 @@ func TestAccContainerCluster_updateMaintenanceExclusionOptions(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2225,6 +2333,7 @@ func TestAccContainerCluster_deleteExclusionWindow(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withExclusion_RecurringMaintenanceWindow(cluster, "2019-01-01T00:00:00Z", "2019-01-02T00:00:00Z", "2019-05-01T00:00:00Z", "2019-05-02T00:00:00Z"), @@ -2234,6 +2343,7 @@ func TestAccContainerCluster_deleteExclusionWindow(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withExclusion_NoMaintenanceWindow(cluster, "2020-01-01T00:00:00Z", "2020-01-02T00:00:00Z"), @@ -2243,6 +2353,7 @@ func TestAccContainerCluster_deleteExclusionWindow(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2265,6 +2376,7 @@ func TestAccContainerCluster_withIPAllocationPolicy_existingSecondaryRanges(t *t ResourceName: "google_container_cluster.with_ip_allocation_policy", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2287,6 +2399,7 @@ func TestAccContainerCluster_withIPAllocationPolicy_specificIPRanges(t *testing. ResourceName: "google_container_cluster.with_ip_allocation_policy", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2309,6 +2422,7 @@ func TestAccContainerCluster_withIPAllocationPolicy_specificSizes(t *testing.T) ResourceName: "google_container_cluster.with_ip_allocation_policy", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2336,7 +2450,7 @@ func TestAccContainerCluster_stackType_withDualStack(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -2364,7 +2478,7 @@ func TestAccContainerCluster_stackType_withSingleStack(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -2392,7 +2506,7 @@ func TestAccContainerCluster_with_PodCIDROverprovisionDisabled(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -2419,7 +2533,7 @@ func TestAccContainerCluster_nodeAutoprovisioning(t *testing.T) { ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_autoprovisioning(clusterName, false, false), @@ -2432,7 +2546,7 @@ func TestAccContainerCluster_nodeAutoprovisioning(t *testing.T) { ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -2460,7 +2574,7 @@ func TestAccContainerCluster_nodeAutoprovisioningDefaults(t *testing.T) { ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_autoprovisioningDefaults(clusterName, true), @@ -2474,7 +2588,7 @@ func TestAccContainerCluster_nodeAutoprovisioningDefaults(t *testing.T) { ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_autoprovisioningDefaultsMinCpuPlatform(clusterName, !includeMinCpuPlatform), @@ -2483,7 +2597,7 @@ func TestAccContainerCluster_nodeAutoprovisioningDefaults(t *testing.T) { ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -2506,6 +2620,7 @@ func TestAccContainerCluster_autoprovisioningDefaultsUpgradeSettings(t *testing. ResourceName: "google_container_cluster.with_autoprovisioning_upgrade_settings", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_autoprovisioningDefaultsUpgradeSettings(clusterName, 2, 1, "BLUE_GREEN"), @@ -2518,6 +2633,7 @@ func TestAccContainerCluster_autoprovisioningDefaultsUpgradeSettings(t *testing. ResourceName: "google_container_cluster.with_autoprovisioning_upgrade_settings", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2544,7 +2660,7 @@ func TestAccContainerCluster_nodeAutoprovisioningNetworkTags(t *testing.T) { ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -2567,6 +2683,7 @@ func TestAccContainerCluster_withShieldedNodes(t *testing.T) { ResourceName: "google_container_cluster.with_shielded_nodes", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withShieldedNodes(clusterName, false), @@ -2575,6 +2692,7 @@ func TestAccContainerCluster_withShieldedNodes(t *testing.T) { ResourceName: "google_container_cluster.with_shielded_nodes", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2599,7 +2717,7 @@ func TestAccContainerCluster_withAutopilot(t *testing.T) { ResourceName: "google_container_cluster.with_autopilot", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -2634,7 +2752,7 @@ func TestAccContainerClusterCustomServiceAccount_withAutopilot(t *testing.T) { ResourceName: "google_container_cluster.with_autopilot", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -2679,7 +2797,7 @@ func TestAccContainerCluster_withAutopilotNetworkTags(t *testing.T) { ResourceName: "google_container_cluster.with_autopilot", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -2703,7 +2821,7 @@ func TestAccContainerCluster_withWorkloadIdentityConfig(t *testing.T) { ResourceName: "google_container_cluster.with_workload_identity_config", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, { Config: testAccContainerCluster_updateWorkloadIdentityConfig(pid, clusterName, false), @@ -2712,7 +2830,7 @@ func TestAccContainerCluster_withWorkloadIdentityConfig(t *testing.T) { ResourceName: "google_container_cluster.with_workload_identity_config", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, { Config: testAccContainerCluster_updateWorkloadIdentityConfig(pid, clusterName, true), @@ -2721,7 +2839,7 @@ func TestAccContainerCluster_withWorkloadIdentityConfig(t *testing.T) { ResourceName: "google_container_cluster.with_workload_identity_config", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, }, }) @@ -2744,6 +2862,7 @@ func TestAccContainerCluster_withIdentityServiceConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withIdentityServiceConfigEnabled(clusterName), @@ -2752,6 +2871,7 @@ func TestAccContainerCluster_withIdentityServiceConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withIdentityServiceConfigUpdated(clusterName), @@ -2760,6 +2880,7 @@ func TestAccContainerCluster_withIdentityServiceConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_basic(clusterName), @@ -2768,6 +2889,7 @@ func TestAccContainerCluster_withIdentityServiceConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2790,6 +2912,7 @@ func TestAccContainerCluster_withLoggingConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withLoggingConfigEnabled(clusterName), @@ -2798,6 +2921,7 @@ func TestAccContainerCluster_withLoggingConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withLoggingConfigDisabled(clusterName), @@ -2806,6 +2930,7 @@ func TestAccContainerCluster_withLoggingConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withLoggingConfigUpdated(clusterName), @@ -2814,6 +2939,7 @@ func TestAccContainerCluster_withLoggingConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_basic(clusterName), @@ -2822,6 +2948,7 @@ func TestAccContainerCluster_withLoggingConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2843,7 +2970,7 @@ func TestAccContainerCluster_withMonitoringConfigAdvancedDatapathObservabilityCo ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withMonitoringConfigAdvancedDatapathObservabilityConfigDisabled(clusterName), @@ -2852,7 +2979,7 @@ func TestAccContainerCluster_withMonitoringConfigAdvancedDatapathObservabilityCo ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -2874,7 +3001,7 @@ func TestAccContainerCluster_withMonitoringConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withMonitoringConfigEnabled(clusterName), @@ -2883,7 +3010,7 @@ func TestAccContainerCluster_withMonitoringConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withMonitoringConfigDisabled(clusterName), @@ -2892,7 +3019,7 @@ func TestAccContainerCluster_withMonitoringConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withMonitoringConfigUpdated(clusterName), @@ -2901,7 +3028,7 @@ func TestAccContainerCluster_withMonitoringConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withMonitoringConfigPrometheusUpdated(clusterName), @@ -2910,7 +3037,7 @@ func TestAccContainerCluster_withMonitoringConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, // Back to basic settings to test setting Prometheus on its own { @@ -2920,7 +3047,7 @@ func TestAccContainerCluster_withMonitoringConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withMonitoringConfigPrometheusOnly(clusterName), @@ -2929,7 +3056,7 @@ func TestAccContainerCluster_withMonitoringConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withMonitoringConfigPrometheusOnly2(clusterName), @@ -2938,7 +3065,7 @@ func TestAccContainerCluster_withMonitoringConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_basic(clusterName), @@ -2947,7 +3074,7 @@ func TestAccContainerCluster_withMonitoringConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -2969,6 +3096,7 @@ func TestAccContainerCluster_withSoleTenantGroup(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2994,6 +3122,7 @@ func TestAccContainerCluster_withAutoscalingProfile(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withAutoscalingProfile(clusterName, "OPTIMIZE_UTILIZATION"), @@ -3003,6 +3132,7 @@ func TestAccContainerCluster_withAutoscalingProfile(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3050,6 +3180,7 @@ func TestAccContainerCluster_sharedVpc(t *testing.T) { ImportStateId: fmt.Sprintf("%s-service/us-central1-a/%s", projectName, clusterName), ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3072,6 +3203,7 @@ func TestAccContainerCluster_withBinaryAuthorizationEnabledBool(t *testing.T) { ResourceName: "google_container_cluster.with_binary_authorization_enabled_bool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withBinaryAuthorizationEnabledBool(clusterName, false), @@ -3080,6 +3212,7 @@ func TestAccContainerCluster_withBinaryAuthorizationEnabledBool(t *testing.T) { ResourceName: "google_container_cluster.with_binary_authorization_enabled_bool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3102,6 +3235,7 @@ func TestAccContainerCluster_withBinaryAuthorizationEvaluationModeAutopilot(t *t ResourceName: "google_container_cluster.with_binary_authorization_evaluation_mode", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withBinaryAuthorizationEvaluationMode(clusterName, true, "DISABLED"), @@ -3110,6 +3244,7 @@ func TestAccContainerCluster_withBinaryAuthorizationEvaluationModeAutopilot(t *t ResourceName: "google_container_cluster.with_binary_authorization_evaluation_mode", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3132,6 +3267,7 @@ func TestAccContainerCluster_withBinaryAuthorizationEvaluationModeClassic(t *tes ResourceName: "google_container_cluster.with_binary_authorization_evaluation_mode", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withBinaryAuthorizationEvaluationMode(clusterName, false, "DISABLED"), @@ -3140,6 +3276,7 @@ func TestAccContainerCluster_withBinaryAuthorizationEvaluationModeClassic(t *tes ResourceName: "google_container_cluster.with_binary_authorization_evaluation_mode", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3163,6 +3300,7 @@ func TestAccContainerCluster_withFlexiblePodCIDR(t *testing.T) { ResourceName: "google_container_cluster.with_flexible_cidr", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3187,7 +3325,7 @@ func TestAccContainerCluster_nodeAutoprovisioningDefaultsDiskSizeGb(t *testing.T ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_autoprovisioningDefaultsDiskSizeGb(clusterName, !includeDiskSizeGb), @@ -3196,7 +3334,7 @@ func TestAccContainerCluster_nodeAutoprovisioningDefaultsDiskSizeGb(t *testing.T ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -3220,7 +3358,7 @@ func TestAccContainerCluster_nodeAutoprovisioningDefaultsDiskType(t *testing.T) ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_autoprovisioningDefaultsDiskType(clusterName, !includeDiskType), @@ -3229,7 +3367,7 @@ func TestAccContainerCluster_nodeAutoprovisioningDefaultsDiskType(t *testing.T) ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -3253,7 +3391,7 @@ func TestAccContainerCluster_nodeAutoprovisioningDefaultsImageType(t *testing.T) ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_autoprovisioningDefaultsImageType(clusterName, !includeImageType), @@ -3262,7 +3400,7 @@ func TestAccContainerCluster_nodeAutoprovisioningDefaultsImageType(t *testing.T) ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -3292,6 +3430,7 @@ func TestAccContainerCluster_nodeAutoprovisioningDefaultsBootDiskKmsKey(t *testi ImportStateVerify: true, ImportStateVerifyIgnore: []string{ "min_master_version", + "deletion_protection", "node_pool", // cluster_autoscaling (node auto-provisioning) creates new node pools automatically }, }, @@ -3316,7 +3455,7 @@ func TestAccContainerCluster_nodeAutoprovisioningDefaultsShieldedInstance(t *tes ResourceName: "google_container_cluster.nap_shielded_instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -3339,7 +3478,7 @@ func TestAccContainerCluster_autoprovisioningDefaultsManagement(t *testing.T) { ResourceName: "google_container_cluster.with_autoprovisioning_management", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_autoprovisioningDefaultsManagement(clusterName, true, true), @@ -3348,7 +3487,7 @@ func TestAccContainerCluster_autoprovisioningDefaultsManagement(t *testing.T) { ResourceName: "google_container_cluster.with_autoprovisioning_management", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -3380,6 +3519,7 @@ func TestAccContainerCluster_errorCleanDanglingCluster(t *testing.T) { ResourceName: "google_container_cluster.cidr_error_preempt", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: overlapConfig, @@ -3429,6 +3569,7 @@ func TestAccContainerCluster_withExternalIpsConfig(t *testing.T) { ResourceName: "google_container_cluster.with_external_ips_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withExternalIpsConfig(pid, clusterName, false), @@ -3437,6 +3578,7 @@ func TestAccContainerCluster_withExternalIpsConfig(t *testing.T) { ResourceName: "google_container_cluster.with_external_ips_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3460,7 +3602,7 @@ func TestAccContainerCluster_withMeshCertificatesConfig(t *testing.T) { ResourceName: "google_container_cluster.with_mesh_certificates_config", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, { Config: testAccContainerCluster_updateMeshCertificatesConfig(pid, clusterName, true), @@ -3469,7 +3611,7 @@ func TestAccContainerCluster_withMeshCertificatesConfig(t *testing.T) { ResourceName: "google_container_cluster.with_mesh_certificates_config", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, { Config: testAccContainerCluster_updateMeshCertificatesConfig(pid, clusterName, false), @@ -3478,7 +3620,7 @@ func TestAccContainerCluster_withMeshCertificatesConfig(t *testing.T) { ResourceName: "google_container_cluster.with_mesh_certificates_config", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, }, }) @@ -3502,6 +3644,7 @@ func TestAccContainerCluster_withCostManagementConfig(t *testing.T) { ResourceName: "google_container_cluster.with_cost_management_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_updateCostManagementConfig(pid, clusterName, false), @@ -3510,6 +3653,7 @@ func TestAccContainerCluster_withCostManagementConfig(t *testing.T) { ResourceName: "google_container_cluster.with_cost_management_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3540,6 +3684,7 @@ func TestAccContainerCluster_withDatabaseEncryption(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_basic(clusterName), @@ -3548,6 +3693,7 @@ func TestAccContainerCluster_withDatabaseEncryption(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3570,6 +3716,7 @@ func TestAccContainerCluster_withAdvancedDatapath(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3594,6 +3741,7 @@ func TestAccContainerCluster_withResourceUsageExportConfig(t *testing.T) { ResourceName: "google_container_cluster.with_resource_usage_export_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withResourceUsageExportConfig(clusterName, datesetId, "false"), @@ -3602,6 +3750,7 @@ func TestAccContainerCluster_withResourceUsageExportConfig(t *testing.T) { ResourceName: "google_container_cluster.with_resource_usage_export_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withResourceUsageExportConfigNoConfig(clusterName, datesetId), @@ -3610,6 +3759,7 @@ func TestAccContainerCluster_withResourceUsageExportConfig(t *testing.T) { ResourceName: "google_container_cluster.with_resource_usage_export_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3636,6 +3786,7 @@ func TestAccContainerCluster_withMasterAuthorizedNetworksDisabled(t *testing.T) ResourceName: "google_container_cluster.with_private_cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3659,6 +3810,7 @@ func TestAccContainerCluster_withEnableKubernetesAlpha(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3681,7 +3833,7 @@ func TestAccContainerCluster_withEnableKubernetesBetaAPIs(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -3704,7 +3856,7 @@ func TestAccContainerCluster_withEnableKubernetesBetaAPIsOnExistingCluster(t *te ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withEnableKubernetesBetaAPIs(clusterName), @@ -3713,7 +3865,7 @@ func TestAccContainerCluster_withEnableKubernetesBetaAPIsOnExistingCluster(t *te ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -3753,6 +3905,7 @@ func TestAccContainerCluster_withDNSConfig(t *testing.T) { ResourceName: "google_container_cluster.with_dns_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3777,7 +3930,7 @@ func TestAccContainerCluster_withGatewayApiConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withGatewayApiConfig(clusterName, "CHANNEL_STANDARD"), @@ -3786,7 +3939,7 @@ func TestAccContainerCluster_withGatewayApiConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -3811,7 +3964,7 @@ func TestAccContainerCluster_withTPUConfig(t *testing.T) { ImportState: true, ImportStateVerify: true, // TODO: remove when tpu_config can be read from the API - ImportStateVerifyIgnore: []string{"tpu_config"}, + ImportStateVerifyIgnore: []string{"tpu_config", "deletion_protection"}, }, }, }) @@ -3834,7 +3987,7 @@ func TestAccContainerCluster_withProtectConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withProtectConfigUpdated(clusterName), @@ -3843,7 +3996,7 @@ func TestAccContainerCluster_withProtectConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -3867,6 +4020,7 @@ func TestAccContainerCluster_withSecurityPostureConfig(t *testing.T) { ResourceName: "google_container_cluster.with_security_posture_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_SetWorkloadVulnerabilityToStandard(clusterName), @@ -3875,6 +4029,7 @@ func TestAccContainerCluster_withSecurityPostureConfig(t *testing.T) { ResourceName: "google_container_cluster.with_security_posture_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_DisableALL(clusterName), @@ -3883,6 +4038,7 @@ func TestAccContainerCluster_withSecurityPostureConfig(t *testing.T) { ResourceName: "google_container_cluster.with_security_posture_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3897,6 +4053,7 @@ resource "google_container_cluster" "with_security_posture_config" { security_posture_config { mode = "BASIC" } + deletion_protection = false } `, resource_name) } @@ -3910,6 +4067,7 @@ resource "google_container_cluster" "with_security_posture_config" { security_posture_config { vulnerability_mode = "VULNERABILITY_BASIC" } + deletion_protection = false } `, resource_name) } @@ -3924,6 +4082,7 @@ resource "google_container_cluster" "with_security_posture_config" { mode = "DISABLED" vulnerability_mode = "VULNERABILITY_DISABLED" } + deletion_protection = false } `, resource_name) } @@ -3944,6 +4103,7 @@ func TestAccContainerCluster_autopilot_minimal(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3965,7 +4125,7 @@ func TestAccContainerCluster_autopilot_net_admin(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_autopilot_net_admin(clusterName, false), @@ -3974,7 +4134,7 @@ func TestAccContainerCluster_autopilot_net_admin(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_autopilot_net_admin(clusterName, true), @@ -3983,7 +4143,7 @@ func TestAccContainerCluster_autopilot_net_admin(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -4005,6 +4165,7 @@ func TestAccContainerCluster_additional_pod_ranges_config_on_create(t *testing.T ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -4026,6 +4187,7 @@ func TestAccContainerCluster_additional_pod_ranges_config_on_update(t *testing.T ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_additional_pod_ranges_config(clusterName, 2), @@ -4034,6 +4196,7 @@ func TestAccContainerCluster_additional_pod_ranges_config_on_update(t *testing.T ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_additional_pod_ranges_config(clusterName, 0), @@ -4042,6 +4205,7 @@ func TestAccContainerCluster_additional_pod_ranges_config_on_update(t *testing.T ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_additional_pod_ranges_config(clusterName, 1), @@ -4050,6 +4214,7 @@ func TestAccContainerCluster_additional_pod_ranges_config_on_update(t *testing.T ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_additional_pod_ranges_config(clusterName, 0), @@ -4058,6 +4223,7 @@ func TestAccContainerCluster_additional_pod_ranges_config_on_update(t *testing.T ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -4114,6 +4280,7 @@ resource "google_container_cluster" "primary" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } `, name) } @@ -4125,6 +4292,7 @@ resource "google_container_cluster" "primary" { location = "us-central1-a" initial_node_count = 1 networking_mode = "ROUTES" + deletion_protection = false } `, name) } @@ -4159,6 +4327,7 @@ resource "google_container_cluster" "primary" { <% unless version == 'ga' -%> enable_intranode_visibility = true <% end -%> +deletion_protection = false } `, name) } @@ -4194,6 +4363,7 @@ resource "google_container_cluster" "primary" { <% unless version == 'ga' -%> enable_intranode_visibility = true <% end -%> + deletion_protection = false } `, name) } @@ -4256,6 +4426,7 @@ resource "google_container_cluster" "primary" { } <% end -%> } + deletion_protection = false } `, projectID, clusterName) } @@ -4319,6 +4490,7 @@ resource "google_container_cluster" "primary" { enabled = true } <% end -%> + deletion_protection = false } } `, projectID, clusterName) @@ -4357,6 +4529,7 @@ resource "google_container_cluster" "primary" { // load_balancer_type = "LOAD_BALANCER_TYPE_INTERNAL" // } // } +// deletion_protection = false // } // `, projectID, clusterName) // } @@ -4378,6 +4551,7 @@ resource "google_container_cluster" "notification_config" { topic = google_pubsub_topic.%s.id } } + deletion_protection = false } `, topic, topic, clusterName, topic) } @@ -4393,6 +4567,7 @@ resource "google_container_cluster" "notification_config" { enabled = false } } + deletion_protection = false } `, clusterName) } @@ -4418,6 +4593,7 @@ resource "google_container_cluster" "filtered_notification_config" { } } } + deletion_protection = false } `, topic, topic, clusterName, topic) } @@ -4443,6 +4619,7 @@ resource "google_container_cluster" "filtered_notification_config" { } } } + deletion_protection = false } `, topic, topic, clusterName, topic) } @@ -4465,6 +4642,7 @@ resource "google_container_cluster" "filtered_notification_config" { topic = google_pubsub_topic.%s.id } } + deletion_protection = false } `, topic, topic, clusterName, topic) } @@ -4489,6 +4667,7 @@ resource "google_container_cluster" "confidential_nodes" { confidential_nodes { enabled = true } + deletion_protection = false } `, clusterName, npName) } @@ -4513,6 +4692,7 @@ resource "google_container_cluster" "confidential_nodes" { confidential_nodes { enabled = false } + deletion_protection = false } `, clusterName, npName) } @@ -4535,6 +4715,7 @@ resource "google_container_cluster" "confidential_nodes" { } enable_l4_ilb_subsetting = true + deletion_protection = false } `, clusterName, npName) } @@ -4557,6 +4738,7 @@ resource "google_container_cluster" "confidential_nodes" { } enable_l4_ilb_subsetting = false + deletion_protection = false } `, clusterName, npName) } @@ -4579,10 +4761,22 @@ resource "google_container_cluster" "with_network_policy_enabled" { disabled = false } } + deletion_protection = false } `, clusterName) } +func testAccContainerCluster_withDeletionProtection(clusterName string, deletionProtection string) string { + return fmt.Sprintf(` +resource "google_container_cluster" "primary" { + name = "%s" + location = "us-central1-a" + initial_node_count = 1 + + deletion_protection = %s +} +`, clusterName, deletionProtection) +} func testAccContainerCluster_withReleaseChannelEnabled(clusterName string, channel string) string { return fmt.Sprintf(` @@ -4594,6 +4788,7 @@ resource "google_container_cluster" "with_release_channel" { release_channel { channel = "%s" } + deletion_protection = false } `, clusterName, channel) } @@ -4610,6 +4805,7 @@ resource "google_container_cluster" "with_release_channel" { location = "us-central1-a" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1a.release_channel_default_version["%s"] + deletion_protection = false } `, clusterName, channel) } @@ -4625,6 +4821,7 @@ resource "google_container_cluster" "with_cluster_telemetry" { cluster_telemetry { type = "%s" } + deletion_protection = false } `, clusterName, telemetryType) } @@ -4637,6 +4834,7 @@ resource "google_container_cluster" "with_network_policy_enabled" { location = "us-central1-a" initial_node_count = 1 remove_default_node_pool = true + deletion_protection = false } `, clusterName) } @@ -4652,6 +4850,7 @@ resource "google_container_cluster" "with_network_policy_enabled" { network_policy { enabled = false } + deletion_protection = false } `, clusterName) } @@ -4673,6 +4872,7 @@ resource "google_container_cluster" "with_network_policy_enabled" { disabled = true } } + deletion_protection = false } `, clusterName) } @@ -4687,6 +4887,7 @@ resource "google_container_cluster" "primary" { authenticator_groups_config { security_group = "gke-security-groups@%s" } + deletion_protection = false } `, name, orgDomain) } @@ -4701,6 +4902,7 @@ resource "google_container_cluster" "primary" { authenticator_groups_config { security_group = "" } + deletion_protection = false } `, name) } @@ -4730,6 +4932,7 @@ resource "google_container_cluster" "with_master_authorized_networks" { master_authorized_networks_config { %s } + deletion_protection = false } `, clusterName, cidrBlocks) } @@ -4740,6 +4943,7 @@ resource "google_container_cluster" "with_master_authorized_networks" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } `, clusterName) } @@ -4750,6 +4954,7 @@ resource "google_container_cluster" "regional" { name = "%s" location = "us-central1" initial_node_count = 1 + deletion_protection = false } `, clusterName) } @@ -4780,7 +4985,7 @@ func TestAccContainerCluster_withPrivateEndpointSubnetwork(t *testing.T) { ResourceName: "google_container_cluster.with_private_endpoint_subnetwork", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -4825,6 +5030,7 @@ resource "google_container_cluster" "with_private_endpoint_subnetwork" { private_cluster_config { private_endpoint_subnetwork = google_compute_subnetwork.container_subnetwork2.name } + deletion_protection = false } `, containerNetName, s1Name, s1Cidr, s2Name, s2Cidr, clusterName) } @@ -4849,7 +5055,7 @@ func TestAccContainerCluster_withPrivateClusterConfigPrivateEndpointSubnetwork(t ResourceName: "google_container_cluster.with_private_endpoint_subnetwork", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -4901,6 +5107,7 @@ resource "google_container_cluster" "with_private_endpoint_subnetwork" { cluster_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[1].range_name } + deletion_protection = false } `, containerNetName, clusterName) } @@ -4922,7 +5129,7 @@ func TestAccContainerCluster_withEnablePrivateEndpointToggle(t *testing.T) { ResourceName: "google_container_cluster.with_enable_private_endpoint", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withEnablePrivateEndpoint(clusterName, "false"), @@ -4931,7 +5138,7 @@ func TestAccContainerCluster_withEnablePrivateEndpointToggle(t *testing.T) { ResourceName: "google_container_cluster.with_enable_private_endpoint", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -4985,6 +5192,7 @@ resource "google_container_cluster" "with_enable_private_endpoint" { private_cluster_config { enable_private_endpoint = %s } + deletion_protection = false } `, clusterName, flag) } @@ -4998,6 +5206,7 @@ resource "google_container_cluster" "regional" { node_pool { name = "%s" } + deletion_protection = false } `, cluster, nodePool) } @@ -5013,6 +5222,7 @@ resource "google_container_cluster" "with_node_locations" { "us-central1-f", "us-central1-c", ] + deletion_protection = false } `, clusterName) } @@ -5028,6 +5238,7 @@ resource "google_container_cluster" "with_node_locations" { "us-central1-f", "us-central1-b", ] + deletion_protection = false } `, clusterName) } @@ -5083,6 +5294,7 @@ resource "google_container_cluster" "with_tpu" { cluster_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[1].range_name } + deletion_protection = false } `, containerNetName, clusterName) } @@ -5095,6 +5307,7 @@ resource "google_container_cluster" "with_intranode_visibility" { location = "us-central1-a" initial_node_count = 1 enable_intranode_visibility = true + deletion_protection = false } `, clusterName) } @@ -5107,6 +5320,7 @@ resource "google_container_cluster" "with_intranode_visibility" { initial_node_count = 1 enable_intranode_visibility = false private_ipv6_google_access = "PRIVATE_IPV6_GOOGLE_ACCESS_BIDIRECTIONAL" + deletion_protection = false } `, clusterName) } @@ -5122,6 +5336,7 @@ resource "google_container_cluster" "with_version" { location = "us-central1-a" min_master_version = data.google_container_engine_versions.central1a.latest_master_version initial_node_count = 1 + deletion_protection = false } `, clusterName) } @@ -5137,6 +5352,7 @@ resource "google_container_cluster" "with_version" { location = "us-central1-a" min_master_version = data.google_container_engine_versions.central1a.valid_master_versions[3] initial_node_count = 1 + deletion_protection = false } `, clusterName) } @@ -5152,6 +5368,7 @@ resource "google_container_cluster" "with_master_auth_no_cert" { issue_client_certificate = false } } + deletion_protection = false } `, clusterName) } @@ -5168,6 +5385,7 @@ resource "google_container_cluster" "with_version" { min_master_version = data.google_container_engine_versions.central1a.latest_master_version node_version = data.google_container_engine_versions.central1a.valid_node_versions[1] initial_node_count = 1 + deletion_protection = false } `, clusterName) } @@ -5217,6 +5435,7 @@ resource "google_container_cluster" "with_node_config" { // Updatable fields image_type = "COS_CONTAINERD" } + deletion_protection = false } `, clusterName) } @@ -5231,6 +5450,7 @@ resource "google_container_cluster" "with_logging_variant_in_node_config" { node_config { logging_variant = "%s" } + deletion_protection = false } `, clusterName, loggingVariant) } @@ -5248,6 +5468,7 @@ resource "google_container_cluster" "with_logging_variant_in_node_pool" { logging_variant = "%s" } } + deletion_protection = false } `, clusterName, nodePoolName, loggingVariant) } @@ -5264,6 +5485,7 @@ resource "google_container_cluster" "with_logging_variant_node_pool_default" { logging_variant = "%s" } } + deletion_protection = false } `, clusterName, loggingVariant) } @@ -5283,6 +5505,7 @@ resource "google_container_cluster" "with_node_pool_defaults" { } } } + deletion_protection = false } `, clusterName, enabled) } @@ -5333,6 +5556,7 @@ resource "google_container_cluster" "with_node_config" { // Updatable fields image_type = "UBUNTU_CONTAINERD" } + deletion_protection = false } `, clusterName) } @@ -5349,6 +5573,7 @@ resource "google_container_cluster" "with_node_config_scope_alias" { disk_size_gb = 15 oauth_scopes = ["compute-rw", "storage-ro", "logging-write", "monitoring"] } + deletion_protection = false } `, clusterName) } @@ -5389,6 +5614,7 @@ resource "google_container_cluster" "with_node_config" { enable_integrity_monitoring = true } } + deletion_protection = false } `, clusterName) } @@ -5428,6 +5654,7 @@ resource "google_container_cluster" "with_node_config" { consume_reservation_type = "ANY_RESERVATION" } } + deletion_protection = false } `, clusterName) } @@ -5498,6 +5725,7 @@ resource "google_container_cluster" "with_node_config" { ] } } + deletion_protection = false depends_on = [google_project_service.container] } `, reservation, clusterName) @@ -5525,6 +5753,7 @@ resource "google_container_cluster" "with_workload_metadata_config" { mode = "GCE_METADATA" } } + deletion_protection = false } `, clusterName) } @@ -5565,6 +5794,7 @@ resource "google_container_cluster" "with_sandbox_config" { effect = "NO_SCHEDULE" } } + deletion_protection = false } `, clusterName) } @@ -5605,6 +5835,7 @@ resource "google_container_cluster" "with_sandbox_config" { effect = "NO_SCHEDULE" } } + deletion_protection = false } `, clusterName) } @@ -5628,6 +5859,7 @@ resource "google_container_cluster" "with_boot_disk_kms_key" { boot_disk_kms_key = "%s" } + deletion_protection = false } `, clusterName, kmsKeyName) } @@ -5645,6 +5877,7 @@ resource "google_container_cluster" "with_net_ref_by_url" { initial_node_count = 1 network = google_compute_network.container_network.self_link + deletion_protection = false } resource "google_container_cluster" "with_net_ref_by_name" { @@ -5653,6 +5886,7 @@ resource "google_container_cluster" "with_net_ref_by_name" { initial_node_count = 1 network = google_compute_network.container_network.name + deletion_protection = false } `, network, cluster, cluster) } @@ -5684,6 +5918,7 @@ resource "google_container_cluster" "with_autoprovisioning_management" { } } } + deletion_protection = false } `, clusterName, autoUpgrade, autoRepair) } @@ -5727,6 +5962,7 @@ resource "google_container_cluster" "primary" { "https://www.googleapis.com/auth/monitoring", ] } + deletion_protection = false } `, cluster, cluster, cluster) } @@ -5736,6 +5972,7 @@ func testAccContainerCluster_withNodePoolBasic(cluster, nodePool string) string resource "google_container_cluster" "with_node_pool" { name = "%s" location = "us-central1-a" + deletion_protection = false node_pool { name = "%s" @@ -5762,6 +5999,7 @@ resource "google_container_cluster" "with_node_pool" { initial_node_count = 2 version = data.google_container_engine_versions.central1a.valid_node_versions[2] } + deletion_protection = false } `, cluster, nodePool) } @@ -5783,6 +6021,7 @@ resource "google_container_cluster" "with_node_pool" { initial_node_count = 2 version = data.google_container_engine_versions.central1a.valid_node_versions[1] } + deletion_protection = false } `, cluster, nodePool) } @@ -5802,6 +6041,7 @@ resource "google_container_cluster" "with_node_pool" { name = "%s" node_count = 2 } + deletion_protection = false } `, cluster, nodePool) } @@ -5821,6 +6061,7 @@ resource "google_container_cluster" "with_node_pool" { name = "%s" node_count = 3 } + deletion_protection = false } `, cluster, nodePool) } @@ -5837,6 +6078,7 @@ resource "google_container_cluster" "autoscaling_with_profile" { enabled = false autoscaling_profile = "%s" } + deletion_protection = false } `, cluster, autoscalingProfile) return config @@ -5854,6 +6096,7 @@ resource "google_container_cluster" "with_autoprovisioning" { location = "us-central1-a" min_master_version = data.google_container_engine_versions.central1a.latest_master_version initial_node_count = 1 + deletion_protection = false `, cluster) if autoprovisioning { config += ` @@ -5898,6 +6141,7 @@ resource "google_container_cluster" "with_autoprovisioning" { location = "us-central1-a" min_master_version = data.google_container_engine_versions.central1a.latest_master_version initial_node_count = 1 + deletion_protection = false logging_service = "none" monitoring_service = "none" @@ -5966,6 +6210,7 @@ resource "google_container_cluster" "with_autoprovisioning" { %s } } + deletion_protection = false }`, cluster, minCpuPlatformCfg) } @@ -6011,6 +6256,7 @@ func testAccContainerCluster_autoprovisioningDefaultsUpgradeSettings(clusterName } } } + deletion_protection = false } `, clusterName, maxSurge, maxUnavailable, strategy, blueGreenSettings) } @@ -6048,6 +6294,7 @@ func testAccContainerCluster_autoprovisioningDefaultsUpgradeSettingsWithBlueGree } } } + deletion_protection = false } `, clusterName, strategy, duration, duration) } @@ -6081,6 +6328,7 @@ resource "google_container_cluster" "with_autoprovisioning" { %s } } + deletion_protection = false }`, cluster, DiskSizeGbCfg) } @@ -6113,6 +6361,7 @@ resource "google_container_cluster" "with_autoprovisioning" { %s } } + deletion_protection = false }`, cluster, DiskTypeCfg) } @@ -6145,6 +6394,7 @@ resource "google_container_cluster" "with_autoprovisioning" { %s } } + deletion_protection = false }`, cluster, imageTypeCfg) } @@ -6171,6 +6421,7 @@ resource "google_container_cluster" "nap_boot_disk_kms_key" { boot_disk_kms_key = "%s" } } + deletion_protection = false } `, clusterName, kmsKeyName) } @@ -6202,6 +6453,7 @@ resource "google_container_cluster" "nap_shielded_instance" { } } } + deletion_protection = false }`, cluster) } @@ -6219,6 +6471,7 @@ resource "google_container_cluster" "with_node_pool" { max_node_count = 3 } } + deletion_protection = false } `, cluster, np) } @@ -6237,6 +6490,7 @@ resource "google_container_cluster" "with_node_pool" { max_node_count = 5 } } + deletion_protection = false } `, cluster, np) } @@ -6261,6 +6515,7 @@ resource "google_container_cluster" "with_node_pool" { location_policy = "BALANCED" } } + deletion_protection = false } `, cluster, np) } @@ -6285,6 +6540,7 @@ resource "google_container_cluster" "with_node_pool" { location_policy = "ANY" } } + deletion_protection = false } `, cluster, np) } @@ -6304,6 +6560,7 @@ resource "google_container_cluster" "with_node_pool" { name = "%s" initial_node_count = 2 } + deletion_protection = false } `, cluster, nodePool) } @@ -6318,6 +6575,7 @@ resource "google_container_cluster" "with_node_pool_name_prefix" { name_prefix = "%s" node_count = 2 } + deletion_protection = false } `, cluster, npPrefix) } @@ -6337,6 +6595,7 @@ resource "google_container_cluster" "with_node_pool_multiple" { name = "%s-two" node_count = 3 } + deletion_protection = false } `, cluster, npPrefix, npPrefix) } @@ -6353,6 +6612,7 @@ resource "google_container_cluster" "with_node_pool_multiple" { name_prefix = "%s" node_count = 1 } + deletion_protection = false } `, cluster, npPrefix, npPrefix) } @@ -6387,6 +6647,7 @@ resource "google_container_cluster" "with_node_pool_node_config" { tags = ["foo", "bar"] } } + deletion_protection = false } `, cluster, np) } @@ -6408,6 +6669,7 @@ resource "google_container_cluster" "with_maintenance_window" { location = "us-central1-a" initial_node_count = 1 %s + deletion_protection = false } `, clusterName, maintenancePolicy) } @@ -6431,6 +6693,7 @@ resource "google_container_cluster" "with_recurring_maintenance_window" { location = "us-central1-a" initial_node_count = 1 %s + deletion_protection = false } `, clusterName, maintenancePolicy) @@ -6461,6 +6724,7 @@ resource "google_container_cluster" "with_maintenance_exclusion_window" { end_time = "%s" } } + deletion_protection = false } `, clusterName, w1startTime, w1endTime, w1startTime, w1endTime, w2startTime, w2endTime) } @@ -6496,6 +6760,7 @@ resource "google_container_cluster" "with_maintenance_exclusion_options" { } } } + deletion_protection = false } `, cclusterName, w1startTime, w1endTime, w1startTime, w1endTime, scope1, w2startTime, w2endTime, scope2) } @@ -6525,6 +6790,7 @@ resource "google_container_cluster" "with_maintenance_exclusion_options" { end_time = "%s" } } + deletion_protection = false } `, cclusterName, w1startTime, w1endTime, w1startTime, w1endTime, w2startTime, w2endTime) } @@ -6536,6 +6802,7 @@ resource "google_container_cluster" "with_maintenance_exclusion_options" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false maintenance_policy { recurring_window { @@ -6579,6 +6846,7 @@ resource "google_container_cluster" "with_maintenance_exclusion_window" { recurrence = "FREQ=DAILY" } } + deletion_protection = false } `, clusterName, w1startTime, w1endTime) } @@ -6601,6 +6869,7 @@ resource "google_container_cluster" "with_maintenance_exclusion_window" { end_time = "%s" } } + deletion_protection = false } `, clusterName, w1startTime, w1endTime) } @@ -6642,6 +6911,7 @@ resource "google_container_cluster" "with_ip_allocation_policy" { cluster_secondary_range_name = "pods" services_secondary_range_name = "services" } + deletion_protection = false } `, containerNetName, clusterName) } @@ -6674,6 +6944,7 @@ resource "google_container_cluster" "with_ip_allocation_policy" { cluster_ipv4_cidr_block = "10.0.0.0/16" services_ipv4_cidr_block = "10.1.0.0/16" } + deletion_protection = false } `, containerNetName, clusterName) } @@ -6706,6 +6977,7 @@ resource "google_container_cluster" "with_ip_allocation_policy" { cluster_ipv4_cidr_block = "/16" services_ipv4_cidr_block = "/22" } + deletion_protection = false } `, containerNetName, clusterName) } @@ -6743,6 +7015,7 @@ resource "google_container_cluster" "with_stack_type" { services_ipv4_cidr_block = "10.1.0.0/16" stack_type = "IPV4_IPV6" } + deletion_protection = false } `, containerNetName, clusterName) } @@ -6777,6 +7050,7 @@ resource "google_container_cluster" "with_stack_type" { services_ipv4_cidr_block = "10.1.0.0/16" stack_type = "IPV4" } + deletion_protection = false } `, containerNetName, clusterName) } @@ -6809,10 +7083,11 @@ resource "google_container_cluster" "with_pco_disabled" { ip_allocation_policy { cluster_ipv4_cidr_block = "10.1.0.0/16" services_ipv4_cidr_block = "10.2.0.0/16" - pod_cidr_overprovision_config { - disabled = true - } + pod_cidr_overprovision_config { + disabled = true + } } + deletion_protection = false } `, containerNetName, clusterName) } @@ -6841,6 +7116,7 @@ resource "google_container_cluster" "with_resource_usage_export_config" { dataset_id = google_bigquery_dataset.default.dataset_id } } + deletion_protection = false } `, datasetId, clusterName, enableMetering) } @@ -6857,6 +7133,7 @@ resource "google_container_cluster" "with_resource_usage_export_config" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } `, datasetId, clusterName) } @@ -6908,6 +7185,7 @@ resource "google_container_cluster" "with_private_cluster" { cluster_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[1].range_name } + deletion_protection = false } `, containerNetName, clusterName, location, autopilotEnabled) } @@ -6963,6 +7241,7 @@ resource "google_container_cluster" "with_private_cluster" { cluster_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[1].range_name } + deletion_protection = false } `, containerNetName, clusterName, masterGlobalAccessEnabled) } @@ -6979,6 +7258,7 @@ resource "google_container_cluster" "with_private_cluster" { enabled = %t } } + deletion_protection = false } `, clusterName, masterGlobalAccessEnabled) } @@ -6991,6 +7271,7 @@ resource "google_container_cluster" "with_shielded_nodes" { initial_node_count = 1 enable_shielded_nodes = %v + deletion_protection = false } `, clusterName, enabled) } @@ -7010,6 +7291,7 @@ resource "google_container_cluster" "with_workload_identity_config" { workload_pool = "${data.google_project.project.project_id}.svc.id.goog" } remove_default_node_pool = true + deletion_protection = false } `, projectID, clusterName) @@ -7039,6 +7321,7 @@ resource "google_container_cluster" "with_workload_identity_config" { initial_node_count = 1 remove_default_node_pool = true %s + deletion_protection = false } `, projectID, clusterName, workloadIdentityConfig) } @@ -7147,6 +7430,7 @@ resource "google_container_cluster" "shared_vpc_cluster" { google_compute_subnetwork_iam_member.service_network_cloud_services, google_compute_subnetwork_iam_member.service_network_gke_user, ] + deletion_protection = false } `, projectName, org, billingId, projectName, org, billingId, suffix, suffix, name) } @@ -7161,6 +7445,7 @@ resource "google_container_cluster" "with_binary_authorization_enabled_bool" { binary_authorization { enabled = %v } + deletion_protection = false } `, clusterName, enabled) } @@ -7178,6 +7463,7 @@ resource "google_container_cluster" "with_binary_authorization_evaluation_mode" binary_authorization { evaluation_mode = "%s" } + deletion_protection = false } `, clusterName, autopilot_enabled, evaluation_mode) } @@ -7231,6 +7517,7 @@ resource "google_container_cluster" "with_flexible_cidr" { } default_max_pods_per_node = 100 + deletion_protection = false } `, containerNetName, clusterName) } @@ -7263,6 +7550,7 @@ resource "google_container_cluster" "cidr_error_preempt" { cluster_ipv4_cidr_block = "10.0.0.0/16" services_ipv4_cidr_block = "10.1.0.0/16" } + deletion_protection = false } `, containerNetName, clusterName) } @@ -7285,6 +7573,7 @@ resource "google_container_cluster" "cidr_error_overlap" { cluster_ipv4_cidr_block = "10.0.0.0/16" services_ipv4_cidr_block = "10.1.0.0/16" } + deletion_protection = false } `, initConfig, secondCluster) } @@ -7295,6 +7584,7 @@ resource "google_container_cluster" "with_resource_labels" { name = "invalid-gke-cluster" location = "%s" initial_node_count = 1 + deletion_protection = false } `, location) } @@ -7312,6 +7602,7 @@ func testAccContainerCluster_withExternalIpsConfig(projectID string, clusterName service_external_ips_config { enabled = %v } + deletion_protection = false }`, projectID, clusterName, enabled) } @@ -7332,6 +7623,7 @@ func testAccContainerCluster_withMeshCertificatesConfigEnabled(projectID string, mesh_certificates { enable_certificates = true } + deletion_protection = false } `, projectID, clusterName) } @@ -7350,9 +7642,10 @@ func testAccContainerCluster_updateMeshCertificatesConfig(projectID string, clus workload_identity_config { workload_pool = "${data.google_project.project.project_id}.svc.id.goog" } - mesh_certificates { + mesh_certificates { enable_certificates = %v - } + } + deletion_protection = false }`, projectID, clusterName, enabled) } @@ -7369,6 +7662,7 @@ func testAccContainerCluster_updateCostManagementConfig(projectID string, cluste cost_management_config { enabled = %v } + deletion_protection = false }`, projectID, clusterName, enabled) } @@ -7405,6 +7699,7 @@ resource "google_container_cluster" "primary" { state = "ENCRYPTED" key_name = "%[2]s" } + deletion_protection = false } `, kmsData.KeyRing.Name, kmsData.CryptoKey.Name, clusterName) } @@ -7423,6 +7718,7 @@ resource "google_container_cluster" "primary" { release_channel { channel = "RAPID" } + deletion_protection = false } `, clusterName, datapathProvider) } @@ -7471,6 +7767,7 @@ resource "google_container_cluster" "with_private_cluster" { cluster_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[1].range_name } + deletion_protection = false } `, containerNetName, clusterName) } @@ -7490,6 +7787,7 @@ resource "google_container_cluster" "primary" { auto_upgrade = false } } + deletion_protection = false } `, cluster, np) } @@ -7505,6 +7803,7 @@ resource "google_container_cluster" "primary" { location = "us-central1-a" min_master_version = data.google_container_engine_versions.central1a.release_channel_latest_version["STABLE"] initial_node_count = 1 + deletion_protection = false } `, clusterName) } @@ -7520,6 +7819,7 @@ resource "google_container_cluster" "primary" { location = "us-central1-a" min_master_version = data.google_container_engine_versions.uscentral1a.release_channel_latest_version["STABLE"] initial_node_count = 1 + deletion_protection = false # This feature has been available since GKE 1.27, and currently the only # supported Beta API is authentication.k8s.io/v1beta1/selfsubjectreviews. @@ -7559,6 +7859,7 @@ resource "google_container_cluster" "primary" { enable_private_nodes = false master_ipv4_cidr_block = "10.42.0.0/28" } + deletion_protection = false } `, name) } @@ -7624,6 +7925,7 @@ resource "google_container_cluster" "with_autopilot" { name = "%s" location = "%s" enable_autopilot = %v + deletion_protection = false min_master_version = "latest" release_channel { channel = "RAPID" @@ -7667,6 +7969,7 @@ resource "google_container_cluster" "with_dns_config" { cluster_dns_domain = "%s" cluster_dns_scope = "%s" } + deletion_protection = false } `, clusterName, clusterDns, clusterDnsDomain, clusterDnsScope) } @@ -7685,6 +7988,7 @@ resource "google_container_cluster" "primary" { gateway_api_config { channel = "%s" } + deletion_protection = false } `, clusterName, gatewayApiChannel) } @@ -7699,6 +8003,7 @@ resource "google_container_cluster" "primary" { identity_service_config { enabled = true } + deletion_protection = false } `, name) } @@ -7712,6 +8017,7 @@ resource "google_container_cluster" "primary" { identity_service_config { enabled = false } + deletion_protection = false } `, name) } @@ -7729,6 +8035,7 @@ resource "google_container_cluster" "primary" { monitoring_config { enable_components = [ "SYSTEM_COMPONENTS" ] } + deletion_protection = false } `, name) } @@ -7742,6 +8049,7 @@ resource "google_container_cluster" "primary" { logging_config { enable_components = [] } + deletion_protection = false } `, name) } @@ -7758,6 +8066,7 @@ resource "google_container_cluster" "primary" { monitoring_config { enable_components = [ "SYSTEM_COMPONENTS" ] } + deletion_protection = false } `, name) } @@ -7775,6 +8084,7 @@ resource "google_container_cluster" "primary" { monitoring_config { enable_components = [ "SYSTEM_COMPONENTS", "APISERVER", "CONTROLLER_MANAGER", "SCHEDULER" ] } + deletion_protection = false } `, name) } @@ -7788,6 +8098,7 @@ resource "google_container_cluster" "primary" { monitoring_config { enable_components = [] } + deletion_protection = false } `, name) } @@ -7801,6 +8112,7 @@ resource "google_container_cluster" "primary" { monitoring_config { enable_components = [ "SYSTEM_COMPONENTS", "APISERVER", "CONTROLLER_MANAGER" ] } + deletion_protection = false } `, name) } @@ -7817,6 +8129,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = false } `, name) } @@ -7833,6 +8146,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = false } `, name) } @@ -7848,6 +8162,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = false } `, name) } @@ -7897,6 +8212,7 @@ resource "google_container_cluster" "primary" { relay_mode = "INTERNAL_VPC_LB" } } + deletion_protection = false } `, name, name) } @@ -7946,6 +8262,7 @@ resource "google_container_cluster" "primary" { relay_mode = "DISABLED" } } + deletion_protection = false } `, name, name) } @@ -7977,6 +8294,7 @@ resource "google_container_cluster" "primary" { disk_type = "pd-ssd" node_group = google_compute_node_group.group.name } + deletion_protection = false } `, name, name, name) } @@ -8034,6 +8352,7 @@ resource "google_container_cluster" "with_tpu_config" { cluster_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[1].range_name } + deletion_protection = false } `, network, cluster) } @@ -8054,6 +8373,7 @@ resource "google_container_cluster" "primary" { timeouts { create = "40s" } + deletion_protection = false }`, cluster, project, project) } @@ -8068,6 +8388,7 @@ resource "google_container_cluster" "primary" { workload_identity_config { workload_pool = "%s.svc.id.goog" } + deletion_protection = false }`, cluster, project, project) } @@ -8085,6 +8406,7 @@ resource "google_container_cluster" "primary" { } workload_vulnerability_mode = "BASIC" } + deletion_protection = false } `, name) } @@ -8102,6 +8424,7 @@ resource "google_container_cluster" "primary" { } workload_vulnerability_mode = "DISABLED" } + deletion_protection = false } `, name) } @@ -8114,6 +8437,7 @@ resource "google_container_cluster" "primary" { name = "%s" location = "us-central1" enable_autopilot = true + deletion_protection = false }`, name) } @@ -8125,6 +8449,7 @@ resource "google_container_cluster" "primary" { enable_autopilot = true allow_net_admin = %t min_master_version = 1.27 + deletion_protection = false }`, name, enabled) } @@ -8153,6 +8478,7 @@ func TestAccContainerCluster_customPlacementPolicy(t *testing.T) { ResourceName: "google_container_cluster.cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -8186,6 +8512,7 @@ resource "google_container_cluster" "cluster" { policy_name = google_compute_resource_policy.policy.name } } + deletion_protection = false }`, policyName, cluster, np) } @@ -8265,6 +8592,7 @@ func testAccContainerCluster_additional_pod_ranges_config(name string, nameCount services_secondary_range_name = "gke-autopilot-services" %s } + deletion_protection = false } `, name, name, name, aprc) } 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 11a4f1d43c61..3c4d3eecfe76 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 @@ -516,7 +516,7 @@ func TestAccContainerNodePool_withMultiNicNetworkConfig(t *testing.T) { ResourceName: "google_container_cluster.cluster", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"network_config.0.create_pod_range"}, + ImportStateVerifyIgnore: []string{"network_config.0.create_pod_range", "deletion_protection"}, }, }, }) @@ -595,6 +595,7 @@ resource "google_container_cluster" "cluster" { cluster_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[1].range_name } + deletion_protection = false } resource "google_container_node_pool" "with_enable_private_nodes" { @@ -1262,6 +1263,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1317,6 +1319,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" min_master_version = data.google_container_engine_versions.central1a.latest_master_version initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1371,6 +1374,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" min_master_version = data.google_container_engine_versions.central1a.latest_master_version initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1418,6 +1422,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1466,6 +1471,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1531,6 +1537,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-f" initial_node_count = 1 min_master_version = "1.25" + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1575,6 +1582,7 @@ func TestAccContainerNodePool_compactPlacement(t *testing.T) { ResourceName: "google_container_cluster.cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1586,6 +1594,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1639,6 +1648,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_compute_resource_policy" "policy" { @@ -1684,6 +1694,7 @@ func TestAccContainerNodePool_threadsPerCore(t *testing.T) { ResourceName: "google_container_cluster.cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1695,6 +1706,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false node_config { machine_type = "c2-standard-4" @@ -1767,6 +1779,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1785,6 +1798,7 @@ resource "google_container_cluster" "with_logging_variant" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "with_logging_variant" { @@ -1810,6 +1824,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1866,6 +1881,7 @@ resource "google_container_cluster" "cluster" { master_authorized_networks_config { } + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1924,6 +1940,7 @@ resource "google_container_cluster" "cluster" { master_authorized_networks_config { } + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1942,6 +1959,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1959,6 +1977,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1976,6 +1995,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1992,6 +2012,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -2014,6 +2035,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1" initial_node_count = 3 min_master_version = "1.27" + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -2037,6 +2059,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1" initial_node_count = 3 min_master_version = "1.27" + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -2066,6 +2089,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1" initial_node_count = 3 min_master_version = "1.27" + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -2084,6 +2108,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -2105,6 +2130,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -2131,6 +2157,7 @@ resource "google_container_cluster" "cluster" { "us-central1-b", "us-central1-c", ] + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -2153,6 +2180,7 @@ resource "google_container_cluster" "cluster" { "us-central1-b", "us-central1-c", ] + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -2173,6 +2201,7 @@ resource "google_container_cluster" "cluster" { release_channel { channel = "UNSPECIFIED" } + deletion_protection = false } resource "google_container_node_pool" "np_with_management" { @@ -2198,6 +2227,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "np_with_node_config" { @@ -2252,6 +2282,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "np_with_node_config" { @@ -2313,6 +2344,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1a.latest_master_version + deletion_protection = false } resource "google_container_node_pool" "with_reservation_affinity" { @@ -2345,6 +2377,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1a.latest_master_version + deletion_protection = false } resource "google_compute_reservation" "gce_reservation" { @@ -2396,6 +2429,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1a.latest_master_version + deletion_protection = false } resource "google_container_node_pool" "with_workload_metadata_config" { @@ -2437,6 +2471,7 @@ resource "google_container_cluster" "cluster" { workload_identity_config { workload_pool = "${data.google_project.project.project_id}.svc.id.goog" } + deletion_protection = false } resource "google_container_node_pool" "with_workload_metadata_config" { @@ -2470,6 +2505,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1a.latest_master_version + deletion_protection = false } resource "google_container_node_pool" "with_sandbox_config" { @@ -2510,6 +2546,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1a.latest_master_version + deletion_protection = false } # cpu_manager_policy & cpu_cfs_quota_period cannot be blank if cpu_cfs_quota is set to true @@ -2548,6 +2585,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1a.latest_master_version + deletion_protection = false } resource "google_container_node_pool" "with_linux_node_config" { @@ -2631,6 +2669,7 @@ resource "google_container_cluster" "cluster" { release_channel { channel = "RAPID" } + deletion_protection = false } resource "google_container_node_pool" "with_manual_pod_cidr" { @@ -2768,6 +2807,7 @@ resource "google_container_cluster" "cluster" { } enable_multi_networking = true datapath_provider = "ADVANCED_DATAPATH" + deletion_protection = false } resource "google_container_node_pool" "with_multi_nic" { @@ -2829,6 +2869,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1a.latest_master_version + deletion_protection = false } resource "google_container_node_pool" "with_boot_disk_kms_key" { @@ -2886,6 +2927,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1" initial_node_count = 1 min_master_version = "${data.google_container_engine_versions.central1.latest_master_version}" + deletion_protection = false } resource "google_container_node_pool" "with_upgrade_settings" { @@ -2909,6 +2951,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-c" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1c.latest_master_version + deletion_protection = false } resource "google_container_node_pool" "np_with_gpu" { @@ -2958,6 +3001,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "np_with_node_config_scope_alias" { @@ -2985,6 +3029,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1a.latest_master_version + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -3009,6 +3054,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1a.latest_master_version + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -3028,6 +3074,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-f" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -3053,6 +3100,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-f" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -3074,6 +3122,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-f" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -3099,6 +3148,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-f" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -3129,6 +3179,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-f" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -3164,6 +3215,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -3187,6 +3239,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np1" { @@ -3211,6 +3264,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np1" { @@ -3255,6 +3309,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1a.latest_master_version + deletion_protection = false } resource "google_container_node_pool" "with_sole_tenant_config" { @@ -3331,6 +3386,7 @@ resource "google_container_cluster" "cluster" { } machine_type = "n2-standard-2" } + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -3360,6 +3416,7 @@ resource "google_container_cluster" "cluster" { } machine_type = "n2-standard-2" } + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -3414,6 +3471,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central2-b" initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "regular_pool" { @@ -3482,6 +3540,7 @@ resource "google_container_cluster" "cluster" { } machine_type = "n2-standard-2" } + deletion_protection = false } resource "google_container_node_pool" "np" { 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 7f0ffe052456..db170c912973 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 @@ -1165,6 +1165,7 @@ resource "google_container_cluster" "primary" { workload_identity_config { workload_pool = "${data.google_project.project.project_id}.svc.id.goog" } + deletion_protection = false } resource "google_project_iam_binding" "workloadidentity" { diff --git a/mmv1/third_party/terraform/services/dns/resource_dns_managed_zone_test.go.erb b/mmv1/third_party/terraform/services/dns/resource_dns_managed_zone_test.go.erb index a964f5a33b37..fbbd8ad3bbcf 100644 --- a/mmv1/third_party/terraform/services/dns/resource_dns_managed_zone_test.go.erb +++ b/mmv1/third_party/terraform/services/dns/resource_dns_managed_zone_test.go.erb @@ -443,6 +443,7 @@ resource "google_container_cluster" "cluster-1" { name = "tf-test-cluster-1-%s" location = "us-central1-c" initial_node_count = 1 + deletion_protection = false networking_mode = "VPC_NATIVE" default_snat_status { diff --git a/mmv1/third_party/terraform/services/dns/resource_dns_response_policy_test.go.erb b/mmv1/third_party/terraform/services/dns/resource_dns_response_policy_test.go.erb index 3bc78da05c1a..5029770f1cef 100644 --- a/mmv1/third_party/terraform/services/dns/resource_dns_response_policy_test.go.erb +++ b/mmv1/third_party/terraform/services/dns/resource_dns_response_policy_test.go.erb @@ -125,6 +125,7 @@ resource "google_container_cluster" "cluster-1" { cluster_secondary_range_name = google_compute_subnetwork.subnetwork-1.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.subnetwork-1.secondary_ip_range[1].range_name } + deletion_protection = false } `, suffix, network, suffix, suffix, suffix) } @@ -203,6 +204,7 @@ resource "google_container_cluster" "cluster-1" { cluster_secondary_range_name = google_compute_subnetwork.subnetwork-1.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.subnetwork-1.secondary_ip_range[1].range_name } + deletion_protection = false } `, suffix, suffix, suffix, suffix) } diff --git a/mmv1/third_party/terraform/services/gkebackup/resource_gke_backup_backup_plan_test.go.erb b/mmv1/third_party/terraform/services/gkebackup/resource_gke_backup_backup_plan_test.go.erb index 47650b4288f7..9c8b4886b507 100644 --- a/mmv1/third_party/terraform/services/gkebackup/resource_gke_backup_backup_plan_test.go.erb +++ b/mmv1/third_party/terraform/services/gkebackup/resource_gke_backup_backup_plan_test.go.erb @@ -59,6 +59,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = false } resource "google_gke_backup_backup_plan" "backupplan" { @@ -91,6 +92,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = false } resource "google_gke_backup_backup_plan" "backupplan" { diff --git a/mmv1/third_party/terraform/services/gkehub/resource_gke_hub_feature_membership_test.go.erb b/mmv1/third_party/terraform/services/gkehub/resource_gke_hub_feature_membership_test.go.erb index 8d905fadbf77..66015707cc14 100644 --- a/mmv1/third_party/terraform/services/gkehub/resource_gke_hub_feature_membership_test.go.erb +++ b/mmv1/third_party/terraform/services/gkehub/resource_gke_hub_feature_membership_test.go.erb @@ -387,6 +387,7 @@ resource "google_container_cluster" "primary" { name = "tf-test-cl%{random_suffix}" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false depends_on = [google_project_service.mci, google_project_service.container, google_project_service.container, google_project_service.gkehub] } @@ -452,6 +453,7 @@ resource "google_container_cluster" "primary" { name = "tf-test-cl%{random_suffix}" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false depends_on = [google_project_service.mci, google_project_service.container, google_project_service.container, google_project_service.gkehub] } @@ -518,6 +520,7 @@ resource "google_container_cluster" "primary" { name = "tf-test-cl%{random_suffix}" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false depends_on = [google_project_service.mci, google_project_service.container, google_project_service.container, google_project_service.gkehub, google_project_service.acm] } @@ -817,6 +820,7 @@ resource "google_container_cluster" "primary" { name = "tf-test-cl%{random_suffix}" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false depends_on = [google_project_service.container, google_project_service.gkehub] } @@ -869,6 +873,7 @@ resource "google_container_cluster" "primary" { name = "tf-test-cl%{random_suffix}" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false depends_on = [google_project_service.container, google_project_service.gkehub] } @@ -920,6 +925,7 @@ resource "google_container_cluster" "primary" { name = "tf-test-cl%{random_suffix}" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false depends_on = [google_project_service.container, google_project_service.gkehub] } @@ -971,6 +977,7 @@ resource "google_container_cluster" "primary" { location = "us-central1-a" initial_node_count = 1 project = google_project.project.project_id + deletion_protection = false depends_on = [google_project_service.container, google_project_service.container, google_project_service.gkehub] } @@ -979,6 +986,7 @@ resource "google_container_cluster" "secondary" { location = "us-central1-a" initial_node_count = 1 project = google_project.project.project_id + deletion_protection = false depends_on = [google_project_service.container, google_project_service.container, google_project_service.gkehub] } @@ -987,6 +995,7 @@ resource "google_container_cluster" "tertiary" { location = "us-central1-a" initial_node_count = 1 project = google_project.project.project_id + deletion_protection = false depends_on = [google_project_service.container, google_project_service.container, google_project_service.gkehub] } @@ -996,6 +1005,7 @@ resource "google_container_cluster" "quarternary" { location = "us-central1-a" initial_node_count = 1 project = google_project.project.project_id + deletion_protection = false depends_on = [google_project_service.container, google_project_service.container, google_project_service.gkehub] } @@ -1069,6 +1079,7 @@ resource "google_container_cluster" "container_acmoci" { initial_node_count = 1 network = google_compute_network.testnetwork.self_link project = google_project.project.project_id + deletion_protection = false depends_on = [google_project_service.container, google_project_service.container, google_project_service.gkehub] } diff --git a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_feature_test.go.erb b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_feature_test.go.erb index 11580f7c3c63..616bebb70a6b 100644 --- a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_feature_test.go.erb +++ b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_feature_test.go.erb @@ -245,6 +245,7 @@ resource "google_container_cluster" "primary" { location = "us-central1-a" initial_node_count = 1 project = google_project.project.project_id + deletion_protection = false depends_on = [google_project_service.mci, google_project_service.container, google_project_service.container, google_project_service.gkehub] } @@ -253,6 +254,7 @@ resource "google_container_cluster" "secondary" { location = "us-central1-a" initial_node_count = 1 project = google_project.project.project_id + deletion_protection = false depends_on = [google_project_service.mci, google_project_service.container, google_project_service.container, google_project_service.gkehub] } @@ -296,6 +298,7 @@ resource "google_container_cluster" "primary" { location = "us-central1-a" initial_node_count = 1 project = google_project.project.project_id + deletion_protection = false depends_on = [google_project_service.mci, google_project_service.container, google_project_service.container, google_project_service.gkehub] } @@ -304,6 +307,7 @@ resource "google_container_cluster" "secondary" { location = "us-central1-a" initial_node_count = 1 project = google_project.project.project_id + deletion_protection = false depends_on = [google_project_service.mci, google_project_service.container, google_project_service.container, google_project_service.gkehub] } diff --git a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_membership_binding_test.go b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_membership_binding_test.go index b800f61a99bc..8f1a7bc10787 100644 --- a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_membership_binding_test.go +++ b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_membership_binding_test.go @@ -50,6 +50,7 @@ resource "google_container_cluster" "primary" { name = "basiccluster%{random_suffix}" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_gke_hub_membership" "example" { @@ -91,6 +92,7 @@ resource "google_container_cluster" "primary" { name = "basiccluster%{random_suffix}" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_gke_hub_membership" "example" { diff --git a/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown b/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown index 5a1c9688de2b..f9d4b4cecbcc 100644 --- a/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown @@ -16,6 +16,10 @@ Manages a Google Kubernetes Engine (GKE) cluster. For more information see [the official documentation](https://cloud.google.com/container-engine/docs/clusters) and [the API reference](https://cloud.google.com/kubernetes-engine/docs/reference/rest/v1beta1/projects.locations.clusters). +-> **Note**: On version 5.0.0+ of the provider, you must explicitly set `deletion_protection=false` +(and run `terraform apply` to write the field to state) in order to destroy a cluster. +It is recommended to not set this field (or set it to true) until you're ready to destroy. + ~> **Warning:** All arguments and attributes, including basic auth username and passwords as well as certificate outputs will be stored in the raw state as plaintext. [Read more about sensitive data in state](https://www.terraform.io/language/state/sensitive-data). @@ -118,6 +122,10 @@ locations. In contrast, in a regional cluster, cluster master nodes are present in multiple zones in the region. For that reason, regional clusters should be preferred. +* `deletion_protection` - (Optional) Whether or not to allow Terraform to destroy +the cluster. Unless this field is set to false in Terraform state, a +`terraform destroy` or `terraform apply` that would delete the cluster will fail. + * `addons_config` - (Optional) The configuration for addons supported by GKE. Structure is [documented below](#nested_addons_config). From 262bbe6ff4f6167c081f381c9dea88d3c49398fd Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Tue, 26 Sep 2023 17:18:00 -0500 Subject: [PATCH 64/67] 5.0.0 - remove computed keys from JSON in monitoring dashboard (#9065) --- .../resource_monitoring_dashboard.go | 37 +++++++++++++++---- .../resource_monitoring_dashboard_test.go | 2 - .../docs/r/monitoring_dashboard.html.markdown | 6 +++ 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/mmv1/third_party/terraform/services/monitoring/resource_monitoring_dashboard.go b/mmv1/third_party/terraform/services/monitoring/resource_monitoring_dashboard.go index aa8a0d57c5e3..458b5cfbb1c8 100644 --- a/mmv1/third_party/terraform/services/monitoring/resource_monitoring_dashboard.go +++ b/mmv1/third_party/terraform/services/monitoring/resource_monitoring_dashboard.go @@ -14,24 +14,45 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) -func monitoringDashboardDiffSuppress(k, old, new string, d *schema.ResourceData) bool { - computedFields := []string{"etag", "name"} +// This recursive function takes an old map and a new map and is intended to remove the computed keys +// from the old json string (stored in state) so that it doesn't show a diff if it's not defined in the +// new map's json string (defined in config) +func removeComputedKeys(old map[string]interface{}, new map[string]interface{}) map[string]interface{} { + for k, v := range old { + if _, ok := old[k]; ok && new[k] == nil { + delete(old, k) + continue + } + + if reflect.ValueOf(v).Kind() == reflect.Map { + old[k] = removeComputedKeys(v.(map[string]interface{}), new[k].(map[string]interface{})) + continue + } + + if reflect.ValueOf(v).Kind() == reflect.Slice { + for i, j := range v.([]interface{}) { + if reflect.ValueOf(j).Kind() == reflect.Map { + old[k].([]interface{})[i] = removeComputedKeys(j.(map[string]interface{}), new[k].([]interface{})[i].(map[string]interface{})) + } + } + continue + } + } + + return old +} +func monitoringDashboardDiffSuppress(k, old, new string, d *schema.ResourceData) bool { oldMap, err := structure.ExpandJsonFromString(old) if err != nil { return false } - newMap, err := structure.ExpandJsonFromString(new) if err != nil { return false } - for _, f := range computedFields { - delete(oldMap, f) - delete(newMap, f) - } - + oldMap = removeComputedKeys(oldMap, newMap) return reflect.DeepEqual(oldMap, newMap) } diff --git a/mmv1/third_party/terraform/services/monitoring/resource_monitoring_dashboard_test.go b/mmv1/third_party/terraform/services/monitoring/resource_monitoring_dashboard_test.go index 1f8caaa86759..5c1a5d28afd7 100644 --- a/mmv1/third_party/terraform/services/monitoring/resource_monitoring_dashboard_test.go +++ b/mmv1/third_party/terraform/services/monitoring/resource_monitoring_dashboard_test.go @@ -83,8 +83,6 @@ func TestAccMonitoringDashboard_rowLayout(t *testing.T) { } func TestAccMonitoringDashboard_update(t *testing.T) { - // TODO: Fix requires a breaking change https://github.com/hashicorp/terraform-provider-google/issues/9976 - t.Skip() t.Parallel() acctest.VcrTest(t, resource.TestCase{ diff --git a/mmv1/third_party/terraform/website/docs/r/monitoring_dashboard.html.markdown b/mmv1/third_party/terraform/website/docs/r/monitoring_dashboard.html.markdown index b3d0e0dd63b6..97c32f85b993 100644 --- a/mmv1/third_party/terraform/website/docs/r/monitoring_dashboard.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/monitoring_dashboard.html.markdown @@ -114,6 +114,12 @@ The following arguments are supported: The JSON representation of a dashboard, following the format at https://cloud.google.com/monitoring/api/ref_v3/rest/v1/projects.dashboards. The representation of an existing dashboard can be found by using the [API Explorer](https://cloud.google.com/monitoring/api/ref_v3/rest/v1/projects.dashboards/get) + ~> **Warning:** Because this is represented as a JSON string, Terraform doesn't have underlying information to know + which fields in the string have defaults. To prevent permanent diffs from default values, Terraform will attempt to + suppress diffs where the value is returned in the JSON string but doesn't exist in the configuration. Consequently, + legitmate remove-only diffs will also be suppressed. For Terraform to detect the diff, key removals must also be + accompanied by a non-removal change (trivial or not). + - - - From 1155209a13cc0767493aeeb3784e7d0eb2e94659 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Tue, 26 Sep 2023 15:32:15 -0700 Subject: [PATCH 65/67] Apply new labels model to google_gke_backup_restore_plan (#9093) --- mmv1/products/gkebackup/RestorePlan.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmv1/products/gkebackup/RestorePlan.yaml b/mmv1/products/gkebackup/RestorePlan.yaml index 556eca8574e9..c70bda73c22d 100644 --- a/mmv1/products/gkebackup/RestorePlan.yaml +++ b/mmv1/products/gkebackup/RestorePlan.yaml @@ -137,7 +137,7 @@ properties: name: description description: | User specified descriptive string for this RestorePlan. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: labels description: | Description: A set of custom labels supplied by the user. From 9e3193cf3e56a89f499c6645930a8516a598b94c Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Wed, 27 Sep 2023 14:17:31 -0500 Subject: [PATCH 66/67] remove alloydb backup test overrides --- mmv1/products/alloydb/Backup.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/mmv1/products/alloydb/Backup.yaml b/mmv1/products/alloydb/Backup.yaml index ca21f23e49c9..454e5a5c779a 100644 --- a/mmv1/products/alloydb/Backup.yaml +++ b/mmv1/products/alloydb/Backup.yaml @@ -42,8 +42,6 @@ examples: alloydb_cluster_name: 'alloydb-cluster' alloydb_instance_name: 'alloydb-instance' network_name: 'alloydb-network' - test_vars_overrides: - network_name: 'acctest.BootstrapSharedTestNetwork(t, "alloydb-backup-basic")' ignore_read_extra: - 'reconciling' - 'update_time' @@ -55,8 +53,6 @@ examples: alloydb_cluster_name: 'alloydb-cluster' alloydb_instance_name: 'alloydb-instance' network_name: 'alloydb-network' - test_vars_overrides: - network_name: 'acctest.BootstrapSharedTestNetwork(t, "alloydb-backup-full")' ignore_read_extra: - 'reconciling' - 'update_time' From d7c47451a7fcb600c55249b7d7f9333862f12c15 Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Thu, 28 Sep 2023 11:34:02 -0500 Subject: [PATCH 67/67] Temporary fix for TGC tests (#9116) --- ...ess_context_manager_service_perimeter.json | 0 ...ccess_context_manager_service_perimeter.tf | 0 ...text_manager_service_perimeter.tfplan.json | 0 .../example_bigquery_dataset.json | 5 +--- .../example_bigquery_dataset.tf | 0 .../example_bigquery_dataset.tfplan.json | 0 .../example_bigquery_dataset_iam_binding.json | 5 +--- .../example_bigquery_dataset_iam_binding.tf | 0 ...e_bigquery_dataset_iam_binding.tfplan.json | 0 .../example_bigquery_dataset_iam_member.json | 5 +--- .../example_bigquery_dataset_iam_member.tf | 0 ...le_bigquery_dataset_iam_member.tfplan.json | 0 .../example_bigquery_dataset_iam_policy.json | 5 +--- .../example_bigquery_dataset_iam_policy.tf | 0 ...le_bigquery_dataset_iam_policy.tfplan.json | 0 ..._dataset_iam_policy_empty_policy_data.json | 0 ...ry_dataset_iam_policy_empty_policy_data.tf | 0 ...t_iam_policy_empty_policy_data.tfplan.json | 0 .../example_cloud_run_service.json | 5 +--- .../example_cloud_run_service.tf | 0 .../example_cloud_run_service.tfplan.json | 0 .../example_compute_disk.json | 5 +--- .../example_compute_disk.tf | 0 .../example_compute_disk.tfplan.json | 0 .../example_compute_disk_empty_image.json | 5 +--- .../example_compute_disk_empty_image.tf | 0 ...ample_compute_disk_empty_image.tfplan.json | 0 .../example_compute_snapshot.json | 5 +--- .../example_compute_snapshot.tf | 0 .../example_compute_snapshot.tfplan.json | 0 .../example_pubsub_subscription.json | 6 ----- .../example_pubsub_subscription.tf | 0 .../example_pubsub_subscription.tfplan.json | 0 ...ample_pubsub_subscription_iam_binding.json | 5 +--- ...example_pubsub_subscription_iam_binding.tf | 0 ...ubsub_subscription_iam_binding.tfplan.json | 0 ...xample_pubsub_subscription_iam_member.json | 5 +--- .../example_pubsub_subscription_iam_member.tf | 0 ...pubsub_subscription_iam_member.tfplan.json | 0 ...xample_pubsub_subscription_iam_policy.json | 5 +--- .../example_pubsub_subscription_iam_policy.tf | 0 ...pubsub_subscription_iam_policy.tfplan.json | 0 .../example_pubsub_topic.json | 3 --- .../example_pubsub_topic.tf | 0 .../example_pubsub_topic.tfplan.json | 0 .../example_sql_database_instance.json | 0 .../example_sql_database_instance.tf | 0 .../example_sql_database_instance.tfplan.json | 0 .../data-ignored/full_spanner_instance.json | 21 +++++++++++++++ .../full_spanner_instance.tf | 0 .../full_spanner_instance.tfplan.json | 0 .../full_sql_database_instance.json | 0 .../full_sql_database_instance.tf | 0 .../full_sql_database_instance.tfplan.json | 0 .../tgc/tests/data/full_spanner_instance.json | 26 ------------------- 55 files changed, 32 insertions(+), 79 deletions(-) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_access_context_manager_service_perimeter.json (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_access_context_manager_service_perimeter.tf (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_access_context_manager_service_perimeter.tfplan.json (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_bigquery_dataset.json (92%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_bigquery_dataset.tf (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_bigquery_dataset.tfplan.json (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_bigquery_dataset_iam_binding.json (94%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_bigquery_dataset_iam_binding.tf (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_bigquery_dataset_iam_binding.tfplan.json (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_bigquery_dataset_iam_member.json (94%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_bigquery_dataset_iam_member.tf (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_bigquery_dataset_iam_member.tfplan.json (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_bigquery_dataset_iam_policy.json (94%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_bigquery_dataset_iam_policy.tf (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_bigquery_dataset_iam_policy.tfplan.json (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_bigquery_dataset_iam_policy_empty_policy_data.json (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_bigquery_dataset_iam_policy_empty_policy_data.tf (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_bigquery_dataset_iam_policy_empty_policy_data.tfplan.json (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_cloud_run_service.json (94%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_cloud_run_service.tf (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_cloud_run_service.tfplan.json (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_compute_disk.json (92%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_compute_disk.tf (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_compute_disk.tfplan.json (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_compute_disk_empty_image.json (92%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_compute_disk_empty_image.tf (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_compute_disk_empty_image.tfplan.json (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_compute_snapshot.json (95%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_compute_snapshot.tf (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_compute_snapshot.tfplan.json (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_pubsub_subscription.json (92%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_pubsub_subscription.tf (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_pubsub_subscription.tfplan.json (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_pubsub_subscription_iam_binding.json (93%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_pubsub_subscription_iam_binding.tf (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_pubsub_subscription_iam_binding.tfplan.json (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_pubsub_subscription_iam_member.json (93%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_pubsub_subscription_iam_member.tf (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_pubsub_subscription_iam_member.tfplan.json (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_pubsub_subscription_iam_policy.json (93%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_pubsub_subscription_iam_policy.tf (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_pubsub_subscription_iam_policy.tfplan.json (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_pubsub_topic.json (90%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_pubsub_topic.tf (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_pubsub_topic.tfplan.json (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_sql_database_instance.json (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_sql_database_instance.tf (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/example_sql_database_instance.tfplan.json (100%) create mode 100644 mmv1/third_party/tgc/tests/data-ignored/full_spanner_instance.json rename mmv1/third_party/tgc/tests/{data => data-ignored}/full_spanner_instance.tf (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/full_spanner_instance.tfplan.json (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/full_sql_database_instance.json (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/full_sql_database_instance.tf (100%) rename mmv1/third_party/tgc/tests/{data => data-ignored}/full_sql_database_instance.tfplan.json (100%) delete mode 100644 mmv1/third_party/tgc/tests/data/full_spanner_instance.json diff --git a/mmv1/third_party/tgc/tests/data/example_access_context_manager_service_perimeter.json b/mmv1/third_party/tgc/tests/data-ignored/example_access_context_manager_service_perimeter.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_access_context_manager_service_perimeter.json rename to mmv1/third_party/tgc/tests/data-ignored/example_access_context_manager_service_perimeter.json diff --git a/mmv1/third_party/tgc/tests/data/example_access_context_manager_service_perimeter.tf b/mmv1/third_party/tgc/tests/data-ignored/example_access_context_manager_service_perimeter.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_access_context_manager_service_perimeter.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_access_context_manager_service_perimeter.tf diff --git a/mmv1/third_party/tgc/tests/data/example_access_context_manager_service_perimeter.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_access_context_manager_service_perimeter.tfplan.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_access_context_manager_service_perimeter.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_access_context_manager_service_perimeter.tfplan.json diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.json b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset.json similarity index 92% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset.json rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset.json index c55d9a2c4ee6..a4a2b676db21 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset.json @@ -13,12 +13,9 @@ "datasetReference": { "datasetId": "test-dataset" }, - "labels": { - "env": "dev" - }, "location": "EU", "defaultTableExpirationMs": 3.6e+06 } } } -] +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tf b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset.tf diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset.tfplan.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset.tfplan.json diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.json b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_binding.json similarity index 94% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.json rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_binding.json index 770149249ec3..475d09d6eed7 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_binding.json @@ -13,9 +13,6 @@ "datasetId": "test-dataset" }, "defaultTableExpirationMs": 3600000, - "labels": { - "env": "dev" - }, "location": "EU", "friendlyName": "" } @@ -32,4 +29,4 @@ ] } } -] +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tf b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_binding.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_binding.tf diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_binding.tfplan.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_binding.tfplan.json diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.json b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_member.json similarity index 94% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.json rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_member.json index 7aed9ac6ce97..c352a6c27d7e 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_member.json @@ -13,9 +13,6 @@ "datasetId": "test-dataset" }, "defaultTableExpirationMs": 3600000, - "labels": { - "env": "dev" - }, "location": "EU", "friendlyName": "" } @@ -31,4 +28,4 @@ ] } } -] +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tf b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_member.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_member.tf diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_member.tfplan.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_member.tfplan.json diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.json b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy.json similarity index 94% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.json rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy.json index 5908f8d7600c..610a1d876072 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy.json @@ -13,9 +13,6 @@ "datasetId": "test-dataset" }, "defaultTableExpirationMs": 3600000, - "labels": { - "env": "dev" - }, "location": "EU", "friendlyName": "" } @@ -32,4 +29,4 @@ ] } } -] +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tf b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy.tf diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy.tfplan.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy.tfplan.json diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.json b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy_empty_policy_data.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.json rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy_empty_policy_data.json diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.tf b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy_empty_policy_data.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy_empty_policy_data.tf diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy_empty_policy_data.tfplan.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy_empty_policy_data.tfplan.json diff --git a/mmv1/third_party/tgc/tests/data/example_cloud_run_service.json b/mmv1/third_party/tgc/tests/data-ignored/example_cloud_run_service.json similarity index 94% rename from mmv1/third_party/tgc/tests/data/example_cloud_run_service.json rename to mmv1/third_party/tgc/tests/data-ignored/example_cloud_run_service.json index 70c5a7a0e44f..1816a9eedf8a 100644 --- a/mmv1/third_party/tgc/tests/data/example_cloud_run_service.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_cloud_run_service.json @@ -12,9 +12,6 @@ "apiVersion": "serving.knative.dev/v1", "kind": "Service", "metadata": { - "annotations": { - "generated-by": "magic-modules" - }, "name": "cloudrun-to-get-cai", "namespace": "{{.Provider.project}}" }, @@ -48,4 +45,4 @@ } } } -] +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/example_cloud_run_service.tf b/mmv1/third_party/tgc/tests/data-ignored/example_cloud_run_service.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_cloud_run_service.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_cloud_run_service.tf diff --git a/mmv1/third_party/tgc/tests/data/example_cloud_run_service.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_cloud_run_service.tfplan.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_cloud_run_service.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_cloud_run_service.tfplan.json diff --git a/mmv1/third_party/tgc/tests/data/example_compute_disk.json b/mmv1/third_party/tgc/tests/data-ignored/example_compute_disk.json similarity index 92% rename from mmv1/third_party/tgc/tests/data/example_compute_disk.json rename to mmv1/third_party/tgc/tests/data-ignored/example_compute_disk.json index 61a32615a0ac..7e41c7aee5fb 100644 --- a/mmv1/third_party/tgc/tests/data/example_compute_disk.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_compute_disk.json @@ -9,9 +9,6 @@ "discovery_name": "Disk", "parent": "//cloudresourcemanager.googleapis.com/projects/{{.Provider.project}}", "data": { - "labels": { - "environment": "dev" - }, "name": "test-disk", "physicalBlockSizeBytes": 4096, "sourceImage": "projects/debian-cloud/global/images/debian-8-jessie-v20170523", @@ -20,4 +17,4 @@ } } } -] +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/example_compute_disk.tf b/mmv1/third_party/tgc/tests/data-ignored/example_compute_disk.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_compute_disk.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_compute_disk.tf diff --git a/mmv1/third_party/tgc/tests/data/example_compute_disk.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_compute_disk.tfplan.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_compute_disk.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_compute_disk.tfplan.json diff --git a/mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.json b/mmv1/third_party/tgc/tests/data-ignored/example_compute_disk_empty_image.json similarity index 92% rename from mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.json rename to mmv1/third_party/tgc/tests/data-ignored/example_compute_disk_empty_image.json index ce1e0ebe8700..8df2a102df02 100644 --- a/mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_compute_disk_empty_image.json @@ -9,9 +9,6 @@ "discovery_name": "Disk", "parent": "//cloudresourcemanager.googleapis.com/projects/{{.Provider.project}}", "data": { - "labels": { - "environment": "dev" - }, "name": "test-disk", "physicalBlockSizeBytes": 4096, "type": "projects/{{.Provider.project}}/zones/us-central1-a/diskTypes/pd-ssd", @@ -19,4 +16,4 @@ } } } -] +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.tf b/mmv1/third_party/tgc/tests/data-ignored/example_compute_disk_empty_image.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_compute_disk_empty_image.tf diff --git a/mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_compute_disk_empty_image.tfplan.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_compute_disk_empty_image.tfplan.json diff --git a/mmv1/third_party/tgc/tests/data/example_compute_snapshot.json b/mmv1/third_party/tgc/tests/data-ignored/example_compute_snapshot.json similarity index 95% rename from mmv1/third_party/tgc/tests/data/example_compute_snapshot.json rename to mmv1/third_party/tgc/tests/data-ignored/example_compute_snapshot.json index dc1590f5f74c..2b42e398093b 100644 --- a/mmv1/third_party/tgc/tests/data/example_compute_snapshot.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_compute_snapshot.json @@ -9,9 +9,6 @@ "discovery_name": "Snapshot", "parent": "//cloudresourcemanager.googleapis.com/projects/{{.Provider.project}}", "data": { - "labels": { - "test-name": "test-value" - }, "name": "test-instance", "sourceDisk": "projects/{{.Provider.project}}/zones/us-central1-a/disks/debian-disk", "storageLocations": [ @@ -39,4 +36,4 @@ } } } -] +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/example_compute_snapshot.tf b/mmv1/third_party/tgc/tests/data-ignored/example_compute_snapshot.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_compute_snapshot.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_compute_snapshot.tf diff --git a/mmv1/third_party/tgc/tests/data/example_compute_snapshot.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_compute_snapshot.tfplan.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_compute_snapshot.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_compute_snapshot.tfplan.json diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription.json b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription.json similarity index 92% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription.json rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription.json index f883358d426c..975dba182166 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription.json @@ -14,9 +14,6 @@ "expirationPolicy": { "ttl": "300000.5s" }, - "labels": { - "test-label2": "test-value2" - }, "messageRetentionDuration": "1200s", "retainAckedMessages": true, "retryPolicy": { @@ -39,9 +36,6 @@ "ackDeadlineSeconds": 20, "deadLetterPolicy": null, "expirationPolicy": null, - "labels": { - "test-label1": "test-value1" - }, "messageRetentionDuration": "604800s", "pushConfig": { "pushEndpoint": "https://example.com/push" diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription.tf b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription.tf diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription.tfplan.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription.tfplan.json diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.json b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_binding.json similarity index 93% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.json rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_binding.json index de0fda73b41b..8780c890de23 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_binding.json @@ -12,9 +12,6 @@ "ackDeadlineSeconds": 20, "deadLetterPolicy": null, "expirationPolicy": null, - "labels": { - "test-label1": "test-value1" - }, "messageRetentionDuration": "604800s", "pushConfig": { "pushEndpoint": "https://example.com/push" @@ -33,4 +30,4 @@ ] } } -] +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.tf b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_binding.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_binding.tf diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_binding.tfplan.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_binding.tfplan.json diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.json b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_member.json similarity index 93% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.json rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_member.json index de0fda73b41b..8780c890de23 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_member.json @@ -12,9 +12,6 @@ "ackDeadlineSeconds": 20, "deadLetterPolicy": null, "expirationPolicy": null, - "labels": { - "test-label1": "test-value1" - }, "messageRetentionDuration": "604800s", "pushConfig": { "pushEndpoint": "https://example.com/push" @@ -33,4 +30,4 @@ ] } } -] +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.tf b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_member.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_member.tf diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_member.tfplan.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_member.tfplan.json diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.json b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_policy.json similarity index 93% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.json rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_policy.json index de0fda73b41b..8780c890de23 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_policy.json @@ -12,9 +12,6 @@ "ackDeadlineSeconds": 20, "deadLetterPolicy": null, "expirationPolicy": null, - "labels": { - "test-label1": "test-value1" - }, "messageRetentionDuration": "604800s", "pushConfig": { "pushEndpoint": "https://example.com/push" @@ -33,4 +30,4 @@ ] } } -] +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.tf b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_policy.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_policy.tf diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_policy.tfplan.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_policy.tfplan.json diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_topic.json b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_topic.json similarity index 90% rename from mmv1/third_party/tgc/tests/data/example_pubsub_topic.json rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_topic.json index 03f0436f9d32..d51df4736115 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_topic.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_topic.json @@ -10,9 +10,6 @@ "parent": "//cloudresourcemanager.googleapis.com/projects/{{.Provider.project}}", "data": { "kmsKeyName": "projects/{{.Provider.project}}/locations/australia-southeast1/keyRings/default_kms_keyring_name/cryptoKeys/default_kms_key_name", - "labels": { - "test-key": "test-value" - }, "messageStoragePolicy": { "allowedPersistenceRegions": [ "australia-southeast1" diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_topic.tf b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_topic.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_pubsub_topic.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_topic.tf diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_topic.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_topic.tfplan.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_pubsub_topic.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_topic.tfplan.json diff --git a/mmv1/third_party/tgc/tests/data/example_sql_database_instance.json b/mmv1/third_party/tgc/tests/data-ignored/example_sql_database_instance.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_sql_database_instance.json rename to mmv1/third_party/tgc/tests/data-ignored/example_sql_database_instance.json diff --git a/mmv1/third_party/tgc/tests/data/example_sql_database_instance.tf b/mmv1/third_party/tgc/tests/data-ignored/example_sql_database_instance.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_sql_database_instance.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_sql_database_instance.tf diff --git a/mmv1/third_party/tgc/tests/data/example_sql_database_instance.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_sql_database_instance.tfplan.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_sql_database_instance.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_sql_database_instance.tfplan.json diff --git a/mmv1/third_party/tgc/tests/data-ignored/full_spanner_instance.json b/mmv1/third_party/tgc/tests/data-ignored/full_spanner_instance.json new file mode 100644 index 000000000000..44bdf373c50d --- /dev/null +++ b/mmv1/third_party/tgc/tests/data-ignored/full_spanner_instance.json @@ -0,0 +1,21 @@ +[ + { + "name": "//spanner.googleapis.com/projects/{{.Provider.project}}/instances/spanner-instance", + "asset_type": "spanner.googleapis.com/Instance", + "ancestry_path": "{{.Ancestry}}/project/{{.Provider.project}}", + "resource": { + "version": "v1", + "discovery_document_uri": "https://www.googleapis.com/discovery/v1/apis/spanner/v1/rest", + "discovery_name": "Instance", + "parent": "//cloudresourcemanager.googleapis.com/projects/{{.Provider.project}}", + "data": { + "instance": { + "config": "projects/{{.Provider.project}}/instanceConfigs/regional-us-central1", + "displayName": "spanner-instance", + "nodeCount": 1 + }, + "instanceId": "spanner-instance" + } + } + } +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/full_spanner_instance.tf b/mmv1/third_party/tgc/tests/data-ignored/full_spanner_instance.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/full_spanner_instance.tf rename to mmv1/third_party/tgc/tests/data-ignored/full_spanner_instance.tf diff --git a/mmv1/third_party/tgc/tests/data/full_spanner_instance.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/full_spanner_instance.tfplan.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/full_spanner_instance.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/full_spanner_instance.tfplan.json diff --git a/mmv1/third_party/tgc/tests/data/full_sql_database_instance.json b/mmv1/third_party/tgc/tests/data-ignored/full_sql_database_instance.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/full_sql_database_instance.json rename to mmv1/third_party/tgc/tests/data-ignored/full_sql_database_instance.json diff --git a/mmv1/third_party/tgc/tests/data/full_sql_database_instance.tf b/mmv1/third_party/tgc/tests/data-ignored/full_sql_database_instance.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/full_sql_database_instance.tf rename to mmv1/third_party/tgc/tests/data-ignored/full_sql_database_instance.tf diff --git a/mmv1/third_party/tgc/tests/data/full_sql_database_instance.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/full_sql_database_instance.tfplan.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/full_sql_database_instance.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/full_sql_database_instance.tfplan.json diff --git a/mmv1/third_party/tgc/tests/data/full_spanner_instance.json b/mmv1/third_party/tgc/tests/data/full_spanner_instance.json deleted file mode 100644 index af1e69cebd46..000000000000 --- a/mmv1/third_party/tgc/tests/data/full_spanner_instance.json +++ /dev/null @@ -1,26 +0,0 @@ -[ -{ - "name": "//spanner.googleapis.com/projects/{{.Provider.project}}/instances/spanner-instance", - "asset_type": "spanner.googleapis.com/Instance", - "ancestry_path": "{{.Ancestry}}/project/{{.Provider.project}}", - "resource": { - "version": "v1", - "discovery_document_uri": "https://www.googleapis.com/discovery/v1/apis/spanner/v1/rest", - "discovery_name": "Instance", - "parent": "//cloudresourcemanager.googleapis.com/projects/{{.Provider.project}}", - "data": { - "instance": { - "config": "projects/{{.Provider.project}}/instanceConfigs/regional-us-central1", - "displayName": "spanner-instance", - "labels": { - "label1": "value1", - "label2": "value2", - "label3": "value3" - }, - "nodeCount": 1 - }, - "instanceId": "spanner-instance" - } - } -} -]