diff --git a/apptests/kustomize/kustomize.go b/apptests/kustomize/kustomize.go new file mode 100644 index 000000000..6e9186fec --- /dev/null +++ b/apptests/kustomize/kustomize.go @@ -0,0 +1,83 @@ +package kustomize + +import ( + "github.com/drone/envsubst" + "sigs.k8s.io/kustomize/api/krusty" + "sigs.k8s.io/kustomize/api/resmap" + "sigs.k8s.io/kustomize/api/resource" + "sigs.k8s.io/kustomize/kyaml/filesys" +) + +type Kustomize struct { + directory string // The directory where the kustomization file is located + substitutes map[string]string // The map of environment variables to substitute in the resources + resources resmap.ResMap // The map of resources generated by the kustomization process +} + +// New creates a new Kustomize instance with the given directory and substitutes. +func New(dir string, subs map[string]string) *Kustomize { + return &Kustomize{ + directory: dir, + substitutes: subs, + resources: resmap.New(), + } +} + +// Build runs the kustomization process on the directory and substitutes the +// environment variables in the resources. +func (k *Kustomize) Build() error { + opts := krusty.MakeDefaultOptions() + opts.Reorder = krusty.ReorderOptionLegacy + + kustomizer := krusty.MakeKustomizer(opts) + + // Run the kustomizer on the directory and get the resource map + resourceMap, err := kustomizer.Run(filesys.MakeFsOnDisk(), k.directory) + if err != nil { + return err + } + + k.resources.Clear() + for _, r := range resourceMap.Resources() { + yaml, err := r.AsYAML() + if err != nil { + return err + } + + out, err := envsubst.Eval(string(yaml), func(s string) string { + return k.substitutes[s] + }) + if err != nil { + return err + } + + // Convert the output string to a resource and append it to the resources map + res, err := newResourceFromString(out) + if err != nil { + return err + } + k.resources.Append(res) + } + + return nil +} + +// Output returns the YAML representation of the resources map as a string. +func (k *Kustomize) Output() (string, error) { + yml, err := k.resources.AsYaml() + if err != nil { + return "", err + } + return string(yml), nil +} + +// newResourceFromString converts a given string to a Kubernetes resource. +func newResourceFromString(str string) (*resource.Resource, error) { + fc := resmap.NewFactory(&resource.Factory{}) + resource, err := fc.NewResMapFromBytes([]byte(str)) + if err != nil { + return nil, err + } + + return resource.Resources()[0], nil +} diff --git a/apptests/kustomize/kustomize_test.go b/apptests/kustomize/kustomize_test.go new file mode 100644 index 000000000..93d5882d9 --- /dev/null +++ b/apptests/kustomize/kustomize_test.go @@ -0,0 +1,37 @@ +package kustomize + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestBuild(t *testing.T) { + wd, err := os.Getwd() + assert.NoError(t, err) + + builder := New( + filepath.Join(wd, "testdata"), + map[string]string{ + "name": "test", + "namespace": "test", + }, + ) + err = builder.Build() + assert.NoError(t, err) + + output, err := builder.Output() + assert.NoError(t, err) + + // define the expected output + expected := `apiVersion: apps/v1 +kind: Deployment +metadata: + name: test + namespace: test +` + + assert.Equal(t, output, expected) +} diff --git a/apptests/kustomize/testdata/kustomization.yaml b/apptests/kustomize/testdata/kustomization.yaml new file mode 100644 index 000000000..12d16695a --- /dev/null +++ b/apptests/kustomize/testdata/kustomization.yaml @@ -0,0 +1,4 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- sample.yaml diff --git a/apptests/kustomize/testdata/sample.yaml b/apptests/kustomize/testdata/sample.yaml new file mode 100644 index 000000000..270baf3cc --- /dev/null +++ b/apptests/kustomize/testdata/sample.yaml @@ -0,0 +1,6 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ${name} + namespace: ${namespace}