-
Notifications
You must be signed in to change notification settings - Fork 77
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
Fix #653: incorrectly strips quotes from string values that resemble YAML booleans #654
Conversation
…ues that resemble YAML booleans
Hi @ericzbeard, thanks so much for merging this fix! Do you have an ETA for the next release of Rain? We're looking forward to it so we can use Rain in our CI without needing complex workarounds 🙂 |
|
@ericzbeard I’ve looked deeper into this, and after analyzing how Why this PR's changes should be kept & released
Suggested Changelog Entry
|
Before fix (string to boolean conversion, no workaround): Param1: -> Param1:
Default: "ON" -> Default: ON # no workaround
Param2: -> Param2:
Default: "OFF" -> Default: OFF # no workaround
Param3: -> Param3:
Default: "Yes" -> Default: Yes # no workaround
Param4: -> Param4:
Default: "No" -> Default: No # no workaround
Param5: -> Param5:
Default: "True" -> Default: "True"
Param6: -> Param6:
Default: "False" -> Default: "False"
Param7: -> Param7:
Default: Maybe -> Default: Maybe
Param8: -> Param8:
Default: ON -> Default: ON
Param9: -> Param9:
Default: OFF -> Default: OFF
Param10: -> Param10:
Default: Yes -> Default: Yes
Param11: -> Param11:
Default: No -> Default: No
Param12: -> Param12:
Default: True -> Default: True
Param13: -> Param13:
Default: False -> Default: False After fix (boolean to string conversion, workaround: just use true/false for booleans, as required by YAML 1.2): Param1: -> Param1:
Default: "ON" -> Default: "ON"
Param2: -> Param2:
Default: "OFF" -> Default: "OFF"
Param3: -> Param3:
Default: "Yes" -> Default: "Yes"
Param4: -> Param4:
Default: "No" -> Default: "No"
Param5: -> Param5:
Default: "True" -> Default: "True"
Param6: -> Param6:
Default: "False" -> Default: "False"
Param7: -> Param7:
Default: Maybe -> Default: Maybe
Param8: -> Param8:
Default: ON -> Default: "ON" # replace with True
Param9: -> Param9:
Default: OFF -> Default: "OFF" # replace with False
Param10: -> Param10:
Default: Yes -> Default: "Yes" # replace with True
Param11: -> Param11:
Default: No -> Default: "No" # replace with False
Param12: -> Param12:
Default: True -> Default: True
Param13: -> Param13:
Default: False -> Default: False |
Thanks for the detailed write-up on this issue. I'm somewhat concerned about shipping something that's technically a breaking change in a minor version release. But I imagine that in most (all?) cases where this mattered, people had probably adopted the flag to change the node styles across the entire template. |
Can we put this new behavior behind a new node-style? |
Yeah sure, something like this? Index: cft/format/transform.go
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/cft/format/transform.go b/cft/format/transform.go
--- a/cft/format/transform.go (revision 471caf008e4562aa5f8b62e01a544f3f685db8cc)
+++ b/cft/format/transform.go (date 1741340107190)
@@ -119,14 +119,16 @@
if n.Kind == yaml.ScalarNode {
n.Style = yaml.DoubleQuotedStyle
}
- case "":
- // Default style for consistent formatting:
- // Force double quotes on ambiguous scalar strings.
+ case "strict-booleans":
+ // Enforce YAML 1.2 behavior: Only `true` and `false` are booleans, all others are strings
if n.Kind == yaml.ScalarNode && n.Tag == "!!str" && isAmbiguousScalar(n.Value) {
n.Style = yaml.DoubleQuotedStyle
} else {
n.Style = 0
}
+ case "":
+ // Default style for consistent formatting
+ n.Style = 0
default:
panic("invalid --node-style: " + NodeStyle)
}
Index: cft/format/format_test.go
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/cft/format/format_test.go b/cft/format/format_test.go
--- a/cft/format/format_test.go (revision 471caf008e4562aa5f8b62e01a544f3f685db8cc)
+++ b/cft/format/format_test.go (date 1741340931613)
@@ -801,75 +801,86 @@
}
}
-func TestAmbiguousScalarOn(t *testing.T) {
- input := `
-Resources:
- MyResource:
- Type: AWS::RDS::DBClusterParameterGroup
- Properties:
- Parameters:
- require_secure_transport: "ON"
-`
- // We expect the ambiguous value "ON" to remain quoted in the output.
- expected := `Resources:
- MyResource:
- Type: AWS::RDS::DBClusterParameterGroup
- Properties:
- Parameters:
- require_secure_transport: "ON"
-`
- template, err := parse.String(input)
- if err != nil {
- t.Fatal(err)
- }
+func TestAmbiguousScalars_StrictBooleans_On(t *testing.T) {
+ // Save the original style
+ originalStyle := format.NodeStyle
+ // Restore after test completes
+ defer func() {
+ format.NodeStyle = originalStyle
+ }()
- actual := format.String(template, format.Options{Unsorted: true})
- if d := cmp.Diff(strings.TrimSpace(expected), strings.TrimSpace(actual)); d != "" {
- t.Fatalf("Diff: %s", d)
- }
-}
+ // Override for this test only
+ format.NodeStyle = "strict-booleans"
-func TestAmbiguousScalarsInParameters(t *testing.T) {
input := `
-Parameters:
- Param1:
- Default: "ON"
- Param2:
- Default: "OFF"
- Param3:
- Default: "Yes"
- Param4:
- Default: "No"
- Param5:
- Default: "True"
- Param6:
- Default: "False"
- Param7:
- Default: "Maybe"
+Param1:
+ Default: "ON"
+Param2:
+ Default: "OFF"
+Param3:
+ Default: "Yes"
+Param4:
+ Default: "No"
+Param5:
+ Default: "True"
+Param6:
+ Default: "False"
+Param7:
+ Default: Maybe
+Param8:
+ Default: ON
+Param9:
+ Default: OFF
+Param10:
+ Default: Yes
+Param11:
+ Default: No
+Param12:
+ Default: True
+Param13:
+ Default: False
`
// The ambiguous values (Param1 through Param6) should be rendered with quotes,
// while a non-ambiguous value (Param7) may be unquoted.
- expected := `Parameters:
- Param1:
- Default: "ON"
+ expected := `
+Param1:
+ Default: "ON"
- Param2:
- Default: "OFF"
+Param2:
+ Default: "OFF"
- Param3:
- Default: "Yes"
+Param3:
+ Default: "Yes"
- Param4:
- Default: "No"
+Param4:
+ Default: "No"
- Param5:
- Default: "True"
+Param5:
+ Default: "True"
- Param6:
- Default: "False"
+Param6:
+ Default: "False"
- Param7:
- Default: Maybe
+Param7:
+ Default: Maybe
+
+Param8:
+ Default: "ON"
+
+Param9:
+ Default: "OFF"
+
+Param10:
+ Default: "Yes"
+
+Param11:
+ Default: "No"
+
+Param12:
+ Default: True
+
+Param13:
+ Default: False
`
template, err := parse.String(input)
if err != nil {
@@ -882,18 +893,76 @@
}
}
-func TestNonAmbiguousScalar(t *testing.T) {
+func TestAmbiguousScalars_StrictBooleans_Off(t *testing.T) {
input := `
-Resources:
- MyResource:
- Properties:
- example_value: "OnX"
+Param1:
+ Default: "ON"
+Param2:
+ Default: "OFF"
+Param3:
+ Default: "Yes"
+Param4:
+ Default: "No"
+Param5:
+ Default: "True"
+Param6:
+ Default: "False"
+Param7:
+ Default: Maybe
+Param8:
+ Default: ON
+Param9:
+ Default: OFF
+Param10:
+ Default: Yes
+Param11:
+ Default: No
+Param12:
+ Default: True
+Param13:
+ Default: False
`
- // Since "OnX" is not an ambiguous token, it can be rendered without quotes.
- expected := `Resources:
- MyResource:
- Properties:
- example_value: OnX
+ // The ambiguous values (Param1 through Param6) should be rendered with quotes,
+ // while a non-ambiguous value (Param7) may be unquoted.
+ expected := `
+Param1:
+ Default: ON
+
+Param2:
+ Default: OFF
+
+Param3:
+ Default: Yes
+
+Param4:
+ Default: No
+
+Param5:
+ Default: "True"
+
+Param6:
+ Default: "False"
+
+Param7:
+ Default: Maybe
+
+Param8:
+ Default: ON
+
+Param9:
+ Default: OFF
+
+Param10:
+ Default: Yes
+
+Param11:
+ Default: No
+
+Param12:
+ Default: True
+
+Param13:
+ Default: False
`
template, err := parse.String(input)
if err != nil { Let me know if I should create a PR with these changes. |
Related to #319 |
Issue #, if available:
#653
Description of changes:
Ensure ambiguous YAML scalars (
ON
,OFF
,YES
,NO
,TRUE
,FALSE
) remain quoted to prevent unintended type conversion in CloudFormation templates. Includes tests to verify correct handling inParameters
andProperties
.By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.