From a6a78cb9f8ad12cf201d4e4b53db0b646f5cce75 Mon Sep 17 00:00:00 2001 From: Andrei Vsiakikh Date: Fri, 26 Sep 2025 16:43:16 +1200 Subject: [PATCH 1/5] fix rename issue --- ssm/parameters.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ssm/parameters.go b/ssm/parameters.go index 4d1e669..8ec747b 100644 --- a/ssm/parameters.go +++ b/ssm/parameters.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" goPath "path" + "strings" "github.com/apex/log" "github.com/aws/aws-sdk-go/aws" @@ -252,6 +253,16 @@ func GetParameters(names, paths, plainNames, plainPaths []string, transformation log.WithError(err).Fatal("Can't expand vars") } + // Normalize parameter names to support both uppercase and lowercase for backwards compatibility + // This ensures rename transformations work regardless of casing in config files + normalizedParameters := make(map[string]string) + for key, value := range parameters { + normalizedParameters[key] = value // original key + normalizedParameters[strings.ToLower(key)] = value // lowercase version + normalizedParameters[strings.ToUpper(key)] = value // uppercase version + } + parameters = normalizedParameters + for _, transformation := range transformationsList { parameters, err = transformation.Transform(parameters) if err != nil { From 60734289e1182dcf6e6579d18c3fc1481aae0388 Mon Sep 17 00:00:00 2001 From: Andrei Vsiakikh Date: Mon, 29 Sep 2025 11:11:10 +1300 Subject: [PATCH 2/5] upgrade ssm-parent --- ssm/parameters.go | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/ssm/parameters.go b/ssm/parameters.go index 8ec747b..5746cfd 100644 --- a/ssm/parameters.go +++ b/ssm/parameters.go @@ -253,13 +253,13 @@ func GetParameters(names, paths, plainNames, plainPaths []string, transformation log.WithError(err).Fatal("Can't expand vars") } - // Normalize parameter names to support both uppercase and lowercase for backwards compatibility - // This ensures rename transformations work regardless of casing in config files + // Normalize all parameter names to UPPERCASE to ensure consistent casing + // This solves the Viper case sensitivity issue where config keys are lowercase + // but AWS SSM parameters need to be matched regardless of original casing normalizedParameters := make(map[string]string) for key, value := range parameters { - normalizedParameters[key] = value // original key - normalizedParameters[strings.ToLower(key)] = value // lowercase version - normalizedParameters[strings.ToUpper(key)] = value // uppercase version + upperKey := strings.ToUpper(key) + normalizedParameters[upperKey] = value } parameters = normalizedParameters @@ -269,5 +269,14 @@ func GetParameters(names, paths, plainNames, plainPaths []string, transformation log.WithError(err).Fatal("can't transform parameter") } } + + // Normalize again after transformations to ensure all new keys are also uppercase + // This handles keys created by template and other transformations + finalNormalizedParameters := make(map[string]string) + for key, value := range parameters { + upperKey := strings.ToUpper(key) + finalNormalizedParameters[upperKey] = value + } + parameters = finalNormalizedParameters return } From 40b8624ba3ea81ad2a5d7acbaf7c89baeb39be83 Mon Sep 17 00:00:00 2001 From: Andrei Vsiakikh Date: Mon, 29 Sep 2025 11:49:29 +1300 Subject: [PATCH 3/5] fix rename issue --- ssm/parameters.go | 28 ++++++++++++++++++++++++++++ ssm/transformations/actions.go | 10 +++++----- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/ssm/parameters.go b/ssm/parameters.go index 5746cfd..6554a6b 100644 --- a/ssm/parameters.go +++ b/ssm/parameters.go @@ -263,6 +263,34 @@ func GetParameters(names, paths, plainNames, plainPaths []string, transformation } parameters = normalizedParameters + // Normalize transformation rule keys to uppercase to match normalized parameters + for _, transformation := range transformationsList { + switch t := transformation.(type) { + case *transformations.RenameTransformation: + normalizedRule := make(map[string]string) + for key, value := range t.Rule { + normalizedRule[strings.ToUpper(key)] = value + } + t.Rule = normalizedRule + case *transformations.TemplateTransformation: + normalizedRule := make(map[string]string) + for key, value := range t.Rule { + normalizedRule[strings.ToUpper(key)] = value + } + t.Rule = normalizedRule + case *transformations.TrimTransformation: + normalizedRule := make(map[string]string) + for key, value := range t.Rule { + normalizedRule[strings.ToUpper(key)] = value + } + t.Rule = normalizedRule + case *transformations.DeleteTransformation: + for i, key := range t.Rule { + t.Rule[i] = strings.ToUpper(key) + } + } + } + for _, transformation := range transformationsList { parameters, err = transformation.Transform(parameters) if err != nil { diff --git a/ssm/transformations/actions.go b/ssm/transformations/actions.go index 809c3d3..7c7e694 100644 --- a/ssm/transformations/actions.go +++ b/ssm/transformations/actions.go @@ -77,13 +77,13 @@ type TrimTransformation struct { } func (t *TrimTransformation) Transform(source map[string]string) (map[string]string, error) { - if _, found := t.Rule["trim"]; !found { - return source, fmt.Errorf("\"trim\" rule not set") + if _, found := t.Rule["TRIM"]; !found { + return source, fmt.Errorf("\"TRIM\" rule not set") } - if _, found := t.Rule["starts_with"]; !found { - return source, fmt.Errorf("\"starts_with\" rule not set") + if _, found := t.Rule["STARTS_WITH"]; !found { + return source, fmt.Errorf("\"STARTS_WITH\" rule not set") } - TrimKeys(source, t.Rule["trim"], t.Rule["starts_with"]) + TrimKeys(source, t.Rule["TRIM"], t.Rule["STARTS_WITH"]) return source, nil } From dc38158ca9517630b4ba5f1ba59d633deb6b8079 Mon Sep 17 00:00:00 2001 From: Andrei Vsiakikh Date: Mon, 29 Sep 2025 12:06:28 +1300 Subject: [PATCH 4/5] fix rename issue --- ssm/parameters.go | 27 ++++++--------------------- ssm/transformations/actions.go | 10 +++++----- 2 files changed, 11 insertions(+), 26 deletions(-) diff --git a/ssm/parameters.go b/ssm/parameters.go index 6554a6b..1d3581a 100644 --- a/ssm/parameters.go +++ b/ssm/parameters.go @@ -253,17 +253,15 @@ func GetParameters(names, paths, plainNames, plainPaths []string, transformation log.WithError(err).Fatal("Can't expand vars") } - // Normalize all parameter names to UPPERCASE to ensure consistent casing - // This solves the Viper case sensitivity issue where config keys are lowercase - // but AWS SSM parameters need to be matched regardless of original casing + // Normalize only the parameter keys to UPPERCASE to solve Viper case sensitivity issue + // This ensures AWS parameter names match the transformation rule keys from config normalizedParameters := make(map[string]string) for key, value := range parameters { - upperKey := strings.ToUpper(key) - normalizedParameters[upperKey] = value + normalizedParameters[strings.ToUpper(key)] = value } parameters = normalizedParameters - // Normalize transformation rule keys to uppercase to match normalized parameters + // Normalize transformation rule keys for rename/template/delete to UPPERCASE to match parameters for _, transformation := range transformationsList { switch t := transformation.(type) { case *transformations.RenameTransformation: @@ -278,17 +276,13 @@ func GetParameters(names, paths, plainNames, plainPaths []string, transformation normalizedRule[strings.ToUpper(key)] = value } t.Rule = normalizedRule - case *transformations.TrimTransformation: - normalizedRule := make(map[string]string) - for key, value := range t.Rule { - normalizedRule[strings.ToUpper(key)] = value - } - t.Rule = normalizedRule case *transformations.DeleteTransformation: for i, key := range t.Rule { t.Rule[i] = strings.ToUpper(key) } } + // Note: TrimTransformation config keys (trim, starts_with) are NOT normalized + // because they are configuration instructions, not parameter names } for _, transformation := range transformationsList { @@ -297,14 +291,5 @@ func GetParameters(names, paths, plainNames, plainPaths []string, transformation log.WithError(err).Fatal("can't transform parameter") } } - - // Normalize again after transformations to ensure all new keys are also uppercase - // This handles keys created by template and other transformations - finalNormalizedParameters := make(map[string]string) - for key, value := range parameters { - upperKey := strings.ToUpper(key) - finalNormalizedParameters[upperKey] = value - } - parameters = finalNormalizedParameters return } diff --git a/ssm/transformations/actions.go b/ssm/transformations/actions.go index 7c7e694..809c3d3 100644 --- a/ssm/transformations/actions.go +++ b/ssm/transformations/actions.go @@ -77,13 +77,13 @@ type TrimTransformation struct { } func (t *TrimTransformation) Transform(source map[string]string) (map[string]string, error) { - if _, found := t.Rule["TRIM"]; !found { - return source, fmt.Errorf("\"TRIM\" rule not set") + if _, found := t.Rule["trim"]; !found { + return source, fmt.Errorf("\"trim\" rule not set") } - if _, found := t.Rule["STARTS_WITH"]; !found { - return source, fmt.Errorf("\"STARTS_WITH\" rule not set") + if _, found := t.Rule["starts_with"]; !found { + return source, fmt.Errorf("\"starts_with\" rule not set") } - TrimKeys(source, t.Rule["TRIM"], t.Rule["STARTS_WITH"]) + TrimKeys(source, t.Rule["trim"], t.Rule["starts_with"]) return source, nil } From f3201ba8f03a6050fe0a0859efdcfb05af22f833 Mon Sep 17 00:00:00 2001 From: Andrei Vsiakikh Date: Mon, 29 Sep 2025 13:14:56 +1300 Subject: [PATCH 5/5] fix rename issue --- ssm/parameters.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/ssm/parameters.go b/ssm/parameters.go index 1d3581a..77295f7 100644 --- a/ssm/parameters.go +++ b/ssm/parameters.go @@ -237,13 +237,20 @@ func GetParameters(names, paths, plainNames, plainPaths []string, transformation localPaths = ExpandArgs(paths) localPlainPaths = ExpandArgs(plainPaths) } + allParameters, err := getAllParameters(localNames, localPaths, localPlainNames, localPlainPaths, strict, recursive) if err != nil { return parameters, err } + parameters = make(map[string]string) for _, parameter := range allParameters { - err = mergo.Merge(¶meters, ¶meter, mergo.WithOverride) + // Normalize keys to uppercase before merging to solve Viper case sensitivity issue + normalized := make(map[string]string, len(parameter)) + for k, v := range parameter { + normalized[strings.ToUpper(k)] = v + } + err = mergo.Merge(¶meters, &normalized, mergo.WithOverride) if err != nil { log.WithError(err).Fatal("Can't merge maps") } @@ -253,25 +260,17 @@ func GetParameters(names, paths, plainNames, plainPaths []string, transformation log.WithError(err).Fatal("Can't expand vars") } - // Normalize only the parameter keys to UPPERCASE to solve Viper case sensitivity issue - // This ensures AWS parameter names match the transformation rule keys from config - normalizedParameters := make(map[string]string) - for key, value := range parameters { - normalizedParameters[strings.ToUpper(key)] = value - } - parameters = normalizedParameters - - // Normalize transformation rule keys for rename/template/delete to UPPERCASE to match parameters + // Normalize transformation rule keys to uppercase to match parameter keys for _, transformation := range transformationsList { switch t := transformation.(type) { case *transformations.RenameTransformation: - normalizedRule := make(map[string]string) + normalizedRule := make(map[string]string, len(t.Rule)) for key, value := range t.Rule { normalizedRule[strings.ToUpper(key)] = value } t.Rule = normalizedRule case *transformations.TemplateTransformation: - normalizedRule := make(map[string]string) + normalizedRule := make(map[string]string, len(t.Rule)) for key, value := range t.Rule { normalizedRule[strings.ToUpper(key)] = value } @@ -293,3 +292,4 @@ func GetParameters(names, paths, plainNames, plainPaths []string, transformation } return } +