From 3767b0ed02c90889f2656ba9deb557e560b19ca2 Mon Sep 17 00:00:00 2001 From: Harshika Jain Date: Fri, 18 Oct 2024 01:01:38 +0530 Subject: [PATCH] Update `google_sql_database` and `google_sql_user` to not do Read actions when instance is not active (#11866) Co-authored-by: Sarah French <15078782+SarahFrench@users.noreply.github.com> --- mmv1/products/sql/Database.yaml | 1 + .../sql_database_activation_policy.tmpl | 8 +++ .../sql/resource_sql_database_test.go | 68 ++++++++++++++++++- .../services/sql/resource_sql_user.go | 12 ++-- .../services/sql/resource_sql_user_test.go | 59 ++++++++++++++++ 5 files changed, 140 insertions(+), 8 deletions(-) create mode 100644 mmv1/templates/terraform/pre_read/sql_database_activation_policy.tmpl diff --git a/mmv1/products/sql/Database.yaml b/mmv1/products/sql/Database.yaml index 01f4a62d6247..089cb3384f0c 100644 --- a/mmv1/products/sql/Database.yaml +++ b/mmv1/products/sql/Database.yaml @@ -48,6 +48,7 @@ async: collection_url_key: 'items' custom_code: pre_delete: 'templates/terraform/pre_delete/sql_database_deletion_policy.tmpl' + pre_read: 'templates/terraform/pre_read/sql_database_activation_policy.tmpl' # Sweeper skipped as this resource has customized deletion. exclude_sweeper: true read_error_transform: 'transformSQLDatabaseReadError' diff --git a/mmv1/templates/terraform/pre_read/sql_database_activation_policy.tmpl b/mmv1/templates/terraform/pre_read/sql_database_activation_policy.tmpl new file mode 100644 index 000000000000..582504e94e11 --- /dev/null +++ b/mmv1/templates/terraform/pre_read/sql_database_activation_policy.tmpl @@ -0,0 +1,8 @@ +instance := d.Get("instance").(string) +databaseInstance, err := config.NewSqlAdminClient(userAgent).Instances.Get(project, instance).Do() + if err != nil { + return err + } + if databaseInstance.Settings.ActivationPolicy != "ALWAYS" { + return nil + } \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_database_test.go b/mmv1/third_party/terraform/services/sql/resource_sql_database_test.go index aabe707bc983..939a8fa37fdc 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_database_test.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_database_test.go @@ -157,9 +157,9 @@ func testAccCheckGoogleSqlDatabaseExists(t *testing.T, n string, database *sqlad *database = *found - return nil - } -} + return nil + } + } func testAccSqlDatabaseDestroyProducer(t *testing.T) func(s *terraform.State) error { return func(s *terraform.State) error { @@ -183,6 +183,68 @@ func testAccSqlDatabaseDestroyProducer(t *testing.T) func(s *terraform.State) er } } +func TestAccSqlDatabase_instanceWithActivationPolicy(t *testing.T) { + t.Parallel() + + var database sqladmin.Database + + instance_name := fmt.Sprintf("tf-test-%d", acctest.RandInt(t)) + database_name := fmt.Sprintf("tf-test-%d", acctest.RandInt(t)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccSqlDatabaseDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testGoogleSqlDatabase_instanceWithActivationPolicy(instance_name, database_name , "ALWAYS"), + Check: resource.ComposeTestCheckFunc( + testAccCheckGoogleSqlDatabaseExists( + t, "google_sql_database.database", &database), + ), + }, + // Step 2: Update activation_policy to NEVER + { + Config: testGoogleSqlDatabase_instanceWithActivationPolicy(instance_name, database_name, "NEVER"), + }, + // Step 3: Refresh to verify no errors + { + Config: testGoogleSqlDatabase_instanceWithActivationPolicy(instance_name, database_name, "NEVER"), + }, + // Step 4: Update activation_policy to ALWAYS so that post-test destroy code is able to delete the google_sql_database resource + { + Config: testGoogleSqlDatabase_instanceWithActivationPolicy(instance_name, database_name, "ALWAYS"), + Check: resource.ComposeTestCheckFunc( + testAccCheckGoogleSqlDatabaseExists( + t, "google_sql_database.database", &database), + ), + }, + }, + }) +} + +func testGoogleSqlDatabase_instanceWithActivationPolicy(instance_name, database_name, activationPolicy string) string { + return fmt.Sprintf(` +resource "google_sql_database_instance" "instance" { + name = "%s" + database_version = "MYSQL_5_7" + region = "us-central1" + deletion_protection = false + settings { + tier = "db-f1-micro" + availability_type = "ZONAL" + activation_policy = "%s" + } +} + +resource "google_sql_database" "database" { + name = "%s" + instance = google_sql_database_instance.instance.name + } +`, instance_name, activationPolicy, database_name,) +} + + var testGoogleSqlDatabase_basic = ` resource "google_sql_database_instance" "instance" { name = "%s" diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_user.go b/mmv1/third_party/terraform/services/sql/resource_sql_user.go index c507f883f122..f54e1fdac50a 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_user.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_user.go @@ -326,6 +326,13 @@ func resourceSqlUserRead(d *schema.ResourceData, meta interface{}) error { instance := d.Get("instance").(string) name := d.Get("name").(string) host := d.Get("host").(string) + databaseInstance, err := config.NewSqlAdminClient(userAgent).Instances.Get(project, instance).Do() + if err != nil { + return err + } + if databaseInstance.Settings.ActivationPolicy != "ALWAYS" { + return nil + } var users *sqladmin.UsersListResponse err = nil @@ -342,11 +349,6 @@ func resourceSqlUserRead(d *schema.ResourceData, meta interface{}) error { } var user *sqladmin.User - databaseInstance, err := config.NewSqlAdminClient(userAgent).Instances.Get(project, instance).Do() - if err != nil { - return err - } - for _, currentUser := range users.Items { var username string if !(strings.Contains(databaseInstance.DatabaseVersion, "POSTGRES") || currentUser.Type == "CLOUD_IAM_GROUP") { diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_user_test.go b/mmv1/third_party/terraform/services/sql/resource_sql_user_test.go index 80c50c7363ce..a14ad85a4fe2 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_user_test.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_user_test.go @@ -324,6 +324,65 @@ func TestAccSqlUser_mysqlPasswordPolicy(t *testing.T) { }) } +func TestAccSqlUser_instanceWithActivationPolicy(t *testing.T) { + // Multiple fine-grained resources + acctest.SkipIfVcr(t) + t.Parallel() + + instance := fmt.Sprintf("tf-test-%d", acctest.RandInt(t)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccSqlUserDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testGoogleSqlUser_instanceWithActivationPolicy(instance, "ALWAYS"), + Check: resource.ComposeTestCheckFunc( + testAccCheckGoogleSqlUserExists(t, "google_sql_user.user"), + ), + }, + // Step 2: Update activation_policy to NEVER + { + Config: testGoogleSqlUser_instanceWithActivationPolicy(instance, "NEVER"), + }, + // Step 3: Refresh to verify no errors + { + Config: testGoogleSqlUser_instanceWithActivationPolicy(instance, "NEVER"), + }, + // Step 4: Update activation_policy to ALWAYS so that post-test destroy code is able to delete the google_sql_user resource + { + Config: testGoogleSqlUser_instanceWithActivationPolicy(instance, "ALWAYS"), + Check: resource.ComposeTestCheckFunc( + testAccCheckGoogleSqlUserExists(t, "google_sql_user.user"), + ), + }, + }, + }) +} + +func testGoogleSqlUser_instanceWithActivationPolicy(instance, activationPolicy string) string { + return fmt.Sprintf(` +resource "google_sql_database_instance" "instance" { + name = "%s" + database_version = "MYSQL_5_7" + region = "us-central1" + deletion_protection = false + settings { + tier = "db-f1-micro" + availability_type = "ZONAL" + activation_policy = "%s" + } +} + +resource "google_sql_user" "user" { + name = "admin" + instance = google_sql_database_instance.instance.name + password = "password" + } +`, instance, activationPolicy) +} + func testGoogleSqlUser_mysql(instance, password string) string { return fmt.Sprintf(` resource "google_sql_database_instance" "instance" {