Skip to content

Commit 2f059a3

Browse files
nat-hendersonAshish Amarnath
authored and
Ashish Amarnath
committed
Reduce flakiness by ensuring three successful fetches of IAM resources before returning. (hashicorp#1197)
1 parent e1e8a85 commit 2f059a3

File tree

1 file changed

+39
-4
lines changed

1 file changed

+39
-4
lines changed

google/iam.go

+39-4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ package google
22

33
import (
44
"fmt"
5-
"github.com/hashicorp/terraform/helper/schema"
6-
"google.golang.org/api/cloudresourcemanager/v1"
75
"log"
86
"time"
7+
8+
"github.com/hashicorp/terraform/helper/schema"
9+
"google.golang.org/api/cloudresourcemanager/v1"
10+
"google.golang.org/api/googleapi"
911
)
1012

1113
// The ResourceIamUpdater interface is implemented for each GCP resource supporting IAM policy.
@@ -47,11 +49,14 @@ func iamPolicyReadModifyWrite(updater ResourceIamUpdater, modify iamPolicyModify
4749
mutexKV.Lock(mutexKey)
4850
defer mutexKV.Unlock(mutexKey)
4951

52+
backoff := time.Second
5053
for {
51-
backoff := time.Second
5254
log.Printf("[DEBUG]: Retrieving policy for %s\n", updater.DescribeResource())
5355
p, err := updater.GetResourceIamPolicy()
54-
if err != nil {
56+
if e, ok := err.(*googleapi.Error); ok && e.Code == 429 {
57+
time.Sleep(backoff)
58+
continue
59+
} else if err != nil {
5560
return err
5661
}
5762
log.Printf("[DEBUG]: Retrieved policy for %s: %+v\n", updater.DescribeResource(), p)
@@ -64,6 +69,36 @@ func iamPolicyReadModifyWrite(updater ResourceIamUpdater, modify iamPolicyModify
6469
log.Printf("[DEBUG]: Setting policy for %s to %+v\n", updater.DescribeResource(), p)
6570
err = updater.SetResourceIamPolicy(p)
6671
if err == nil {
72+
fetchBackoff := 1 * time.Second
73+
for successfulFetches := 0; successfulFetches < 3; {
74+
time.Sleep(fetchBackoff)
75+
new_p, err := updater.GetResourceIamPolicy()
76+
if err != nil {
77+
// Quota for Read is pretty limited, so watch out for running out of quota.
78+
if e, ok := err.(*googleapi.Error); ok && e.Code == 429 {
79+
fetchBackoff = fetchBackoff * 2
80+
} else {
81+
return err
82+
}
83+
}
84+
modified_p := new_p
85+
// This relies on the fact that `modify` is idempotent: since other changes might have
86+
// happened between the call to set the policy and now, we just need to make sure that
87+
// our change has been made. 'modify(p) == p' is our check for whether this has been
88+
// correctly applied.
89+
err = modify(modified_p)
90+
if err != nil {
91+
return err
92+
}
93+
if modified_p == new_p {
94+
successfulFetches += 1
95+
} else {
96+
fetchBackoff = fetchBackoff * 2
97+
if fetchBackoff > 30*time.Second {
98+
return fmt.Errorf("Error applying IAM policy to %s: Waited too long for propagation.\n", updater.DescribeResource())
99+
}
100+
}
101+
}
67102
break
68103
}
69104
if isConflictError(err) {

0 commit comments

Comments
 (0)