Merge pull request #370 from mengqiy/multiple_patches
support multiple patches for the same GVKN
This commit is contained in:
commit
09240ed0d4
|
|
@ -86,7 +86,7 @@ func (a *applicationImpl) Resources() (resource.ResourceCollection, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
patches, err := resource.NewFromPaths(a.loader, a.manifest.Patches)
|
patches, err := resource.NewFromPatches(a.loader, a.manifest.Patches)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs.Append(err)
|
errs.Append(err)
|
||||||
}
|
}
|
||||||
|
|
@ -121,7 +121,7 @@ func (a *applicationImpl) Resources() (resource.ResourceCollection, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
t, err := a.getTransformer(patches)
|
t, err := a.getTransformer()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -136,7 +136,7 @@ func (a *applicationImpl) Resources() (resource.ResourceCollection, error) {
|
||||||
// RawResources computes and returns the raw resources from the manifest.
|
// RawResources computes and returns the raw resources from the manifest.
|
||||||
func (a *applicationImpl) RawResources() (resource.ResourceCollection, error) {
|
func (a *applicationImpl) RawResources() (resource.ResourceCollection, error) {
|
||||||
subAppResources, errs := a.subAppResources()
|
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 {
|
if err != nil {
|
||||||
errs.Append(err)
|
errs.Append(err)
|
||||||
}
|
}
|
||||||
|
|
@ -182,7 +182,7 @@ func (a *applicationImpl) subAppResources() (resource.ResourceCollection, *inter
|
||||||
// 2) apply labels
|
// 2) apply labels
|
||||||
// 3) apply annotations
|
// 3) apply annotations
|
||||||
// 4) update name reference
|
// 4) update name reference
|
||||||
func (a *applicationImpl) getTransformer(patches resource.ResourceCollection) (transformers.Transformer, error) {
|
func (a *applicationImpl) getTransformer() (transformers.Transformer, error) {
|
||||||
ts := []transformers.Transformer{}
|
ts := []transformers.Transformer{}
|
||||||
|
|
||||||
npt, err := transformers.NewDefaultingNamePrefixTransformer(string(a.manifest.NamePrefix))
|
npt, err := transformers.NewDefaultingNamePrefixTransformer(string(a.manifest.NamePrefix))
|
||||||
|
|
|
||||||
|
|
@ -20,20 +20,16 @@ import (
|
||||||
"k8s.io/kubectl/pkg/loader"
|
"k8s.io/kubectl/pkg/loader"
|
||||||
)
|
)
|
||||||
|
|
||||||
func resourcesFromPath(loader loader.Loader, path 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 {
|
||||||
content, err := loader.Load(path)
|
content, err := loader.Load(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return decodeToResourceCollection(content)
|
res, err := 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) {
|
|
||||||
allResources := []ResourceCollection{}
|
|
||||||
for _, path := range paths {
|
|
||||||
res, err := resourcesFromPath(loader, path)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -41,3 +37,21 @@ func NewFromPaths(loader loader.Loader, paths []string) (ResourceCollection, err
|
||||||
}
|
}
|
||||||
return Merge(allResources...)
|
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
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
if len(resources) != 2 {
|
||||||
t.Fatalf("%#v should contain 2 appResource, but got %d", resources, len(resources))
|
t.Fatalf("%#v should contain 2 appResource, but got %d", resources, len(resources))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,13 +23,12 @@ import (
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
k8syaml "k8s.io/apimachinery/pkg/util/yaml"
|
k8syaml "k8s.io/apimachinery/pkg/util/yaml"
|
||||||
"k8s.io/kubectl/pkg/kinflate/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// decode decodes a list of objects in byte array format
|
// 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)
|
decoder := k8syaml.NewYAMLOrJSONDecoder(bytes.NewReader(in), 1024)
|
||||||
objs := []*unstructured.Unstructured{}
|
resources := []*Resource{}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
for {
|
for {
|
||||||
|
|
@ -38,32 +37,29 @@ func decode(in []byte) ([]*unstructured.Unstructured, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
objs = append(objs, &out)
|
resources = append(resources, &Resource{Data: &out})
|
||||||
}
|
}
|
||||||
if err != io.EOF {
|
if err != io.EOF {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return objs, nil
|
return resources, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// decodeToResourceCollection decodes a list of objects in byte array format.
|
// decodeToResourceCollection decodes a list of objects in byte array format.
|
||||||
// it will return a ResourceCollection.
|
// it will return a ResourceCollection.
|
||||||
func decodeToResourceCollection(in []byte) (ResourceCollection, error) {
|
func decodeToResourceCollection(in []byte) (ResourceCollection, error) {
|
||||||
objs, err := decode(in)
|
resources, err := decode(in)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
into := ResourceCollection{}
|
into := ResourceCollection{}
|
||||||
for i, obj := range objs {
|
for _, res := range resources {
|
||||||
gvkn := types.GroupVersionKindName{
|
gvkn := res.GVKN()
|
||||||
GVK: obj.GroupVersionKind(),
|
|
||||||
Name: obj.GetName(),
|
|
||||||
}
|
|
||||||
if _, found := into[gvkn]; found {
|
if _, found := into[gvkn]; found {
|
||||||
return into, fmt.Errorf("GroupVersionKindName: %#v already exists in the map", gvkn)
|
return into, fmt.Errorf("GroupVersionKindName: %#v already exists in the map", gvkn)
|
||||||
}
|
}
|
||||||
into[gvkn] = &Resource{Data: objs[i]}
|
into[gvkn] = res
|
||||||
}
|
}
|
||||||
return into, nil
|
return into, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,13 +30,13 @@ import (
|
||||||
|
|
||||||
// overlayTransformer contains a map of overlay objects
|
// overlayTransformer contains a map of overlay objects
|
||||||
type overlayTransformer struct {
|
type overlayTransformer struct {
|
||||||
overlay resource.ResourceCollection
|
overlay []*resource.Resource
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Transformer = &overlayTransformer{}
|
var _ Transformer = &overlayTransformer{}
|
||||||
|
|
||||||
// NewOverlayTransformer constructs a overlayTransformer.
|
// NewOverlayTransformer constructs a overlayTransformer.
|
||||||
func NewOverlayTransformer(overlay resource.ResourceCollection) (Transformer, error) {
|
func NewOverlayTransformer(overlay []*resource.Resource) (Transformer, error) {
|
||||||
if len(overlay) == 0 {
|
if len(overlay) == 0 {
|
||||||
return NewNoOpTransformer(), nil
|
return NewNoOpTransformer(), nil
|
||||||
}
|
}
|
||||||
|
|
@ -46,8 +46,9 @@ func NewOverlayTransformer(overlay resource.ResourceCollection) (Transformer, er
|
||||||
// Transform apply the overlay on top of the base resources.
|
// Transform apply the overlay on top of the base resources.
|
||||||
func (o *overlayTransformer) Transform(baseResourceMap resource.ResourceCollection) error {
|
func (o *overlayTransformer) Transform(baseResourceMap resource.ResourceCollection) error {
|
||||||
// Strategic merge the resources exist in both base and overlay.
|
// 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.
|
// Merge overlay with base resource.
|
||||||
|
gvkn := overlay.GVKN()
|
||||||
base, found := baseResourceMap[gvkn]
|
base, found := baseResourceMap[gvkn]
|
||||||
if !found {
|
if !found {
|
||||||
return fmt.Errorf("failed to find an object with %#v to apply the patch", gvkn.GVK)
|
return fmt.Errorf("failed to find an object with %#v to apply the patch", gvkn.GVK)
|
||||||
|
|
|
||||||
|
|
@ -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{
|
Data: &unstructured.Unstructured{
|
||||||
Object: map[string]interface{}{
|
Object: map[string]interface{}{
|
||||||
"apiVersion": "apps/v1",
|
"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{
|
Data: &unstructured.Unstructured{
|
||||||
Object: map[string]interface{}{
|
Object: map[string]interface{}{
|
||||||
"apiVersion": "example.com/v1",
|
"apiVersion": "example.com/v1",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue