Skip to content

Commit 683ee15

Browse files
authored
terraform suport for google_folder_service_identity (#13462)
1 parent d4fa379 commit 683ee15

5 files changed

+278
-0
lines changed

mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl

+1
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ var handwrittenResources = map[string]*schema.Resource{
382382
"google_endpoints_service": servicemanagement.ResourceEndpointsService(),
383383
"google_folder": resourcemanager.ResourceGoogleFolder(),
384384
"google_folder_organization_policy": resourcemanager.ResourceGoogleFolderOrganizationPolicy(),
385+
"google_folder_service_identity": resourcemanager.ResourceFolderServiceIdentity(),
385386
"google_logging_billing_account_sink": logging.ResourceLoggingBillingAccountSink(),
386387
"google_logging_billing_account_exclusion": logging.ResourceLoggingExclusion(logging.BillingAccountLoggingExclusionSchema, logging.NewBillingAccountLoggingExclusionUpdater, logging.BillingAccountLoggingExclusionIdParseFunc),
387388
"google_logging_billing_account_bucket_config": logging.ResourceLoggingBillingAccountBucketConfig(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package resourcemanager
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"time"
7+
8+
"github.com/hashicorp/terraform-provider-google/google/services/serviceusage"
9+
"github.com/hashicorp/terraform-provider-google/google/tpgresource"
10+
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
11+
12+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
13+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
14+
)
15+
16+
func ResourceFolderServiceIdentity() *schema.Resource {
17+
return &schema.Resource{
18+
Create: resourceFolderServiceIdentityCreate,
19+
Read: resourceFolderServiceIdentityRead,
20+
Delete: resourceFolderServiceIdentityDelete,
21+
22+
Timeouts: &schema.ResourceTimeout{
23+
Create: schema.DefaultTimeout(20 * time.Minute),
24+
Read: schema.DefaultTimeout(10 * time.Minute),
25+
Delete: schema.DefaultTimeout(20 * time.Minute),
26+
},
27+
28+
CustomizeDiff: customdiff.All(
29+
tpgresource.DefaultProviderProject,
30+
),
31+
32+
Schema: map[string]*schema.Schema{
33+
"service": {
34+
Type: schema.TypeString,
35+
Required: true,
36+
ForceNew: true,
37+
},
38+
"folder": {
39+
Type: schema.TypeString,
40+
Required: true,
41+
ForceNew: true,
42+
},
43+
"email": {
44+
Type: schema.TypeString,
45+
Computed: true,
46+
},
47+
"member": {
48+
Type: schema.TypeString,
49+
Computed: true,
50+
Description: `The Identity of the Google managed service account in the form 'serviceAccount:{email}'. This value is often used to refer to the service account in order to grant IAM permissions.`,
51+
},
52+
},
53+
UseJSONNumber: true,
54+
}
55+
}
56+
57+
func resourceFolderServiceIdentityCreate(d *schema.ResourceData, meta interface{}) error {
58+
config := meta.(*transport_tpg.Config)
59+
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
60+
if err != nil {
61+
return err
62+
}
63+
64+
url, err := tpgresource.ReplaceVars(d, config, "{{"{{"}}ServiceUsageBasePath{{"}}"}}folders/{{"{{"}}folder{{"}}"}}/services/{{"{{"}}service{{"}}"}}:generateServiceIdentity")
65+
if err != nil {
66+
return err
67+
}
68+
69+
billingProject := ""
70+
71+
// err == nil indicates that the billing_project value was found
72+
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
73+
billingProject = bp
74+
}
75+
if err != nil {
76+
return err
77+
}
78+
79+
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
80+
Config: config,
81+
Method: "POST",
82+
Project: billingProject,
83+
RawURL: url,
84+
UserAgent: userAgent,
85+
Timeout: d.Timeout(schema.TimeoutCreate),
86+
})
87+
if err != nil {
88+
return fmt.Errorf("Error creating Folder Service Identity: %s", err)
89+
}
90+
91+
var opRes map[string]interface{}
92+
err = serviceusage.ServiceUsageOperationWaitTimeWithResponse(
93+
config, res, &opRes, billingProject, "Creating Folder Service Identity", userAgent,
94+
d.Timeout(schema.TimeoutCreate))
95+
if err != nil {
96+
return err
97+
}
98+
99+
log.Printf("[DEBUG] Finished creating Folder Service Identity %q: %#v", d.Id(), res)
100+
101+
id, err := tpgresource.ReplaceVars(d, config, "folders/{{"{{"}}folder{{"}}"}}/services/{{"{{"}}service{{"}}"}}")
102+
if err != nil {
103+
return fmt.Errorf("Error constructing id: %s", err)
104+
}
105+
d.SetId(id)
106+
107+
// This API may not return the service identity's details, even if the relevant
108+
// Google API is configured for service identities.
109+
if emailVal, ok := opRes["email"]; ok {
110+
email, ok := emailVal.(string)
111+
if !ok {
112+
return fmt.Errorf("unexpected type for email: got %T, want string", email)
113+
}
114+
if err := d.Set("email", email); err != nil {
115+
return fmt.Errorf("Error setting email: %s", err)
116+
}
117+
if err := d.Set("member", "serviceAccount:"+email); err != nil {
118+
return fmt.Errorf("Error setting member: %s", err)
119+
}
120+
}
121+
return nil
122+
}
123+
124+
// There is no read endpoint for this API.
125+
func resourceFolderServiceIdentityRead(d *schema.ResourceData, meta interface{}) error {
126+
return nil
127+
}
128+
129+
// There is no delete endpoint for this API.
130+
func resourceFolderServiceIdentityDelete(d *schema.ResourceData, meta interface{}) error {
131+
return nil
132+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
resource: 'google_folder_service_identity'
2+
generation_type: 'handwritten'
3+
api_service_name: 'serviceusage.googleapis.com'
4+
api_version: 'v1'
5+
api_resource_type_kind: 'Service'
6+
fields:
7+
- field: 'email'
8+
- field: 'member'
9+
- field: 'folder'
10+
- field: 'service'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package resourcemanager_test
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
"testing"
7+
"github.com/hashicorp/terraform-provider-google/google/acctest"
8+
"github.com/hashicorp/terraform-provider-google/google/envvar"
9+
10+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
11+
)
12+
13+
func TestAccFolderServiceIdentity_basic(t *testing.T) {
14+
t.Parallel()
15+
16+
context := map[string]interface{}{
17+
"org_id": envvar.GetTestOrgFromEnv(t),
18+
"random_suffix": acctest.RandString(t, 5),
19+
}
20+
21+
acctest.VcrTest(t, resource.TestCase{
22+
PreCheck: func() { acctest.AccTestPreCheck(t) },
23+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
24+
Steps: []resource.TestStep{
25+
{
26+
Config: testGoogleFolderServiceIdentity_basic(context),
27+
Check: resource.ComposeTestCheckFunc(
28+
// Email field for osconfig service account should be non-empty and contain at least an "@".
29+
resource.TestCheckResourceAttrWith("google_folder_service_identity.osconfig_sa", "email", func(value string) error {
30+
if strings.Contains(value, "@") {
31+
return nil
32+
}
33+
return fmt.Errorf("osconfig_sa service identity email value was %s, expected a valid email", value)
34+
}),
35+
// Member field for osconfig service account should start with "serviceAccount:service-folder-" and end with "@gcp-sa-osconfig.iam.gserviceaccount.com"
36+
resource.TestCheckResourceAttrWith("google_folder_service_identity.osconfig_sa", "member", func(value string) error {
37+
if !strings.HasPrefix(value, "serviceAccount:service-folder-") {
38+
return fmt.Errorf("osconfig_sa folder service identity member value %q does not start with 'serviceAccount:service-folder-'", value)
39+
}
40+
if !strings.HasSuffix(value, "@gcp-sa-osconfig.iam.gserviceaccount.com") {
41+
return fmt.Errorf("osconfig_sa folder service identity member value %q does not end with '@gcp-sa-osconfig.iam.gserviceaccount.com'", value)
42+
}
43+
return nil
44+
}),
45+
),
46+
},
47+
},
48+
})
49+
}
50+
51+
func testGoogleFolderServiceIdentity_basic(context map[string]interface{}) string {
52+
return acctest.Nprintf(`
53+
resource "google_folder" "folder" {
54+
parent = "organizations/%{org_id}"
55+
display_name = "test-folder-%{random_suffix}"
56+
deletion_protection = false
57+
}
58+
59+
resource "google_folder_service_identity" "osconfig_sa" {
60+
folder = google_folder.folder.folder_id
61+
service = "osconfig.googleapis.com"
62+
}
63+
`, context)
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
---
2+
subcategory: "Cloud Platform"
3+
description: |-
4+
Generate folder service identity for a service.
5+
---
6+
7+
# google_folder_service_identity
8+
9+
Generate folder service identity for a service.
10+
11+
~> **Note:** Once created, this resource cannot be updated or destroyed. These
12+
actions are a no-op.
13+
14+
~> **Note:** This resource can be used to retrieve the emails of the [Google-managed folder service accounts](https://cloud.google.com/iam/docs/service-agents)
15+
of the APIs that Google has configured with a Service Identity. You can run `gcloud beta services identity create --service SERVICE_NAME.googleapis.com --folder FOLDER` to
16+
verify if an API supports this.
17+
18+
To get more information about Service Identity, see:
19+
20+
* [API documentation](https://cloud.google.com/service-usage/docs/reference/rest/v1beta1/services/generateServiceIdentity)
21+
22+
## Example Usage - Folder Service Identity Basic
23+
24+
```hcl
25+
resource "google_folder" "my_folder" {
26+
parent = "organizations/1234567"
27+
display_name = "my-folder"
28+
}
29+
30+
resource "google_folder_service_identity" "osconfig_sa" {
31+
folder = google_folder.my_folder.folder_id
32+
service = "osconfig.googleapis.com"
33+
}
34+
35+
36+
resource "google_folder_iam_member" "admin" {
37+
folder = google_folder.my_folder.name
38+
role = "roles/osconfig.serviceAgent"
39+
member = google_folder_service_identity.osconfig_sa.member
40+
}
41+
```
42+
43+
## Argument Reference
44+
45+
The following arguments are supported:
46+
47+
* `service` -
48+
(Required)
49+
The service to generate identity for.
50+
51+
- - -
52+
53+
* `folder` - (Required) The folder in which the resource belongs.
54+
55+
## Attributes Reference
56+
57+
In addition to the arguments listed above, the following computed attributes are exported:
58+
59+
* `email` - The email address of the Google managed service account.
60+
* `member` - The Identity of the Google managed service account in the form 'serviceAccount:{email}'. This value is often used to refer to the service account in order to grant IAM permissions.
61+
62+
## Import
63+
64+
This resource does not support import.
65+
66+
## Timeouts
67+
68+
This resource provides the following
69+
[Timeouts](https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/retries-and-customizable-timeouts) configuration options: configuration options:
70+
71+
* `create` - Default is 20 minutes.

0 commit comments

Comments
 (0)