Skip to content

Commit

Permalink
Create data sources for tag_keys and tag_values (#6042)
Browse files Browse the repository at this point in the history
* Created branch tag-data-sources from main

* initial commit of data sources for IAM tags

* Tests for tags data sources

* Added documentation

* Making error messages better
  • Loading branch information
nphilbrook authored May 24, 2022
1 parent 7f1ec36 commit f8ff657
Show file tree
Hide file tree
Showing 7 changed files with 505 additions and 0 deletions.
106 changes: 106 additions & 0 deletions mmv1/third_party/terraform/data_sources/data_source_tags_tag_key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package google

import (
"errors"
"fmt"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
resourceManagerV3 "google.golang.org/api/cloudresourcemanager/v3"
)

func dataSourceGoogleTagsTagKey() *schema.Resource {
return &schema.Resource{
Read: dataSourceGoogleTagsTagKeyRead,

Schema: map[string]*schema.Schema{
"parent": {
Type: schema.TypeString,
Required: true,
},
"short_name": {
Type: schema.TypeString,
Required: true,
},
"namespaced_name": {
Type: schema.TypeString,
Computed: true,
},
"description": {
Type: schema.TypeString,
Computed: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
"id": {
Type: schema.TypeString,
Computed: true,
},
"create_time": {
Type: schema.TypeString,
Computed: true,
},
"update_time": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func dataSourceGoogleTagsTagKeyRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
userAgent, err := generateUserAgentString(d, config.userAgent)
if err != nil {
return err
}

var tagKeyMatch *resourceManagerV3.TagKey
parent := d.Get("parent").(string)
shortName := d.Get("short_name").(string)
token := ""

for paginate := true; paginate; {
resp, err := config.NewResourceManagerV3Client(userAgent).TagKeys.List().Parent(parent).PageSize(300).PageToken(token).Do()
if err != nil {
return fmt.Errorf("error reading tag key list: %s", err)
}

for _, tagKey := range resp.TagKeys {
if tagKey.ShortName == shortName {
if tagKeyMatch != nil {
return errors.New("more than one matching tag key found")
}
tagKeyMatch = tagKey
}
}
token = resp.NextPageToken
paginate = token != ""
}

if tagKeyMatch == nil {
return fmt.Errorf("tag key with short_name %s not found under parent %s", shortName, parent)
}

d.SetId(tagKeyMatch.Name)
nameParts := strings.Split(tagKeyMatch.Name, "/")
if err := d.Set("name", nameParts[1]); err != nil {
return fmt.Errorf("Error setting tag key name: %s", err)
}
if err := d.Set("namespaced_name", tagKeyMatch.NamespacedName); err != nil {
return fmt.Errorf("Error setting tag key namespaced_name: %s", err)
}
if err := d.Set("create_time", tagKeyMatch.CreateTime); err != nil {
return fmt.Errorf("Error setting tag key create_time: %s", err)
}
if err := d.Set("update_time", tagKeyMatch.UpdateTime); err != nil {
return fmt.Errorf("Error setting tag key update_time: %s", err)
}
if err := d.Set("description", tagKeyMatch.Description); err != nil {
return fmt.Errorf("Error setting tag key description: %s", err)
}

return nil
}
106 changes: 106 additions & 0 deletions mmv1/third_party/terraform/data_sources/data_source_tags_tag_value.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package google

import (
"errors"
"fmt"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
resourceManagerV3 "google.golang.org/api/cloudresourcemanager/v3"
)

func dataSourceGoogleTagsTagValue() *schema.Resource {
return &schema.Resource{
Read: dataSourceGoogleTagsTagValueRead,

Schema: map[string]*schema.Schema{
"parent": {
Type: schema.TypeString,
Required: true,
},
"short_name": {
Type: schema.TypeString,
Required: true,
},
"namespaced_name": {
Type: schema.TypeString,
Computed: true,
},
"description": {
Type: schema.TypeString,
Computed: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
"id": {
Type: schema.TypeString,
Computed: true,
},
"create_time": {
Type: schema.TypeString,
Computed: true,
},
"update_time": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func dataSourceGoogleTagsTagValueRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
userAgent, err := generateUserAgentString(d, config.userAgent)
if err != nil {
return err
}

var tagValueMatch *resourceManagerV3.TagValue
parent := d.Get("parent").(string)
shortName := d.Get("short_name").(string)
token := ""

for paginate := true; paginate; {
resp, err := config.NewResourceManagerV3Client(userAgent).TagValues.List().Parent(parent).PageSize(300).PageToken(token).Do()
if err != nil {
return fmt.Errorf("error reading tag value list: %s", err)
}

for _, tagValue := range resp.TagValues {
if tagValue.ShortName == shortName {
if tagValueMatch != nil {
return errors.New("more than one matching tag value found")
}
tagValueMatch = tagValue
}
}
token = resp.NextPageToken
paginate = token != ""
}

if tagValueMatch == nil {
return fmt.Errorf("tag value with short_name %s not found under parent %s", shortName, parent)
}

d.SetId(tagValueMatch.Name)
nameParts := strings.Split(tagValueMatch.Name, "/")
if err := d.Set("name", nameParts[1]); err != nil {
return fmt.Errorf("Error setting tag value name: %s", err)
}
if err := d.Set("namespaced_name", tagValueMatch.NamespacedName); err != nil {
return fmt.Errorf("Error setting tag value namespaced_name: %s", err)
}
if err := d.Set("create_time", tagValueMatch.CreateTime); err != nil {
return fmt.Errorf("Error setting tag value create_time: %s", err)
}
if err := d.Set("update_time", tagValueMatch.UpdateTime); err != nil {
return fmt.Errorf("Error setting tag value update_time: %s", err)
}
if err := d.Set("description", tagValueMatch.Description); err != nil {
return fmt.Errorf("Error setting tag value description: %s", err)
}

return nil
}
93 changes: 93 additions & 0 deletions mmv1/third_party/terraform/tests/data_source_tags_tag_key_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package google

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func TestAccDataSourceGoogleTagsTagKey_default(t *testing.T) {
org := getTestOrgFromEnv(t)

parent := fmt.Sprintf("organizations/%s", org)
shortName := "tf-test-" + randString(t, 10)

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDataSourceGoogleTagsTagKeyConfig(parent, shortName),
Check: resource.ComposeTestCheckFunc(
testAccDataSourceGoogleTagsTagKeyCheck("data.google_tags_tag_key.my_tag_key", "google_tags_tag_key.foobar"),
),
},
},
})
}

func TestAccDataSourceGoogleTagsTagKey_dot(t *testing.T) {
org := getTestOrgFromEnv(t)

parent := fmt.Sprintf("organizations/%s", org)
shortName := "terraform.test." + randString(t, 10)

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDataSourceGoogleTagsTagKeyConfig(parent, shortName),
Check: resource.ComposeTestCheckFunc(
testAccDataSourceGoogleTagsTagKeyCheck("data.google_tags_tag_key.my_tag_key", "google_tags_tag_key.foobar"),
),
},
},
})
}

