Skip to content

Commit cd307a2

Browse files
authored
Merge pull request #97 from tmccombs/template-escapes
fix: Properly escape things that should be escaped
2 parents 8f18435 + e897a28 commit cd307a2

File tree

2 files changed

+34
-2
lines changed

2 files changed

+34
-2
lines changed

convert/convert.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,14 +219,23 @@ func (c *converter) convertUnary(v *hclsyntax.UnaryOpExpr) (interface{}, error)
219219
return ctyjson.SimpleJSONValue{Value: val}, nil
220220
}
221221

222+
// Escape sequences that have special meaning in hcl json
223+
// such as ${ that come from literals, that shouldn't have
224+
// real interpolation
225+
func escapeLiteral(lit string) string {
226+
lit = strings.Replace(lit, "${", "$${", -1)
227+
lit = strings.Replace(lit, "%{", "%%{", -1)
228+
return lit
229+
}
230+
222231
func (c *converter) convertTemplate(t *hclsyntax.TemplateExpr) (string, error) {
223232
if t.IsStringLiteral() {
224233
// safe because the value is just the string
225234
v, err := t.Value(nil)
226235
if err != nil {
227236
return "", err
228237
}
229-
return v.AsString(), nil
238+
return escapeLiteral(v.AsString()), nil
230239
}
231240
var builder strings.Builder
232241
for _, part := range t.Parts {
@@ -251,7 +260,7 @@ func (c *converter) convertStringPart(expr hclsyntax.Expression) (string, error)
251260
if err != nil {
252261
return "", err
253262
}
254-
return s.AsString(), nil
263+
return escapeLiteral(s.AsString()), nil
255264
case *hclsyntax.TemplateExpr:
256265
return c.convertTemplate(v)
257266
case *hclsyntax.TemplateWrapExpr:

convert/convert_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,29 @@ func TestBlocksWithAndWithoutLabels(t *testing.T) {
305305
}
306306
}
307307

308+
// https://github.com/tmccombs/hcl2json/issues/96
309+
func TestTemplateEscapes(t *testing.T) {
310+
input := `
311+
v = "$${one}"
312+
x = "${var.y} $${oh}"
313+
y = "%{ if true }%%{hi}%{ endif }"
314+
z = "%%{oh"
315+
`
316+
317+
expected := `{
318+
"v": "$${one}",
319+
"x": "${var.y} $${oh}",
320+
"y": "%{if true}%%{hi}%{endif}",
321+
"z": "%%{oh"
322+
}`
323+
324+
converted, err := Bytes([]byte(input), "", Options{})
325+
if err != nil {
326+
t.Fatal("Failed to parse: ", err)
327+
}
328+
compareTest(t, converted, expected)
329+
}
330+
308331
func compareTest(t *testing.T, input []byte, expected string) {
309332
var indented bytes.Buffer
310333
if err := json.Indent(&indented, input, "", "\t"); err != nil {

0 commit comments

Comments
 (0)