Skip to content

Commit eaaf033

Browse files
Add tags field to Folder resource (#11424) (#8113)
[upstream:4f35c8aaa99063b05ef948d62f129f334e15f049] Signed-off-by: Modular Magician <[email protected]>
1 parent dcc72fa commit eaaf033

File tree

4 files changed

+103
-4
lines changed

4 files changed

+103
-4
lines changed

.changelog/11424.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
resourcemanager: added `tags` field to `google_folder` to allow setting tags for folders at creation time
3+
```

google-beta/services/resourcemanager/resource_google_folder.go

+16-4
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,13 @@ func ResourceGoogleFolder() *schema.Resource {
7373
Default: true,
7474
Description: `When the field is set to true or unset in Terraform state, a terraform apply or terraform destroy that would delete the instance will fail. When the field is set to false, deleting the instance is allowed.`,
7575
},
76+
"tags": {
77+
Type: schema.TypeMap,
78+
Optional: true,
79+
ForceNew: true,
80+
Elem: &schema.Schema{Type: schema.TypeString},
81+
Description: `A map of resource manager tags. Resource manager tag keys and values have the same definition as resource manager tags. Keys must be in the format tagKeys/{tag_key_id}, and values are in the format tagValues/456. The field is ignored when empty.`,
82+
},
7683
},
7784
UseJSONNumber: true,
7885
}
@@ -88,14 +95,19 @@ func resourceGoogleFolderCreate(d *schema.ResourceData, meta interface{}) error
8895
displayName := d.Get("display_name").(string)
8996
parent := d.Get("parent").(string)
9097

98+
folder := &resourceManagerV3.Folder{
99+
DisplayName: displayName,
100+
Parent: parent,
101+
}
102+
if _, ok := d.GetOk("tags"); ok {
103+
folder.Tags = tpgresource.ExpandStringMap(d, "tags")
104+
}
105+
91106
var op *resourceManagerV3.Operation
92107
err = transport_tpg.Retry(transport_tpg.RetryOptions{
93108
RetryFunc: func() error {
94109
var reqErr error
95-
op, reqErr = config.NewResourceManagerV3Client(userAgent).Folders.Create(&resourceManagerV3.Folder{
96-
DisplayName: displayName,
97-
Parent: parent,
98-
}).Do()
110+
op, reqErr = config.NewResourceManagerV3Client(userAgent).Folders.Create(folder).Do()
99111
return reqErr
100112
},
101113
Timeout: d.Timeout(schema.TimeoutCreate),

google-beta/services/resourcemanager/resource_google_folder_test.go

+73
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package resourcemanager_test
44

55
import (
66
"fmt"
7+
"regexp"
78
"testing"
89

910
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
@@ -90,6 +91,45 @@ func TestAccFolder_moveParent(t *testing.T) {
9091
})
9192
}
9293

94+
// Test that a Folder resource can be created with tags
95+
func TestAccFolder_tags(t *testing.T) {
96+
t.Parallel()
97+
98+
org := envvar.GetTestOrgFromEnv(t)
99+
parent := "organizations/" + org
100+
folderDisplayName := "tf-test-" + acctest.RandString(t, 10)
101+
tagKey := acctest.BootstrapSharedTestTagKey(t, "crm-folder-tagkey")
102+
tagValue := acctest.BootstrapSharedTestTagValue(t, "crm-folder-tagvalue", tagKey)
103+
folder_tags := resourceManagerV3.Folder{}
104+
acctest.VcrTest(t, resource.TestCase{
105+
PreCheck: func() { acctest.AccTestPreCheck(t) },
106+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
107+
Steps: []resource.TestStep{
108+
{
109+
Config: testAccFolder_tags(folderDisplayName, parent, map[string]string{org + "/" + tagKey: tagValue}),
110+
Check: resource.ComposeTestCheckFunc(
111+
testAccCheckGoogleFolderExists(t, "google_folder.folder_tags", &folder_tags),
112+
),
113+
},
114+
// Make sure import supports tags
115+
{
116+
ResourceName: "google_folder.folder_tags",
117+
ImportState: true,
118+
ImportStateVerify: true,
119+
ImportStateVerifyIgnore: []string{"tags", "deletion_protection"}, // we don't read tags back
120+
},
121+
// Update tags tries to replace the folder but fails due to deletion protection
122+
{
123+
Config: testAccFolder_tags(folderDisplayName, org, map[string]string{}),
124+
ExpectError: regexp.MustCompile("deletion_protection"),
125+
},
126+
{
127+
Config: testAccFolder_tagsAllowDestroy(folderDisplayName, parent, map[string]string{org + "/" + tagKey: tagValue}),
128+
},
129+
},
130+
})
131+
}
132+
93133
func testAccCheckGoogleFolderDestroyProducer(t *testing.T) func(s *terraform.State) error {
94134
return func(s *terraform.State) error {
95135
config := acctest.GoogleProviderConfig(t)
@@ -161,6 +201,39 @@ resource "google_folder" "folder1" {
161201
`, folder, parent)
162202
}
163203

204+
func testAccFolder_tags(folder, parent string, tags map[string]string) string {
205+
r := fmt.Sprintf(`
206+
resource "google_folder" "folder_tags" {
207+
display_name = "%s"
208+
parent = "%s"
209+
tags = {`, folder, parent)
210+
211+
l := ""
212+
for key, value := range tags {
213+
l += fmt.Sprintf("%q = %q\n", key, value)
214+
}
215+
216+
l += fmt.Sprintf("}\n}")
217+
return r + l
218+
}
219+
220+
func testAccFolder_tagsAllowDestroy(folder, parent string, tags map[string]string) string {
221+
r := fmt.Sprintf(`
222+
resource "google_folder" "folder_tags" {
223+
display_name = "%s"
224+
parent = "%s"
225+
deletion_protection = false
226+
tags = {`, folder, parent)
227+
228+
l := ""
229+
for key, value := range tags {
230+
l += fmt.Sprintf("%q = %q\n", key, value)
231+
}
232+
233+
l += fmt.Sprintf("}\n}")
234+
return r + l
235+
}
236+
164237
func testAccFolder_move(folder1, folder2, parent string) string {
165238
return fmt.Sprintf(`
166239
resource "google_folder" "folder1" {

website/docs/r/google_folder.html.markdown

+11
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ resource must have `roles/resourcemanager.folderCreator`. See the
2020
[Access Control for Folders Using IAM](https://cloud.google.com/resource-manager/docs/access-control-folders)
2121
doc for more information.
2222

23+
~> It may take a while for the attached tag bindings to be deleted after the folder is scheduled to be deleted.
24+
2325
## Example Usage
2426

2527
```hcl
@@ -34,6 +36,13 @@ resource "google_folder" "team-abc" {
3436
display_name = "Team ABC"
3537
parent = google_folder.department1.name
3638
}
39+
40+
# Folder with a tag
41+
resource "google_folder" "department1" {
42+
display_name = "Department 1"
43+
parent = "organizations/1234567"
44+
tags = {"1234567/env":"staging"}
45+
}
3746
```
3847

3948
## Argument Reference
@@ -46,6 +55,8 @@ The following arguments are supported:
4655
* `parent` - (Required) The resource name of the parent Folder or Organization.
4756
Must be of the form `folders/{folder_id}` or `organizations/{org_id}`.
4857

58+
* `tags` - (Optional) A map of resource manager tags. Resource manager tag keys and values have the same definition as resource manager tags. Keys must be in the format tagKeys/{tag_key_id}, and values are in the format tagValues/456. The field is ignored when empty. The field is immutable and causes resource replacement when mutated.
59+
4960
## Attributes Reference
5061

5162
In addition to the arguments listed above, the following computed attributes are

0 commit comments

Comments
 (0)