mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-05-17 18:25:26 +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.
251 lines
5.8 KiB
Go
251 lines
5.8 KiB
Go
// Copyright 2022 The Kubernetes Authors.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package krmfunction
|
|
|
|
import (
|
|
"bytes"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func getTransformerCode() []byte {
|
|
// a simple namespace transformer
|
|
return []byte(`
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"sigs.k8s.io/kustomize/api/resmap"
|
|
"sigs.k8s.io/yaml"
|
|
"sigs.k8s.io/kustomize/api/filters/namespace"
|
|
"sigs.k8s.io/kustomize/kyaml/filtersutil"
|
|
"sigs.k8s.io/kustomize/api/types"
|
|
)
|
|
|
|
type plugin struct{
|
|
Namespace string ` + "`json:\"namespace,omitempty\" yaml:\"namespace,omitempty\"`" + `
|
|
FieldSpecs []types.FieldSpec ` + "`json:\"fieldSpecs,omitempty\" yaml:\"fieldSpecs,omitempty\"`" + `
|
|
}
|
|
|
|
var KustomizePlugin plugin //nolint:gochecknoglobals
|
|
|
|
func (p *plugin) Config(
|
|
_ *resmap.PluginHelpers, config []byte) (err error) {
|
|
return yaml.Unmarshal(config, p)
|
|
}
|
|
|
|
func (p *plugin) Transform(rm resmap.ResMap) error {
|
|
if len(p.Namespace) == 0 {
|
|
return nil
|
|
}
|
|
for _, r := range rm.Resources() {
|
|
if r.IsNilOrEmpty() {
|
|
// Don't mutate empty objects?
|
|
continue
|
|
}
|
|
err := filtersutil.ApplyToJSON(namespace.Filter{
|
|
Namespace: p.Namespace,
|
|
FsSlice: p.FieldSpecs,
|
|
}, r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
matches := rm.GetMatchingResourcesByCurrentId(r.CurId().Equals)
|
|
if len(matches) != 1 {
|
|
return fmt.Errorf(
|
|
"namespace transformation produces ID conflict: %+v", matches)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
`)
|
|
}
|
|
|
|
func getTransformerInputResource() []byte {
|
|
return []byte(`
|
|
apiVersion: config.kubernetes.io/v1
|
|
kind: ResourceList
|
|
functionConfig:
|
|
apiVersion: foo-corp.com/v1
|
|
kind: FulfillmentCenter
|
|
metadata:
|
|
name: staging
|
|
annotations:
|
|
config.kubernetes.io/function: |
|
|
container:
|
|
image: gcr.io/example/foo:v1.0.0
|
|
data:
|
|
namespace: foo
|
|
fieldSpecs:
|
|
- path: metadata/namespace
|
|
create: true
|
|
items:
|
|
- apiVersion: apps/v1
|
|
kind: foobar
|
|
metadata:
|
|
name: whatever
|
|
`)
|
|
}
|
|
|
|
func runKrmFunction(t *testing.T, input []byte, dir string) []byte {
|
|
t.Helper()
|
|
prepareCmd := func(name string, arg ...string) (*exec.Cmd, *bytes.Buffer, *bytes.Buffer) {
|
|
ob := bytes.NewBuffer([]byte{})
|
|
eb := bytes.NewBuffer([]byte{})
|
|
cmd := exec.Command(name, arg...)
|
|
cmd.Stdout = ob
|
|
cmd.Stderr = eb
|
|
cmd.Dir = dir
|
|
return cmd, ob, eb
|
|
}
|
|
cmd, ob, eb := prepareCmd("go", "mod", "tidy")
|
|
require.NoErrorf(t, cmd.Run(), "Stdout:\n%s\nStderr:\n%s\n", ob.String(), eb.String())
|
|
|
|
cmd, ob, eb = prepareCmd("go", "run", ".")
|
|
cmd.Stdin = bytes.NewReader(input)
|
|
require.NoErrorf(t, cmd.Run(), "Stdout:\n%s\nStderr:\n%s\n", ob.String(), eb.String())
|
|
|
|
return ob.Bytes()
|
|
}
|
|
|
|
func TestTransformerConverter(t *testing.T) {
|
|
dir := t.TempDir()
|
|
|
|
err := os.WriteFile(filepath.Join(dir, "Plugin.go"),
|
|
getTransformerCode(), 0644)
|
|
require.NoError(t, err)
|
|
|
|
c := NewConverter(filepath.Join(dir, "output"),
|
|
filepath.Join(dir, "Plugin.go"))
|
|
|
|
err = c.Convert()
|
|
require.NoError(t, err)
|
|
|
|
output := runKrmFunction(t, getTransformerInputResource(), filepath.Join(dir, "output"))
|
|
assert.Equal(t, `apiVersion: config.kubernetes.io/v1
|
|
kind: ResourceList
|
|
items:
|
|
- apiVersion: apps/v1
|
|
kind: foobar
|
|
metadata:
|
|
name: whatever
|
|
namespace: foo
|
|
functionConfig:
|
|
apiVersion: foo-corp.com/v1
|
|
kind: FulfillmentCenter
|
|
metadata:
|
|
name: staging
|
|
annotations:
|
|
config.kubernetes.io/function: |
|
|
container:
|
|
image: gcr.io/example/foo:v1.0.0
|
|
data:
|
|
namespace: foo
|
|
fieldSpecs:
|
|
- path: metadata/namespace
|
|
create: true
|
|
`, string(output))
|
|
}
|
|
|
|
func getGeneratorCode() []byte {
|
|
return []byte(`package main
|
|
|
|
import (
|
|
"sigs.k8s.io/kustomize/api/kv"
|
|
"sigs.k8s.io/kustomize/api/resmap"
|
|
"sigs.k8s.io/kustomize/api/types"
|
|
"sigs.k8s.io/yaml"
|
|
)
|
|
|
|
type plugin struct {
|
|
h *resmap.PluginHelpers
|
|
types.ObjectMeta ` + "`json:\"metadata,omitempty\" yaml:\"metadata,omitempty\"`" + `
|
|
types.ConfigMapArgs
|
|
}
|
|
|
|
var KustomizePlugin plugin //nolint:gochecknoglobals
|
|
|
|
func (p *plugin) Config(h *resmap.PluginHelpers, config []byte) (err error) {
|
|
p.ConfigMapArgs = types.ConfigMapArgs{}
|
|
err = yaml.Unmarshal(config, p)
|
|
if p.ConfigMapArgs.Name == "" {
|
|
p.ConfigMapArgs.Name = p.Name
|
|
}
|
|
if p.ConfigMapArgs.Namespace == "" {
|
|
p.ConfigMapArgs.Namespace = p.Namespace
|
|
}
|
|
p.h = h
|
|
return
|
|
}
|
|
|
|
func (p *plugin) Generate() (resmap.ResMap, error) {
|
|
return p.h.ResmapFactory().FromConfigMapArgs(
|
|
kv.NewLoader(p.h.Loader(), p.h.Validator()), p.ConfigMapArgs)
|
|
}`)
|
|
}
|
|
|
|
func getGeneratorInputResource() []byte {
|
|
return []byte(`
|
|
apiVersion: config.kubernetes.io/v1
|
|
kind: ResourceList
|
|
functionConfig:
|
|
apiVersion: foo-corp.com/v1
|
|
kind: FulfillmentCenter
|
|
metadata:
|
|
name: staging
|
|
annotations:
|
|
config.kubernetes.io/function: |
|
|
container:
|
|
image: gcr.io/example/foo:v1.0.0
|
|
data:
|
|
metadata:
|
|
name: staging
|
|
items: []
|
|
`)
|
|
}
|
|
|
|
func TestGeneratorConverter(t *testing.T) {
|
|
dir := t.TempDir()
|
|
|
|
err := os.WriteFile(filepath.Join(dir, "Plugin.go"),
|
|
getGeneratorCode(), 0644)
|
|
require.NoError(t, err)
|
|
|
|
c := NewConverter(filepath.Join(dir, "output"),
|
|
filepath.Join(dir, "Plugin.go"))
|
|
|
|
err = c.Convert()
|
|
require.NoError(t, err)
|
|
output := runKrmFunction(t, getGeneratorInputResource(), filepath.Join(dir, "output"))
|
|
assert.Equal(t, `apiVersion: config.kubernetes.io/v1
|
|
kind: ResourceList
|
|
items:
|
|
- apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: staging
|
|
annotations:
|
|
internal.config.kubernetes.io/generatorBehavior: unspecified
|
|
internal.config.kubernetes.io/needsHashSuffix: enabled
|
|
functionConfig:
|
|
apiVersion: foo-corp.com/v1
|
|
kind: FulfillmentCenter
|
|
metadata:
|
|
name: staging
|
|
annotations:
|
|
config.kubernetes.io/function: |
|
|
container:
|
|
image: gcr.io/example/foo:v1.0.0
|
|
data:
|
|
metadata:
|
|
name: staging
|
|
`, string(output))
|
|
}
|