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