From 67532e09da9b00666a4044fefbb43cf5906cef25 Mon Sep 17 00:00:00 2001 From: Mengqi Yu Date: Thu, 22 Mar 2018 14:09:18 -0700 Subject: [PATCH] support multiple patches for the same GVKN --- pkg/kinflate/app/application.go | 8 ++--- pkg/kinflate/resource/appresource.go | 38 ++++++++++++++++------- pkg/kinflate/resource/appresource_test.go | 2 +- pkg/kinflate/resource/util.go | 20 +++++------- pkg/kinflate/transformers/overlay.go | 7 +++-- pkg/kinflate/transformers/overlay_test.go | 10 ++---- 6 files changed, 45 insertions(+), 40 deletions(-) diff --git a/pkg/kinflate/app/application.go b/pkg/kinflate/app/application.go index 4662c55bf..cc8adb975 100644 --- a/pkg/kinflate/app/application.go +++ b/pkg/kinflate/app/application.go @@ -86,7 +86,7 @@ func (a *applicationImpl) Resources() (resource.ResourceCollection, error) { return nil, err } - patches, err := resource.NewFromPaths(a.loader, a.manifest.Patches) + patches, err := resource.NewFromPatches(a.loader, a.manifest.Patches) if err != nil { errs.Append(err) } @@ -121,7 +121,7 @@ func (a *applicationImpl) Resources() (resource.ResourceCollection, error) { return nil, err } - t, err := a.getTransformer(patches) + t, err := a.getTransformer() if err != nil { return nil, err } @@ -136,7 +136,7 @@ func (a *applicationImpl) Resources() (resource.ResourceCollection, error) { // RawResources computes and returns the raw resources from the manifest. func (a *applicationImpl) RawResources() (resource.ResourceCollection, error) { subAppResources, errs := a.subAppResources() - resources, err := resource.NewFromPaths(a.loader, a.manifest.Resources) + resources, err := resource.NewFromResources(a.loader, a.manifest.Resources) if err != nil { errs.Append(err) } @@ -182,7 +182,7 @@ func (a *applicationImpl) subAppResources() (resource.ResourceCollection, *inter // 2) apply labels // 3) apply annotations // 4) update name reference -func (a *applicationImpl) getTransformer(patches resource.ResourceCollection) (transformers.Transformer, error) { +func (a *applicationImpl) getTransformer() (transformers.Transformer, error) { ts := []transformers.Transformer{} npt, err := transformers.NewDefaultingNamePrefixTransformer(string(a.manifest.NamePrefix)) diff --git a/pkg/kinflate/resource/appresource.go b/pkg/kinflate/resource/appresource.go index 43b5d72f7..65f3fd456 100644 --- a/pkg/kinflate/resource/appresource.go +++ b/pkg/kinflate/resource/appresource.go @@ -20,20 +20,16 @@ import ( "k8s.io/kubectl/pkg/loader" ) -func resourcesFromPath(loader loader.Loader, path string) (ResourceCollection, error) { - content, err := loader.Load(path) - if err != nil { - return nil, err - } - - return decodeToResourceCollection(content) -} - -// NewFromPaths returns a slice of Resources given a resource path slice from manifest file. -func NewFromPaths(loader loader.Loader, paths []string) (ResourceCollection, error) { +// NewFromResources returns a ResourceCollection given a resource path slice from manifest file. +func NewFromResources(loader loader.Loader, paths []string) (ResourceCollection, error) { allResources := []ResourceCollection{} for _, path := range paths { - res, err := resourcesFromPath(loader, path) + content, err := loader.Load(path) + if err != nil { + return nil, err + } + + res, err := decodeToResourceCollection(content) if err != nil { return nil, err } @@ -41,3 +37,21 @@ func NewFromPaths(loader loader.Loader, paths []string) (ResourceCollection, err } return Merge(allResources...) } + +// NewFromPatches returns a slice of Resources given a patch path slice from manifest file. +func NewFromPatches(loader loader.Loader, paths []string) ([]*Resource, error) { + allResources := []*Resource{} + for _, path := range paths { + content, err := loader.Load(path) + if err != nil { + return nil, err + } + + res, err := decode(content) + if err != nil { + return nil, err + } + allResources = append(allResources, res...) + } + return allResources, nil +} diff --git a/pkg/kinflate/resource/appresource_test.go b/pkg/kinflate/resource/appresource_test.go index 081bfad80..98e10736d 100644 --- a/pkg/kinflate/resource/appresource_test.go +++ b/pkg/kinflate/resource/appresource_test.go @@ -75,7 +75,7 @@ metadata: }, } - resources, _ := NewFromPaths(l, []string{"/home/seans/project/deployment.yaml"}) + resources, _ := NewFromResources(l, []string{"/home/seans/project/deployment.yaml"}) if len(resources) != 2 { t.Fatalf("%#v should contain 2 appResource, but got %d", resources, len(resources)) } diff --git a/pkg/kinflate/resource/util.go b/pkg/kinflate/resource/util.go index 35632cec8..9d06167a3 100644 --- a/pkg/kinflate/resource/util.go +++ b/pkg/kinflate/resource/util.go @@ -23,13 +23,12 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" k8syaml "k8s.io/apimachinery/pkg/util/yaml" - "k8s.io/kubectl/pkg/kinflate/types" ) // decode decodes a list of objects in byte array format -func decode(in []byte) ([]*unstructured.Unstructured, error) { +func decode(in []byte) ([]*Resource, error) { decoder := k8syaml.NewYAMLOrJSONDecoder(bytes.NewReader(in), 1024) - objs := []*unstructured.Unstructured{} + resources := []*Resource{} var err error for { @@ -38,32 +37,29 @@ func decode(in []byte) ([]*unstructured.Unstructured, error) { if err != nil { break } - objs = append(objs, &out) + resources = append(resources, &Resource{Data: &out}) } if err != io.EOF { return nil, err } - return objs, nil + return resources, nil } // decodeToResourceCollection decodes a list of objects in byte array format. // it will return a ResourceCollection. func decodeToResourceCollection(in []byte) (ResourceCollection, error) { - objs, err := decode(in) + resources, err := decode(in) if err != nil { return nil, err } into := ResourceCollection{} - for i, obj := range objs { - gvkn := types.GroupVersionKindName{ - GVK: obj.GroupVersionKind(), - Name: obj.GetName(), - } + for _, res := range resources { + gvkn := res.GVKN() if _, found := into[gvkn]; found { return into, fmt.Errorf("GroupVersionKindName: %#v already exists in the map", gvkn) } - into[gvkn] = &Resource{Data: objs[i]} + into[gvkn] = res } return into, nil } diff --git a/pkg/kinflate/transformers/overlay.go b/pkg/kinflate/transformers/overlay.go index d54c1d9c1..f60146c44 100644 --- a/pkg/kinflate/transformers/overlay.go +++ b/pkg/kinflate/transformers/overlay.go @@ -30,13 +30,13 @@ import ( // overlayTransformer contains a map of overlay objects type overlayTransformer struct { - overlay resource.ResourceCollection + overlay []*resource.Resource } var _ Transformer = &overlayTransformer{} // NewOverlayTransformer constructs a overlayTransformer. -func NewOverlayTransformer(overlay resource.ResourceCollection) (Transformer, error) { +func NewOverlayTransformer(overlay []*resource.Resource) (Transformer, error) { if len(overlay) == 0 { return NewNoOpTransformer(), nil } @@ -46,8 +46,9 @@ func NewOverlayTransformer(overlay resource.ResourceCollection) (Transformer, er // Transform apply the overlay on top of the base resources. func (o *overlayTransformer) Transform(baseResourceMap resource.ResourceCollection) error { // Strategic merge the resources exist in both base and overlay. - for gvkn, overlay := range o.overlay { + for _, overlay := range o.overlay { // Merge overlay with base resource. + gvkn := overlay.GVKN() base, found := baseResourceMap[gvkn] if !found { return fmt.Errorf("failed to find an object with %#v to apply the patch", gvkn.GVK) diff --git a/pkg/kinflate/transformers/overlay_test.go b/pkg/kinflate/transformers/overlay_test.go index 6bdd7f173..85950cde7 100644 --- a/pkg/kinflate/transformers/overlay_test.go +++ b/pkg/kinflate/transformers/overlay_test.go @@ -59,11 +59,8 @@ func TestOverlayRun(t *testing.T) { }, }, } - overlay := resource.ResourceCollection{ + overlay := []*resource.Resource{ { - GVK: schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"}, - Name: "deploy1", - }: &resource.Resource{ Data: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "apps/v1", @@ -175,11 +172,8 @@ func TestNoSchemaOverlayRun(t *testing.T) { }, }, } - overlay := resource.ResourceCollection{ + overlay := []*resource.Resource{ { - GVK: schema.GroupVersionKind{Group: "example.com", Version: "v1", Kind: "Foo"}, - Name: "my-foo", - }: &resource.Resource{ Data: &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "example.com/v1",