33package acctest
44
55import (
6- "fmt"
7- "log"
86 "strconv"
97 "strings"
108 "testing"
119 "time"
1210
1311 "github.com/hashicorp/terraform-provider-google/google/envvar"
1412 "github.com/hashicorp/terraform-provider-google/google/tpgiamresource"
13+ "github.com/hashicorp/terraform-provider-google/google/tpgresource"
14+ transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
1515 cloudresourcemanager "google.golang.org/api/cloudresourcemanager/v1"
1616)
1717
@@ -36,12 +36,6 @@ func BootstrapIamMembers(t *testing.T, members []IamMember) {
3636 t .Fatalf ("Error getting project with id %q: %s" , project .ProjectId , err )
3737 }
3838
39- getPolicyRequest := & cloudresourcemanager.GetIamPolicyRequest {}
40- policy , err := client .Projects .GetIamPolicy (project .ProjectId , getPolicyRequest ).Do ()
41- if err != nil {
42- t .Fatalf ("Error getting project iam policy: %v" , err )
43- }
44-
4539 // Create the bindings we need to add to the policy.
4640 var newBindings []* cloudresourcemanager.Binding
4741 for _ , member := range members {
@@ -51,26 +45,43 @@ func BootstrapIamMembers(t *testing.T, members []IamMember) {
5145 })
5246 }
5347
54- mergedBindings := tpgiamresource .MergeBindings (append (policy .Bindings , newBindings ... ))
48+ // Retry bootstrapping with exponential backoff for concurrent writes
49+ backoff := time .Second
50+ for {
51+ getPolicyRequest := & cloudresourcemanager.GetIamPolicyRequest {}
52+ policy , err := client .Projects .GetIamPolicy (project .ProjectId , getPolicyRequest ).Do ()
53+ if transport_tpg .IsGoogleApiErrorWithCode (err , 429 ) {
54+ t .Logf ("[DEBUG] 429 while attempting to read policy for project %s, waiting %v before attempting again" , project .ProjectId , backoff )
55+ time .Sleep (backoff )
56+ continue
57+ } else if err != nil {
58+ t .Fatalf ("Error getting iam policy for project %s: %v\n " , project .ProjectId , err )
59+ }
60+
61+ mergedBindings := tpgiamresource .MergeBindings (append (policy .Bindings , newBindings ... ))
5562
56- if ! tpgiamresource .CompareBindings (policy .Bindings , mergedBindings ) {
57- addedBindings := tpgiamresource .MissingBindings (policy .Bindings , mergedBindings )
58- for _ , missingBinding := range addedBindings {
59- log .Printf ("[DEBUG] Adding binding: %+v" , missingBinding )
63+ if tpgiamresource .CompareBindings (policy .Bindings , mergedBindings ) {
64+ t .Logf ("[DEBUG] All bindings already present for project %s" , project .ProjectId )
65+ break
6066 }
6167 // The policy must change.
6268 policy .Bindings = mergedBindings
6369 setPolicyRequest := & cloudresourcemanager.SetIamPolicyRequest {Policy : policy }
6470 policy , err = client .Projects .SetIamPolicy (project .ProjectId , setPolicyRequest ).Do ()
65- if err != nil {
66- t .Fatalf ("Error setting project iam policy: %v" , err )
71+ if err == nil {
72+ t .Logf ("[DEBUG] Waiting for IAM bootstrapping to propagate for project %s." , project .ProjectId )
73+ time .Sleep (3 * time .Minute )
74+ break
6775 }
68- msg := "Added the following bindings to the test project's IAM policy:\n "
69- for _ , binding := range addedBindings {
70- msg += fmt .Sprintf ("Members: %q, Role: %q\n " , binding .Members , binding .Role )
76+ if tpgresource .IsConflictError (err ) {
77+ t .Logf ("[DEBUG]: Concurrent policy changes, restarting read-modify-write after %s" , backoff )
78+ time .Sleep (backoff )
79+ backoff = backoff * 2
80+ if backoff > 30 * time .Second {
81+ t .Fatalf ("Error applying IAM policy to %s: Too many conflicts. Latest error: %s" , project .ProjectId , err )
82+ }
83+ continue
7184 }
72- msg += "Waiting for IAM to propagate."
73- t .Log (msg )
74- time .Sleep (3 * time .Minute )
85+ t .Fatalf ("Error setting project iam policy: %v" , err )
7586 }
7687}
0 commit comments