-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #165 from Cox-Automotive/AddDefaultTagsFieldToProv…
…iderBlock Add default tags field to provider block
- Loading branch information
Showing
18 changed files
with
959 additions
and
119 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/Cox-Automotive/alks-go" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
) | ||
|
||
func TagsSchema() *schema.Schema { | ||
return &schema.Schema{ | ||
Type: schema.TypeMap, | ||
Optional: true, | ||
Elem: &schema.Schema{Type: schema.TypeString}, | ||
} | ||
} | ||
|
||
func TagsSchemaComputed() *schema.Schema { | ||
return &schema.Schema{ | ||
Type: schema.TypeMap, | ||
Optional: true, | ||
Computed: true, | ||
Elem: &schema.Schema{Type: schema.TypeString}, | ||
} | ||
} | ||
|
||
//Removes default tags from a map of role specific + default tags | ||
func removeDefaultTags(allTags map[string]interface{}, defalutTags []alks.Tag) []alks.Tag { | ||
for _, t := range defalutTags { | ||
//If the key and value of a tag returned from the role exists in the defaultTags list | ||
//We will assume it was set as a default tag and remove it from role specific tag list | ||
if val, ok := allTags[t.Key]; ok { | ||
if val == t.Value { | ||
delete(allTags, t.Key) | ||
} | ||
} | ||
|
||
} | ||
return tagMapToSlice(allTags) | ||
} | ||
|
||
func tagMapToSlice(tagMap map[string]interface{}) []alks.Tag { | ||
tags := []alks.Tag{} | ||
for k, v := range tagMap { | ||
tag := alks.Tag{Key: k, Value: v.(string)} | ||
tags = append(tags, tag) | ||
} | ||
return tags | ||
} | ||
|
||
func tagSliceToMap(tagSlice []alks.Tag) map[string]interface{} { | ||
tagMap := make(map[string]interface{}) | ||
for _, t := range tagSlice { | ||
tagMap[t.Key] = t.Value | ||
} | ||
return tagMap | ||
} | ||
|
||
//Combines tags defined on an individual resource with the default tags listed on the provider block | ||
//Resource specific tags will overwrite default tags | ||
func combineTagsWithDefault(tags []alks.Tag, defaultTags []alks.Tag) []alks.Tag { | ||
defaultTagsMap := tagSliceToMap(defaultTags) | ||
|
||
for _, t := range tags { | ||
defaultTagsMap[t.Key] = t.Value | ||
} | ||
allTags := tagMapToSlice(defaultTagsMap) | ||
|
||
return allTags | ||
} | ||
|
||
func SetTagsDiff(_ context.Context, diff *schema.ResourceDiff, meta interface{}) error { | ||
defaultTags := meta.(*AlksClient).defaultTags | ||
|
||
resourceTags := tagMapToSlice(diff.Get("tags").(map[string]interface{})) | ||
|
||
allTags := combineTagsWithDefault(resourceTags, defaultTags) | ||
|
||
// To ensure "tags_all" is correctly computed, we explicitly set the attribute diff | ||
// when the merger of resource-level tags onto provider-level tags results in n > 0 tags, | ||
// otherwise we mark the attribute as "Computed" only when their is a known diff (excluding an empty map) | ||
// or a change for "tags_all". | ||
|
||
if len(allTags) > 0 { | ||
if err := diff.SetNew("tags_all", tagSliceToMap(allTags)); err != nil { | ||
return fmt.Errorf("error setting new tags_all diff: %w", err) | ||
} | ||
} else if len(diff.Get("tags_all").(map[string]interface{})) > 0 { | ||
if err := diff.SetNewComputed("tags_all"); err != nil { | ||
return fmt.Errorf("error setting tags_all to computed: %w", err) | ||
} | ||
} else if diff.HasChange("tags_all") { | ||
if err := diff.SetNewComputed("tags_all"); err != nil { | ||
return fmt.Errorf("error setting tags_all to computed: %w", err) | ||
} | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
package main | ||
|
||
import ( | ||
"reflect" | ||
"testing" | ||
|
||
"github.com/Cox-Automotive/alks-go" | ||
) | ||
|
||
func TestRemoveDefaultTags(t *testing.T) { | ||
cases := []struct { | ||
allTagsMap map[string]interface{} | ||
defaultTagsSlice []alks.Tag | ||
expected []alks.Tag | ||
}{ | ||
{ | ||
allTagsMap: map[string]interface{}{ | ||
"resourceKey1": "resourceValue1", | ||
"defaultKey1": "defaultValue1", | ||
}, | ||
defaultTagsSlice: []alks.Tag{{Key: "defaultKey1", Value: "defaultValue1"}}, | ||
expected: []alks.Tag{{Key: "resourceKey1", Value: "resourceValue1"}}, | ||
}, | ||
{ | ||
allTagsMap: map[string]interface{}{ | ||
"defaultKey2": "defaultValue2", | ||
"defaultKey1": "resourceValue2", | ||
}, | ||
defaultTagsSlice: []alks.Tag{ | ||
{Key: "defaultKey2", Value: "defaultValue2"}, | ||
{Key: "defaultKey1", Value: "defaultValue2"}, | ||
}, | ||
expected: []alks.Tag{ | ||
{Key: "defaultKey1", Value: "resourceValue2"}, //Should not remove this key. We are assuming that if the key matches one in default but not the value, that the default key was overwritten on purpose in the role definition and shouldnt be removed | ||
}, | ||
}, | ||
} | ||
|
||
for _, c := range cases { | ||
resourceTagsSlice := removeDefaultTags(c.allTagsMap, c.defaultTagsSlice) | ||
if !reflect.DeepEqual(resourceTagsSlice, c.expected) { | ||
t.Fatalf("Error matching output and expected: %#v vs %#v", resourceTagsSlice, c.expected) | ||
} | ||
} | ||
} | ||
|
||
func TestTagMapToSlice(t *testing.T) { | ||
cases := []struct { | ||
tagMap map[string]interface{} | ||
expected []alks.Tag | ||
}{ | ||
{ | ||
tagMap: map[string]interface{}{ | ||
"key1": "value1", | ||
}, | ||
expected: []alks.Tag{{Key: "key1", Value: "value1"}}, | ||
}, | ||
} | ||
|
||
for _, c := range cases { | ||
tagSlice := tagMapToSlice(c.tagMap) | ||
if !reflect.DeepEqual(tagSlice, c.expected) { | ||
t.Fatalf("Error matching output and expected: %#v vs %#v", tagSlice, c.expected) | ||
} | ||
} | ||
} | ||
|
||
func TestTagSliceToMap(t *testing.T) { | ||
cases := []struct { | ||
tagSlice []alks.Tag | ||
expected map[string]interface{} | ||
}{ | ||
{ | ||
tagSlice: []alks.Tag{{Key: "defaultKey1", Value: "defaultValue1"}}, | ||
expected: map[string]interface{}{"defaultKey1": "defaultValue1"}, | ||
}, | ||
} | ||
|
||
for _, c := range cases { | ||
tagMap := tagSliceToMap(c.tagSlice) | ||
if !reflect.DeepEqual(tagMap, c.expected) { | ||
t.Fatalf("Error matching output and expected: %#v vs %#v", tagMap, c.expected) | ||
} | ||
} | ||
} | ||
|
||
func TestCombineTagsWithDefault(t *testing.T) { | ||
cases := []struct { | ||
defaultTagSlice []alks.Tag | ||
resourceTagSlice []alks.Tag | ||
expected []alks.Tag | ||
}{ | ||
{ | ||
defaultTagSlice: []alks.Tag{{Key: "defaultKey1", Value: "defaultValue1"}}, | ||
resourceTagSlice: []alks.Tag{{Key: "defaultKey1", Value: "resourceValue1"}}, | ||
expected: []alks.Tag{{Key: "defaultKey1", Value: "resourceValue1"}}, | ||
}, | ||
} | ||
|
||
for _, c := range cases { | ||
tagSlice := combineTagsWithDefault(c.resourceTagSlice, c.defaultTagSlice) | ||
if !reflect.DeepEqual(tagSlice, c.expected) { | ||
t.Fatalf("Error matching output and expected: %#v vs %#v", tagSlice, c.expected) | ||
} | ||
} | ||
} |
Oops, something went wrong.