From 0d1718fa838803d412f23b1cd398e49ce0290a4d Mon Sep 17 00:00:00 2001 From: Dana Hoffman Date: Wed, 31 May 2017 15:19:27 -0400 Subject: [PATCH] provider/google: use a mutex to prevent concurrent sql instance operations (#14424) --- .../providers/google/resource_sql_database.go | 4 ++ .../google/resource_sql_database_instance.go | 4 ++ .../resource_sql_database_instance_test.go | 41 +++++++++++++++++++ builtin/providers/google/resource_sql_user.go | 6 +++ 4 files changed, 55 insertions(+) diff --git a/builtin/providers/google/resource_sql_database.go b/builtin/providers/google/resource_sql_database.go index e8df24a70..a6b034aa5 100644 --- a/builtin/providers/google/resource_sql_database.go +++ b/builtin/providers/google/resource_sql_database.go @@ -57,6 +57,8 @@ func resourceSqlDatabaseCreate(d *schema.ResourceData, meta interface{}) error { Instance: instance_name, } + mutexKV.Lock(instanceMutexKey(project, instance_name)) + defer mutexKV.Unlock(instanceMutexKey(project, instance_name)) op, err := config.clientSqlAdmin.Databases.Insert(project, instance_name, db).Do() @@ -111,6 +113,8 @@ func resourceSqlDatabaseDelete(d *schema.ResourceData, meta interface{}) error { database_name := d.Get("name").(string) instance_name := d.Get("instance").(string) + mutexKV.Lock(instanceMutexKey(project, instance_name)) + defer mutexKV.Unlock(instanceMutexKey(project, instance_name)) op, err := config.clientSqlAdmin.Databases.Delete(project, instance_name, database_name).Do() diff --git a/builtin/providers/google/resource_sql_database_instance.go b/builtin/providers/google/resource_sql_database_instance.go index 893562723..109c25a88 100644 --- a/builtin/providers/google/resource_sql_database_instance.go +++ b/builtin/providers/google/resource_sql_database_instance.go @@ -1172,3 +1172,7 @@ func validateNumericRange(v interface{}, k string, min int, max int) (ws []strin } return } + +func instanceMutexKey(project, instance_name string) string { + return fmt.Sprintf("google-sql-database-instance-%s-%s", project, instance_name) +} diff --git a/builtin/providers/google/resource_sql_database_instance_test.go b/builtin/providers/google/resource_sql_database_instance_test.go index 479342c04..c553cbc44 100644 --- a/builtin/providers/google/resource_sql_database_instance_test.go +++ b/builtin/providers/google/resource_sql_database_instance_test.go @@ -277,6 +277,24 @@ func TestAccGoogleSqlDatabaseInstance_authNets(t *testing.T) { }) } +// Tests that a SQL instance can be referenced from more than one other resource without +// throwing an error during provisioning, see #9018. +func TestAccGoogleSqlDatabaseInstance_multipleOperations(t *testing.T) { + databaseID, instanceID, userID := acctest.RandString(8), acctest.RandString(8), acctest.RandString(8) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccGoogleSqlDatabaseInstanceDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: fmt.Sprintf( + testGoogleSqlDatabaseInstance_multipleOperations, databaseID, instanceID, userID), + }, + }, + }) +} + func testAccCheckGoogleSqlDatabaseInstanceEquals(n string, instance *sqladmin.DatabaseInstance) resource.TestCheckFunc { return func(s *terraform.State) error { @@ -678,3 +696,26 @@ resource "google_sql_database_instance" "instance" { } } ` + +var testGoogleSqlDatabaseInstance_multipleOperations = ` +resource "google_sql_database_instance" "instance" { + name = "tf-test-%s" + region = "us-central" + settings { + tier = "D0" + crash_safe_replication = false + } +} + +resource "google_sql_database" "database" { + name = "tf-test-%s" + instance = "${google_sql_database_instance.instance.name}" +} + +resource "google_sql_user" "user" { + name = "tf-test-%s" + instance = "${google_sql_database_instance.instance.name}" + host = "google.com" + password = "hunter2" +} +` diff --git a/builtin/providers/google/resource_sql_user.go b/builtin/providers/google/resource_sql_user.go index afcc88e19..bc98f2bb7 100644 --- a/builtin/providers/google/resource_sql_user.go +++ b/builtin/providers/google/resource_sql_user.go @@ -76,6 +76,8 @@ func resourceSqlUserCreate(d *schema.ResourceData, meta interface{}) error { Host: host, } + mutexKV.Lock(instanceMutexKey(project, instance)) + defer mutexKV.Unlock(instanceMutexKey(project, instance)) op, err := config.clientSqlAdmin.Users.Insert(project, instance, user).Do() @@ -163,6 +165,8 @@ func resourceSqlUserUpdate(d *schema.ResourceData, meta interface{}) error { Host: host, } + mutexKV.Lock(instanceMutexKey(project, instance)) + defer mutexKV.Unlock(instanceMutexKey(project, instance)) op, err := config.clientSqlAdmin.Users.Update(project, instance, host, name, user).Do() @@ -196,6 +200,8 @@ func resourceSqlUserDelete(d *schema.ResourceData, meta interface{}) error { instance := d.Get("instance").(string) host := d.Get("host").(string) + mutexKV.Lock(instanceMutexKey(project, instance)) + defer mutexKV.Unlock(instanceMutexKey(project, instance)) op, err := config.clientSqlAdmin.Users.Delete(project, instance, host, name).Do() if err != nil {