@@ -5,21 +5,25 @@ package acctest
55import (
66 "fmt"
77 "log"
8+ "strconv"
9+ "strings"
810 "testing"
11+ "time"
912
1013 "github.com/hashicorp/terraform-provider-google/google/envvar"
1114 "github.com/hashicorp/terraform-provider-google/google/tpgiamresource"
1215 cloudresourcemanager "google.golang.org/api/cloudresourcemanager/v1"
1316)
1417
15- // BootstrapAllPSARoles ensures that the given project's IAM
16- // policy grants the given service agents the given roles.
17- // prefix is usually "service-" and indicates the service agent should have the
18- // given prefix before the project number.
19- // This is important to bootstrap because using iam policy resources means that
20- // deleting them removes permissions for concurrent tests.
21- // Return whether the bindings changed.
22- func BootstrapAllPSARoles (t * testing.T , prefix string , agentNames , roles []string ) bool {
18+ type IamMember struct {
19+ Member , Role string
20+ }
21+
22+ // BootstrapIamMembers ensures that a given set of member/role pairs exist in the default
23+ // test project. This should be used to avoid race conditions that can happen on the
24+ // default project due to parallel tests managing the same member/role pairings. Members
25+ // will have `{project_number}` replaced with the default test project's project number.
26+ func BootstrapIamMembers (t * testing.T , members []IamMember ) {
2327 config := BootstrapConfig (t )
2428 if config == nil {
2529 t .Fatal ("Could not bootstrap a config for BootstrapAllPSARoles." )
@@ -38,17 +42,12 @@ func BootstrapAllPSARoles(t *testing.T, prefix string, agentNames, roles []strin
3842 t .Fatalf ("Error getting project iam policy: %v" , err )
3943 }
4044
41- members := make ([]string , len (agentNames ))
42- for i , agentName := range agentNames {
43- members [i ] = fmt .Sprintf ("serviceAccount:%s%d@%s.iam.gserviceaccount.com" , prefix , project .ProjectNumber , agentName )
44- }
45-
4645 // Create the bindings we need to add to the policy.
4746 var newBindings []* cloudresourcemanager.Binding
48- for _ , role := range roles {
47+ for _ , member := range members {
4948 newBindings = append (newBindings , & cloudresourcemanager.Binding {
50- Role : role ,
51- Members : members ,
49+ Role : member . Role ,
50+ Members : [] string { strings . ReplaceAll ( member . Member , "{project_number}" , strconv . FormatInt ( project . ProjectNumber , 10 ))} ,
5251 })
5352 }
5453
@@ -70,10 +69,32 @@ func BootstrapAllPSARoles(t *testing.T, prefix string, agentNames, roles []strin
7069 for _ , binding := range addedBindings {
7170 msg += fmt .Sprintf ("Members: %q, Role: %q\n " , binding .Members , binding .Role )
7271 }
73- msg += "Retry the test in a few minutes."
74- t .Error (msg )
75- return true
72+ msg += "Waiting for IAM to propagate."
73+ t .Log (msg )
74+ time .Sleep (3 * time .Minute )
75+ }
76+ }
77+
78+ // BootstrapAllPSARoles ensures that the given project's IAM
79+ // policy grants the given service agents the given roles.
80+ // prefix is usually "service-" and indicates the service agent should have the
81+ // given prefix before the project number.
82+ // This is important to bootstrap because using iam policy resources means that
83+ // deleting them removes permissions for concurrent tests.
84+ // Return whether the bindings changed.
85+ func BootstrapAllPSARoles (t * testing.T , prefix string , agentNames , roles []string ) bool {
86+ var members []IamMember
87+ for _ , agentName := range agentNames {
88+ member := fmt .Sprintf ("serviceAccount:%s{project_number}@%s.iam.gserviceaccount.com" , prefix , agentName )
89+ for _ , role := range roles {
90+ members = append (members , IamMember {
91+ Member : member ,
92+ Role : role ,
93+ })
94+ }
7695 }
96+ BootstrapIamMembers (t , members )
97+ // Always return false because we now wait for IAM propagation.
7798 return false
7899}
79100
0 commit comments