Skip to content

Commit 11bc9eb

Browse files
fix(deployment): quote ConfigMap values with %q, as the go agents already do (#79)
A rendered ConfigMap value is an arbitrary string — a JSON document, a comma-joined list, a sentence. This template wrapped it in hand-written quotes, so the first " inside a value closed the string early and the rest of it became YAML. The render then refused its own output: configmap.yaml: yaml: line 6: did not find expected key and deleted the tree it had just written, leaving nothing to read, which is why it took a template comparison rather than a log to find. service-go and service-go-grpc already render `{{ printf "%q" $value }}`; only this agent and service-nextjs did not, so the same defect is open there and is being fixed separately. The secret template is deliberately untouched: a Secret's `data` holds base64, which contains nothing that breaks naive quoting, and the go agents quote it the same way. The test executes the template directly rather than through the agent's deployment path, because the fault is the template's quoting and nothing above it — a test needing core's deployment wrapper to reach this line would not say where the fault is. It fails on the old template with the same "not parseable YAML" symptom seen in production, and the assertion is that the document parses AND each value survives byte for byte. Found rendering platform-obin's staging deployment for the Lane 3 Catalogue; the module that hit it is a python-fastapi service whose configuration carries a JSON value. Co-authored-by: Antoine Toussaint <312536060+antoinetoussaint-byte@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 83dc764 commit 11bc9eb

2 files changed

Lines changed: 57 additions & 1 deletion

File tree

‎configmap_quoting_test.go‎

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package main
2+
3+
import (
4+
"strings"
5+
"testing"
6+
"text/template"
7+
8+
"github.com/stretchr/testify/require"
9+
"gopkg.in/yaml.v3"
10+
)
11+
12+
// A ConfigMap value is an arbitrary string: a JSON document, a comma-joined
13+
// list, a sentence. This template used to wrap it in hand-written quotes, so
14+
// the first `"` inside a value closed the string early and the remainder became
15+
// YAML — which is how a render refused its own output with
16+
//
17+
// configmap.yaml: yaml: line 6: did not find expected key
18+
//
19+
// and then deleted the tree it had just written, leaving nothing to read. The
20+
// sibling go agents already rendered `printf "%q"`; only this one did not.
21+
//
22+
// The template is executed directly rather than through the agent's deployment
23+
// path, because the defect is in the template's quoting and nothing above it:
24+
// a test that needs core's deployment wrapper to reach this line would not say
25+
// where the fault is.
26+
func TestConfigMapQuotesValuesThatContainYAMLSyntax(t *testing.T) {
27+
hostile := map[string]string{
28+
"MODULE_PRINCIPALS": `{"documents":{"scopes":["read","write"]}}`,
29+
"COLON_AND_SPACE": "key: value",
30+
"TRAILING_BACKSLASH": `C:\path\`,
31+
"NEWLINE": "first\nsecond",
32+
"QUOTED_WORD": `say "hello"`,
33+
"HASH": "value # not a comment",
34+
"EMPTY": "",
35+
}
36+
raw, err := deploymentFS.ReadFile("templates/deployment/kustomize/overlays/environment/configmap.yaml.tmpl")
37+
require.NoError(t, err)
38+
parsed, err := template.New("configmap").Parse(string(raw))
39+
require.NoError(t, err)
40+
41+
var out strings.Builder
42+
require.NoError(t, parsed.Execute(&out, map[string]any{
43+
"Service": map[string]any{"Name": map[string]any{"DNSCase": "model"}},
44+
"Namespace": "platform-obin-model",
45+
"Deployment": map[string]any{"ConfigMap": hostile},
46+
}))
47+
48+
var document struct {
49+
Data map[string]string `yaml:"data"`
50+
}
51+
require.NoError(t, yaml.Unmarshal([]byte(out.String()), &document),
52+
"the rendered configmap is not parseable YAML:\n%s", out.String())
53+
for key, want := range hostile {
54+
require.Equal(t, want, document.Data[key], "value for %s did not survive rendering", key)
55+
}
56+
}

‎templates/deployment/kustomize/overlays/environment/configmap.yaml.tmpl‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ metadata:
55
namespace: "{{ .Namespace }}"
66
data:
77
{{- range $key, $value := .Deployment.ConfigMap }}
8-
{{$key}}: "{{$value}}"
8+
{{$key}}: {{ printf "%q" $value }}
99
{{- end }}

0 commit comments

Comments
 (0)