From d6edcc4c358686a653eec8781ceaefa4345c476e Mon Sep 17 00:00:00 2001 From: Shawn O'Dell Date: Mon, 25 Oct 2021 19:52:43 -0400 Subject: [PATCH 1/9] manifest envsubst Signed-off-by: Shawn O'Dell --- pkg/test/case.go | 4 ++ pkg/test/utils/kubernetes.go | 2 + pkg/test/utils/strings.go | 11 +++ pkg/test/utils/strings_test.go | 19 ++++++ pkg/test/utils/translate.go | 111 +++++++++++++++++++++++++++++++ pkg/test/utils/translate_test.go | 67 +++++++++++++++++++ 6 files changed, 214 insertions(+) create mode 100644 pkg/test/utils/strings.go create mode 100644 pkg/test/utils/strings_test.go create mode 100644 pkg/test/utils/translate.go create mode 100644 pkg/test/utils/translate_test.go diff --git a/pkg/test/case.go b/pkg/test/case.go index 97814b0d..ef20fb44 100644 --- a/pkg/test/case.go +++ b/pkg/test/case.go @@ -386,6 +386,10 @@ func (t *Case) determineNamespace() *namespace { ns.Name = fmt.Sprintf("kuttl-test-%s", petname.Generate(2, "-")) ns.AutoCreated = true } + + if _, ok := os.LookupEnv("NAMESPACE"); ok { // user can supply this environment variable + os.Setenv("NAMESPACE", t.PreferredNamespace) // set this environment variable so it can be templated by other 'steps' + } // if we have a preferred namespace, we do NOT auto-create return ns } diff --git a/pkg/test/utils/kubernetes.go b/pkg/test/utils/kubernetes.go index 38603ba1..57f75ef7 100644 --- a/pkg/test/utils/kubernetes.go +++ b/pkg/test/utils/kubernetes.go @@ -515,6 +515,8 @@ func LoadYAML(path string, r io.Reader) ([]client.Object, error) { return nil, fmt.Errorf("error decoding yaml %s: %w", path, err) } + unstructuredObj.Object = Translate(unstructuredObj.Object).(map[string]interface{}) + obj, err := ConvertUnstructured(unstructuredObj) if err != nil { return nil, fmt.Errorf("error converting unstructured object %s (%s): %w", ResourceID(unstructuredObj), path, err) diff --git a/pkg/test/utils/strings.go b/pkg/test/utils/strings.go new file mode 100644 index 00000000..21ca1435 --- /dev/null +++ b/pkg/test/utils/strings.go @@ -0,0 +1,11 @@ +package utils + +// TrimLeftChar trims the left character from a string +func TrimLeftChar(s string) string { + for i := range s { + if i > 0 { + return s[i:] + } + } + return s[:0] +} diff --git a/pkg/test/utils/strings_test.go b/pkg/test/utils/strings_test.go new file mode 100644 index 00000000..a6642241 --- /dev/null +++ b/pkg/test/utils/strings_test.go @@ -0,0 +1,19 @@ +package utils + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestTrimLeftChar(t *testing.T) { + testMap := map[string]string{ + "": "", + "$": "", + "$NAMESPACE": "NAMESPACE", + "NAMESPACE": "AMESPACE", + } + for k, v := range testMap { + assert.Equal(t, v, TrimLeftChar(k)) + } +} diff --git a/pkg/test/utils/translate.go b/pkg/test/utils/translate.go new file mode 100644 index 00000000..61ad03ab --- /dev/null +++ b/pkg/test/utils/translate.go @@ -0,0 +1,111 @@ +package utils + +import ( + "os" + "reflect" + "strings" +) + +// Translate traverses an arbitrary struct and translates all strings it encounters +// replacing variable references with environment variables +// the pet name generator also sets the NAMESPACE env var (if not already set) so +// $NAMESPACE references *should* use the generated one +// +// The MIT License (MIT) +// +// Copyright (c) 2014 Heye Vöcking +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +func Translate(obj interface{}) interface{} { + // Wrap the original in a reflect.Value + original := reflect.ValueOf(obj) + + copy := reflect.New(original.Type()).Elem() + translateRecursive(copy, original) + + // Remove the reflection wrapper + return copy.Interface() +} + +func translateRecursive(copy, original reflect.Value) { + switch original.Kind() { + // The first cases handle nested structures and translate them recursively + + // If it is a pointer we need to unwrap and call once again + case reflect.Ptr: + // To get the actual value of the original we have to call Elem() + // At the same time this unwraps the pointer so we don't end up in + // an infinite recursion + originalValue := original.Elem() + // Check if the pointer is nil + if !originalValue.IsValid() { + return + } + // Allocate a new object and set the pointer to it + copy.Set(reflect.New(originalValue.Type())) + // Unwrap the newly created pointer + translateRecursive(copy.Elem(), originalValue) + + // If it is an interface (which is very similar to a pointer), do basically the + // same as for the pointer. Though a pointer is not the same as an interface so + // note that we have to call Elem() after creating a new object because otherwise + // we would end up with an actual pointer + case reflect.Interface: + // Get rid of the wrapping interface + originalValue := original.Elem() + // Create a new object. Now new gives us a pointer, but we want the value it + // points to, so we have to call Elem() to unwrap it + copyValue := reflect.New(originalValue.Type()).Elem() + translateRecursive(copyValue, originalValue) + copy.Set(copyValue) + + // If it is a struct we translate each field + case reflect.Struct: + for i := 0; i < original.NumField(); i += 1 { + translateRecursive(copy.Field(i), original.Field(i)) + } + + // If it is a slice we create a new slice and translate each element + case reflect.Slice: + copy.Set(reflect.MakeSlice(original.Type(), original.Len(), original.Cap())) + for i := 0; i < original.Len(); i += 1 { + translateRecursive(copy.Index(i), original.Index(i)) + } + + // If it is a map we create a new map and translate each value + case reflect.Map: + copy.Set(reflect.MakeMap(original.Type())) + for _, key := range original.MapKeys() { + originalValue := original.MapIndex(key) + // New gives us a pointer, but again we want the value + copyValue := reflect.New(originalValue.Type()).Elem() + translateRecursive(copyValue, originalValue) + copy.SetMapIndex(key, copyValue) + } + + // Otherwise we cannot traverse anywhere so this finishes the the recursion + + // If it is a string translate it (yay finally we're doing what we came for) + case reflect.String: + translatedString := original.Interface().(string) + if strings.HasPrefix(translatedString, "$") { + variable := TrimLeftChar(translatedString) + if val, ok := os.LookupEnv(variable); ok { + translatedString = val + } + } + copy.SetString(translatedString) + + // And everything else will simply be taken from the original + default: + copy.Set(original) + } +} diff --git a/pkg/test/utils/translate_test.go b/pkg/test/utils/translate_test.go new file mode 100644 index 00000000..202e3ded --- /dev/null +++ b/pkg/test/utils/translate_test.go @@ -0,0 +1,67 @@ +package utils + +import ( + "bytes" + "fmt" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/util/yaml" +) + +func testDecoder(s string) *unstructured.Unstructured { + b := []byte(s) + d := yaml.NewYAMLOrJSONDecoder(bytes.NewBuffer(b), len(b)) + u := &unstructured.Unstructured{} + if err := d.Decode(u); err != nil { + fmt.Println(err) + } + return u +} + +func TestTranslate(t *testing.T) { + namespace := "foo" + if err := os.Setenv("NAMESPACE", namespace); err != nil { + fmt.Println(err) + } + BAZ := "bar" + if err := os.Setenv("BAZ", BAZ); err != nil { + fmt.Println(err) + } + + manifestTemplate := ` +apiVersion: example.com/v1 +kind: CustomResource +metadata: + name: test + namespace: $NAMESPACE +status: + ready: true +spec: + key1: + key1: data + key2: $BAZ + key2: + key1: "$NAMESPACE" +` + + manifestTemplated := fmt.Sprintf(` +apiVersion: example.com/v1 +kind: CustomResource +metadata: + name: test + namespace: %s +status: + ready: true +spec: + key1: + key1: data + key2: %s + key2: + key1: %s +`, namespace, BAZ, namespace) + + assert.Equal(t, fmt.Sprint(testDecoder(manifestTemplated)), fmt.Sprint(Translate(testDecoder(manifestTemplate)))) +} From e18a213de9631b6410b9c877c6952cdf606136b5 Mon Sep 17 00:00:00 2001 From: Shawn O'Dell Date: Wed, 29 Dec 2021 16:52:55 -0500 Subject: [PATCH 2/9] Update pkg/test/utils/translate.go Co-authored-by: Chris Bandy Signed-off-by: Shawn O'Dell --- pkg/test/utils/translate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/test/utils/translate.go b/pkg/test/utils/translate.go index 61ad03ab..cd634aac 100644 --- a/pkg/test/utils/translate.go +++ b/pkg/test/utils/translate.go @@ -97,7 +97,7 @@ func translateRecursive(copy, original reflect.Value) { case reflect.String: translatedString := original.Interface().(string) if strings.HasPrefix(translatedString, "$") { - variable := TrimLeftChar(translatedString) + variable := translatedString[1:] if val, ok := os.LookupEnv(variable); ok { translatedString = val } From bca08cccff64b3e1366c458d76857e4cbf80c67d Mon Sep 17 00:00:00 2001 From: Shawn O'Dell Date: Sun, 22 Jan 2023 16:46:29 -0600 Subject: [PATCH 3/9] fmt Signed-off-by: Shawn O'Dell --- tools.go | 1 + 1 file changed, 1 insertion(+) diff --git a/tools.go b/tools.go index 655b4e6b..51f74411 100644 --- a/tools.go +++ b/tools.go @@ -1,3 +1,4 @@ +//go:build tools // +build tools // Package tools is used to import go modules that we use for tooling as dependencies. From 6e64c5d89f1cae3d8f3a69444d68ef23c9edc524 Mon Sep 17 00:00:00 2001 From: Shawn O'Dell Date: Sun, 22 Jan 2023 16:47:23 -0600 Subject: [PATCH 4/9] remove TrimLeftChar Signed-off-by: Shawn O'Dell --- pkg/test/utils/strings.go | 11 ----------- pkg/test/utils/strings_test.go | 19 ------------------- 2 files changed, 30 deletions(-) delete mode 100644 pkg/test/utils/strings.go delete mode 100644 pkg/test/utils/strings_test.go diff --git a/pkg/test/utils/strings.go b/pkg/test/utils/strings.go deleted file mode 100644 index 21ca1435..00000000 --- a/pkg/test/utils/strings.go +++ /dev/null @@ -1,11 +0,0 @@ -package utils - -// TrimLeftChar trims the left character from a string -func TrimLeftChar(s string) string { - for i := range s { - if i > 0 { - return s[i:] - } - } - return s[:0] -} diff --git a/pkg/test/utils/strings_test.go b/pkg/test/utils/strings_test.go deleted file mode 100644 index a6642241..00000000 --- a/pkg/test/utils/strings_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package utils - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestTrimLeftChar(t *testing.T) { - testMap := map[string]string{ - "": "", - "$": "", - "$NAMESPACE": "NAMESPACE", - "NAMESPACE": "AMESPACE", - } - for k, v := range testMap { - assert.Equal(t, v, TrimLeftChar(k)) - } -} From b9e4e4541f5eefa67cbb30f45722b87d9645092b Mon Sep 17 00:00:00 2001 From: Shawn O'Dell Date: Sun, 22 Jan 2023 16:48:37 -0600 Subject: [PATCH 5/9] simplify env expansion Co-authored-by: Chris Bandy Signed-off-by: Shawn O'Dell --- pkg/test/utils/translate.go | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/pkg/test/utils/translate.go b/pkg/test/utils/translate.go index cd634aac..0df230a0 100644 --- a/pkg/test/utils/translate.go +++ b/pkg/test/utils/translate.go @@ -3,7 +3,6 @@ package utils import ( "os" "reflect" - "strings" ) // Translate traverses an arbitrary struct and translates all strings it encounters @@ -13,7 +12,7 @@ import ( // // The MIT License (MIT) // -// Copyright (c) 2014 Heye Vöcking +// # Copyright (c) 2014 Heye Vöcking // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -95,14 +94,7 @@ func translateRecursive(copy, original reflect.Value) { // If it is a string translate it (yay finally we're doing what we came for) case reflect.String: - translatedString := original.Interface().(string) - if strings.HasPrefix(translatedString, "$") { - variable := translatedString[1:] - if val, ok := os.LookupEnv(variable); ok { - translatedString = val - } - } - copy.SetString(translatedString) + copy.SetString(os.ExpandEnv(original.Interface().(string))) // And everything else will simply be taken from the original default: From 68ecec15e185cb5305a71a5ea3d3ba3365fe0492 Mon Sep 17 00:00:00 2001 From: Shawn O'Dell Date: Sun, 22 Jan 2023 17:03:33 -0600 Subject: [PATCH 6/9] use t.Setenv Co-authored-by: Chris Bandy Signed-off-by: Shawn O'Dell --- pkg/test/utils/translate_test.go | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/pkg/test/utils/translate_test.go b/pkg/test/utils/translate_test.go index 202e3ded..8b53b3f7 100644 --- a/pkg/test/utils/translate_test.go +++ b/pkg/test/utils/translate_test.go @@ -3,7 +3,6 @@ package utils import ( "bytes" "fmt" - "os" "testing" "github.com/stretchr/testify/assert" @@ -23,13 +22,9 @@ func testDecoder(s string) *unstructured.Unstructured { func TestTranslate(t *testing.T) { namespace := "foo" - if err := os.Setenv("NAMESPACE", namespace); err != nil { - fmt.Println(err) - } - BAZ := "bar" - if err := os.Setenv("BAZ", BAZ); err != nil { - fmt.Println(err) - } + t.Setenv("NAMESPACE", namespace) + baz := "bar" + t.Setenv("BAZ", baz) manifestTemplate := ` apiVersion: example.com/v1 @@ -61,7 +56,7 @@ spec: key2: %s key2: key1: %s -`, namespace, BAZ, namespace) +`, namespace, baz, namespace) assert.Equal(t, fmt.Sprint(testDecoder(manifestTemplated)), fmt.Sprint(Translate(testDecoder(manifestTemplate)))) } From 1f4be625603f8281e6393b92620270c771daaf33 Mon Sep 17 00:00:00 2001 From: Shawn O'Dell Date: Mon, 23 Jan 2023 11:45:38 -0600 Subject: [PATCH 7/9] expand environmentt variables in the yaml Signed-off-by: Shawn O'Dell --- pkg/test/utils/kubernetes.go | 5 +- pkg/test/utils/kubernetes_test.go | 22 +++++++ pkg/test/utils/translate.go | 103 ------------------------------ pkg/test/utils/translate_test.go | 62 ------------------ 4 files changed, 25 insertions(+), 167 deletions(-) delete mode 100644 pkg/test/utils/translate.go delete mode 100644 pkg/test/utils/translate_test.go diff --git a/pkg/test/utils/kubernetes.go b/pkg/test/utils/kubernetes.go index 57f75ef7..668f5eae 100644 --- a/pkg/test/utils/kubernetes.go +++ b/pkg/test/utils/kubernetes.go @@ -508,6 +508,9 @@ func LoadYAML(path string, r io.Reader) ([]client.Object, error) { return nil, fmt.Errorf("error reading yaml %s: %w", path, err) } + // replace all variables from the environment + data = []byte(os.ExpandEnv(string(data))) + unstructuredObj := &unstructured.Unstructured{} decoder := yaml.NewYAMLOrJSONDecoder(bytes.NewBuffer(data), len(data)) @@ -515,8 +518,6 @@ func LoadYAML(path string, r io.Reader) ([]client.Object, error) { return nil, fmt.Errorf("error decoding yaml %s: %w", path, err) } - unstructuredObj.Object = Translate(unstructuredObj.Object).(map[string]interface{}) - obj, err := ConvertUnstructured(unstructuredObj) if err != nil { return nil, fmt.Errorf("error converting unstructured object %s (%s): %w", ResourceID(unstructuredObj), path, err) diff --git a/pkg/test/utils/kubernetes_test.go b/pkg/test/utils/kubernetes_test.go index 2cb1bdb1..e190ead8 100644 --- a/pkg/test/utils/kubernetes_test.go +++ b/pkg/test/utils/kubernetes_test.go @@ -5,6 +5,7 @@ import ( "context" "errors" "os" + "strconv" "testing" "time" @@ -182,6 +183,11 @@ spec: containers: - name: nginx image: nginx:1.7.9 + - name: app + image: app:$APP_VERSION + resources: + requests: + cpu: ${CPU_COUNT} --- apiVersion: v1 kind: Pod @@ -198,6 +204,13 @@ spec: t.Fatal(err) } + appVersion := "0.0.1-alpha" + t.Setenv("APP_VERSION", appVersion) + // test replacing a different type (int64 in this case) + // and nested values + cpuCount := int64(2) + t.Setenv("CPU_COUNT", strconv.Itoa(int(cpuCount))) + objs, err := LoadYAMLFromFile(tmpfile.Name()) assert.Nil(t, err) @@ -216,6 +229,15 @@ spec: "image": "nginx:1.7.9", "name": "nginx", }, + map[string]interface{}{ + "name": "app", + "image": "app:" + appVersion, + "resources": map[string]interface{}{ + "requests": map[string]interface{}{ + "cpu": cpuCount, + }, + }, + }, }, }, }, diff --git a/pkg/test/utils/translate.go b/pkg/test/utils/translate.go deleted file mode 100644 index 0df230a0..00000000 --- a/pkg/test/utils/translate.go +++ /dev/null @@ -1,103 +0,0 @@ -package utils - -import ( - "os" - "reflect" -) - -// Translate traverses an arbitrary struct and translates all strings it encounters -// replacing variable references with environment variables -// the pet name generator also sets the NAMESPACE env var (if not already set) so -// $NAMESPACE references *should* use the generated one -// -// The MIT License (MIT) -// -// # Copyright (c) 2014 Heye Vöcking -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -func Translate(obj interface{}) interface{} { - // Wrap the original in a reflect.Value - original := reflect.ValueOf(obj) - - copy := reflect.New(original.Type()).Elem() - translateRecursive(copy, original) - - // Remove the reflection wrapper - return copy.Interface() -} - -func translateRecursive(copy, original reflect.Value) { - switch original.Kind() { - // The first cases handle nested structures and translate them recursively - - // If it is a pointer we need to unwrap and call once again - case reflect.Ptr: - // To get the actual value of the original we have to call Elem() - // At the same time this unwraps the pointer so we don't end up in - // an infinite recursion - originalValue := original.Elem() - // Check if the pointer is nil - if !originalValue.IsValid() { - return - } - // Allocate a new object and set the pointer to it - copy.Set(reflect.New(originalValue.Type())) - // Unwrap the newly created pointer - translateRecursive(copy.Elem(), originalValue) - - // If it is an interface (which is very similar to a pointer), do basically the - // same as for the pointer. Though a pointer is not the same as an interface so - // note that we have to call Elem() after creating a new object because otherwise - // we would end up with an actual pointer - case reflect.Interface: - // Get rid of the wrapping interface - originalValue := original.Elem() - // Create a new object. Now new gives us a pointer, but we want the value it - // points to, so we have to call Elem() to unwrap it - copyValue := reflect.New(originalValue.Type()).Elem() - translateRecursive(copyValue, originalValue) - copy.Set(copyValue) - - // If it is a struct we translate each field - case reflect.Struct: - for i := 0; i < original.NumField(); i += 1 { - translateRecursive(copy.Field(i), original.Field(i)) - } - - // If it is a slice we create a new slice and translate each element - case reflect.Slice: - copy.Set(reflect.MakeSlice(original.Type(), original.Len(), original.Cap())) - for i := 0; i < original.Len(); i += 1 { - translateRecursive(copy.Index(i), original.Index(i)) - } - - // If it is a map we create a new map and translate each value - case reflect.Map: - copy.Set(reflect.MakeMap(original.Type())) - for _, key := range original.MapKeys() { - originalValue := original.MapIndex(key) - // New gives us a pointer, but again we want the value - copyValue := reflect.New(originalValue.Type()).Elem() - translateRecursive(copyValue, originalValue) - copy.SetMapIndex(key, copyValue) - } - - // Otherwise we cannot traverse anywhere so this finishes the the recursion - - // If it is a string translate it (yay finally we're doing what we came for) - case reflect.String: - copy.SetString(os.ExpandEnv(original.Interface().(string))) - - // And everything else will simply be taken from the original - default: - copy.Set(original) - } -} diff --git a/pkg/test/utils/translate_test.go b/pkg/test/utils/translate_test.go deleted file mode 100644 index 8b53b3f7..00000000 --- a/pkg/test/utils/translate_test.go +++ /dev/null @@ -1,62 +0,0 @@ -package utils - -import ( - "bytes" - "fmt" - "testing" - - "github.com/stretchr/testify/assert" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/util/yaml" -) - -func testDecoder(s string) *unstructured.Unstructured { - b := []byte(s) - d := yaml.NewYAMLOrJSONDecoder(bytes.NewBuffer(b), len(b)) - u := &unstructured.Unstructured{} - if err := d.Decode(u); err != nil { - fmt.Println(err) - } - return u -} - -func TestTranslate(t *testing.T) { - namespace := "foo" - t.Setenv("NAMESPACE", namespace) - baz := "bar" - t.Setenv("BAZ", baz) - - manifestTemplate := ` -apiVersion: example.com/v1 -kind: CustomResource -metadata: - name: test - namespace: $NAMESPACE -status: - ready: true -spec: - key1: - key1: data - key2: $BAZ - key2: - key1: "$NAMESPACE" -` - - manifestTemplated := fmt.Sprintf(` -apiVersion: example.com/v1 -kind: CustomResource -metadata: - name: test - namespace: %s -status: - ready: true -spec: - key1: - key1: data - key2: %s - key2: - key1: %s -`, namespace, baz, namespace) - - assert.Equal(t, fmt.Sprint(testDecoder(manifestTemplated)), fmt.Sprint(Translate(testDecoder(manifestTemplate)))) -} From 57a72e09103fbc1b2839f21e346851fb69ad15c6 Mon Sep 17 00:00:00 2001 From: Shawn O'Dell Date: Mon, 23 Jan 2023 14:49:31 -0600 Subject: [PATCH 8/9] use t.tmpdir and add more tests Signed-off-by: Shawn O'Dell --- pkg/test/utils/kubernetes_test.go | 39 +++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/pkg/test/utils/kubernetes_test.go b/pkg/test/utils/kubernetes_test.go index e190ead8..6b04aa1a 100644 --- a/pkg/test/utils/kubernetes_test.go +++ b/pkg/test/utils/kubernetes_test.go @@ -169,7 +169,8 @@ func TestRetryWithTimeout(t *testing.T) { } func TestLoadYAML(t *testing.T) { - tmpfile, err := os.CreateTemp("", "test.yaml") + tmpDir := t.TempDir() + tmpfile, err := os.CreateTemp(tmpDir, "test.yaml") assert.Nil(t, err) defer tmpfile.Close() @@ -199,6 +200,14 @@ spec: containers: - name: nginx image: nginx:1.7.9 +--- +apiVersion: $GROUP_VERSION +kind: $KIND +metadata: + name: hello +spec: + config: + $KEY_VAR: bar `), 0600) if err != nil { t.Fatal(err) @@ -211,6 +220,16 @@ spec: cpuCount := int64(2) t.Setenv("CPU_COUNT", strconv.Itoa(int(cpuCount))) + // test GVK + groupVersion := "example.com/v1" + t.Setenv("GROUP_VERSION", groupVersion) + kind := "custom" + t.Setenv("KIND", kind) + + // key update + keyVar := "baz" + t.Setenv("KEY_VAR", keyVar) + objs, err := LoadYAMLFromFile(tmpfile.Name()) assert.Nil(t, err) @@ -263,10 +282,26 @@ spec: }, }, }, objs[1]) + + assert.Equal(t, &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": groupVersion, + "kind": kind, + "metadata": map[string]interface{}{ + "name": "hello", + }, + "spec": map[string]interface{}{ + "config": map[string]interface{}{ + keyVar: "bar", + }, + }, + }, + }, objs[2]) } func TestMatchesKind(t *testing.T) { - tmpfile, err := os.CreateTemp("", "test.yaml") + tmpDir := t.TempDir() + tmpfile, err := os.CreateTemp(tmpDir, "test.yaml") assert.Nil(t, err) defer tmpfile.Close() From fb20595dc6b8b4c57febba74d9ede4488c3ef7c6 Mon Sep 17 00:00:00 2001 From: Shawn O'Dell Date: Wed, 21 Jun 2023 17:38:18 -0500 Subject: [PATCH 9/9] Update pkg/test/case.go Signed-off-by: Shawn O'Dell --- pkg/test/case.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/test/case.go b/pkg/test/case.go index ef20fb44..d0b572bc 100644 --- a/pkg/test/case.go +++ b/pkg/test/case.go @@ -387,7 +387,7 @@ func (t *Case) determineNamespace() *namespace { ns.AutoCreated = true } - if _, ok := os.LookupEnv("NAMESPACE"); ok { // user can supply this environment variable + if _, ok := os.LookupEnv("NAMESPACE"); !ok { // user can supply this environment variable os.Setenv("NAMESPACE", t.PreferredNamespace) // set this environment variable so it can be templated by other 'steps' } // if we have a preferred namespace, we do NOT auto-create