func testAccDataSourceGoogleTagsTagKeyCheck(data_source_name string, resource_name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
ds, ok := s.RootModule().Resources[data_source_name]
if !ok {
return fmt.Errorf("root module has no resource called %s", data_source_name)
}

rs, ok := s.RootModule().Resources[resource_name]
if !ok {
return fmt.Errorf("can't find %s in state", resource_name)
}

ds_attr := ds.Primary.Attributes
rs_attr := rs.Primary.Attributes
tag_key_attrs_to_test := []string{"parent", "short_name", "name", "namespaced_name", "create_time", "update_time", "description"}

for _, attr_to_check := range tag_key_attrs_to_test {
if ds_attr[attr_to_check] != rs_attr[attr_to_check] {
return fmt.Errorf(
"%s is %s; want %s",
attr_to_check,
ds_attr[attr_to_check],
rs_attr[attr_to_check],
)
}
}
return nil
}
}

func testAccDataSourceGoogleTagsTagKeyConfig(parent string, shortName string) string {
return fmt.Sprintf(`
resource "google_tags_tag_key" "foobar" {
parent = "%s"
short_name = "%s"
}
data "google_tags_tag_key" "my_tag_key" {
parent = google_tags_tag_key.foobar.parent
short_name = google_tags_tag_key.foobar.short_name
}
`, parent, shortName)
}
Loading

0 comments on commit f8ff657

Please sign in to comment.