Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Proof of Concept] provider: Ignore tags implementation #10418

Merged
merged 9 commits into from
Oct 31, 2019
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