From 09f86881a679045b1d226780e246098c4e7f3dba Mon Sep 17 00:00:00 2001 From: xescugc Date: Wed, 25 Aug 2021 16:26:46 +0200 Subject: [PATCH] hcl: When writting Module variables normalize the names As in some cases, like 'tags', they have keys that cannot be converted direclty into valirables names so we have to normailze them. For this we reused the 'tag' logic and abstracted it to the 'util' lib so it can be shared between the 2 packages --- CHANGELOG.md | 5 +++++ hcl/writer.go | 7 ++++--- hcl/writer_test.go | 11 +++++++++++ tag/tag.go | 12 +++--------- util/name.go | 14 ++++++++++++++ util/name_test.go | 37 +++++++++++++++++++++++++++++++++++++ 6 files changed, 74 insertions(+), 12 deletions(-) create mode 100644 util/name.go create mode 100644 util/name_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 9054ad4987..1c4d5d50df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,11 @@ - Integration between Interpolation and Modules has been changed to not generate invalid HCL references ([Issue #219](https://github.com/cycloidio/terracognita/issues/219) +### Fixed + +- Variables names will now be normalized to be valid HCL + ([PUll #219](https://github.com/cycloidio/terracognita/pull/227) + ## [0.7.2] _2021-08-13_ ### Added diff --git a/hcl/writer.go b/hcl/writer.go index c84c7ceea3..b199fed7e0 100644 --- a/hcl/writer.go +++ b/hcl/writer.go @@ -15,6 +15,7 @@ import ( "github.com/cycloidio/terracognita/errcode" "github.com/cycloidio/terracognita/log" "github.com/cycloidio/terracognita/provider" + "github.com/cycloidio/terracognita/util" "github.com/cycloidio/terracognita/writer" "github.com/hashicorp/hcl/v2/hclwrite" "github.com/pkg/errors" @@ -362,7 +363,7 @@ func walkVariables(cfg map[string]interface{}, validVariables map[string]struct{ case []interface{}: if len(v) == 0 { if hasKey(validVariables, currentKey) { - varName := strings.ReplaceAll(currentKey, ".", "_") + varName := util.NormalizeName(strings.ReplaceAll(currentKey, ".", "_")) variables[varName] = map[string]interface{}{ "default": cfg[key], } @@ -378,7 +379,7 @@ func walkVariables(cfg map[string]interface{}, validVariables map[string]struct{ } } else { if hasKey(validVariables, currentKey) { - varName := strings.ReplaceAll(currentKey, ".", "_") + varName := util.NormalizeName(strings.ReplaceAll(currentKey, ".", "_")) variables[varName] = map[string]interface{}{ "default": cfg[key], } @@ -389,7 +390,7 @@ func walkVariables(cfg map[string]interface{}, validVariables map[string]struct{ // This means is a "simple" value so we can // directly replace it with the variable if hasKey(validVariables, currentKey) { - varName := strings.ReplaceAll(currentKey, ".", "_") + varName := util.NormalizeName(strings.ReplaceAll(currentKey, ".", "_")) variables[varName] = map[string]interface{}{ "default": cfg[key], } diff --git a/hcl/writer_test.go b/hcl/writer_test.go index 1c2f8d5908..81132058c1 100644 --- a/hcl/writer_test.go +++ b/hcl/writer_test.go @@ -332,6 +332,9 @@ resource "type" "name" { "key": "value", "key2": "value", "key3": []interface{}{}, + "key4": map[string]interface{}{ + "nested:key:4": "value4", + }, } ehcl = ` resource "type" "name" { @@ -342,12 +345,16 @@ resource "type" "name2" { key = var.type_name2_key key2 = var.type_name2_key2 key3 = var.type_name2_key3 + key4 { + "nested:key:4" = var.type_name2_key4_nested_key_4 + } } module "test" { # type_name2_key = "value" # type_name2_key2 = "value" # type_name2_key3 = [] + # type_name2_key4_nested_key_4 = "value4" # type_name_key = "value" source = "./module-test" } @@ -381,6 +388,10 @@ variable "type_name2_key3" { default = [] } +variable "type_name2_key4_nested_key_4" { + default = "value4" +} + variable "type_name_key" { default = "value" } diff --git a/tag/tag.go b/tag/tag.go index 072014edca..c9d3320950 100644 --- a/tag/tag.go +++ b/tag/tag.go @@ -11,6 +11,7 @@ import ( "github.com/aws/aws-sdk-go/service/rds" "github.com/chr4/pwgen" "github.com/cycloidio/terracognita/errcode" + "github.com/cycloidio/terracognita/util" "github.com/hashicorp/hcl/v2/hclsyntax" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -18,7 +19,6 @@ import ( // nameRegexp is the new regexp used to validate the names // of the resources on TF (defined on configs/configschema/internal_validate.go) var nameRegexp = regexp.MustCompile(`^[a-z0-9_]+$`) -var invalidNameRegexp = regexp.MustCompile(`[^a-z0-9_]`) // Tag it's an easy representation of // a ec2.Filter for tags @@ -75,8 +75,8 @@ func GetNameFromTag(key string, srd *schema.ResourceData, fallback string) strin n = strings.ToLower(name.(string)) } - forcedN := forceResourceName(n) - forcedFallback := forceResourceName(fallback) + forcedN := util.NormalizeName(n) + forcedFallback := util.NormalizeName(fallback) if isValidResourceName(n) && hclsyntax.ValidIdentifier(n) { return n @@ -97,12 +97,6 @@ func isValidResourceName(name string) bool { return nameRegexp.MatchString(name) } -// forceResourceName will try to replace all the -// invalid characters of the name for _ -func forceResourceName(name string) string { - return invalidNameRegexp.ReplaceAllString(name, "_") -} - // GetOtherTags used to check other possible tag attributes on resources func GetOtherTags(provider string, srd *schema.ResourceData, filterTag Tag) (string, bool) { // keep the same logic as r.data.GetOk diff --git a/util/name.go b/util/name.go new file mode 100644 index 0000000000..8697decff0 --- /dev/null +++ b/util/name.go @@ -0,0 +1,14 @@ +package util + +import ( + "regexp" + "strings" +) + +var invalidNameRegexp = regexp.MustCompile(`[^a-z0-9_]`) + +// NormalizeName will convert the n into an low case alphanumeric value +// and the invalid characters will be replaced by '_' +func NormalizeName(n string) string { + return invalidNameRegexp.ReplaceAllString(strings.ToLower(n), "_") +} diff --git a/util/name_test.go b/util/name_test.go new file mode 100644 index 0000000000..1b786d37a8 --- /dev/null +++ b/util/name_test.go @@ -0,0 +1,37 @@ +package util_test + +import ( + "testing" + + "github.com/cycloidio/terracognita/util" + "github.com/stretchr/testify/assert" +) + +func TestNormalizeName(t *testing.T) { + tests := []struct { + Name string + In string + Expected string + }{ + { + Name: "NoChange", + In: "in", + Expected: "in", + }, + { + Name: "UpperCase", + In: "IN", + Expected: "in", + }, + { + Name: "Invalid", + In: ":a", + Expected: "_a", + }, + } + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + assert.Equal(t, tt.Expected, util.NormalizeName(tt.In)) + }) + } +}