Files
kustomize/api/resmap/factory_test.go
Karl Isenberg 43868688d5 Use require for Error and NoError
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.
2024-03-20 13:19:18 -07:00

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)
}
})
}
}