Skip to content

Commit 471caf0

Browse files
authored
Merge pull request #654 from leinardi/fix-issue-653
Fix #653: incorrectly strips quotes from string values that resemble YAML booleans
2 parents 8e33538 + 4d348fa commit 471caf0

File tree

2 files changed

+121
-2
lines changed

2 files changed

+121
-2
lines changed

cft/format/format_test.go

+105
Original file line numberDiff line numberDiff line change
@@ -800,3 +800,108 @@ Outputs {
800800
t.Fatalf("Got:\n[%s]\nExpected:\n[%s]\n", output, expected)
801801
}
802802
}
803+
804+
func TestAmbiguousScalarOn(t *testing.T) {
805+
input := `
806+
Resources:
807+
MyResource:
808+
Type: AWS::RDS::DBClusterParameterGroup
809+
Properties:
810+
Parameters:
811+
require_secure_transport: "ON"
812+
`
813+
// We expect the ambiguous value "ON" to remain quoted in the output.
814+
expected := `Resources:
815+
MyResource:
816+
Type: AWS::RDS::DBClusterParameterGroup
817+
Properties:
818+
Parameters:
819+
require_secure_transport: "ON"
820+
`
821+
template, err := parse.String(input)
822+
if err != nil {
823+
t.Fatal(err)
824+
}
825+
826+
actual := format.String(template, format.Options{Unsorted: true})
827+
if d := cmp.Diff(strings.TrimSpace(expected), strings.TrimSpace(actual)); d != "" {
828+
t.Fatalf("Diff: %s", d)
829+
}
830+
}
831+
832+
func TestAmbiguousScalarsInParameters(t *testing.T) {
833+
input := `
834+
Parameters:
835+
Param1:
836+
Default: "ON"
837+
Param2:
838+
Default: "OFF"
839+
Param3:
840+
Default: "Yes"
841+
Param4:
842+
Default: "No"
843+
Param5:
844+
Default: "True"
845+
Param6:
846+
Default: "False"
847+
Param7:
848+
Default: "Maybe"
849+
`
850+
// The ambiguous values (Param1 through Param6) should be rendered with quotes,
851+
// while a non-ambiguous value (Param7) may be unquoted.
852+
expected := `Parameters:
853+
Param1:
854+
Default: "ON"
855+
856+
Param2:
857+
Default: "OFF"
858+
859+
Param3:
860+
Default: "Yes"
861+
862+
Param4:
863+
Default: "No"
864+
865+
Param5:
866+
Default: "True"
867+
868+
Param6:
869+
Default: "False"
870+
871+
Param7:
872+
Default: Maybe
873+
`
874+
template, err := parse.String(input)
875+
if err != nil {
876+
t.Fatal(err)
877+
}
878+
879+
actual := format.String(template, format.Options{Unsorted: true})
880+
if d := cmp.Diff(strings.TrimSpace(expected), strings.TrimSpace(actual)); d != "" {
881+
t.Fatalf("Diff: %s", d)
882+
}
883+
}
884+
885+
func TestNonAmbiguousScalar(t *testing.T) {
886+
input := `
887+
Resources:
888+
MyResource:
889+
Properties:
890+
example_value: "OnX"
891+
`
892+
// Since "OnX" is not an ambiguous token, it can be rendered without quotes.
893+
expected := `Resources:
894+
MyResource:
895+
Properties:
896+
example_value: OnX
897+
`
898+
template, err := parse.String(input)
899+
if err != nil {
900+
t.Fatal(err)
901+
}
902+
903+
actual := format.String(template, format.Options{Unsorted: true})
904+
if d := cmp.Diff(strings.TrimSpace(expected), strings.TrimSpace(actual)); d != "" {
905+
t.Fatalf("Diff: %s", d)
906+
}
907+
}

cft/format/transform.go

+16-2
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,25 @@ func formatNode(n *yaml.Node) *yaml.Node {
120120
n.Style = yaml.DoubleQuotedStyle
121121
}
122122
case "":
123-
// Default style for consistent formatting
124-
n.Style = 0
123+
// Default style for consistent formatting:
124+
// Force double quotes on ambiguous scalar strings.
125+
if n.Kind == yaml.ScalarNode && n.Tag == "!!str" && isAmbiguousScalar(n.Value) {
126+
n.Style = yaml.DoubleQuotedStyle
127+
} else {
128+
n.Style = 0
129+
}
125130
default:
126131
panic("invalid --node-style: " + NodeStyle)
127132
}
128133

129134
return n
130135
}
136+
137+
func isAmbiguousScalar(val string) bool {
138+
switch strings.ToLower(val) {
139+
case "y", "yes", "n", "no", "true", "false", "on", "off":
140+
return true
141+
default:
142+
return false
143+
}
144+
}

0 commit comments

Comments
 (0)