Skip to content

Commit f8a3335

Browse files
vishendanawillow
authored andcommitted
service_account_key: regression fix for v1.14 (#1664)
Commit 8f31fec introduced a bug for the 'service_account_key' resource where it required a project be set either in the provider or in the resource for 'service_account_key', but a project isn't required if the service account is a service account fully qualified name or a service account email. This PR relaxes the requirement that a project needs to be set for the 'service_account_key' resource, 'service_account' datasource and 'service_account_key' datasource, but will error if we try to build a fully qualified name from a service account id when no project can be found. This also cleans up 'serviceAccountFQN' so it is slightly easier to follow and return an error if there is no project but we need one to build the service account fully qualified name. Fixes: #1655
1 parent 43cccf3 commit f8a3335

5 files changed

+31
-30
lines changed

google/data_source_google_service_account.go

+1-6
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,11 @@ func dataSourceGoogleServiceAccount() *schema.Resource {
4343
func dataSourceGoogleServiceAccountRead(d *schema.ResourceData, meta interface{}) error {
4444
config := meta.(*Config)
4545

46-
// Get the project from the resource or fallback to the project
47-
// in the provider configuration
48-
project, err := getProject(d, config)
46+
serviceAccountName, err := serviceAccountFQN(d.Get("account_id").(string), d, config)
4947
if err != nil {
5048
return err
5149
}
5250

53-
// Get the service account as a fully qualified name
54-
serviceAccountName := serviceAccountFQN(d.Get("account_id").(string), project)
55-
5651
sa, err := config.clientIAM.Projects.ServiceAccounts.Get(serviceAccountName).Do()
5752
if err != nil {
5853
return handleNotFoundError(err, d, fmt.Sprintf("Service Account %q", serviceAccountName))

google/data_source_google_service_account_key.go

+1-6
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,11 @@ func dataSourceGoogleServiceAccountKey() *schema.Resource {
4646
func dataSourceGoogleServiceAccountKeyRead(d *schema.ResourceData, meta interface{}) error {
4747
config := meta.(*Config)
4848

49-
// Get the project from the resource or fallback to the project
50-
// in the provider configuration
51-
project, err := getProject(d, config)
49+
serviceAccountName, err := serviceAccountFQN(d.Get("service_account_id").(string), d, config)
5250
if err != nil {
5351
return err
5452
}
5553

56-
// Get the service account as the fully qualified name
57-
serviceAccountName := serviceAccountFQN(d.Get("service_account_id").(string), project)
58-
5954
publicKeyType := d.Get("public_key_type").(string)
6055

6156
// Confirm the service account key exists

google/resource_google_service_account_key.go

+1-5
Original file line numberDiff line numberDiff line change
@@ -87,15 +87,11 @@ func resourceGoogleServiceAccountKey() *schema.Resource {
8787
func resourceGoogleServiceAccountKeyCreate(d *schema.ResourceData, meta interface{}) error {
8888
config := meta.(*Config)
8989

90-
// Get the project from the resource or fallback to the project
91-
// in the provider configuration
92-
project, err := getProject(d, config)
90+
serviceAccountName, err := serviceAccountFQN(d.Get("service_account_id").(string), d, config)
9391
if err != nil {
9492
return err
9593
}
9694

97-
serviceAccountName := serviceAccountFQN(d.Get("service_account_id").(string), project)
98-
9995
r := &iam.CreateServiceAccountKeyRequest{
10096
KeyAlgorithm: d.Get("key_algorithm").(string),
10197
PrivateKeyType: d.Get("private_key_type").(string),

google/utils.go

+22-12
Original file line numberDiff line numberDiff line change
@@ -362,17 +362,27 @@ func lockedCall(lockKey string, f func() error) error {
362362
}
363363

364364
// serviceAccountFQN will attempt to generate the fully qualified name in the format of:
365-
// "projects/(-|<project_name>)/serviceAccounts/<service_account_id>@<project_name>.iam.gserviceaccount.com"
366-
func serviceAccountFQN(serviceAccount, project string) string {
367-
// If the service account id isn't already the fully qualified name
368-
if !strings.HasPrefix(serviceAccount, "projects/") {
369-
// If the service account id is an email
370-
if strings.Contains(serviceAccount, "@") {
371-
serviceAccount = "projects/-/serviceAccounts/" + serviceAccount
372-
} else {
373-
// If the service account id doesn't contain the email, build it
374-
serviceAccount = fmt.Sprintf("projects/-/serviceAccounts/%s@%s.iam.gserviceaccount.com", serviceAccount, project)
375-
}
365+
// "projects/(-|<project>)/serviceAccounts/<service_account_id>@<project>.iam.gserviceaccount.com"
366+
// A project is required if we are trying to build the FQN from a service account id and
367+
// and error will be returned in this case if no project is set in the resource or the
368+
// provider-level config
369+
func serviceAccountFQN(serviceAccount string, d TerraformResourceData, config *Config) (string, error) {
370+
// If the service account id is already the fully qualified name
371+
if strings.HasPrefix(serviceAccount, "projects/") {
372+
return serviceAccount, nil
373+
}
374+
375+
// If the service account id is an email
376+
if strings.Contains(serviceAccount, "@") {
377+
return "projects/-/serviceAccounts/" + serviceAccount, nil
376378
}
377-
return serviceAccount
379+
380+
// Get the project from the resource or fallback to the project
381+
// in the provider configuration
382+
project, err := getProject(d, config)
383+
if err != nil {
384+
return "", err
385+
}
386+
387+
return fmt.Sprintf("projects/-/serviceAccounts/%s@%s.iam.gserviceaccount.com", serviceAccount, project), nil
378388
}

google/utils_test.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,12 @@ func TestServiceAccountFQN(t *testing.T) {
465465
}
466466

467467
for tn, tc := range cases {
468-
serviceAccountName := serviceAccountFQN(tc.serviceAccount, tc.project)
468+
config := &Config{Project: tc.project}
469+
d := &schema.ResourceData{}
470+
serviceAccountName, err := serviceAccountFQN(tc.serviceAccount, d, config)
471+
if err != nil {
472+
t.Fatalf("unexpected error for service account FQN: %s", err)
473+
}
469474
if serviceAccountName != serviceAccountExpected {
470475
t.Errorf("bad: %s, expected '%s' but returned '%s", tn, serviceAccountExpected, serviceAccountName)
471476
}

0 commit comments

Comments
 (0)