diff --git a/pkg/app/application.go b/pkg/app/application.go index 77ba7c233..1a5b7065e 100644 --- a/pkg/app/application.go +++ b/pkg/app/application.go @@ -318,7 +318,8 @@ func (a *applicationImpl) resolveRefVars(resources resmap.ResMap) (map[string]st for _, refvar := range vars { refGVKN := resource.NewResId(refvar.ObjRef.GroupVersionKind(), refvar.ObjRef.Name) if r, found := resources[refGVKN]; found { - s, err := resource.GetFieldValue(r.Unstruct().UnstructuredContent(), strings.Split(refvar.FieldRef.FieldPath, ".")) + s, err := resource.GetFieldValue( + r.UnstructuredContent(), strings.Split(refvar.FieldRef.FieldPath, ".")) if err != nil { return nil, fmt.Errorf("failed to resolve referred var: %+v", refvar) } diff --git a/pkg/diff/rundiff.go b/pkg/diff/rundiff.go index 5918ea35c..1c04fb0c1 100644 --- a/pkg/diff/rundiff.go +++ b/pkg/diff/rundiff.go @@ -51,12 +51,12 @@ func writeYamlToNewDir(in resmap.ResMap, prefix string) (*directory, error) { return nil, err } - for gvkn, obj := range in { - f, err := dir.newFile(gvkn.String()) + for id, obj := range in { + f, err := dir.newFile(id.String()) if err != nil { return nil, err } - err = print(obj.Unstruct(), f) + err = print(obj, f) f.Close() if err != nil { return nil, err diff --git a/pkg/resmap/configmap.go b/pkg/resmap/configmap.go index 6c24a9745..f95d475b7 100644 --- a/pkg/resmap/configmap.go +++ b/pkg/resmap/configmap.go @@ -28,42 +28,37 @@ import ( "k8s.io/apimachinery/pkg/util/validation" ) -func newResourceFromConfigMap(l loader.Loader, cm types.ConfigMapArgs) (*resource.Resource, error) { - corev1CM, err := makeConfigMap(l, cm) +func newResourceFromConfigMap(l loader.Loader, cmArgs types.ConfigMapArgs) (*resource.Resource, error) { + cm, err := makeConfigMap(l, cmArgs) if err != nil { return nil, err } - - data, err := newUnstructuredFromObject(corev1CM) - if err != nil { - return nil, err - } - return resource.NewResource(data, cm.Behavior), nil + return resource.NewResourceWithBehavior(cm, resource.NewGenerationBehavior(cmArgs.Behavior)) } -func makeConfigMap(l loader.Loader, cm types.ConfigMapArgs) (*corev1.ConfigMap, error) { +func makeConfigMap(l loader.Loader, cmArgs types.ConfigMapArgs) (*corev1.ConfigMap, error) { var envPairs, literalPairs, filePairs []kvPair var err error - corev1cm := &corev1.ConfigMap{} - corev1cm.APIVersion = "v1" - corev1cm.Kind = "ConfigMap" - corev1cm.Name = cm.Name - corev1cm.Data = map[string]string{} + cm := &corev1.ConfigMap{} + cm.APIVersion = "v1" + cm.Kind = "ConfigMap" + cm.Name = cmArgs.Name + cm.Data = map[string]string{} - if cm.EnvSource != "" { - envPairs, err = keyValuesFromEnvFile(l, cm.EnvSource) + if cmArgs.EnvSource != "" { + envPairs, err = keyValuesFromEnvFile(l, cmArgs.EnvSource) if err != nil { - return nil, fmt.Errorf("error reading keys from env source file: %s %v", cm.EnvSource, err) + return nil, fmt.Errorf("error reading keys from env source file: %s %v", cmArgs.EnvSource, err) } } - literalPairs, err = keyValuesFromLiteralSources(cm.LiteralSources) + literalPairs, err = keyValuesFromLiteralSources(cmArgs.LiteralSources) if err != nil { return nil, fmt.Errorf("error reading key values from literal sources: %v", err) } - filePairs, err = keyValuesFromFileSources(l, cm.FileSources) + filePairs, err = keyValuesFromFileSources(l, cmArgs.FileSources) if err != nil { return nil, fmt.Errorf("error reading key values from file sources: %v", err) } @@ -72,13 +67,13 @@ func makeConfigMap(l loader.Loader, cm types.ConfigMapArgs) (*corev1.ConfigMap, // merge key value pairs from all the sources for _, kv := range allPairs { - err = addKV(corev1cm.Data, kv) + err = addKV(cm.Data, kv) if err != nil { return nil, fmt.Errorf("error adding key in configmap: %v", err) } } - return corev1cm, nil + return cm, nil } func keyValuesFromEnvFile(l loader.Loader, path string) ([]kvPair, error) { diff --git a/pkg/resmap/resmap.go b/pkg/resmap/resmap.go index f62809786..b39efe40e 100644 --- a/pkg/resmap/resmap.go +++ b/pkg/resmap/resmap.go @@ -19,7 +19,6 @@ package resmap import ( "bytes" - "encoding/json" "fmt" "io" "reflect" @@ -30,7 +29,6 @@ import ( "github.com/kubernetes-sigs/kustomize/pkg/loader" "github.com/kubernetes-sigs/kustomize/pkg/resource" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" k8syaml "k8s.io/apimachinery/pkg/util/yaml" ) @@ -40,8 +38,8 @@ type ResMap map[resource.ResId]*resource.Resource // EncodeAsYaml encodes a ResMap to YAML; encoded objects separated by `---`. func (m ResMap) EncodeAsYaml() ([]byte, error) { ids := []resource.ResId{} - for gvkn := range m { - ids = append(ids, gvkn) + for id := range m { + ids = append(ids, id) } sort.Sort(IdSlice(ids)) @@ -49,7 +47,7 @@ func (m ResMap) EncodeAsYaml() ([]byte, error) { var b []byte buf := bytes.NewBuffer(b) for _, id := range ids { - obj := m[id].Unstruct() + obj := m[id] out, err := yaml.Marshal(obj) if err != nil { return nil, err @@ -87,8 +85,8 @@ func (m1 ResMap) ErrorIfNotEqual(m2 ResMap) error { if !found { return fmt.Errorf("%#v doesn't exist in %#v", id, m2) } - if !reflect.DeepEqual(obj1.Unstruct(), obj2.Unstruct()) { - return fmt.Errorf("%#v doesn't match %#v", obj1.Unstruct(), obj2.Unstruct()) + if !reflect.DeepEqual(obj1, obj2) { + return fmt.Errorf("%#v doesn't match %#v", obj1, obj2) } } return nil @@ -153,11 +151,11 @@ func newResMapFromBytes(b []byte) (ResMap, error) { result := ResMap{} for _, res := range resources { - gvkn := res.Id() - if _, found := result[gvkn]; found { - return result, fmt.Errorf("GroupVersionKindName: %#v already exists b the map", gvkn) + id := res.Id() + if _, found := result[id]; found { + return result, fmt.Errorf("GroupVersionKindName: %#v already exists b the map", id) } - result[gvkn] = res + result[id] = res } return result, nil } @@ -165,11 +163,11 @@ func newResMapFromBytes(b []byte) (ResMap, error) { func newResMapFromResourceSlice(resources []*resource.Resource) (ResMap, error) { result := ResMap{} for _, res := range resources { - gvkn := res.Id() - if _, found := result[gvkn]; found { - return nil, fmt.Errorf("duplicated %#v is not allowed", gvkn) + id := res.Id() + if _, found := result[id]; found { + return nil, fmt.Errorf("duplicated %#v is not allowed", id) } - result[gvkn] = res + result[id] = res } return result, nil } @@ -197,21 +195,17 @@ func newResourceSliceFromBytes(in []byte) ([]*resource.Resource, error) { func Merge(maps ...ResMap) (ResMap, error) { result := ResMap{} for _, m := range maps { - for gvkn, obj := range m { - if _, found := result[gvkn]; found { - return nil, fmt.Errorf("there is already an entry: %q", gvkn) + for id, obj := range m { + if _, found := result[id]; found { + return nil, fmt.Errorf("there is already an entry: %q", id) } - result[gvkn] = obj + result[id] = obj } } return result, nil } -const behaviorCreate = "create" -const behaviorReplace = "replace" -const behaviorMerge = "merge" - // MergeWithOverride merges the entries in the ResMap slice with Override. // If there is already an entry with the same Id , different actions are performed // according to value of behavior field: @@ -221,44 +215,30 @@ const behaviorMerge = "merge" func MergeWithOverride(maps ...ResMap) (ResMap, error) { result := ResMap{} for _, m := range maps { - for gvkn, resource := range m { - if _, found := result[gvkn]; found { - switch resource.Behavior() { - case "", behaviorCreate: - return nil, fmt.Errorf("Create an existing gvkn %#v is not allowed", gvkn) - case behaviorReplace: - glog.V(4).Infof("Replace object %v by %v", result[gvkn].Unstruct().Object, resource.Unstruct().Object) - resource.Replace(result[gvkn]) - result[gvkn] = resource - case behaviorMerge: - glog.V(4).Infof("Merge object %v with %v", result[gvkn].Unstruct().Object, resource.Unstruct().Object) - resource.Merge(result[gvkn]) - result[gvkn] = resource - glog.V(4).Infof("The merged object is %v", result[gvkn].Unstruct().Object) + for id, r := range m { + if _, found := result[id]; found { + switch r.Behavior() { + case resource.BehaviorReplace: + glog.V(4).Infof("Replace object %v by %v", result[id].Object, r.Object) + r.Replace(result[id]) + result[id] = r + case resource.BehaviorMerge: + glog.V(4).Infof("Merge object %v with %v", result[id].Object, r.Object) + r.Merge(result[id]) + result[id] = r + glog.V(4).Infof("The merged object is %v", result[id].Object) default: - return nil, fmt.Errorf("The behavior of %#v must be one of merge and replace since it already exists in the base", gvkn) + return nil, fmt.Errorf("Id %#v exists; must merge or replace.", id) } } else { - switch resource.Behavior() { - case "", behaviorCreate: - result[gvkn] = resource - case behaviorMerge, behaviorReplace: - return nil, fmt.Errorf("No merge or replace is allowed for non existing gvkn %#v", gvkn) + switch r.Behavior() { + case resource.BehaviorMerge, resource.BehaviorReplace: + return nil, fmt.Errorf("Id %#v does not exist; cannot merge or replace.", id) default: - return nil, fmt.Errorf("The behavior of %#v must be create since it doesn't exist", gvkn) + result[id] = r } } } } return result, nil } - -func newUnstructuredFromObject(in runtime.Object) (*unstructured.Unstructured, error) { - marshaled, err := json.Marshal(in) - if err != nil { - return nil, err - } - var out unstructured.Unstructured - err = out.UnmarshalJSON(marshaled) - return &out, err -} diff --git a/pkg/resmap/secret.go b/pkg/resmap/secret.go index 810c2cd5d..6d9fe94a4 100644 --- a/pkg/resmap/secret.go +++ b/pkg/resmap/secret.go @@ -28,32 +28,34 @@ import ( corev1 "k8s.io/api/core/v1" ) -func newFromSecretGenerator(p string, s types.SecretArgs) (*resource.Resource, error) { - corev1secret := &corev1.Secret{} - corev1secret.APIVersion = "v1" - corev1secret.Kind = "Secret" - corev1secret.Name = s.Name - corev1secret.Type = corev1.SecretType(s.Type) - if corev1secret.Type == "" { - corev1secret.Type = corev1.SecretTypeOpaque +func newResourceFromSecretGenerator(p string, sArgs types.SecretArgs) (*resource.Resource, error) { + s, err := makeSecret(p, sArgs) + if err != nil { + return nil, err } - corev1secret.Data = map[string][]byte{} + return resource.NewResourceWithBehavior( + s, resource.NewGenerationBehavior(sArgs.Behavior)) +} - for k, v := range s.Commands { +func makeSecret(p string, sArgs types.SecretArgs) (*corev1.Secret, error) { + s := &corev1.Secret{} + s.APIVersion = "v1" + s.Kind = "Secret" + s.Name = sArgs.Name + s.Type = corev1.SecretType(sArgs.Type) + if s.Type == "" { + s.Type = corev1.SecretTypeOpaque + } + s.Data = map[string][]byte{} + + for k, v := range sArgs.Commands { out, err := createSecretKey(p, v) if err != nil { return nil, err } - corev1secret.Data[k] = out + s.Data[k] = out } - - obj, err := newUnstructuredFromObject(corev1secret) - - if err != nil { - return nil, err - } - - return resource.NewResource(obj, s.Behavior), nil + return s, nil } func createSecretKey(wd string, command string) ([]byte, error) { @@ -65,7 +67,6 @@ func createSecretKey(wd string, command string) ([]byte, error) { defer cancel() cmd := exec.CommandContext(ctx, "sh", "-c", command) cmd.Dir = wd - return cmd.Output() } @@ -74,7 +75,7 @@ func createSecretKey(wd string, command string) ([]byte, error) { func NewResMapFromSecretArgs(p string, secretList []types.SecretArgs) (ResMap, error) { allResources := []*resource.Resource{} for _, secret := range secretList { - res, err := newFromSecretGenerator(p, secret) + res, err := newResourceFromSecretGenerator(p, secret) if err != nil { return nil, err } diff --git a/pkg/resmap/secret_test.go b/pkg/resmap/secret_test.go index b2b495143..d36037e17 100644 --- a/pkg/resmap/secret_test.go +++ b/pkg/resmap/secret_test.go @@ -30,10 +30,10 @@ import ( var secret = schema.GroupVersionKind{Version: "v1", Kind: "Secret"} -func TestNewFromSecretGenerators(t *testing.T) { +func TestNewResMapFromSecretArgs(t *testing.T) { secrets := []types.SecretArgs{ { - Name: "secret", + Name: "apple", Commands: map[string]string{ "DB_USERNAME": "printf admin", "DB_PASSWORD": "printf somepw", @@ -41,19 +41,20 @@ func TestNewFromSecretGenerators(t *testing.T) { Type: "Opaque", }, } - re, err := NewResMapFromSecretArgs(".", secrets) + actual, err := NewResMapFromSecretArgs(".", secrets) if err != nil { t.Fatalf("unexpected error: %v", err) } + expected := ResMap{ - resource.NewResId(secret, "secret"): resource.NewResource( + resource.NewResId(secret, "apple"): resource.NewBehaviorlessResource( &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "v1", "kind": "Secret", "metadata": map[string]interface{}{ - "name": "secret", + "name": "apple", "creationTimestamp": nil, }, "type": string(corev1.SecretTypeOpaque), @@ -62,11 +63,9 @@ func TestNewFromSecretGenerators(t *testing.T) { "DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")), }, }, - }, - ""), + }), } - - if !reflect.DeepEqual(re, expected) { - t.Fatalf("%#v\ndoesn't match expected:\n%#v", re, expected) + if !reflect.DeepEqual(actual, expected) { + t.Fatalf("%#v\ndoesn't match expected:\n%#v", actual, expected) } } diff --git a/pkg/resource/generationbehavior.go b/pkg/resource/generationbehavior.go new file mode 100644 index 000000000..dea2254f2 --- /dev/null +++ b/pkg/resource/generationbehavior.go @@ -0,0 +1,59 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package resource + +// GenerationBehavior specifies generation behavior of configmaps, secrets and maybe other resources. +type GenerationBehavior int + +const ( + // Unspecified behavior typically treated as a Create. + BehaviorUnspecified GenerationBehavior = iota + // Make a new resource. + BehaviorCreate + // Replace a resource. + BehaviorReplace + // Attempt to merge a new resource with an existing resource. + BehaviorMerge +) + +// String converts a GenerationBehavior to a string. +func (b GenerationBehavior) String() string { + switch b { + case BehaviorReplace: + return "replace" + case BehaviorMerge: + return "merge" + case BehaviorCreate: + return "create" + default: + return "unspecified" + } +} + +// NewGenerationBehavior converts a string to a GenerationBehavior. +func NewGenerationBehavior(s string) GenerationBehavior { + switch s { + case "replace": + return BehaviorReplace + case "merge": + return BehaviorMerge + case "create": + return BehaviorCreate + default: + return BehaviorUnspecified + } +} diff --git a/pkg/resource/resource.go b/pkg/resource/resource.go index eaf4cee30..aa3e5b5ec 100644 --- a/pkg/resource/resource.go +++ b/pkg/resource/resource.go @@ -25,56 +25,49 @@ import ( "k8s.io/apimachinery/pkg/runtime" ) -// Resource is a Kubernetes Resource Object paired with a behavior. +// Resource is an "Unstructured" (json/map form) Kubernetes API resource object +// paired with a GenerationBehavior. type Resource struct { - unstruct *unstructured.Unstructured - behavior string + unstructured.Unstructured + b GenerationBehavior } -// NewResource returns a new instance of Resource. -func NewResource(u *unstructured.Unstructured, b string) *Resource { - return &Resource{unstruct: u, behavior: b} +// NewResourceWithBehavior returns a new instance of Resource. +func NewResourceWithBehavior(obj runtime.Object, b 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 + } + var u unstructured.Unstructured + err = u.UnmarshalJSON(marshaled) + return &Resource{Unstructured: u, b: b}, nil } // NewBehaviorlessResource returns a new instance of Resource. func NewBehaviorlessResource(u *unstructured.Unstructured) *Resource { - return &Resource{unstruct: u} + return &Resource{Unstructured: *u, b: BehaviorUnspecified} } // Behavior returns the behavior for the resource. -func (r *Resource) Behavior() string { - return r.behavior -} - -// Unstruct returns the unstructured object holding the resource. -func (r *Resource) Unstruct() *unstructured.Unstructured { - return r.unstruct -} - -// SetUnstruct sets a new member. -func (r *Resource) SetUnstruct(u *unstructured.Unstructured) { - r.unstruct = u +func (r *Resource) Behavior() GenerationBehavior { + return r.b } // Id returns the ResId for the resource. func (r *Resource) Id() ResId { - var empty ResId - if r.unstruct == nil { - return empty - } - gvk := r.unstruct.GroupVersionKind() - return NewResId(gvk, r.unstruct.GetName()) + return NewResId(r.GroupVersionKind(), r.GetName()) } func (r *Resource) Merge(other *Resource) { r.Replace(other) - mergeConfigmap(r.unstruct.Object, other.unstruct.Object, r.unstruct.Object) + mergeConfigmap(r.Object, other.Object, r.Object) } func (r *Resource) Replace(other *Resource) { - r.unstruct.SetLabels(mergeStringMaps(other.unstruct.GetLabels(), r.unstruct.GetLabels())) - r.unstruct.SetAnnotations(mergeStringMaps(other.unstruct.GetAnnotations(), r.unstruct.GetAnnotations())) - r.unstruct.SetName(other.unstruct.GetName()) + r.SetLabels(mergeStringMaps(other.GetLabels(), r.GetLabels())) + r.SetAnnotations(mergeStringMaps(other.GetAnnotations(), r.GetAnnotations())) + r.SetName(other.GetName()) } // TODO: Add BinaryData once we sync to new k8s.io/api diff --git a/pkg/transformers/labelsandannotations.go b/pkg/transformers/labelsandannotations.go index 7d976aa33..8f3f7c249 100644 --- a/pkg/transformers/labelsandannotations.go +++ b/pkg/transformers/labelsandannotations.go @@ -57,8 +57,7 @@ func NewMapTransformer(pc []PathConfig, m map[string]string) (Transformer, error // fields specified in mapTransformer. func (o *mapTransformer) Transform(m resmap.ResMap) error { for id := range m { - obj := m[id].Unstruct() - objMap := obj.UnstructuredContent() + objMap := m[id].UnstructuredContent() for _, path := range o.pathConfigs { if !selectByGVK(id.Gvk(), path.GroupVersionKind) { continue diff --git a/pkg/transformers/namehash.go b/pkg/transformers/namehash.go index 861c53ea0..52e72f51a 100644 --- a/pkg/transformers/namehash.go +++ b/pkg/transformers/namehash.go @@ -22,8 +22,8 @@ import ( "github.com/kubernetes-sigs/kustomize/pkg/hash" "github.com/kubernetes-sigs/kustomize/pkg/resmap" + "github.com/kubernetes-sigs/kustomize/pkg/resource" "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" ) @@ -40,20 +40,20 @@ func NewNameHashTransformer() Transformer { // Transform appends hash to configmaps and secrets. func (o *nameHashTransformer) Transform(m resmap.ResMap) error { - for id, obj := range m { + for id, res := range m { switch { case selectByGVK(id.Gvk(), &schema.GroupVersionKind{Version: "v1", Kind: "ConfigMap"}): - appendHashForConfigMap(obj.Unstruct()) + appendHashForConfigMap(res) case selectByGVK(id.Gvk(), &schema.GroupVersionKind{Version: "v1", Kind: "Secret"}): - appendHashForSecret(obj.Unstruct()) + appendHashForSecret(res) } } return nil } -func appendHashForConfigMap(obj *unstructured.Unstructured) error { - cm, err := unstructuredToConfigmap(obj) +func appendHashForConfigMap(res *resource.Resource) error { + cm, err := unstructuredToConfigmap(res) if err != nil { return err } @@ -61,14 +61,14 @@ func appendHashForConfigMap(obj *unstructured.Unstructured) error { if err != nil { return err } - nameWithHash := fmt.Sprintf("%s-%s", obj.GetName(), h) - obj.SetName(nameWithHash) + nameWithHash := fmt.Sprintf("%s-%s", res.GetName(), h) + res.SetName(nameWithHash) return nil } // TODO: Remove this function after we support hash unstructured objects -func unstructuredToConfigmap(in *unstructured.Unstructured) (*v1.ConfigMap, error) { - marshaled, err := json.Marshal(in) +func unstructuredToConfigmap(res *resource.Resource) (*v1.ConfigMap, error) { + marshaled, err := json.Marshal(res) if err != nil { return nil, err } @@ -77,8 +77,8 @@ func unstructuredToConfigmap(in *unstructured.Unstructured) (*v1.ConfigMap, erro return &out, err } -func appendHashForSecret(obj *unstructured.Unstructured) error { - secret, err := unstructuredToSecret(obj) +func appendHashForSecret(res *resource.Resource) error { + secret, err := unstructuredToSecret(res) if err != nil { return err } @@ -86,14 +86,14 @@ func appendHashForSecret(obj *unstructured.Unstructured) error { if err != nil { return err } - nameWithHash := fmt.Sprintf("%s-%s", obj.GetName(), h) - obj.SetName(nameWithHash) + nameWithHash := fmt.Sprintf("%s-%s", res.GetName(), h) + res.SetName(nameWithHash) return nil } // TODO: Remove this function after we support hash unstructured objects -func unstructuredToSecret(in *unstructured.Unstructured) (*v1.Secret, error) { - marshaled, err := json.Marshal(in) +func unstructuredToSecret(res *resource.Resource) (*v1.Secret, error) { + marshaled, err := json.Marshal(res) if err != nil { return nil, err } diff --git a/pkg/transformers/namereference.go b/pkg/transformers/namereference.go index 68d23230f..eb49611d1 100644 --- a/pkg/transformers/namereference.go +++ b/pkg/transformers/namereference.go @@ -49,11 +49,9 @@ func NewNameReferenceTransformer(pc []referencePathConfig) (Transformer, error) // The old name is in the key in the map and the new name is in the object // associated with the key. e.g. if is one of the key-value pair in the map, // then the old name is k.Name and the new name is v.GetName() -func (o *nameReferenceTransformer) Transform( - m resmap.ResMap) error { +func (o *nameReferenceTransformer) Transform(m resmap.ResMap) error { for id := range m { - obj := m[id].Unstruct() - objMap := obj.UnstructuredContent() + objMap := m[id].UnstructuredContent() for _, referencePathConfig := range o.pathConfigs { for _, path := range referencePathConfig.pathConfigs { if !selectByGVK(id.Gvk(), path.GroupVersionKind) { @@ -71,21 +69,19 @@ func (o *nameReferenceTransformer) Transform( } func (o *nameReferenceTransformer) updateNameReference( - GVK schema.GroupVersionKind, - m resmap.ResMap, -) func(in interface{}) (interface{}, error) { + GVK schema.GroupVersionKind, m resmap.ResMap) func(in interface{}) (interface{}, error) { return func(in interface{}) (interface{}, error) { s, ok := in.(string) if !ok { return nil, fmt.Errorf("%#v is expectd to be %T", in, s) } - for id, obj := range m { + for id, res := range m { if !selectByGVK(id.Gvk(), &GVK) { continue } if id.Name() == s { - return obj.Unstruct().GetName(), nil + return res.GetName(), nil } } return in, nil diff --git a/pkg/transformers/namespace.go b/pkg/transformers/namespace.go index 3d118ce38..cc161ccf6 100644 --- a/pkg/transformers/namespace.go +++ b/pkg/transformers/namespace.go @@ -36,8 +36,8 @@ func NewNamespaceTransformer(ns string) Transformer { // Transform adds the namespace. func (o *namespaceTransformer) Transform(m resmap.ResMap) error { - for _, obj := range m { - obj.Unstruct().SetNamespace(o.namespace) + for _, res := range m { + res.SetNamespace(o.namespace) } return nil } diff --git a/pkg/transformers/overlay.go b/pkg/transformers/overlay.go index 23ca61486..ae3c765e8 100644 --- a/pkg/transformers/overlay.go +++ b/pkg/transformers/overlay.go @@ -24,7 +24,6 @@ import ( "github.com/kubernetes-sigs/kustomize/pkg/resmap" "github.com/kubernetes-sigs/kustomize/pkg/resource" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/client-go/kubernetes/scheme" @@ -63,15 +62,15 @@ func (o *overlayTransformer) Transform(baseResourceMap resmap.ResMap) error { } merged := map[string]interface{}{} versionedObj, err := scheme.Scheme.New(id.Gvk()) - baseName := base.Unstruct().GetName() + baseName := base.GetName() switch { case runtime.IsNotRegisteredError(err): // Use JSON merge patch to handle types w/o schema - baseBytes, err := json.Marshal(base.Unstruct()) + baseBytes, err := json.Marshal(base) if err != nil { return err } - patchBytes, err := json.Marshal(overlay.Unstruct()) + patchBytes, err := json.Marshal(overlay) if err != nil { return err } @@ -95,15 +94,15 @@ func (o *overlayTransformer) Transform(baseResourceMap resmap.ResMap) error { return err } merged, err = strategicpatch.StrategicMergeMapPatchUsingLookupPatchMeta( - base.Unstruct().Object, - overlay.Unstruct().Object, + base.Object, + overlay.Object, lookupPatchMeta) if err != nil { return err } } - base.Unstruct().SetName(baseName) - baseResourceMap[id].Unstruct().Object = merged + base.SetName(baseName) + baseResourceMap[id].Object = merged } return nil } @@ -112,7 +111,6 @@ func (o *overlayTransformer) Transform(baseResourceMap resmap.ResMap) error { // It errors out if there is conflict between patches. func (o *overlayTransformer) mergePatches() (resmap.ResMap, error) { rc := resmap.ResMap{} - patches := resourcesToObjects(o.overlay) for ix, patch := range o.overlay { id := patch.Id() existing, found := rc[id] @@ -135,31 +133,22 @@ func (o *overlayTransformer) mergePatches() (resmap.ResMap, error) { } } - conflict, err := cd.hasConflict(existing.Unstruct(), patch.Unstruct()) + conflict, err := cd.hasConflict(existing, patch) if err != nil { return nil, err } if conflict { - conflictingPatch, err := cd.findConflict(ix, patches) + conflictingPatch, err := cd.findConflict(ix, o.overlay) if err != nil { return nil, err } - return nil, fmt.Errorf("there is conflict between %#v and %#v", conflictingPatch.Object, patch.Unstruct().Object) - } else { - merged, err := cd.mergePatches(existing.Unstruct(), patch.Unstruct()) - if err != nil { - return nil, err - } - existing.SetUnstruct(merged) + return nil, fmt.Errorf("there is conflict between %#v and %#v", conflictingPatch.Object, patch.Object) } + merged, err := cd.mergePatches(existing, patch) + if err != nil { + return nil, err + } + rc[id] = merged } return rc, nil } - -func resourcesToObjects(rs []*resource.Resource) []*unstructured.Unstructured { - objectList := make([]*unstructured.Unstructured, len(rs)) - for i := range rs { - objectList[i] = rs[i].Unstruct() - } - return objectList -} diff --git a/pkg/transformers/overlayconflictdetector.go b/pkg/transformers/overlayconflictdetector.go index 6a0d30587..4c9dca7e2 100644 --- a/pkg/transformers/overlayconflictdetector.go +++ b/pkg/transformers/overlayconflictdetector.go @@ -19,18 +19,18 @@ package transformers import ( "encoding/json" - jsonpatch "github.com/evanphx/json-patch" + "github.com/evanphx/json-patch" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "github.com/kubernetes-sigs/kustomize/pkg/resource" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/mergepatch" "k8s.io/apimachinery/pkg/util/strategicpatch" ) type conflictDetector interface { - hasConflict(patch1, patch2 *unstructured.Unstructured) (bool, error) - findConflict(conflictingPatchIdx int, patches []*unstructured.Unstructured) (*unstructured.Unstructured, error) - mergePatches(patch1, patch2 *unstructured.Unstructured) (*unstructured.Unstructured, error) + hasConflict(patch1, patch2 *resource.Resource) (bool, error) + findConflict(conflictingPatchIdx int, patches []*resource.Resource) (*resource.Resource, error) + mergePatches(patch1, patch2 *resource.Resource) (*resource.Resource, error) } type jsonMergePatch struct{} @@ -41,11 +41,11 @@ func newJMPConflictDetector() conflictDetector { return &jsonMergePatch{} } -func (jmp *jsonMergePatch) hasConflict(patch1, patch2 *unstructured.Unstructured) (bool, error) { +func (jmp *jsonMergePatch) hasConflict(patch1, patch2 *resource.Resource) (bool, error) { return mergepatch.HasConflicts(patch1.Object, patch2.Object) } -func (jmp *jsonMergePatch) findConflict(conflictingPatchIdx int, patches []*unstructured.Unstructured) (*unstructured.Unstructured, error) { +func (jmp *jsonMergePatch) findConflict(conflictingPatchIdx int, patches []*resource.Resource) (*resource.Resource, error) { for i, patch := range patches { if i == conflictingPatchIdx { continue @@ -65,8 +65,8 @@ func (jmp *jsonMergePatch) findConflict(conflictingPatchIdx int, patches []*unst return nil, nil } -func (jmp *jsonMergePatch) mergePatches(patch1, patch2 *unstructured.Unstructured) (*unstructured.Unstructured, error) { - var merged unstructured.Unstructured +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) if err != nil { @@ -96,11 +96,11 @@ func newSMPConflictDetector(versionedObj runtime.Object) (conflictDetector, erro return &strategicMergePatch{lookupPatchMeta: lookupPatchMeta}, err } -func (smp *strategicMergePatch) hasConflict(patch1, patch2 *unstructured.Unstructured) (bool, error) { +func (smp *strategicMergePatch) hasConflict(patch1, patch2 *resource.Resource) (bool, error) { return strategicpatch.MergingMapsHaveConflicts(patch1.Object, patch2.Object, smp.lookupPatchMeta) } -func (smp *strategicMergePatch) findConflict(conflictingPatchIdx int, patches []*unstructured.Unstructured) (*unstructured.Unstructured, error) { +func (smp *strategicMergePatch) findConflict(conflictingPatchIdx int, patches []*resource.Resource) (*resource.Resource, error) { for i, patch := range patches { if i == conflictingPatchIdx { continue @@ -121,8 +121,8 @@ func (smp *strategicMergePatch) findConflict(conflictingPatchIdx int, patches [] return nil, nil } -func (smp *strategicMergePatch) mergePatches(patch1, patch2 *unstructured.Unstructured) (*unstructured.Unstructured, error) { - merged := unstructured.Unstructured{} +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) diff --git a/pkg/transformers/prefixname.go b/pkg/transformers/prefixname.go index 1bc9070bb..81e1608c9 100644 --- a/pkg/transformers/prefixname.go +++ b/pkg/transformers/prefixname.go @@ -58,8 +58,7 @@ func NewNamePrefixTransformer(pc []PathConfig, np string) (Transformer, error) { // Transform prepends the name prefix. func (o *namePrefixTransformer) Transform(m resmap.ResMap) error { for id := range m { - obj := m[id].Unstruct() - objMap := obj.UnstructuredContent() + objMap := m[id].UnstructuredContent() for _, path := range o.pathConfigs { if !selectByGVK(id.Gvk(), path.GroupVersionKind) { continue diff --git a/pkg/transformers/refvars.go b/pkg/transformers/refvars.go index b572178d0..1be055e95 100644 --- a/pkg/transformers/refvars.go +++ b/pkg/transformers/refvars.go @@ -45,8 +45,7 @@ func NewRefVarTransformer(vars map[string]string) (Transformer, error) { // 3. Add remaining service environment vars func (rv *refvarTransformer) Transform(resources resmap.ResMap) error { for GVKn := range resources { - obj := resources[GVKn].Unstruct() - objMap := obj.UnstructuredContent() + objMap := resources[GVKn].UnstructuredContent() for _, pc := range rv.pathConfigs { if !selectByGVK(GVKn.Gvk(), pc.GroupVersionKind) { continue