pull/31952/merge
Matheus Pimenta 3 days ago committed by GitHub
commit 60c446ef3c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -21,6 +21,7 @@ import (
"regexp"
"strconv"
"strings"
"unicode"
)
// SimpleHead defines what the structure of the head of a manifest file
@ -35,7 +36,16 @@ type SimpleHead struct {
var sep = regexp.MustCompile("(?:^|\\s*\n)---\\s*")
// SplitManifests takes a string of manifest and returns a map contains individual manifests
// SplitManifests takes a manifest string and returns a map containing individual manifests.
//
// **Note for Chart API v3**: This function (due to the regex above) has allowed _WRONG_
// Go templates to be defined inside charts across the years. The generated text from Go
// templates may contain `---apiVersion: v1`, and this function magically splits this back
// to `---\napiVersion: v1`. This has caused issues recently after Helm 4 introduced
// kio.ParseAll to inject annotations when post-renderers are used. In Chart API v3,
// we should kill this regex with fire (or change it) and expose charts doing the wrong
// thing Go template-wise. Helm should say a big _NO_ to charts doing the wrong thing,
// with or without post-renderers.
func SplitManifests(bigFile string) map[string]string {
// Basically, we're quickly splitting a stream of YAML documents into an
// array of YAML docs. The file name is just a place holder, but should be
@ -44,15 +54,15 @@ func SplitManifests(bigFile string) map[string]string {
tpl := "manifest-%d"
res := map[string]string{}
// Making sure that any extra whitespace in YAML stream doesn't interfere in splitting documents correctly.
bigFileTmp := strings.TrimSpace(bigFile)
bigFileTmp := strings.TrimLeftFunc(bigFile, unicode.IsSpace)
docs := sep.Split(bigFileTmp, -1)
var count int
for _, d := range docs {
if d == "" {
if strings.TrimSpace(d) == "" {
continue
}
d = strings.TrimSpace(d)
d = strings.TrimLeftFunc(d, unicode.IsSpace)
res[fmt.Sprintf(tpl, count)] = d
count = count + 1
}

@ -21,7 +21,15 @@ import (
"testing"
)
const mockManifestFile = `
func TestSplitManifests(t *testing.T) {
tests := []struct {
name string
input string
expected map[string]string
}{
{
name: "single doc with leading separator and whitespace",
input: `
---
apiVersion: v1
@ -35,9 +43,9 @@ spec:
- name: nemo-test
image: fake-image
cmd: fake-command
`
const expectedManifest = `apiVersion: v1
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: Pod
metadata:
name: finding-nemo,
@ -47,15 +55,463 @@ spec:
containers:
- name: nemo-test
image: fake-image
cmd: fake-command`
cmd: fake-command
`,
},
},
{
name: "empty input",
input: "",
expected: map[string]string{},
},
{
name: "whitespace only",
input: " \n\n \n",
expected: map[string]string{},
},
{
name: "whitespace-only doc after separator is skipped",
input: "---\napiVersion: v1\nkind: ConfigMap\nmetadata:\n name: cm1\n---\n \n",
expected: map[string]string{
"manifest-0": "apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: cm1",
},
},
{
name: "single doc no separator",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
`,
},
},
{
name: "two docs with proper separator",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: cm1
---
apiVersion: v1
kind: ConfigMap
metadata:
name: cm2
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: cm1`,
"manifest-1": `apiVersion: v1
kind: ConfigMap
metadata:
name: cm2
`,
},
},
func TestSplitManifest(t *testing.T) {
manifests := SplitManifests(mockManifestFile)
if len(manifests) != 1 {
t.Errorf("Expected 1 manifest, got %v", len(manifests))
// Block scalar chomping indicator tests using | (clip), |- (strip), and |+ (keep)
// inputs with 0, 1, and 2 trailing newlines after the block content.
// Note: the emitter may normalize the output chomping indicator when the
// trailing newline count makes another indicator equivalent for the result.
// | (clip) input — clips trailing newlines to exactly one, though with
// 0 trailing newlines the emitted output may normalize to |-.
{
name: "block scalar clip (|) with 0 trailing newlines",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |
hello`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |
hello`,
},
},
{
name: "block scalar clip (|) with 1 trailing newline",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |
hello
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |
hello
`,
},
},
{
name: "block scalar clip (|) with 2 trailing newlines",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |
hello
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |
hello
`,
},
},
// |- (strip)
{
name: "block scalar strip (|-) with 0 trailing newlines",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |-
hello`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |-
hello`,
},
},
{
name: "block scalar strip (|-) with 1 trailing newline",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |-
hello
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |-
hello
`,
},
},
{
name: "block scalar strip (|-) with 2 trailing newlines",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |-
hello
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |-
hello
`,
},
},
// |+ (keep)
{
name: "block scalar keep (|+) with 0 trailing newlines",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |+
hello`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |+
hello`,
},
},
{
name: "block scalar keep (|+) with 1 trailing newline",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |+
hello
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |+
hello
`,
},
},
{
name: "block scalar keep (|+) with 2 trailing newlines",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |+
hello
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |+
hello
`,
},
},
// Multi-doc with block scalars: the regex consumes \s*\n before ---,
// so trailing newlines from non-last docs are stripped.
{
name: "multi-doc block scalar clip (|) before separator",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |
hello
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |
hello`,
"manifest-1": `apiVersion: v1
kind: ConfigMap
metadata:
name: test2
`,
},
},
{
name: "multi-doc block scalar keep (|+) with 2 trailing newlines before separator",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |+
hello
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |+
hello`,
"manifest-1": `apiVersion: v1
kind: ConfigMap
metadata:
name: test2
`,
},
},
// **Note for Chart API v3**: The following tests exercise the lenient
// regex that splits `---apiVersion` back into separate documents.
// In Chart API v3, these inputs should return an _ERROR_ instead.
// See the comment on the SplitManifests function for more details.
{
name: "leading glued separator (---apiVersion)",
input: `
---apiVersion: v1
kind: ConfigMap
metadata:
name: cm1
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: cm1
`,
},
},
{
name: "mid-content glued separator (---apiVersion)",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: cm1
---apiVersion: v1
kind: ConfigMap
metadata:
name: cm2
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: cm1`,
"manifest-1": `apiVersion: v1
kind: ConfigMap
metadata:
name: cm2
`,
},
},
{
name: "multiple glued separators",
input: `
---apiVersion: v1
kind: ConfigMap
metadata:
name: cm1
---apiVersion: v1
kind: ConfigMap
metadata:
name: cm2
---apiVersion: v1
kind: ConfigMap
metadata:
name: cm3
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: cm1`,
"manifest-1": `apiVersion: v1
kind: ConfigMap
metadata:
name: cm2`,
"manifest-2": `apiVersion: v1
kind: ConfigMap
metadata:
name: cm3
`,
},
},
{
name: "mixed glued and proper separators",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: cm1
---
apiVersion: v1
kind: ConfigMap
metadata:
name: cm2
---apiVersion: v1
kind: ConfigMap
metadata:
name: cm3
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: cm1`,
"manifest-1": `apiVersion: v1
kind: ConfigMap
metadata:
name: cm2`,
"manifest-2": `apiVersion: v1
kind: ConfigMap
metadata:
name: cm3
`,
},
},
}
expected := map[string]string{"manifest-0": expectedManifest}
if !reflect.DeepEqual(manifests, expected) {
t.Errorf("Expected %v, got %v", expected, manifests)
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := SplitManifests(tt.input)
if !reflect.DeepEqual(result, tt.expected) {
t.Errorf("SplitManifests() =\n%v\nwant:\n%v", result, tt.expected)
}
})
}
}

