Skip to content

Commit

Permalink
Merge pull request #10418 from terraform-providers/f-ignore_tags-poc
Browse files Browse the repository at this point in the history
[Proof of Concept] provider: Ignore tags implementation
  • Loading branch information
bflad authored Oct 31, 2019
2 parents 74ca20a + c56a1e9 commit 1882316
Show file tree
Hide file tree
Showing 10 changed files with 656 additions and 6 deletions.
11 changes: 9 additions & 2 deletions aws/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ import (
"github.com/aws/aws-sdk-go/service/xray"
awsbase "github.com/hashicorp/aws-sdk-go-base"
"github.com/hashicorp/terraform-plugin-sdk/helper/logging"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
)

type Config struct {
Expand All @@ -158,8 +159,10 @@ type Config struct {
AllowedAccountIds []string
ForbiddenAccountIds []string

Endpoints map[string]string
Insecure bool
Endpoints map[string]string
IgnoreTagPrefixes []string
IgnoreTags []string
Insecure bool

SkipCredsValidation bool
SkipGetEC2Platforms bool
Expand Down Expand Up @@ -239,6 +242,8 @@ type AWSClient struct {
glueconn *glue.Glue
guarddutyconn *guardduty.GuardDuty
iamconn *iam.IAM
ignoreTagPrefixes keyvaluetags.KeyValueTags
ignoreTags keyvaluetags.KeyValueTags
inspectorconn *inspector.Inspector
iotconn *iot.IoT
iotanalyticsconn *iotanalytics.IoTAnalytics
Expand Down Expand Up @@ -432,6 +437,8 @@ func (c *Config) Client() (interface{}, error) {
glueconn: glue.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints["glue"])})),
guarddutyconn: guardduty.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints["guardduty"])})),
iamconn: iam.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints["iam"])})),
ignoreTagPrefixes: keyvaluetags.New(c.IgnoreTagPrefixes),
ignoreTags: keyvaluetags.New(c.IgnoreTags),
inspectorconn: inspector.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints["inspector"])})),
iotconn: iot.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints["iot"])})),
iotanalyticsconn: iotanalytics.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints["iotanalytics"])})),
Expand Down
32 changes: 32 additions & 0 deletions aws/internal/keyvaluetags/key_value_tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,30 @@ func (tags KeyValueTags) IgnoreElasticbeanstalk() KeyValueTags {
return result
}

// IgnorePrefixes returns non-matching tag key prefixes.
func (tags KeyValueTags) IgnorePrefixes(ignoreTagPrefixes KeyValueTags) KeyValueTags {
result := make(KeyValueTags)

for k, v := range tags {
var ignore bool

for ignoreTagPrefix := range ignoreTagPrefixes {
if strings.HasPrefix(k, ignoreTagPrefix) {
ignore = true
break
}
}

if ignore {
continue
}

result[k] = v
}

return result
}

// IgnoreRDS returns non-AWS and non-RDS tag keys.
func (tags KeyValueTags) IgnoreRds() KeyValueTags {
result := make(KeyValueTags)
Expand Down Expand Up @@ -178,6 +202,14 @@ func New(i interface{}) KeyValueTags {
kvtm[k] = &str
}

return kvtm
case []string:
kvtm := make(KeyValueTags, len(value))

for _, v := range value {
kvtm[v] = nil
}

return kvtm
case []interface{}:
kvtm := make(KeyValueTags, len(value))
Expand Down
163 changes: 161 additions & 2 deletions aws/internal/keyvaluetags/key_value_tags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,93 @@ func TestKeyValueTagsIgnoreElasticbeanstalk(t *testing.T) {
}
}

