diff --git a/google/resource_sql_database_instance.go b/google/resource_sql_database_instance.go index 28ca32d4e01..304d91ba9bb 100644 --- a/google/resource_sql_database_instance.go +++ b/google/resource_sql_database_instance.go @@ -685,10 +685,10 @@ func resourceSqlDatabaseInstanceCreate(d *schema.ResourceData, meta interface{}) // replica, then any users are inherited from the master instance and should be left alone. if !sqlResourceIsReplica(d) { var users *sqladmin.UsersListResponse - err = retry(func() error { + err = retryTime(func() error { users, err = config.clientSqlAdmin.Users.List(project, instance.Name).Do() return err - }) + }, 3) if err != nil { return fmt.Errorf("Error, attempting to list users associated with instance %s: %s", instance.Name, err) } diff --git a/google/resource_sql_user.go b/google/resource_sql_user.go index 8289aa8644f..60f08bf1687 100644 --- a/google/resource_sql_user.go +++ b/google/resource_sql_user.go @@ -87,7 +87,9 @@ func resourceSqlUserCreate(d *schema.ResourceData, meta interface{}) error { "user %s into instance %s: %s", name, instance, err) } - d.SetId(fmt.Sprintf("%s/%s", instance, name)) + // This will include a double-slash (//) for 2nd generation instances, + // for which user.Host is an empty string. That's okay. + d.SetId(fmt.Sprintf("%s/%s/%s", user.Name, user.Host, user.Instance)) err = sqladminOperationWait(config, op, project, "Insert User") @@ -111,14 +113,20 @@ func resourceSqlUserRead(d *schema.ResourceData, meta interface{}) error { name := d.Get("name").(string) host := d.Get("host").(string) - users, err := config.clientSqlAdmin.Users.List(project, instance).Do() - + var users *sqladmin.UsersListResponse + err = nil + err = retry(func() error { + users, err = config.clientSqlAdmin.Users.List(project, instance).Do() + return err + }) if err != nil { return handleNotFoundError(err, d, fmt.Sprintf("SQL User %q in instance %q", name, instance)) } var user *sqladmin.User for _, currentUser := range users.Items { + // The second part of this conditional is irrelevant for 2nd generation instances because + // host and currentUser.Host will always both be empty. if currentUser.Name == name && currentUser.Host == host { user = currentUser break @@ -136,6 +144,7 @@ func resourceSqlUserRead(d *schema.ResourceData, meta interface{}) error { d.Set("instance", user.Instance) d.Set("name", user.Name) d.Set("project", project) + d.SetId(fmt.Sprintf("%s/%s/%s", user.Name, user.Host, user.Instance)) return nil } @@ -225,7 +234,6 @@ func resourceSqlUserImporter(d *schema.ResourceData, meta interface{}) ([]*schem d.Set("instance", parts[0]) d.Set("host", parts[1]) d.Set("name", parts[2]) - d.SetId(fmt.Sprintf("%s/%s", parts[0], parts[2])) } else { return nil, fmt.Errorf("Invalid specifier. Expecting {instance}/{name} for 2nd generation instance and {instance}/{host}/{name} for 1st generation instance") } diff --git a/google/resource_sql_user_test.go b/google/resource_sql_user_test.go index 607252fdf68..6be64dfa542 100644 --- a/google/resource_sql_user_test.go +++ b/google/resource_sql_user_test.go @@ -68,6 +68,7 @@ func TestAccSqlUser_secondGen(t *testing.T) { }, resource.TestStep{ ResourceName: "google_sql_user.user", + ImportStateId: instance + "/admin", ImportState: true, ImportStateVerify: true, ImportStateVerifyIgnore: []string{"password"}, diff --git a/google/sqladmin_operation.go b/google/sqladmin_operation.go index 5d0c559b8fc..9fb40bb0f1e 100644 --- a/google/sqladmin_operation.go +++ b/google/sqladmin_operation.go @@ -7,6 +7,7 @@ import ( "time" "github.com/hashicorp/terraform/helper/resource" + "google.golang.org/api/googleapi" "google.golang.org/api/sqladmin/v1beta4" ) @@ -18,13 +19,12 @@ type SqlAdminOperationWaiter struct { func (w *SqlAdminOperationWaiter) RefreshFunc() resource.StateRefreshFunc { return func() (interface{}, string, error) { - var op *sqladmin.Operation - var err error - log.Printf("[DEBUG] self_link: %s", w.Op.SelfLink) - op, err = w.Service.Operations.Get(w.Project, w.Op.Name).Do() + op, err := w.Service.Operations.Get(w.Project, w.Op.Name).Do() - if err != nil { + if e, ok := err.(*googleapi.Error); ok && (e.Code == 429 || e.Code == 503) { + return w.Op, "PENDING", nil + } else if err != nil { return nil, "", err }