mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-11 17:12:51 +00:00
610 lines
12 KiB
Go
610 lines
12 KiB
Go
// Copyright 2020 The Kubernetes Authors.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package wrappy
|
|
|
|
import (
|
|
"fmt"
|
|
"path/filepath"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"sigs.k8s.io/kustomize/api/filesys"
|
|
"sigs.k8s.io/kustomize/api/kv"
|
|
"sigs.k8s.io/kustomize/api/loader"
|
|
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
|
"sigs.k8s.io/kustomize/api/types"
|
|
)
|
|
|
|
func TestMakeConfigMap(t *testing.T) {
|
|
factory := &WNodeFactory{}
|
|
type expected struct {
|
|
out string
|
|
errMsg string
|
|
}
|
|
|
|
testCases := map[string]struct {
|
|
args types.ConfigMapArgs
|
|
exp expected
|
|
}{
|
|
"construct config map from env": {
|
|
args: types.ConfigMapArgs{
|
|
GeneratorArgs: types.GeneratorArgs{
|
|
Name: "envConfigMap",
|
|
KvPairSources: types.KvPairSources{
|
|
EnvSources: []string{
|
|
filepath.Join("configmap", "app.env"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
exp: expected{
|
|
out: `apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: envConfigMap
|
|
data:
|
|
DB_USERNAME: admin
|
|
DB_PASSWORD: qwerty
|
|
`,
|
|
},
|
|
},
|
|
"construct config map from text file": {
|
|
args: types.ConfigMapArgs{
|
|
GeneratorArgs: types.GeneratorArgs{
|
|
Name: "fileConfigMap1",
|
|
KvPairSources: types.KvPairSources{
|
|
FileSources: []string{
|
|
filepath.Join("configmap", "app-init.ini"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
exp: expected{
|
|
out: `apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: fileConfigMap1
|
|
data:
|
|
app-init.ini: |
|
|
FOO=bar
|
|
BAR=baz
|
|
`,
|
|
},
|
|
},
|
|
"construct config map from text and binary file": {
|
|
args: types.ConfigMapArgs{
|
|
GeneratorArgs: types.GeneratorArgs{
|
|
Name: "fileConfigMap2",
|
|
KvPairSources: types.KvPairSources{
|
|
FileSources: []string{
|
|
filepath.Join("configmap", "app-init.ini"),
|
|
filepath.Join("configmap", "app.bin"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
exp: expected{
|
|
errMsg: "configMap generate error: key 'app.bin' appears " +
|
|
"to have non-utf8 data; binaryData field not yet supported",
|
|
out: `apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: fileConfigMap2
|
|
data:
|
|
app-init.ini: |
|
|
FOO=bar
|
|
BAR=baz
|
|
`,
|
|
},
|
|
},
|
|
"construct config map from literal": {
|
|
args: types.ConfigMapArgs{
|
|
GeneratorArgs: types.GeneratorArgs{
|
|
Name: "literalConfigMap1",
|
|
KvPairSources: types.KvPairSources{
|
|
LiteralSources: []string{"a=x", "b=y", "c=\"Hello World\"", "d='true'"},
|
|
},
|
|
Options: &types.GeneratorOptions{
|
|
Labels: map[string]string{
|
|
"foo": "bar",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
exp: expected{
|
|
out: `apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: literalConfigMap1
|
|
labels:
|
|
foo: 'bar'
|
|
data:
|
|
a: x
|
|
b: y
|
|
c: Hello World
|
|
d: "true"
|
|
`,
|
|
},
|
|
},
|
|
"construct config map from literal with GeneratorOptions in ConfigMapArgs": {
|
|
args: types.ConfigMapArgs{
|
|
GeneratorArgs: types.GeneratorArgs{
|
|
Name: "literalConfigMap2",
|
|
KvPairSources: types.KvPairSources{
|
|
LiteralSources: []string{"a=x", "b=y", "c=\"Hello World\"", "d='true'"},
|
|
},
|
|
Options: &types.GeneratorOptions{
|
|
Labels: map[string]string{
|
|
"veggie": "celery",
|
|
"dog": "beagle",
|
|
"cat": "annoying",
|
|
},
|
|
Annotations: map[string]string{
|
|
"river": "Missouri",
|
|
"city": "Iowa City",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
exp: expected{
|
|
out: `apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: literalConfigMap2
|
|
labels:
|
|
cat: 'annoying'
|
|
dog: 'beagle'
|
|
veggie: 'celery'
|
|
annotations:
|
|
city: 'Iowa City'
|
|
river: 'Missouri'
|
|
data:
|
|
a: x
|
|
b: y
|
|
c: Hello World
|
|
d: "true"
|
|
`,
|
|
},
|
|
},
|
|
}
|
|
fSys := filesys.MakeFsInMemory()
|
|
fSys.WriteFile(
|
|
filesys.RootedPath("configmap", "app.env"),
|
|
[]byte("DB_USERNAME=admin\nDB_PASSWORD=qwerty\n"))
|
|
fSys.WriteFile(
|
|
filesys.RootedPath("configmap", "app-init.ini"),
|
|
[]byte("FOO=bar\nBAR=baz\n"))
|
|
fSys.WriteFile(
|
|
filesys.RootedPath("configmap", "app.bin"),
|
|
[]byte{0xff, 0xfd})
|
|
kvLdr := kv.NewLoader(
|
|
loader.NewFileLoaderAtRoot(fSys),
|
|
valtest_test.MakeFakeValidator())
|
|
|
|
for n := range testCases {
|
|
tc := testCases[n]
|
|
t.Run(n, func(t *testing.T) {
|
|
rn, err := factory.makeConfigMap(kvLdr, &tc.args)
|
|
if err != nil {
|
|
if !assert.EqualError(t, err, tc.exp.errMsg) {
|
|
t.FailNow()
|
|
}
|
|
return
|
|
}
|
|
if tc.exp.errMsg != "" {
|
|
t.Fatalf("%s: should return error '%s'", n, tc.exp.errMsg)
|
|
}
|
|
output := rn.MustString()
|
|
if !assert.Equal(t, tc.exp.out, output) {
|
|
t.FailNow()
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMakeSecret(t *testing.T) {
|
|
factory := &WNodeFactory{}
|
|
type expected struct {
|
|
out string
|
|
errMsg string
|
|
}
|
|
|
|
testCases := map[string]struct {
|
|
args types.SecretArgs
|
|
exp expected
|
|
}{
|
|
"construct secret from env": {
|
|
args: types.SecretArgs{
|
|
GeneratorArgs: types.GeneratorArgs{
|
|
Name: "envSecret",
|
|
KvPairSources: types.KvPairSources{
|
|
EnvSources: []string{
|
|
filepath.Join("secret", "app.env"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
exp: expected{
|
|
errMsg: "TODO(WNodeFactory): finish implementation of makeSecret",
|
|
out: `apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: envSecret
|
|
data:
|
|
DB_USERNAME: admin
|
|
DB_PASSWORD: qwerty
|
|
`,
|
|
},
|
|
},
|
|
"construct secret from text file": {
|
|
args: types.SecretArgs{
|
|
GeneratorArgs: types.GeneratorArgs{
|
|
Name: "fileSecret1",
|
|
KvPairSources: types.KvPairSources{
|
|
FileSources: []string{
|
|
filepath.Join("secret", "app-init.ini"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
exp: expected{
|
|
errMsg: "TODO(WNodeFactory): finish implementation of makeSecret",
|
|
out: `apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: fileSecret1
|
|
data:
|
|
app-init.ini: |
|
|
FOO=bar
|
|
BAR=baz
|
|
`,
|
|
},
|
|
},
|
|
"construct secret from text and binary file": {
|
|
args: types.SecretArgs{
|
|
GeneratorArgs: types.GeneratorArgs{
|
|
Name: "fileSecret2",
|
|
KvPairSources: types.KvPairSources{
|
|
FileSources: []string{
|
|
filepath.Join("secret", "app-init.ini"),
|
|
filepath.Join("secret", "app.bin"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
exp: expected{
|
|
errMsg: "TODO(WNodeFactory): finish implementation of makeSecret",
|
|
out: `apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: fileSecret2
|
|
data:
|
|
app-init.ini: |
|
|
FOO=bar
|
|
BAR=baz
|
|
`,
|
|
},
|
|
},
|
|
"construct secret from literal": {
|
|
args: types.SecretArgs{
|
|
GeneratorArgs: types.GeneratorArgs{
|
|
Name: "literalSecret1",
|
|
KvPairSources: types.KvPairSources{
|
|
LiteralSources: []string{"a=x", "b=y", "c=\"Hello World\"", "d='true'"},
|
|
},
|
|
Options: &types.GeneratorOptions{
|
|
Labels: map[string]string{
|
|
"foo": "bar",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
exp: expected{
|
|
errMsg: "TODO(WNodeFactory): finish implementation of makeSecret",
|
|
out: `apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: literalSecret1
|
|
labels:
|
|
foo: 'bar'
|
|
data:
|
|
a: x
|
|
b: y
|
|
c: Hello World
|
|
d: "true"
|
|
`,
|
|
},
|
|
},
|
|
"construct secret from literal with GeneratorOptions in SecretArgs": {
|
|
args: types.SecretArgs{
|
|
GeneratorArgs: types.GeneratorArgs{
|
|
Name: "literalSecret2",
|
|
KvPairSources: types.KvPairSources{
|
|
LiteralSources: []string{"a=x", "b=y", "c=\"Hello World\"", "d='true'"},
|
|
},
|
|
Options: &types.GeneratorOptions{
|
|
Labels: map[string]string{
|
|
"veggie": "celery",
|
|
"dog": "beagle",
|
|
"cat": "annoying",
|
|
},
|
|
Annotations: map[string]string{
|
|
"river": "Missouri",
|
|
"city": "Iowa City",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
exp: expected{
|
|
errMsg: "TODO(WNodeFactory): finish implementation of makeSecret",
|
|
out: `apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: literalSecret2
|
|
labels:
|
|
cat: 'annoying'
|
|
dog: 'beagle'
|
|
veggie: 'celery'
|
|
annotations:
|
|
city: 'Iowa City'
|
|
river: 'Missouri'
|
|
data:
|
|
a: x
|
|
b: y
|
|
c: Hello World
|
|
d: "true"
|
|
`,
|
|
},
|
|
},
|
|
}
|
|
fSys := filesys.MakeFsInMemory()
|
|
fSys.WriteFile(
|
|
filesys.RootedPath("secret", "app.env"),
|
|
[]byte("DB_USERNAME=admin\nDB_PASSWORD=qwerty\n"))
|
|
fSys.WriteFile(
|
|
filesys.RootedPath("secret", "app-init.ini"),
|
|
[]byte("FOO=bar\nBAR=baz\n"))
|
|
fSys.WriteFile(
|
|
filesys.RootedPath("secret", "app.bin"),
|
|
[]byte{0xff, 0xfd})
|
|
kvLdr := kv.NewLoader(
|
|
loader.NewFileLoaderAtRoot(fSys),
|
|
valtest_test.MakeFakeValidator())
|
|
|
|
for n := range testCases {
|
|
tc := testCases[n]
|
|
t.Run(n, func(t *testing.T) {
|
|
rn, err := factory.makeSecret(kvLdr, &tc.args)
|
|
if err != nil {
|
|
if !assert.EqualError(t, err, tc.exp.errMsg) {
|
|
t.FailNow()
|
|
}
|
|
return
|
|
}
|
|
if tc.exp.errMsg != "" {
|
|
t.Fatalf("%s: should return error '%s'", n, tc.exp.errMsg)
|
|
}
|
|
output := rn.MustString()
|
|
if !assert.Equal(t, tc.exp.out, output) {
|
|
t.FailNow()
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSliceFromBytes(t *testing.T) {
|
|
factory := &WNodeFactory{}
|
|
testConfigMap :=
|
|
map[string]interface{}{
|
|
"apiVersion": "v1",
|
|
"kind": "ConfigMap",
|
|
"metadata": map[string]interface{}{
|
|
"name": "winnie",
|
|
},
|
|
}
|
|
testConfigMapList :=
|
|
map[string]interface{}{
|
|
"apiVersion": "v1",
|
|
"kind": "ConfigMapList",
|
|
"items": []interface{}{
|
|
testConfigMap,
|
|
testConfigMap,
|
|
},
|
|
}
|
|
|
|
type expected struct {
|
|
out []map[string]interface{}
|
|
isErr bool
|
|
}
|
|
|
|
testCases := map[string]struct {
|
|
input []byte
|
|
exp expected
|
|
}{
|
|
"garbage": {
|
|
input: []byte("garbageIn: garbageOut"),
|
|
exp: expected{
|
|
isErr: true,
|
|
},
|
|
},
|
|
"noBytes": {
|
|
input: []byte{},
|
|
exp: expected{
|
|
out: []map[string]interface{}{},
|
|
},
|
|
},
|
|
"goodJson": {
|
|
input: []byte(`
|
|
{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie"}}
|
|
`),
|
|
exp: expected{
|
|
out: []map[string]interface{}{testConfigMap},
|
|
},
|
|
},
|
|
"goodYaml1": {
|
|
input: []byte(`
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: winnie
|
|
`),
|
|
exp: expected{
|
|
out: []map[string]interface{}{testConfigMap},
|
|
},
|
|
},
|
|
"goodYaml2": {
|
|
input: []byte(`
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: winnie
|
|
---
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: winnie
|
|
`),
|
|
exp: expected{
|
|
out: []map[string]interface{}{testConfigMap, testConfigMap},
|
|
},
|
|
},
|
|
"localConfigYaml": {
|
|
input: []byte(`
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: winnie-skip
|
|
annotations:
|
|
# this annotation causes the Resource to be ignored by kustomize
|
|
config.kubernetes.io/local-config: ""
|
|
---
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: winnie
|
|
`),
|
|
exp: expected{
|
|
out: []map[string]interface{}{testConfigMap},
|
|
},
|
|
},
|
|
"garbageInOneOfTwoObjects": {
|
|
input: []byte(`
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: winnie
|
|
---
|
|
WOOOOOOOOOOOOOOOOOOOOOOOOT: woot
|
|
`),
|
|
exp: expected{
|
|
isErr: true,
|
|
},
|
|
},
|
|
"emptyObjects": {
|
|
input: []byte(`
|
|
---
|
|
#a comment
|
|
|
|
---
|
|
|
|
`),
|
|
exp: expected{
|
|
out: []map[string]interface{}{},
|
|
},
|
|
},
|
|
"Missing .metadata.name in object": {
|
|
input: []byte(`
|
|
apiVersion: v1
|
|
kind: Namespace
|
|
metadata:
|
|
annotations:
|
|
foo: bar
|
|
`),
|
|
exp: expected{
|
|
isErr: true,
|
|
},
|
|
},
|
|
"nil value in list": {
|
|
input: []byte(`
|
|
apiVersion: builtin
|
|
kind: ConfigMapGenerator
|
|
metadata:
|
|
name: kube100-site
|
|
labels:
|
|
app: web
|
|
testList:
|
|
- testA
|
|
-
|
|
`),
|
|
exp: expected{
|
|
isErr: true,
|
|
},
|
|
},
|
|
"List": {
|
|
input: []byte(`
|
|
apiVersion: v1
|
|
kind: List
|
|
items:
|
|
- apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: winnie
|
|
- apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: winnie
|
|
`),
|
|
exp: expected{
|
|
out: []map[string]interface{}{
|
|
testConfigMap,
|
|
testConfigMap},
|
|
},
|
|
},
|
|
"ConfigMapList": {
|
|
input: []byte(`
|
|
apiVersion: v1
|
|
kind: ConfigMapList
|
|
items:
|
|
- apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: winnie
|
|
- apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: winnie
|
|
`),
|
|
exp: expected{
|
|
out: []map[string]interface{}{testConfigMapList},
|
|
},
|
|
},
|
|
}
|
|
|
|
for n := range testCases {
|
|
tc := testCases[n]
|
|
t.Run(n, func(t *testing.T) {
|
|
rs, err := factory.SliceFromBytes(tc.input)
|
|
if tc.exp.isErr && err == nil {
|
|
t.Fatalf("%v: should return error", n)
|
|
}
|
|
if !tc.exp.isErr && err != nil {
|
|
t.Fatalf("%v: unexpected error: %s", n, err)
|
|
}
|
|
if len(tc.exp.out) != len(rs) {
|
|
fmt.Printf("%s: \nexpected:%v\nactual: %v\n",
|
|
n, tc.exp.out, rs)
|
|
t.Fatalf("%s: length mismatch; expected %d, actual %d",
|
|
n, len(tc.exp.out), len(rs))
|
|
}
|
|
for i := range rs {
|
|
if !reflect.DeepEqual(tc.exp.out[i], rs[i].Map()) {
|
|
t.Fatalf("%s: Got: %v\nexpected:%v",
|
|
n, rs[i].Map(), tc.exp.out[i])
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|