diff --git a/internal/k8sdeps/hash.go b/internal/k8sdeps/hash.go index fcdd353cb..7bf8606c5 100644 --- a/internal/k8sdeps/hash.go +++ b/internal/k8sdeps/hash.go @@ -54,7 +54,7 @@ func (h *KustHash) Hash(m map[string]interface{}) (string, error) { } return SecretHash(sec) default: - return "", fmt.Errorf("Type %s is supported for hashing in %v", kind, m) + return "", fmt.Errorf("type %s is supported for hashing in %v", kind, m) } } diff --git a/internal/k8sdeps/unstructadapter.go b/internal/k8sdeps/unstructadapter.go new file mode 100644 index 000000000..11e4a3fd9 --- /dev/null +++ b/internal/k8sdeps/unstructadapter.go @@ -0,0 +1,118 @@ +package k8sdeps + +import ( + "encoding/json" + "fmt" + "io" + "strings" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/kustomize/pkg/gvk" + "sigs.k8s.io/kustomize/pkg/ifc" +) + +var _ ifc.Kunstructured = &UnstructAdapter{} + +// UnstructAdapter wraps unstructured.Unstructured from +// https://github.com/kubernetes/apimachinery/blob/master/ +// pkg/apis/meta/v1/unstructured/unstructured.go +// to isolate dependence on apimachinery. +type UnstructAdapter struct { + unstructured.Unstructured +} + +// NewKunstructuredFromObject returns a new instance of Kunstructured. +func NewKunstructuredFromObject(obj runtime.Object) (ifc.Kunstructured, error) { + // Convert obj to a byte stream, then convert that to JSON (Unstructured). + marshaled, err := json.Marshal(obj) + if err != nil { + return &UnstructAdapter{}, err + } + var u unstructured.Unstructured + err = u.UnmarshalJSON(marshaled) + // creationTimestamp always 'null', remove it + u.SetCreationTimestamp(metav1.Time{}) + return &UnstructAdapter{Unstructured: u}, err +} + +// NewKunstructuredFromMap returns a new instance of Kunstructured. +func NewKunstructuredFromMap(m map[string]interface{}) ifc.Kunstructured { + return NewKunstructuredFromUnstruct(unstructured.Unstructured{Object: m}) +} + +// NewKunstructuredFromUnstruct returns a new instance of Kunstructured. +func NewKunstructuredFromUnstruct(u unstructured.Unstructured) ifc.Kunstructured { + return &UnstructAdapter{Unstructured: u} +} + +// NewKunstructuredSliceFromBytes unmarshalls bytes into a Kunstructured slice. +func NewKunstructuredSliceFromBytes( + in []byte, decoder ifc.Decoder) ([]ifc.Kunstructured, error) { + decoder.SetInput(in) + var result []ifc.Kunstructured + var err error + for err == nil || isEmptyYamlError(err) { + var out unstructured.Unstructured + err = decoder.Decode(&out) + if err == nil { + result = append(result, &UnstructAdapter{Unstructured: out}) + } + } + if err != io.EOF { + return nil, err + } + return result, nil +} + +// GetGvk returns the Gvk name of the object. +func (fs *UnstructAdapter) GetGvk() gvk.Gvk { + return gvk.FromSchemaGvk(fs.GroupVersionKind()) +} + +// Copy provides a copy behind an interface. +func (fs *UnstructAdapter) Copy() ifc.Kunstructured { + return &UnstructAdapter{*fs.DeepCopy()} +} + +// Map returns the unstructured content map. +func (fs *UnstructAdapter) Map() map[string]interface{} { + return fs.Object +} + +// SetMap overrides the unstructured content map. +func (fs *UnstructAdapter) SetMap(m map[string]interface{}) { + fs.Object = m +} + +// GetFieldValue returns value at the given fieldpath. +func (fs *UnstructAdapter) GetFieldValue(fieldPath string) (string, error) { + return getFieldValue(fs.UnstructuredContent(), strings.Split(fieldPath, ".")) +} + +func getFieldValue(m map[string]interface{}, pathToField []string) (string, error) { + if len(pathToField) == 0 { + return "", fmt.Errorf("field not found") + } + if len(pathToField) == 1 { + if v, found := m[pathToField[0]]; found { + if s, ok := v.(string); ok { + return s, nil + } + return "", fmt.Errorf("value at fieldpath is not of string type") + } + return "", fmt.Errorf("field at given fieldpath does not exist") + } + v := m[pathToField[0]] + switch typedV := v.(type) { + case map[string]interface{}: + return getFieldValue(typedV, pathToField[1:]) + default: + return "", fmt.Errorf("%#v is not expected to be a primitive type", typedV) + } +} + +func isEmptyYamlError(err error) bool { + return strings.Contains(err.Error(), "is missing in 'null'") +} diff --git a/internal/k8sdeps/unstructadapter_test.go b/internal/k8sdeps/unstructadapter_test.go new file mode 100644 index 000000000..dabb4e409 --- /dev/null +++ b/internal/k8sdeps/unstructadapter_test.go @@ -0,0 +1,162 @@ +package k8sdeps + +import ( + "reflect" + "sigs.k8s.io/kustomize/pkg/ifc" + "testing" +) + +var testConfigMap = NewKunstructuredFromMap( + map[string]interface{}{ + "apiVersion": "v1", + "kind": "ConfigMap", + "metadata": map[string]interface{}{ + "name": "winnie", + }, + }) + +func TestNewKunstructuredSliceFromBytes(t *testing.T) { + tests := []struct { + name string + input []byte + expectedOut []ifc.Kunstructured + expectedErr bool + }{ + { + name: "garbage", + input: []byte("garbageIn: garbageOut"), + expectedOut: []ifc.Kunstructured{}, + expectedErr: true, + }, + { + name: "noBytes", + input: []byte{}, + expectedOut: []ifc.Kunstructured{}, + expectedErr: false, + }, + { + name: "goodJson", + input: []byte(` +{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie"}} +`), + expectedOut: []ifc.Kunstructured{testConfigMap}, + expectedErr: false, + }, + { + name: "goodYaml1", + input: []byte(` +apiVersion: v1 +kind: ConfigMap +metadata: + name: winnie +`), + expectedOut: []ifc.Kunstructured{testConfigMap}, + expectedErr: false, + }, + { + name: "goodYaml2", + input: []byte(` +apiVersion: v1 +kind: ConfigMap +metadata: + name: winnie +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: winnie +`), + expectedOut: []ifc.Kunstructured{testConfigMap, testConfigMap}, + expectedErr: false, + }, + { + name: "garbageInOneOfTwoObjects", + input: []byte(` +apiVersion: v1 +kind: ConfigMap +metadata: + name: winnie +--- +WOOOOOOOOOOOOOOOOOOOOOOOOT: woot +`), + expectedOut: []ifc.Kunstructured{}, + expectedErr: true, + }, + } + + for _, test := range tests { + rs, err := NewKunstructuredSliceFromBytes( + test.input, NewKustDecoder()) + if test.expectedErr && err == nil { + t.Fatalf("%v: should return error", test.name) + } + if !test.expectedErr && err != nil { + t.Fatalf("%v: unexpected error: %s", test.name, err) + } + if len(rs) != len(test.expectedOut) { + t.Fatalf("%s: length mismatch %d != %d", + test.name, len(rs), len(test.expectedOut)) + } + for i := range rs { + if !reflect.DeepEqual(test.expectedOut[i], rs[i]) { + t.Fatalf("%s: Got: %v\nexpected:%v", + test.name, test.expectedOut[i], rs[i]) + } + } + } +} + +func TestGetFieldValue(t *testing.T) { + funStruct := NewKunstructuredFromMap(map[string]interface{}{ + "Kind": "Service", + "metadata": map[string]interface{}{ + "labels": map[string]string{ + "app": "application-name", + }, + "name": "service-name", + }, + "spec": map[string]interface{}{ + "ports": map[string]interface{}{ + "port": "80", + }, + }, + }) + + tests := []struct { + pathToField string + expectedValue string + errorExpected bool + }{ + { + pathToField: "Kind", + expectedValue: "Service", + errorExpected: false, + }, + { + pathToField: "metadata.name", + expectedValue: "service-name", + errorExpected: false, + }, + { + pathToField: "metadata.non-existing-field", + expectedValue: "", + errorExpected: true, + }, + { + pathToField: "spec.ports.port", + expectedValue: "80", + errorExpected: false, + }, + } + + for _, test := range tests { + s, err := funStruct.GetFieldValue(test.pathToField) + if test.errorExpected && err == nil { + t.Fatalf("should return error, but no error returned") + } else { + if test.expectedValue != s { + t.Fatalf("Got:%s expected:%s", s, test.expectedValue) + } + } + } +} diff --git a/pkg/commands/build/build_test.go b/pkg/commands/build/build_test.go index f3c05328c..7458fc8fe 100644 --- a/pkg/commands/build/build_test.go +++ b/pkg/commands/build/build_test.go @@ -104,7 +104,10 @@ func TestBuild(t *testing.T) { } for _, testcaseName := range testcases { - t.Run(testcaseName, func(t *testing.T) { runBuildTestCase(t, testcaseName, updateKustomizeExpected, fSys) }) + t.Run(testcaseName, + func(t *testing.T) { + runBuildTestCase(t, testcaseName, updateKustomizeExpected, fSys) + }) } } diff --git a/pkg/configmapandsecret/configmapfactory_test.go b/pkg/configmapandsecret/configmapfactory_test.go index 2b7514365..579353dda 100644 --- a/pkg/configmapandsecret/configmapfactory_test.go +++ b/pkg/configmapandsecret/configmapfactory_test.go @@ -22,7 +22,6 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "sigs.k8s.io/kustomize/pkg/fs" "sigs.k8s.io/kustomize/pkg/loader" "sigs.k8s.io/kustomize/pkg/types" @@ -44,22 +43,6 @@ func makeEnvConfigMap(name string) *corev1.ConfigMap { } } -func makeUnstructuredEnvConfigMap(name string) *unstructured.Unstructured { - return &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": "v1", - "kind": "ConfigMap", - "metadata": map[string]interface{}{ - "name": name, - }, - "data": map[string]interface{}{ - "DB_USERNAME": "admin", - "DB_PASSWORD": "somepw", - }, - }, - } -} - func makeFileConfigMap(name string) *corev1.ConfigMap { return &corev1.ConfigMap{ TypeMeta: metav1.TypeMeta{ diff --git a/pkg/ifc/ifc.go b/pkg/ifc/ifc.go index b5071c5b0..c4a00ba12 100644 --- a/pkg/ifc/ifc.go +++ b/pkg/ifc/ifc.go @@ -17,6 +17,8 @@ limitations under the License. // Package ifc holds miscellaneous interfaces used by kustomize. package ifc +import "sigs.k8s.io/kustomize/pkg/gvk" + // Decoder unmarshalls byte input into an object. type Decoder interface { // SetInput accepts new input. @@ -48,3 +50,22 @@ type Loader interface { type Hash interface { Hash(m map[string]interface{}) (string, error) } + +// Kunstructured allows manipulation of k8s objects +// that do not have Golang structs. +type Kunstructured interface { + Map() map[string]interface{} + SetMap(map[string]interface{}) + Copy() Kunstructured + GetFieldValue(string) (string, error) + MarshalJSON() ([]byte, error) + UnmarshalJSON([]byte) error + GetGvk() gvk.Gvk + GetKind() string + GetName() string + SetName(string) + GetLabels() map[string]string + SetLabels(map[string]string) + GetAnnotations() map[string]string + SetAnnotations(map[string]string) +} diff --git a/pkg/patch/transformer/factory_test.go b/pkg/patch/transformer/factory_test.go index 8fd7eb0ed..5791c2ba5 100644 --- a/pkg/patch/transformer/factory_test.go +++ b/pkg/patch/transformer/factory_test.go @@ -182,7 +182,7 @@ func TestNewPatchJson6902FactoryMulti(t *testing.T) { id := resid.NewResId(gvk.FromKind("foo"), "some-name") base := resmap.ResMap{ - id: resource.NewResourceFromMap( + id: resource.NewFromMap( map[string]interface{}{ "kind": "foo", "metadata": map[string]interface{}{ @@ -208,7 +208,7 @@ func TestNewPatchJson6902FactoryMulti(t *testing.T) { }), } expected := resmap.ResMap{ - id: resource.NewResourceFromMap( + id: resource.NewFromMap( map[string]interface{}{ "kind": "foo", "metadata": map[string]interface{}{ @@ -296,7 +296,7 @@ func TestNewPatchJson6902FactoryMultiConflict(t *testing.T) { id := resid.NewResId(gvk.FromKind("foo"), "some-name") base := resmap.ResMap{ - id: resource.NewResourceFromMap( + id: resource.NewFromMap( map[string]interface{}{ "kind": "foo", "metadata": map[string]interface{}{ diff --git a/pkg/patch/transformer/patchjson6902json.go b/pkg/patch/transformer/patchjson6902json.go index 11bfa2280..6737b959c 100644 --- a/pkg/patch/transformer/patchjson6902json.go +++ b/pkg/patch/transformer/patchjson6902json.go @@ -45,7 +45,7 @@ func (t *patchJson6902JSONTransformer) Transform(baseResourceMap resmap.ResMap) if obj == nil { return err } - rawObj, err := obj.Unstructured.MarshalJSON() + rawObj, err := obj.MarshalJSON() if err != nil { return err } diff --git a/pkg/patch/transformer/patchjson6902json_test.go b/pkg/patch/transformer/patchjson6902json_test.go index 3d5e2d8ad..5be44f339 100644 --- a/pkg/patch/transformer/patchjson6902json_test.go +++ b/pkg/patch/transformer/patchjson6902json_test.go @@ -32,7 +32,7 @@ var deploy = gvk.Gvk{Group: "apps", Version: "v1", Kind: "Deployment"} func TestJsonPatchJSONTransformer_Transform(t *testing.T) { id := resid.NewResId(deploy, "deploy1") base := resmap.ResMap{ - id: resource.NewResourceFromMap( + id: resource.NewFromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -69,7 +69,7 @@ func TestJsonPatchJSONTransformer_Transform(t *testing.T) { t.Fatalf("unexpected error : %v", err) } expected := resmap.ResMap{ - id: resource.NewResourceFromMap( + id: resource.NewFromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", diff --git a/pkg/resmap/configmap.go b/pkg/resmap/configmap.go index 8c0efba13..05b8da92e 100644 --- a/pkg/resmap/configmap.go +++ b/pkg/resmap/configmap.go @@ -37,7 +37,7 @@ func NewResMapFromConfigMapArgs( if err != nil { return nil, err } - res, err := resource.NewResourceWithBehavior( + res, err := resource.NewWithBehavior( cm, ifc.NewGenerationBehavior(cmArgs.Behavior)) if err != nil { return nil, err diff --git a/pkg/resmap/configmap_test.go b/pkg/resmap/configmap_test.go index 07914ea5b..fdf67a14b 100644 --- a/pkg/resmap/configmap_test.go +++ b/pkg/resmap/configmap_test.go @@ -57,7 +57,7 @@ func TestNewFromConfigMaps(t *testing.T) { filepath: "/home/seans/project/app.env", content: "DB_USERNAME=admin\nDB_PASSWORD=somepw", expected: ResMap{ - resid.NewResId(cmap, "envConfigMap"): resource.NewResourceFromMap( + resid.NewResId(cmap, "envConfigMap"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -83,7 +83,7 @@ func TestNewFromConfigMaps(t *testing.T) { filepath: "/home/seans/project/app-init.ini", content: "FOO=bar\nBAR=baz\n", expected: ResMap{ - resid.NewResId(cmap, "fileConfigMap"): resource.NewResourceFromMap( + resid.NewResId(cmap, "fileConfigMap"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -109,7 +109,7 @@ BAR=baz }, }, expected: ResMap{ - resid.NewResId(cmap, "literalConfigMap"): resource.NewResourceFromMap( + resid.NewResId(cmap, "literalConfigMap"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", diff --git a/pkg/resmap/resmap.go b/pkg/resmap/resmap.go index f40f0d475..29c7dedbe 100644 --- a/pkg/resmap/resmap.go +++ b/pkg/resmap/resmap.go @@ -68,7 +68,7 @@ func (m ResMap) EncodeAsYaml() ([]byte, error) { buf := bytes.NewBuffer(b) for _, id := range ids { obj := m[id] - out, err := yaml.Marshal(obj) + out, err := yaml.Marshal(obj.Map()) if err != nil { return nil, err } @@ -117,7 +117,7 @@ func (m ResMap) ErrorIfNotEqual(m2 ResMap) error { func (m ResMap) DeepCopy() ResMap { mcopy := make(ResMap) for id, obj := range m { - mcopy[id] = resource.NewResourceFromUnstruct(obj.Unstructured) + mcopy[id] = resource.NewFromKunstructured(obj.Copy()) mcopy[id].SetBehavior(obj.Behavior()) } return mcopy @@ -156,7 +156,7 @@ func NewResMapFromFiles( // newResMapFromBytes decodes a list of objects in byte array format. func newResMapFromBytes(b []byte, d ifc.Decoder) (ResMap, error) { - resources, err := resource.NewResourceSliceFromBytes(b, d) + resources, err := resource.NewSliceFromBytes(b, d) if err != nil { return nil, err } @@ -227,15 +227,18 @@ func MergeWithOverride(maps ...ResMap) (ResMap, error) { id = matchedId[0] switch r.Behavior() { case ifc.BehaviorReplace: - glog.V(4).Infof("Replace %v with %v", result[id].Object, r.Object) + glog.V(4).Infof( + "Replace %v with %v", result[id].Map(), r.Map()) r.Replace(result[id]) result[id] = r result[id].SetBehavior(ifc.BehaviorCreate) case ifc.BehaviorMerge: - glog.V(4).Infof("Merging %v with %v", result[id].Object, r.Object) + glog.V(4).Infof( + "Merging %v with %v", result[id].Map(), r.Map()) r.Merge(result[id]) result[id] = r - glog.V(4).Infof("Merged object is %v", result[id].Object) + glog.V(4).Infof( + "Merged object is %v", result[id].Map()) result[id].SetBehavior(ifc.BehaviorCreate) default: return nil, fmt.Errorf("id %#v exists; must merge or replace", id) diff --git a/pkg/resmap/resmap_test.go b/pkg/resmap/resmap_test.go index fcde0294a..d3653e31c 100644 --- a/pkg/resmap/resmap_test.go +++ b/pkg/resmap/resmap_test.go @@ -44,7 +44,7 @@ metadata: name: cm2 `) input := ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -52,7 +52,7 @@ metadata: "name": "cm1", }, }), - resid.NewResId(cmap, "cm2"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm2"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -72,7 +72,7 @@ metadata: func TestDemandOneMatchForId(t *testing.T) { rm1 := ResMap{ - resid.NewResIdWithPrefixNamespace(cmap, "cm1", "prefix1", "ns1"): resource.NewResourceFromMap( + resid.NewResIdWithPrefixNamespace(cmap, "cm1", "prefix1", "ns1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -80,7 +80,7 @@ func TestDemandOneMatchForId(t *testing.T) { "name": "cm1", }, }), - resid.NewResIdWithPrefixNamespace(cmap, "cm2", "prefix1", "ns1"): resource.NewResourceFromMap( + resid.NewResIdWithPrefixNamespace(cmap, "cm2", "prefix1", "ns1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -118,7 +118,7 @@ func TestDemandOneMatchForId(t *testing.T) { } func TestFilterBy(t *testing.T) { - rm := ResMap{resid.NewResIdWithPrefixNamespace(cmap, "cm1", "prefix1", "ns1"): resource.NewResourceFromMap( + rm := ResMap{resid.NewResIdWithPrefixNamespace(cmap, "cm1", "prefix1", "ns1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -126,7 +126,7 @@ func TestFilterBy(t *testing.T) { "name": "cm1", }, }), - resid.NewResIdWithPrefixNamespace(cmap, "cm2", "prefix1", "ns1"): resource.NewResourceFromMap( + resid.NewResIdWithPrefixNamespace(cmap, "cm2", "prefix1", "ns1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -136,7 +136,7 @@ func TestFilterBy(t *testing.T) { }), } rm1 := ResMap{ - resid.NewResIdWithPrefixNamespace(cmap, "cm3", "prefix1", "ns2"): resource.NewResourceFromMap( + resid.NewResIdWithPrefixNamespace(cmap, "cm3", "prefix1", "ns2"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -162,7 +162,7 @@ func TestFilterBy(t *testing.T) { } func TestDeepCopy(t *testing.T) { rm1 := ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -170,7 +170,7 @@ func TestDeepCopy(t *testing.T) { "name": "cm1", }, }), - resid.NewResId(cmap, "cm2"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm2"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -194,7 +194,7 @@ func TestDeepCopy(t *testing.T) { func TestErrorIfNotEqual(t *testing.T) { rm1 := ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -202,7 +202,7 @@ func TestErrorIfNotEqual(t *testing.T) { "name": "cm1", }, }), - resid.NewResId(cmap, "cm2"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm2"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -218,7 +218,7 @@ func TestErrorIfNotEqual(t *testing.T) { } rm2 := ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -235,7 +235,7 @@ func TestErrorIfNotEqual(t *testing.T) { } rm3 := ResMap{ - resid.NewResId(cmap, "cm2"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm2"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -252,7 +252,7 @@ func TestErrorIfNotEqual(t *testing.T) { } rm4 := ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -291,7 +291,7 @@ metadata: if ferr := l.AddFile("/home/seans/project/deployment.yaml", []byte(resourceStr)); ferr != nil { t.Fatalf("Error adding fake file: %v\n", ferr) } - expected := ResMap{resid.NewResId(deploy, "dply1"): resource.NewResourceFromMap( + expected := ResMap{resid.NewResId(deploy, "dply1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -299,7 +299,7 @@ metadata: "name": "dply1", }, }), - resid.NewResId(deploy, "dply2"): resource.NewResourceFromMap( + resid.NewResId(deploy, "dply2"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -333,7 +333,7 @@ metadata: name: cm2 `) expected := ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -341,7 +341,7 @@ metadata: "name": "cm1", }, }), - resid.NewResId(cmap, "cm2"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm2"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -362,7 +362,7 @@ metadata: func TestMergeWithoutOverride(t *testing.T) { input1 := ResMap{ - resid.NewResId(deploy, "deploy1"): resource.NewResourceFromMap( + resid.NewResId(deploy, "deploy1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -372,7 +372,7 @@ func TestMergeWithoutOverride(t *testing.T) { }), } input2 := ResMap{ - resid.NewResId(statefulset, "stateful1"): resource.NewResourceFromMap( + resid.NewResId(statefulset, "stateful1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "StatefulSet", @@ -383,7 +383,7 @@ func TestMergeWithoutOverride(t *testing.T) { } input := []ResMap{input1, input2} expected := ResMap{ - resid.NewResId(deploy, "deploy1"): resource.NewResourceFromMap( + resid.NewResId(deploy, "deploy1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -391,7 +391,7 @@ func TestMergeWithoutOverride(t *testing.T) { "name": "foo-deploy1", }, }), - resid.NewResId(statefulset, "stateful1"): resource.NewResourceFromMap( + resid.NewResId(statefulset, "stateful1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "StatefulSet", @@ -428,7 +428,7 @@ func TestMergeWithoutOverride(t *testing.T) { func generateMergeFixtures(b ifc.GenerationBehavior) []ResMap { input1 := ResMap{ - resid.NewResId(cmap, "cmap"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cmap"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "ConfigMap", @@ -442,7 +442,7 @@ func generateMergeFixtures(b ifc.GenerationBehavior) []ResMap { }), } input2 := ResMap{ - resid.NewResId(cmap, "cmap"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cmap"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "ConfigMap", @@ -463,7 +463,7 @@ func generateMergeFixtures(b ifc.GenerationBehavior) []ResMap { func TestMergeWithOverride(t *testing.T) { expected := ResMap{ - resid.NewResId(cmap, "cmap"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cmap"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "ConfigMap", diff --git a/pkg/resmap/secret.go b/pkg/resmap/secret.go index cdfa97d87..06e27f8c3 100644 --- a/pkg/resmap/secret.go +++ b/pkg/resmap/secret.go @@ -38,10 +38,10 @@ func NewResMapFromSecretArgs( if args.Behavior == "" { args.Behavior = "create" } - res, err := resource.NewResourceWithBehavior( + res, err := resource.NewWithBehavior( s, ifc.NewGenerationBehavior(args.Behavior)) if err != nil { - return nil, errors.Wrap(err, "NewResourceWithBehavior") + return nil, errors.Wrap(err, "NewWithBehavior") } allResources = append(allResources, res) } diff --git a/pkg/resmap/secret_test.go b/pkg/resmap/secret_test.go index ef4825a44..53242b6f3 100644 --- a/pkg/resmap/secret_test.go +++ b/pkg/resmap/secret_test.go @@ -63,7 +63,7 @@ func TestNewResMapFromSecretArgs(t *testing.T) { } expected := ResMap{ - resid.NewResId(secret, "apple"): resource.NewResourceFromMap( + resid.NewResId(secret, "apple"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", @@ -76,7 +76,7 @@ func TestNewResMapFromSecretArgs(t *testing.T) { "DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")), }, }).SetBehavior(ifc.BehaviorCreate), - resid.NewResId(secret, "peanuts"): resource.NewResourceFromMap( + resid.NewResId(secret, "peanuts"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", diff --git a/pkg/resource/resource.go b/pkg/resource/resource.go index 0229999d1..9ef6683b1 100644 --- a/pkg/resource/resource.go +++ b/pkg/resource/resource.go @@ -18,55 +18,48 @@ limitations under the License. package resource import ( - "encoding/json" - "fmt" - "io" + "log" "strings" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - "sigs.k8s.io/kustomize/pkg/gvk" + "sigs.k8s.io/kustomize/internal/k8sdeps" "sigs.k8s.io/kustomize/pkg/ifc" internal "sigs.k8s.io/kustomize/pkg/internal/error" "sigs.k8s.io/kustomize/pkg/patch" "sigs.k8s.io/kustomize/pkg/resid" ) -// Resource is an "Unstructured" (json/map form) Kubernetes API resource object +// Resource is map representation of a Kubernetes API resource object // paired with a GenerationBehavior. type Resource struct { - unstructured.Unstructured + ifc.Kunstructured b ifc.GenerationBehavior } -// NewResourceWithBehavior returns a new instance of Resource. -func NewResourceWithBehavior(obj runtime.Object, b ifc.GenerationBehavior) (*Resource, error) { - // Convert obj to a byte stream, then convert that to JSON (Unstructured). - marshaled, err := json.Marshal(obj) - if err != nil { - return nil, err +// NewWithBehavior returns a new instance of Resource. +func NewWithBehavior(obj runtime.Object, b ifc.GenerationBehavior) (*Resource, error) { + u, err := k8sdeps.NewKunstructuredFromObject(obj) + return &Resource{Kunstructured: u, b: b}, err +} + +// NewFromMap returns a new instance of Resource. +func NewFromMap(m map[string]interface{}) *Resource { + return &Resource{ + Kunstructured: k8sdeps.NewKunstructuredFromMap(m), + b: ifc.BehaviorUnspecified} +} + +// NewFromKunstructured returns a new instance of Resource. +func NewFromKunstructured(u ifc.Kunstructured) *Resource { + if u == nil { + log.Fatal("unstruct ifc must not be null") } - var u unstructured.Unstructured - err = u.UnmarshalJSON(marshaled) - // creationTimestamp always 'null', remove it - u.SetCreationTimestamp(metav1.Time{}) - return &Resource{Unstructured: u, b: b}, err + return &Resource{Kunstructured: u, b: ifc.BehaviorUnspecified} } -// NewResourceFromMap returns a new instance of Resource. -func NewResourceFromMap(m map[string]interface{}) *Resource { - return NewResourceFromUnstruct(unstructured.Unstructured{Object: m}) -} - -// NewResourceFromUnstruct returns a new instance of Resource. -func NewResourceFromUnstruct(u unstructured.Unstructured) *Resource { - return &Resource{Unstructured: u, b: ifc.BehaviorUnspecified} -} - -// NewResourceSliceFromPatches returns a slice of resources given a patch path +// NewSliceFromPatches returns a slice of resources given a patch path // slice from a kustomization file. -func NewResourceSliceFromPatches( +func NewSliceFromPatches( ldr ifc.Loader, paths []patch.StrategicMerge, decoder ifc.Decoder) ([]*Resource, error) { var result []*Resource @@ -75,7 +68,7 @@ func NewResourceSliceFromPatches( if err != nil { return nil, err } - res, err := NewResourceSliceFromBytes(content, decoder) + res, err := NewSliceFromBytes(content, decoder) if err != nil { return nil, internal.Handler(err, string(path)) } @@ -84,29 +77,20 @@ func NewResourceSliceFromPatches( return result, nil } -// NewResourceSliceFromBytes unmarshalls bytes into a Resource slice. -func NewResourceSliceFromBytes( +// NewSliceFromBytes unmarshalls bytes into a Resource slice. +func NewSliceFromBytes( in []byte, decoder ifc.Decoder) ([]*Resource, error) { - decoder.SetInput(in) - var result []*Resource - var err error - for err == nil || isEmptyYamlError(err) { - var out unstructured.Unstructured - err = decoder.Decode(&out) - if err == nil { - result = append(result, NewResourceFromUnstruct(out)) - } - } - if err != io.EOF { + funStructs, err := k8sdeps.NewKunstructuredSliceFromBytes(in, decoder) + if err != nil { return nil, err } + var result []*Resource + for _, u := range funStructs { + result = append(result, NewFromKunstructured(u)) + } return result, nil } -func isEmptyYamlError(err error) bool { - return strings.Contains(err.Error(), "is missing in 'null'") -} - // String returns resource as JSON. func (r *Resource) String() string { bs, err := r.MarshalJSON() @@ -134,24 +118,27 @@ func (r *Resource) IsGenerated() bool { // Id returns the ResId for the resource. func (r *Resource) Id() resid.ResId { - return resid.NewResId(gvk.FromSchemaGvk(r.GroupVersionKind()), r.GetName()) + return resid.NewResId(r.GetGvk(), r.GetName()) } // Merge performs merge with other resource. func (r *Resource) Merge(other *Resource) { r.Replace(other) - mergeConfigmap(r.Object, other.Object, r.Object) + mergeConfigmap(r.Map(), other.Map(), r.Map()) } // Replace performs replace with other resource. func (r *Resource) Replace(other *Resource) { r.SetLabels(mergeStringMaps(other.GetLabels(), r.GetLabels())) - r.SetAnnotations(mergeStringMaps(other.GetAnnotations(), r.GetAnnotations())) + r.SetAnnotations( + mergeStringMaps(other.GetAnnotations(), r.GetAnnotations())) r.SetName(other.GetName()) } // TODO: Add BinaryData once we sync to new k8s.io/api -func mergeConfigmap(mergedTo map[string]interface{}, maps ...map[string]interface{}) { +func mergeConfigmap( + mergedTo map[string]interface{}, + maps ...map[string]interface{}) { mergedMap := map[string]interface{}{} for _, m := range maps { datamap, ok := m["data"].(map[string]interface{}) @@ -173,30 +160,3 @@ func mergeStringMaps(maps ...map[string]string) map[string]string { } return result } - -// GetFieldValue returns value at the given fieldpath. -func (r *Resource) GetFieldValue(fieldPath string) (string, error) { - return getFieldValue(r.UnstructuredContent(), strings.Split(fieldPath, ".")) -} - -func getFieldValue(m map[string]interface{}, pathToField []string) (string, error) { - if len(pathToField) == 0 { - return "", fmt.Errorf("field not found") - } - if len(pathToField) == 1 { - if v, found := m[pathToField[0]]; found { - if s, ok := v.(string); ok { - return s, nil - } - return "", fmt.Errorf("value at fieldpath is not of string type") - } - return "", fmt.Errorf("field at given fieldpath does not exist") - } - v := m[pathToField[0]] - switch typedV := v.(type) { - case map[string]interface{}: - return getFieldValue(typedV, pathToField[1:]) - default: - return "", fmt.Errorf("%#v is not expected to be a primitive type", typedV) - } -} diff --git a/pkg/resource/resource_test.go b/pkg/resource/resource_test.go index 10a610933..500ec04ba 100644 --- a/pkg/resource/resource_test.go +++ b/pkg/resource/resource_test.go @@ -25,7 +25,7 @@ import ( "sigs.k8s.io/kustomize/pkg/patch" ) -var testConfigMap = NewResourceFromMap( +var testConfigMap = NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -36,7 +36,7 @@ var testConfigMap = NewResourceFromMap( const testConfigMapString = `unspecified:{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie"}}` -var testDeployment = NewResourceFromMap( +var testDeployment = NewFromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -122,7 +122,7 @@ WOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOT: woot }, } for _, test := range tests { - rs, err := NewResourceSliceFromPatches( + rs, err := NewSliceFromPatches( l, test.input, k8sdeps.NewKustDecoder()) if test.expectedErr && err == nil { t.Fatalf("%v: should return error", test.name) @@ -142,149 +142,3 @@ WOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOT: woot } } } - -func TestNewResourceSliceFromBytes(t *testing.T) { - tests := []struct { - name string - input []byte - expectedOut []*Resource - expectedErr bool - }{ - { - name: "garbage", - input: []byte("garbageIn: garbageOut"), - expectedOut: []*Resource{}, - expectedErr: true, - }, - { - name: "noBytes", - input: []byte{}, - expectedOut: []*Resource{}, - expectedErr: false, - }, - { - name: "goodJson", - input: []byte(` -{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie"}} -`), - expectedOut: []*Resource{testConfigMap}, - expectedErr: false, - }, - { - name: "goodYaml1", - input: []byte(` -apiVersion: v1 -kind: ConfigMap -metadata: - name: winnie -`), - expectedOut: []*Resource{testConfigMap}, - expectedErr: false, - }, - { - name: "goodYaml2", - input: []byte(` -apiVersion: v1 -kind: ConfigMap -metadata: - name: winnie ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: winnie -`), - expectedOut: []*Resource{testConfigMap, testConfigMap}, - expectedErr: false, - }, - { - name: "garbageInOneOfTwoObjects", - input: []byte(` -apiVersion: v1 -kind: ConfigMap -metadata: - name: winnie ---- -WOOOOOOOOOOOOOOOOOOOOOOOOT: woot -`), - expectedOut: []*Resource{}, - expectedErr: true, - }, - } - - for _, test := range tests { - rs, err := NewResourceSliceFromBytes( - test.input, k8sdeps.NewKustDecoder()) - if test.expectedErr && err == nil { - t.Fatalf("%v: should return error", test.name) - } - if !test.expectedErr && err != nil { - t.Fatalf("%v: unexpected error: %s", test.name, err) - } - if len(rs) != len(test.expectedOut) { - t.Fatalf("%s: length mismatch %d != %d", - test.name, len(rs), len(test.expectedOut)) - } - for i := range rs { - if !reflect.DeepEqual(test.expectedOut[i], rs[i]) { - t.Fatalf("%s: Got: %v\nexpected:%v", - test.name, test.expectedOut[i], rs[i]) - } - } - } -} - -func TestGetFieldValue(t *testing.T) { - res := NewResourceFromMap(map[string]interface{}{ - "Kind": "Service", - "metadata": map[string]interface{}{ - "labels": map[string]string{ - "app": "application-name", - }, - "name": "service-name", - }, - "spec": map[string]interface{}{ - "ports": map[string]interface{}{ - "port": "80", - }, - }, - }) - - tests := []struct { - pathToField string - expectedValue string - errorExpected bool - }{ - { - pathToField: "Kind", - expectedValue: "Service", - errorExpected: false, - }, - { - pathToField: "metadata.name", - expectedValue: "service-name", - errorExpected: false, - }, - { - pathToField: "metadata.non-existing-field", - expectedValue: "", - errorExpected: true, - }, - { - pathToField: "spec.ports.port", - expectedValue: "80", - errorExpected: false, - }, - } - - for _, test := range tests { - s, err := res.GetFieldValue(test.pathToField) - if test.errorExpected && err == nil { - t.Fatalf("should return error, but no error returned") - } else { - if test.expectedValue != s { - t.Fatalf("Got:%s expected:%s", s, test.expectedValue) - } - } - } -} diff --git a/pkg/target/kusttarget.go b/pkg/target/kusttarget.go index 2e67b9029..4c1000828 100644 --- a/pkg/target/kusttarget.go +++ b/pkg/target/kusttarget.go @@ -146,10 +146,10 @@ func (kt *KustTarget) loadCustomizedResMap() (resmap.ResMap, error) { return nil, err } - patches, err := resource.NewResourceSliceFromPatches( + patches, err := resource.NewSliceFromPatches( kt.ldr, kt.kustomization.PatchesStrategicMerge, kt.decoder) if err != nil { - errs.Append(errors.Wrap(err, "NewResourceSliceFromPatches")) + errs.Append(errors.Wrap(err, "NewSliceFromPatches")) } if len(errs.Get()) > 0 { diff --git a/pkg/target/kusttarget_test.go b/pkg/target/kusttarget_test.go index 7f45fafe9..4b064eda7 100644 --- a/pkg/target/kusttarget_test.go +++ b/pkg/target/kusttarget_test.go @@ -116,7 +116,7 @@ var ns = gvk.Gvk{Version: "v1", Kind: "Namespace"} func TestResources1(t *testing.T) { expected := resmap.ResMap{ - resid.NewResIdWithPrefixNamespace(deploy, "dply1", "foo-", "ns1"): resource.NewResourceFromMap( + resid.NewResIdWithPrefixNamespace(deploy, "dply1", "foo-", "ns1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -149,7 +149,7 @@ func TestResources1(t *testing.T) { }, }, }), - resid.NewResIdWithPrefixNamespace(cmap, "literalConfigMap", "foo-", "ns1"): resource.NewResourceFromMap( + resid.NewResIdWithPrefixNamespace(cmap, "literalConfigMap", "foo-", "ns1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -168,7 +168,7 @@ func TestResources1(t *testing.T) { "DB_PASSWORD": "somepw", }, }).SetBehavior(ifc.BehaviorCreate), - resid.NewResIdWithPrefixNamespace(secret, "secret", "foo-", "ns1"): resource.NewResourceFromMap( + resid.NewResIdWithPrefixNamespace(secret, "secret", "foo-", "ns1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", @@ -188,7 +188,7 @@ func TestResources1(t *testing.T) { "DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")), }, }).SetBehavior(ifc.BehaviorCreate), - resid.NewResIdWithPrefixNamespace(ns, "ns1", "foo-", ""): resource.NewResourceFromMap( + resid.NewResIdWithPrefixNamespace(ns, "ns1", "foo-", ""): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Namespace", diff --git a/pkg/transformers/imagetag.go b/pkg/transformers/imagetag.go index e99297415..ef1f7c279 100644 --- a/pkg/transformers/imagetag.go +++ b/pkg/transformers/imagetag.go @@ -41,7 +41,7 @@ func (pt *imageTagTransformer) Transform(resources resmap.ResMap) error { return nil } for _, res := range resources { - err := pt.findAndReplaceTag(res.UnstructuredContent()) + err := pt.findAndReplaceTag(res.Map()) if err != nil { return err } diff --git a/pkg/transformers/imagetag_test.go b/pkg/transformers/imagetag_test.go index c5b2e03a4..1156a9eda 100644 --- a/pkg/transformers/imagetag_test.go +++ b/pkg/transformers/imagetag_test.go @@ -29,7 +29,7 @@ import ( func TestImageTagTransformer(t *testing.T) { m := resmap.ResMap{ - resid.NewResId(deploy, "deploy1"): resource.NewResourceFromMap( + resid.NewResId(deploy, "deploy1"): resource.NewFromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -60,7 +60,7 @@ func TestImageTagTransformer(t *testing.T) { }, }, }), - resid.NewResId(gvk.Gvk{Kind: "randomKind"}, "random"): resource.NewResourceFromMap( + resid.NewResId(gvk.Gvk{Kind: "randomKind"}, "random"): resource.NewFromMap( map[string]interface{}{ "spec": map[string]interface{}{ "template": map[string]interface{}{ @@ -97,7 +97,7 @@ func TestImageTagTransformer(t *testing.T) { }), } expected := resmap.ResMap{ - resid.NewResId(deploy, "deploy1"): resource.NewResourceFromMap( + resid.NewResId(deploy, "deploy1"): resource.NewFromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -128,7 +128,7 @@ func TestImageTagTransformer(t *testing.T) { }, }, }), - resid.NewResId(gvk.Gvk{Kind: "randomKind"}, "random"): resource.NewResourceFromMap( + resid.NewResId(gvk.Gvk{Kind: "randomKind"}, "random"): resource.NewFromMap( map[string]interface{}{ "spec": map[string]interface{}{ "template": map[string]interface{}{ diff --git a/pkg/transformers/labelsandannotations.go b/pkg/transformers/labelsandannotations.go index 4ff008ea2..ea8070279 100644 --- a/pkg/transformers/labelsandannotations.go +++ b/pkg/transformers/labelsandannotations.go @@ -58,7 +58,7 @@ func NewMapTransformer(pc []transformerconfig.PathConfig, m map[string]string) ( // fields specified in mapTransformer. func (o *mapTransformer) Transform(m resmap.ResMap) error { for id := range m { - objMap := m[id].UnstructuredContent() + objMap := m[id].Map() for _, path := range o.pathConfigs { if !id.Gvk().IsSelected(&path.Gvk) { continue diff --git a/pkg/transformers/labelsandannotations_test.go b/pkg/transformers/labelsandannotations_test.go index 6c8c47ba3..d4814f47d 100644 --- a/pkg/transformers/labelsandannotations_test.go +++ b/pkg/transformers/labelsandannotations_test.go @@ -44,7 +44,7 @@ var ingress = gvk.Gvk{Kind: "Ingress"} func TestLabelsRun(t *testing.T) { m := resmap.ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -52,7 +52,7 @@ func TestLabelsRun(t *testing.T) { "name": "cm1", }, }), - resid.NewResId(deploy, "deploy1"): resource.NewResourceFromMap( + resid.NewResId(deploy, "deploy1"): resource.NewFromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -78,7 +78,7 @@ func TestLabelsRun(t *testing.T) { }, }, }), - resid.NewResId(service, "svc1"): resource.NewResourceFromMap( + resid.NewResId(service, "svc1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Service", @@ -94,7 +94,7 @@ func TestLabelsRun(t *testing.T) { }, }, }), - resid.NewResId(job, "job1"): resource.NewResourceFromMap( + resid.NewResId(job, "job1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "batch/v1", "kind": "Job", @@ -114,7 +114,7 @@ func TestLabelsRun(t *testing.T) { }, }, }), - resid.NewResId(job, "job2"): resource.NewResourceFromMap( + resid.NewResId(job, "job2"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "batch/v1", "kind": "Job", @@ -139,7 +139,7 @@ func TestLabelsRun(t *testing.T) { }, }, }), - resid.NewResId(cronjob, "cronjob1"): resource.NewResourceFromMap( + resid.NewResId(cronjob, "cronjob1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "batch/v1beta1", "kind": "CronJob", @@ -164,7 +164,7 @@ func TestLabelsRun(t *testing.T) { }, }, }), - resid.NewResId(cronjob, "cronjob2"): resource.NewResourceFromMap( + resid.NewResId(cronjob, "cronjob2"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "batch/v1beta1", "kind": "CronJob", @@ -196,7 +196,7 @@ func TestLabelsRun(t *testing.T) { }), } expected := resmap.ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -208,7 +208,7 @@ func TestLabelsRun(t *testing.T) { }, }, }), - resid.NewResId(deploy, "deploy1"): resource.NewResourceFromMap( + resid.NewResId(deploy, "deploy1"): resource.NewFromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -246,7 +246,7 @@ func TestLabelsRun(t *testing.T) { }, }, }), - resid.NewResId(service, "svc1"): resource.NewResourceFromMap( + resid.NewResId(service, "svc1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Service", @@ -270,7 +270,7 @@ func TestLabelsRun(t *testing.T) { }, }, }), - resid.NewResId(job, "job1"): resource.NewResourceFromMap( + resid.NewResId(job, "job1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "batch/v1", "kind": "Job", @@ -300,7 +300,7 @@ func TestLabelsRun(t *testing.T) { }, }, }), - resid.NewResId(job, "job2"): resource.NewResourceFromMap( + resid.NewResId(job, "job2"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "batch/v1", "kind": "Job", @@ -337,7 +337,7 @@ func TestLabelsRun(t *testing.T) { }, }, }), - resid.NewResId(cronjob, "cronjob1"): resource.NewResourceFromMap( + resid.NewResId(cronjob, "cronjob1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "batch/v1beta1", "kind": "CronJob", @@ -372,7 +372,7 @@ func TestLabelsRun(t *testing.T) { }, }, }), - resid.NewResId(cronjob, "cronjob2"): resource.NewResourceFromMap( + resid.NewResId(cronjob, "cronjob2"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "batch/v1beta1", "kind": "CronJob", @@ -433,7 +433,7 @@ func TestLabelsRun(t *testing.T) { func TestAnnotationsRun(t *testing.T) { m := resmap.ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -441,7 +441,7 @@ func TestAnnotationsRun(t *testing.T) { "name": "cm1", }, }), - resid.NewResId(deploy, "deploy1"): resource.NewResourceFromMap( + resid.NewResId(deploy, "deploy1"): resource.NewFromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -467,7 +467,7 @@ func TestAnnotationsRun(t *testing.T) { }, }, }), - resid.NewResId(service, "svc1"): resource.NewResourceFromMap( + resid.NewResId(service, "svc1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Service", @@ -485,7 +485,7 @@ func TestAnnotationsRun(t *testing.T) { }), } expected := resmap.ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -497,7 +497,7 @@ func TestAnnotationsRun(t *testing.T) { }, }, }), - resid.NewResId(deploy, "deploy1"): resource.NewResourceFromMap( + resid.NewResId(deploy, "deploy1"): resource.NewFromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -531,7 +531,7 @@ func TestAnnotationsRun(t *testing.T) { }, }, }), - resid.NewResId(service, "svc1"): resource.NewResourceFromMap( + resid.NewResId(service, "svc1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Service", diff --git a/pkg/transformers/namehash.go b/pkg/transformers/namehash.go index 67c699d88..51f09208b 100644 --- a/pkg/transformers/namehash.go +++ b/pkg/transformers/namehash.go @@ -51,7 +51,7 @@ func (o *nameHashTransformer) Transform(m resmap.ResMap) error { } func (o *nameHashTransformer) appendHash(res *resource.Resource) error { - h, err := o.hash.Hash(res.Object) + h, err := o.hash.Hash(res.Map()) if err != nil { return err } diff --git a/pkg/transformers/namehash_test.go b/pkg/transformers/namehash_test.go index 5f0ed98a5..81ec42e47 100644 --- a/pkg/transformers/namehash_test.go +++ b/pkg/transformers/namehash_test.go @@ -29,7 +29,7 @@ import ( func TestNameHashTransformer(t *testing.T) { objs := resmap.ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -37,7 +37,7 @@ func TestNameHashTransformer(t *testing.T) { "name": "cm1", }, }), - resid.NewResId(deploy, "deploy1"): resource.NewResourceFromMap( + resid.NewResId(deploy, "deploy1"): resource.NewFromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -63,7 +63,7 @@ func TestNameHashTransformer(t *testing.T) { }, }, }), - resid.NewResId(service, "svc1"): resource.NewResourceFromMap( + resid.NewResId(service, "svc1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Service", @@ -79,7 +79,7 @@ func TestNameHashTransformer(t *testing.T) { }, }, }), - resid.NewResId(secret, "secret1"): resource.NewResourceFromMap( + resid.NewResId(secret, "secret1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", @@ -90,7 +90,7 @@ func TestNameHashTransformer(t *testing.T) { } expected := resmap.ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -98,7 +98,7 @@ func TestNameHashTransformer(t *testing.T) { "name": "cm1", }, }), - resid.NewResId(deploy, "deploy1"): resource.NewResourceFromMap( + resid.NewResId(deploy, "deploy1"): resource.NewFromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -124,7 +124,7 @@ func TestNameHashTransformer(t *testing.T) { }, }, }), - resid.NewResId(service, "svc1"): resource.NewResourceFromMap( + resid.NewResId(service, "svc1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Service", @@ -140,7 +140,7 @@ func TestNameHashTransformer(t *testing.T) { }, }, }), - resid.NewResId(secret, "secret1"): resource.NewResourceFromMap( + resid.NewResId(secret, "secret1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", diff --git a/pkg/transformers/namereference.go b/pkg/transformers/namereference.go index 22f8a319e..0ce85ec12 100644 --- a/pkg/transformers/namereference.go +++ b/pkg/transformers/namereference.go @@ -48,7 +48,7 @@ func NewNameReferenceTransformer(pc []transformerconfig.ReferencePathConfig) (Tr // then the old name is k.Name and the new name is v.GetName() func (o *nameReferenceTransformer) Transform(m resmap.ResMap) error { for id := range m { - objMap := m[id].UnstructuredContent() + objMap := m[id].Map() for _, referencePathConfig := range o.pathConfigs { for _, path := range referencePathConfig.PathConfigs { if !id.Gvk().IsSelected(&path.Gvk) { diff --git a/pkg/transformers/namereference_test.go b/pkg/transformers/namereference_test.go index b52351cb4..5fc7e3b7a 100644 --- a/pkg/transformers/namereference_test.go +++ b/pkg/transformers/namereference_test.go @@ -28,7 +28,7 @@ import ( func TestNameReferenceRun(t *testing.T) { m := resmap.ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -36,7 +36,7 @@ func TestNameReferenceRun(t *testing.T) { "name": "someprefix-cm1-somehash", }, }), - resid.NewResId(cmap, "cm2"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm2"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -44,7 +44,7 @@ func TestNameReferenceRun(t *testing.T) { "name": "someprefix-cm2-somehash", }, }), - resid.NewResId(secret, "secret1"): resource.NewResourceFromMap( + resid.NewResId(secret, "secret1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", @@ -52,7 +52,7 @@ func TestNameReferenceRun(t *testing.T) { "name": "someprefix-secret1-somehash", }, }), - resid.NewResId(pvc, "claim1"): resource.NewResourceFromMap( + resid.NewResId(pvc, "claim1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "PersistentVolumeClaim", @@ -60,7 +60,7 @@ func TestNameReferenceRun(t *testing.T) { "name": "someprefix-claim1", }, }), - resid.NewResId(ingress, "ingress1"): resource.NewResourceFromMap( + resid.NewResId(ingress, "ingress1"): resource.NewFromMap( map[string]interface{}{ "group": "extensions", "apiVersion": "v1beta1", @@ -80,7 +80,7 @@ func TestNameReferenceRun(t *testing.T) { }, }, ), - resid.NewResId(deploy, "deploy1"): resource.NewResourceFromMap( + resid.NewResId(deploy, "deploy1"): resource.NewFromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -158,7 +158,7 @@ func TestNameReferenceRun(t *testing.T) { }, }, }), - resid.NewResId(statefulset, "statefulset1"): resource.NewResourceFromMap( + resid.NewResId(statefulset, "statefulset1"): resource.NewFromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -195,7 +195,7 @@ func TestNameReferenceRun(t *testing.T) { expected[k] = v } - expected[resid.NewResId(deploy, "deploy1")] = resource.NewResourceFromMap( + expected[resid.NewResId(deploy, "deploy1")] = resource.NewFromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -273,7 +273,7 @@ func TestNameReferenceRun(t *testing.T) { }, }, }) - expected[resid.NewResId(statefulset, "statefulset1")] = resource.NewResourceFromMap( + expected[resid.NewResId(statefulset, "statefulset1")] = resource.NewFromMap( map[string]interface{}{ "group": "apps", "apiVersion": "v1", @@ -303,7 +303,7 @@ func TestNameReferenceRun(t *testing.T) { }, }, }) - expected[resid.NewResId(ingress, "ingress1")] = resource.NewResourceFromMap( + expected[resid.NewResId(ingress, "ingress1")] = resource.NewFromMap( map[string]interface{}{ "group": "extensions", "apiVersion": "v1beta1", diff --git a/pkg/transformers/namespace.go b/pkg/transformers/namespace.go index 16366a0a8..84528966c 100644 --- a/pkg/transformers/namespace.go +++ b/pkg/transformers/namespace.go @@ -85,7 +85,7 @@ func (o *namespaceTransformer) Transform(m resmap.ResMap) error { } for id := range mf { - objMap := mf[id].UnstructuredContent() + objMap := mf[id].Map() for _, path := range o.pathConfigs { if !id.Gvk().IsSelected(&path.Gvk) { continue @@ -118,7 +118,7 @@ func (o *namespaceTransformer) updateClusterRoleBinding(m resmap.ResMap) { if id.Gvk().Kind != "ClusterRoleBinding" && id.Gvk().Kind != "RoleBinding" { continue } - objMap := m[id].UnstructuredContent() + objMap := m[id].Map() subjects := objMap["subjects"].([]interface{}) for i := range subjects { subject := subjects[i].(map[string]interface{}) diff --git a/pkg/transformers/namespace_test.go b/pkg/transformers/namespace_test.go index 5943b59d6..eb8ca25c8 100644 --- a/pkg/transformers/namespace_test.go +++ b/pkg/transformers/namespace_test.go @@ -28,7 +28,7 @@ import ( func TestNamespaceRun(t *testing.T) { m := resmap.ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -36,7 +36,7 @@ func TestNamespaceRun(t *testing.T) { "name": "cm1", }, }), - resid.NewResId(cmap, "cm2"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm2"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -45,7 +45,7 @@ func TestNamespaceRun(t *testing.T) { "namespace": "foo", }, }), - resid.NewResId(ns, "ns1"): resource.NewResourceFromMap( + resid.NewResId(ns, "ns1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Namespace", @@ -53,7 +53,7 @@ func TestNamespaceRun(t *testing.T) { "name": "ns1", }, }), - resid.NewResId(sa, "default"): resource.NewResourceFromMap( + resid.NewResId(sa, "default"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ServiceAccount", @@ -62,7 +62,7 @@ func TestNamespaceRun(t *testing.T) { "namespace": "system", }, }), - resid.NewResId(sa, "service-account"): resource.NewResourceFromMap( + resid.NewResId(sa, "service-account"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ServiceAccount", @@ -71,7 +71,7 @@ func TestNamespaceRun(t *testing.T) { "namespace": "system", }, }), - resid.NewResId(crb, "crb"): resource.NewResourceFromMap( + resid.NewResId(crb, "crb"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "rbac.authorization.k8s.io/v1", "kind": "ClusterRoleBinding", @@ -96,7 +96,7 @@ func TestNamespaceRun(t *testing.T) { }, }, }), - resid.NewResId(crd, "crd"): resource.NewResourceFromMap( + resid.NewResId(crd, "crd"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "apiextensions.k8s.io/v1beta1", "kind": "CustomResourceDefinition", @@ -106,7 +106,7 @@ func TestNamespaceRun(t *testing.T) { }), } expected := resmap.ResMap{ - resid.NewResIdWithPrefixNamespace(ns, "ns1", "", ""): resource.NewResourceFromMap( + resid.NewResIdWithPrefixNamespace(ns, "ns1", "", ""): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "Namespace", @@ -114,7 +114,7 @@ func TestNamespaceRun(t *testing.T) { "name": "ns1", }, }), - resid.NewResIdWithPrefixNamespace(cmap, "cm1", "", "test"): resource.NewResourceFromMap( + resid.NewResIdWithPrefixNamespace(cmap, "cm1", "", "test"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -123,7 +123,7 @@ func TestNamespaceRun(t *testing.T) { "namespace": "test", }, }), - resid.NewResIdWithPrefixNamespace(cmap, "cm2", "", "test"): resource.NewResourceFromMap( + resid.NewResIdWithPrefixNamespace(cmap, "cm2", "", "test"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -132,7 +132,7 @@ func TestNamespaceRun(t *testing.T) { "namespace": "test", }, }), - resid.NewResIdWithPrefixNamespace(sa, "default", "", "test"): resource.NewResourceFromMap( + resid.NewResIdWithPrefixNamespace(sa, "default", "", "test"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ServiceAccount", @@ -141,7 +141,7 @@ func TestNamespaceRun(t *testing.T) { "namespace": "test", }, }), - resid.NewResIdWithPrefixNamespace(sa, "service-account", "", "test"): resource.NewResourceFromMap( + resid.NewResIdWithPrefixNamespace(sa, "service-account", "", "test"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ServiceAccount", @@ -150,7 +150,7 @@ func TestNamespaceRun(t *testing.T) { "namespace": "test", }, }), - resid.NewResId(crb, "crb"): resource.NewResourceFromMap( + resid.NewResId(crb, "crb"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "rbac.authorization.k8s.io/v1", "kind": "ClusterRoleBinding", @@ -175,7 +175,7 @@ func TestNamespaceRun(t *testing.T) { }, }, }), - resid.NewResId(crd, "crd"): resource.NewResourceFromMap( + resid.NewResId(crd, "crd"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "apiextensions.k8s.io/v1beta1", "kind": "CustomResourceDefinition", diff --git a/pkg/transformers/patch.go b/pkg/transformers/patch.go index eae69d6af..af5d6f7e1 100644 --- a/pkg/transformers/patch.go +++ b/pkg/transformers/patch.go @@ -70,11 +70,11 @@ func (pt *patchTransformer) Transform(baseResourceMap resmap.ResMap) error { switch { case runtime.IsNotRegisteredError(err): // Use JSON merge patch to handle types w/o schema - baseBytes, err := json.Marshal(base) + baseBytes, err := json.Marshal(base.Map()) if err != nil { return err } - patchBytes, err := json.Marshal(patch) + patchBytes, err := json.Marshal(patch.Map()) if err != nil { return err } @@ -98,15 +98,15 @@ func (pt *patchTransformer) Transform(baseResourceMap resmap.ResMap) error { return err } merged, err = strategicpatch.StrategicMergeMapPatchUsingLookupPatchMeta( - base.Object, - patch.Object, + base.Map(), + patch.Map(), lookupPatchMeta) if err != nil { return err } } base.SetName(baseName) - baseResourceMap[id].Object = merged + baseResourceMap[id].SetMap(merged) } return nil } @@ -146,7 +146,9 @@ func (pt *patchTransformer) mergePatches() (resmap.ResMap, error) { if err != nil { return nil, err } - return nil, fmt.Errorf("there is conflict between %#v and %#v", conflictingPatch.Object, patch.Object) + return nil, fmt.Errorf( + "conflict between %#v and %#v", + conflictingPatch.Map(), patch.Map()) } merged, err := cd.mergePatches(existing, patch) if err != nil { diff --git a/pkg/transformers/patch_test.go b/pkg/transformers/patch_test.go index b8f004100..aca087f28 100644 --- a/pkg/transformers/patch_test.go +++ b/pkg/transformers/patch_test.go @@ -28,7 +28,7 @@ import ( func TestOverlayRun(t *testing.T) { base := resmap.ResMap{ - resid.NewResId(deploy, "deploy1"): resource.NewResourceFromMap( + resid.NewResId(deploy, "deploy1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -55,7 +55,7 @@ func TestOverlayRun(t *testing.T) { }), } patch := []*resource.Resource{ - resource.NewResourceFromMap(map[string]interface{}{ + resource.NewFromMap(map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": map[string]interface{}{ @@ -88,7 +88,7 @@ func TestOverlayRun(t *testing.T) { ), } expected := resmap.ResMap{ - resid.NewResId(deploy, "deploy1"): resource.NewResourceFromMap( + resid.NewResId(deploy, "deploy1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -137,7 +137,7 @@ func TestOverlayRun(t *testing.T) { func TestMultiplePatches(t *testing.T) { base := resmap.ResMap{ - resid.NewResId(deploy, "deploy1"): resource.NewResourceFromMap( + resid.NewResId(deploy, "deploy1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -159,7 +159,7 @@ func TestMultiplePatches(t *testing.T) { }), } patch := []*resource.Resource{ - resource.NewResourceFromMap(map[string]interface{}{ + resource.NewFromMap(map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": map[string]interface{}{ @@ -185,7 +185,7 @@ func TestMultiplePatches(t *testing.T) { }, }, ), - resource.NewResourceFromMap(map[string]interface{}{ + resource.NewFromMap(map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": map[string]interface{}{ @@ -216,7 +216,7 @@ func TestMultiplePatches(t *testing.T) { ), } expected := resmap.ResMap{ - resid.NewResId(deploy, "deploy1"): resource.NewResourceFromMap( + resid.NewResId(deploy, "deploy1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -267,7 +267,7 @@ func TestMultiplePatches(t *testing.T) { func TestMultiplePatchesWithConflict(t *testing.T) { base := resmap.ResMap{ - resid.NewResId(deploy, "deploy1"): resource.NewResourceFromMap( + resid.NewResId(deploy, "deploy1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", @@ -289,7 +289,7 @@ func TestMultiplePatchesWithConflict(t *testing.T) { }), } patch := []*resource.Resource{ - resource.NewResourceFromMap(map[string]interface{}{ + resource.NewFromMap(map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": map[string]interface{}{ @@ -315,7 +315,7 @@ func TestMultiplePatchesWithConflict(t *testing.T) { }, }, ), - resource.NewResourceFromMap(map[string]interface{}{ + resource.NewFromMap(map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": map[string]interface{}{ @@ -352,7 +352,7 @@ func TestMultiplePatchesWithConflict(t *testing.T) { func TestNoSchemaOverlayRun(t *testing.T) { base := resmap.ResMap{ - resid.NewResId(foo, "my-foo"): resource.NewResourceFromMap( + resid.NewResId(foo, "my-foo"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "example.com/v1", "kind": "Foo", @@ -368,7 +368,7 @@ func TestNoSchemaOverlayRun(t *testing.T) { }), } patch := []*resource.Resource{ - resource.NewResourceFromMap(map[string]interface{}{ + resource.NewFromMap(map[string]interface{}{ "apiVersion": "example.com/v1", "kind": "Foo", "metadata": map[string]interface{}{ @@ -384,7 +384,7 @@ func TestNoSchemaOverlayRun(t *testing.T) { ), } expected := resmap.ResMap{ - resid.NewResId(foo, "my-foo"): resource.NewResourceFromMap( + resid.NewResId(foo, "my-foo"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "example.com/v1", "kind": "Foo", @@ -415,7 +415,7 @@ func TestNoSchemaOverlayRun(t *testing.T) { func TestNoSchemaMultiplePatches(t *testing.T) { base := resmap.ResMap{ - resid.NewResId(foo, "my-foo"): resource.NewResourceFromMap( + resid.NewResId(foo, "my-foo"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "example.com/v1", "kind": "Foo", @@ -431,7 +431,7 @@ func TestNoSchemaMultiplePatches(t *testing.T) { }), } patch := []*resource.Resource{ - resource.NewResourceFromMap(map[string]interface{}{ + resource.NewFromMap(map[string]interface{}{ "apiVersion": "example.com/v1", "kind": "Foo", "metadata": map[string]interface{}{ @@ -445,7 +445,7 @@ func TestNoSchemaMultiplePatches(t *testing.T) { }, }, ), - resource.NewResourceFromMap(map[string]interface{}{ + resource.NewFromMap(map[string]interface{}{ "apiVersion": "example.com/v1", "kind": "Foo", "metadata": map[string]interface{}{ @@ -464,7 +464,7 @@ func TestNoSchemaMultiplePatches(t *testing.T) { ), } expected := resmap.ResMap{ - resid.NewResId(foo, "my-foo"): resource.NewResourceFromMap( + resid.NewResId(foo, "my-foo"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "example.com/v1", "kind": "Foo", @@ -499,7 +499,7 @@ func TestNoSchemaMultiplePatches(t *testing.T) { func TestNoSchemaMultiplePatchesWithConflict(t *testing.T) { base := resmap.ResMap{ - resid.NewResId(foo, "my-foo"): resource.NewResourceFromMap( + resid.NewResId(foo, "my-foo"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "example.com/v1", "kind": "Foo", @@ -515,7 +515,7 @@ func TestNoSchemaMultiplePatchesWithConflict(t *testing.T) { }), } patch := []*resource.Resource{ - resource.NewResourceFromMap(map[string]interface{}{ + resource.NewFromMap(map[string]interface{}{ "apiVersion": "example.com/v1", "kind": "Foo", "metadata": map[string]interface{}{ @@ -528,7 +528,7 @@ func TestNoSchemaMultiplePatchesWithConflict(t *testing.T) { }, }, }), - resource.NewResourceFromMap(map[string]interface{}{ + resource.NewFromMap(map[string]interface{}{ "apiVersion": "example.com/v1", "kind": "Foo", "metadata": map[string]interface{}{ diff --git a/pkg/transformers/patchconflictdetector.go b/pkg/transformers/patchconflictdetector.go index 97a65f022..2a8fe1d52 100644 --- a/pkg/transformers/patchconflictdetector.go +++ b/pkg/transformers/patchconflictdetector.go @@ -18,7 +18,6 @@ package transformers import ( "encoding/json" - "github.com/evanphx/json-patch" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/mergepatch" @@ -40,20 +39,23 @@ func newJMPConflictDetector() conflictDetector { return &jsonMergePatch{} } -func (jmp *jsonMergePatch) hasConflict(patch1, patch2 *resource.Resource) (bool, error) { - return mergepatch.HasConflicts(patch1.Object, patch2.Object) +func (jmp *jsonMergePatch) hasConflict( + patch1, patch2 *resource.Resource) (bool, error) { + return mergepatch.HasConflicts(patch1.Map(), patch2.Map()) } -func (jmp *jsonMergePatch) findConflict(conflictingPatchIdx int, patches []*resource.Resource) (*resource.Resource, error) { +func (jmp *jsonMergePatch) findConflict( + conflictingPatchIdx int, patches []*resource.Resource) (*resource.Resource, error) { for i, patch := range patches { if i == conflictingPatchIdx { continue } - if patches[conflictingPatchIdx].GroupVersionKind() != patch.GroupVersionKind() || - patches[conflictingPatchIdx].GetName() != patch.GetName() { + if !patches[conflictingPatchIdx].Id().GvknEquals(patch.Id()) { continue } - conflict, err := mergepatch.HasConflicts(patch.Object, patches[conflictingPatchIdx].Object) + conflict, err := mergepatch.HasConflicts( + patch.Map(), + patches[conflictingPatchIdx].Map()) if err != nil { return nil, err } @@ -64,14 +66,13 @@ func (jmp *jsonMergePatch) findConflict(conflictingPatchIdx int, patches []*reso return nil, nil } -func (jmp *jsonMergePatch) mergePatches(patch1, patch2 *resource.Resource) (*resource.Resource, error) { - var merged resource.Resource - var mergedMap map[string]interface{} - baseBytes, err := json.Marshal(patch1.Object) +func (jmp *jsonMergePatch) mergePatches( + patch1, patch2 *resource.Resource) (*resource.Resource, error) { + baseBytes, err := json.Marshal(patch1.Map()) if err != nil { return nil, err } - patchBytes, err := json.Marshal(patch2.Object) + patchBytes, err := json.Marshal(patch2.Map()) if err != nil { return nil, err } @@ -79,9 +80,9 @@ func (jmp *jsonMergePatch) mergePatches(patch1, patch2 *resource.Resource) (*res if err != nil { return nil, err } + mergedMap := make(map[string]interface{}) err = json.Unmarshal(mergedBytes, &mergedMap) - merged.SetUnstructuredContent(mergedMap) - return &merged, err + return resource.NewFromMap(mergedMap), err } type strategicMergePatch struct { @@ -95,21 +96,24 @@ func newSMPConflictDetector(versionedObj runtime.Object) (conflictDetector, erro return &strategicMergePatch{lookupPatchMeta: lookupPatchMeta}, err } -func (smp *strategicMergePatch) hasConflict(patch1, patch2 *resource.Resource) (bool, error) { - return strategicpatch.MergingMapsHaveConflicts(patch1.Object, patch2.Object, smp.lookupPatchMeta) +func (smp *strategicMergePatch) hasConflict(p1, p2 *resource.Resource) (bool, error) { + return strategicpatch.MergingMapsHaveConflicts( + p1.Map(), p2.Map(), smp.lookupPatchMeta) } -func (smp *strategicMergePatch) findConflict(conflictingPatchIdx int, patches []*resource.Resource) (*resource.Resource, error) { +func (smp *strategicMergePatch) findConflict( + conflictingPatchIdx int, patches []*resource.Resource) (*resource.Resource, error) { for i, patch := range patches { if i == conflictingPatchIdx { continue } - if patches[conflictingPatchIdx].GroupVersionKind() != patch.GroupVersionKind() || - patches[conflictingPatchIdx].GetName() != patch.GetName() { + if !patches[conflictingPatchIdx].Id().GvknEquals(patch.Id()) { continue } conflict, err := strategicpatch.MergingMapsHaveConflicts( - patch.Object, patches[conflictingPatchIdx].Object, smp.lookupPatchMeta) + patch.Map(), + patches[conflictingPatchIdx].Map(), + smp.lookupPatchMeta) if err != nil { return nil, err } @@ -121,9 +125,7 @@ func (smp *strategicMergePatch) findConflict(conflictingPatchIdx int, patches [] } func (smp *strategicMergePatch) mergePatches(patch1, patch2 *resource.Resource) (*resource.Resource, error) { - merged := resource.Resource{} mergeJsonMap, err := strategicpatch.MergeStrategicMergeMapPatchUsingLookupPatchMeta( - smp.lookupPatchMeta, patch1.Object, patch2.Object) - merged.SetUnstructuredContent(mergeJsonMap) - return &merged, err + smp.lookupPatchMeta, patch1.Map(), patch2.Map()) + return resource.NewFromMap(mergeJsonMap), err } diff --git a/pkg/transformers/prefixname.go b/pkg/transformers/prefixname.go index 7e294812f..15e5e6a67 100644 --- a/pkg/transformers/prefixname.go +++ b/pkg/transformers/prefixname.go @@ -80,7 +80,7 @@ func (o *namePrefixTransformer) Transform(m resmap.ResMap) error { if id.Gvk().IsSelected(&deprecateNamePrefixPathConfig.Gvk) { log.Println("Adding nameprefix to Namespace resource will be deprecated in next release.") } - objMap := mf[id].UnstructuredContent() + objMap := mf[id].Map() for _, path := range o.pathConfigs { if !id.Gvk().IsSelected(&path.Gvk) { continue diff --git a/pkg/transformers/prefixname_test.go b/pkg/transformers/prefixname_test.go index 01efbacdf..b7bd89980 100644 --- a/pkg/transformers/prefixname_test.go +++ b/pkg/transformers/prefixname_test.go @@ -28,7 +28,7 @@ import ( func TestPrefixNameRun(t *testing.T) { m := resmap.ResMap{ - resid.NewResId(cmap, "cm1"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm1"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -36,7 +36,7 @@ func TestPrefixNameRun(t *testing.T) { "name": "cm1", }, }), - resid.NewResId(cmap, "cm2"): resource.NewResourceFromMap( + resid.NewResId(cmap, "cm2"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -44,7 +44,7 @@ func TestPrefixNameRun(t *testing.T) { "name": "cm2", }, }), - resid.NewResId(crd, "crd"): resource.NewResourceFromMap( + resid.NewResId(crd, "crd"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "apiextensions.k8s.io/v1beta1", "kind": "CustomResourceDefinition", @@ -54,7 +54,7 @@ func TestPrefixNameRun(t *testing.T) { }), } expected := resmap.ResMap{ - resid.NewResIdWithPrefix(cmap, "cm1", "someprefix-"): resource.NewResourceFromMap( + resid.NewResIdWithPrefix(cmap, "cm1", "someprefix-"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -62,7 +62,7 @@ func TestPrefixNameRun(t *testing.T) { "name": "someprefix-cm1", }, }), - resid.NewResIdWithPrefix(cmap, "cm2", "someprefix-"): resource.NewResourceFromMap( + resid.NewResIdWithPrefix(cmap, "cm2", "someprefix-"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "v1", "kind": "ConfigMap", @@ -70,7 +70,7 @@ func TestPrefixNameRun(t *testing.T) { "name": "someprefix-cm2", }, }), - resid.NewResId(crd, "crd"): resource.NewResourceFromMap( + resid.NewResId(crd, "crd"): resource.NewFromMap( map[string]interface{}{ "apiVersion": "apiextensions.k8s.io/v1beta1", "kind": "CustomResourceDefinition", diff --git a/pkg/transformers/refvars.go b/pkg/transformers/refvars.go index 47e131e4a..596198a61 100644 --- a/pkg/transformers/refvars.go +++ b/pkg/transformers/refvars.go @@ -32,7 +32,7 @@ func NewRefVarTransformer(vars map[string]string, p []transformerconfig.PathConf // 3. Add remaining service environment vars func (rv *refvarTransformer) Transform(resources resmap.ResMap) error { for resId := range resources { - objMap := resources[resId].UnstructuredContent() + objMap := resources[resId].Map() for _, pc := range rv.pathConfigs { if !resId.Gvk().IsSelected(&pc.Gvk) { continue