From 9e772a85d6c113ae38b6e5439d7ae72380481bec Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Mon, 11 Dec 2023 10:48:50 +0000 Subject: [PATCH 01/27] Remove use of `google_kms_crypto_key_iam_binding` resources in acceptance tests to reduce test failures related to missing permissions (#9590) * Replace use of `google_kms_crypto_key_iam_binding` with `_member` equivalent * Replace use of `google_kms_crypto_key_iam_binding` with `_member` equivalent in examples files * Split `google_kms_crypto_key_iam_binding` with 2 members into two `_member` IAM resources in example file * Replace `google_kms_crypto_key_iam_binding` with 5 members into `_member` IAM resources created via for_each loop When this example is used to generate a test the crypto key used is a bootstrapped resource. By using an authoritative `_binding` IAM resource we allow conflict between tests using the same bootstrapped cypto key * Fix mistyped argument name * Remove use of for_each in acceptance test, create separate example files for test vs docs * SKip `TestAccCloudfunctions2function_cloudfunctions2CmekExample` in VCR * Skip `TestAccDataprocMetastoreService_dataprocMetastoreServiceCmekTestExample` in VCR --- mmv1/products/cloudfunctions2/Function.yaml | 16 +++ mmv1/products/metastore/Service.yaml | 1 + .../apigee_environment_type_test.tf.erb | 8 +- .../examples/apigee_instance_full.tf.erb | 8 +- .../examples/apigee_instance_full_test.tf.erb | 8 +- .../examples/apigee_nat_address_basic.tf.erb | 8 +- .../apigee_organization_cloud_full.tf.erb | 8 +- ...tion_cloud_full_disable_vpc_peering.tf.erb | 8 +- ...cloud_full_disable_vpc_peering_test.tf.erb | 8 +- ...apigee_organization_cloud_full_test.tf.erb | 8 +- .../apigee_organization_retention_test.tf.erb | 8 +- .../examples/cloudfunctions2_cmek.tf.erb | 68 ++++++++--- .../examples/cloudfunctions2_cmek_docs.tf.erb | 113 ++++++++++++++++++ .../examples/data_fusion_instance_cmek.tf.erb | 8 +- ...ataproc_metastore_service_cmek_test.tf.erb | 19 ++- ...ateca_certificate_authority_byo_key.tf.erb | 16 +-- .../examples/sql_instance_cmek.tf.erb | 6 +- .../alloydb/resource_alloydb_backup_test.go | 6 +- .../alloydb/resource_alloydb_cluster_test.go | 74 +++++------- ...resource_alloydb_secondary_cluster_test.go | 8 +- ...urce_compute_instance_template_test.go.erb | 4 + .../resource_logging_bucket_config_test.go | 16 +-- .../resource_sql_database_instance_test.go | 18 +-- 23 files changed, 281 insertions(+), 164 deletions(-) create mode 100644 mmv1/templates/terraform/examples/cloudfunctions2_cmek_docs.tf.erb diff --git a/mmv1/products/cloudfunctions2/Function.yaml b/mmv1/products/cloudfunctions2/Function.yaml index 0618283b0381..b0c34b5429dd 100644 --- a/mmv1/products/cloudfunctions2/Function.yaml +++ b/mmv1/products/cloudfunctions2/Function.yaml @@ -218,6 +218,8 @@ examples: - 'build_config.0.source.0.storage_source.0.bucket' - !ruby/object:Provider::Terraform::Examples name: 'cloudfunctions2_cmek' + skip_docs: true # the example file is written in a repetitive way to help acc tests, so exclude + skip_vcr: true primary_resource_id: 'function' min_version: beta vars: @@ -239,6 +241,20 @@ examples: ignore_read_extra: - 'build_config.0.source.0.storage_source.0.object' - 'build_config.0.source.0.storage_source.0.bucket' + - !ruby/object:Provider::Terraform::Examples + name: 'cloudfunctions2_cmek_docs' + skip_test: true # this example file will cause IAM conflicts between tests if used to make a test + primary_resource_id: 'function' + min_version: beta + vars: + function: 'function-cmek' + bucket_name: 'gcf-source' + zip_path: 'function-source.zip' + kms_service_name: 'cloudkms.googleapis.com' + cmek-repo: 'cmek-repo' + unencoded-ar-repo: 'ar-repo' + kms_key_name: 'cmek-key' + project: 'my-project-name' iam_policy: !ruby/object:Api::Resource::IamPolicy parent_resource_attribute: 'cloud_function' method_name_separator: ':' diff --git a/mmv1/products/metastore/Service.yaml b/mmv1/products/metastore/Service.yaml index e1ae22ed13e2..7d72c683b7f5 100644 --- a/mmv1/products/metastore/Service.yaml +++ b/mmv1/products/metastore/Service.yaml @@ -66,6 +66,7 @@ examples: - !ruby/object:Provider::Terraform::Examples name: 'dataproc_metastore_service_cmek_test' skip_docs: true + skip_vcr: true primary_resource_id: 'default' vars: metastore_service_name: 'example-service' diff --git a/mmv1/templates/terraform/examples/apigee_environment_type_test.tf.erb b/mmv1/templates/terraform/examples/apigee_environment_type_test.tf.erb index 1286cc5ec1dd..d0baa2ab5fe2 100644 --- a/mmv1/templates/terraform/examples/apigee_environment_type_test.tf.erb +++ b/mmv1/templates/terraform/examples/apigee_environment_type_test.tf.erb @@ -86,15 +86,13 @@ resource "google_project_service_identity" "apigee_sa" { service = google_project_service.apigee.service } -resource "google_kms_crypto_key_iam_binding" "apigee_sa_keyuser" { +resource "google_kms_crypto_key_iam_member" "apigee_sa_keyuser" { provider = google-beta crypto_key_id = google_kms_crypto_key.apigee_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${google_project_service_identity.apigee_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.apigee_sa.email}" } resource "google_apigee_organization" "apigee_org" { @@ -109,7 +107,7 @@ resource "google_apigee_organization" "apigee_org" { depends_on = [ google_service_networking_connection.apigee_vpc_connection, google_project_service.apigee, - google_kms_crypto_key_iam_binding.apigee_sa_keyuser, + google_kms_crypto_key_iam_member.apigee_sa_keyuser, ] } diff --git a/mmv1/templates/terraform/examples/apigee_instance_full.tf.erb b/mmv1/templates/terraform/examples/apigee_instance_full.tf.erb index 2cd5f3282265..26445ef11b85 100644 --- a/mmv1/templates/terraform/examples/apigee_instance_full.tf.erb +++ b/mmv1/templates/terraform/examples/apigee_instance_full.tf.erb @@ -38,13 +38,11 @@ resource "google_project_service_identity" "apigee_sa" { service = google_project_service.apigee.service } -resource "google_kms_crypto_key_iam_binding" "apigee_sa_keyuser" { +resource "google_kms_crypto_key_iam_member" "apigee_sa_keyuser" { crypto_key_id = google_kms_crypto_key.apigee_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${google_project_service_identity.apigee_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.apigee_sa.email}" } resource "google_apigee_organization" "apigee_org" { @@ -57,7 +55,7 @@ resource "google_apigee_organization" "apigee_org" { depends_on = [ google_service_networking_connection.apigee_vpc_connection, - google_kms_crypto_key_iam_binding.apigee_sa_keyuser, + google_kms_crypto_key_iam_member.apigee_sa_keyuser, ] } diff --git a/mmv1/templates/terraform/examples/apigee_instance_full_test.tf.erb b/mmv1/templates/terraform/examples/apigee_instance_full_test.tf.erb index 08a5e3ab1558..8690e4320f25 100644 --- a/mmv1/templates/terraform/examples/apigee_instance_full_test.tf.erb +++ b/mmv1/templates/terraform/examples/apigee_instance_full_test.tf.erb @@ -86,15 +86,13 @@ resource "google_project_service_identity" "apigee_sa" { service = google_project_service.apigee.service } -resource "google_kms_crypto_key_iam_binding" "apigee_sa_keyuser" { +resource "google_kms_crypto_key_iam_member" "apigee_sa_keyuser" { provider = google-beta crypto_key_id = google_kms_crypto_key.apigee_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${google_project_service_identity.apigee_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.apigee_sa.email}" } resource "google_apigee_organization" "apigee_org" { @@ -109,7 +107,7 @@ resource "google_apigee_organization" "apigee_org" { depends_on = [ google_service_networking_connection.apigee_vpc_connection, - google_kms_crypto_key_iam_binding.apigee_sa_keyuser, + google_kms_crypto_key_iam_member.apigee_sa_keyuser, ] } diff --git a/mmv1/templates/terraform/examples/apigee_nat_address_basic.tf.erb b/mmv1/templates/terraform/examples/apigee_nat_address_basic.tf.erb index 3114e517815b..cbcbc32c10dc 100644 --- a/mmv1/templates/terraform/examples/apigee_nat_address_basic.tf.erb +++ b/mmv1/templates/terraform/examples/apigee_nat_address_basic.tf.erb @@ -38,13 +38,11 @@ resource "google_project_service_identity" "apigee_sa" { service = google_project_service.apigee.service } -resource "google_kms_crypto_key_iam_binding" "apigee_sa_keyuser" { +resource "google_kms_crypto_key_iam_member" "apigee_sa_keyuser" { crypto_key_id = google_kms_crypto_key.apigee_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${google_project_service_identity.apigee_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.apigee_sa.email}" } resource "google_apigee_organization" "apigee_org" { @@ -57,7 +55,7 @@ resource "google_apigee_organization" "apigee_org" { depends_on = [ google_service_networking_connection.apigee_vpc_connection, - google_kms_crypto_key_iam_binding.apigee_sa_keyuser, + google_kms_crypto_key_iam_member.apigee_sa_keyuser, ] } diff --git a/mmv1/templates/terraform/examples/apigee_organization_cloud_full.tf.erb b/mmv1/templates/terraform/examples/apigee_organization_cloud_full.tf.erb index 891fb47422a9..6d37ffa69dbc 100644 --- a/mmv1/templates/terraform/examples/apigee_organization_cloud_full.tf.erb +++ b/mmv1/templates/terraform/examples/apigee_organization_cloud_full.tf.erb @@ -38,13 +38,11 @@ resource "google_project_service_identity" "apigee_sa" { service = google_project_service.apigee.service } -resource "google_kms_crypto_key_iam_binding" "apigee_sa_keyuser" { +resource "google_kms_crypto_key_iam_member" "apigee_sa_keyuser" { crypto_key_id = google_kms_crypto_key.apigee_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${google_project_service_identity.apigee_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.apigee_sa.email}" } resource "google_apigee_organization" "org" { @@ -57,6 +55,6 @@ resource "google_apigee_organization" "org" { depends_on = [ google_service_networking_connection.apigee_vpc_connection, - google_kms_crypto_key_iam_binding.apigee_sa_keyuser, + google_kms_crypto_key_iam_member.apigee_sa_keyuser, ] } diff --git a/mmv1/templates/terraform/examples/apigee_organization_cloud_full_disable_vpc_peering.tf.erb b/mmv1/templates/terraform/examples/apigee_organization_cloud_full_disable_vpc_peering.tf.erb index d393b02985f3..42f797ce28c4 100644 --- a/mmv1/templates/terraform/examples/apigee_organization_cloud_full_disable_vpc_peering.tf.erb +++ b/mmv1/templates/terraform/examples/apigee_organization_cloud_full_disable_vpc_peering.tf.erb @@ -20,13 +20,11 @@ resource "google_project_service_identity" "apigee_sa" { service = google_project_service.apigee.service } -resource "google_kms_crypto_key_iam_binding" "apigee_sa_keyuser" { +resource "google_kms_crypto_key_iam_member" "apigee_sa_keyuser" { crypto_key_id = google_kms_crypto_key.apigee_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${google_project_service_identity.apigee_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.apigee_sa.email}" } resource "google_apigee_organization" "org" { @@ -38,6 +36,6 @@ resource "google_apigee_organization" "org" { runtime_database_encryption_key_name = google_kms_crypto_key.apigee_key.id depends_on = [ - google_kms_crypto_key_iam_binding.apigee_sa_keyuser, + google_kms_crypto_key_iam_member.apigee_sa_keyuser, ] } diff --git a/mmv1/templates/terraform/examples/apigee_organization_cloud_full_disable_vpc_peering_test.tf.erb b/mmv1/templates/terraform/examples/apigee_organization_cloud_full_disable_vpc_peering_test.tf.erb index e1857349148b..f39d3fd4e9ef 100644 --- a/mmv1/templates/terraform/examples/apigee_organization_cloud_full_disable_vpc_peering_test.tf.erb +++ b/mmv1/templates/terraform/examples/apigee_organization_cloud_full_disable_vpc_peering_test.tf.erb @@ -51,15 +51,13 @@ resource "google_project_service_identity" "apigee_sa" { service = google_project_service.apigee.service } -resource "google_kms_crypto_key_iam_binding" "apigee_sa_keyuser" { +resource "google_kms_crypto_key_iam_member" "apigee_sa_keyuser" { provider = google-beta crypto_key_id = google_kms_crypto_key.apigee_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${google_project_service_identity.apigee_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.apigee_sa.email}" } resource "google_apigee_organization" "<%= ctx[:primary_resource_id] %>" { @@ -84,6 +82,6 @@ resource "google_apigee_organization" "<%= ctx[:primary_resource_id] %>" { } depends_on = [ - google_kms_crypto_key_iam_binding.apigee_sa_keyuser, + google_kms_crypto_key_iam_member.apigee_sa_keyuser, ] } diff --git a/mmv1/templates/terraform/examples/apigee_organization_cloud_full_test.tf.erb b/mmv1/templates/terraform/examples/apigee_organization_cloud_full_test.tf.erb index a58a60fe4e2a..5a859ec6b7e6 100644 --- a/mmv1/templates/terraform/examples/apigee_organization_cloud_full_test.tf.erb +++ b/mmv1/templates/terraform/examples/apigee_organization_cloud_full_test.tf.erb @@ -86,15 +86,13 @@ resource "google_project_service_identity" "apigee_sa" { service = google_project_service.apigee.service } -resource "google_kms_crypto_key_iam_binding" "apigee_sa_keyuser" { +resource "google_kms_crypto_key_iam_member" "apigee_sa_keyuser" { provider = google-beta crypto_key_id = google_kms_crypto_key.apigee_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${google_project_service_identity.apigee_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.apigee_sa.email}" } resource "google_apigee_organization" "<%= ctx[:primary_resource_id] %>" { @@ -120,6 +118,6 @@ resource "google_apigee_organization" "<%= ctx[:primary_resource_id] %>" { depends_on = [ google_service_networking_connection.apigee_vpc_connection, - google_kms_crypto_key_iam_binding.apigee_sa_keyuser, + google_kms_crypto_key_iam_member.apigee_sa_keyuser, ] } diff --git a/mmv1/templates/terraform/examples/apigee_organization_retention_test.tf.erb b/mmv1/templates/terraform/examples/apigee_organization_retention_test.tf.erb index 365ba939e5a0..0de08ec9eb4b 100644 --- a/mmv1/templates/terraform/examples/apigee_organization_retention_test.tf.erb +++ b/mmv1/templates/terraform/examples/apigee_organization_retention_test.tf.erb @@ -86,15 +86,13 @@ resource "google_project_service_identity" "apigee_sa" { service = google_project_service.apigee.service } -resource "google_kms_crypto_key_iam_binding" "apigee_sa_keyuser" { +resource "google_kms_crypto_key_iam_member" "apigee_sa_keyuser" { provider = google-beta crypto_key_id = google_kms_crypto_key.apigee_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${google_project_service_identity.apigee_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.apigee_sa.email}" } resource "google_apigee_organization" "<%= ctx[:primary_resource_id] %>" { @@ -110,7 +108,7 @@ resource "google_apigee_organization" "<%= ctx[:primary_resource_id] %>" { depends_on = [ google_service_networking_connection.apigee_vpc_connection, google_project_service.apigee, - google_kms_crypto_key_iam_binding.apigee_sa_keyuser, + google_kms_crypto_key_iam_member.apigee_sa_keyuser, ] } diff --git a/mmv1/templates/terraform/examples/cloudfunctions2_cmek.tf.erb b/mmv1/templates/terraform/examples/cloudfunctions2_cmek.tf.erb index 9ad4af6978f4..0db9b17ad3de 100644 --- a/mmv1/templates/terraform/examples/cloudfunctions2_cmek.tf.erb +++ b/mmv1/templates/terraform/examples/cloudfunctions2_cmek.tf.erb @@ -37,34 +37,58 @@ resource "google_artifact_registry_repository" "unencoded-ar-repo" { format = "DOCKER" } -resource "google_artifact_registry_repository_iam_binding" "binding" { +resource "google_artifact_registry_repository_iam_member" "member" { provider = google-beta location = google_artifact_registry_repository.encoded-ar-repo.location repository = google_artifact_registry_repository.encoded-ar-repo.name role = "roles/artifactregistry.admin" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcf-admin-robot.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcf-admin-robot.iam.gserviceaccount.com" } -resource "google_kms_crypto_key_iam_binding" "gcf_cmek_keyuser" { +resource "google_kms_crypto_key_iam_member" "gcf_cmek_keyuser_1" { provider = google-beta crypto_key_id = "<%= ctx[:vars]['kms_key_name'] %>" role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcf-admin-robot.iam.gserviceaccount.com", - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-artifactregistry.iam.gserviceaccount.com", - "serviceAccount:service-${data.google_project.project.number}@gs-project-accounts.iam.gserviceaccount.com", - "serviceAccount:service-${data.google_project.project.number}@serverless-robot-prod.iam.gserviceaccount.com", - "serviceAccount:${google_project_service_identity.ea_sa.email}", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcf-admin-robot.iam.gserviceaccount.com" +} - depends_on = [ - google_project_service_identity.ea_sa - ] +resource "google_kms_crypto_key_iam_member" "gcf_cmek_keyuser_2" { + provider = google-beta + + crypto_key_id = "<%= ctx[:vars]['kms_key_name'] %>" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-artifactregistry.iam.gserviceaccount.com" +} + +resource "google_kms_crypto_key_iam_member" "gcf_cmek_keyuser_3" { + provider = google-beta + + crypto_key_id = "<%= ctx[:vars]['kms_key_name'] %>" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + member = "serviceAccount:service-${data.google_project.project.number}@gs-project-accounts.iam.gserviceaccount.com" +} + +resource "google_kms_crypto_key_iam_member" "gcf_cmek_keyuser_4" { + provider = google-beta + + crypto_key_id = "<%= ctx[:vars]['kms_key_name'] %>" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + member = "serviceAccount:service-${data.google_project.project.number}@serverless-robot-prod.iam.gserviceaccount.com" +} + +resource "google_kms_crypto_key_iam_member" "gcf_cmek_keyuser_5" { + provider = google-beta + + crypto_key_id = "<%= ctx[:vars]['kms_key_name'] %>" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + member = "serviceAccount:${google_project_service_identity.ea_sa.email}" } resource "google_artifact_registry_repository" "encoded-ar-repo" { @@ -74,8 +98,13 @@ resource "google_artifact_registry_repository" "encoded-ar-repo" { repository_id = "<%= ctx[:vars]['cmek-repo'] %>" format = "DOCKER" kms_key_name = "<%= ctx[:vars]['kms_key_name'] %>" + depends_on = [ - google_kms_crypto_key_iam_binding.gcf_cmek_keyuser + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_1, + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_2, + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_3, + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_4, + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_5, ] } @@ -107,7 +136,10 @@ resource "google_cloudfunctions2_function" "<%= ctx[:primary_resource_id] %>" { } depends_on = [ - google_kms_crypto_key_iam_binding.gcf_cmek_keyuser + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_1, + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_2, + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_3, + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_4, + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_5, ] - } diff --git a/mmv1/templates/terraform/examples/cloudfunctions2_cmek_docs.tf.erb b/mmv1/templates/terraform/examples/cloudfunctions2_cmek_docs.tf.erb new file mode 100644 index 000000000000..8d719665a418 --- /dev/null +++ b/mmv1/templates/terraform/examples/cloudfunctions2_cmek_docs.tf.erb @@ -0,0 +1,113 @@ +locals { + project = "<%= ctx[:vars]['project'] %>" # Google Cloud Platform Project ID +} + +data "google_project" "project" { + provider = google-beta +} + +resource "google_storage_bucket" "bucket" { + provider = google-beta + + name = "${local.project}-<%= ctx[:vars]['bucket_name'] %>" # Every bucket name must be globally unique + location = "US" + uniform_bucket_level_access = true +} + +resource "google_storage_bucket_object" "object" { + provider = google-beta + + name = "function-source.zip" + bucket = google_storage_bucket.bucket.name + source = "<%= ctx[:vars]['zip_path'] %>" # Add path to the zipped function source code +} + +resource "google_project_service_identity" "ea_sa" { + provider = google-beta + + project = data.google_project.project.project_id + service = "eventarc.googleapis.com" +} + +resource "google_artifact_registry_repository" "unencoded-ar-repo" { + provider = google-beta + + repository_id = "<%= ctx[:vars]['unencoded-ar-repo'] %>" + location = "us-central1" + format = "DOCKER" +} + +resource "google_artifact_registry_repository_iam_binding" "binding" { + provider = google-beta + + location = google_artifact_registry_repository.encoded-ar-repo.location + repository = google_artifact_registry_repository.encoded-ar-repo.name + role = "roles/artifactregistry.admin" + members = [ + "serviceAccount:service-${data.google_project.project.number}@gcf-admin-robot.iam.gserviceaccount.com", + ] +} + +resource "google_kms_crypto_key_iam_binding" "gcf_cmek_keyuser" { + provider = google-beta + + crypto_key_id = "<%= ctx[:vars]['kms_key_name'] %>" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + members = [ + "serviceAccount:service-${data.google_project.project.number}@gcf-admin-robot.iam.gserviceaccount.com", + "serviceAccount:service-${data.google_project.project.number}@gcp-sa-artifactregistry.iam.gserviceaccount.com", + "serviceAccount:service-${data.google_project.project.number}@gs-project-accounts.iam.gserviceaccount.com", + "serviceAccount:service-${data.google_project.project.number}@serverless-robot-prod.iam.gserviceaccount.com", + "serviceAccount:${google_project_service_identity.ea_sa.email}", + ] + + depends_on = [ + google_project_service_identity.ea_sa + ] +} + +resource "google_artifact_registry_repository" "encoded-ar-repo" { + provider = google-beta + + location = "us-central1" + repository_id = "<%= ctx[:vars]['cmek-repo'] %>" + format = "DOCKER" + kms_key_name = "<%= ctx[:vars]['kms_key_name'] %>" + depends_on = [ + google_kms_crypto_key_iam_binding.gcf_cmek_keyuser + ] +} + +resource "google_cloudfunctions2_function" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + + name = "<%= ctx[:vars]['function'] %>" + location = "us-central1" + description = "CMEK function" + kms_key_name = "<%= ctx[:vars]['kms_key_name'] %>" + + build_config { + runtime = "nodejs16" + entry_point = "helloHttp" # Set the entry point + docker_repository = google_artifact_registry_repository.encoded-ar-repo.id + + source { + storage_source { + bucket = google_storage_bucket.bucket.name + object = google_storage_bucket_object.object.name + } + } + } + + service_config { + max_instance_count = 1 + available_memory = "256M" + timeout_seconds = 60 + } + + depends_on = [ + google_kms_crypto_key_iam_binding.gcf_cmek_keyuser + ] + +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/data_fusion_instance_cmek.tf.erb b/mmv1/templates/terraform/examples/data_fusion_instance_cmek.tf.erb index a72007725613..1bb61692283a 100644 --- a/mmv1/templates/terraform/examples/data_fusion_instance_cmek.tf.erb +++ b/mmv1/templates/terraform/examples/data_fusion_instance_cmek.tf.erb @@ -7,7 +7,7 @@ resource "google_data_fusion_instance" "<%= ctx[:primary_resource_id] %>" { key_reference = google_kms_crypto_key.crypto_key.id } - depends_on = [google_kms_crypto_key_iam_binding.crypto_key_binding] + depends_on = [google_kms_crypto_key_iam_member.crypto_key_member] } resource "google_kms_crypto_key" "crypto_key" { @@ -20,13 +20,11 @@ resource "google_kms_key_ring" "key_ring" { location = "us-central1" } -resource "google_kms_crypto_key_iam_binding" "crypto_key_binding" { +resource "google_kms_crypto_key_iam_member" "crypto_key_member" { crypto_key_id = google_kms_crypto_key.crypto_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-datafusion.iam.gserviceaccount.com" - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-datafusion.iam.gserviceaccount.com" } data "google_project" "project" {} diff --git a/mmv1/templates/terraform/examples/dataproc_metastore_service_cmek_test.tf.erb b/mmv1/templates/terraform/examples/dataproc_metastore_service_cmek_test.tf.erb index f821af8a37c6..731960437dd5 100644 --- a/mmv1/templates/terraform/examples/dataproc_metastore_service_cmek_test.tf.erb +++ b/mmv1/templates/terraform/examples/dataproc_metastore_service_cmek_test.tf.erb @@ -15,7 +15,10 @@ resource "google_dataproc_metastore_service" "<%= ctx[:primary_resource_id] %>" version = "3.1.2" } - depends_on = [google_kms_crypto_key_iam_binding.crypto_key_binding] + depends_on = [ + google_kms_crypto_key_iam_member.crypto_key_member_1, + google_kms_crypto_key_iam_member.crypto_key_member_2, + ] } resource "google_kms_crypto_key" "crypto_key" { @@ -30,12 +33,16 @@ resource "google_kms_key_ring" "key_ring" { location = "us-central1" } -resource "google_kms_crypto_key_iam_binding" "crypto_key_binding" { +resource "google_kms_crypto_key_iam_member" "crypto_key_member_1" { crypto_key_id = google_kms_crypto_key.crypto_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-metastore.iam.gserviceaccount.com", - "serviceAccount:${data.google_storage_project_service_account.gcs_account.email_address}" - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-metastore.iam.gserviceaccount.com" } + +resource "google_kms_crypto_key_iam_member" "crypto_key_member_2" { + crypto_key_id = google_kms_crypto_key.crypto_key.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + member = "serviceAccount:${data.google_storage_project_service_account.gcs_account.email_address}" +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/privateca_certificate_authority_byo_key.tf.erb b/mmv1/templates/terraform/examples/privateca_certificate_authority_byo_key.tf.erb index 1db78f99f431..392e848712f3 100644 --- a/mmv1/templates/terraform/examples/privateca_certificate_authority_byo_key.tf.erb +++ b/mmv1/templates/terraform/examples/privateca_certificate_authority_byo_key.tf.erb @@ -3,21 +3,17 @@ resource "google_project_service_identity" "privateca_sa" { service = "privateca.googleapis.com" } -resource "google_kms_crypto_key_iam_binding" "privateca_sa_keyuser_signerverifier" { +resource "google_kms_crypto_key_iam_member" "privateca_sa_keyuser_signerverifier" { crypto_key_id = "<%= ctx[:vars]['kms_key_name'] %>" role = "roles/cloudkms.signerVerifier" - members = [ - "serviceAccount:${google_project_service_identity.privateca_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.privateca_sa.email}" } -resource "google_kms_crypto_key_iam_binding" "privateca_sa_keyuser_viewer" { +resource "google_kms_crypto_key_iam_member" "privateca_sa_keyuser_viewer" { crypto_key_id = "<%= ctx[:vars]['kms_key_name'] %>" role = "roles/viewer" - members = [ - "serviceAccount:${google_project_service_identity.privateca_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.privateca_sa.email}" } resource "google_privateca_certificate_authority" "<%= ctx[:primary_resource_id] %>" { @@ -69,8 +65,8 @@ resource "google_privateca_certificate_authority" "<%= ctx[:primary_resource_id] } depends_on = [ - google_kms_crypto_key_iam_binding.privateca_sa_keyuser_signerverifier, - google_kms_crypto_key_iam_binding.privateca_sa_keyuser_viewer, + google_kms_crypto_key_iam_member.privateca_sa_keyuser_signerverifier, + google_kms_crypto_key_iam_member.privateca_sa_keyuser_viewer, ] } # [END privateca_create_ca_byo_key] \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/sql_instance_cmek.tf.erb b/mmv1/templates/terraform/examples/sql_instance_cmek.tf.erb index 3b352c0e574a..e0134a2caa28 100644 --- a/mmv1/templates/terraform/examples/sql_instance_cmek.tf.erb +++ b/mmv1/templates/terraform/examples/sql_instance_cmek.tf.erb @@ -23,14 +23,12 @@ resource "google_kms_crypto_key" "key" { # [END cloud_sql_instance_key] # [START cloud_sql_instance_crypto_key] -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { provider = google-beta crypto_key_id = google_kms_crypto_key.key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${google_project_service_identity.gcp_sa_cloud_sql.email}", - ] + member = "serviceAccount:${google_project_service_identity.gcp_sa_cloud_sql.email}" } # [END cloud_sql_instance_crypto_key] 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 6f5c9c6c8616..259b207c672c 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 @@ -230,12 +230,10 @@ resource "google_kms_crypto_key" "key" { key_ring = google_kms_key_ring.keyring.id } -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { crypto_key_id = google_kms_crypto_key.key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com" } `, context) } 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 21ba1948a2ff..bf1255bc788e 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 @@ -491,7 +491,7 @@ resource "google_alloydb_cluster" "default" { encryption_config { kms_key_name = google_kms_crypto_key.key.id } - depends_on = [google_kms_crypto_key_iam_binding.crypto_key] + depends_on = [google_kms_crypto_key_iam_member.crypto_key] } resource "google_compute_network" "default" { name = "tf-test-alloydb-cluster%{random_suffix}" @@ -505,12 +505,10 @@ resource "google_kms_crypto_key" "key" { name = "%{key_name}" key_ring = google_kms_key_ring.keyring.id } -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { crypto_key_id = google_kms_crypto_key.key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com" } `, context) } @@ -582,7 +580,7 @@ resource "google_alloydb_cluster" "default" { lifecycle { prevent_destroy = true } - depends_on = [google_kms_crypto_key_iam_binding.crypto_key] + depends_on = [google_kms_crypto_key_iam_member.crypto_key] } resource "google_compute_network" "default" { @@ -601,12 +599,10 @@ resource "google_kms_crypto_key" "key" { key_ring = google_kms_key_ring.keyring.id } -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { crypto_key_id = google_kms_crypto_key.key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com" } `, context) } @@ -632,9 +628,9 @@ resource "google_alloydb_cluster" "default" { } } lifecycle { - prevent_destroy = true + prevent_destroy = true } - depends_on = [google_kms_crypto_key_iam_binding.crypto_key] + depends_on = [google_kms_crypto_key_iam_member.crypto_key] } resource "google_compute_network" "default" { @@ -654,24 +650,20 @@ resource "google_kms_crypto_key" "key" { } resource "google_kms_crypto_key" "key2" { - name = "%{key_name}-2" - key_ring = google_kms_key_ring.keyring.id + name = "%{key_name}-2" + key_ring = google_kms_key_ring.keyring.id } -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { crypto_key_id = google_kms_crypto_key.key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com" } -resource "google_kms_crypto_key_iam_binding" "crypto_key2" { - crypto_key_id = google_kms_crypto_key.key2.id - role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", - ] +resource "google_kms_crypto_key_iam_member" "crypto_key2" { + crypto_key_id = google_kms_crypto_key.key2.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com" } `, context) } @@ -696,7 +688,7 @@ resource "google_alloydb_cluster" "default" { retention_period = "510s" } } - depends_on = [google_kms_crypto_key_iam_binding.crypto_key] + depends_on = [google_kms_crypto_key_iam_member.crypto_key] } resource "google_compute_network" "default" { @@ -720,20 +712,16 @@ resource "google_kms_crypto_key" "key2" { key_ring = google_kms_key_ring.keyring.id } -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { crypto_key_id = google_kms_crypto_key.key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com" } -resource "google_kms_crypto_key_iam_binding" "crypto_key2" { - crypto_key_id = google_kms_crypto_key.key2.id - role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", - ] +resource "google_kms_crypto_key_iam_member" "crypto_key2" { + crypto_key_id = google_kms_crypto_key.key2.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com" } `, context) } @@ -1042,7 +1030,7 @@ resource "google_alloydb_cluster" "default" { lifecycle { prevent_destroy = true } - depends_on = [google_kms_crypto_key_iam_binding.crypto_key] + depends_on = [google_kms_crypto_key_iam_member.crypto_key] } resource "google_compute_network" "default" { @@ -1051,12 +1039,10 @@ resource "google_compute_network" "default" { data "google_project" "project" {} -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { crypto_key_id = "%{key_name}" role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com" } `, context) } @@ -1074,7 +1060,7 @@ resource "google_alloydb_cluster" "default" { kms_key_name = "%{key_name}" } } - depends_on = [google_kms_crypto_key_iam_binding.crypto_key] + depends_on = [google_kms_crypto_key_iam_member.crypto_key] } resource "google_compute_network" "default" { @@ -1083,12 +1069,10 @@ resource "google_compute_network" "default" { data "google_project" "project" {} -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { crypto_key_id = "%{key_name}" role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com" } `, context) } diff --git a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_secondary_cluster_test.go b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_secondary_cluster_test.go index 55e01d0a2c54..3c98505bbd53 100644 --- a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_secondary_cluster_test.go +++ b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_secondary_cluster_test.go @@ -519,7 +519,7 @@ resource "google_alloydb_cluster" "secondary" { kms_key_name = google_kms_crypto_key.key.id } - depends_on = [google_alloydb_instance.primary, google_kms_crypto_key_iam_binding.crypto_key] + depends_on = [google_alloydb_instance.primary, google_kms_crypto_key_iam_member.crypto_key] } data "google_project" "project" {} @@ -538,12 +538,10 @@ resource "google_kms_crypto_key" "key" { key_ring = google_kms_key_ring.keyring.id } -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { crypto_key_id = google_kms_crypto_key.key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com" } `, context) } 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 7518d6b70131..01b6f1c19767 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 @@ -3650,6 +3650,10 @@ resource "google_compute_image" "image" { kms_key_self_link = data.google_kms_crypto_key.key.id kms_key_service_account = google_service_account.test.email } + + depends_on = [ + google_kms_crypto_key_iam_member.crypto_key + ] } diff --git a/mmv1/third_party/terraform/services/logging/resource_logging_bucket_config_test.go b/mmv1/third_party/terraform/services/logging/resource_logging_bucket_config_test.go index b4556484a999..ab5b0313d09e 100644 --- a/mmv1/third_party/terraform/services/logging/resource_logging_bucket_config_test.go +++ b/mmv1/third_party/terraform/services/logging/resource_logging_bucket_config_test.go @@ -343,22 +343,18 @@ resource "google_kms_crypto_key" "key2" { key_ring = google_kms_key_ring.keyring.id } -resource "google_kms_crypto_key_iam_binding" "crypto_key_binding1" { +resource "google_kms_crypto_key_iam_member" "crypto_key_member1" { crypto_key_id = google_kms_crypto_key.key1.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${data.google_logging_project_cmek_settings.cmek_settings.service_account_id}", - ] + member = "serviceAccount:${data.google_logging_project_cmek_settings.cmek_settings.service_account_id}" } -resource "google_kms_crypto_key_iam_binding" "crypto_key_binding2" { +resource "google_kms_crypto_key_iam_member" "crypto_key_member2" { crypto_key_id = google_kms_crypto_key.key2.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${data.google_logging_project_cmek_settings.cmek_settings.service_account_id}", - ] + member = "serviceAccount:${data.google_logging_project_cmek_settings.cmek_settings.service_account_id}" } `, context), keyRingName, cryptoKeyName, cryptoKeyNameUpdate) } @@ -378,7 +374,7 @@ resource "google_logging_project_bucket_config" "basic" { kms_key_name = google_kms_crypto_key.key1.id } - depends_on = [google_kms_crypto_key_iam_binding.crypto_key_binding1] + depends_on = [google_kms_crypto_key_iam_member.crypto_key_member1] } `, testAccLoggingBucketConfigProject_preCmekSettings(context, keyRingName, cryptoKeyName, cryptoKeyNameUpdate), bucketId) } @@ -398,7 +394,7 @@ resource "google_logging_project_bucket_config" "basic" { kms_key_name = google_kms_crypto_key.key2.id } - depends_on = [google_kms_crypto_key_iam_binding.crypto_key_binding2] + depends_on = [google_kms_crypto_key_iam_member.crypto_key_member2] } `, testAccLoggingBucketConfigProject_preCmekSettings(context, keyRingName, cryptoKeyName, cryptoKeyNameUpdate), bucketId) } 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 af63bbd48ee1..74ca85b1fee6 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 @@ -3714,13 +3714,11 @@ resource "google_kms_crypto_key" "key" { key_ring = google_kms_key_ring.keyring.id } -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { crypto_key_id = google_kms_crypto_key.key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-cloud-sql.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-cloud-sql.iam.gserviceaccount.com" } resource "google_sql_database_instance" "master" { @@ -3773,13 +3771,11 @@ resource "google_kms_crypto_key" "key" { key_ring = google_kms_key_ring.keyring.id } -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { crypto_key_id = google_kms_crypto_key.key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-cloud-sql.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-cloud-sql.iam.gserviceaccount.com" } resource "google_sql_database_instance" "master" { @@ -3812,13 +3808,11 @@ resource "google_kms_crypto_key" "key-rep" { key_ring = google_kms_key_ring.keyring-rep.id } -resource "google_kms_crypto_key_iam_binding" "crypto_key_rep" { +resource "google_kms_crypto_key_iam_member" "crypto_key_rep" { crypto_key_id = google_kms_crypto_key.key-rep.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-cloud-sql.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-cloud-sql.iam.gserviceaccount.com" } resource "google_sql_database_instance" "replica" { From cba7bf3076d97ae01b9857e82653149eadc9e4d5 Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Mon, 11 Dec 2023 09:36:45 -0800 Subject: [PATCH 02/27] Add additional check to dangling cluster test (#9335) * Add additional check to dangling cluster test Also remove unused code which was needed for failed creation test * Avoid empty timeout field * Skip in VCR --- .../terraform/acctest/bootstrap_test_utils.go | 59 -------------- .../resource_container_cluster_test.go.erb | 76 +++++++++++++++++-- 2 files changed, 68 insertions(+), 67 deletions(-) diff --git a/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go b/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go index d0bb61468ad6..bb8e89626a59 100644 --- a/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go +++ b/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go @@ -611,65 +611,6 @@ func BootstrapServicePerimeterProjects(t *testing.T, desiredProjects int) []*clo return projects } -func RemoveContainerServiceAgentRoleFromContainerEngineRobot(t *testing.T, project *cloudresourcemanager.Project) { - config := BootstrapConfig(t) - if config == nil { - return - } - - client := config.NewResourceManagerClient(config.UserAgent) - containerEngineRobot := fmt.Sprintf("serviceAccount:service-%d@container-engine-robot.iam.gserviceaccount.com", project.ProjectNumber) - getPolicyRequest := &cloudresourcemanager.GetIamPolicyRequest{} - policy, err := client.Projects.GetIamPolicy(project.ProjectId, getPolicyRequest).Do() - if err != nil { - t.Fatalf("error getting project iam policy: %v", err) - } - roleFound := false - changed := false - for _, binding := range policy.Bindings { - if binding.Role == "roles/container.serviceAgent" { - memberFound := false - for i, member := range binding.Members { - if member == containerEngineRobot { - binding.Members[i] = binding.Members[len(binding.Members)-1] - memberFound = true - } - } - if memberFound { - binding.Members = binding.Members[:len(binding.Members)-1] - changed = true - } - } else if binding.Role == "roles/editor" { - memberFound := false - for _, member := range binding.Members { - if member == containerEngineRobot { - memberFound = true - break - } - } - if !memberFound { - binding.Members = append(binding.Members, containerEngineRobot) - changed = true - } - roleFound = true - } - } - if !roleFound { - policy.Bindings = append(policy.Bindings, &cloudresourcemanager.Binding{ - Members: []string{containerEngineRobot}, - Role: "roles/editor", - }) - changed = true - } - if changed { - setPolicyRequest := &cloudresourcemanager.SetIamPolicyRequest{Policy: policy} - policy, err = client.Projects.SetIamPolicy(project.ProjectId, setPolicyRequest).Do() - if err != nil { - t.Fatalf("error setting project iam policy: %v", err) - } - } -} - // BootstrapProject will create or get a project named // "" that will persist across test runs, // where projectIDSuffix is based off of getTestProjectFromEnv(). The reason 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 c79ed5c9779a..2428c885beef 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 @@ -3657,15 +3657,35 @@ func TestAccContainerCluster_autoprovisioningDefaultsManagement(t *testing.T) { // 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) { + acctest.SkipIfVcr(t) // skipped because the timeout step doesn't record operation GET interactions t.Parallel() - prefix := acctest.RandString(t, 10) - clusterName := fmt.Sprintf("tf-test-cluster-%s", prefix) - clusterNameError := fmt.Sprintf("tf-test-cluster-err-%s", prefix) + suffix := acctest.RandString(t, 10) + clusterName := fmt.Sprintf("tf-test-cluster-%s", suffix) + clusterNameError := fmt.Sprintf("tf-test-cluster-err-%s", suffix) + clusterNameErrorWithTimeout := fmt.Sprintf("tf-test-cluster-timeout-%s", suffix) containerNetName := fmt.Sprintf("tf-test-container-net-%s", acctest.RandString(t, 10)) initConfig := testAccContainerCluster_withInitialCIDR(containerNetName, clusterName) overlapConfig := testAccContainerCluster_withCIDROverlap(initConfig, clusterNameError) + overlapConfigWithTimeout := testAccContainerCluster_withCIDROverlapWithTimeout(initConfig, clusterNameErrorWithTimeout, "40s") + + checkTaintApplied := func(st *terraform.State) error { + // Return an error if there is no tainted (i.e. marked for deletion) cluster. + ms := st.RootModule() + errCluster, ok := ms.Resources["google_container_cluster.cidr_error_overlap"] + if !ok { + var resourceNames []string + for rn := range ms.Resources { + resourceNames = append(resourceNames, rn) + } + return fmt.Errorf("could not find google_container_cluster.cidr_error_overlap in resources: %v", resourceNames) + } + if !errCluster.Primary.Tainted { + return fmt.Errorf("cluster with ID %s should be tainted, but is not", errCluster.Primary.ID) + } + return nil + } acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -3682,14 +3702,28 @@ func TestAccContainerCluster_errorCleanDanglingCluster(t *testing.T) { ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { + // First attempt to create the overlapping cluster with no timeout, this should fail and taint the resource. Config: overlapConfig, ExpectError: regexp.MustCompile("Error waiting for creating GKE cluster"), }, - // If tainted cluster won't be deleted, this step will return an error { - Config: overlapConfig, - PlanOnly: true, + // Check that the tainted resource is in the config. + Config: overlapConfig, + PlanOnly: true, + ExpectNonEmptyPlan: true, + Check: checkTaintApplied, + }, + { + // Next attempt to create the overlapping cluster with a 40s timeout. This will fail with a different error. + Config: overlapConfigWithTimeout, + ExpectError: regexp.MustCompile("timeout while waiting for state to become 'DONE'"), + }, + { + // Check that the tainted resource is in the config. + Config: overlapConfig, + PlanOnly: true, ExpectNonEmptyPlan: true, + Check: checkTaintApplied, }, }, }) @@ -5467,7 +5501,6 @@ func TestAccContainerCluster_withEnablePrivateEndpointToggle(t *testing.T) { } func testAccContainerCluster_withEnablePrivateEndpoint(clusterName, flag, networkName, subnetworkName string) string { - return fmt.Sprintf(` data "google_container_engine_versions" "uscentral1a" { location = "us-central1-a" @@ -7981,7 +8014,7 @@ resource "google_container_cluster" "cidr_error_preempt" { func testAccContainerCluster_withCIDROverlap(initConfig, secondCluster string) string { return fmt.Sprintf(` - %s +%s resource "google_container_cluster" "cidr_error_overlap" { name = "%s" @@ -8002,6 +8035,33 @@ resource "google_container_cluster" "cidr_error_overlap" { `, initConfig, secondCluster) } + +func testAccContainerCluster_withCIDROverlapWithTimeout(initConfig, secondCluster, createTimeout string) string { + return fmt.Sprintf(` +%s + +resource "google_container_cluster" "cidr_error_overlap" { + name = "%s" + location = "us-central1-a" + + network = google_compute_network.container_network.name + subnetwork = google_compute_subnetwork.container_subnetwork.name + + initial_node_count = 1 + + networking_mode = "VPC_NATIVE" + ip_allocation_policy { + cluster_ipv4_cidr_block = "10.0.0.0/16" + services_ipv4_cidr_block = "10.1.0.0/16" + } + deletion_protection = false + timeouts { + create = "%s" + } +} +`, initConfig, secondCluster, createTimeout) +} + func testAccContainerCluster_withInvalidLocation(location string) string { return fmt.Sprintf(` resource "google_container_cluster" "with_resource_labels" { From c2f6cc6bfdc7c160de0eb36c9b9c9e6f151d8bba Mon Sep 17 00:00:00 2001 From: bcreddy-gcp <123543489+bcreddy-gcp@users.noreply.github.com> Date: Mon, 11 Dec 2023 23:41:52 +0530 Subject: [PATCH 03/27] Terraform support for Workbench instances (#9368) * Workbench Instances * fix yaml to run tests * fix yaml to run tests * fix basic test * diff suppress for tags * add custom flattens * Add labels example * fix tags diff * custom_flatten with ignore_read * removed ignore_read * remove ignore_read on disks * Add kms key in full test * read_ignore for examples * clean up extra flattens * add update test * fix indent lint * fix wbi lint * fix lint issues * fix whitespace * change names in full test to vars * change tests to use variable names instead of hard coded values * stop wbi before updating machine_type * all tests passing * fix terraformgoogleconversion-codegen compiler error * make service account immutable * addressed issues with immutable fields * add disable_proxy_access into full example * Add disable_proxy_access in full test * remove returns in pre and post updates * test false values in secure vm config * fix empty shielded instance config * fixed update on non stop needing fields failing * create custom update mask * make disks sub fields completely immutable * update tests for shielded config and gpu driver * Removed scopes block from product * removed apis required * break shielded_instance_config update msk into submasks * revert update mask for shieldedInstanceConfig * Make vm image immutable * Remove gpu driver config * remove shielded instance config field * removed unspecified values in enums * reupload * removed max_items in serviceAccounts --- mmv1/products/workbench/Instance.yaml | 472 ++++++++++++++++++ mmv1/products/workbench/product.yaml | 39 ++ .../terraform/constants/workbench_instance.go | 142 ++++++ ...stance_boot_disk_encryption_flatten.go.erb | 17 + ...ench_instance_boot_disk_kms_flatten.go.erb | 17 + ...nch_instance_boot_disk_type_flatten.go.erb | 17 + ...stance_data_disk_encryption_flatten.go.erb | 17 + ...ench_instance_data_disk_kms_flatten.go.erb | 17 + ...nch_instance_data_disk_type_flatten.go.erb | 17 + ...workbench_instance_vm_image_flatten.go.erb | 17 + .../examples/workbench_instance_basic.tf.erb | 4 + .../workbench_instance_basic_gpu.tf.erb | 15 + .../examples/workbench_instance_full.tf.erb | 78 +++ .../examples/workbench_instance_labels.tf.erb | 24 + .../post_create/workbench_instance.go.erb | 3 + .../post_update/workbench_instance.go.erb | 35 ++ .../pre_update/workbench_instance.go.erb | 61 +++ ...esource_workbench_instance_gpu_test.go.erb | 272 ++++++++++ 18 files changed, 1264 insertions(+) create mode 100644 mmv1/products/workbench/Instance.yaml create mode 100644 mmv1/products/workbench/product.yaml create mode 100644 mmv1/templates/terraform/constants/workbench_instance.go create mode 100644 mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_encryption_flatten.go.erb create mode 100644 mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_kms_flatten.go.erb create mode 100644 mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_type_flatten.go.erb create mode 100644 mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_encryption_flatten.go.erb create mode 100644 mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_kms_flatten.go.erb create mode 100644 mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_type_flatten.go.erb create mode 100644 mmv1/templates/terraform/custom_flatten/workbench_instance_vm_image_flatten.go.erb create mode 100644 mmv1/templates/terraform/examples/workbench_instance_basic.tf.erb create mode 100644 mmv1/templates/terraform/examples/workbench_instance_basic_gpu.tf.erb create mode 100644 mmv1/templates/terraform/examples/workbench_instance_full.tf.erb create mode 100644 mmv1/templates/terraform/examples/workbench_instance_labels.tf.erb create mode 100644 mmv1/templates/terraform/post_create/workbench_instance.go.erb create mode 100644 mmv1/templates/terraform/post_update/workbench_instance.go.erb create mode 100644 mmv1/templates/terraform/pre_update/workbench_instance.go.erb create mode 100644 mmv1/third_party/terraform/services/workbench/resource_workbench_instance_gpu_test.go.erb diff --git a/mmv1/products/workbench/Instance.yaml b/mmv1/products/workbench/Instance.yaml new file mode 100644 index 000000000000..c5e77ee1abee --- /dev/null +++ b/mmv1/products/workbench/Instance.yaml @@ -0,0 +1,472 @@ +# 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 +base_url: "projects/{{project}}/locations/{{location}}/instances" +create_url: "projects/{{project}}/locations/{{location}}/instances?instanceId={{name}}" +self_link: "projects/{{project}}/locations/{{location}}/instances/{{name}}" +id_format: "projects/{{project}}/locations/{{location}}/instances/{{name}}" +import_format: + - "projects/{{project}}/locations/{{location}}/instances/{{name}}" +name: Instance +description: A Workbench instance. +update_verb: :PATCH +update_mask: true +iam_policy: !ruby/object:Api::Resource::IamPolicy + method_name_separator: ":" + fetch_iam_policy_verb: :GET + parent_resource_attribute: "name" + import_format: + [ + 'projects/{{project}}/locations/{{location}}/instances/{{name}}', + '{{name}}', + ] + base_url: projects/{{project}}/locations/{{location}}/instances/{{name}} +autogen_async: true +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'workbench_instance_basic' + primary_resource_id: 'instance' + primary_resource_name: "fmt.Sprintf(\"tf-test-workbench-instance%s\", + context[\"\ + random_suffix\"])" + region_override: 'us-west1-a' + vars: + instance_name: 'workbench-instance' + - !ruby/object:Provider::Terraform::Examples + name: 'workbench_instance_basic_gpu' + primary_resource_id: 'instance' + primary_resource_name: "fmt.Sprintf(\"tf-test-workbench-instance%s\", + context[\"\ + random_suffix\"])" + region_override: 'us-west1-a' + vars: + instance_name: 'workbench-instance' + ignore_read_extra: + - 'gce_setup.0.vm_image' + - !ruby/object:Provider::Terraform::Examples + name: 'workbench_instance_labels' + primary_resource_id: 'instance' + primary_resource_name: "fmt.Sprintf(\"tf-test-workbench-instance%s\", + context[\"\ + random_suffix\"])" + region_override: 'us-west1-a' + vars: + instance_name: 'workbench-instance' + network_name: 'wbi-test-default' + test_env_vars: + service_account: :SERVICE_ACCT + - !ruby/object:Provider::Terraform::Examples + name: 'workbench_instance_full' + primary_resource_id: 'instance' + primary_resource_name: "fmt.Sprintf(\"tf-test-workbench-instance%s\", + context[\"\ + random_suffix\"])" + region_override: 'us-west1-a' + vars: + instance_name: 'workbench-instance' + network_name: 'wbi-test-default' + keyring_name: 'tftest-shared-keyring-1' + key_name: 'tftest-shared-key-1' + test_env_vars: + service_account: :SERVICE_ACCT + ignore_read_extra: + - 'gce_setup.0.vm_image' + - 'gce_setup.0.boot_disk.0.disk_encryption' + - 'gce_setup.0.boot_disk.0.disk_type' + - 'gce_setup.0.boot_disk.0.kms_key' + - 'gce_setup.0.data_disks.0.disk_encryption' + - 'gce_setup.0.data_disks.0.disk_type' + - 'gce_setup.0.data_disks.0.kms_key' +timeouts: !ruby/object:Api::Timeouts + insert_minutes: 10 + update_minutes: 20 +custom_code: !ruby/object:Provider::Terraform::CustomCode + constants: templates/terraform/constants/workbench_instance.go + post_create: templates/terraform/post_create/workbench_instance.go.erb + pre_update: templates/terraform/pre_update/workbench_instance.go.erb + post_update: templates/terraform/post_update/workbench_instance.go.erb +properties: + - !ruby/object:Api::Type::String + name: name + description: 'The name of this workbench instance. Format: `projects/{project_id}/locations/{location}/instances/{instance_id}`' + required: true + immutable: true + url_param_only: true + pattern: v2/projects/{{project}}/locations/{{location}}/instances/{{name}} + custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' + - !ruby/object:Api::Type::NestedObject + name: gceSetup + default_from_api: true + description: The definition of how to configure a VM instance outside of Resources and Identity. + properties: + - !ruby/object:Api::Type::String + name: machineType + default_from_api: true + description: | + Optional. The machine type of the VM instance. https://cloud.google.com/compute/docs/machine-resource + pattern: projects/{{project}}/zones/{{location}}/machineTypes/{{name}} + diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' + custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb + - !ruby/object:Api::Type::Array + name: acceleratorConfigs + description: | + The hardware accelerators used on this instance. If you use accelerators, make sure that your configuration has + [enough vCPUs and memory to support the `machine_type` you have selected](https://cloud.google.com/compute/docs/gpus/#gpus-list). + Currently supports only one accelerator configuration. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::Enum + name: type + values: + - NVIDIA_TESLA_P100 + - NVIDIA_TESLA_V100 + - NVIDIA_TESLA_P4 + - NVIDIA_TESLA_T4 + - NVIDIA_TESLA_A100 + - NVIDIA_A100_80GB + - NVIDIA_L4 + - NVIDIA_TESLA_T4_VWS + - NVIDIA_TESLA_P100_VWS + - NVIDIA_TESLA_P4_VWS + description: Optional. Type of this accelerator. + - !ruby/object:Api::Type::String + name: coreCount + description: Optional. Count of cores of this accelerator. + description: | + Optional. The hardware accelerators used on this instance. If you + use accelerators, make sure that your configuration has [enough vCPUs and memory + to support the `machine_type` you have selected](https://cloud.google.com/compute/docs/gpus/#gpus-list). + Currently supports only one accelerator configuration. + - !ruby/object:Api::Type::Array + name: serviceAccounts + description: | + The service account that serves as an identity for the VM instance. Currently supports only one service account. + default_from_api: true + immutable: true + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: email + immutable: true + default_from_api: true + description: Optional. Email address of the service account. + - !ruby/object:Api::Type::Array + name: scopes + item_type: Api::Type::String + description: | + Output only. The list of scopes to be made available for this + service account. Set by the CLH to https://www.googleapis.com/auth/cloud-platform + output: true + description: | + Optional. The service account that serves as an identity for the + VM instance. Currently supports only one service account. + - !ruby/object:Api::Type::NestedObject + name: vmImage + custom_flatten: templates/terraform/custom_flatten/workbench_instance_vm_image_flatten.go.erb + default_from_api: true + immutable: true + description: | + Definition of a custom Compute Engine virtual machine image for starting + a workbench instance with the environment installed directly on the VM. + properties: + - !ruby/object:Api::Type::String + name: project + immutable: true + description: | + The name of the Google Cloud project that this VM image belongs to. + Format: {project_id} + - !ruby/object:Api::Type::String + name: name + immutable: true + description: Optional. Use VM image name to find the image. + exactly_one_of: + - vm_image.0.name + - vm_image.0.family + - !ruby/object:Api::Type::String + name: family + immutable: true + description: | + Optional. Use this VM image family to find the image; the newest + image in this family will be used. + exactly_one_of: + - vm_image.0.name + - vm_image.0.family + - !ruby/object:Api::Type::NestedObject + name: bootDisk + default_from_api: true + description: The definition of a boot disk. + immutable: true + properties: + - !ruby/object:Api::Type::String + name: diskSizeGb + default_from_api: true + immutable: true + description: | + Optional. The size of the boot disk in GB attached to this instance, + up to a maximum of 64000 GB (64 TB). If not specified, this defaults to the + recommended value of 150GB. + - !ruby/object:Api::Type::Enum + name: diskType + default_from_api: true + immutable: true + custom_flatten: templates/terraform/custom_flatten/workbench_instance_boot_disk_type_flatten.go.erb + values: + - PD_STANDARD + - PD_SSD + - PD_BALANCED + - PD_EXTREME + description: Optional. Indicates the type of the disk. + - !ruby/object:Api::Type::Enum + name: diskEncryption + default_from_api: true + custom_flatten: templates/terraform/custom_flatten/workbench_instance_boot_disk_encryption_flatten.go.erb + values: + - GMEK + - CMEK + description: | + Optional. Input only. Disk encryption method used on the boot and + data disks, defaults to GMEK. + immutable: true + - !ruby/object:Api::Type::String + name: kmsKey + description: | + 'Optional. Input only. The KMS key used to encrypt the disks, only + applicable if disk_encryption is CMEK. Format: `projects/{project_id}/locations/{location}/keyRings/{key_ring_id}/cryptoKeys/{key_id}` + Learn more about using your own encryption keys.' + immutable: true + custom_flatten: templates/terraform/custom_flatten/workbench_instance_boot_disk_kms_flatten.go.erb + - !ruby/object:Api::Type::Array + name: dataDisks + description: Data disks attached to the VM instance. Currently supports only one data disk. + max_size: 1 + default_from_api: true + immutable: true + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: diskSizeGb + default_from_api: true + immutable: true + description: | + Optional. The size of the disk in GB attached to this VM instance, + up to a maximum of 64000 GB (64 TB). If not specified, this defaults to + 100. + - !ruby/object:Api::Type::Enum + name: diskType + custom_flatten: templates/terraform/custom_flatten/workbench_instance_data_disk_type_flatten.go.erb + values: + - PD_STANDARD + - PD_SSD + - PD_BALANCED + - PD_EXTREME + description: Optional. Input only. Indicates the type of the disk. + immutable: true + - !ruby/object:Api::Type::Enum + name: diskEncryption + default_from_api: true + custom_flatten: templates/terraform/custom_flatten/workbench_instance_data_disk_encryption_flatten.go.erb + values: + - GMEK + - CMEK + description: | + Optional. Input only. Disk encryption method used on the boot + and data disks, defaults to GMEK. + immutable: true + - !ruby/object:Api::Type::String + name: kmsKey + description: | + 'Optional. Input only. The KMS key used to encrypt the disks, + only applicable if disk_encryption is CMEK. Format: `projects/{project_id}/locations/{location}/keyRings/{key_ring_id}/cryptoKeys/{key_id}` + Learn more about using your own encryption keys.' + immutable: true + custom_flatten: templates/terraform/custom_flatten/workbench_instance_data_disk_kms_flatten.go.erb + description: | + Optional. Data disks attached to the VM instance. Currently supports + only one data disk. + - !ruby/object:Api::Type::Array + name: networkInterfaces + description: The network interfaces for the VM. Supports only one interface. + default_from_api: true + immutable: true + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: network + description: 'Optional. The name of the VPC that this VM instance is in.' + immutable: true + custom_expand: templates/terraform/custom_expand/network_full_url.erb + diff_suppress_func: tpgresource.CompareSelfLinkRelativePaths + default_from_api: true + - !ruby/object:Api::Type::String + name: subnet + immutable: true + description: 'Optional. The name of the subnet that this VM instance is in.' + diff_suppress_func: tpgresource.CompareSelfLinkRelativePaths + default_from_api: true + - !ruby/object:Api::Type::Enum + name: nicType + immutable: true + description: | + Optional. The type of vNIC to be used on this interface. This + may be gVNIC or VirtioNet. + values: + - VIRTIO_NET + - GVNIC + description: Optional. The network interfaces for the VM. Supports only one interface. + - !ruby/object:Api::Type::Boolean + name: disablePublicIp + default_from_api: true + immutable: true + description: Optional. If true, no external IP will be assigned to this VM instance. + - !ruby/object:Api::Type::Array + name: tags + item_type: Api::Type::String + default_from_api: true + diff_suppress_func: WorkbenchInstanceTagsDiffSuppress + immutable: true + description: | + Optional. The Compute Engine tags to add to instance (see [Tagging + instances](https://cloud.google.com/compute/docs/label-or-tag-resources#tags)). + - !ruby/object:Api::Type::KeyValuePairs + name: metadata + default_from_api: true + diff_suppress_func: WorkbenchInstanceMetadataDiffSuppress + description: Optional. Custom metadata to apply to this instance. + - !ruby/object:Api::Type::Boolean + name: enableIpForwarding + immutable: true + description: | + Optional. Flag to enable ip forwarding or not, default false/off. + https://cloud.google.com/vpc/docs/using-routes#canipforward + - !ruby/object:Api::Type::String + name: proxyUri + description: Output only. The proxy endpoint that is used to access the Jupyter notebook. + output: true + - !ruby/object:Api::Type::Array + name: instanceOwners + item_type: Api::Type::String + description: | + 'Optional. Input only. The owner 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.' + ignore_read: true + immutable: true + - !ruby/object:Api::Type::String + name: creator + description: Output only. Email address of entity that sent original CreateInstance request. + output: true + - !ruby/object:Api::Type::String + name: state + description: Output only. The state of this instance. + output: true + - !ruby/object:Api::Type::Array + name: upgradeHistory + description: Output only. The upgrade history of this instance. + output: true + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: snapshot + description: Optional. The snapshot of the boot disk of this workbench instance before upgrade. + - !ruby/object:Api::Type::String + name: vmImage + description: Optional. The VM image before this instance upgrade. + - !ruby/object:Api::Type::String + name: containerImage + description: Optional. The container image before this instance upgrade. + - !ruby/object:Api::Type::String + name: framework + description: Optional. The framework of this workbench instance. + - !ruby/object:Api::Type::String + name: version + description: Optional. The version of the workbench instance before this upgrade. + - !ruby/object:Api::Type::String + name: state + description: Output only. The state of this instance upgrade history entry. + output: true + - !ruby/object:Api::Type::String + name: createTime + description: | + An RFC3339 timestamp in UTC time. This in the format of yyyy-MM-ddTHH:mm:ss.SSSZ. + The milliseconds portion (".SSS") is optional. + - !ruby/object:Api::Type::String + name: action + description: Optional. Action. Rolloback or Upgrade. + - !ruby/object:Api::Type::String + name: targetVersion + description: Optional. Target VM Version, like m63. + - !ruby/object:Api::Type::String + name: healthState + description: Output only. Instance health_state. + output: true + - !ruby/object:Api::Type::NestedObject + properties: [] + name: healthInfo + description: | + 'Output only. Additional information about instance health. Example: + healthInfo": { "docker_proxy_agent_status": "1", "docker_status": "1", "jupyterlab_api_status": + "-1", "jupyterlab_status": "-1", "updated": "2020-10-18 09:40:03.573409" }' + output: true + - !ruby/object:Api::Type::String + name: createTime + description: | + An RFC3339 timestamp in UTC time. This in the format of yyyy-MM-ddTHH:mm:ss.SSSZ. + The milliseconds portion (".SSS") is optional. + output: true + - !ruby/object:Api::Type::String + name: updateTime + description: | + An RFC3339 timestamp in UTC time. This in the format of yyyy-MM-ddTHH:mm:ss.SSSZ. + The milliseconds portion (".SSS") is optional. + output: true + - !ruby/object:Api::Type::Boolean + name: disableProxyAccess + immutable: true + description: Optional. If true, the workbench instance will not register with the proxy. + - !ruby/object:Api::Type::KeyValueLabels + name: labels + description: | + Optional. Labels to apply to this instance. These can be later modified + by the UpdateInstance method. + diff_suppress_func: WorkbenchInstanceLabelsDiffSuppress +parameters: + - !ruby/object:Api::Type::String + name: location + description: Part of `parent`. See documentation of `projectsId`. + url_param_only: true + required: true + immutable: true + - !ruby/object:Api::Type::String + name: instanceId + description: Required. User-defined unique ID of this instance. + url_param_only: true + immutable: true +async: !ruby/object:Api::OpAsync + operation: !ruby/object:Api::OpAsync::Operation + path: name + base_url: "{{op_id}}" + wait_ms: 1000 + timeouts: + result: !ruby/object:Api::OpAsync::Result + path: response + resource_inside_response: true + status: !ruby/object:Api::OpAsync::Status + path: done + complete: true + allowed: + - true + - false + error: !ruby/object:Api::OpAsync::Error + path: error + message: message diff --git a/mmv1/products/workbench/product.yaml b/mmv1/products/workbench/product.yaml new file mode 100644 index 000000000000..cbfc6ec431f1 --- /dev/null +++ b/mmv1/products/workbench/product.yaml @@ -0,0 +1,39 @@ +# 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::Product +name: Workbench +display_name: Vertex AI Workbench +versions: + - !ruby/object:Api::Product::Version + name: ga + base_url: https://notebooks.googleapis.com/v2/ +scopes: + - https://www.googleapis.com/auth/cloud-platform +async: !ruby/object:Api::OpAsync + operation: !ruby/object:Api::OpAsync::Operation + base_url: '{{op_id}}' + path: 'name' + 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' + message: 'message' diff --git a/mmv1/templates/terraform/constants/workbench_instance.go b/mmv1/templates/terraform/constants/workbench_instance.go new file mode 100644 index 000000000000..6ae6d20dca67 --- /dev/null +++ b/mmv1/templates/terraform/constants/workbench_instance.go @@ -0,0 +1,142 @@ +var WorkbenchInstanceProvidedLabels = []string{ + "consumer-project-id", + "consumer-project-number", + "notebooks-product", + "resource-name", +} + +func WorkbenchInstanceLabelsDiffSuppress(k, old, new string, d *schema.ResourceData) bool { + // Suppress diffs for the labels + for _, label := range WorkbenchInstanceProvidedLabels { + 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 +} + + +var WorkbenchInstanceProvidedMetadata = []string{ + "disable-swap-binaries", + "enable-guest-attributes", + "proxy-backend-id", + "proxy-registration-url", + "agent-health-check-interval-seconds", + "agent-health-check-path", + "container", + "data-disk-uri", + "dataproc-allow-custom-clusters", + "dataproc-cluster-name", + "dataproc-configs", + "dataproc-default-subnet", + "dataproc-locations-list", + "dataproc-machine-types-list", + "dataproc-notebooks-url", + "dataproc-region", + "dataproc-service-account", + "disable-check-xsrf", + "framework", + "gcs-data-bucket", + "generate-diagnostics-bucket", + "generate-diagnostics-file", + "generate-diagnostics-options", + "image-url", + "install-monitoring-agent", + "install-nvidia-driver", + "installed-extensions", + "notebooks-api", + "notebooks-api-version", + "notebooks-examples-location", + "notebooks-location", + "nvidia-driver-gcs-path", + "proxy-mode", + "proxy-status", + "proxy-url", + "proxy-user-mail", + "report-container-health", + "report-notebook-metrics", + "report-system-health", + "report-system-status", + "restriction", + "serial-port-logging-enable", + "shutdown-script", + "title", + "use-collaborative", + "version", + "enable-oslogin", +} + +func WorkbenchInstanceMetadataDiffSuppress(k, old, new string, d *schema.ResourceData) bool { + // Suppress diffs for the Metadata + for _, metadata := range WorkbenchInstanceProvidedMetadata { + if strings.Contains(k, metadata) && new == "" { + return true + } + } + + // Let diff be determined by metadata + if strings.Contains(k, "gce_setup.0.metadata.%") { + return true + } + + // For other keys, don't suppress diff. + return false +} + + +var WorkbenchInstanceProvidedTags = []string{ + "deeplearning-vm", + "notebook-instance", +} + +func WorkbenchInstanceTagsDiffSuppress(_, _, _ string, d *schema.ResourceData) bool { + old, new := d.GetChange("gce_setup.0.tags") + oldValue := old.([]interface{}) + newValue := new.([]interface{}) + oldValueList := []string{} + newValueList := []string{} + + for _, item := range oldValue { + oldValueList = append(oldValueList,item.(string)) + } + + for _, item := range newValue { + newValueList = append(newValueList,item.(string)) + } + newValueList= append(newValueList,WorkbenchInstanceProvidedTags...) + + sort.Strings(oldValueList) + sort.Strings(newValueList) + if reflect.DeepEqual(oldValueList, newValueList) { + return true + } + return false +} + +<% unless compiler == "terraformgoogleconversion-codegen" -%> +// waitForWorkbenchInstanceActive waits for an workbench instance to become "ACTIVE" +func waitForWorkbenchInstanceActive(d *schema.ResourceData, config *transport_tpg.Config, timeout time.Duration) error { + return resource.Retry(timeout, func() *resource.RetryError { + if err := resourceWorkbenchInstanceRead(d, config); err != nil { + return resource.NonRetryableError(err) + } + + name := d.Get("name").(string) + state := d.Get("state").(string) + if state == "ACTIVE" { + log.Printf("[DEBUG] Workbench Instance %q has state %q.", name, state) + return nil + } else { + return resource.RetryableError(fmt.Errorf("Workbench Instance %q has state %q. Waiting for ACTIVE state", name, state)) + } + + }) +} +<% end -%> diff --git a/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_encryption_flatten.go.erb b/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_encryption_flatten.go.erb new file mode 100644 index 000000000000..eb44d9657f33 --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_encryption_flatten.go.erb @@ -0,0 +1,17 @@ +<%# 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 flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return d.Get("gce_setup.0.boot_disk.0.disk_encryption") +} diff --git a/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_kms_flatten.go.erb b/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_kms_flatten.go.erb new file mode 100644 index 000000000000..70c27a7661e2 --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_kms_flatten.go.erb @@ -0,0 +1,17 @@ +<%# 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 flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return d.Get("gce_setup.0.boot_disk.0.kms_key") +} diff --git a/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_type_flatten.go.erb b/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_type_flatten.go.erb new file mode 100644 index 000000000000..05092c33d46c --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_type_flatten.go.erb @@ -0,0 +1,17 @@ +<%# 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 flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return d.Get("gce_setup.0.boot_disk.0.disk_type") +} diff --git a/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_encryption_flatten.go.erb b/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_encryption_flatten.go.erb new file mode 100644 index 000000000000..d93558a3db76 --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_encryption_flatten.go.erb @@ -0,0 +1,17 @@ +<%# 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 flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return d.Get("gce_setup.0.data_disks.0.disk_encryption") +} diff --git a/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_kms_flatten.go.erb b/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_kms_flatten.go.erb new file mode 100644 index 000000000000..b6a7b9649db0 --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_kms_flatten.go.erb @@ -0,0 +1,17 @@ +<%# 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 flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return d.Get("gce_setup.0.data_disks.0.kms_key") +} diff --git a/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_type_flatten.go.erb b/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_type_flatten.go.erb new file mode 100644 index 000000000000..b23aa34b41e3 --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_type_flatten.go.erb @@ -0,0 +1,17 @@ +<%# 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 flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return d.Get("gce_setup.0.data_disks.0.disk_type") +} diff --git a/mmv1/templates/terraform/custom_flatten/workbench_instance_vm_image_flatten.go.erb b/mmv1/templates/terraform/custom_flatten/workbench_instance_vm_image_flatten.go.erb new file mode 100644 index 000000000000..24a7978041e5 --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/workbench_instance_vm_image_flatten.go.erb @@ -0,0 +1,17 @@ +<%# 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 flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return d.Get("gce_setup.0.vm_image") +} diff --git a/mmv1/templates/terraform/examples/workbench_instance_basic.tf.erb b/mmv1/templates/terraform/examples/workbench_instance_basic.tf.erb new file mode 100644 index 000000000000..3a2cac94277d --- /dev/null +++ b/mmv1/templates/terraform/examples/workbench_instance_basic.tf.erb @@ -0,0 +1,4 @@ +resource "google_workbench_instance" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['instance_name'] %>" + location = "us-west1-a" +} diff --git a/mmv1/templates/terraform/examples/workbench_instance_basic_gpu.tf.erb b/mmv1/templates/terraform/examples/workbench_instance_basic_gpu.tf.erb new file mode 100644 index 000000000000..41c682cf1936 --- /dev/null +++ b/mmv1/templates/terraform/examples/workbench_instance_basic_gpu.tf.erb @@ -0,0 +1,15 @@ +resource "google_workbench_instance" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['instance_name'] %>" + location = "us-central1-a" + gce_setup { + machine_type = "n1-standard-1" // cant be e2 because of accelerator + accelerator_configs { + type = "NVIDIA_TESLA_T4" + core_count = 1 + } + vm_image { + project = "deeplearning-platform-release" + family = "tf-latest-gpu" + } + } +} diff --git a/mmv1/templates/terraform/examples/workbench_instance_full.tf.erb b/mmv1/templates/terraform/examples/workbench_instance_full.tf.erb new file mode 100644 index 000000000000..f9f603ab483d --- /dev/null +++ b/mmv1/templates/terraform/examples/workbench_instance_full.tf.erb @@ -0,0 +1,78 @@ +resource "google_compute_network" "my_network" { + name = "<%= ctx[:vars]['network_name'] %>" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "my_subnetwork" { + name = "<%= ctx[:vars]['network_name'] %>" + network = google_compute_network.my_network.id + region = "us-central1" + ip_cidr_range = "10.0.1.0/24" +} + +resource "google_kms_key_ring" "keyring" { + name = "<%= ctx[:vars]['keyring_name'] %>" + location = "global" +} + +resource "google_kms_crypto_key" "crypto-key" { + name = "<%= ctx[:vars]['key_name'] %>" + key_ring = google_kms_key_ring.keyring.id +} + +resource "google_workbench_instance" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['instance_name'] %>" + location = "us-central1-a" + + gce_setup { + machine_type = "n1-standard-4" // cant be e2 because of accelerator + accelerator_configs { + type = "NVIDIA_TESLA_T4" + core_count = 1 + } + + disable_public_ip = false + + service_accounts { + email = "<%= ctx[:test_env_vars]["service_account"] %>" + } + + boot_disk { + disk_size_gb = 310 + disk_type = "PD_SSD" + disk_encryption = "GMEK" + kms_key = google_kms_crypto_key.crypto-key.id + } + + data_disks { + disk_size_gb = 330 + disk_type = "PD_SSD" + disk_encryption = "GMEK" + kms_key = google_kms_crypto_key.crypto-key.id + } + + network_interfaces { + network = google_compute_network.my_network.id + subnet = google_compute_subnetwork.my_subnetwork.id + nic_type = "GVNIC" + } + + metadata = { + terraform = "true" + } + + enable_ip_forwarding = true + + tags = ["abc", "def"] + + } + + disable_proxy_access = "true" + + instance_owners = [ "<%= ctx[:test_env_vars]["service_account"] %>"] + + labels = { + k = "val" + } + +} diff --git a/mmv1/templates/terraform/examples/workbench_instance_labels.tf.erb b/mmv1/templates/terraform/examples/workbench_instance_labels.tf.erb new file mode 100644 index 000000000000..3a0d9afda853 --- /dev/null +++ b/mmv1/templates/terraform/examples/workbench_instance_labels.tf.erb @@ -0,0 +1,24 @@ +resource "google_workbench_instance" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['instance_name'] %>" + location = "us-central1-a" + + gce_setup { + machine_type = "e2-standard-4" + + service_accounts { + email = "<%= ctx[:test_env_vars]["service_account"] %>" + } + + metadata = { + terraform = "true" + } + + } + + instance_owners = [ "<%= ctx[:test_env_vars]["service_account"] %>"] + + labels = { + k = "val" + } + +} diff --git a/mmv1/templates/terraform/post_create/workbench_instance.go.erb b/mmv1/templates/terraform/post_create/workbench_instance.go.erb new file mode 100644 index 000000000000..e3a968e4a6b2 --- /dev/null +++ b/mmv1/templates/terraform/post_create/workbench_instance.go.erb @@ -0,0 +1,3 @@ +if err := waitForWorkbenchInstanceActive(d, config, d.Timeout(schema.TimeoutCreate) - time.Minute); err != nil { + return fmt.Errorf("Workbench instance %q did not reach ACTIVE state: %q", d.Get("name").(string), err) +} diff --git a/mmv1/templates/terraform/post_update/workbench_instance.go.erb b/mmv1/templates/terraform/post_update/workbench_instance.go.erb new file mode 100644 index 000000000000..fa994a3aacb4 --- /dev/null +++ b/mmv1/templates/terraform/post_update/workbench_instance.go.erb @@ -0,0 +1,35 @@ +state := d.Get("state").(string) + +if state != "ACTIVE" { + startURL, err := tpgresource.ReplaceVars(d, config, "{{WorkbenchBasePath}}projects/{{project}}/locations/{{location}}/instances/{{name}}:start") + if err != nil { + return err + } + + log.Printf("[DEBUG] Starting Workbench Instance: %q", name) + + emptyReqBody := make(map[string]interface{}) + + pRes, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: billingProject, + RawURL: startURL, + UserAgent: userAgent, + Body: emptyReqBody, + }) + if err != nil { + return fmt.Errorf("Error Starting Workbench Instance: %s", err) + } + + var opResp map[string]interface{} + err = WorkbenchOperationWaitTimeWithResponse( + config, pRes, &opResp, project, "Starting Workbench Instance", userAgent, + d.Timeout(schema.TimeoutUpdate)) + if err != nil { + return fmt.Errorf("Error waiting to start Workbench Instance: %s", err) + } + +} else { + log.Printf("[DEBUG] Workbench Instance %q has state %q.", name, state) +} diff --git a/mmv1/templates/terraform/pre_update/workbench_instance.go.erb b/mmv1/templates/terraform/pre_update/workbench_instance.go.erb new file mode 100644 index 000000000000..2b33205942a7 --- /dev/null +++ b/mmv1/templates/terraform/pre_update/workbench_instance.go.erb @@ -0,0 +1,61 @@ +name := d.Get("name").(string) +if d.HasChange("gce_setup.0.machine_type") || d.HasChange("gce_setup.0.accelerator_configs") { + state := d.Get("state").(string) + if state != "STOPPED" { + stopURL, err := tpgresource.ReplaceVars(d, config, "{{WorkbenchBasePath}}projects/{{project}}/locations/{{location}}/instances/{{name}}:stop") + if err != nil { + return err + } + + log.Printf("[DEBUG] Stopping Workbench Instance: %q", name) + + emptyReqBody := make(map[string]interface{}) + + dRes, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: billingProject, + RawURL: stopURL, + UserAgent: userAgent, + Body: emptyReqBody, + }) + if err != nil { + return fmt.Errorf("Error Stopping Workbench Instance: %s", err) + } + + var opRes map[string]interface{} + err = WorkbenchOperationWaitTimeWithResponse( + config, dRes, &opRes, project, "Stopping Workbench Instance", userAgent, + d.Timeout(schema.TimeoutUpdate)) + if err != nil { + return fmt.Errorf("Error waiting to stop Workbench Instance: %s", err) + } + + } else { + log.Printf("[DEBUG] Workbench Instance %q has state %q.", name, state) + } + +} else { + log.Printf("[DEBUG] Workbench Instance %q need not be stopped for the update.", name) +} + +// Build custom mask since the notebooks API does not support gce_setup as a valid mask +newUpdateMask := []string{} +if d.HasChange("gce_setup.0.machine_type") { + newUpdateMask = append(newUpdateMask, "gce_setup.machine_type") +} +if d.HasChange("gce_setup.0.accelerator_configs") { + newUpdateMask = append(newUpdateMask, "gce_setup.accelerator_configs") +} +if d.HasChange("gce_setup.0.metadata") { + newUpdateMask = append(newUpdateMask, "gceSetup.metadata") +} +if d.HasChange("effective_labels") { + newUpdateMask = append(newUpdateMask, "labels") +} + +// Overwrite the previously set mask. +url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(newUpdateMask, ",")}) +if err != nil { + return err +} diff --git a/mmv1/third_party/terraform/services/workbench/resource_workbench_instance_gpu_test.go.erb b/mmv1/third_party/terraform/services/workbench/resource_workbench_instance_gpu_test.go.erb new file mode 100644 index 000000000000..c1914881b2a6 --- /dev/null +++ b/mmv1/third_party/terraform/services/workbench/resource_workbench_instance_gpu_test.go.erb @@ -0,0 +1,272 @@ +<% autogen_exception -%> +package workbench_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccWorkbenchInstance_update(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), + Steps: []resource.TestStep{ + { + Config: testAccWorkbenchInstance_basic(context), + }, + { + ResourceName: "google_workbench_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"}, + }, + { + Config: testAccWorkbenchInstance_update(context), + }, + { + ResourceName: "google_workbench_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccWorkbenchInstance_basic(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_workbench_instance" "instance" { + name = "tf-test-workbench-instance%{random_suffix}" + location = "us-central1-a" +} +`, context) +} + +func testAccWorkbenchInstance_update(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_workbench_instance" "instance" { + name = "tf-test-workbench-instance%{random_suffix}" + location = "us-central1-a" + + gce_setup { + machine_type = "n1-standard-16" + + accelerator_configs{ + type = "NVIDIA_TESLA_T4" + core_count = 1 + } + + metadata = { + terraform = "true" + } + + } + + labels = { + k = "val" + } + +} +`, context) +} + +func TestAccWorkbenchInstance_updateGpu(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), + Steps: []resource.TestStep{ + { + Config: testAccWorkbenchInstance_basicGpu(context), + }, + { + ResourceName: "google_workbench_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"}, + }, + { + Config: testAccWorkbenchInstance_updateGpu(context), + }, + { + ResourceName: "google_workbench_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccWorkbenchInstance_basicGpu(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_workbench_instance" "instance" { + name = "tf-test-workbench-instance%{random_suffix}" + location = "us-central1-a" + gce_setup { + machine_type = "n1-standard-1" // cant be e2 because of accelerator + accelerator_configs { + type = "NVIDIA_TESLA_T4" + core_count = 1 + } + + } +} +`, context) +} + +func testAccWorkbenchInstance_updateGpu(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_workbench_instance" "instance" { + name = "tf-test-workbench-instance%{random_suffix}" + location = "us-central1-a" + + gce_setup { + machine_type = "n1-standard-16" + + accelerator_configs{ + type = "NVIDIA_TESLA_P4" + core_count = 1 + } + + } + + labels = { + k = "val" + } + +} +`, context) +} + +func TestAccWorkbenchInstance_removeGpu(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), + Steps: []resource.TestStep{ + { + Config: testAccWorkbenchInstance_Gpu(context), + }, + { + ResourceName: "google_workbench_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"}, + }, + { + Config: testAccWorkbenchInstance_updateGpu(context), + }, + { + ResourceName: "google_workbench_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccWorkbenchInstance_Gpu(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_workbench_instance" "instance" { + name = "tf-test-workbench-instance%{random_suffix}" + location = "us-central1-a" + gce_setup { + machine_type = "n1-standard-1" // cant be e2 because of accelerator + accelerator_configs { + type = "NVIDIA_TESLA_T4" + core_count = 1 + } + + } +} +`, context) +} + +func testAccWorkbenchInstance_removeGpu(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_workbench_instance" "instance" { + name = "tf-test-workbench-instance%{random_suffix}" + location = "us-central1-a" + + gce_setup { + machine_type = "n1-standard-16" + + } + +} +`, context) +} + +func TestAccWorkbenchInstance_updateMetadata(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), + Steps: []resource.TestStep{ + { + Config: testAccWorkbenchInstance_basic(context), + }, + { + ResourceName: "google_workbench_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"}, + }, + { + Config: testAccWorkbenchInstance_updateMetadata(context), + }, + { + ResourceName: "google_workbench_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccWorkbenchInstance_updateMetadata(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_workbench_instance" "instance" { + name = "tf-test-workbench-instance%{random_suffix}" + location = "us-central1-a" + + gce_setup { + metadata = { + terraform = "true" + } + } + + labels = { + k = "val" + } + +} +`, context) +} From 42bac036dc8ec30910c69ca6e6703fd6654ba7d1 Mon Sep 17 00:00:00 2001 From: James Edouard Date: Mon, 11 Dec 2023 17:24:56 -0500 Subject: [PATCH 04/27] Add support for severity options in AlertPolicy (#9544) * Add support for severity options in AlertPolicy * Update description for severity options * Add update test for severity options * Format go changes --------- Co-authored-by: James Edouard --- mmv1/products/monitoring/AlertPolicy.yaml | 10 +++++++++ .../resource_monitoring_alert_policy_test.go | 22 ++++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/mmv1/products/monitoring/AlertPolicy.yaml b/mmv1/products/monitoring/AlertPolicy.yaml index 92aa4f110ad8..d968e2d4ea1c 100644 --- a/mmv1/products/monitoring/AlertPolicy.yaml +++ b/mmv1/products/monitoring/AlertPolicy.yaml @@ -957,6 +957,16 @@ properties: to 63 Unicode characters or 128 bytes, whichever is smaller. Labels and values can contain only lowercase letters, numerals, underscores, and dashes. Keys must begin with a letter. + - !ruby/object:Api::Type::Enum + name: severity + description: | + The severity of an alert policy indicates how important incidents generated + by that policy are. The severity level will be displayed on the Incident + detail page and in notifications. + values: + - :CRITICAL + - :ERROR + - :WARNING - !ruby/object:Api::Type::NestedObject name: documentation description: | diff --git a/mmv1/third_party/terraform/services/monitoring/resource_monitoring_alert_policy_test.go b/mmv1/third_party/terraform/services/monitoring/resource_monitoring_alert_policy_test.go index 857d40c00b24..c21ebca4a15d 100644 --- a/mmv1/third_party/terraform/services/monitoring/resource_monitoring_alert_policy_test.go +++ b/mmv1/third_party/terraform/services/monitoring/resource_monitoring_alert_policy_test.go @@ -48,7 +48,7 @@ func testAccMonitoringAlertPolicy_basic(t *testing.T) { CheckDestroy: testAccCheckAlertPolicyDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccMonitoringAlertPolicy_basicCfg(alertName, conditionName, "ALIGN_RATE", filter), + Config: testAccMonitoringAlertPolicy_basicCfg(alertName, conditionName, "ALIGN_RATE", filter, "WARNING"), }, { ResourceName: "google_monitoring_alert_policy.basic", @@ -65,8 +65,10 @@ func testAccMonitoringAlertPolicy_update(t *testing.T) { conditionName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) filter1 := `metric.type=\"compute.googleapis.com/instance/disk/write_bytes_count\" AND resource.type=\"gce_instance\"` aligner1 := "ALIGN_RATE" + severity1 := "WARNING" filter2 := `metric.type=\"compute.googleapis.com/instance/cpu/utilization\" AND resource.type=\"gce_instance\"` aligner2 := "ALIGN_MAX" + severity2 := "ERROR" acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -74,7 +76,7 @@ func testAccMonitoringAlertPolicy_update(t *testing.T) { CheckDestroy: testAccCheckAlertPolicyDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccMonitoringAlertPolicy_basicCfg(alertName, conditionName, aligner1, filter1), + Config: testAccMonitoringAlertPolicy_basicCfg(alertName, conditionName, aligner1, filter1, severity1), }, { ResourceName: "google_monitoring_alert_policy.basic", @@ -82,7 +84,7 @@ func testAccMonitoringAlertPolicy_update(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccMonitoringAlertPolicy_basicCfg(alertName, conditionName, aligner2, filter2), + Config: testAccMonitoringAlertPolicy_basicCfg(alertName, conditionName, aligner2, filter2, severity2), }, { ResourceName: "google_monitoring_alert_policy.basic", @@ -233,7 +235,7 @@ func testAccMonitoringAlertPolicy_promql(t *testing.T) { }) } -func testAccMonitoringAlertPolicy_basicCfg(alertName, conditionName, aligner, filter string) string { +func testAccMonitoringAlertPolicy_basicCfg(alertName, conditionName, aligner, filter, severity string) string { return fmt.Sprintf(` resource "google_monitoring_alert_policy" "basic" { display_name = "%s" @@ -255,8 +257,10 @@ resource "google_monitoring_alert_policy" "basic" { threshold_value = "0.5" } } + + severity = "%s" } -`, alertName, conditionName, aligner, filter) +`, alertName, conditionName, aligner, filter, severity) } func testAccMonitoringAlertPolicy_fullCfg(alertName, conditionName1, conditionName2 string) string { @@ -319,6 +323,8 @@ resource "google_monitoring_alert_policy" "full" { } } + severity = "WARNING" + documentation { content = "test content" mime_type = "text/markdown" @@ -348,6 +354,8 @@ resource "google_monitoring_alert_policy" "mql" { } } + severity = "WARNING" + documentation { content = "test content" mime_type = "text/markdown" @@ -382,6 +390,8 @@ resource "google_monitoring_alert_policy" "log" { auto_close = "2000s" } + severity = "WARNING" + documentation { content = "test content" mime_type = "text/markdown" @@ -441,6 +451,8 @@ resource "google_monitoring_alert_policy" "promql" { } } + severity = "WARNING" + documentation { content = "test content" mime_type = "text/markdown" From 135dfa3e51199e0bb43be5e9e782c2edfd4f88fd Mon Sep 17 00:00:00 2001 From: Edward Sun <42220489+edwardmedia@users.noreply.github.com> Date: Mon, 11 Dec 2023 14:42:16 -0800 Subject: [PATCH 05/27] taint writer_identity (#9561) * taint writer_identity * update error handling --------- Co-authored-by: Edward Sun --- .../logging/resource_logging_project_sink.go | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 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 86f28c26d76f..9a2ecf70d7d6 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 @@ -94,10 +94,19 @@ func resourceLoggingProjectSinkAcquireOrCreate(d *schema.ResourceData, meta inte return resourceLoggingProjectSinkUpdate(d, meta) } -// if bigquery_options is set unique_writer_identity must be true +// 1) if bigquery_options is set unique_writer_identity must be true +// 2) taint the value of writer_identity when unique_writer_identity is updating from false -> true func resourceLoggingProjectSinkCustomizeDiff(ctx context.Context, d *schema.ResourceDiff, meta interface{}) error { // separate func to allow unit testing - return resourceLoggingProjectSinkCustomizeDiffFunc(d) + err := resourceLoggingProjectSinkCustomizeDiffFunc(d) + if err != nil { + return err + } + err = resourceLoggingProjectSinkUniqueWriterIdentityCustomizeDiffFunc(d) + if err != nil { + return err + } + return nil } func resourceLoggingProjectSinkCustomizeDiffFunc(diff tpgresource.TerraformResourceDiff) error { @@ -115,6 +124,20 @@ func resourceLoggingProjectSinkCustomizeDiffFunc(diff tpgresource.TerraformResou return nil } +func resourceLoggingProjectSinkUniqueWriterIdentityCustomizeDiffFunc(diff *schema.ResourceDiff) error { + if !diff.HasChange("unique_writer_identity") { + return nil + } + // taint the value of writer_identity when unique_writer_identity is updating from false -> true + if diff.Get("unique_writer_identity").(bool) { + err := diff.SetNewComputed("writer_identity") + if err != nil { + return fmt.Errorf("Error re-setting writer_identity: %s", err) + } + } + return nil +} + func resourceLoggingProjectSinkRead(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) From 0124464a2158773138682030d38e0a454c998238 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Mon, 11 Dec 2023 23:56:51 +0000 Subject: [PATCH 06/27] Update Cloud Run v2 tests to make service account with sweepable name (#9620) --- .../data_source_google_cloud_run_v2_job_test.go | 14 ++++++-------- ...data_source_google_cloud_run_v2_service_test.go | 14 ++++++-------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/mmv1/third_party/terraform/services/cloudrunv2/data_source_google_cloud_run_v2_job_test.go b/mmv1/third_party/terraform/services/cloudrunv2/data_source_google_cloud_run_v2_job_test.go index 5e2044eb37f1..482e4a196d18 100644 --- a/mmv1/third_party/terraform/services/cloudrunv2/data_source_google_cloud_run_v2_job_test.go +++ b/mmv1/third_party/terraform/services/cloudrunv2/data_source_google_cloud_run_v2_job_test.go @@ -75,7 +75,7 @@ func TestAccDataSourceGoogleCloudRunV2Job_bindIAMPermission(t *testing.T) { project := envvar.GetTestProjectFromEnv() - name := fmt.Sprintf("tf-test-cloud-run-v2-job-%d", acctest.RandInt(t)) + name := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) location := "us-central1" id := fmt.Sprintf("projects/%s/locations/%s/jobs/%s", project, location, name) @@ -122,18 +122,16 @@ data "google_cloud_run_v2_job" "hello" { } resource "google_service_account" "foo" { - account_id = "foo-service-account" - display_name = "foo-service-account" + account_id = "%s" + display_name = "Service account for google_cloud_run_v2_job data source acceptance test " } -resource "google_cloud_run_v2_job_iam_binding" "foo_run_invoker" { +resource "google_cloud_run_v2_job_iam_member" "foo_run_invoker" { name = data.google_cloud_run_v2_job.hello.name location = data.google_cloud_run_v2_job.hello.location role = "roles/run.invoker" - members = [ - "serviceAccount:${google_service_account.foo.email}", - ] + member = "serviceAccount:${google_service_account.foo.email}" } -`, name, location) +`, name, location, name) } diff --git a/mmv1/third_party/terraform/services/cloudrunv2/data_source_google_cloud_run_v2_service_test.go b/mmv1/third_party/terraform/services/cloudrunv2/data_source_google_cloud_run_v2_service_test.go index 7f7a4d5129c9..64de401e1e0e 100644 --- a/mmv1/third_party/terraform/services/cloudrunv2/data_source_google_cloud_run_v2_service_test.go +++ b/mmv1/third_party/terraform/services/cloudrunv2/data_source_google_cloud_run_v2_service_test.go @@ -68,7 +68,7 @@ func TestAccDataSourceGoogleCloudRunV2Service_bindIAMPermission(t *testing.T) { project := envvar.GetTestProjectFromEnv() - name := fmt.Sprintf("tf-test-cloud-run-v2-service-%d", acctest.RandInt(t)) + name := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) location := "us-central1" id := fmt.Sprintf("projects/%s/locations/%s/services/%s", project, location, name) @@ -108,18 +108,16 @@ data "google_cloud_run_v2_service" "hello" { } resource "google_service_account" "foo" { - account_id = "foo-service-account" - display_name = "foo-service-account" + account_id = "%s" + display_name = "Service account for google_cloud_run_v2_service data source acceptance test " } -resource "google_cloud_run_v2_service_iam_binding" "foo_run_invoker" { +resource "google_cloud_run_v2_service_iam_member" "foo_run_invoker" { name = data.google_cloud_run_v2_service.hello.name location = data.google_cloud_run_v2_service.hello.location role = "roles/run.invoker" - members = [ - "serviceAccount:${google_service_account.foo.email}", - ] + member = "serviceAccount:${google_service_account.foo.email}" } -`, name, location) +`, name, location, name) } From e87ca382d9e0e077426c1061920f1c69c63f3eee Mon Sep 17 00:00:00 2001 From: Swamita Gupta <55314843+swamitagupta@users.noreply.github.com> Date: Tue, 12 Dec 2023 22:09:52 +0530 Subject: [PATCH 07/27] Add type field to PrivateCloud in Vmwareengine (#9608) --- mmv1/products/vmwareengine/PrivateCloud.yaml | 13 ++++++++++++- .../vmware_engine_private_cloud_full.tf.erb | 6 ++++-- .../resource_vmwareengine_private_cloud_test.go | 4 +++- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/mmv1/products/vmwareengine/PrivateCloud.yaml b/mmv1/products/vmwareengine/PrivateCloud.yaml index 662dbe755cdb..33eac4d383f4 100644 --- a/mmv1/products/vmwareengine/PrivateCloud.yaml +++ b/mmv1/products/vmwareengine/PrivateCloud.yaml @@ -20,7 +20,7 @@ create_url: 'projects/{{project}}/locations/{{location}}/privateClouds?privateCl update_verb: :PATCH references: !ruby/object:Api::Resource::ReferenceLinks api: 'https://cloud.google.com/vmware-engine/docs/reference/rest/v1/projects.locations.privateClouds' -description: / Represents a private cloud resource. Private clouds are zonal resources. +description: Represents a private cloud resource. Private clouds are zonal resources. error_abort_predicates: ['transport_tpg.Is429QuotaError'] async: !ruby/object:Api::OpAsync operation: !ruby/object:Api::OpAsync::Operation @@ -285,3 +285,14 @@ properties: name: 'fqdn' description: |- Fully qualified domain name of the appliance. + + - !ruby/object:Api::Type::Enum + name: 'type' + description: | + Initial type of the private cloud. + immutable: true + ignore_read: true + values: + - :STANDARD + - :TIME_LIMITED + default_value: :STANDARD diff --git a/mmv1/templates/terraform/examples/vmware_engine_private_cloud_full.tf.erb b/mmv1/templates/terraform/examples/vmware_engine_private_cloud_full.tf.erb index d246a3576538..ee12d6bfdd24 100644 --- a/mmv1/templates/terraform/examples/vmware_engine_private_cloud_full.tf.erb +++ b/mmv1/templates/terraform/examples/vmware_engine_private_cloud_full.tf.erb @@ -2,6 +2,7 @@ resource "google_vmwareengine_private_cloud" "<%= ctx[:primary_resource_id] %>" location = "<%= ctx[:test_env_vars]['region'] %>-a" name = "<%= ctx[:vars]['private_cloud_id'] %>" description = "Sample test PC." + type = "TIME_LIMITED" network_config { management_cidr = "192.168.30.0/24" vmware_engine_network = google_vmwareengine_network.pc-nw.id @@ -11,7 +12,7 @@ resource "google_vmwareengine_private_cloud" "<%= ctx[:primary_resource_id] %>" cluster_id = "<%= ctx[:vars]['management_cluster_id'] %>" node_type_configs { node_type_id = "standard-72" - node_count = 3 + node_count = 1 custom_core_count = 32 } } @@ -21,4 +22,5 @@ resource "google_vmwareengine_network" "pc-nw" { name = "<%= ctx[:vars]['network_id'] %>" location = "global" type = "STANDARD" - description = "PC network description." \ No newline at end of file + description = "PC network description." +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go index 05195787f1a2..b486ff495db4 100644 --- a/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go +++ b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go @@ -27,7 +27,7 @@ func TestAccVmwareenginePrivateCloud_vmwareEnginePrivateCloudUpdate(t *testing.T CheckDestroy: testAccCheckVmwareenginePrivateCloudDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testPrivateCloudUpdateConfig(context, "description1", 3), + Config: testPrivateCloudUpdateConfig(context, "description1", 1), Check: resource.ComposeTestCheckFunc( acctest.CheckDataSourceStateMatchesResourceStateWithIgnores("data.google_vmwareengine_private_cloud.ds", "google_vmwareengine_private_cloud.vmw-engine-pc", map[string]struct{}{}), testAccCheckGoogleVmwareengineNsxCredentialsMeta("data.google_vmwareengine_nsx_credentials.nsx-ds"), @@ -78,6 +78,7 @@ resource "google_vmwareengine_private_cloud" "vmw-engine-pc" { location = "%{region}-a" name = "tf-test-sample-pc%{random_suffix}" description = "%{description}" + type = "TIME_LIMITED" network_config { management_cidr = "192.168.30.0/24" vmware_engine_network = google_vmwareengine_network.default-nw.id @@ -104,6 +105,7 @@ data "google_vmwareengine_private_cloud" "ds" { data "google_vmwareengine_nsx_credentials" "nsx-ds" { parent = google_vmwareengine_private_cloud.vmw-engine-pc.id } + data "google_vmwareengine_vcenter_credentials" "vcenter-ds" { parent = google_vmwareengine_private_cloud.vmw-engine-pc.id } From b4195a644bc0aaba2197195d3b8d472969c6a469 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Tue, 12 Dec 2023 16:58:23 +0000 Subject: [PATCH 08/27] Remove use of `google_kms_crypto_key_iam_binding` resource in tests, to make tests stable in overnight testing (#9621) * Remove `google_kms_crypto_key_iam_binding` resources that affect shared crypto keys * Remove unnecessary use of `google_kms_crypto_key_iam_binding` (no shared crypto key affected) By removing this usage of `google_kms_crypto_key_iam_binding` I intend to make it easier to identify when acc tests affect shared resources that aren't provisioned by the test * Remove unnecessary use of `google_kms_crypto_key_iam_binding` (no shared crypto key affected) * Fix call to config function in acc test * Update mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function_test.go.erb * Skip `TestAccCloudFunctionsFunction_cmek` in VCR --- ...secure_source_manager_instance_cmek.tf.erb | 6 ++-- ...source_cloudfunctions_function_test.go.erb | 31 ++++++++++++++----- .../resource_compute_instance_test.go.erb | 8 ++--- .../resource_spanner_database_test.go.erb | 8 ++--- 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/mmv1/templates/terraform/examples/secure_source_manager_instance_cmek.tf.erb b/mmv1/templates/terraform/examples/secure_source_manager_instance_cmek.tf.erb index abde1100aaa7..c7fd6f9312d3 100644 --- a/mmv1/templates/terraform/examples/secure_source_manager_instance_cmek.tf.erb +++ b/mmv1/templates/terraform/examples/secure_source_manager_instance_cmek.tf.erb @@ -8,13 +8,11 @@ resource "google_kms_crypto_key" "crypto_key" { key_ring = google_kms_key_ring.key_ring.id } -resource "google_kms_crypto_key_iam_binding" "crypto_key_binding" { +resource "google_kms_crypto_key_iam_member" "crypto_key_binding" { crypto_key_id = google_kms_crypto_key.crypto_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-sourcemanager.iam.gserviceaccount.com" - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-sourcemanager.iam.gserviceaccount.com" } resource "google_secure_source_manager_instance" "<%= ctx[:primary_resource_id] %>" { 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 9bf727547801..0c2be3a3a1a3 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 @@ -295,7 +295,9 @@ func TestAccCloudFunctionsFunction_dockerRepository(t *testing.T) { <% unless version == "ga" -%> func TestAccCloudFunctionsFunction_cmek(t *testing.T) { + acctest.SkipIfVcr(t) t.Parallel() + kmsKey := acctest.BootstrapKMSKeyInLocation(t, "us-central1") funcResourceName := "google_cloudfunctions_function.function" arRepoName := fmt.Sprintf("tf-cmek-test-docker-repository-%s", acctest.RandString(t, 10)) @@ -1078,24 +1080,37 @@ resource "google_artifact_registry_repository_iam_binding" "binding" { ] } -resource "google_kms_crypto_key_iam_binding" "gcf_cmek_keyuser" { +resource "google_kms_crypto_key_iam_member" "gcf_cmek_keyuser_1" { crypto_key_id = "%s" role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcf-admin-robot.iam.gserviceaccount.com", - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-artifactregistry.iam.gserviceaccount.com", - "serviceAccount:service-${data.google_project.project.number}@gs-project-accounts.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcf-admin-robot.iam.gserviceaccount.com" } +resource "google_kms_crypto_key_iam_member" "gcf_cmek_keyuser_2" { + crypto_key_id = "%s" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-artifactregistry.iam.gserviceaccount.com" +} + +resource "google_kms_crypto_key_iam_member" "gcf_cmek_keyuser_3" { + crypto_key_id = "%s" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + member = "serviceAccount:service-${data.google_project.project.number}@gs-project-accounts.iam.gserviceaccount.com" +} + + resource "google_artifact_registry_repository" "encoded-ar-repo" { repository_id = "%s" kms_key_name = "%s" location = "us-central1" format = "DOCKER" depends_on = [ - google_kms_crypto_key_iam_binding.gcf_cmek_keyuser + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_1, + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_2, + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_3, ] } @@ -1123,7 +1138,7 @@ resource "google_cloudfunctions_function" "function" { timeout = 61 entry_point = "helloGET" } -`, kmsKey, arRepoName, kmsKey, bucketName, zipFilePath, functionName, kmsKey) +`, kmsKey, kmsKey, kmsKey, arRepoName, kmsKey, bucketName, zipFilePath, functionName, kmsKey) } <% end -%> 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 6d747946cef6..f52854d8a441 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 @@ -6905,12 +6905,10 @@ data "google_compute_image" "my_image" { data "google_project" "project" {} -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { crypto_key_id = "%{key_name}" role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${data.google_project.project.number}-compute@developer.gserviceaccount.com", - ] + member = "serviceAccount:${data.google_project.project.number}-compute@developer.gserviceaccount.com" } resource "google_compute_instance" "foobar" { @@ -6932,7 +6930,7 @@ resource "google_compute_instance" "foobar" { network_interface { network = "default" } - depends_on = [google_kms_crypto_key_iam_binding.crypto_key] + depends_on = [google_kms_crypto_key_iam_member.crypto_key] } `, context) diff --git a/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.erb b/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.erb index 5488cdf31c35..3eb94e373be8 100644 --- a/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.erb +++ b/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.erb @@ -642,7 +642,7 @@ resource "google_spanner_database" "database" { deletion_protection = false - depends_on = [google_kms_crypto_key_iam_binding.crypto-key-binding] + depends_on = [google_kms_crypto_key_iam_member.crypto-key-binding] } resource "google_kms_key_ring" "keyring" { @@ -658,14 +658,12 @@ resource "google_kms_crypto_key" "example-key" { rotation_period = "100000s" } -resource "google_kms_crypto_key_iam_binding" "crypto-key-binding" { +resource "google_kms_crypto_key_iam_member" "crypto-key-binding" { provider = google-beta crypto_key_id = google_kms_crypto_key.example-key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${google_project_service_identity.ck_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.ck_sa.email}" } data "google_project" "project" { From 414d6bee6501a5d143222e5412dcfef100e9cd61 Mon Sep 17 00:00:00 2001 From: bcreddy-gcp <123543489+bcreddy-gcp@users.noreply.github.com> Date: Tue, 12 Dec 2023 22:54:59 +0530 Subject: [PATCH 09/27] Label support for Google Managed Notebooks (#9625) --- mmv1/products/notebooks/Runtime.yaml | 9 +++++++++ .../terraform/examples/notebook_runtime_kernels.tf.erb | 3 +++ .../terraform/examples/notebook_runtime_script.tf.erb | 3 +++ 3 files changed, 15 insertions(+) diff --git a/mmv1/products/notebooks/Runtime.yaml b/mmv1/products/notebooks/Runtime.yaml index 721822b3e8e1..7657f51a0c95 100644 --- a/mmv1/products/notebooks/Runtime.yaml +++ b/mmv1/products/notebooks/Runtime.yaml @@ -569,3 +569,12 @@ properties: sessions stats. output: true output: true + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' + description: | + The labels to associate with this runtime. Label **keys** must + contain 1 to 63 characters, and must conform to [RFC 1035] + (https://www.ietf.org/rfc/rfc1035.txt). Label **values** may be + empty, but, if present, must contain 1 to 63 characters, and must + conform to [RFC 1035](https://www.ietf.org/rfc/rfc1035.txt). No + more than 32 labels can be associated with a cluster. diff --git a/mmv1/templates/terraform/examples/notebook_runtime_kernels.tf.erb b/mmv1/templates/terraform/examples/notebook_runtime_kernels.tf.erb index d97313a6bbff..1db5a97fe1b8 100644 --- a/mmv1/templates/terraform/examples/notebook_runtime_kernels.tf.erb +++ b/mmv1/templates/terraform/examples/notebook_runtime_kernels.tf.erb @@ -22,4 +22,7 @@ resource "google_notebooks_runtime" "<%= ctx[:primary_resource_id] %>" { } } } + labels = { + k = "val" + } } diff --git a/mmv1/templates/terraform/examples/notebook_runtime_script.tf.erb b/mmv1/templates/terraform/examples/notebook_runtime_script.tf.erb index d9320d924dbd..5dcb7e218896 100644 --- a/mmv1/templates/terraform/examples/notebook_runtime_script.tf.erb +++ b/mmv1/templates/terraform/examples/notebook_runtime_script.tf.erb @@ -19,4 +19,7 @@ resource "google_notebooks_runtime" "<%= ctx[:primary_resource_id] %>" { } } } + labels = { + k = "val" + } } From 1d1d8ed2a19c751c8fc14ef6e36b9bee54906568 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Tue, 12 Dec 2023 18:57:36 +0000 Subject: [PATCH 10/27] Add missing `depends_on` meta arguments to acceptance test config (#9623) --- .../resource_compute_instance_template_test.go.erb | 12 ++++++++++++ 1 file changed, 12 insertions(+) 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 01b6f1c19767..b7ce7bb72af7 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 @@ -3592,6 +3592,10 @@ resource "google_compute_snapshot" "snapshot" { kms_key_self_link = data.google_kms_crypto_key.key.id kms_key_service_account = google_service_account.test.email } + + depends_on = [ + google_kms_crypto_key_iam_member.crypto_key + ] } resource "google_compute_instance_template" "template" { @@ -3611,6 +3615,10 @@ resource "google_compute_instance_template" "template" { network_interface { network = "default" } + + depends_on = [ + google_kms_crypto_key_iam_member.crypto_key + ] } `, context) } @@ -3674,6 +3682,10 @@ resource "google_compute_instance_template" "template" { network_interface { network = "default" } + + depends_on = [ + google_kms_crypto_key_iam_member.crypto_key + ] } `, context) } From 6afde3f9effd7c1c7298108a856395f220421201 Mon Sep 17 00:00:00 2001 From: rahul2393 Date: Wed, 13 Dec 2023 00:58:29 +0530 Subject: [PATCH 11/27] feat(spanner): support defining autoscaling limit as nodes (#9606) --- mmv1/products/spanner/Instance.yaml | 32 +++++- .../encoders/spanner_instance_update.go.erb | 6 ++ .../spanner_instance_with_autoscaling.tf.erb | 7 +- .../spanner/resource_spanner_instance_test.go | 101 ++++++++++++++++++ 4 files changed, 143 insertions(+), 3 deletions(-) diff --git a/mmv1/products/spanner/Instance.yaml b/mmv1/products/spanner/Instance.yaml index 0a353ee85dd8..251e3ee20d17 100644 --- a/mmv1/products/spanner/Instance.yaml +++ b/mmv1/products/spanner/Instance.yaml @@ -180,19 +180,49 @@ properties: name: 'autoscalingLimits' description: | Defines scale in controls to reduce the risk of response latency - and outages due to abrupt scale-in events + and outages due to abrupt scale-in events. Users can define the minimum and + maximum compute capacity allocated to the instance, and the autoscaler will + only scale within that range. Users can either use nodes or processing + units to specify the limits, but should use the same unit to set both the + min_limit and max_limit. properties: - !ruby/object:Api::Type::Integer name: 'minProcessingUnits' description: | Specifies minimum number of processing units allocated to the instance. If set, this number should be multiples of 1000. + exactly_one_of: + - min_processing_units + - min_nodes - !ruby/object:Api::Type::Integer name: 'maxProcessingUnits' description: | Specifies maximum number of processing units allocated to the instance. If set, this number should be multiples of 1000 and be greater than or equal to min_processing_units. + exactly_one_of: + - max_processing_units + - max_nodes + - !ruby/object:Api::Type::Integer + name: 'minNodes' + description: | + Specifies number of nodes allocated to the instance. If set, this number + should be greater than or equal to 1. + exactly_one_of: + - min_processing_units + - min_nodes + required_with: + - max_nodes + - !ruby/object:Api::Type::Integer + name: 'maxNodes' + description: | + Specifies maximum number of nodes allocated to the instance. If set, this number + should be greater than or equal to min_nodes. + exactly_one_of: + - max_processing_units + - max_nodes + required_with: + - min_nodes - !ruby/object:Api::Type::NestedObject name: 'autoscalingTargets' description: | diff --git a/mmv1/templates/terraform/encoders/spanner_instance_update.go.erb b/mmv1/templates/terraform/encoders/spanner_instance_update.go.erb index 6c9cc875a3b9..bb917b112ad1 100644 --- a/mmv1/templates/terraform/encoders/spanner_instance_update.go.erb +++ b/mmv1/templates/terraform/encoders/spanner_instance_update.go.erb @@ -24,6 +24,12 @@ if d.HasChange("autoscaling_config.0.autoscaling_limits.0.max_processing_units") if d.HasChange("autoscaling_config.0.autoscaling_limits.0.min_processing_units") { updateMask = append(updateMask, "autoscalingConfig.autoscalingLimits.minProcessingUnits") } +if d.HasChange("autoscaling_config.0.autoscaling_limits.0.max_nodes") { + updateMask = append(updateMask, "autoscalingConfig.autoscalingLimits.maxNodes") +} +if d.HasChange("autoscaling_config.0.autoscaling_limits.0.min_nodes") { + updateMask = append(updateMask, "autoscalingConfig.autoscalingLimits.minNodes") +} if d.HasChange("autoscaling_config.0.autoscaling_targets.0.high_priority_cpu_utilization_percent") { updateMask = append(updateMask, "autoscalingConfig.autoscalingTargets.highPriorityCpuUtilizationPercent") } diff --git a/mmv1/templates/terraform/examples/spanner_instance_with_autoscaling.tf.erb b/mmv1/templates/terraform/examples/spanner_instance_with_autoscaling.tf.erb index 3830a71a70d8..aa541cff768d 100644 --- a/mmv1/templates/terraform/examples/spanner_instance_with_autoscaling.tf.erb +++ b/mmv1/templates/terraform/examples/spanner_instance_with_autoscaling.tf.erb @@ -3,8 +3,11 @@ resource "google_spanner_instance" "example" { display_name = "Test Spanner Instance" autoscaling_config { autoscaling_limits { - max_processing_units = 3000 - min_processing_units = 2000 + // Define the minimum and maximum compute capacity allocated to the instance + // Either use nodes or processing units to specify the limits, + // but should use the same unit to set both the min_limit and max_limit. + max_processing_units = 3000 // OR max_nodes = 3 + min_processing_units = 2000 // OR min_nodes = 2 } autoscaling_targets { high_priority_cpu_utilization_percent = 75 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 07d2e067bd19..562721abe6c7 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 @@ -203,6 +203,67 @@ func TestAccSpannerInstance_basicWithAutoscalingUsingProcessingUnitConfigUpdate( }) } +func TestAccSpannerInstance_basicWithAutoscalingUsingNodeConfig(t *testing.T) { + t.Parallel() + + displayName := fmt.Sprintf("spanner-test-%s-dname", acctest.RandString(t, 10)) + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckSpannerInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccSpannerInstance_basicWithAutoscalerConfigUsingNodesAsConfigs(displayName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("google_spanner_instance.basic", "state"), + ), + }, + { + ResourceName: "google_spanner_instance.basic", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccSpannerInstance_basicWithAutoscalingUsingNodeConfigUpdate(t *testing.T) { + t.Parallel() + + displayName := fmt.Sprintf("spanner-test-%s-dname", acctest.RandString(t, 10)) + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckSpannerInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccSpannerInstance_basicWithAutoscalerConfigUsingNodesAsConfigsUpdate(displayName, 1, 2, 65, 95), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("google_spanner_instance.basic", "state"), + ), + }, + { + ResourceName: "google_spanner_instance.basic", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccSpannerInstance_basicWithAutoscalerConfigUsingNodesAsConfigsUpdate(displayName, 2, 3, 75, 90), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("google_spanner_instance.basic", "state"), + ), + }, + { + ResourceName: "google_spanner_instance.basic", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + }, + }) +} + func testAccSpannerInstance_basic(name string) string { return fmt.Sprintf(` resource "google_spanner_instance" "basic" { @@ -304,3 +365,43 @@ resource "google_spanner_instance" "basic" { } `, name, name, maxProcessingUnits, minProcessingUnits, cupUtilizationPercent, storageUtilizationPercent) } + +func testAccSpannerInstance_basicWithAutoscalerConfigUsingNodesAsConfigs(name string) string { + return fmt.Sprintf(` +resource "google_spanner_instance" "basic" { + name = "%s" + config = "regional-us-central1" + display_name = "%s" + autoscaling_config { + autoscaling_limits { + max_nodes = 2 + min_nodes = 1 + } + autoscaling_targets { + high_priority_cpu_utilization_percent = 65 + storage_utilization_percent = 95 + } + } +} +`, name, name) +} + +func testAccSpannerInstance_basicWithAutoscalerConfigUsingNodesAsConfigsUpdate(name string, minNodes, maxNodes, cupUtilizationPercent, storageUtilizationPercent int) string { + return fmt.Sprintf(` +resource "google_spanner_instance" "basic" { + name = "%s" + config = "regional-us-central1" + display_name = "%s" + autoscaling_config { + autoscaling_limits { + max_nodes = %v + min_nodes = %v + } + autoscaling_targets { + high_priority_cpu_utilization_percent = %v + storage_utilization_percent = %v + } + } +} +`, name, name, maxNodes, minNodes, cupUtilizationPercent, storageUtilizationPercent) +} From de7d39b50c5d9894e25770a457eb9ab2c2f96eaf Mon Sep 17 00:00:00 2001 From: sahsagar-google <126025352+sahsagar-google@users.noreply.github.com> Date: Tue, 12 Dec 2023 15:45:21 -0800 Subject: [PATCH 12/27] The version field should be under configmanagement instead of under oci (#9587) * Adding Terraform resources for Tenancy APIs in GKEHub * Segregating MembershipBinding and MembershipRBACRoleBinding to keep things simpler in the review * Fixing the docu URIs * Adding TF support for Tenancy API for Membership Binding * Adding dependent membership binding to the same commit chain * Making Scope un-updatable and replacing hard coded project number with the one from test env * Making Scope RRBAC updatable * Making Namespace immutable * Adding update test cases * Removing all memberships field from Scope since it is no longer supported * Removing all_memberships field for Scope from all test cases * Making naming in examples consistent across Tenancy APIs documentation * Update mmv1/templates/terraform/examples/gkehub_membership_binding_basic.tf.erb Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> * Update mmv1/templates/terraform/examples/gkehub_membership_binding_basic.tf.erb Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> * Update mmv1/templates/terraform/examples/gkehub_membership_rbac_role_binding_basic.tf.erb Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> * Fixing typo in the resource name * Adding state migrations for Membership * Updating the feature_membership documentation with the current resource state. Adding membership_location field to the doc * Fixing the version field to be directly under configmanagement instead of under the oci field * Adding tests for the field version * Changing version fields value to test upgradation --------- Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> --- mmv1/products/gkehub2/Feature.yaml | 6 +++--- .../services/gkehub2/resource_gke_hub_feature_test.go.erb | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/mmv1/products/gkehub2/Feature.yaml b/mmv1/products/gkehub2/Feature.yaml index 67be3b1efc02..b3968b337586 100644 --- a/mmv1/products/gkehub2/Feature.yaml +++ b/mmv1/products/gkehub2/Feature.yaml @@ -215,6 +215,9 @@ properties: name: configmanagement description: Config Management spec properties: + - !ruby/object:Api::Type::String + name: version + description: 'Version of ACM installed' - !ruby/object:Api::Type::NestedObject name: configSync description: 'ConfigSync configuration for the cluster' @@ -271,9 +274,6 @@ properties: - !ruby/object:Api::Type::String name: syncWaitSecs description: 'Period in seconds between consecutive syncs. Default: 15' - - !ruby/object:Api::Type::String - name: version - description: 'Version of ACM installed' - !ruby/object:Api::Type::NestedObject name: policycontroller description: Policy Controller spec 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 f2c14b2d223f..5af1d572cfd7 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 @@ -460,6 +460,7 @@ resource "google_gke_hub_feature" "feature" { location = "global" fleet_default_member_config { configmanagement { + version = "1.16.0" config_sync { source_format = "hierarchy" git { @@ -486,6 +487,7 @@ resource "google_gke_hub_feature" "feature" { location = "global" fleet_default_member_config { configmanagement { + version = "1.16.1" config_sync { source_format = "unstructured" oci { From 3bacb448e960f8c56905e7012311953e920310e9 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Wed, 13 Dec 2023 10:00:17 -0800 Subject: [PATCH 13/27] Fix the out of boundary error (#9628) --- .../resource_monitoring_dashboard.go | 2 +- .../resource_monitoring_dashboard_test.go | 55 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) 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 458b5cfbb1c8..0da5fbbac8b1 100644 --- a/mmv1/third_party/terraform/services/monitoring/resource_monitoring_dashboard.go +++ b/mmv1/third_party/terraform/services/monitoring/resource_monitoring_dashboard.go @@ -31,7 +31,7 @@ func removeComputedKeys(old map[string]interface{}, new map[string]interface{}) if reflect.ValueOf(v).Kind() == reflect.Slice { for i, j := range v.([]interface{}) { - if reflect.ValueOf(j).Kind() == reflect.Map { + if reflect.ValueOf(j).Kind() == reflect.Map && len(new[k].([]interface{})) > i { old[k].([]interface{})[i] = removeComputedKeys(j.(map[string]interface{}), new[k].([]interface{})[i].(map[string]interface{})) } } 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 5c1a5d28afd7..0729ce06c1ed 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 @@ -117,6 +117,15 @@ func TestAccMonitoringDashboard_update(t *testing.T) { ImportStateVerify: true, ImportStateVerifyIgnore: []string{"project"}, }, + { + Config: testAccMonitoringDashboard_gridLayoutUpdate(), + }, + { + ResourceName: "google_monitoring_dashboard.dashboard", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"project"}, + }, }, }) } @@ -242,6 +251,52 @@ EOF `) } +func testAccMonitoringDashboard_gridLayoutUpdate() string { + return fmt.Sprintf(` +resource "google_monitoring_dashboard" "dashboard" { + dashboard_json = < Date: Wed, 13 Dec 2023 19:52:42 +0000 Subject: [PATCH 14/27] Make MMv1 control .go-version files in TPG and TPGB (#9636) * Make .go-version file be controlled by Magic Modules * Change .go-version's value so PR automation shows effects of last commit * Move .go-version copying responsibiilty to compile~copy.yaml * Revert cb62866 --- mmv1/provider/terraform/common~copy.yaml | 1 + mmv1/third_party/terraform/.go-version | 1 + 2 files changed, 2 insertions(+) create mode 100644 mmv1/third_party/terraform/.go-version diff --git a/mmv1/provider/terraform/common~copy.yaml b/mmv1/provider/terraform/common~copy.yaml index 4953b9ccca91..7a61c213c988 100644 --- a/mmv1/provider/terraform/common~copy.yaml +++ b/mmv1/provider/terraform/common~copy.yaml @@ -154,3 +154,4 @@ '.teamcity/Makefile': 'third_party/terraform/.teamcity/Makefile' 'version/version.go': 'third_party/terraform/version/version.go' 'go.sum': 'third_party/terraform/go.sum' +'.go-version': 'third_party/terraform/.go-version' diff --git a/mmv1/third_party/terraform/.go-version b/mmv1/third_party/terraform/.go-version new file mode 100644 index 000000000000..5fb5a6b4f547 --- /dev/null +++ b/mmv1/third_party/terraform/.go-version @@ -0,0 +1 @@ +1.20 From 06405ce9d51d2ddbeeec92275ca1283df344d520 Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Wed, 13 Dec 2023 12:53:32 -0800 Subject: [PATCH 15/27] Launch generate comment magician command (#9611) * Use magician for generate comment * Fix formatting of breaking changes * Keep diff string empty * Add missing newline * Add copyright notices * Add missing space * Revert changes from running generate-comment --- .ci/gcb-generate-diffs-new.yml | 6 ++--- .ci/magician/cloudbuild/build_trigger.go | 15 +++++++++++ .ci/magician/cloudbuild/community.go | 15 +++++++++++ .ci/magician/cloudbuild/constants.go | 15 +++++++++++ .ci/magician/cloudbuild/init.go | 15 +++++++++++ .ci/magician/cmd/community_checker.go | 16 +++++++++-- .ci/magician/cmd/community_checker_test.go | 15 +++++++++++ .ci/magician/cmd/generate_comment.go | 27 +++++++++++++++---- .ci/magician/cmd/generate_comment_test.go | 15 +++++++++++ .ci/magician/cmd/interfaces.go | 15 +++++++++++ .ci/magician/cmd/membership_checker.go | 16 +++++++++-- .ci/magician/cmd/membership_checker_test.go | 15 +++++++++++ .ci/magician/cmd/mock_cloudbuild_test.go | 15 +++++++++++ .ci/magician/cmd/mock_github_test.go | 15 +++++++++++ .ci/magician/cmd/mock_runner_test.go | 15 +++++++++++ .ci/magician/cmd/root.go | 16 +++++++++-- .ci/magician/cmd/test_tgc.go | 15 +++++++++++ .ci/magician/cmd/test_tgc_test.go | 15 +++++++++++ .ci/magician/cmd/test_tpg.go | 15 +++++++++++ .ci/magician/cmd/test_tpg_test.go | 15 +++++++++++ .ci/magician/exec/runner.go | 15 +++++++++++ .ci/magician/github/get.go | 15 +++++++++++ .ci/magician/github/init.go | 15 +++++++++++ .ci/magician/github/membership.go | 15 +++++++++++ .ci/magician/github/membership_test.go | 15 +++++++++++ .ci/magician/github/reviewer_assignment.go | 15 +++++++++++ .../github/reviewer_assignment_test.go | 15 +++++++++++ .ci/magician/github/set.go | 15 +++++++++++ .ci/magician/main.go | 16 +++++++++-- .ci/magician/utility/utils.go | 15 +++++++++++ .ci/magician/utility/utils_test.go | 15 +++++++++++ 31 files changed, 456 insertions(+), 16 deletions(-) diff --git a/.ci/gcb-generate-diffs-new.yml b/.ci/gcb-generate-diffs-new.yml index 5beac1aa4a95..57aa9241c48a 100644 --- a/.ci/gcb-generate-diffs-new.yml +++ b/.ci/gcb-generate-diffs-new.yml @@ -169,17 +169,17 @@ steps: - $_PR_NUMBER - name: 'gcr.io/graphite-docker-images/go-plus' - entrypoint: '/workspace/.ci/scripts/go-plus/github-differ/generate_comment.sh' + entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' id: diff secretEnv: ["GITHUB_TOKEN"] + args: + - 'generate-comment' env: - BUILD_ID=$BUILD_ID - PROJECT_ID=$PROJECT_ID - BUILD_STEP=17 - COMMIT_SHA=$COMMIT_SHA - PR_NUMBER=$_PR_NUMBER - args: - - $_PR_NUMBER - name: 'gcr.io/graphite-docker-images/go-plus' id: tgc-test diff --git a/.ci/magician/cloudbuild/build_trigger.go b/.ci/magician/cloudbuild/build_trigger.go index 676e5a5b64a6..f776af1222cd 100644 --- a/.ci/magician/cloudbuild/build_trigger.go +++ b/.ci/magician/cloudbuild/build_trigger.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package cloudbuild import ( diff --git a/.ci/magician/cloudbuild/community.go b/.ci/magician/cloudbuild/community.go index 09b8d2d6345a..4e7a84091778 100644 --- a/.ci/magician/cloudbuild/community.go +++ b/.ci/magician/cloudbuild/community.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package cloudbuild import ( diff --git a/.ci/magician/cloudbuild/constants.go b/.ci/magician/cloudbuild/constants.go index a64c5fce7c61..1286bd2a54b2 100644 --- a/.ci/magician/cloudbuild/constants.go +++ b/.ci/magician/cloudbuild/constants.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package cloudbuild const PROJECT_ID = "graphite-docker-images" diff --git a/.ci/magician/cloudbuild/init.go b/.ci/magician/cloudbuild/init.go index 52f65318aa0c..908351d741d3 100644 --- a/.ci/magician/cloudbuild/init.go +++ b/.ci/magician/cloudbuild/init.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package cloudbuild type Client struct { diff --git a/.ci/magician/cmd/community_checker.go b/.ci/magician/cmd/community_checker.go index 3630bbb323f1..f968ca74abff 100644 --- a/.ci/magician/cmd/community_checker.go +++ b/.ci/magician/cmd/community_checker.go @@ -1,6 +1,18 @@ /* -Copyright © 2023 NAME HERE -*/ +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package cmd import ( diff --git a/.ci/magician/cmd/community_checker_test.go b/.ci/magician/cmd/community_checker_test.go index f429a7910cb1..364524cc2a52 100644 --- a/.ci/magician/cmd/community_checker_test.go +++ b/.ci/magician/cmd/community_checker_test.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package cmd import ( diff --git a/.ci/magician/cmd/generate_comment.go b/.ci/magician/cmd/generate_comment.go index 2d2aa39f3b73..b6d457382111 100644 --- a/.ci/magician/cmd/generate_comment.go +++ b/.ci/magician/cmd/generate_comment.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package cmd import ( @@ -124,7 +139,9 @@ func execGenerateComment(buildID, projectID, buildStep, commit, prNumber, github os.Exit(1) } } - diffs += "\n" + repoDiffs + if repoDiffs != "" { + diffs += "\n" + repoDiffs + } } var showBreakingChangesFailed bool @@ -156,7 +173,7 @@ func execGenerateComment(buildID, projectID, buildStep, commit, prNumber, github fmt.Println("Error computing TPG breaking changes: ", err) showBreakingChangesFailed = true } - versionedBreakingChanges[repo.Version] = output + versionedBreakingChanges[repo.Version] = strings.TrimSuffix(output, "\n") err = addLabels(diffProcessorPath, githubToken, prNumber, r) if err != nil { fmt.Println("Error adding TPG labels to PR: ", err) @@ -209,7 +226,7 @@ The breaking change detector crashed during execution. This is usually due to th if diffs == "" { message += "## Diff report\nYour PR hasn't generated any diffs, but I'll let you know if a future commit does." } else { - message += "## Diff report\nYour PR generated some diffs in downstreams - here they are.\n" + diffs + message += "## Diff report\nYour PR generated some diffs in downstreams - here they are.\n" + diffs + "\n" if missingTests != "" { message += "\n" + missingTests + "\n" } @@ -344,14 +361,14 @@ func combineBreakingChanges(tpgBreaking, tpgbBreaking string) string { allMessages = append(tpgUnique, tpgbMessages...) } if len(allMessages) > 0 { - return `Breaking Change(s) Detected + return `## Breaking Change(s) Detected The following breaking change(s) were detected within your pull request. * ` + strings.Join(allMessages, "\n* ") + ` If you believe this detection to be incorrect please raise the concern with your reviewer. If you intend to make this change you will need to wait for a [major release](https://www.terraform.io/plugin/sdkv2/best-practices/versioning#example-major-number-increments) window. -An ` + "`override-breaking-change`" + `label can be added to allow merging. +An ` + "`override-breaking-change`" + ` label can be added to allow merging. ` } return "" diff --git a/.ci/magician/cmd/generate_comment_test.go b/.ci/magician/cmd/generate_comment_test.go index b05acfa4f8e3..88b0a28f38d8 100644 --- a/.ci/magician/cmd/generate_comment_test.go +++ b/.ci/magician/cmd/generate_comment_test.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package cmd import ( diff --git a/.ci/magician/cmd/interfaces.go b/.ci/magician/cmd/interfaces.go index ef99df1723bd..a03bce062439 100644 --- a/.ci/magician/cmd/interfaces.go +++ b/.ci/magician/cmd/interfaces.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package cmd import ( diff --git a/.ci/magician/cmd/membership_checker.go b/.ci/magician/cmd/membership_checker.go index b5fcd8b85160..8b3eee525035 100644 --- a/.ci/magician/cmd/membership_checker.go +++ b/.ci/magician/cmd/membership_checker.go @@ -1,6 +1,18 @@ /* -Copyright © 2023 NAME HERE -*/ +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package cmd import ( diff --git a/.ci/magician/cmd/membership_checker_test.go b/.ci/magician/cmd/membership_checker_test.go index 184c9ec5d8eb..a71fa110164c 100644 --- a/.ci/magician/cmd/membership_checker_test.go +++ b/.ci/magician/cmd/membership_checker_test.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package cmd import ( diff --git a/.ci/magician/cmd/mock_cloudbuild_test.go b/.ci/magician/cmd/mock_cloudbuild_test.go index f4da97a06771..e75c76949f06 100644 --- a/.ci/magician/cmd/mock_cloudbuild_test.go +++ b/.ci/magician/cmd/mock_cloudbuild_test.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package cmd type mockCloudBuild struct { diff --git a/.ci/magician/cmd/mock_github_test.go b/.ci/magician/cmd/mock_github_test.go index 49bd98b624bb..e017700c41ad 100644 --- a/.ci/magician/cmd/mock_github_test.go +++ b/.ci/magician/cmd/mock_github_test.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package cmd import "magician/github" diff --git a/.ci/magician/cmd/mock_runner_test.go b/.ci/magician/cmd/mock_runner_test.go index 16867dca123a..6743e3a1e6c5 100644 --- a/.ci/magician/cmd/mock_runner_test.go +++ b/.ci/magician/cmd/mock_runner_test.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package cmd import ( diff --git a/.ci/magician/cmd/root.go b/.ci/magician/cmd/root.go index b19c57e6ea24..f39a0e69e0a2 100644 --- a/.ci/magician/cmd/root.go +++ b/.ci/magician/cmd/root.go @@ -1,6 +1,18 @@ /* -Copyright © 2023 NAME HERE -*/ +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package cmd import ( diff --git a/.ci/magician/cmd/test_tgc.go b/.ci/magician/cmd/test_tgc.go index a5610daaedb9..9f0edf2f29bf 100644 --- a/.ci/magician/cmd/test_tgc.go +++ b/.ci/magician/cmd/test_tgc.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package cmd import ( diff --git a/.ci/magician/cmd/test_tgc_test.go b/.ci/magician/cmd/test_tgc_test.go index f9004ddf0e8a..daf4b94409fe 100644 --- a/.ci/magician/cmd/test_tgc_test.go +++ b/.ci/magician/cmd/test_tgc_test.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package cmd import ( diff --git a/.ci/magician/cmd/test_tpg.go b/.ci/magician/cmd/test_tpg.go index 75398c7a4281..c8923ad42106 100644 --- a/.ci/magician/cmd/test_tpg.go +++ b/.ci/magician/cmd/test_tpg.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package cmd import ( diff --git a/.ci/magician/cmd/test_tpg_test.go b/.ci/magician/cmd/test_tpg_test.go index ad77c7596f21..d1ca8882471d 100644 --- a/.ci/magician/cmd/test_tpg_test.go +++ b/.ci/magician/cmd/test_tpg_test.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package cmd import ( diff --git a/.ci/magician/exec/runner.go b/.ci/magician/exec/runner.go index 3bc21e23116d..5d746f7a963d 100644 --- a/.ci/magician/exec/runner.go +++ b/.ci/magician/exec/runner.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package exec import ( diff --git a/.ci/magician/github/get.go b/.ci/magician/github/get.go index 30df68d4db4a..9b1dbc7acdd8 100644 --- a/.ci/magician/github/get.go +++ b/.ci/magician/github/get.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package github import ( diff --git a/.ci/magician/github/init.go b/.ci/magician/github/init.go index ff63ae2c1ef5..a931ad5efca5 100644 --- a/.ci/magician/github/init.go +++ b/.ci/magician/github/init.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package github import ( diff --git a/.ci/magician/github/membership.go b/.ci/magician/github/membership.go index adac576f2f68..21aaea6f459b 100644 --- a/.ci/magician/github/membership.go +++ b/.ci/magician/github/membership.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package github import ( diff --git a/.ci/magician/github/membership_test.go b/.ci/magician/github/membership_test.go index 1f2264bdf3c2..88598107012b 100644 --- a/.ci/magician/github/membership_test.go +++ b/.ci/magician/github/membership_test.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package github import ( diff --git a/.ci/magician/github/reviewer_assignment.go b/.ci/magician/github/reviewer_assignment.go index 820bb76a4f81..b57a0ae311ce 100644 --- a/.ci/magician/github/reviewer_assignment.go +++ b/.ci/magician/github/reviewer_assignment.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package github import ( diff --git a/.ci/magician/github/reviewer_assignment_test.go b/.ci/magician/github/reviewer_assignment_test.go index 779d308cfb22..6514a8dd5b67 100644 --- a/.ci/magician/github/reviewer_assignment_test.go +++ b/.ci/magician/github/reviewer_assignment_test.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package github import ( diff --git a/.ci/magician/github/set.go b/.ci/magician/github/set.go index e1575a4e505c..a5d4adffe53f 100644 --- a/.ci/magician/github/set.go +++ b/.ci/magician/github/set.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package github import ( diff --git a/.ci/magician/main.go b/.ci/magician/main.go index 41c664080c04..a018e0eaee5c 100644 --- a/.ci/magician/main.go +++ b/.ci/magician/main.go @@ -1,6 +1,18 @@ /* -Copyright © 2023 NAME HERE -*/ +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package main import "magician/cmd" diff --git a/.ci/magician/utility/utils.go b/.ci/magician/utility/utils.go index 6bc778f97e3f..cdec5a6d0fc2 100644 --- a/.ci/magician/utility/utils.go +++ b/.ci/magician/utility/utils.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package utility import ( diff --git a/.ci/magician/utility/utils_test.go b/.ci/magician/utility/utils_test.go index 2f82538ab7c1..5bc47df94996 100644 --- a/.ci/magician/utility/utils_test.go +++ b/.ci/magician/utility/utils_test.go @@ -1,3 +1,18 @@ +/* +* Copyright 2023 Google LLC. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ package utility import ( From f8feaf07fdeff43bd80832c47ec15f645d7228a4 Mon Sep 17 00:00:00 2001 From: Matt Cary <34742400+mattcary@users.noreply.github.com> Date: Wed, 13 Dec 2023 13:57:04 -0800 Subject: [PATCH 16/27] No pdcsi disable on create (#9557) --- .../resource_container_cluster.go.erb | 48 +++++++++++++++---- .../resource_container_cluster_test.go.erb | 2 +- 2 files changed, 41 insertions(+), 9 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 8b9fa8414480..d73fb6bf1d99 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 @@ -2381,11 +2381,28 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er cluster.SecurityPostureConfig = expandSecurityPostureConfig(v) } + needUpdateAfterCreate := false + // 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. enablePrivateEndpointPSCCluster := isEnablePrivateEndpointPSCCluster(cluster) if enablePrivateEndpointPSCCluster { cluster.PrivateClusterConfig.EnablePrivateEndpoint = false + needUpdateAfterCreate = true + } + + enablePDCSI := isEnablePDCSI(cluster); + if !enablePDCSI { + // GcePersistentDiskCsiDriver cannot be disabled at cluster create, only on cluster update. Ignore on create then update after creation. + // If pdcsi is disabled, the config should be defined. But we will be paranoid and double-check. + needUpdateAfterCreate = true + if cluster.AddonsConfig == nil { + cluster.AddonsConfig = &container.AddonsConfig{} + } + if cluster.AddonsConfig.GcePersistentDiskCsiDriverConfig == nil { + cluster.AddonsConfig.GcePersistentDiskCsiDriverConfig = &container.GcePersistentDiskCsiDriverConfig{} + } + cluster.AddonsConfig.GcePersistentDiskCsiDriverConfig.Enabled = true } req := &container.CreateClusterRequest{ @@ -2472,14 +2489,22 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er } } - if enablePrivateEndpointPSCCluster { + if needUpdateAfterCreate { name := containerClusterFullName(project, location, clusterName) - req := &container.UpdateClusterRequest{ - Update: &container.ClusterUpdate{ - DesiredEnablePrivateEndpoint: true, - ForceSendFields: []string{"DesiredEnablePrivateEndpoint"}, - }, + update := &container.ClusterUpdate{} + if enablePrivateEndpointPSCCluster { + update.DesiredEnablePrivateEndpoint = true + update.ForceSendFields = append(update.ForceSendFields, "DesiredEnablePrivateEndpoint"); + } + if !enablePDCSI { + update.DesiredAddonsConfig = &container.AddonsConfig{ + GcePersistentDiskCsiDriverConfig: &container.GcePersistentDiskCsiDriverConfig{ + Enabled: false, + }, + } + update.ForceSendFields = append(update.ForceSendFields, "DesiredAddonsConfig.GcePersistentDiskCsiDriverConfig.Enabled"); } + req := &container.UpdateClusterRequest{Update: update} err = transport_tpg.Retry(transport_tpg.RetryOptions{ RetryFunc: func() error { @@ -2492,12 +2517,12 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er }, }) if err != nil { - return errwrap.Wrapf("Error updating enable private endpoint: {{err}}", err) + return errwrap.Wrapf(fmt.Sprintf("Error updating cluster for %v: {{err}}", update.ForceSendFields), err) } err = ContainerOperationWait(config, op, project, location, "updating enable private endpoint", userAgent, d.Timeout(schema.TimeoutCreate)) if err != nil { - return errwrap.Wrapf("Error while waiting to enable private endpoint: {{err}}", err) + return errwrap.Wrapf(fmt.Sprintf("Error while waiting on cluster update for %v: {{err}}", update.ForceSendFields), err) } } @@ -4946,6 +4971,13 @@ func isEnablePrivateEndpointPSCCluster(cluster *container.Cluster) bool { return false } +func isEnablePDCSI(cluster *container.Cluster) bool { + if cluster.AddonsConfig == nil || cluster.AddonsConfig.GcePersistentDiskCsiDriverConfig == nil { + return true; // PDCSI is enabled by default. + } + return cluster.AddonsConfig.GcePersistentDiskCsiDriverConfig.Enabled +} + func expandPrivateClusterConfig(configured interface{}) *container.PrivateClusterConfig { l := configured.([]interface{}) if len(l) == 0 { 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 2428c885beef..34f0aa301a43 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 @@ -127,7 +127,6 @@ func TestAccContainerCluster_misc(t *testing.T) { } func TestAccContainerCluster_withAddons(t *testing.T) { - t.Skipf("Skipping test %s due to https://github.com/hashicorp/terraform-provider-google/issues/16114", t.Name()) t.Parallel() clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) @@ -4803,6 +4802,7 @@ resource "google_container_cluster" "primary" { enabled = true } <% end -%> + } deletion_protection = false network = "%s" subnetwork = "%s" From daa26f918c289b2fbf73b36d4028e5d27ac4328e Mon Sep 17 00:00:00 2001 From: sunchengxuanivy <39369372+sunchengxuanivy@users.noreply.github.com> Date: Fri, 15 Dec 2023 01:32:37 +0800 Subject: [PATCH 17/27] add support for auxiliary_node_groups in google_dataproc_cluster (#9484) --- .../dataproc/resource_dataproc_cluster.go | 270 ++++++++++++++++++ .../resource_dataproc_cluster_test.go.erb | 98 +++++++ .../docs/r/dataproc_cluster.html.markdown | 73 +++++ 3 files changed, 441 insertions(+) diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster.go b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster.go index 210e77b9b791..8636606f219b 100644 --- a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster.go +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster.go @@ -113,6 +113,7 @@ var ( "cluster_config.0.lifecycle_config", "cluster_config.0.endpoint_config", "cluster_config.0.dataproc_metric_config", + "cluster_config.0.auxiliary_node_groups", } ) @@ -1507,6 +1508,7 @@ by Dataproc`, "dataproc_metric_config": { Type: schema.TypeList, Optional: true, + Computed: true, MaxItems: 1, Description: `The config for Dataproc metrics.`, AtLeastOneOf: clusterConfigKeys, @@ -1521,6 +1523,129 @@ by Dataproc`, }, }, }, + "auxiliary_node_groups": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Description: `The node group settings.`, + AtLeastOneOf: clusterConfigKeys, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "node_group": { + Required: true, + Description: `Node group configuration.`, + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Description: `The Node group resource name.`, + Type: schema.TypeString, + Computed: true, + }, + "roles": { + Type: schema.TypeList, + Description: `Node group roles.`, + Required: true, + ForceNew: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{"ROLE_UNSPECIFIED", "DRIVER"}, false), + }, + }, + "node_group_config": { + Description: `The node group instance group configuration.`, + Optional: true, + Computed: true, + MaxItems: 1, + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "num_instances": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Computed: true, + Description: `Specifies the number of auxiliary nodes to create. If not specified, GCP will default to a predetermined computed value.`, + }, + "machine_type": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: `The name of a Google Compute Engine machine type to create for the master`, + }, + "min_cpu_platform": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: `The name of a minimum generation of CPU family for the auxiliary node group. If not specified, GCP will default to a predetermined computed value for each zone.`, + }, + "disk_config": { + + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Disk Config`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "num_local_ssds": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + Description: `The amount of local SSD disks that will be attached to each master cluster node. Defaults to 0.`, + ForceNew: true, + }, + + "boot_disk_size_gb": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + Description: `Size of the primary disk attached to each node, specified in GB. The primary disk contains the boot volume and system libraries, and 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.`, + ForceNew: true, + ValidateFunc: validation.IntAtLeast(10), + }, + + "boot_disk_type": { + Type: schema.TypeString, + Optional: true, + Description: `The disk type of the primary disk attached to each node. Such as "pd-ssd" or "pd-standard". Defaults to "pd-standard".`, + ForceNew: true, + Default: "pd-standard", + }, + }, + }, + }, + "accelerators": { + Type: schema.TypeSet, + Optional: true, + ForceNew: true, + Elem: acceleratorsSchema(), + Description: `The Compute Engine accelerator (GPU) configuration for these instances. Can be specified multiple times.`, + }, + "instance_names": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `List of auxiliary node group instance names which have been assigned to the cluster.`, + }, + }, + }, + }, + }, + }, + }, + "node_group_id": { + Computed: true, + Optional: true, + ForceNew: true, + Type: schema.TypeString, + Description: `A node group ID. Generated if not specified. The ID must contain only letters (a-z, A-Z), numbers (0-9), underscores (_), and hyphens (-). Cannot begin or end with underscore or hyphen. Must consist of from 3 to 33 characters.`, + }, + }, + }, + }, }, }, }, @@ -1893,9 +2018,89 @@ func expandClusterConfig(d *schema.ResourceData, config *transport_tpg.Config) ( log.Println("[INFO] got preemptible worker config") conf.SecondaryWorkerConfig = expandPreemptibleInstanceGroupConfig(cfg) } + + if v, ok := d.GetOk("cluster_config.0.auxiliary_node_groups"); ok { + log.Println("[INFO] got auxiliary node group config") + conf.AuxiliaryNodeGroups = expandAuxiliaryNodeGroupsConfig(v) + } return conf, nil } +func expandAuxiliaryNodeGroupsConfig(v interface{}) []*dataproc.AuxiliaryNodeGroup { + auxiliaryNodeGroupsList := v.([]interface{}) + + auxiliaryNodeGroups := []*dataproc.AuxiliaryNodeGroup{} + for _, v1 := range auxiliaryNodeGroupsList { + auxiliaryNodeGroupItem := v1.(map[string]interface{}) + auxiliaryNodeGroup := &dataproc.AuxiliaryNodeGroup{ + NodeGroup: expandNodeGroup(auxiliaryNodeGroupItem["node_group"].([]interface{})[0].(map[string]interface{})), + } + if x, ok := auxiliaryNodeGroupItem["node_group_id"]; ok { + auxiliaryNodeGroup.NodeGroupId = x.(string) + } + auxiliaryNodeGroups = append(auxiliaryNodeGroups, auxiliaryNodeGroup) + } + + return auxiliaryNodeGroups +} + +func expandNodeGroup(cfg map[string]interface{}) *dataproc.NodeGroup { + conf := &dataproc.NodeGroup{} + roles := []string{} + roleList := cfg["roles"] + for _, v1 := range roleList.([]interface{}) { + roles = append(roles, v1.(string)) + } + conf.Roles = roles + + if v, ok := cfg["name"]; ok { + conf.Name = v.(string) + } + + if v, ok := cfg["node_group_config"]; ok { + ng := v.([]interface{}) + if len(ng) > 0 { + conf.NodeGroupConfig = expandNodeGroupConfig(v.([]interface{})[0].(map[string]interface{})) + } + } + return conf +} + +func expandNodeGroupConfig(cfg map[string]interface{}) *dataproc.InstanceGroupConfig { + icg := &dataproc.InstanceGroupConfig{} + + if v, ok := cfg["num_instances"]; ok { + icg.NumInstances = int64(v.(int)) + } + if v, ok := cfg["machine_type"]; ok { + icg.MachineTypeUri = tpgresource.GetResourceNameFromSelfLink(v.(string)) + } + if v, ok := cfg["min_cpu_platform"]; ok { + icg.MinCpuPlatform = v.(string) + } + + if dc, ok := cfg["disk_config"]; ok { + d := dc.([]interface{}) + if len(d) > 0 { + dcfg := d[0].(map[string]interface{}) + icg.DiskConfig = &dataproc.DiskConfig{} + + if v, ok := dcfg["boot_disk_size_gb"]; ok { + icg.DiskConfig.BootDiskSizeGb = int64(v.(int)) + } + if v, ok := dcfg["num_local_ssds"]; ok { + icg.DiskConfig.NumLocalSsds = int64(v.(int)) + } + if v, ok := dcfg["boot_disk_type"]; ok { + icg.DiskConfig.BootDiskType = v.(string) + } + } + } + + icg.Accelerators = expandAccelerators(cfg["accelerators"].(*schema.Set).List()) + return icg +} + func expandGceClusterConfig(d *schema.ResourceData, config *transport_tpg.Config) (*dataproc.GceClusterConfig, error) { conf := &dataproc.GceClusterConfig{} @@ -2621,6 +2826,15 @@ func flattenClusterConfig(d *schema.ResourceData, cfg *dataproc.ClusterConfig) ( } data["initialization_action"] = val } + + if len(cfg.AuxiliaryNodeGroups) > 0 { + val, err := flattenAuxiliaryNodeGroups(cfg.AuxiliaryNodeGroups) + if err != nil { + return nil, err + } + data["auxiliary_node_groups"] = val + } + return []map[string]interface{}{data}, nil } @@ -2785,6 +2999,62 @@ func flattenInitializationActions(nia []*dataproc.NodeInitializationAction) ([]m } +func flattenAuxiliaryNodeGroups(ang []*dataproc.AuxiliaryNodeGroup) ([]map[string]interface{}, error) { + + auxiliaryNodeGroups := []map[string]interface{}{} + for _, v := range ang { + nodeGroup := map[string]interface{}{ + "node_group": flatternNodeGroup(v.NodeGroup), + } + if len(v.NodeGroupId) > 0 { + nodeGroup["node_group_id"] = v.NodeGroupId + } + + auxiliaryNodeGroups = append(auxiliaryNodeGroups, nodeGroup) + } + return auxiliaryNodeGroups, nil + +} + +func flatternNodeGroup(ng *dataproc.NodeGroup) []map[string]interface{} { + nodeGroup := map[string]interface{}{ + "roles": ng.Roles, + } + + if ng.Name != "" { + nodeGroup["name"] = ng.Name + } + + if ng.NodeGroupConfig != nil { + nodeGroup["node_group_config"] = flattenNodeGroupConfig(ng.NodeGroupConfig) + } + + return []map[string]interface{}{nodeGroup} + +} + +func flattenNodeGroupConfig(icg *dataproc.InstanceGroupConfig) []map[string]interface{} { + disk := map[string]interface{}{} + data := map[string]interface{}{} + + if icg != nil { + data["num_instances"] = icg.NumInstances + data["machine_type"] = tpgresource.GetResourceNameFromSelfLink(icg.MachineTypeUri) + data["min_cpu_platform"] = icg.MinCpuPlatform + data["instance_names"] = icg.InstanceNames + if icg.DiskConfig != nil { + disk["boot_disk_size_gb"] = icg.DiskConfig.BootDiskSizeGb + disk["num_local_ssds"] = icg.DiskConfig.NumLocalSsds + disk["boot_disk_type"] = icg.DiskConfig.BootDiskType + } + data["accelerators"] = flattenAccelerators(icg.Accelerators) + + } + + data["disk_config"] = []map[string]interface{}{disk} + return []map[string]interface{}{data} +} + func flattenGceClusterConfig(d *schema.ResourceData, gcc *dataproc.GceClusterConfig) []map[string]interface{} { if gcc == nil { return []map[string]interface{}{} 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 c1e050b94491..6c003db6e7b0 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 @@ -173,6 +173,24 @@ func TestAccDataprocCluster_withAccelerators(t *testing.T) { }) } +func testAccCheckDataprocAuxiliaryNodeGroupAccelerator(cluster *dataproc.Cluster, project string) resource.TestCheckFunc { + return func(s *terraform.State) error { + expectedUri := fmt.Sprintf("projects/%s/zones/.*/acceleratorTypes/nvidia-tesla-k80", project) + r := regexp.MustCompile(expectedUri) + + nodeGroup := cluster.Config.AuxiliaryNodeGroups[0].NodeGroup.NodeGroupConfig.Accelerators + if len(nodeGroup) != 1 { + return fmt.Errorf("Saw %d nodeGroup accelerator types instead of 1", len(nodeGroup)) + } + + matches := r.FindStringSubmatch(nodeGroup[0].AcceleratorTypeUri) + if len(matches) != 1 { + return fmt.Errorf("Saw %s master accelerator type instead of %s", nodeGroup[0].AcceleratorTypeUri, expectedUri) + } + return nil + } +} + func testAccCheckDataprocClusterAccelerator(cluster *dataproc.Cluster, project string, masterCount int, workerCount int) resource.TestCheckFunc { return func(s *terraform.State) error { expectedUri := fmt.Sprintf("projects/%s/zones/.*/acceleratorTypes/nvidia-tesla-k80", project) @@ -514,6 +532,38 @@ func TestAccDataprocCluster_spotWithInstanceFlexibilityPolicy(t *testing.T) { }) } +func TestAccDataprocCluster_spotWithAuxiliaryNodeGroups(t *testing.T) { + t.Parallel() + + project := envvar.GetTestProjectFromEnv() + rnd := acctest.RandString(t, 10) + var cluster dataproc.Cluster + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckDataprocClusterDestroy(t), + Steps: []resource.TestStep{ + { + Config: testAccDataprocCluster_withAuxiliaryNodeGroups(rnd), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_auxiliary_node_groups", &cluster), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_auxiliary_node_groups", "cluster_config.0.auxiliary_node_groups.0.node_group.0.roles.0", "DRIVER"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_auxiliary_node_groups", "cluster_config.0.auxiliary_node_groups.0.node_group.0.node_group_config.0.num_instances", "2"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_auxiliary_node_groups", "cluster_config.0.auxiliary_node_groups.0.node_group.0.node_group_config.0.machine_type", "n1-standard-2"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_auxiliary_node_groups", "cluster_config.0.auxiliary_node_groups.0.node_group.0.node_group_config.0.min_cpu_platform", "AMD Rome"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_auxiliary_node_groups", "cluster_config.0.auxiliary_node_groups.0.node_group.0.node_group_config.0.disk_config.0.boot_disk_size_gb", "35"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_auxiliary_node_groups", "cluster_config.0.auxiliary_node_groups.0.node_group.0.node_group_config.0.disk_config.0.boot_disk_type", "pd-standard"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_auxiliary_node_groups", "cluster_config.0.auxiliary_node_groups.0.node_group.0.node_group_config.0.disk_config.0.num_local_ssds", "1"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_auxiliary_node_groups", "cluster_config.0.auxiliary_node_groups.0.node_group.0.node_group_config.0.accelerators.0.accelerator_count", "1"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_auxiliary_node_groups", "cluster_config.0.auxiliary_node_groups.0.node_group_id", "node-group-id"), + testAccCheckDataprocAuxiliaryNodeGroupAccelerator(&cluster, project), + + ), + }, + }, + }) +} + func TestAccDataprocCluster_withStagingBucket(t *testing.T) { t.Parallel() @@ -1881,6 +1931,54 @@ resource "google_dataproc_cluster" "spot_with_instance_flexibility_policy" { `, rnd) } +func testAccDataprocCluster_withAuxiliaryNodeGroups(rnd string) string { + return fmt.Sprintf(` +resource "google_dataproc_cluster" "with_auxiliary_node_groups" { + name = "tf-test-dproc-%s" + region = "us-central1" + + cluster_config { + master_config { + num_instances = "1" + machine_type = "e2-medium" + disk_config { + boot_disk_size_gb = 35 + } + } + + worker_config { + num_instances = "2" + machine_type = "e2-medium" + disk_config { + boot_disk_size_gb = 35 + } + } + + auxiliary_node_groups{ + node_group_id="node-group-id" + node_group { + roles = ["DRIVER"] + node_group_config{ + num_instances=2 + machine_type="n1-standard-2" + min_cpu_platform = "AMD Rome" + disk_config { + boot_disk_size_gb = 35 + boot_disk_type = "pd-standard" + num_local_ssds = 1 + } + accelerators { + accelerator_count = 1 + accelerator_type = "nvidia-tesla-k80" + } + } + } + } + } +} + `, rnd) +} + func testAccDataprocCluster_withStagingBucketOnly(bucketName string) string { return fmt.Sprintf(` resource "google_storage_bucket" "bucket" { 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 32762397ff06..a09753653a04 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 @@ -381,6 +381,9 @@ resource "google_dataproc_cluster" "accelerated_cluster" { * `dataproc_metric_config` (Optional) The Compute Engine accelerator (GPU) configuration for these instances. Can be specified multiple times. Structure [defined below](#nested_dataproc_metric_config). +* `auxiliary_node_groups` (Optional) A Dataproc NodeGroup resource is a group of Dataproc cluster nodes that execute an assigned role. + Structure [defined below](#nested_auxiliary_node_groups). + * `metastore_config` (Optional) The config setting for metastore service with the cluster. Structure [defined below](#nested_metastore_config). - - - @@ -828,6 +831,76 @@ dataproc_metric_config { - - - +The `auxiliary_node_groups` block supports: + +```hcl +auxiliary_node_groups{ + node_group { + roles = ["DRIVER"] + node_group_config{ + num_instances=2 + machine_type="n1-standard-2" + min_cpu_platform = "AMD Rome" + disk_config { + boot_disk_size_gb = 35 + boot_disk_type = "pd-standard" + num_local_ssds = 1 + } + accelerators { + accelerator_count = 1 + accelerator_type = "nvidia-tesla-t4" + } + } + } +} +``` + + +* `node_group` - (Required) Node group configuration. + + * `roles` - (Required) Node group roles. + One of `"DRIVER"`. + + * `name` - (Optional) The Node group resource name. + + * `node_group_config` - (Optional) The node group instance group configuration. + + * `num_instances`- (Optional, Computed) Specifies the number of master nodes to create. + Please set a number greater than 0. Node Group must have at least 1 instance. + + * `machine_type` - (Optional, Computed) The name of a Google Compute Engine machine type + to create for the node group. If not specified, GCP will default to a predetermined + computed value (currently `n1-standard-4`). + + * `min_cpu_platform` - (Optional, Computed) The name of a minimum generation of CPU family + for the node group. If not specified, GCP will default to a predetermined computed value + for each zone. See [the guide](https://cloud.google.com/compute/docs/instances/specify-min-cpu-platform) + for details about which CPU families are available (and defaulted) for each zone. + + * `disk_config` (Optional) Disk Config + + * `boot_disk_type` - (Optional) The disk type of the primary disk attached to each node. + One of `"pd-ssd"` or `"pd-standard"`. Defaults to `"pd-standard"`. + + * `boot_disk_size_gb` - (Optional, Computed) Size of the primary disk attached to each node, specified + in GB. The primary disk contains the boot volume and system libraries, and 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. + + * `num_local_ssds` - (Optional) The amount of local SSD disks that will be attached to each master cluster node. + Defaults to 0. + + * `accelerators` (Optional) The Compute Engine accelerator (GPU) configuration for these instances. Can be specified + multiple times. + + * `accelerator_type` - (Required) The short name of the accelerator type to expose to this instance. For example, `nvidia-tesla-k80`. + + * `accelerator_count` - (Required) The number of the accelerator cards of this type exposed to this instance. Often restricted to one of `1`, `2`, `4`, or `8`. + + +- - - + The `lifecycle_config` block supports: ```hcl From 13e0b26a522ca2dc631e0cffa6710bebad7cd584 Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Thu, 14 Dec 2023 12:36:21 -0600 Subject: [PATCH 18/27] Add c2thorn to vacation reviewers for December (#9643) --- .ci/magician/github/membership.go | 1 + 1 file changed, 1 insertion(+) diff --git a/.ci/magician/github/membership.go b/.ci/magician/github/membership.go index 21aaea6f459b..993c9ddd0e62 100644 --- a/.ci/magician/github/membership.go +++ b/.ci/magician/github/membership.go @@ -49,6 +49,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{ "hao-nan-li", + "c2thorn", } ) From 5e89b3b459087978b89d3405bd4821d9af1436f3 Mon Sep 17 00:00:00 2001 From: Zach Berger Date: Thu, 14 Dec 2023 11:48:23 -0800 Subject: [PATCH 19/27] Add resources for Cloud Logging default settings (#9409) * Add folder and organization setting resources * Try GetTestOrgTargetFromEnv instead of GetTestOrgFromEnv. * Use correct organization for testing. * Remove key rotation to fix VCR test. * Don't specify fields matching default values. * Specify true instead of yes. * Use BootstrapKMSKeyInLocation instead of creating new keys. * Add missing quotes * Add additional examples to generate additional tests. * Remove unneeded resources from examples. * Simplify tests to be one full resource creation and one update. * Fix typo in test * Document and cleanup example. --- mmv1/products/logging/FolderSettings.yaml | 84 ++++++++++++++++++ .../logging/OrganizationSettings.yaml | 82 ++++++++++++++++++ .../logging_folder_settings_all.tf.erb | 22 +++++ .../logging_organization_settings_all.tf.erb | 17 ++++ .../resource_logging_folder_settings_test.go | 86 +++++++++++++++++++ ...urce_logging_organization_settings_test.go | 74 ++++++++++++++++ 6 files changed, 365 insertions(+) create mode 100644 mmv1/products/logging/FolderSettings.yaml create mode 100644 mmv1/products/logging/OrganizationSettings.yaml create mode 100644 mmv1/templates/terraform/examples/logging_folder_settings_all.tf.erb create mode 100644 mmv1/templates/terraform/examples/logging_organization_settings_all.tf.erb create mode 100644 mmv1/third_party/terraform/services/logging/resource_logging_folder_settings_test.go create mode 100644 mmv1/third_party/terraform/services/logging/resource_logging_organization_settings_test.go diff --git a/mmv1/products/logging/FolderSettings.yaml b/mmv1/products/logging/FolderSettings.yaml new file mode 100644 index 000000000000..8cd0f8f3b5c7 --- /dev/null +++ b/mmv1/products/logging/FolderSettings.yaml @@ -0,0 +1,84 @@ +# 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: 'FolderSettings' +description: | + Default resource settings control whether CMEK is required for new log buckets. These settings also determine the storage location for the _Default and _Required log buckets, and whether the _Default sink is enabled or disabled. +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Configure default settings for organizations and folders': 'https://cloud.google.com/logging/docs/default-settings' + api: 'https://cloud.google.com/logging/docs/reference/v2/rest/v2/TopLevel/getSettings' +base_url: 'folders/{{folder}}/settings' +self_link: 'folders/{{folder}}/settings' +import_format: ['folders/{{folder}}/settings'] +# Hardcode the updateMask since d.HasChanged does not work on create. +create_url: 'folders/{{folder}}/settings?updateMask=disableDefaultSink,storageLocation,kmsKeyName' +update_url: 'folders/{{folder}}/settings?updateMask=disableDefaultSink,storageLocation,kmsKeyName' +# This is a singleton resource that already is created, so create +# is really an update, and therefore should be PATCHed. +create_verb: :PATCH +update_verb: :PATCH +# update_mask: true +# This is a singleton resource that cannot be deleted, so skip delete. +skip_delete: true +examples: + - !ruby/object:Provider::Terraform::Examples + name: "logging_folder_settings_all" + primary_resource_id: "example" + vars: + key_name: "kms-key" + folder_name: "folder-name" + test_env_vars: + org_id: :ORG_ID + test_vars_overrides: + key_name: 'acctest.BootstrapKMSKeyInLocation(t, "us-central1").CryptoKey.Name' +parameters: + - !ruby/object:Api::Type::String + name: 'folder' + required: true + immutable: true + url_param_only: true + description: | + The folder for which to retrieve settings. +properties: + - !ruby/object:Api::Type::String + name: name + output: true + description: | + The resource name of the settings. + - !ruby/object:Api::Type::String + name: kmsKeyName + default_from_api: true + description: | + The resource name for the configured Cloud KMS key. + - !ruby/object:Api::Type::String + name: kmsServiceAccountId + output: true + description: | + The service account that will be used by the Log Router to access your Cloud KMS key. + - !ruby/object:Api::Type::String + name: storageLocation + default_from_api: true + description: | + The storage location that Cloud Logging will use to create new resources when a location is needed but not explicitly provided. + - !ruby/object:Api::Type::Boolean + name: disableDefaultSink + default_from_api: true + description: | + If set to true, the _Default sink in newly created projects and folders will created in a disabled state. This can be used to automatically disable log storage if there is already an aggregated sink configured in the hierarchy. The _Default sink can be re-enabled manually if needed. + - !ruby/object:Api::Type::String + name: loggingServiceAccountId + output: true + description: | + The service account for the given container. Sinks use this service account as their writerIdentity if no custom service account is provided. diff --git a/mmv1/products/logging/OrganizationSettings.yaml b/mmv1/products/logging/OrganizationSettings.yaml new file mode 100644 index 000000000000..cf5acbabb4eb --- /dev/null +++ b/mmv1/products/logging/OrganizationSettings.yaml @@ -0,0 +1,82 @@ +# 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: 'OrganizationSettings' +description: | + Default resource settings control whether CMEK is required for new log buckets. These settings also determine the storage location for the _Default and _Required log buckets, and whether the _Default sink is enabled or disabled. +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Configure default settings for organizations and folders': 'https://cloud.google.com/logging/docs/default-settings' + api: 'https://cloud.google.com/logging/docs/reference/v2/rest/v2/TopLevel/getSettings' +base_url: 'organizations/{{organization}}/settings' +self_link: 'organizations/{{organization}}/settings' +import_format: ['organizations/{{organization}}/settings'] +# Hardcode the updateMask since d.HasChanged does not work on create. +create_url: 'organizations/{{organization}}/settings?updateMask=disableDefaultSink,storageLocation,kmsKeyName' +update_url: 'organizations/{{organization}}/settings?updateMask=disableDefaultSink,storageLocation,kmsKeyName' +# This is a singleton resource that already is created, so create +# is really an update, and therefore should be PATCHed. +create_verb: :PATCH +update_verb: :PATCH +# This is a singleton resource that cannot be deleted, so skip delete. +skip_delete: true +examples: + - !ruby/object:Provider::Terraform::Examples + name: "logging_organization_settings_all" + primary_resource_id: "example" + # Covered by update test. + skip_test: true + vars: + key_name: "kms-key" + test_env_vars: + org_id: :ORG_TARGET +parameters: + - !ruby/object:Api::Type::String + name: 'organization' + required: true + immutable: true + url_param_only: true + description: | + The organization for which to retrieve or configure settings. +properties: + - !ruby/object:Api::Type::String + name: name + output: true + description: | + The resource name of the settings. + - !ruby/object:Api::Type::String + name: kmsKeyName + default_from_api: true + description: | + The resource name for the configured Cloud KMS key. + - !ruby/object:Api::Type::String + name: kmsServiceAccountId + output: true + description: | + The service account that will be used by the Log Router to access your Cloud KMS key. + - !ruby/object:Api::Type::String + name: storageLocation + default_from_api: true + description: | + The storage location that Cloud Logging will use to create new resources when a location is needed but not explicitly provided. + - !ruby/object:Api::Type::Boolean + name: disableDefaultSink + default_from_api: true + description: | + If set to true, the _Default sink in newly created projects and folders will created in a disabled state. This can be used to automatically disable log storage if there is already an aggregated sink configured in the hierarchy. The _Default sink can be re-enabled manually if needed. + - !ruby/object:Api::Type::String + name: loggingServiceAccountId + output: true + description: | + The service account for the given container. Sinks use this service account as their writerIdentity if no custom service account is provided. diff --git a/mmv1/templates/terraform/examples/logging_folder_settings_all.tf.erb b/mmv1/templates/terraform/examples/logging_folder_settings_all.tf.erb new file mode 100644 index 000000000000..35a35ccd6fac --- /dev/null +++ b/mmv1/templates/terraform/examples/logging_folder_settings_all.tf.erb @@ -0,0 +1,22 @@ +resource "google_logging_folder_settings" "<%= ctx[:primary_resource_id] %>" { + disable_default_sink = true + folder = google_folder.my_folder.folder_id + kms_key_name = "<%= ctx[:vars]['key_name'] %>" + storage_location = "us-central1" + depends_on = [ google_kms_crypto_key_iam_member.iam ] +} + +resource "google_folder" "my_folder" { + display_name = "<%= ctx[:vars]['folder_name'] %>" + parent = "organizations/<%= ctx[:test_env_vars]['org_id'] %>" +} + +data "google_logging_folder_settings" "settings" { + folder = google_folder.my_folder.folder_id +} + +resource "google_kms_crypto_key_iam_member" "iam" { + crypto_key_id = "<%= ctx[:vars]['key_name'] %>" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + member = "serviceAccount:${data.google_logging_folder_settings.settings.kms_service_account_id}" +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/logging_organization_settings_all.tf.erb b/mmv1/templates/terraform/examples/logging_organization_settings_all.tf.erb new file mode 100644 index 000000000000..dd4b38bde6dd --- /dev/null +++ b/mmv1/templates/terraform/examples/logging_organization_settings_all.tf.erb @@ -0,0 +1,17 @@ +resource "google_logging_organization_settings" "<%= ctx[:primary_resource_id] %>" { + disable_default_sink = true + kms_key_name = "<%= ctx[:vars]['key_name'] %>" + organization = "<%= ctx[:test_env_vars]['org_id'] %>" + storage_location = "us-central1" + depends_on = [ google_kms_crypto_key_iam_member.iam ] +} + +data "google_logging_organization_settings" "settings" { + organization = "<%= ctx[:test_env_vars]['org_id'] %>" +} + +resource "google_kms_crypto_key_iam_member" "iam" { + crypto_key_id = "<%= ctx[:vars]['key_name'] %>" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + member = "serviceAccount:${data.google_logging_organization_settings.settings.kms_service_account_id}" +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/logging/resource_logging_folder_settings_test.go b/mmv1/third_party/terraform/services/logging/resource_logging_folder_settings_test.go new file mode 100644 index 000000000000..e88dc0d529a5 --- /dev/null +++ b/mmv1/third_party/terraform/services/logging/resource_logging_folder_settings_test.go @@ -0,0 +1,86 @@ +package logging_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 TestAccLoggingFolderSettings_update(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + "original_key": acctest.BootstrapKMSKeyInLocation(t, "us-central1").CryptoKey.Name, + "updated_key": acctest.BootstrapKMSKeyInLocation(t, "us-east1").CryptoKey.Name, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccLoggingFolderSettings_onlyRequired(context), + }, + { + ResourceName: "google_logging_folder_settings.example", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"folder"}, + }, + { + Config: testAccLoggingFolderSettings_full(context), + }, + { + ResourceName: "google_logging_folder_settings.example", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"folder"}, + }, + }, + }) +} + +func testAccLoggingFolderSettings_full(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_logging_folder_settings" "example" { + disable_default_sink = true + folder = google_folder.my_folder.folder_id + kms_key_name = "%{original_key}" + storage_location = "us-central1" + depends_on = [ google_kms_crypto_key_iam_member.iam ] +} + +resource "google_folder" "my_folder" { + display_name = "tf-test-folder-%{random_suffix}" + parent = "organizations/%{org_id}" +} + +data "google_logging_folder_settings" "settings" { + folder = google_folder.my_folder.folder_id +} + +resource "google_kms_crypto_key_iam_member" "iam" { + crypto_key_id = "%{original_key}" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + member = "serviceAccount:${data.google_logging_folder_settings.settings.kms_service_account_id}" +} +`, context) +} + +func testAccLoggingFolderSettings_onlyRequired(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_logging_folder_settings" "example" { + folder = google_folder.my_folder.folder_id +} + +resource "google_folder" "my_folder" { + display_name = "tf-test-folder-%{random_suffix}" + parent = "organizations/%{org_id}" +} +`, context) +} diff --git a/mmv1/third_party/terraform/services/logging/resource_logging_organization_settings_test.go b/mmv1/third_party/terraform/services/logging/resource_logging_organization_settings_test.go new file mode 100644 index 000000000000..ce2896c4e181 --- /dev/null +++ b/mmv1/third_party/terraform/services/logging/resource_logging_organization_settings_test.go @@ -0,0 +1,74 @@ +package logging_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 TestAccLoggingOrganizationSettings_update(t *testing.T) { + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgTargetFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + "original_key": acctest.BootstrapKMSKeyInLocation(t, "us-central1").CryptoKey.Name, + "updated_key": acctest.BootstrapKMSKeyInLocation(t, "us-east1").CryptoKey.Name, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccLoggingOrganizationSettings_onlyRequired(context), + }, + { + ResourceName: "google_logging_organization_settings.example", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"organization"}, + }, + { + Config: testAccLoggingOrganizationSettings_full(context), + }, + { + ResourceName: "google_logging_organization_settings.example", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"organization"}, + }, + }, + }) +} + +func testAccLoggingOrganizationSettings_full(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_logging_organization_settings" "example" { + disable_default_sink = false + kms_key_name = "%{original_key}" + organization = "%{org_id}" + storage_location = "us-central1" + depends_on = [ google_kms_crypto_key_iam_member.iam ] +} + +data "google_logging_organization_settings" "settings" { + organization = "%{org_id}" +} + +resource "google_kms_crypto_key_iam_member" "iam" { + crypto_key_id = "%{original_key}" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + member = "serviceAccount:${data.google_logging_organization_settings.settings.kms_service_account_id}" +} +`, context) +} + +func testAccLoggingOrganizationSettings_onlyRequired(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_logging_organization_settings" "example" { + organization = "%{org_id}" +} +`, context) +} From 06deb0484e7db634bb29304aaeb9d01e594e011a Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Thu, 14 Dec 2023 11:48:36 -0800 Subject: [PATCH 20/27] Added vmware engine increase (#9646) * Added vmware engine increase * Update README.md --- .ci/infra/terraform/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.ci/infra/terraform/README.md b/.ci/infra/terraform/README.md index 99a467952681..76c872f13f0c 100644 --- a/.ci/infra/terraform/README.md +++ b/.ci/infra/terraform/README.md @@ -69,3 +69,4 @@ Quotas that will need to be adjusted to support all tests: - compute.googleapis.com/routers - compute.googleapis.com/c2_cpus (us-central1) - compute.googleapis.com/n2_cpus (us-central1) to 36+ +- VMware Engine standard 72 vCPUs nodes per region - southamerica-east1 to 21 From 617cca41c65236cbbb39730359cdcda653fde17a Mon Sep 17 00:00:00 2001 From: Shuya Ma <87669292+shuyama1@users.noreply.github.com> Date: Thu, 14 Dec 2023 12:05:39 -0800 Subject: [PATCH 21/27] Revert "The version field should be under configmanagement instead of under oci" (#9645) --- mmv1/products/gkehub2/Feature.yaml | 6 +++--- .../services/gkehub2/resource_gke_hub_feature_test.go.erb | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/mmv1/products/gkehub2/Feature.yaml b/mmv1/products/gkehub2/Feature.yaml index b3968b337586..67be3b1efc02 100644 --- a/mmv1/products/gkehub2/Feature.yaml +++ b/mmv1/products/gkehub2/Feature.yaml @@ -215,9 +215,6 @@ properties: name: configmanagement description: Config Management spec properties: - - !ruby/object:Api::Type::String - name: version - description: 'Version of ACM installed' - !ruby/object:Api::Type::NestedObject name: configSync description: 'ConfigSync configuration for the cluster' @@ -274,6 +271,9 @@ properties: - !ruby/object:Api::Type::String name: syncWaitSecs description: 'Period in seconds between consecutive syncs. Default: 15' + - !ruby/object:Api::Type::String + name: version + description: 'Version of ACM installed' - !ruby/object:Api::Type::NestedObject name: policycontroller description: Policy Controller spec 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 5af1d572cfd7..f2c14b2d223f 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 @@ -460,7 +460,6 @@ resource "google_gke_hub_feature" "feature" { location = "global" fleet_default_member_config { configmanagement { - version = "1.16.0" config_sync { source_format = "hierarchy" git { @@ -487,7 +486,6 @@ resource "google_gke_hub_feature" "feature" { location = "global" fleet_default_member_config { configmanagement { - version = "1.16.1" config_sync { source_format = "unstructured" oci { From 0c03a04663f6880034c08529349224741bfc3642 Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Thu, 14 Dec 2023 12:35:44 -0800 Subject: [PATCH 22/27] Add custom flattener for diagflowcx agent git integration settings field (#9597) * Add a custom flattener for the parent field * Update mmv1/templates/terraform/custom_flatten/dialogflowcx_agent_git_integration_settings_github_settings.go.erb Co-authored-by: Stephen Lewis (Burrows) --------- Co-authored-by: Stephen Lewis (Burrows) --- mmv1/products/dialogflowcx/Agent.yaml | 2 +- ...ntegration_settings_github_settings.go.erb | 32 +++++++++++++++++++ ...ttings_github_settings_access_token.go.erb | 17 ---------- 3 files changed, 33 insertions(+), 18 deletions(-) create mode 100644 mmv1/templates/terraform/custom_flatten/dialogflowcx_agent_git_integration_settings_github_settings.go.erb delete mode 100644 mmv1/templates/terraform/custom_flatten/dialogflowcx_agent_git_integration_settings_github_settings_access_token.go.erb diff --git a/mmv1/products/dialogflowcx/Agent.yaml b/mmv1/products/dialogflowcx/Agent.yaml index 086400417dda..c661bb18ecbc 100644 --- a/mmv1/products/dialogflowcx/Agent.yaml +++ b/mmv1/products/dialogflowcx/Agent.yaml @@ -164,6 +164,7 @@ properties: name: 'githubSettings' description: | Settings of integration with GitHub. + custom_flatten: 'templates/terraform/custom_flatten/dialogflowcx_agent_git_integration_settings_github_settings.go.erb' # accessToken comes from config, no response properties: - !ruby/object:Api::Type::String name: 'displayName' @@ -183,7 +184,6 @@ properties: The access token used to authenticate the access to the GitHub repository. sensitive: true ignore_read: true - custom_flatten: 'templates/terraform/custom_flatten/dialogflowcx_agent_git_integration_settings_github_settings_access_token.go.erb' - !ruby/object:Api::Type::Array name: 'branches' description: | diff --git a/mmv1/templates/terraform/custom_flatten/dialogflowcx_agent_git_integration_settings_github_settings.go.erb b/mmv1/templates/terraform/custom_flatten/dialogflowcx_agent_git_integration_settings_github_settings.go.erb new file mode 100644 index 000000000000..bf689e0f2566 --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/dialogflowcx_agent_git_integration_settings_github_settings.go.erb @@ -0,0 +1,32 @@ +<%# The license inside this block applies to this file. + # Copyright 2018 Google Inc. + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. +-%> +func flattenDialogflowCXAgentGitIntegrationSettingsGithubSettings(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + // ignore access_token, which is always returned as REDACTED + delete(original, "access_token"); + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["display_name"] = original["displayName"] + transformed["repository_uri"] = original["repositoryUri"] + transformed["tracking_branch"] = original["trackingBranch"] + transformed["access_token"] = d.Get("git_integration_settings.0.github_settings.0.access_token") + transformed["branches"] = original["branches"] + return []interface{}{transformed} +} diff --git a/mmv1/templates/terraform/custom_flatten/dialogflowcx_agent_git_integration_settings_github_settings_access_token.go.erb b/mmv1/templates/terraform/custom_flatten/dialogflowcx_agent_git_integration_settings_github_settings_access_token.go.erb deleted file mode 100644 index 7102f1e6fb07..000000000000 --- a/mmv1/templates/terraform/custom_flatten/dialogflowcx_agent_git_integration_settings_github_settings_access_token.go.erb +++ /dev/null @@ -1,17 +0,0 @@ -<%# The license inside this block applies to this file. - # Copyright 2018 Google Inc. - # Licensed under the Apache License, Version 2.0 (the "License"); - # you may not use this file except in compliance with the License. - # You may obtain a copy of the License at - # - # http://www.apache.org/licenses/LICENSE-2.0 - # - # Unless required by applicable law or agreed to in writing, software - # distributed under the License is distributed on an "AS IS" BASIS, - # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - # See the License for the specific language governing permissions and - # limitations under the License. --%> -func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return d.Get("git_integration_settings.0.github_settings.0.access_token") -} From 05f4a8d1d6b7e577e7cf563f2b6f10827a8cebd7 Mon Sep 17 00:00:00 2001 From: Derrek Bertrand Date: Thu, 14 Dec 2023 15:54:43 -0500 Subject: [PATCH 23/27] Remove unnecessary lifecycle ignore_changes from examples (#9571) --- .../terraform/examples/cloudrunv2_job_basic.tf.erb | 8 +------- .../terraform/examples/cloudrunv2_job_directvpc.tf.erb | 6 ------ .../terraform/examples/cloudrunv2_job_emptydir.tf.erb | 6 ------ .../terraform/examples/cloudrunv2_job_secret.tf.erb | 6 ------ .../terraform/examples/cloudrunv2_job_sql.tf.erb | 6 ------ .../terraform/examples/cloudrunv2_job_vpcaccess.tf.erb | 6 ------ .../examples/cloudrunv2_service_custom_audiences.tf.erb | 8 +------- .../examples/cloudrunv2_service_multicontainer.tf.erb | 6 ------ 8 files changed, 2 insertions(+), 50 deletions(-) diff --git a/mmv1/templates/terraform/examples/cloudrunv2_job_basic.tf.erb b/mmv1/templates/terraform/examples/cloudrunv2_job_basic.tf.erb index 8e675f0344cf..c37ab87a9f3d 100644 --- a/mmv1/templates/terraform/examples/cloudrunv2_job_basic.tf.erb +++ b/mmv1/templates/terraform/examples/cloudrunv2_job_basic.tf.erb @@ -9,10 +9,4 @@ resource "google_cloud_run_v2_job" "<%= ctx[:primary_resource_id] %>" { } } } - - lifecycle { - ignore_changes = [ - launch_stage, - ] - } -} \ No newline at end of file +} diff --git a/mmv1/templates/terraform/examples/cloudrunv2_job_directvpc.tf.erb b/mmv1/templates/terraform/examples/cloudrunv2_job_directvpc.tf.erb index a28913e7fc13..9b38d9722a59 100644 --- a/mmv1/templates/terraform/examples/cloudrunv2_job_directvpc.tf.erb +++ b/mmv1/templates/terraform/examples/cloudrunv2_job_directvpc.tf.erb @@ -17,10 +17,4 @@ resource "google_cloud_run_v2_job" "<%= ctx[:primary_resource_id] %>" { } } } - - lifecycle { - ignore_changes = [ - launch_stage, - ] - } } diff --git a/mmv1/templates/terraform/examples/cloudrunv2_job_emptydir.tf.erb b/mmv1/templates/terraform/examples/cloudrunv2_job_emptydir.tf.erb index 107b03c3c53c..0c51bbcd36df 100644 --- a/mmv1/templates/terraform/examples/cloudrunv2_job_emptydir.tf.erb +++ b/mmv1/templates/terraform/examples/cloudrunv2_job_emptydir.tf.erb @@ -21,10 +21,4 @@ resource "google_cloud_run_v2_job" "<%= ctx[:primary_resource_id] %>" { } } } - - lifecycle { - ignore_changes = [ - launch_stage, - ] - } } diff --git a/mmv1/templates/terraform/examples/cloudrunv2_job_secret.tf.erb b/mmv1/templates/terraform/examples/cloudrunv2_job_secret.tf.erb index 387d0baf2b05..137234fdcea2 100644 --- a/mmv1/templates/terraform/examples/cloudrunv2_job_secret.tf.erb +++ b/mmv1/templates/terraform/examples/cloudrunv2_job_secret.tf.erb @@ -26,12 +26,6 @@ resource "google_cloud_run_v2_job" "<%= ctx[:primary_resource_id] %>" { } } - lifecycle { - ignore_changes = [ - launch_stage, - ] - } - depends_on = [ google_secret_manager_secret_version.secret-version-data, google_secret_manager_secret_iam_member.secret-access, diff --git a/mmv1/templates/terraform/examples/cloudrunv2_job_sql.tf.erb b/mmv1/templates/terraform/examples/cloudrunv2_job_sql.tf.erb index 24740a509e58..d94410960200 100644 --- a/mmv1/templates/terraform/examples/cloudrunv2_job_sql.tf.erb +++ b/mmv1/templates/terraform/examples/cloudrunv2_job_sql.tf.erb @@ -34,12 +34,6 @@ resource "google_cloud_run_v2_job" "<%= ctx[:primary_resource_id] %>" { } } } - - lifecycle { - ignore_changes = [ - launch_stage, - ] - } } data "google_project" "project" { diff --git a/mmv1/templates/terraform/examples/cloudrunv2_job_vpcaccess.tf.erb b/mmv1/templates/terraform/examples/cloudrunv2_job_vpcaccess.tf.erb index a90af1a27972..409c48dfef9a 100644 --- a/mmv1/templates/terraform/examples/cloudrunv2_job_vpcaccess.tf.erb +++ b/mmv1/templates/terraform/examples/cloudrunv2_job_vpcaccess.tf.erb @@ -13,12 +13,6 @@ resource "google_cloud_run_v2_job" "<%= ctx[:primary_resource_id] %>" { } } } - - lifecycle { - ignore_changes = [ - launch_stage, - ] - } } resource "google_vpc_access_connector" "connector" { diff --git a/mmv1/templates/terraform/examples/cloudrunv2_service_custom_audiences.tf.erb b/mmv1/templates/terraform/examples/cloudrunv2_service_custom_audiences.tf.erb index 6147add9ab27..50445e63e7e5 100644 --- a/mmv1/templates/terraform/examples/cloudrunv2_service_custom_audiences.tf.erb +++ b/mmv1/templates/terraform/examples/cloudrunv2_service_custom_audiences.tf.erb @@ -11,10 +11,4 @@ resource "google_cloud_run_v2_service" "<%= ctx[:primary_resource_id] %>" { image = "us-docker.pkg.dev/cloudrun/container/hello" } } - - lifecycle { - ignore_changes = [ - launch_stage, - ] - } -} \ No newline at end of file +} diff --git a/mmv1/templates/terraform/examples/cloudrunv2_service_multicontainer.tf.erb b/mmv1/templates/terraform/examples/cloudrunv2_service_multicontainer.tf.erb index 03391c9bb2b9..bb5a86133d9b 100644 --- a/mmv1/templates/terraform/examples/cloudrunv2_service_multicontainer.tf.erb +++ b/mmv1/templates/terraform/examples/cloudrunv2_service_multicontainer.tf.erb @@ -29,10 +29,4 @@ resource "google_cloud_run_v2_service" "<%= ctx[:primary_resource_id] %>" { } } } - - lifecycle { - ignore_changes = [ - launch_stage, - ] - } } From a080fd37344e552c5bf62a11e5e1f0425b8b7b40 Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Thu, 14 Dec 2023 13:00:56 -0800 Subject: [PATCH 24/27] Magician refactor generate comment (#9613) * Run cassettes on main Revert local testing changes Test: make magician-check-vcr-cassettes the only step Also collect passing and skipping tests collectResult no longer returns an error Remove extra return value gitignore magician binary Print logs Actually set logPaths and cassettePaths Rework management of environment variables Remove extra ] Also print all_tests.log Echo home Include HOME in env Echo path Use GOCACHE instead of HOME add -vet=off Run all tests, skip printing logs Run 24 tests and upload logs Add -r and remove logs Also upload cassettes Run tests for one resource in recording Run tests for one resource in replaying Also capture PATH Run recording again Clone hashicorp provider instead of mm Run all tests Run replaying Move check cassettes to push-downstream Remove echo PATH change to GA in doc (#9491) Co-authored-by: Edward Sun Refactor magician structs (#9605) * Refactored github interfaces Fixed bug in overriding breaking changes * gofmt * Removed GetPullRequestLabelIDs Use magician for generate comment Fix formatting of breaking changes Keep diff string empty Add missing newline Add copyright notices Add missing space Revert changes from running generate-comment Run cassettes on main Print logs Rework management of environment variables change to GA in doc (#9491) Co-authored-by: Edward Sun git checkout main gcb-generate-diffs-new.yml * Move Version into provider package and Repo into source package * Remove second walk func * Add , * Add source Runner interface * Remove check cassettes changes * Fix issues with diff processor build * Fix test --- .ci/magician/cmd/generate_comment.go | 237 +++++++++++----------- .ci/magician/cmd/generate_comment_test.go | 87 +++++--- .ci/magician/cmd/interfaces.go | 4 +- .ci/magician/cmd/mock_runner_test.go | 97 +++++---- .ci/magician/exec/runner.go | 36 +++- .ci/magician/provider/version.go | 37 ++++ .ci/magician/source/repo.go | 85 ++++++++ .ci/scripts/go-plus/magician/exec.sh | 2 +- .gitignore | 3 + 9 files changed, 394 insertions(+), 194 deletions(-) create mode 100644 .ci/magician/provider/version.go create mode 100644 .ci/magician/source/repo.go diff --git a/.ci/magician/cmd/generate_comment.go b/.ci/magician/cmd/generate_comment.go index b6d457382111..2684f3068aa5 100644 --- a/.ci/magician/cmd/generate_comment.go +++ b/.ci/magician/cmd/generate_comment.go @@ -19,6 +19,8 @@ import ( "fmt" "magician/exec" "magician/github" + "magician/provider" + "magician/source" "os" "path/filepath" "regexp" @@ -29,14 +31,16 @@ import ( const allowBreakingChangesLabel = "override-breaking-change" -type ProviderVersion string - -type Repository struct { - Name string // Name in GitHub (e.g. magic-modules) - Title string // Title for display (e.g. Magic Modules) - Path string // local Path once checked out, including Name - Version ProviderVersion - DiffCanFail bool // whether to allow the command to continue if cloning or diffing the repo fails +var gcEnvironmentVariables = [...]string{ + "BUILD_ID", + "BUILD_STEP", + "COMMIT_SHA", + "GITHUB_TOKEN", + "GOPATH", + "HOME", + "PATH", + "PR_NUMBER", + "PROJECT_ID", } var generateCommentCmd = &cobra.Command{ @@ -45,12 +49,7 @@ var generateCommentCmd = &cobra.Command{ Long: `This command processes pull requests and performs various validations and actions based on the PR's metadata and author. The following PR details are expected as environment variables: - 1. BUILD_ID - 2. PROJECT_ID - 3. BUILD_STEP - 4. COMMIT_SHA - 5. PR_NUMBER - 6. GITHUB_TOKEN +` + listGCEnvironmentVariables() + ` The command performs the following steps: 1. Clone the tpg, tpgb, tfc, and tfoics repos from modular-magician. @@ -61,25 +60,14 @@ var generateCommentCmd = &cobra.Command{ 6. Run unit tests for the missing test detector. `, Run: func(cmd *cobra.Command, args []string) { - buildID := os.Getenv("BUILD_ID") - fmt.Println("Build ID: ", buildID) - - projectID := os.Getenv("PROJECT_ID") - fmt.Println("Project ID: ", projectID) - - buildStep := os.Getenv("BUILD_STEP") - fmt.Println("Build Step: ", buildStep) - - commit := os.Getenv("COMMIT_SHA") - fmt.Println("Commit SHA: ", commit) - - prNumber := os.Getenv("PR_NUMBER") - fmt.Println("PR Number: ", prNumber) - - githubToken, ok := os.LookupEnv("GITHUB_TOKEN") - if !ok { - fmt.Println("Did not provide GITHUB_TOKEN environment variable") - os.Exit(1) + env := make(map[string]string, len(gcEnvironmentVariables)) + for _, ev := range gcEnvironmentVariables { + val, ok := os.LookupEnv(ev) + if !ok { + fmt.Printf("Did not provide %s environment variable\n", ev) + os.Exit(1) + } + env[ev] = val } gh := github.NewClient() @@ -88,14 +76,23 @@ var generateCommentCmd = &cobra.Command{ fmt.Println("Error creating a runner: ", err) os.Exit(1) } - execGenerateComment(buildID, projectID, buildStep, commit, prNumber, githubToken, gh, rnr) + ctlr := source.NewController(filepath.Join("workspace", "go"), "modular-magician", env["GITHUB_TOKEN"], rnr) + execGenerateComment(env, gh, rnr, ctlr) }, } -func execGenerateComment(buildID, projectID, buildStep, commit, prNumber, githubToken string, gh GithubClient, r ExecRunner) { - newBranch := "auto-pr-" + prNumber - oldBranch := "auto-pr-" + prNumber + "-old" - wd := r.GetCWD() +func listGCEnvironmentVariables() string { + var result string + for i, ev := range gcEnvironmentVariables { + result += fmt.Sprintf("\t%2d. %s\n", i+1, ev) + } + return result +} + +func execGenerateComment(env map[string]string, gh GithubClient, rnr ExecRunner, ctlr *source.Controller) { + newBranch := "auto-pr-" + env["PR_NUMBER"] + oldBranch := "auto-pr-" + env["PR_NUMBER"] + "-old" + wd := rnr.GetCWD() mmLocalPath := filepath.Join(wd, "..", "..") tpgRepoName := "terraform-provider-google" tpgLocalPath := filepath.Join(mmLocalPath, "..", "tpg") @@ -108,7 +105,7 @@ func execGenerateComment(buildID, projectID, buildStep, commit, prNumber, github tfcLocalPath := filepath.Join(mmLocalPath, "..", "tfc") var diffs string - for _, repo := range []Repository{ + for _, repo := range []*source.Repo{ { Name: tpgRepoName, Title: "Terraform GA", @@ -132,7 +129,7 @@ func execGenerateComment(buildID, projectID, buildStep, commit, prNumber, github }, } { // TPG/TPGB difference - repoDiffs, err := cloneAndDiff(repo, oldBranch, newBranch, githubToken, r) + repoDiffs, err := cloneAndDiff(repo, oldBranch, newBranch, ctlr) if err != nil { fmt.Printf("Error cloning and diffing tpg repo: %v\n", err) if !repo.DiffCanFail { @@ -148,37 +145,43 @@ func execGenerateComment(buildID, projectID, buildStep, commit, prNumber, github var err error diffProcessorPath := filepath.Join(mmLocalPath, "tools", "diff-processor") // versionedBreakingChanges is a map of breaking change output by provider version. - versionedBreakingChanges := make(map[ProviderVersion]string, 2) - - for _, repo := range []Repository{ + versionedBreakingChanges := make(map[provider.Version]string, 2) + + env["OLD_REF"] = oldBranch + env["NEW_REF"] = newBranch + for _, repo := range []struct { + Title string + Path string + Version provider.Version + }{ { Title: "TPG", Path: tpgLocalPath, - Version: "ga", + Version: provider.GA, }, { Title: "TPGB", Path: tpgbLocalPath, - Version: "beta", + Version: provider.Beta, }, } { - // TPG diff processor - err = buildDiffProcessor(diffProcessorPath, repo.Path, oldBranch, newBranch, r) + // TPG(B) diff processor + err = buildDiffProcessor(diffProcessorPath, repo.Path, env, rnr) if err != nil { fmt.Println(err) os.Exit(1) } - output, err := computeBreakingChanges(diffProcessorPath, r) + output, err := computeBreakingChanges(diffProcessorPath, rnr) if err != nil { fmt.Println("Error computing TPG breaking changes: ", err) showBreakingChangesFailed = true } versionedBreakingChanges[repo.Version] = strings.TrimSuffix(output, "\n") - err = addLabels(diffProcessorPath, githubToken, prNumber, r) + err = addLabels(diffProcessorPath, env, rnr) if err != nil { fmt.Println("Error adding TPG labels to PR: ", err) } - err = cleanDiffProcessor(diffProcessorPath, r) + err = cleanDiffProcessor(diffProcessorPath, rnr) if err != nil { fmt.Println("Error cleaning up diff processor: ", err) os.Exit(1) @@ -190,11 +193,11 @@ func execGenerateComment(buildID, projectID, buildStep, commit, prNumber, github breakingChanges = `## Breaking Change Detection Failed The breaking change detector crashed during execution. This is usually due to the downstream provider(s) failing to compile. Please investigate or follow up with your reviewer.` } else { - breakingChanges = combineBreakingChanges(versionedBreakingChanges["ga"], versionedBreakingChanges["beta"]) + breakingChanges = combineBreakingChanges(versionedBreakingChanges[provider.GA], versionedBreakingChanges[provider.Beta]) } // Missing test detector - missingTests, err := detectMissingTests(mmLocalPath, tpgbLocalPath, oldBranch, r) + missingTests, err := detectMissingTests(mmLocalPath, tpgbLocalPath, oldBranch, rnr) if err != nil { fmt.Println("Error setting up missing test detector: ", err) os.Exit(1) @@ -205,7 +208,7 @@ The breaking change detector crashed during execution. This is usually due to th if breakingChanges != "" { message += breakingChanges + "\n\n" - pullRequest, err := gh.GetPullRequest(prNumber) + pullRequest, err := gh.GetPullRequest(env["PR_NUMBER"]) if err != nil { fmt.Printf("Error getting pull request: %v\n", err) os.Exit(1) @@ -232,100 +235,98 @@ The breaking change detector crashed during execution. This is usually due to th } } - if err := gh.PostComment(prNumber, message); err != nil { - fmt.Printf("Error posting comment to PR %s: %v\n", prNumber, err) + if err := gh.PostComment(env["PR_NUMBER"], message); err != nil { + fmt.Printf("Error posting comment to PR %s: %v\n", env["PR_NUMBER"], err) } - targetURL := fmt.Sprintf("https://console.cloud.google.com/cloud-build/builds;region=global/%s;step=%s?project=%s", buildID, buildStep, projectID) - if err := gh.PostBuildStatus(prNumber, "terraform-provider-breaking-change-test", breakingState, targetURL, commit); err != nil { - fmt.Printf("Error posting build status for pr %s commit %s: %v\n", prNumber, commit, err) + targetURL := fmt.Sprintf("https://console.cloud.google.com/cloud-build/builds;region=global/%s;step=%s?project=%s", env["BUILD_ID"], env["BUILD_STEP"], env["PROJECT_ID"]) + if err := gh.PostBuildStatus(env["PR_NUMBER"], "terraform-provider-breaking-change-test", breakingState, targetURL, env["COMMIT_SHA"]); err != nil { + fmt.Printf("Error posting build status for pr %s commit %s: %v\n", env["PR_NUMBER"], env["COMMIT_SHA"], err) os.Exit(1) } - if err := r.PushDir(mmLocalPath); err != nil { + if err := rnr.PushDir(mmLocalPath); err != nil { fmt.Println(err) os.Exit(1) } - if diffs := r.MustRun("git", []string{"diff", "HEAD", "origin/main", "tools/missing-test-detector"}, nil); diffs != "" { + if diffs := rnr.MustRun("git", []string{"diff", "HEAD", "origin/main", "tools/missing-test-detector"}, nil); diffs != "" { fmt.Printf("Found diffs in missing test detector:\n%s\nRunning tests.\n", diffs) - if err := testTools(mmLocalPath, tpgbLocalPath, prNumber, commit, buildID, buildStep, projectID, gh, r); err != nil { + if err := testTools(mmLocalPath, tpgbLocalPath, env, gh, rnr); err != nil { fmt.Printf("Error testing tools in %s: %v\n", mmLocalPath, err) os.Exit(1) } } - if err := r.PopDir(); err != nil { + if err := rnr.PopDir(); err != nil { fmt.Println(err) os.Exit(1) } } -func cloneAndDiff(repo Repository, oldBranch, newBranch, githubToken string, r ExecRunner) (string, error) { +func cloneAndDiff(repo *source.Repo, oldBranch, newBranch string, ctlr *source.Controller) (string, error) { // Clone the repo to the desired repo.Path. - url := fmt.Sprintf("https://modular-magician:%s@github.com/modular-magician/%s", githubToken, repo.Name) - if _, err := r.Run("git", []string{"clone", "-b", newBranch, url, repo.Path}, nil); err != nil { + repo.Branch = newBranch + if err := ctlr.Clone(repo); err != nil { return "", fmt.Errorf("error cloning %s: %v\n", repo.Name, err) } - // Push dir to the newly cloned repo. - if err := r.PushDir(repo.Path); err != nil { + if err := ctlr.Fetch(repo, oldBranch); err != nil { return "", err } - if _, err := r.Run("git", []string{"fetch", "origin", oldBranch}, nil); err != nil { - return "", fmt.Errorf("error fetching branch %s in repo %s: %v\n", oldBranch, repo.Name, err) - } - // Return summary, if any, and return to original directory. - if summary, err := r.Run("git", []string{"diff", "origin/" + oldBranch, "origin/" + newBranch, "--shortstat"}, nil); err != nil { - return "", fmt.Errorf("error diffing %s and %s: %v\n", oldBranch, newBranch, err) - } else if summary != "" { - summary = strings.TrimSuffix(summary, "\n") - return fmt.Sprintf("%s: [Diff](https://github.com/modular-magician/%s/compare/%s..%s) (%s)", repo.Title, repo.Name, oldBranch, newBranch, summary), r.PopDir() + // Return summary, if any. + diffs, err := ctlr.Diff(repo, oldBranch, newBranch) + if err != nil { + return "", err + } + if diffs == "" { + return "", nil } - return "", r.PopDir() + diffs = strings.TrimSuffix(diffs, "\n") + return fmt.Sprintf("%s: [Diff](https://github.com/modular-magician/%s/compare/%s..%s) (%s)", repo.Title, repo.Name, oldBranch, newBranch, diffs), nil } // Build the diff processor for tpg or tpgb -func buildDiffProcessor(diffProcessorPath, providerLocalPath, oldBranch, newBranch string, r ExecRunner) error { - if err := r.PushDir(diffProcessorPath); err != nil { +func buildDiffProcessor(diffProcessorPath, providerLocalPath string, env map[string]string, rnr ExecRunner) error { + if err := rnr.PushDir(diffProcessorPath); err != nil { return err } for _, path := range []string{"old", "new"} { - if err := r.Copy(providerLocalPath, filepath.Join(diffProcessorPath, path)); err != nil { + if err := rnr.Copy(providerLocalPath, filepath.Join(diffProcessorPath, path)); err != nil { return err } } - if _, err := r.Run("make", []string{"build"}, []string{"OLD_REF=" + oldBranch, "NEW_REF=" + newBranch}); err != nil { + if _, err := rnr.Run("make", []string{"build"}, env); err != nil { return fmt.Errorf("Error running make build in %s: %v\n", diffProcessorPath, err) } - return r.PopDir() + return rnr.PopDir() } -func computeBreakingChanges(diffProcessorPath string, r ExecRunner) (string, error) { - if err := r.PushDir(diffProcessorPath); err != nil { +func computeBreakingChanges(diffProcessorPath string, rnr ExecRunner) (string, error) { + if err := rnr.PushDir(diffProcessorPath); err != nil { return "", err } - breakingChanges, err := r.Run("bin/diff-processor", []string{"breaking-changes"}, nil) + breakingChanges, err := rnr.Run("bin/diff-processor", []string{"breaking-changes"}, nil) if err != nil { return "", err } - return breakingChanges, r.PopDir() + return breakingChanges, rnr.PopDir() } -func addLabels(diffProcessorPath, githubToken, prNumber string, r ExecRunner) error { - if err := r.PushDir(diffProcessorPath); err != nil { +func addLabels(diffProcessorPath string, env map[string]string, rnr ExecRunner) error { + if err := rnr.PushDir(diffProcessorPath); err != nil { return err } - output, err := r.Run("bin/diff-processor", []string{"add-labels", prNumber}, []string{fmt.Sprintf("GITHUB_TOKEN=%s", githubToken)}) + output, err := rnr.Run("bin/diff-processor", []string{"add-labels", env["PR_NUMBER"]}, env) fmt.Println(output) if err != nil { return err } - return r.PopDir() + return rnr.PopDir() } -func cleanDiffProcessor(diffProcessorPath string, r ExecRunner) error { +func cleanDiffProcessor(diffProcessorPath string, rnr ExecRunner) error { for _, path := range []string{"old", "new", "bin"} { - if err := r.RemoveAll(filepath.Join(diffProcessorPath, path)); err != nil { + if err := rnr.RemoveAll(filepath.Join(diffProcessorPath, path)); err != nil { return err } } @@ -377,93 +378,93 @@ An ` + "`override-breaking-change`" + ` label can be added to allow merging. // Run the missing test detector and return the results. // Returns an empty string unless there are missing tests. // Error will be nil unless an error occurs during setup. -func detectMissingTests(mmLocalPath, tpgbLocalPath, oldBranch string, r ExecRunner) (string, error) { +func detectMissingTests(mmLocalPath, tpgbLocalPath, oldBranch string, rnr ExecRunner) (string, error) { tpgbLocalPathOld := tpgbLocalPath + "old" - if err := r.Copy(tpgbLocalPath, tpgbLocalPathOld); err != nil { + if err := rnr.Copy(tpgbLocalPath, tpgbLocalPathOld); err != nil { return "", err } - if err := r.PushDir(tpgbLocalPathOld); err != nil { + if err := rnr.PushDir(tpgbLocalPathOld); err != nil { return "", err } - if _, err := r.Run("git", []string{"checkout", "origin/" + oldBranch}, nil); err != nil { + if _, err := rnr.Run("git", []string{"checkout", "origin/" + oldBranch}, nil); err != nil { return "", err } - if err := updatePackageName("old", tpgbLocalPathOld, r); err != nil { + if err := updatePackageName("old", tpgbLocalPathOld, rnr); err != nil { return "", err } - if err := updatePackageName("new", tpgbLocalPath, r); err != nil { + if err := updatePackageName("new", tpgbLocalPath, rnr); err != nil { return "", err } - if err := r.PopDir(); err != nil { + if err := rnr.PopDir(); err != nil { return "", err } missingTestDetectorPath := filepath.Join(mmLocalPath, "tools", "missing-test-detector") - if err := r.PushDir(missingTestDetectorPath); err != nil { + if err := rnr.PushDir(missingTestDetectorPath); err != nil { return "", err } - if _, err := r.Run("go", []string{"mod", "edit", "-replace", fmt.Sprintf("google/provider/%s=%s", "new", tpgbLocalPath)}, nil); err != nil { + if _, err := rnr.Run("go", []string{"mod", "edit", "-replace", fmt.Sprintf("google/provider/%s=%s", "new", tpgbLocalPath)}, nil); err != nil { fmt.Printf("Error running go mod edit: %v\n", err) } - if _, err := r.Run("go", []string{"mod", "edit", "-replace", fmt.Sprintf("google/provider/%s=%s", "old", tpgbLocalPathOld)}, nil); err != nil { + if _, err := rnr.Run("go", []string{"mod", "edit", "-replace", fmt.Sprintf("google/provider/%s=%s", "old", tpgbLocalPathOld)}, nil); err != nil { fmt.Printf("Error running go mod edit: %v\n", err) } - if _, err := r.Run("go", []string{"mod", "tidy"}, nil); err != nil { + if _, err := rnr.Run("go", []string{"mod", "tidy"}, nil); err != nil { fmt.Printf("Error running go mod tidy: %v\n", err) } - missingTests, err := r.Run("go", []string{"run", ".", fmt.Sprintf("-services-dir=%s/google-beta/services", tpgbLocalPath)}, nil) + missingTests, err := rnr.Run("go", []string{"run", ".", fmt.Sprintf("-services-dir=%s/google-beta/services", tpgbLocalPath)}, nil) if err != nil { fmt.Printf("Error running missing test detector: %v\n", err) missingTests = "" } else { fmt.Printf("Successfully ran missing test detector:\n%s\n", missingTests) } - return missingTests, r.PopDir() + return missingTests, rnr.PopDir() } // Update the provider package name to the given name in the given path. // name should be either "old" or "new". -func updatePackageName(name, path string, r ExecRunner) error { +func updatePackageName(name, path string, rnr ExecRunner) error { oldPackageName := "github.com/hashicorp/terraform-provider-google-beta" newPackageName := "google/provider/" + name fmt.Printf("Updating package name in %s from %s to %s\n", path, oldPackageName, newPackageName) - if err := r.PushDir(path); err != nil { + if err := rnr.PushDir(path); err != nil { return err } - if _, err := r.Run("find", []string{".", "-type", "f", "-name", "*.go", "-exec", "sed", "-i.bak", fmt.Sprintf("s~%s~%s~g", oldPackageName, newPackageName), "{}", "+"}, nil); err != nil { + if _, err := rnr.Run("find", []string{".", "-type", "f", "-name", "*.go", "-exec", "sed", "-i.bak", fmt.Sprintf("s~%s~%s~g", oldPackageName, newPackageName), "{}", "+"}, nil); err != nil { return fmt.Errorf("error running find: %v\n", err) } - if _, err := r.Run("sed", []string{"-i.bak", fmt.Sprintf("s|%s|%s|g", oldPackageName, newPackageName), "go.mod"}, nil); err != nil { + if _, err := rnr.Run("sed", []string{"-i.bak", fmt.Sprintf("s|%s|%s|g", oldPackageName, newPackageName), "go.mod"}, nil); err != nil { return fmt.Errorf("error running sed: %v\n", err) } - if _, err := r.Run("sed", []string{"-i.bak", fmt.Sprintf("s|%s|%s|g", oldPackageName, newPackageName), "go.sum"}, nil); err != nil { + if _, err := rnr.Run("sed", []string{"-i.bak", fmt.Sprintf("s|%s|%s|g", oldPackageName, newPackageName), "go.sum"}, nil); err != nil { return fmt.Errorf("error running sed: %v\n", err) } - return r.PopDir() + return rnr.PopDir() } // Run unit tests for the missing test detector and diff processor. // Report results using Github API. -func testTools(mmLocalPath, tpgbLocalPath, prNumber, commit, buildID, buildStep, projectID string, gh GithubClient, r ExecRunner) error { +func testTools(mmLocalPath, tpgbLocalPath string, env map[string]string, gh GithubClient, rnr ExecRunner) error { missingTestDetectorPath := filepath.Join(mmLocalPath, "tools", "missing-test-detector") - r.PushDir(missingTestDetectorPath) - if _, err := r.Run("go", []string{"mod", "tidy"}, nil); err != nil { + rnr.PushDir(missingTestDetectorPath) + if _, err := rnr.Run("go", []string{"mod", "tidy"}, nil); err != nil { fmt.Printf("error running go mod tidy in %s: %v\n", missingTestDetectorPath, err) } servicesDir := filepath.Join(tpgbLocalPath, "google-beta", "services") state := "success" - if _, err := r.Run("go", []string{"test"}, []string{"SERVICES_DIR=" + servicesDir}); err != nil { + if _, err := rnr.Run("go", []string{"test"}, map[string]string{"SERVICES_DIR": servicesDir}); err != nil { fmt.Printf("error from running go test in %s: %v\n", missingTestDetectorPath, err) state = "failure" } - targetURL := fmt.Sprintf("https://console.cloud.google.com/cloud-build/builds;region=global/%s;step=%s?project=%s", buildID, buildStep, projectID) - if err := gh.PostBuildStatus(prNumber, "unit-tests-missing-test-detector", state, targetURL, commit); err != nil { + targetURL := fmt.Sprintf("https://console.cloud.google.com/cloud-build/builds;region=global/%s;step=%s?project=%s", env["BUILD_ID"], env["BUILD_STEP"], env["PROJECT_ID"]) + if err := gh.PostBuildStatus(env["PR_NUMBER"], "unit-tests-missing-test-detector", state, targetURL, env["COMMIT_SHA"]); err != nil { return err } - return r.PopDir() + return rnr.PopDir() } func init() { diff --git a/.ci/magician/cmd/generate_comment_test.go b/.ci/magician/cmd/generate_comment_test.go index 88b0a28f38d8..46f90886f180 100644 --- a/.ci/magician/cmd/generate_comment_test.go +++ b/.ci/magician/cmd/generate_comment_test.go @@ -16,6 +16,7 @@ package cmd import ( + "magician/source" "reflect" "testing" ) @@ -25,9 +26,28 @@ func TestExecGenerateComment(t *testing.T) { gh := &mockGithub{ calledMethods: make(map[string][][]any), } - execGenerateComment("build1", "project1", "17", "sha1", "pr1", "*******", gh, mr) + ctlr := source.NewController("/mock/dir/go", "modular-magician", "*******", mr) + env := map[string]string{ + "BUILD_ID": "build1", + "BUILD_STEP": "17", + "COMMIT_SHA": "sha1", + "GITHUB_TOKEN": "*******", + "PR_NUMBER": "pr1", + "PROJECT_ID": "project1", + } + diffProcessorEnv := map[string]string{ + "BUILD_ID": "build1", + "BUILD_STEP": "17", + "COMMIT_SHA": "sha1", + "GITHUB_TOKEN": "*******", + "NEW_REF": "auto-pr-pr1", + "OLD_REF": "auto-pr-pr1-old", + "PR_NUMBER": "pr1", + "PROJECT_ID": "project1", + } + execGenerateComment(env, gh, mr, ctlr) - for method, expectedCalls := range map[string][][]any{ + for method, expectedCalls := range map[string][]ParameterList{ "Copy": { {"/mock/dir/tpg", "/mock/dir/magic-modules/tools/diff-processor/old"}, {"/mock/dir/tpg", "/mock/dir/magic-modules/tools/diff-processor/new"}, @@ -44,38 +64,39 @@ func TestExecGenerateComment(t *testing.T) { {"/mock/dir/magic-modules/tools/diff-processor/bin"}, }, "Run": { - {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-pr1", "https://modular-magician:*******@github.com/modular-magician/terraform-provider-google", "/mock/dir/tpg"}, []string(nil)}, - {"/mock/dir/tpg", "git", []string{"fetch", "origin", "auto-pr-pr1-old"}, []string(nil)}, - {"/mock/dir/tpg", "git", []string{"diff", "origin/auto-pr-pr1-old", "origin/auto-pr-pr1", "--shortstat"}, []string(nil)}, - {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-pr1", "https://modular-magician:*******@github.com/modular-magician/terraform-provider-google-beta", "/mock/dir/tpgb"}, []string(nil)}, - {"/mock/dir/tpgb", "git", []string{"fetch", "origin", "auto-pr-pr1-old"}, []string(nil)}, - {"/mock/dir/tpgb", "git", []string{"diff", "origin/auto-pr-pr1-old", "origin/auto-pr-pr1", "--shortstat"}, []string(nil)}, - {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-pr1", "https://modular-magician:*******@github.com/modular-magician/terraform-google-conversion", "/mock/dir/tfc"}, []string(nil)}, - {"/mock/dir/tfc", "git", []string{"fetch", "origin", "auto-pr-pr1-old"}, []string(nil)}, - {"/mock/dir/tfc", "git", []string{"diff", "origin/auto-pr-pr1-old", "origin/auto-pr-pr1", "--shortstat"}, []string(nil)}, - {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-pr1", "https://modular-magician:*******@github.com/modular-magician/docs-examples", "/mock/dir/tfoics"}, []string(nil)}, - {"/mock/dir/tfoics", "git", []string{"fetch", "origin", "auto-pr-pr1-old"}, []string(nil)}, - {"/mock/dir/tfoics", "git", []string{"diff", "origin/auto-pr-pr1-old", "origin/auto-pr-pr1", "--shortstat"}, []string(nil)}, - {"/mock/dir/magic-modules/tools/diff-processor", "make", []string{"build"}, []string{"OLD_REF=auto-pr-pr1-old", "NEW_REF=auto-pr-pr1"}}, - {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"breaking-changes"}, []string(nil)}, - {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"add-labels", "pr1"}, []string{"GITHUB_TOKEN=*******"}}, - {"/mock/dir/magic-modules/tools/diff-processor", "make", []string{"build"}, []string{"OLD_REF=auto-pr-pr1-old", "NEW_REF=auto-pr-pr1"}}, - {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"breaking-changes"}, []string(nil)}, - {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"add-labels", "pr1"}, []string{"GITHUB_TOKEN=*******"}}, - {"/mock/dir/tpgbold", "git", []string{"checkout", "origin/auto-pr-pr1-old"}, []string(nil)}, - {"/mock/dir/tpgbold", "find", []string{".", "-type", "f", "-name", "*.go", "-exec", "sed", "-i.bak", "s~github.com/hashicorp/terraform-provider-google-beta~google/provider/old~g", "{}", "+"}, []string(nil)}, - {"/mock/dir/tpgbold", "sed", []string{"-i.bak", "s|github.com/hashicorp/terraform-provider-google-beta|google/provider/old|g", "go.mod"}, []string(nil)}, - {"/mock/dir/tpgbold", "sed", []string{"-i.bak", "s|github.com/hashicorp/terraform-provider-google-beta|google/provider/old|g", "go.sum"}, []string(nil)}, - {"/mock/dir/tpgb", "find", []string{".", "-type", "f", "-name", "*.go", "-exec", "sed", "-i.bak", "s~github.com/hashicorp/terraform-provider-google-beta~google/provider/new~g", "{}", "+"}, []string(nil)}, - {"/mock/dir/tpgb", "sed", []string{"-i.bak", "s|github.com/hashicorp/terraform-provider-google-beta|google/provider/new|g", "go.mod"}, []string(nil)}, - {"/mock/dir/tpgb", "sed", []string{"-i.bak", "s|github.com/hashicorp/terraform-provider-google-beta|google/provider/new|g", "go.sum"}, []string(nil)}, - {"/mock/dir/magic-modules/tools/missing-test-detector", "go", []string{"mod", "edit", "-replace", "google/provider/new=/mock/dir/tpgb"}, []string(nil)}, - {"/mock/dir/magic-modules/tools/missing-test-detector", "go", []string{"mod", "edit", "-replace", "google/provider/old=/mock/dir/tpgbold"}, []string(nil)}, - {"/mock/dir/magic-modules/tools/missing-test-detector", "go", []string{"mod", "tidy"}, []string(nil)}, - {"/mock/dir/magic-modules/tools/missing-test-detector", "go", []string{"run", ".", "-services-dir=/mock/dir/tpgb/google-beta/services"}, []string(nil)}, - {"/mock/dir/magic-modules", "git", []string{"diff", "HEAD", "origin/main", "tools/missing-test-detector"}, []string(nil)}}, + {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-pr1", "https://modular-magician:*******@github.com/modular-magician/terraform-provider-google", "/mock/dir/tpg"}, map[string]string(nil)}, + {"/mock/dir/tpg", "git", []string{"fetch", "origin", "auto-pr-pr1-old"}, map[string]string(nil)}, + {"/mock/dir/tpg", "git", []string{"diff", "origin/auto-pr-pr1-old", "origin/auto-pr-pr1", "--shortstat"}, map[string]string(nil)}, + {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-pr1", "https://modular-magician:*******@github.com/modular-magician/terraform-provider-google-beta", "/mock/dir/tpgb"}, map[string]string(nil)}, + {"/mock/dir/tpgb", "git", []string{"fetch", "origin", "auto-pr-pr1-old"}, map[string]string(nil)}, + {"/mock/dir/tpgb", "git", []string{"diff", "origin/auto-pr-pr1-old", "origin/auto-pr-pr1", "--shortstat"}, map[string]string(nil)}, + {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-pr1", "https://modular-magician:*******@github.com/modular-magician/terraform-google-conversion", "/mock/dir/tfc"}, map[string]string(nil)}, + {"/mock/dir/tfc", "git", []string{"fetch", "origin", "auto-pr-pr1-old"}, map[string]string(nil)}, + {"/mock/dir/tfc", "git", []string{"diff", "origin/auto-pr-pr1-old", "origin/auto-pr-pr1", "--shortstat"}, map[string]string(nil)}, + {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-pr1", "https://modular-magician:*******@github.com/modular-magician/docs-examples", "/mock/dir/tfoics"}, map[string]string(nil)}, + {"/mock/dir/tfoics", "git", []string{"fetch", "origin", "auto-pr-pr1-old"}, map[string]string(nil)}, + {"/mock/dir/tfoics", "git", []string{"diff", "origin/auto-pr-pr1-old", "origin/auto-pr-pr1", "--shortstat"}, map[string]string(nil)}, + {"/mock/dir/magic-modules/tools/diff-processor", "make", []string{"build"}, diffProcessorEnv}, + {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"breaking-changes"}, map[string]string(nil)}, + {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"add-labels", "pr1"}, diffProcessorEnv}, + {"/mock/dir/magic-modules/tools/diff-processor", "make", []string{"build"}, diffProcessorEnv}, + {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"breaking-changes"}, map[string]string(nil)}, + {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"add-labels", "pr1"}, diffProcessorEnv}, + {"/mock/dir/tpgbold", "git", []string{"checkout", "origin/auto-pr-pr1-old"}, map[string]string(nil)}, + {"/mock/dir/tpgbold", "find", []string{".", "-type", "f", "-name", "*.go", "-exec", "sed", "-i.bak", "s~github.com/hashicorp/terraform-provider-google-beta~google/provider/old~g", "{}", "+"}, map[string]string(nil)}, + {"/mock/dir/tpgbold", "sed", []string{"-i.bak", "s|github.com/hashicorp/terraform-provider-google-beta|google/provider/old|g", "go.mod"}, map[string]string(nil)}, + {"/mock/dir/tpgbold", "sed", []string{"-i.bak", "s|github.com/hashicorp/terraform-provider-google-beta|google/provider/old|g", "go.sum"}, map[string]string(nil)}, + {"/mock/dir/tpgb", "find", []string{".", "-type", "f", "-name", "*.go", "-exec", "sed", "-i.bak", "s~github.com/hashicorp/terraform-provider-google-beta~google/provider/new~g", "{}", "+"}, map[string]string(nil)}, + {"/mock/dir/tpgb", "sed", []string{"-i.bak", "s|github.com/hashicorp/terraform-provider-google-beta|google/provider/new|g", "go.mod"}, map[string]string(nil)}, + {"/mock/dir/tpgb", "sed", []string{"-i.bak", "s|github.com/hashicorp/terraform-provider-google-beta|google/provider/new|g", "go.sum"}, map[string]string(nil)}, + {"/mock/dir/magic-modules/tools/missing-test-detector", "go", []string{"mod", "edit", "-replace", "google/provider/new=/mock/dir/tpgb"}, map[string]string(nil)}, + {"/mock/dir/magic-modules/tools/missing-test-detector", "go", []string{"mod", "edit", "-replace", "google/provider/old=/mock/dir/tpgbold"}, map[string]string(nil)}, + {"/mock/dir/magic-modules/tools/missing-test-detector", "go", []string{"mod", "tidy"}, map[string]string(nil)}, + {"/mock/dir/magic-modules/tools/missing-test-detector", "go", []string{"run", ".", "-services-dir=/mock/dir/tpgb/google-beta/services"}, map[string]string(nil)}, + {"/mock/dir/magic-modules", "git", []string{"diff", "HEAD", "origin/main", "tools/missing-test-detector"}, map[string]string(nil)}, + }, } { - if actualCalls, ok := mr.calledMethods[method]; !ok { + if actualCalls, ok := mr.Calls(method); !ok { t.Fatalf("Found no calls for %s", method) } else if len(actualCalls) != len(expectedCalls) { t.Fatalf("Unexpected number of calls for %s, got %d, expected %d", method, len(actualCalls), len(expectedCalls)) diff --git a/.ci/magician/cmd/interfaces.go b/.ci/magician/cmd/interfaces.go index a03bce062439..fa87eedca9cc 100644 --- a/.ci/magician/cmd/interfaces.go +++ b/.ci/magician/cmd/interfaces.go @@ -44,6 +44,6 @@ type ExecRunner interface { RemoveAll(path string) error PushDir(path string) error PopDir() error - Run(name string, args, env []string) (string, error) - MustRun(name string, args, env []string) string + Run(name string, args []string, env map[string]string) (string, error) + MustRun(name string, args []string, env map[string]string) string } diff --git a/.ci/magician/cmd/mock_runner_test.go b/.ci/magician/cmd/mock_runner_test.go index 6743e3a1e6c5..5789d9878a3f 100644 --- a/.ci/magician/cmd/mock_runner_test.go +++ b/.ci/magician/cmd/mock_runner_test.go @@ -20,45 +20,53 @@ import ( "errors" "fmt" "log" + "path/filepath" ) +type ParameterList []any + +type MockRunner interface { + ExecRunner + Calls(method string) ([]ParameterList, bool) +} + type mockRunner struct { - calledMethods map[string][][]any + calledMethods map[string][]ParameterList cmdResults map[string]string cwd string dirStack *list.List } -func NewMockRunner() *mockRunner { +func NewMockRunner() MockRunner { return &mockRunner{ - calledMethods: make(map[string][][]any), + calledMethods: make(map[string][]ParameterList), cmdResults: map[string]string{ - "/mock/dir/tfc git [clone -b auto-pr-pr1 https://modular-magician:*******@github.com/modular-magician/docs-examples /mock/dir/tfoics] []": "", - "/mock/dir/tpgb git [clone -b auto-pr-pr1 https://modular-magician:*******@github.com/modular-magician/terraform-google-conversion /mock/dir/tfc] []": "", - " git [clone -b auto-pr-pr1 https://modular-magician:*******@github.com/modular-magician/terraform-provider-google /mock/dir/tpg] []": "", - "/mock/dir/tpg git [clone -b auto-pr-pr1 https://modular-magician:*******@github.com/modular-magician/terraform-provider-google-beta /mock/dir/tpgb] []": "", - "/mock/dir/magic-modules git [diff HEAD origin/main tools/missing-test-detector] []": "", - "/mock/dir/magic-modules/tools/diff-processor bin/diff-processor [breaking-changes] []": "", - "/mock/dir/magic-modules/tools/diff-processor make [build] [OLD_REF=auto-pr-pr1-old NEW_REF=auto-pr-pr1]": "", - "/mock/dir/magic-modules/tools/missing-test-detector go [mod edit -replace google/provider/new=/mock/dir/tpgb] []": "", - "/mock/dir/magic-modules/tools/missing-test-detector go [mod edit -replace google/provider/old=/mock/dir/tpgbold] []": "", - "/mock/dir/magic-modules/tools/missing-test-detector go [mod tidy] []": "", - "/mock/dir/magic-modules/tools/missing-test-detector go [run . -services-dir=/mock/dir/tpgb/google-beta/services] []": "## Missing test report\nYour PR includes resource fields which are not covered by any test.\n\nResource: `google_folder_access_approval_settings` (3 total tests)\nPlease add an acceptance test which includes these fields. The test should include the following:\n\n```hcl\nresource \"google_folder_access_approval_settings\" \"primary\" {\n uncovered_field = # value needed\n}\n\n```\n", - "/mock/dir/tfc git [diff origin/auto-pr-pr1-old origin/auto-pr-pr1 --shortstat] []": " 1 file changed, 10 insertions(+)\n", - "/mock/dir/tfc git [fetch origin auto-pr-pr1-old] []": "", - "/mock/dir/tfoics git [diff origin/auto-pr-pr1-old origin/auto-pr-pr1 --shortstat] []": "", - "/mock/dir/tfoics git [fetch origin auto-pr-pr1-old] []": "", - "/mock/dir/tpg git [diff origin/auto-pr-pr1-old origin/auto-pr-pr1 --shortstat] []": " 2 files changed, 40 insertions(+)\n", - "/mock/dir/tpg git [fetch origin auto-pr-pr1-old] []": "", - "/mock/dir/tpgb find [. -type f -name *.go -exec sed -i.bak s~github.com/hashicorp/terraform-provider-google-beta~google/provider/new~g {} +] []": "", - "/mock/dir/tpgb git [diff origin/auto-pr-pr1-old origin/auto-pr-pr1 --shortstat] []": " 2 files changed, 40 insertions(+)\n", - "/mock/dir/tpgb git [fetch origin auto-pr-pr1-old] []": "", - "/mock/dir/tpgb sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/new|g go.mod] []": "", - "/mock/dir/tpgb sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/new|g go.sum] []": "", - "/mock/dir/tpgbold find [. -type f -name *.go -exec sed -i.bak s~github.com/hashicorp/terraform-provider-google-beta~google/provider/old~g {} +] []": "", - "/mock/dir/tpgbold git [checkout origin/auto-pr-pr1-old] []": "", - "/mock/dir/tpgbold sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/old|g go.mod] []": "", - "/mock/dir/tpgbold sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/old|g go.sum] []": "", + "/mock/dir/tfc git [clone -b auto-pr-pr1 https://modular-magician:*******@github.com/modular-magician/docs-examples /mock/dir/tfoics] map[]": "", + "/mock/dir/tpgb git [clone -b auto-pr-pr1 https://modular-magician:*******@github.com/modular-magician/terraform-google-conversion /mock/dir/tfc] map[]": "", + " git [clone -b auto-pr-pr1 https://modular-magician:*******@github.com/modular-magician/terraform-provider-google /mock/dir/tpg] map[]": "", + "/mock/dir/tpg git [clone -b auto-pr-pr1 https://modular-magician:*******@github.com/modular-magician/terraform-provider-google-beta /mock/dir/tpgb] map[]": "", + "/mock/dir/magic-modules git [diff HEAD origin/main tools/missing-test-detector] map[]": "", + "/mock/dir/magic-modules/tools/diff-processor bin/diff-processor [breaking-changes] map[]": "", + "/mock/dir/magic-modules/tools/diff-processor make [build] map[OLD_REF:auto-pr-pr1-old NEW_REF:auto-pr-pr1]": "", + "/mock/dir/magic-modules/tools/missing-test-detector go [mod edit -replace google/provider/new=/mock/dir/tpgb] map[]": "", + "/mock/dir/magic-modules/tools/missing-test-detector go [mod edit -replace google/provider/old=/mock/dir/tpgbold] map[]": "", + "/mock/dir/magic-modules/tools/missing-test-detector go [mod tidy] map[]": "", + "/mock/dir/magic-modules/tools/missing-test-detector go [run . -services-dir=/mock/dir/tpgb/google-beta/services] map[]": "## Missing test report\nYour PR includes resource fields which are not covered by any test.\n\nResource: `google_folder_access_approval_settings` (3 total tests)\nPlease add an acceptance test which includes these fields. The test should include the following:\n\n```hcl\nresource \"google_folder_access_approval_settings\" \"primary\" {\n uncovered_field = # value needed\n}\n\n```\n", + "/mock/dir/tfc git [diff origin/auto-pr-pr1-old origin/auto-pr-pr1 --shortstat] map[]": " 1 file changed, 10 insertions(+)\n", + "/mock/dir/tfc git [fetch origin auto-pr-pr1-old] map[]": "", + "/mock/dir/tfoics git [diff origin/auto-pr-pr1-old origin/auto-pr-pr1 --shortstat] map[]": "", + "/mock/dir/tfoics git [fetch origin auto-pr-pr1-old] map[]": "", + "/mock/dir/tpg git [diff origin/auto-pr-pr1-old origin/auto-pr-pr1 --shortstat] map[]": " 2 files changed, 40 insertions(+)\n", + "/mock/dir/tpg git [fetch origin auto-pr-pr1-old] map[]": "", + "/mock/dir/tpgb find [. -type f -name *.go -exec sed -i.bak s~github.com/hashicorp/terraform-provider-google-beta~google/provider/new~g {} +] map[]": "", + "/mock/dir/tpgb git [diff origin/auto-pr-pr1-old origin/auto-pr-pr1 --shortstat] map[]": " 2 files changed, 40 insertions(+)\n", + "/mock/dir/tpgb git [fetch origin auto-pr-pr1-old] map[]": "", + "/mock/dir/tpgb sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/new|g go.mod] map[]": "", + "/mock/dir/tpgb sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/new|g go.sum] map[]": "", + "/mock/dir/tpgbold find [. -type f -name *.go -exec sed -i.bak s~github.com/hashicorp/terraform-provider-google-beta~google/provider/old~g {} +] map[]": "", + "/mock/dir/tpgbold git [checkout origin/auto-pr-pr1-old] map[]": "", + "/mock/dir/tpgbold sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/old|g go.mod] map[]": "", + "/mock/dir/tpgbold sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/old|g go.sum] map[]": "", }, cwd: "/mock/dir/magic-modules/.ci/magician", dirStack: list.New(), @@ -69,13 +77,29 @@ func (mr *mockRunner) GetCWD() string { return mr.cwd } +func (mr *mockRunner) Mkdir(path string) error { + return nil +} + +func (mr *mockRunner) Walk(root string, fn filepath.WalkFunc) error { + return nil +} + +func (mr *mockRunner) ReadFile(name string) (string, error) { + return "", nil +} + +func (mr *mockRunner) WriteFile(name, data string) error { + return nil +} + func (mr *mockRunner) Copy(src, dest string) error { - mr.calledMethods["Copy"] = append(mr.calledMethods["Copy"], []any{src, dest}) + mr.calledMethods["Copy"] = append(mr.calledMethods["Copy"], ParameterList{src, dest}) return nil } func (mr *mockRunner) RemoveAll(path string) error { - mr.calledMethods["RemoveAll"] = append(mr.calledMethods["RemoveAll"], []any{path}) + mr.calledMethods["RemoveAll"] = append(mr.calledMethods["RemoveAll"], ParameterList{path}) return nil } @@ -101,8 +125,8 @@ func (mr *mockRunner) PopDir() error { return nil } -func (mr *mockRunner) Run(name string, args, env []string) (string, error) { - mr.calledMethods["Run"] = append(mr.calledMethods["Run"], []any{mr.cwd, name, args, env}) +func (mr *mockRunner) Run(name string, args []string, env map[string]string) (string, error) { + mr.calledMethods["Run"] = append(mr.calledMethods["Run"], ParameterList{mr.cwd, name, args, env}) cmd := fmt.Sprintf("%s %s %v %v", mr.cwd, name, args, env) if result, ok := mr.cmdResults[cmd]; ok { return result, nil @@ -111,10 +135,15 @@ func (mr *mockRunner) Run(name string, args, env []string) (string, error) { return "", nil } -func (mr *mockRunner) MustRun(name string, args, env []string) string { +func (mr *mockRunner) MustRun(name string, args []string, env map[string]string) string { out, err := mr.Run(name, args, env) if err != nil { log.Fatal(err) } return out } + +func (mr *mockRunner) Calls(method string) ([]ParameterList, bool) { + calls, ok := mr.calledMethods[method] + return calls, ok +} diff --git a/.ci/magician/exec/runner.go b/.ci/magician/exec/runner.go index 5d746f7a963d..4d85ece99189 100644 --- a/.ci/magician/exec/runner.go +++ b/.ci/magician/exec/runner.go @@ -19,6 +19,7 @@ import ( "container/list" "errors" "fmt" + "io/fs" "log" "os" "os/exec" @@ -51,6 +52,14 @@ func (ar *Runner) Copy(src, dest string) error { return cp.Copy(ar.abs(src), ar.abs(dest)) } +func (ar *Runner) Mkdir(path string) error { + return os.MkdirAll(ar.abs(path), 0777) +} + +func (ar *Runner) Walk(root string, fn filepath.WalkFunc) error { + return filepath.Walk(root, fn) +} + func (ar *Runner) RemoveAll(path string) error { return os.RemoveAll(ar.abs(path)) } @@ -83,19 +92,34 @@ func (ar *Runner) WriteFile(name, data string) error { return os.WriteFile(ar.abs(name), []byte(data), 0644) } -func (ar *Runner) Run(name string, args, env []string) (string, error) { +func (ar *Runner) ReadFile(name string) (string, error) { + data, err := os.ReadFile(ar.abs(name)) + if err != nil { + return "", err + } + return string(data), nil +} + +// Run the given command with the given args and env, return output and error if any +func (ar *Runner) Run(name string, args []string, env map[string]string) (string, error) { cmd := exec.Command(name, args...) cmd.Dir = ar.cwd - cmd.Env = append(os.Environ(), env...) + for ev, val := range env { + cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", ev, val)) + } out, err := cmd.Output() - if err != nil { - exitErr := err.(*exec.ExitError) - return string(out), fmt.Errorf("error running %s: %v\nstdout:\n%sstderr:\n%s", name, err, out, exitErr.Stderr) + switch typedErr := err.(type) { + case *exec.ExitError: + return string(out), fmt.Errorf("error running %s: %v\nstdout:\n%sstderr:\n%s", name, err, out, typedErr.Stderr) + case *fs.PathError: + return "", fmt.Errorf("path error running %s: %v", name, typedErr) + } return string(out), nil } -func (ar *Runner) MustRun(name string, args, env []string) string { +// Run the command and exit if there's an error. +func (ar *Runner) MustRun(name string, args []string, env map[string]string) string { out, err := ar.Run(name, args, env) if err != nil { log.Fatal(err) diff --git a/.ci/magician/provider/version.go b/.ci/magician/provider/version.go new file mode 100644 index 000000000000..7c98f3817e29 --- /dev/null +++ b/.ci/magician/provider/version.go @@ -0,0 +1,37 @@ +package provider + +type Version int + +const ( + GA Version = iota + Beta +) + +const NumVersions = 2 + +func (v Version) String() string { + switch v { + case GA: + return "ga" + case Beta: + return "beta" + } + return "unknown" +} + +func (v Version) BucketPath() string { + if v == GA { + return "" + } + return v.String() + "/" +} + +func (v Version) RepoName() string { + switch v { + case GA: + return "terraform-provider-google" + case Beta: + return "terraform-provider-google-beta" + } + return "unknown" +} diff --git a/.ci/magician/source/repo.go b/.ci/magician/source/repo.go new file mode 100644 index 000000000000..20b7a4f52ec4 --- /dev/null +++ b/.ci/magician/source/repo.go @@ -0,0 +1,85 @@ +package source + +import ( + "fmt" + "path/filepath" + "strings" +) + +type Repo struct { + Name string // Name in GitHub (e.g. magic-modules) + Title string // Title for display (e.g. Magic Modules) + Branch string // Branch to clone, optional + Path string // local Path once cloned, including Name + DiffCanFail bool // whether to allow the command to continue if cloning or diffing the repo fails +} + +type Controller struct { + rnr Runner + username string + token string + goPath string +} + +type Runner interface { + PushDir(path string) error + PopDir() error + Run(name string, args []string, env map[string]string) (string, error) +} + +func NewController(goPath, username, token string, rnr Runner) *Controller { + return &Controller{ + rnr: rnr, + username: username, + token: token, + goPath: goPath, + } +} + +func (gc Controller) SetPath(repo *Repo) { + repo.Path = filepath.Join(gc.goPath, "src", "github.com", gc.username, repo.Name) +} + +func (gc Controller) Clone(repo *Repo) error { + var err error + url := fmt.Sprintf("https://%s:%s@github.com/%s/%s", gc.username, gc.token, gc.username, repo.Name) + if repo.Branch == "" { + _, err = gc.rnr.Run("git", []string{"clone", url, repo.Path}, nil) + } else { + _, err = gc.rnr.Run("git", []string{"clone", "-b", repo.Branch, url, repo.Path}, nil) + } + if err != nil { + if strings.Contains(err.Error(), "already exists and is not an empty directory") { + return nil + } + } + return err +} + +func (gc Controller) Fetch(repo *Repo, branch string) error { + if err := gc.rnr.PushDir(repo.Path); err != nil { + return err + } + if _, err := gc.rnr.Run("git", []string{"fetch", "origin", branch}, nil); err != nil { + return fmt.Errorf("error fetching branch %s in repo %s: %v\n", branch, repo.Name, err) + } + return gc.rnr.PopDir() +} + +func (gc Controller) Diff(repo *Repo, oldBranch, newBranch string) (string, error) { + if err := gc.rnr.PushDir(repo.Path); err != nil { + return "", err + } + diffs, err := gc.rnr.Run("git", []string{"diff", "origin/" + oldBranch, "origin/" + newBranch, "--shortstat"}, nil) + if err != nil { + return "", fmt.Errorf("error diffing %s and %s: %v", oldBranch, newBranch, err) + } + return diffs, gc.rnr.PopDir() +} + +func (gc Controller) Cleanup(repo *Repo) error { + if _, err := gc.rnr.Run("rm", []string{"-rf", repo.Path}, nil); err != nil { + return err + } + return nil +} diff --git a/.ci/scripts/go-plus/magician/exec.sh b/.ci/scripts/go-plus/magician/exec.sh index acd9714f09bd..a0cb4078e6b6 100755 --- a/.ci/scripts/go-plus/magician/exec.sh +++ b/.ci/scripts/go-plus/magician/exec.sh @@ -4,7 +4,7 @@ DIR="$(dirname $(realpath $0))" # Construct the path to the Go program directory and binary -GO_PROGRAM_DIR="$DIR/../../../magician/" +GO_PROGRAM_DIR="$DIR/../../../magician" GO_BINARY="$GO_PROGRAM_DIR/magician_binary" pushd $GO_PROGRAM_DIR diff --git a/.gitignore b/.gitignore index 76a5461db4c2..4aa28d6971f5 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,6 @@ mmv1/build/* tpgtools/temp.serial tpgtools/serialization.go + +# ignore magician binary +.ci/magician/magician From b3ae8dcd7e476f796a8b1ba67ce63cea711be127 Mon Sep 17 00:00:00 2001 From: David Glasser Date: Thu, 14 Dec 2023 15:51:57 -0800 Subject: [PATCH 25/27] Replace "Pubsub Subscription Different Project" example with making all examples cross-project-friendly (#9637) * Fix "Pubsub Subscription Different Project" example PR #2342 changed this example from using `id` to `name`, which removed the project ID from the topic. However, the point of this example is to show how to set up a cross-project subscription, so the example no longer works. This change reverts that change from PR #2342. Fixes hashicorp/terraform-provider-google#11642. Fixes hashicorp/terraform-provider-google#6024. * Make all examples cross-project-friendly and update topic description * Fix typo --------- Co-authored-by: Stephen Lewis (Burrows) --- mmv1/products/pubsub/Subscription.yaml | 13 +++---------- .../examples/pubsub_subscription_dead_letter.tf.erb | 2 +- .../pubsub_subscription_different_project.tf.erb | 10 ---------- .../examples/pubsub_subscription_pull.tf.erb | 2 +- .../examples/pubsub_subscription_push.tf.erb | 2 +- .../examples/pubsub_subscription_push_bq.tf.erb | 2 +- .../pubsub_subscription_push_cloudstorage.tf.erb | 2 +- ...ubsub_subscription_push_cloudstorage_avro.tf.erb | 2 +- 8 files changed, 9 insertions(+), 26 deletions(-) delete mode 100644 mmv1/templates/terraform/examples/pubsub_subscription_different_project.tf.erb diff --git a/mmv1/products/pubsub/Subscription.yaml b/mmv1/products/pubsub/Subscription.yaml index 1def915ef94c..c8db8edf8f1a 100644 --- a/mmv1/products/pubsub/Subscription.yaml +++ b/mmv1/products/pubsub/Subscription.yaml @@ -42,15 +42,6 @@ examples: vars: topic_name: 'example-topic' subscription_name: 'example-subscription' - - !ruby/object:Provider::Terraform::Examples - name: 'pubsub_subscription_different_project' - primary_resource_id: 'example' - skip_test: true - vars: - topic_name: 'example-topic' - topic_project: 'topic-project' - subscription_name: 'example-subscription' - subscription_project: 'subscription-project' - !ruby/object:Provider::Terraform::Examples name: 'pubsub_subscription_dead_letter' primary_resource_id: 'example' @@ -101,7 +92,9 @@ properties: resource: 'Topic' imports: 'name' description: | - A reference to a Topic resource. + A reference to a Topic resource, of the form projects/{project}/topics/{{name}} + (as in the id property of a google_pubsub_topic), or just a topic name if + the topic is in the same project as the subscription. required: true immutable: true pattern: 'projects/{{project}}/topics/{{topic}}' diff --git a/mmv1/templates/terraform/examples/pubsub_subscription_dead_letter.tf.erb b/mmv1/templates/terraform/examples/pubsub_subscription_dead_letter.tf.erb index e7274d16f004..f5b66321767d 100644 --- a/mmv1/templates/terraform/examples/pubsub_subscription_dead_letter.tf.erb +++ b/mmv1/templates/terraform/examples/pubsub_subscription_dead_letter.tf.erb @@ -8,7 +8,7 @@ resource "google_pubsub_topic" "<%= ctx[:primary_resource_id] %>_dead_letter" { resource "google_pubsub_subscription" "<%= ctx[:primary_resource_id] %>" { name = "<%= ctx[:vars]['subscription_name'] %>" - topic = google_pubsub_topic.<%= ctx[:primary_resource_id] %>.name + topic = google_pubsub_topic.<%= ctx[:primary_resource_id] %>.id dead_letter_policy { dead_letter_topic = google_pubsub_topic.<%= ctx[:primary_resource_id] %>_dead_letter.id diff --git a/mmv1/templates/terraform/examples/pubsub_subscription_different_project.tf.erb b/mmv1/templates/terraform/examples/pubsub_subscription_different_project.tf.erb deleted file mode 100644 index 4bf08dfe2460..000000000000 --- a/mmv1/templates/terraform/examples/pubsub_subscription_different_project.tf.erb +++ /dev/null @@ -1,10 +0,0 @@ -resource "google_pubsub_topic" "<%= ctx[:primary_resource_id] %>" { - project = "<%= ctx[:vars]['topic_project'] %>" - name = "<%= ctx[:vars]['topic_name'] %>" -} - -resource "google_pubsub_subscription" "<%= ctx[:primary_resource_id] %>" { - project = "<%= ctx[:vars]['subscription_project'] %>" - name = "<%= ctx[:vars]['subscription_name'] %>" - topic = google_pubsub_topic.<%= ctx[:primary_resource_id] %>.name -} diff --git a/mmv1/templates/terraform/examples/pubsub_subscription_pull.tf.erb b/mmv1/templates/terraform/examples/pubsub_subscription_pull.tf.erb index 35e10f60bcb5..7daa29c14275 100644 --- a/mmv1/templates/terraform/examples/pubsub_subscription_pull.tf.erb +++ b/mmv1/templates/terraform/examples/pubsub_subscription_pull.tf.erb @@ -4,7 +4,7 @@ resource "google_pubsub_topic" "<%= ctx[:primary_resource_id] %>" { resource "google_pubsub_subscription" "<%= ctx[:primary_resource_id] %>" { name = "<%= ctx[:vars]['subscription_name'] %>" - topic = google_pubsub_topic.<%= ctx[:primary_resource_id] %>.name + topic = google_pubsub_topic.<%= ctx[:primary_resource_id] %>.id labels = { foo = "bar" diff --git a/mmv1/templates/terraform/examples/pubsub_subscription_push.tf.erb b/mmv1/templates/terraform/examples/pubsub_subscription_push.tf.erb index 690cbca6aa6e..631f19321888 100644 --- a/mmv1/templates/terraform/examples/pubsub_subscription_push.tf.erb +++ b/mmv1/templates/terraform/examples/pubsub_subscription_push.tf.erb @@ -4,7 +4,7 @@ resource "google_pubsub_topic" "<%= ctx[:primary_resource_id] %>" { resource "google_pubsub_subscription" "<%= ctx[:primary_resource_id] %>" { name = "<%= ctx[:vars]['subscription_name'] %>" - topic = google_pubsub_topic.<%= ctx[:primary_resource_id] %>.name + topic = google_pubsub_topic.<%= ctx[:primary_resource_id] %>.id ack_deadline_seconds = 20 diff --git a/mmv1/templates/terraform/examples/pubsub_subscription_push_bq.tf.erb b/mmv1/templates/terraform/examples/pubsub_subscription_push_bq.tf.erb index 9bc5915278d4..77866e8e0b65 100644 --- a/mmv1/templates/terraform/examples/pubsub_subscription_push_bq.tf.erb +++ b/mmv1/templates/terraform/examples/pubsub_subscription_push_bq.tf.erb @@ -4,7 +4,7 @@ resource "google_pubsub_topic" "<%= ctx[:primary_resource_id] %>" { resource "google_pubsub_subscription" "<%= ctx[:primary_resource_id] %>" { name = "<%= ctx[:vars]['subscription_name'] %>" - topic = google_pubsub_topic.<%= ctx[:primary_resource_id] %>.name + topic = google_pubsub_topic.<%= ctx[:primary_resource_id] %>.id bigquery_config { table = "${google_bigquery_table.test.project}.${google_bigquery_table.test.dataset_id}.${google_bigquery_table.test.table_id}" diff --git a/mmv1/templates/terraform/examples/pubsub_subscription_push_cloudstorage.tf.erb b/mmv1/templates/terraform/examples/pubsub_subscription_push_cloudstorage.tf.erb index 5f89e82f2cb1..e946dada186e 100644 --- a/mmv1/templates/terraform/examples/pubsub_subscription_push_cloudstorage.tf.erb +++ b/mmv1/templates/terraform/examples/pubsub_subscription_push_cloudstorage.tf.erb @@ -10,7 +10,7 @@ resource "google_pubsub_topic" "<%= ctx[:primary_resource_id] %>" { resource "google_pubsub_subscription" "<%= ctx[:primary_resource_id] %>" { name = "<%= ctx[:vars]['subscription_name'] %>" - topic = google_pubsub_topic.<%= ctx[:primary_resource_id] %>.name + topic = google_pubsub_topic.<%= ctx[:primary_resource_id] %>.id cloud_storage_config { bucket = google_storage_bucket.<%= ctx[:primary_resource_id] %>.name diff --git a/mmv1/templates/terraform/examples/pubsub_subscription_push_cloudstorage_avro.tf.erb b/mmv1/templates/terraform/examples/pubsub_subscription_push_cloudstorage_avro.tf.erb index 1692813943e5..8df2217e7b5a 100644 --- a/mmv1/templates/terraform/examples/pubsub_subscription_push_cloudstorage_avro.tf.erb +++ b/mmv1/templates/terraform/examples/pubsub_subscription_push_cloudstorage_avro.tf.erb @@ -10,7 +10,7 @@ resource "google_pubsub_topic" "<%= ctx[:primary_resource_id] %>" { resource "google_pubsub_subscription" "<%= ctx[:primary_resource_id] %>" { name = "<%= ctx[:vars]['subscription_name'] %>" - topic = google_pubsub_topic.<%= ctx[:primary_resource_id] %>.name + topic = google_pubsub_topic.<%= ctx[:primary_resource_id] %>.id cloud_storage_config { bucket = google_storage_bucket.<%= ctx[:primary_resource_id] %>.name From e82ccc2f1c23922a49080ee5095912249f933c2c Mon Sep 17 00:00:00 2001 From: bcreddy-gcp <123543489+bcreddy-gcp@users.noreply.github.com> Date: Fri, 15 Dec 2023 05:32:34 +0530 Subject: [PATCH 26/27] ignore output only fields in update test to fix TestAccNotebooksInstance_update test (#9634) --- .../notebooks/resource_notebooks_instance_test.go.erb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 705d632e51db..6306f1a88f93 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 @@ -47,7 +47,7 @@ func TestAccNotebooksInstance_update(t *testing.T) { ResourceName: "google_notebooks_instance.instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"vm_image", "metadata", "update_time"}, + ImportStateVerifyIgnore: []string{"vm_image", "metadata", "update_time", "proxy_uri", "state"}, }, { Config: testAccNotebooksInstance_update(context, true), @@ -56,7 +56,7 @@ func TestAccNotebooksInstance_update(t *testing.T) { ResourceName: "google_notebooks_instance.instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"vm_image", "metadata", "labels", "terraform_labels", "update_time"}, + ImportStateVerifyIgnore: []string{"vm_image", "metadata", "labels", "terraform_labels", "update_time", "proxy_uri", "state"}, }, { 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", "labels", "terraform_labels", "update_time"}, + ImportStateVerifyIgnore: []string{"vm_image", "metadata", "labels", "terraform_labels", "update_time", "proxy_uri", "state"}, }, }, }) From a0fc14d3bbe079863664c8e90c5d0206eb02ce94 Mon Sep 17 00:00:00 2001 From: Salome Papiashvili Date: Fri, 15 Dec 2023 01:07:58 +0100 Subject: [PATCH 27/27] bump go epi client version to 0.154.0 (#9635) --- mmv1/third_party/terraform/go.mod.erb | 32 +++++++---- mmv1/third_party/terraform/go.sum | 81 ++++++++++++++++++--------- 2 files changed, 74 insertions(+), 39 deletions(-) diff --git a/mmv1/third_party/terraform/go.mod.erb b/mmv1/third_party/terraform/go.mod.erb index 4a7de9491de0..3971c83d3b64 100644 --- a/mmv1/third_party/terraform/go.mod.erb +++ b/mmv1/third_party/terraform/go.mod.erb @@ -24,11 +24,11 @@ require ( github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/hashstructure v1.1.0 github.com/sirupsen/logrus v1.8.1 - golang.org/x/net v0.18.0 - golang.org/x/oauth2 v0.14.0 - google.golang.org/api v0.152.0 - google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f - google.golang.org/grpc v1.59.0 + golang.org/x/net v0.19.0 + golang.org/x/oauth2 v0.15.0 + google.golang.org/api v0.154.0 + google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 + google.golang.org/grpc v1.60.0 google.golang.org/protobuf v1.31.0 ) @@ -49,14 +49,17 @@ require ( github.com/envoyproxy/go-control-plane v0.11.1 // indirect github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect github.com/fatih/color v1.13.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/gammazero/deque v0.0.0-20180920172122-f6adf94963e4 // indirect + github.com/go-logr/logr v1.3.0 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/glog v1.1.2 // 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.6.0 // indirect github.com/google/go-cpy v0.0.0-20211218193943-a9c933c06932 // indirect github.com/google/s2a-go v0.1.7 // indirect - github.com/google/uuid v1.4.0 // indirect + github.com/google/uuid v1.5.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/gax-go/v2 v2.12.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect @@ -85,14 +88,19 @@ require ( github.com/vmihailenco/tagparser v0.1.2 // indirect github.com/zclconf/go-cty v1.11.0 // indirect go.opencensus.io v0.24.0 // indirect - golang.org/x/crypto v0.15.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect + go.opentelemetry.io/otel v1.21.0 // indirect + go.opentelemetry.io/otel/metric v1.21.0 // indirect + go.opentelemetry.io/otel/trace v1.21.0 // indirect + golang.org/x/crypto v0.16.0 // indirect golang.org/x/sync v0.5.0 // indirect - golang.org/x/sys v0.14.0 // indirect + golang.org/x/sys v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f // indirect gopkg.in/yaml.v2 v2.4.0 // indirect -) +) \ No newline at end of file diff --git a/mmv1/third_party/terraform/go.sum b/mmv1/third_party/terraform/go.sum index 62430b733c77..e3268ae87089 100644 --- a/mmv1/third_party/terraform/go.sum +++ b/mmv1/third_party/terraform/go.sum @@ -15,8 +15,6 @@ cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXE cloud.google.com/go/longrunning v0.5.4 h1:w8xEcbZodnA2BbW6sVirkkoC+1gP8wS57EUUgGS0GVg= cloud.google.com/go/longrunning v0.5.4/go.mod h1:zqNVncI0BOP8ST6XQD1+VcvuShMmq7+xFSzOL++V0dI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.57.0 h1:Rz/Jlnt195m9B8CJPQejuTbXaPCoB1w1QYQjD4oKHMk= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.57.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= github.com/GoogleCloudPlatform/declarative-resource-client-library v1.59.0 h1:jL4ac+IUrVftmfduFslaMXWj9ENuiXEiwZFw3U5ikUA= github.com/GoogleCloudPlatform/declarative-resource-client-library v1.59.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= @@ -70,6 +68,8 @@ github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBF github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/gammazero/deque v0.0.0-20180920172122-f6adf94963e4 h1:R+19WKQClnfMXS60cP5BmMe1wjZ4u0evY2p2Ar0ZTXo= github.com/gammazero/deque v0.0.0-20180920172122-f6adf94963e4/go.mod h1:GeIq9qoE43YdGnDXURnmKTnGg15pQz4mYkXSTChbneI= @@ -86,6 +86,11 @@ github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -111,6 +116,7 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= @@ -130,8 +136,8 @@ github.com/google/go-cpy v0.0.0-20211218193943-a9c933c06932/go.mod h1:cC6EdPbj/1 github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= +github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= @@ -260,7 +266,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 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.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= 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= @@ -273,6 +279,7 @@ github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= github.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= @@ -281,6 +288,16 @@ github.com/zclconf/go-cty v1.11.0/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeW github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= +go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= +go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= +go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= +go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= +go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= +go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= @@ -291,14 +308,16 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= -golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -316,18 +335,20 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= -golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= -golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.14.0 h1:P0Vrf/2538nmC0H+pEQ3MNFRRnVR7RlqyVw+bvm26z0= -golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM= +golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= +golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -350,14 +371,19 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= -golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +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.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= @@ -370,37 +396,38 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/api v0.152.0 h1:t0r1vPnfMc260S2Ci+en7kfCZaLOPs5KI0sVV/6jZrY= -google.golang.org/api v0.152.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= +google.golang.org/api v0.154.0 h1:X7QkVKZBskztmpPKWQXgjJRPA2dJYrL6r+sYPRLj050= +google.golang.org/api v0.154.0/go.mod h1:qhSMkM85hgqiokIYsrRyKxrjfBeIhgl4Z2JmeRkYylc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ= -google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY= -google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo= -google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= +google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3 h1:1hfbdAfFbkmpg41000wDVqr7jUpK/Yo+LPnIxxGzmkg= +google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3/go.mod h1:5RBcpGRxr25RbDzY5w+dmaqpSEvl8Gwl1x2CICf60ic= +google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f h1:2yNACc1O40tTnrsbk9Cv6oxiW8pxI/pXj0wRtdlYmgY= +google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f/go.mod h1:Uy9bTZJqmfrw2rIBxgGLnamc78euZULUBrLZ9XTITKI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 h1:/jFB8jK5R3Sq3i/lmeZO0cATSzFfZaJq1J2Euan3XKU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0/go.mod h1:FUoWkonphQm3RhTS+kOEhF8h0iDpm4tdXolVCeZ9KKA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/grpc v1.60.0 h1:6FQAR0kM31P6MRdeluor2w2gPaS4SVNrD/DNTxrQ15k= +google.golang.org/grpc v1.60.0/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -432,4 +459,4 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= +rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= \ No newline at end of file