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

provider: Update preview ignore tags handling to configuration block and shared struct type #12586

Merged
merged 1 commit into from
Apr 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions aws/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,9 @@ type Config struct {
AllowedAccountIds []string
ForbiddenAccountIds []string

Endpoints map[string]string
IgnoreTagPrefixes []string
IgnoreTags []string
Insecure bool
Endpoints map[string]string
IgnoreTagsConfig *keyvaluetags.IgnoreConfig
Insecure bool

SkipCredsValidation bool
SkipGetEC2Platforms bool
Expand Down Expand Up @@ -254,8 +253,7 @@ type AWSClient struct {
guarddutyconn *guardduty.GuardDuty
greengrassconn *greengrass.Greengrass
iamconn *iam.IAM
ignoreTagPrefixes keyvaluetags.KeyValueTags
ignoreTags keyvaluetags.KeyValueTags
IgnoreTagsConfig *keyvaluetags.IgnoreConfig
imagebuilderconn *imagebuilder.Imagebuilder
inspectorconn *inspector.Inspector
iotconn *iot.IoT
Expand Down Expand Up @@ -472,8 +470,7 @@ func (c *Config) Client() (interface{}, error) {
guarddutyconn: guardduty.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints["guardduty"])})),
greengrassconn: greengrass.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints["greengrass"])})),
iamconn: iam.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints["iam"])})),
ignoreTagPrefixes: keyvaluetags.New(c.IgnoreTagPrefixes),
ignoreTags: keyvaluetags.New(c.IgnoreTags),
IgnoreTagsConfig: c.IgnoreTagsConfig,
imagebuilderconn: imagebuilder.New(sess.Copy(&aws.Config{Endpoint: aws.String(c.Endpoints["imagebuilder"])})),
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"])})),
Expand Down
18 changes: 18 additions & 0 deletions aws/internal/keyvaluetags/key_value_tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ const (
RdsTagKeyPrefix = `rds:`
)

// IgnoreConfig contains various options for removing resource tags.
type IgnoreConfig struct {
Keys KeyValueTags
KeyPrefixes KeyValueTags
}

// KeyValueTags is a standard implementation for AWS key-value resource tags.
// The AWS Go SDK is split into multiple service packages, each service with
// its own Go struct type representing a resource tag. To standardize logic
Expand All @@ -38,6 +44,18 @@ func (tags KeyValueTags) IgnoreAws() KeyValueTags {
return result
}

// IgnoreConfig returns any tags not removed by a given configuration.
func (tags KeyValueTags) IgnoreConfig(config *IgnoreConfig) KeyValueTags {
if config == nil {
return tags
}

result := tags.IgnorePrefixes(config.KeyPrefixes)
result = result.Ignore(config.Keys)

return result
}

// IgnoreElasticbeanstalk returns non-AWS and non-Elasticbeanstalk tag keys.
func (tags KeyValueTags) IgnoreElasticbeanstalk() KeyValueTags {
result := make(KeyValueTags)
Expand Down
197 changes: 197 additions & 0 deletions aws/internal/keyvaluetags/key_value_tags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,203 @@ func TestKeyValueTagsIgnoreAws(t *testing.T) {
}
}

