Merge pull request #423 from monopole/hideUnstruct

Hide unstructured.Unstructured behind interface.
This commit is contained in:
k8s-ci-robot
2018-10-08 11:21:45 -07:00
committed by GitHub
35 changed files with 527 additions and 419 deletions

View File

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

View File

@@ -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'")
}

View File

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

View File

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

View File

@@ -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{

View File

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

View File

@@ -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{}{

View File

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

View File

@@ -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",

View File

@@ -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

View File

@@ -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",

View File

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

View File

@@ -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",

View File

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

View File

@@ -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",

View File

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

View File

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

View File

@@ -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 {

View File

@@ -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",

View File

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

View File

@@ -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{}{

View File

@@ -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

View File

@@ -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",

View File

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

View File

@@ -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",

View File

@@ -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) {

View File

@@ -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",

View File

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

View File

@@ -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",

View File

@@ -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 {

View File

@@ -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{}{

View File

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

View File

@@ -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

View File

@@ -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",

View File

@@ -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