mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-05-17 10:15:22 +00:00
Assert keeps going after failure, but require immediately fails the tests, making it easier to find the output related to the test failure, rather than having to comb through a bunch of subsequent assertion failures. For equality tests, we may or may not want to continue, but for error checks we almost always want to immediately fail the test. Exceptions can be changed as-needed.
357 lines
8.5 KiB
Go
357 lines
8.5 KiB
Go
// Copyright 2019 The Kubernetes Authors.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package resmap_test
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"sigs.k8s.io/kustomize/api/ifc"
|
|
loader "sigs.k8s.io/kustomize/api/internal/loader"
|
|
"sigs.k8s.io/kustomize/api/kv"
|
|
ldrpkg "sigs.k8s.io/kustomize/api/pkg/loader"
|
|
. "sigs.k8s.io/kustomize/api/resmap"
|
|
resmaptest_test "sigs.k8s.io/kustomize/api/testutils/resmaptest"
|
|
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
|
|
"sigs.k8s.io/kustomize/api/types"
|
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
|
)
|
|
|
|
func TestFromFile(t *testing.T) {
|
|
resourceStr := `apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: dply1
|
|
---
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: dply2
|
|
---
|
|
# some comment
|
|
---
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: dply2
|
|
namespace: test
|
|
---
|
|
`
|
|
expected := resmaptest_test.NewRmBuilder(t, rf).
|
|
Add(map[string]interface{}{
|
|
"apiVersion": "apps/v1",
|
|
"kind": "Deployment",
|
|
"metadata": map[string]interface{}{
|
|
"name": "dply1",
|
|
}}).
|
|
Add(map[string]interface{}{
|
|
"apiVersion": "apps/v1",
|
|
"kind": "Deployment",
|
|
"metadata": map[string]interface{}{
|
|
"name": "dply2",
|
|
}}).
|
|
Add(map[string]interface{}{
|
|
"apiVersion": "apps/v1",
|
|
"kind": "Deployment",
|
|
"metadata": map[string]interface{}{
|
|
"name": "dply2",
|
|
"namespace": "test",
|
|
}}).ResMap()
|
|
expYaml, err := expected.AsYaml()
|
|
require.NoError(t, err)
|
|
|
|
fSys := filesys.MakeFsInMemory()
|
|
require.NoError(t, fSys.WriteFile("deployment.yaml", []byte(resourceStr)))
|
|
|
|
ldr, err := loader.NewLoader(
|
|
loader.RestrictionRootOnly, filesys.Separator, fSys)
|
|
require.NoError(t, err)
|
|
|
|
m, err := rmF.FromFile(ldr, "deployment.yaml")
|
|
require.NoError(t, err)
|
|
mYaml, err := m.AsYaml()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, expYaml, mYaml)
|
|
}
|
|
|
|
func TestFromBytes(t *testing.T) {
|
|
encoded := []byte(`apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: cm1
|
|
---
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: cm2
|
|
`)
|
|
expected := resmaptest_test.NewRmBuilder(t, rf).
|
|
Add(map[string]interface{}{
|
|
"apiVersion": "v1",
|
|
"kind": "ConfigMap",
|
|
"metadata": map[string]interface{}{
|
|
"name": "cm1",
|
|
}}).
|
|
Add(map[string]interface{}{
|
|
"apiVersion": "v1",
|
|
"kind": "ConfigMap",
|
|
"metadata": map[string]interface{}{
|
|
"name": "cm2",
|
|
}}).ResMap()
|
|
expYaml, err := expected.AsYaml()
|
|
require.NoError(t, err)
|
|
m, err := rmF.NewResMapFromBytes(encoded)
|
|
require.NoError(t, err)
|
|
mYaml, err := m.AsYaml()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, expYaml, mYaml)
|
|
}
|
|
|
|
func TestNewFromConfigMaps(t *testing.T) {
|
|
type testCase struct {
|
|
description string
|
|
input []types.ConfigMapArgs
|
|
filepath string
|
|
content string
|
|
expected ResMap
|
|
}
|
|
|
|
fSys := filesys.MakeFsInMemory()
|
|
ldr, err := loader.NewLoader(
|
|
loader.RestrictionRootOnly, filesys.Separator, fSys)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
kvLdr := kv.NewLoader(ldr, valtest_test.MakeFakeValidator())
|
|
testCases := []testCase{
|
|
{
|
|
description: "construct config map from env",
|
|
input: []types.ConfigMapArgs{
|
|
{
|
|
GeneratorArgs: types.GeneratorArgs{
|
|
Name: "envConfigMap",
|
|
KvPairSources: types.KvPairSources{
|
|
EnvSources: []string{"app.env"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
filepath: "app.env",
|
|
content: "DB_USERNAME=admin\nDB_PASSWORD=somepw",
|
|
expected: resmaptest_test.NewRmBuilder(t, rf).Add(
|
|
map[string]interface{}{
|
|
"apiVersion": "v1",
|
|
"kind": "ConfigMap",
|
|
"metadata": map[string]interface{}{
|
|
"name": "envConfigMap",
|
|
},
|
|
"data": map[string]interface{}{
|
|
"DB_USERNAME": "admin",
|
|
"DB_PASSWORD": "somepw",
|
|
}}).ResMap(),
|
|
},
|
|
|
|
{
|
|
description: "construct config map from file",
|
|
input: []types.ConfigMapArgs{{
|
|
GeneratorArgs: types.GeneratorArgs{
|
|
Name: "fileConfigMap",
|
|
KvPairSources: types.KvPairSources{
|
|
FileSources: []string{"app-init.ini"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
filepath: "app-init.ini",
|
|
content: "FOO=bar\nBAR=baz\n",
|
|
expected: resmaptest_test.NewRmBuilder(t, rf).Add(
|
|
map[string]interface{}{
|
|
"apiVersion": "v1",
|
|
"kind": "ConfigMap",
|
|
"metadata": map[string]interface{}{
|
|
"name": "fileConfigMap",
|
|
},
|
|
"data": map[string]interface{}{
|
|
"app-init.ini": `FOO=bar
|
|
BAR=baz
|
|
`,
|
|
},
|
|
}).ResMap(),
|
|
},
|
|
{
|
|
description: "construct config map from literal",
|
|
input: []types.ConfigMapArgs{
|
|
{
|
|
GeneratorArgs: types.GeneratorArgs{
|
|
Name: "literalConfigMap",
|
|
KvPairSources: types.KvPairSources{
|
|
LiteralSources: []string{"a=x", "b=y", "c=\"Good Morning\"", "d=\"false\""},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expected: resmaptest_test.NewRmBuilder(t, rf).Add(
|
|
map[string]interface{}{
|
|
"apiVersion": "v1",
|
|
"kind": "ConfigMap",
|
|
"metadata": map[string]interface{}{
|
|
"name": "literalConfigMap",
|
|
},
|
|
"data": map[string]interface{}{
|
|
"a": "x",
|
|
"b": "y",
|
|
"c": "Good Morning",
|
|
"d": "false",
|
|
},
|
|
}).ResMap(),
|
|
},
|
|
|
|
// TODO: add testcase for data coming from multiple sources like
|
|
// files/literal/env etc.
|
|
}
|
|
for _, tc := range testCases {
|
|
if tc.filepath != "" {
|
|
if fErr := fSys.WriteFile(tc.filepath, []byte(tc.content)); fErr != nil {
|
|
t.Fatalf("error adding file '%s': %v\n", tc.filepath, fErr)
|
|
}
|
|
}
|
|
r, err := rmF.NewResMapFromConfigMapArgs(kvLdr, tc.input)
|
|
require.NoError(t, err, tc.description)
|
|
r.RemoveBuildAnnotations()
|
|
rYaml, err := r.AsYaml()
|
|
require.NoError(t, err, tc.description)
|
|
tc.expected.RemoveBuildAnnotations()
|
|
expYaml, err := tc.expected.AsYaml()
|
|
require.NoError(t, err, tc.description)
|
|
assert.Equal(t, expYaml, rYaml)
|
|
}
|
|
}
|
|
|
|
func TestNewResMapFromSecretArgs(t *testing.T) {
|
|
secrets := []types.SecretArgs{
|
|
{
|
|
GeneratorArgs: types.GeneratorArgs{
|
|
Name: "apple",
|
|
KvPairSources: types.KvPairSources{
|
|
LiteralSources: []string{
|
|
"DB_USERNAME=admin",
|
|
"DB_PASSWORD=somepw",
|
|
},
|
|
},
|
|
},
|
|
Type: ifc.SecretTypeOpaque,
|
|
},
|
|
}
|
|
fSys := filesys.MakeFsInMemory()
|
|
fSys.Mkdir(filesys.SelfDir)
|
|
|
|
actual, err := rmF.NewResMapFromSecretArgs(
|
|
kv.NewLoader(
|
|
ldrpkg.NewFileLoaderAtRoot(fSys),
|
|
valtest_test.MakeFakeValidator()), secrets)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
actual.RemoveBuildAnnotations()
|
|
actYaml, err := actual.AsYaml()
|
|
require.NoError(t, err)
|
|
|
|
expected := resmaptest_test.NewRmBuilder(t, rf).Add(
|
|
map[string]interface{}{
|
|
"apiVersion": "v1",
|
|
"kind": "Secret",
|
|
"metadata": map[string]interface{}{
|
|
"name": "apple",
|
|
},
|
|
"type": ifc.SecretTypeOpaque,
|
|
"data": map[string]interface{}{
|
|
"DB_USERNAME": base64.StdEncoding.EncodeToString([]byte("admin")),
|
|
"DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")),
|
|
},
|
|
}).ResMap()
|
|
expYaml, err := expected.AsYaml()
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, string(expYaml), string(actYaml))
|
|
}
|
|
|
|
func TestFromRNodeSlice(t *testing.T) {
|
|
type testcase struct {
|
|
input string
|
|
expected ResMap
|
|
}
|
|
testcases := map[string]testcase{
|
|
"no resource": {
|
|
input: "---",
|
|
expected: resmaptest_test.NewRmBuilder(t, rf).ResMap(),
|
|
},
|
|
"single resource": {
|
|
input: `apiVersion: rbac.authorization.k8s.io/v1
|
|
kind: ClusterRole
|
|
metadata:
|
|
name: namespace-reader
|
|
rules:
|
|
- apiGroups:
|
|
- ""
|
|
resources:
|
|
- namespaces
|
|
verbs:
|
|
- get
|
|
- watch
|
|
- list
|
|
`,
|
|
expected: resmaptest_test.NewRmBuilder(t, rf).Add(
|
|
map[string]interface{}{
|
|
"apiVersion": "rbac.authorization.k8s.io/v1",
|
|
"kind": "ClusterRole",
|
|
"metadata": map[string]interface{}{
|
|
"name": "namespace-reader",
|
|
},
|
|
"rules": []interface{}{
|
|
map[string]interface{}{
|
|
"apiGroups": []interface{}{
|
|
"",
|
|
},
|
|
"resources": []interface{}{
|
|
"namespaces",
|
|
},
|
|
"verbs": []interface{}{
|
|
"get",
|
|
"watch",
|
|
"list",
|
|
},
|
|
},
|
|
},
|
|
}).ResMap(),
|
|
},
|
|
"local config": {
|
|
// local config should be ignored
|
|
input: `apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: my-config
|
|
annotations:
|
|
config.kubernetes.io/local-config: 'true'
|
|
`,
|
|
expected: resmaptest_test.NewRmBuilder(t, rf).ResMap(),
|
|
},
|
|
}
|
|
for name := range testcases {
|
|
tc := testcases[name]
|
|
t.Run(name, func(t *testing.T) {
|
|
rm, err := rmF.NewResMapFromRNodeSlice(
|
|
[]*yaml.RNode{yaml.MustParse(tc.input)})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error in test case [%s]: %v", name, err)
|
|
}
|
|
if err = tc.expected.ErrorIfNotEqualLists(rm); err != nil {
|
|
t.Fatalf("error in test case [%s]: %s", name, err)
|
|
}
|
|
})
|
|
}
|
|
}
|