From fa07606697f1d1a20b2fd14252889e52da962ee7 Mon Sep 17 00:00:00 2001
From: Cameron Thornton <camthornton@google.com>
Date: Thu, 14 May 2020 18:07:07 -0700
Subject: [PATCH] Add retry to service account creation

---
 .../resource_google_service_account.go         | 18 +++++++++++++-----
 .../r/google_service_account.html.markdown     |  7 +++++++
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/third_party/terraform/resources/resource_google_service_account.go b/third_party/terraform/resources/resource_google_service_account.go
index 2356b4bbcc01..c90a2e9831fa 100644
--- a/third_party/terraform/resources/resource_google_service_account.go
+++ b/third_party/terraform/resources/resource_google_service_account.go
@@ -19,6 +19,9 @@ func resourceGoogleServiceAccount() *schema.Resource {
 		Importer: &schema.ResourceImporter{
 			State: resourceGoogleServiceAccountImport,
 		},
+		Timeouts: &schema.ResourceTimeout{
+			Create: schema.DefaultTimeout(5 * time.Minute),
+		},
 		Schema: map[string]*schema.Schema{
 			"email": {
 				Type:     schema.TypeString,
@@ -83,10 +86,15 @@ func resourceGoogleServiceAccountCreate(d *schema.ResourceData, meta interface{}
 	}
 
 	d.SetId(sa.Name)
-	// This API is meant to be synchronous, but in practice it shows the old value for
-	// a few milliseconds after the update goes through.  A second is more than enough
-	// time to ensure following reads are correct.
-	time.Sleep(time.Second)
+
+	err = retryTimeDuration(func() (operr error) {
+		_, saerr := config.clientIAM.Projects.ServiceAccounts.Get(d.Id()).Do()
+		return saerr
+	}, d.Timeout(schema.TimeoutCreate), isNotFoundRetryableError("service account creation"))
+
+	if err != nil {
+		return fmt.Errorf("Error reading service account after creation: %s", err)
+	}
 
 	return resourceGoogleServiceAccountRead(d, meta)
 }
@@ -146,7 +154,7 @@ func resourceGoogleServiceAccountUpdate(d *schema.ResourceData, meta interface{}
 	if err != nil {
 		return err
 	}
-	// See comment in Create.
+	// API tends to be asynchronous
 	time.Sleep(time.Second)
 
 	return nil
diff --git a/third_party/terraform/website/docs/r/google_service_account.html.markdown b/third_party/terraform/website/docs/r/google_service_account.html.markdown
index 75efb5f5901a..b411741cf250 100644
--- a/third_party/terraform/website/docs/r/google_service_account.html.markdown
+++ b/third_party/terraform/website/docs/r/google_service_account.html.markdown
@@ -58,6 +58,13 @@ exported:
 
 * `unique_id` - The unique id of the service account.
 
+## Timeouts
+
+This resource provides the following
+[Timeouts](/docs/configuration/resources.html#timeouts) configuration options:
+
+- `create` - Default is 5 minutes.
+
 ## Import
 
 Service accounts can be imported using their URI, e.g.