@ -418,7 +418,8 @@ func TestAnnotateAndMerge(t *testing.T) {
{
name: "single file with single manifest",
files: map[string]string{
"templates/configmap.yaml": `apiVersion: v1
"templates/configmap.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test-cm
@ -438,13 +439,15 @@ data:
{
name: "multiple files with multiple manifests",
files: map[string]string{
"templates/configmap.yaml": `apiVersion: v1
"templates/configmap.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test-cm
data:
key: value`,
"templates/secret.yaml": `apiVersion: v1
"templates/secret.yaml": `
apiVersion: v1
kind: Secret
metadata:
name: test-secret
@ -473,7 +476,8 @@ data:
{
name: "file with multiple manifests",
files: map[string]string{
"templates/multi.yaml": `apiVersion: v1
"templates/multi.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test-cm1
@ -509,7 +513,8 @@ data:
{
name: "partials and empty files are removed",
files: map[string]string{
"templates/cm.yaml": `apiVersion: v1
"templates/cm.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test-cm1
@ -531,14 +536,16 @@ metadata:
{
name: "empty file",
files: map[string]string{
"templates/empty.yaml": "",
"templates/empty.yaml": `
`,
},
expected: ``,
},
{
name: "invalid yaml",
files: map[string]string{
"templates/invalid.yaml": `invalid: yaml: content:
"templates/invalid.yaml": `
invalid: yaml: content:
- malformed`,
},
expectedError: "parsing templates/invalid.yaml",
@ -546,7 +553,12 @@ metadata:
{
name: "leading doc separator glued to content by template whitespace trimming",
files: map[string]string{
"templates/service.yaml": "---apiVersion: v1\nkind: Service\nmetadata:\n name: test-svc\n",
"templates/service.yaml": `
---apiVersion: v1
kind: Service
metadata:
name: test-svc
`,
},
expected: `apiVersion: v1
kind: Service
@ -559,7 +571,13 @@ metadata:
{
name: "leading doc separator on its own line",
files: map[string]string{
"templates/service.yaml": "---\napiVersion: v1\nkind: Service\nmetadata:\n name: test-svc\n",
"templates/service.yaml": `
---
apiVersion: v1
kind: Service
metadata:
name: test-svc
`,
},
expected: `apiVersion: v1
kind: Service
@ -572,7 +590,14 @@ metadata:
{
name: "multiple leading doc separators",
files: map[string]string{
"templates/service.yaml": "---\n---\napiVersion: v1\nkind: Service\nmetadata:\n name: test-svc\n",
"templates/service.yaml": `
---
---
apiVersion: v1
kind: Service
metadata:
name: test-svc
`,
},
expected: `apiVersion: v1
kind: Service
@ -585,7 +610,16 @@ metadata:
{
name: "mid-content doc separator glued to content by template whitespace trimming",
files: map[string]string{
"templates/all.yaml": "apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: test-cm\n---apiVersion: v1\nkind: Service\nmetadata:\n name: test-svc\n",
"templates/all.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test-cm
---apiVersion: v1
kind: Service
metadata:
name: test-svc
`,
},
expected: `apiVersion: v1
kind: ConfigMap
@ -631,7 +665,7 @@ metadata:
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/configmap.yaml'
data:
ca.crt: |-
ca.crt: |
------BEGIN CERTIFICATE------
MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zAKBggqhkjOPQQDAzASMRAw
DgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYwMDAw
@ -667,7 +701,7 @@ metadata:
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/configmap.yaml'
data:
config: |-
config: |
# ---------------------------------------------------------------------------
[section]
key = value
@ -694,7 +728,7 @@ metadata:
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/dashboard.yaml'
data:
dashboard.json: |-
dashboard.json: |
{"options":{"---------":{"color":"#292929","text":"N/A"}}}
`,
},
@ -933,6 +967,605 @@ metadata:
name: cm-12
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/many.yaml'
`,
},
// Block scalar chomping indicator tests using | (clip), |- (strip), and |+ (keep)
// inputs with 0, 1, and 2 trailing newlines after the block content.
// Note: the emitter may normalize the output chomping indicator when the
// trailing newline count makes another indicator equivalent for the result.
// | (clip) input — clips trailing newlines to exactly one, though with
// 0 trailing newlines the emitted output may normalize to |-.
{
name: "block scalar clip (|) with 0 trailing newlines",
files: map[string]string{
"templates/cm.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |
hello`,
},
expected: `apiVersion: v1
kind: ConfigMap
metadata:
name: test
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
key: |-
hello
`,
},
{
name: "block scalar clip (|) with 1 trailing newline",
files: map[string]string{
"templates/cm.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |
hello
`,
},
expected: `apiVersion: v1
kind: ConfigMap
metadata:
name: test
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
key: |
hello
`,
},
{
name: "block scalar clip (|) with 2 trailing newlines",
files: map[string]string{
"templates/cm.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |
hello
`,
},
expected: `apiVersion: v1
kind: ConfigMap
metadata:
name: test
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
key: |
hello
`,
},
// |- (strip) — strips all trailing newlines
{
name: "block scalar strip (|-) with 0 trailing newlines",
files: map[string]string{
"templates/cm.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |-
hello`,
},
expected: `apiVersion: v1
kind: ConfigMap
metadata:
name: test
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
key: |-
hello
`,
},
{
name: "block scalar strip (|-) with 1 trailing newline",
files: map[string]string{
"templates/cm.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |-
hello
`,
},
expected: `apiVersion: v1
kind: ConfigMap
metadata:
name: test
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
key: |-
hello
`,
},
{
name: "block scalar strip (|-) with 2 trailing newlines",
files: map[string]string{
"templates/cm.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |-
hello
`,
},
expected: `apiVersion: v1
kind: ConfigMap
metadata:
name: test
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
key: |-
hello
`,
},
// |+ (keep) — preserves all trailing newlines
{
name: "block scalar keep (|+) with 0 trailing newlines",
files: map[string]string{
"templates/cm.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |+
hello`,
},
expected: `apiVersion: v1
kind: ConfigMap
metadata:
name: test
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
key: |-
hello
`,
},
{
name: "block scalar keep (|+) with 1 trailing newline",
files: map[string]string{
"templates/cm.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |+
hello
`,
},
expected: `apiVersion: v1
kind: ConfigMap
metadata:
name: test
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
key: |
hello
`,
},
{
name: "block scalar keep (|+) with 2 trailing newlines",
files: map[string]string{
"templates/cm.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |+
hello
`,
},
expected: `apiVersion: v1
kind: ConfigMap
metadata:
name: test
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
key: |+
hello
`,
},
// Multi-doc tests: block scalar doc is NOT the last document.
// SplitManifests' regex consumes \s*\n before ---, so trailing
// newlines from non-last docs are always stripped.
// | (clip) in multi-doc (first doc)
{
name: "multi-doc block scalar clip (|) with 0 trailing newlines",
files: map[string]string{
"templates/cm.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |
hello
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
data:
val: simple`,
},
expected: `apiVersion: v1
kind: ConfigMap
metadata:
name: test
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
key: |-
hello
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
val: simple
`,
},
{
name: "multi-doc block scalar clip (|) with 1 trailing newline",
files: map[string]string{
"templates/cm.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |
hello
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
data:
val: simple`,
},
expected: `apiVersion: v1
kind: ConfigMap
metadata:
name: test
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
key: |-
hello
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
val: simple
`,
},
{
name: "multi-doc block scalar clip (|) with 2 trailing newlines",
files: map[string]string{
"templates/cm.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |
hello
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
data:
val: simple`,
},
expected: `apiVersion: v1
kind: ConfigMap
metadata:
name: test
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
key: |-
hello
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
val: simple
`,
},
// |- (strip) in multi-doc (first doc)
{
name: "multi-doc block scalar strip (|-) with 0 trailing newlines",
files: map[string]string{
"templates/cm.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |-
hello
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
data:
val: simple`,
},
expected: `apiVersion: v1
kind: ConfigMap
metadata:
name: test
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
key: |-
hello
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
val: simple
`,
},
{
name: "multi-doc block scalar strip (|-) with 1 trailing newline",
files: map[string]string{
"templates/cm.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |-
hello
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
data:
val: simple`,
},
expected: `apiVersion: v1
kind: ConfigMap
metadata:
name: test
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
key: |-
hello
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
val: simple
`,
},
{
name: "multi-doc block scalar strip (|-) with 2 trailing newlines",
files: map[string]string{
"templates/cm.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |-
hello
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
data:
val: simple`,
},
expected: `apiVersion: v1
kind: ConfigMap
metadata:
name: test
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
key: |-
hello
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
val: simple
`,
},
// |+ (keep) in multi-doc (first doc)
{
name: "multi-doc block scalar keep (|+) with 0 trailing newlines",
files: map[string]string{
"templates/cm.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |+
hello
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
data:
val: simple`,
},
expected: `apiVersion: v1
kind: ConfigMap
metadata:
name: test
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
key: |-
hello
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
val: simple
`,
},
{
name: "multi-doc block scalar keep (|+) with 1 trailing newline",
files: map[string]string{
"templates/cm.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |+
hello
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
data:
val: simple`,
},
expected: `apiVersion: v1
kind: ConfigMap
metadata:
name: test
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
key: |-
hello
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
val: simple
`,
},
{
name: "multi-doc block scalar keep (|+) with 2 trailing newlines",
files: map[string]string{
"templates/cm.yaml": `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |+
hello
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
data:
val: simple`,
},
expected: `apiVersion: v1
kind: ConfigMap
metadata:
name: test
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
key: |-
hello
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
annotations:
postrenderer.helm.sh/postrender-filename: 'templates/cm.yaml'
data:
val: simple
`,
},
}
@ -1201,12 +1834,15 @@ func TestRenderResources_PostRenderer_Success(t *testing.T) {
expectedBuf := `---
# Source: yellow/templates/foodpie
foodpie: world
---
# Source: yellow/templates/with-partials
yellow: Earth
---
# Source: yellow/templates/yellow
yellow: world
`
expectedHook := `kind: ConfigMap
metadata:
@ -1214,7 +1850,8 @@ metadata:
annotations:
"helm.sh/hook": post-install,pre-delete,post-upgrade
data:
name: value`
name: value
`
assert.Equal(t, expectedBuf, buf.String())
assert.Len(t, hooks, 1)
@ -1319,14 +1956,17 @@ func TestRenderResources_PostRenderer_Integration(t *testing.T) {
# Source: hello/templates/goodbye
goodbye: world
color: blue
---
# Source: hello/templates/hello
hello: world
color: blue
---
# Source: hello/templates/with-partials
hello: Earth
color: blue
`
assert.Contains(t, output, "color: blue")
assert.Equal(t, 3, strings.Count(output, "color: blue"))

@ -23,3 +23,4 @@ subjects:
- kind: ServiceAccount
name: schedule-agents
namespace: spaced

@ -15,6 +15,7 @@ metadata:
name: test-secret
stringData:
foo: bar
---
# Source: chart-with-secret/templates/configmap.yaml
apiVersion: v1
@ -24,3 +25,4 @@ metadata:
data:
foo: bar

@ -11,6 +11,7 @@ hash:
key4: 4
key5: 5
key6: 6
---
# Source: issue-9027/templates/values.yaml
global:

@ -155,6 +155,7 @@ spec:
policyTypes:
- Egress
- Ingress
---
# Source: object-order/templates/01-a.yml
# 4 (Deployment should come after all NetworkPolicy manifests, since 'helm template' outputs in install order)

@ -4,6 +4,7 @@ apiVersion: v1
kind: ServiceAccount
metadata:
name: subchart-sa
---
# Source: subchart/templates/subdir/role.yaml
apiVersion: rbac.authorization.k8s.io/v1
@ -14,6 +15,7 @@ rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
---
# Source: subchart/templates/subdir/rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
@ -28,6 +30,7 @@ subjects:
- kind: ServiceAccount
name: subchart-sa
namespace: default
---
# Source: subchart/charts/subcharta/templates/service.yaml
apiVersion: v1
@ -45,6 +48,7 @@ spec:
name: apache
selector:
app.kubernetes.io/name: subcharta
---
# Source: subchart/charts/subchartb/templates/service.yaml
apiVersion: v1
@ -62,6 +66,7 @@ spec:
name: nginx
selector:
app.kubernetes.io/name: subchartb
---
# Source: subchart/templates/service.yaml
apiVersion: v1
@ -93,6 +98,7 @@ metadata:
"helm.sh/hook": test
data:
message: Hello World
---
# Source: subchart/templates/tests/test-nothing.yaml
apiVersion: v1
@ -112,3 +118,4 @@ spec:
- echo
- "$message"
restartPolicy: Never

@ -4,6 +4,7 @@ apiVersion: v1
kind: ServiceAccount
metadata:
name: subchart-sa
---
# Source: subchart/templates/subdir/role.yaml
apiVersion: rbac.authorization.k8s.io/v1
@ -14,6 +15,7 @@ rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
---
# Source: subchart/templates/subdir/rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
@ -28,6 +30,7 @@ subjects:
- kind: ServiceAccount
name: subchart-sa
namespace: default
---
# Source: subchart/charts/subcharta/templates/service.yaml
apiVersion: v1
@ -45,6 +48,7 @@ spec:
name: apache
selector:
app.kubernetes.io/name: subcharta
---
# Source: subchart/charts/subchartb/templates/service.yaml
apiVersion: v1
@ -62,6 +66,7 @@ spec:
name: nginx
selector:
app.kubernetes.io/name: subchartb
---
# Source: subchart/templates/service.yaml
apiVersion: v1
@ -93,6 +98,7 @@ metadata:
"helm.sh/hook": test
data:
message: Hello World
---
# Source: subchart/templates/tests/test-nothing.yaml
apiVersion: v1
@ -112,3 +118,4 @@ spec:
- echo
- "$message"
restartPolicy: Never

@ -4,6 +4,7 @@ apiVersion: v1
kind: ServiceAccount
metadata:
name: subchart-sa
---
# Source: subchart/templates/subdir/role.yaml
apiVersion: rbac.authorization.k8s.io/v1
@ -14,6 +15,7 @@ rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
---
# Source: subchart/templates/subdir/rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
@ -28,6 +30,7 @@ subjects:
- kind: ServiceAccount
name: subchart-sa
namespace: default
---
# Source: subchart/charts/subcharta/templates/service.yaml
apiVersion: v1
@ -45,6 +48,7 @@ spec:
name: apache
selector:
app.kubernetes.io/name: subcharta
---
# Source: subchart/charts/subchartb/templates/service.yaml
apiVersion: v1
@ -62,6 +66,7 @@ spec:
name: nginx
selector:
app.kubernetes.io/name: subchartb
---
# Source: subchart/templates/service.yaml
apiVersion: v1

@ -4,6 +4,7 @@ apiVersion: v1
kind: ServiceAccount
metadata:
name: subchart-sa
---
# Source: subchart/templates/subdir/configmap.yaml
apiVersion: v1
@ -22,6 +23,7 @@ rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
---
# Source: subchart/templates/subdir/rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
@ -36,6 +38,7 @@ subjects:
- kind: ServiceAccount
name: subchart-sa
namespace: default
---
# Source: subchart/charts/subcharta/templates/service.yaml
apiVersion: v1
@ -53,6 +56,7 @@ spec:
name: apache
selector:
app.kubernetes.io/name: subcharta
---
# Source: subchart/charts/subchartb/templates/service.yaml
apiVersion: v1
@ -70,6 +74,7 @@ spec:
name: nginx
selector:
app.kubernetes.io/name: subchartb
---
# Source: subchart/templates/service.yaml
apiVersion: v1
@ -101,6 +106,7 @@ metadata:
"helm.sh/hook": test
data:
message: Hello World
---
# Source: subchart/templates/tests/test-nothing.yaml
apiVersion: v1
@ -120,3 +126,4 @@ spec:
- echo
- "$message"
restartPolicy: Never

@ -4,6 +4,7 @@ apiVersion: v1
kind: ServiceAccount
metadata:
name: subchart-sa
---
# Source: subchart/templates/subdir/configmap.yaml
apiVersion: v1
@ -22,6 +23,7 @@ rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
---
# Source: subchart/templates/subdir/rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
@ -36,6 +38,7 @@ subjects:
- kind: ServiceAccount
name: subchart-sa
namespace: default
---
# Source: subchart/charts/subcharta/templates/service.yaml
apiVersion: v1
@ -53,6 +56,7 @@ spec:
name: apache
selector:
app.kubernetes.io/name: subcharta
---
# Source: subchart/charts/subchartb/templates/service.yaml
apiVersion: v1
@ -70,6 +74,7 @@ spec:
name: nginx
selector:
app.kubernetes.io/name: subchartb
---
# Source: subchart/templates/service.yaml
apiVersion: v1
@ -101,6 +106,7 @@ metadata:
"helm.sh/hook": test
data:
message: Hello World
---
# Source: subchart/templates/tests/test-nothing.yaml
apiVersion: v1
@ -120,3 +126,4 @@ spec:
- echo
- "$message"
restartPolicy: Never

@ -4,6 +4,7 @@ apiVersion: v1
kind: ServiceAccount
metadata:
name: subchart-sa
---
# Source: subchart/templates/subdir/configmap.yaml
apiVersion: v1
@ -22,6 +23,7 @@ rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
---
# Source: subchart/templates/subdir/rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
@ -36,6 +38,7 @@ subjects:
- kind: ServiceAccount
name: subchart-sa
namespace: default
---
# Source: subchart/charts/subcharta/templates/service.yaml
apiVersion: v1
@ -53,6 +56,7 @@ spec:
name: apache
selector:
app.kubernetes.io/name: subcharta
---
# Source: subchart/charts/subchartb/templates/service.yaml
apiVersion: v1
@ -70,6 +74,7 @@ spec:
name: nginx
selector:
app.kubernetes.io/name: subchartb
---
# Source: subchart/templates/service.yaml
apiVersion: v1
@ -101,6 +106,7 @@ metadata:
"helm.sh/hook": test
data:
message: Hello World
---
# Source: subchart/templates/tests/test-nothing.yaml
apiVersion: v1
@ -120,3 +126,4 @@ spec:
- echo
- "$message"
restartPolicy: Never

@ -4,6 +4,7 @@ apiVersion: v1
kind: ServiceAccount
metadata:
name: subchart-sa
---
# Source: subchart/templates/subdir/role.yaml
apiVersion: rbac.authorization.k8s.io/v1
@ -14,6 +15,7 @@ rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
---
# Source: subchart/templates/subdir/rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
@ -28,6 +30,7 @@ subjects:
- kind: ServiceAccount
name: subchart-sa
namespace: default
---
# Source: subchart/charts/subcharta/templates/service.yaml
apiVersion: v1
@ -45,6 +48,7 @@ spec:
name: apache
selector:
app.kubernetes.io/name: subcharta
---
# Source: subchart/charts/subchartb/templates/service.yaml
apiVersion: v1
@ -62,6 +66,7 @@ spec:
name: nginx
selector:
app.kubernetes.io/name: subchartb
---
# Source: subchart/templates/service.yaml
apiVersion: v1
@ -93,6 +98,7 @@ metadata:
"helm.sh/hook": test
data:
message: Hello World
---
# Source: subchart/templates/tests/test-nothing.yaml
apiVersion: v1
@ -112,3 +118,4 @@ spec:
- echo
- "$message"
restartPolicy: Never

@ -4,6 +4,7 @@ apiVersion: v1
kind: ServiceAccount
metadata:
name: subchart-sa
---
# Source: subchart/templates/subdir/role.yaml
apiVersion: rbac.authorization.k8s.io/v1
@ -14,6 +15,7 @@ rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
---
# Source: subchart/templates/subdir/rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
@ -28,6 +30,7 @@ subjects:
- kind: ServiceAccount
name: subchart-sa
namespace: default
---
# Source: subchart/charts/subcharta/templates/service.yaml
apiVersion: v1
@ -45,6 +48,7 @@ spec:
name: apache
selector:
app.kubernetes.io/name: subcharta
---
# Source: subchart/charts/subchartb/templates/service.yaml
apiVersion: v1
@ -62,6 +66,7 @@ spec:
name: nginx
selector:
app.kubernetes.io/name: subchartb
---
# Source: subchart/templates/service.yaml
apiVersion: v1
@ -95,6 +100,7 @@ metadata:
"helm.sh/hook": test
data:
message: Hello World
---
# Source: subchart/templates/tests/test-nothing.yaml
apiVersion: v1
@ -114,3 +120,4 @@ spec:
- echo
- "$message"
restartPolicy: Never

@ -21,6 +21,7 @@ apiVersion: v1
kind: ServiceAccount
metadata:
name: subchart-sa
---
# Source: subchart/templates/subdir/role.yaml
apiVersion: rbac.authorization.k8s.io/v1
@ -31,6 +32,7 @@ rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
---
# Source: subchart/templates/subdir/rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
@ -45,6 +47,7 @@ subjects:
- kind: ServiceAccount
name: subchart-sa
namespace: default
---
# Source: subchart/charts/subcharta/templates/service.yaml
apiVersion: v1
@ -62,6 +65,7 @@ spec:
name: apache
selector:
app.kubernetes.io/name: subcharta
---
# Source: subchart/charts/subchartb/templates/service.yaml
apiVersion: v1
@ -79,6 +83,7 @@ spec:
name: nginx
selector:
app.kubernetes.io/name: subchartb
---
# Source: subchart/templates/service.yaml
apiVersion: v1
@ -110,6 +115,7 @@ metadata:
"helm.sh/hook": test
data:
message: Hello World
---
# Source: subchart/templates/tests/test-nothing.yaml
apiVersion: v1
@ -129,3 +135,4 @@ spec:
- echo
- "$message"
restartPolicy: Never

@ -4,6 +4,7 @@ apiVersion: v1
kind: ServiceAccount
metadata:
name: subchart-sa
---
# Source: subchart/templates/subdir/role.yaml
apiVersion: rbac.authorization.k8s.io/v1
@ -14,6 +15,7 @@ rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
---
# Source: subchart/templates/subdir/rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
@ -28,6 +30,7 @@ subjects:
- kind: ServiceAccount
name: subchart-sa
namespace: default
---
# Source: subchart/charts/subcharta/templates/service.yaml
apiVersion: v1
@ -45,6 +48,7 @@ spec:
name: apache
selector:
app.kubernetes.io/name: subcharta
---
# Source: subchart/charts/subchartb/templates/service.yaml
apiVersion: v1
@ -62,6 +66,7 @@ spec:
name: nginx
selector:
app.kubernetes.io/name: subchartb
---
# Source: subchart/templates/service.yaml
apiVersion: v1
@ -93,6 +98,7 @@ metadata:
"helm.sh/hook": test
data:
message: Hello World
---
# Source: subchart/templates/tests/test-nothing.yaml
apiVersion: v1
@ -112,3 +118,4 @@ spec:
- echo
- "$message"
restartPolicy: Never

@ -4,6 +4,7 @@ apiVersion: v1
kind: ServiceAccount
metadata:
name: subchart-sa
---
# Source: subchart/templates/subdir/role.yaml
apiVersion: rbac.authorization.k8s.io/v1
@ -14,6 +15,7 @@ rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
---
# Source: subchart/templates/subdir/rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
@ -28,6 +30,7 @@ subjects:
- kind: ServiceAccount
name: subchart-sa
namespace: default
---
# Source: subchart/charts/subcharta/templates/service.yaml
apiVersion: v1
@ -45,6 +48,7 @@ spec:
name: apache
selector:
app.kubernetes.io/name: subcharta
---
# Source: subchart/charts/subchartb/templates/service.yaml
apiVersion: v1
@ -62,6 +66,7 @@ spec:
name: nginx
selector:
app.kubernetes.io/name: subchartb
---
# Source: subchart/templates/service.yaml
apiVersion: v1
@ -93,6 +98,7 @@ metadata:
"helm.sh/hook": test
data:
message: Hello World
---
# Source: subchart/templates/tests/test-nothing.yaml
apiVersion: v1
@ -112,3 +118,4 @@ spec:
- echo
- "$message"
restartPolicy: Never

@ -21,6 +21,7 @@ import (
"regexp"
"strconv"
"strings"
"unicode"
)
// SimpleHead defines what the structure of the head of a manifest file
@ -35,7 +36,7 @@ type SimpleHead struct {
var sep = regexp.MustCompile("(?:^|\\s*\n)---\\s*")
// SplitManifests takes a string of manifest and returns a map contains individual manifests
// SplitManifests takes a manifest string and returns a map containing individual manifests.
//
// **Note for Chart API v3**: This function (due to the regex above) has allowed _WRONG_
// Go templates to be defined inside charts across the years. The generated text from Go
@ -53,15 +54,15 @@ func SplitManifests(bigFile string) map[string]string {
tpl := "manifest-%d"
res := map[string]string{}
// Making sure that any extra whitespace in YAML stream doesn't interfere in splitting documents correctly.
bigFileTmp := strings.TrimSpace(bigFile)
bigFileTmp := strings.TrimLeftFunc(bigFile, unicode.IsSpace)
docs := sep.Split(bigFileTmp, -1)
var count int
for _, d := range docs {
if d == "" {
if strings.TrimSpace(d) == "" {
continue
}
d = strings.TrimSpace(d)
d = strings.TrimLeftFunc(d, unicode.IsSpace)
res[fmt.Sprintf(tpl, count)] = d
count = count + 1
}

@ -21,7 +21,15 @@ import (
"testing"
)
const mockManifestFile = `
func TestSplitManifests(t *testing.T) {
tests := []struct {
name string
input string
expected map[string]string
}{
{
name: "single doc with leading separator and whitespace",
input: `
---
apiVersion: v1
@ -35,9 +43,9 @@ spec:
- name: nemo-test
image: fake-image
cmd: fake-command
`
const expectedManifest = `apiVersion: v1
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: Pod
metadata:
name: finding-nemo,
@ -47,15 +55,463 @@ spec:
containers:
- name: nemo-test
image: fake-image
cmd: fake-command`
cmd: fake-command
`,
},
},
{
name: "empty input",
input: "",
expected: map[string]string{},
},
{
name: "whitespace only",
input: " \n\n \n",
expected: map[string]string{},
},
{
name: "whitespace-only doc after separator is skipped",
input: "---\napiVersion: v1\nkind: ConfigMap\nmetadata:\n name: cm1\n---\n \n",
expected: map[string]string{
"manifest-0": "apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: cm1",
},
},
{
name: "single doc no separator",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
`,
},
},
{
name: "two docs with proper separator",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: cm1
---
apiVersion: v1
kind: ConfigMap
metadata:
name: cm2
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: cm1`,
"manifest-1": `apiVersion: v1
kind: ConfigMap
metadata:
name: cm2
`,
},
},
func TestSplitManifest(t *testing.T) {
manifests := SplitManifests(mockManifestFile)
if len(manifests) != 1 {
t.Errorf("Expected 1 manifest, got %v", len(manifests))
// Block scalar chomping indicator tests using | (clip), |- (strip), and |+ (keep)
// inputs with 0, 1, and 2 trailing newlines after the block content.
// Note: the emitter may normalize the output chomping indicator when the
// trailing newline count makes another indicator equivalent for the result.
// | (clip) input — clips trailing newlines to exactly one, though with
// 0 trailing newlines the emitted output may normalize to |-.
{
name: "block scalar clip (|) with 0 trailing newlines",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |
hello`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |
hello`,
},
},
{
name: "block scalar clip (|) with 1 trailing newline",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |
hello
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |
hello
`,
},
},
{
name: "block scalar clip (|) with 2 trailing newlines",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |
hello
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |
hello
`,
},
},
// |- (strip)
{
name: "block scalar strip (|-) with 0 trailing newlines",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |-
hello`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |-
hello`,
},
},
{
name: "block scalar strip (|-) with 1 trailing newline",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |-
hello
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |-
hello
`,
},
},
{
name: "block scalar strip (|-) with 2 trailing newlines",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |-
hello
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |-
hello
`,
},
},
// |+ (keep)
{
name: "block scalar keep (|+) with 0 trailing newlines",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |+
hello`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |+
hello`,
},
},
{
name: "block scalar keep (|+) with 1 trailing newline",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |+
hello
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |+
hello
`,
},
},
{
name: "block scalar keep (|+) with 2 trailing newlines",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |+
hello
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |+
hello
`,
},
},
// Multi-doc with block scalars: the regex consumes \s*\n before ---,
// so trailing newlines from non-last docs are stripped.
{
name: "multi-doc block scalar clip (|) before separator",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |
hello
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |
hello`,
"manifest-1": `apiVersion: v1
kind: ConfigMap
metadata:
name: test2
`,
},
},
{
name: "multi-doc block scalar keep (|+) with 2 trailing newlines before separator",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |+
hello
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
key: |+
hello`,
"manifest-1": `apiVersion: v1
kind: ConfigMap
metadata:
name: test2
`,
},
},
// **Note for Chart API v3**: The following tests exercise the lenient
// regex that splits `---apiVersion` back into separate documents.
// In Chart API v3, these inputs should return an _ERROR_ instead.
// See the comment on the SplitManifests function for more details.
{
name: "leading glued separator (---apiVersion)",
input: `
---apiVersion: v1
kind: ConfigMap
metadata:
name: cm1
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: cm1
`,
},
},
{
name: "mid-content glued separator (---apiVersion)",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: cm1
---apiVersion: v1
kind: ConfigMap
metadata:
name: cm2
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: cm1`,
"manifest-1": `apiVersion: v1
kind: ConfigMap
metadata:
name: cm2
`,
},
},
{
name: "multiple glued separators",
input: `
---apiVersion: v1
kind: ConfigMap
metadata:
name: cm1
---apiVersion: v1
kind: ConfigMap
metadata:
name: cm2
---apiVersion: v1
kind: ConfigMap
metadata:
name: cm3
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: cm1`,
"manifest-1": `apiVersion: v1
kind: ConfigMap
metadata:
name: cm2`,
"manifest-2": `apiVersion: v1
kind: ConfigMap
metadata:
name: cm3
`,
},
},
{
name: "mixed glued and proper separators",
input: `
apiVersion: v1
kind: ConfigMap
metadata:
name: cm1
---
apiVersion: v1
kind: ConfigMap
metadata:
name: cm2
---apiVersion: v1
kind: ConfigMap
metadata:
name: cm3
`,
expected: map[string]string{
"manifest-0": `apiVersion: v1
kind: ConfigMap
metadata:
name: cm1`,
"manifest-1": `apiVersion: v1
kind: ConfigMap
metadata:
name: cm2`,
"manifest-2": `apiVersion: v1
kind: ConfigMap
metadata:
name: cm3
`,
},
},
}
expected := map[string]string{"manifest-0": expectedManifest}
if !reflect.DeepEqual(manifests, expected) {
t.Errorf("Expected %v, got %v", expected, manifests)
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := SplitManifests(tt.input)
if !reflect.DeepEqual(result, tt.expected) {
t.Errorf("SplitManifests() =\n%v\nwant:\n%v", result, tt.expected)
}
})
}
}

Loading…
Cancel
Save