Skip to content

Commit e53a602

Browse files
modular-magicianpaddycarver
authored andcommitted
Add retries/backoff when (only) reading IAM policies (#3455)
Signed-off-by: Modular Magician <[email protected]>
1 parent 7c76b4d commit e53a602

5 files changed

+28
-5
lines changed

google/iam.go

+24-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
"google.golang.org/api/cloudresourcemanager/v1"
1111
)
1212

13+
const maxBackoffSeconds = 30
14+
1315
// The ResourceIamUpdater interface is implemented for each GCP resource supporting IAM policy.
1416
//
1517
// Implementations should keep track of the resource identifier.
@@ -44,6 +46,26 @@ type iamPolicyModifyFunc func(p *cloudresourcemanager.Policy) error
4446

4547
type resourceIdParserFunc func(d *schema.ResourceData, config *Config) error
4648

49+
// Wrapper around updater.GetResourceIamPolicy() to handle retry/backoff
50+
// for just reading policies from IAM
51+
func iamPolicyReadWithRetry(updater ResourceIamUpdater) (*cloudresourcemanager.Policy, error) {
52+
mutexKey := updater.GetMutexKey()
53+
mutexKV.Lock(mutexKey)
54+
defer mutexKV.Unlock(mutexKey)
55+
56+
log.Printf("[DEBUG] Retrieving policy for %s\n", updater.DescribeResource())
57+
var policy *cloudresourcemanager.Policy
58+
err := retryTime(func() (perr error) {
59+
policy, perr = updater.GetResourceIamPolicy()
60+
return perr
61+
}, 10)
62+
if err != nil {
63+
return nil, err
64+
}
65+
log.Printf("[DEBUG] Retrieved policy for %s: %+v\n", updater.DescribeResource(), policy)
66+
return policy, nil
67+
}
68+
4769
func iamPolicyReadModifyWrite(updater ResourceIamUpdater, modify iamPolicyModifyFunc) error {
4870
mutexKey := updater.GetMutexKey()
4971
mutexKV.Lock(mutexKey)
@@ -54,6 +76,7 @@ func iamPolicyReadModifyWrite(updater ResourceIamUpdater, modify iamPolicyModify
5476
log.Printf("[DEBUG]: Retrieving policy for %s\n", updater.DescribeResource())
5577
p, err := updater.GetResourceIamPolicy()
5678
if isGoogleApiErrorWithCode(err, 429) {
79+
log.Printf("[DEBUG] 429 while attempting to read policy for %s, waiting %v before attempting again", updater.DescribeResource(), backoff)
5780
time.Sleep(backoff)
5881
continue
5982
} else if err != nil {
@@ -71,7 +94,7 @@ func iamPolicyReadModifyWrite(updater ResourceIamUpdater, modify iamPolicyModify
7194
if err == nil {
7295
fetchBackoff := 1 * time.Second
7396
for successfulFetches := 0; successfulFetches < 3; {
74-
if fetchBackoff > 30*time.Second {
97+
if fetchBackoff > maxBackoffSeconds*time.Second {
7598
return fmt.Errorf("Error applying IAM policy to %s: Waited too long for propagation.\n", updater.DescribeResource())
7699
}
77100
time.Sleep(fetchBackoff)

google/resource_iam_audit_config.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func resourceIamAuditConfigRead(newUpdaterFunc newResourceIamUpdaterFunc) schema
8686
}
8787

8888
eAuditConfig := getResourceIamAuditConfig(d)
89-
p, err := updater.GetResourceIamPolicy()
89+
p, err := iamPolicyReadWithRetry(updater)
9090
if err != nil {
9191
if isGoogleApiErrorWithCode(err, 404) {
9292
log.Printf("[DEBUG]: AuditConfig for service %q not found for non-existent resource %s, removing from state file.", eAuditConfig.Service, updater.DescribeResource())

google/resource_iam_binding.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func resourceIamBindingRead(newUpdaterFunc newResourceIamUpdaterFunc) schema.Rea
7777
}
7878

7979
eBinding := getResourceIamBinding(d)
80-
p, err := updater.GetResourceIamPolicy()
80+
p, err := iamPolicyReadWithRetry(updater)
8181
if err != nil {
8282
if isGoogleApiErrorWithCode(err, 404) {
8383
log.Printf("[DEBUG]: Binding for role %q not found for non-existent resource %s, removing from state file.", updater.DescribeResource(), eBinding.Role)

google/resource_iam_member.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ func resourceIamMemberRead(newUpdaterFunc newResourceIamUpdaterFunc) schema.Read
112112
}
113113

114114
eMember := getResourceIamMember(d)
115-
p, err := updater.GetResourceIamPolicy()
115+
p, err := iamPolicyReadWithRetry(updater)
116116
if err != nil {
117117
if isGoogleApiErrorWithCode(err, 404) {
118118
log.Printf("[DEBUG]: Binding of member %q with role %q does not exist for non-existent resource %s, removing from state.", eMember.Members[0], eMember.Role, updater.DescribeResource())

google/resource_iam_policy.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func ResourceIamPolicyRead(newUpdaterFunc newResourceIamUpdaterFunc) schema.Read
8181
return err
8282
}
8383

84-
policy, err := updater.GetResourceIamPolicy()
84+
policy, err := iamPolicyReadWithRetry(updater)
8585
if err != nil {
8686
if isGoogleApiErrorWithCode(err, 404) {
8787
log.Printf("[DEBUG]: Policy does not exist for non-existent resource %q", updater.GetResourceId())

0 commit comments

Comments
 (0)