func TestKeyValueTagsIgnoreConfig(t *testing.T) {
testCases := []struct {
name string
tags KeyValueTags
ignoreConfig *IgnoreConfig
want map[string]string
}{
{
name: "empty config",
tags: New(map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
}),
ignoreConfig: &IgnoreConfig{},
want: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
{
name: "no config",
tags: New(map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
}),
ignoreConfig: nil,
want: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
{
name: "no tags",
tags: New(map[string]string{}),
ignoreConfig: &IgnoreConfig{
KeyPrefixes: New([]string{
"key1",
"key2",
"key3",
}),
},
want: map[string]string{},
},
{
name: "keys all matching",
tags: New(map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
}),
ignoreConfig: &IgnoreConfig{
Keys: New(map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
}),
},
want: map[string]string{},
},
{
name: "keys some matching",
tags: New(map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
}),
ignoreConfig: &IgnoreConfig{
Keys: New(map[string]string{
"key1": "value1",
}),
},
want: map[string]string{
"key2": "value2",
"key3": "value3",
},
},
{
name: "keys none matching",
tags: New(map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
}),
ignoreConfig: &IgnoreConfig{
Keys: New(map[string]string{
"key4": "value4",
"key5": "value5",
"key6": "value6",
}),
},
want: map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
},
},
{
name: "keys and key prefixes",
tags: New(map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
}),
ignoreConfig: &IgnoreConfig{
Keys: New([]string{
"key1",
}),
KeyPrefixes: New([]string{
"key2",
}),
},
want: map[string]string{
"key3": "value3",
},
},
{
name: "key prefixes all exact",
tags: New(map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
}),
ignoreConfig: &IgnoreConfig{
KeyPrefixes: New([]string{
"key1",
"key2",
"key3",
}),
},
want: map[string]string{},
},
{
name: "key prefixes all prefixed",
tags: New(map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
}),
ignoreConfig: &IgnoreConfig{
KeyPrefixes: New([]string{
"key",
}),
},
want: map[string]string{},
},
{
name: "key prefixes some prefixed",
tags: New(map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
}),
ignoreConfig: &IgnoreConfig{
KeyPrefixes: New([]string{
"key1",
}),
},
want: map[string]string{
"key2": "value2",
"key3": "value3",
},
},
{
name: "key prefixes none prefixed",
tags: New(map[string]string{
"key1": "value1",
"key2": "value2",
"key3": "value3",
}),
ignoreConfig: &IgnoreConfig{
KeyPrefixes: 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.IgnoreConfig(testCase.ignoreConfig)

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

func TestKeyValueTagsIgnoreElasticbeanstalk(t *testing.T) {
testCases := []struct {
name string
Expand Down
66 changes: 42 additions & 24 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
homedir "github.com/mitchellh/go-homedir"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
)

// Provider returns a terraform.ResourceProvider.
Expand Down Expand Up @@ -90,20 +91,29 @@ 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,
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
Description: "Resource tag keys to ignore across all resources.",
MaxItems: 1,
Description: "Configuration block with settings to ignore resource tags across all resources.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"keys": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
Description: "Resource tag keys to ignore across all resources.",
},
"key_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.",
},
},
},
},

"insecure": {
Expand Down Expand Up @@ -1108,6 +1118,7 @@ func providerConfigure(d *schema.ResourceData, terraformVersion string) (interfa
Region: d.Get("region").(string),
Endpoints: make(map[string]string),
MaxRetries: d.Get("max_retries").(int),
IgnoreTagsConfig: expandProviderIgnoreTags(d.Get("ignore_tags").([]interface{})),
Insecure: d.Get("insecure").(bool),
SkipCredsValidation: d.Get("skip_credentials_validation").(bool),
SkipGetEC2Platforms: d.Get("skip_get_ec2_platforms").(bool),
Expand Down Expand Up @@ -1151,18 +1162,6 @@ 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 Expand Up @@ -1240,3 +1239,22 @@ func endpointsSchema() *schema.Schema {
},
}
}

func expandProviderIgnoreTags(l []interface{}) *keyvaluetags.IgnoreConfig {
if len(l) == 0 || l[0] == nil {
return nil
}

ignoreConfig := &keyvaluetags.IgnoreConfig{}
m := l[0].(map[string]interface{})

if v, ok := m["keys"].(*schema.Set); ok {
ignoreConfig.Keys = keyvaluetags.New(v.List())
}

if v, ok := m["key_prefixes"].(*schema.Set); ok {
ignoreConfig.KeyPrefixes = keyvaluetags.New(v.List())
}

return ignoreConfig
}
Loading