func TestKeyValueTagsIgnorePrefixes(t *testing.T) {
testCases := []struct {
name string
tags KeyValueTags
ignoreTagPrefixes KeyValueTags
want map[string]string
}{
{
name: "empty",
tags: New(map[string]string{}),
ignoreTagPrefixes: New([]string{
"key1",
"key2",
"key3",
}),
want: map[string]string{},
},
{
name: "all_exact",
tags: New(map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
}),
ignoreTagPrefixes: New([]string{
"key1",
"key2",
"key3",
}),
want: map[string]string{},
},
{
name: "all_prefix",
tags: New(map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
}),
ignoreTagPrefixes: New([]string{
"key",
}),
want: map[string]string{},
},
{
name: "mixed",
tags: New(map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
}),
ignoreTagPrefixes: New([]string{
"key1",
}),
want: map[string]string{
"key2": "value2",
"key3": "value3",
},
},
{
name: "none",
tags: New(map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
}),
ignoreTagPrefixes: New([]string{
"key4",
"key5",
"key6",
}),
want: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
}

for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
got := testCase.tags.IgnorePrefixes(testCase.ignoreTagPrefixes)

testKeyValueTagsVerifyMap(t, got.Map(), testCase.want)
})
}
}

func TestKeyValueTagsIgnoreRds(t *testing.T) {
testCases := []struct {
name string
Expand Down Expand Up @@ -256,12 +343,45 @@ func TestKeyValueTagsKeys(t *testing.T) {
want []string
}{
{
name: "empty",
name: "empty_map_string_interface",
tags: New(map[string]interface{}{}),
want: []string{},
},
{
name: "empty_map_string_stringPointer",
tags: New(map[string]*string{}),
want: []string{},
},
{
name: "empty_map_string_string",
tags: New(map[string]string{}),
want: []string{},
},
{
name: "non_empty",
name: "empty_slice_interface",
tags: New(map[string]interface{}{}),
want: []string{},
},
{
name: "empty_slice_string",
tags: New(map[string]string{}),
want: []string{},
},
{
name: "non_empty_map_string_interface",
tags: New(map[string]interface{}{
"key1": "value1",
"key2": "value2",
"key3": "value3",
}),
want: []string{
"key1",
"key2",
"key3",
},
},
{
name: "non_empty_map_string_string",
tags: New(map[string]string{
"key1": "value1",
"key2": "value2",
Expand All @@ -273,6 +393,45 @@ func TestKeyValueTagsKeys(t *testing.T) {
"key3",
},
},
{
name: "non_empty_map_string_stringPointer",
tags: New(map[string]*string{
"key1": testStringPtr("value1"),
"key2": testStringPtr("value2"),
"key3": testStringPtr("value3"),
}),
want: []string{
"key1",
"key2",
"key3",
},
},
{
name: "non_empty_slice_interface",
tags: New([]interface{}{
"key1",
"key2",
"key3",
}),
want: []string{
"key1",
"key2",
"key3",
},
},
{
name: "non_empty_slice_string",
tags: New([]string{
"key1",
"key2",
"key3",
}),
want: []string{
"key1",
"key2",
"key3",
},
},
}

for _, testCase := range testCases {
Expand Down
28 changes: 28 additions & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,22 @@ func Provider() terraform.ResourceProvider {

"endpoints": endpointsSchema(),

"ignore_tag_prefixes": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
Description: "Resource tag key prefixes to ignore across all resources.",
},

"ignore_tags": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
Description: "Resource tag keys to ignore across all resources.",
},

"insecure": {
Type: schema.TypeBool,
Optional: true,
Expand Down Expand Up @@ -1093,6 +1109,18 @@ func providerConfigure(d *schema.ResourceData, terraformVersion string) (interfa
}
}

if v, ok := d.GetOk("ignore_tag_prefixes"); ok {
for _, ignoreTagPrefixRaw := range v.(*schema.Set).List() {
config.IgnoreTagPrefixes = append(config.IgnoreTagPrefixes, ignoreTagPrefixRaw.(string))
}
}

if v, ok := d.GetOk("ignore_tags"); ok {
for _, ignoreTagRaw := range v.(*schema.Set).List() {
config.IgnoreTags = append(config.IgnoreTags, ignoreTagRaw.(string))
}
}

if v, ok := d.GetOk("allowed_account_ids"); ok {
for _, accountIDRaw := range v.(*schema.Set).List() {
config.AllowedAccountIds = append(config.AllowedAccountIds, accountIDRaw.(string))
Expand Down
Loading

0 comments on commit 1882316

Please sign in to comment.