diff --git a/pkg/api/v1alpha1/replacement_plugin_types.go b/pkg/api/v1alpha1/replacement_plugin_types.go index 4ab1c50ce..f18d00306 100644 --- a/pkg/api/v1alpha1/replacement_plugin_types.go +++ b/pkg/api/v1alpha1/replacement_plugin_types.go @@ -19,6 +19,33 @@ import ( "sigs.k8s.io/kustomize/api/types" ) +// These types have been changed in kustomize 4.0.5. +// Copying the version from 3.9.2 + +// Replacement defines how to perform a substitution +// where it is from and where it is to. +type Replacement struct { + Source *ReplSource `json:"source" yaml:"source"` + Target *ReplTarget `json:"target" yaml:"target"` + Targets []*ReplTarget `json:"targets" yaml:"targets"` +} + +// ReplSource defines where a substitution is from +// It can from two different kinds of sources +// - from a field of one resource +// - from a string +type ReplSource struct { + ObjRef *types.Target `json:"objref,omitempty" yaml:"objref,omitempty"` + FieldRef string `json:"fieldref,omitempty" yaml:"fiedldref,omitempty"` + Value string `json:"value,omitempty" yaml:"value,omitempty"` +} + +// ReplTarget defines where a substitution is to. +type ReplTarget struct { + ObjRef *types.Selector `json:"objref,omitempty" yaml:"objref,omitempty"` + FieldRefs []string `json:"fieldrefs,omitempty" yaml:"fieldrefs,omitempty"` +} + // +kubebuilder:object:root=true // ReplacementTransformer plugin configuration for airship document model @@ -27,30 +54,5 @@ type ReplacementTransformer struct { metav1.ObjectMeta `json:"metadata,omitempty"` // Replacements list of source and target field to do a replacement - Replacements []types.Replacement `json:"replacements,omitempty" yaml:"replacements,omitempty"` -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ReplacementTransformer) DeepCopyInto(out *ReplacementTransformer) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - if in.Replacements != nil { - out.Replacements = make([]types.Replacement, len(in.Replacements)) - for i, repl := range in.Replacements { - out.Replacements[i] = types.Replacement{ - Source: &types.ReplSource{ - ObjRef: &types.Target{}, - FieldRef: repl.Source.FieldRef, - Value: repl.Source.Value, - }, - Target: &types.ReplTarget{ - ObjRef: &types.Selector{}, - FieldRefs: repl.Target.FieldRefs, - }, - } - *(out.Replacements[i].Source.ObjRef) = *(in.Replacements[i].Source.ObjRef) - *(out.Replacements[i].Target.ObjRef) = *(in.Replacements[i].Target.ObjRef) - } - } + Replacements []Replacement `json:"replacements,omitempty" yaml:"replacements,omitempty"` } diff --git a/pkg/api/v1alpha1/zz_generated.deepcopy.go b/pkg/api/v1alpha1/zz_generated.deepcopy.go index cd23690eb..6b595167d 100644 --- a/pkg/api/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/api/v1alpha1/zz_generated.deepcopy.go @@ -21,6 +21,7 @@ package v1alpha1 import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/kustomize/api/types" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -805,6 +806,101 @@ func (in *RemoteDirectOptions) DeepCopy() *RemoteDirectOptions { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ReplSource) DeepCopyInto(out *ReplSource) { + *out = *in + if in.ObjRef != nil { + in, out := &in.ObjRef, &out.ObjRef + *out = new(types.Target) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReplSource. +func (in *ReplSource) DeepCopy() *ReplSource { + if in == nil { + return nil + } + out := new(ReplSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ReplTarget) DeepCopyInto(out *ReplTarget) { + *out = *in + if in.ObjRef != nil { + in, out := &in.ObjRef, &out.ObjRef + *out = new(types.Selector) + **out = **in + } + if in.FieldRefs != nil { + in, out := &in.FieldRefs, &out.FieldRefs + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReplTarget. +func (in *ReplTarget) DeepCopy() *ReplTarget { + if in == nil { + return nil + } + out := new(ReplTarget) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Replacement) DeepCopyInto(out *Replacement) { + *out = *in + if in.Source != nil { + in, out := &in.Source, &out.Source + *out = new(ReplSource) + (*in).DeepCopyInto(*out) + } + if in.Target != nil { + in, out := &in.Target, &out.Target + *out = new(ReplTarget) + (*in).DeepCopyInto(*out) + } + if in.Targets != nil { + in, out := &in.Targets, &out.Targets + *out = make([]*ReplTarget, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(ReplTarget) + (*in).DeepCopyInto(*out) + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Replacement. +func (in *Replacement) DeepCopy() *Replacement { + if in == nil { + return nil + } + out := new(Replacement) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ReplacementTransformer) DeepCopyInto(out *ReplacementTransformer) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.Replacements != nil { + in, out := &in.Replacements, &out.Replacements + *out = make([]Replacement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReplacementTransformer. func (in *ReplacementTransformer) DeepCopy() *ReplacementTransformer { if in == nil { diff --git a/pkg/document/plugin/replacement/transformer.go b/pkg/document/plugin/replacement/transformer.go index 7b4cfeceb..c404a19ac 100644 --- a/pkg/document/plugin/replacement/transformer.go +++ b/pkg/document/plugin/replacement/transformer.go @@ -21,7 +21,6 @@ import ( "strings" "k8s.io/apimachinery/pkg/runtime" - "sigs.k8s.io/kustomize/api/types" "sigs.k8s.io/kustomize/kyaml/kio" "sigs.k8s.io/kustomize/kyaml/yaml" @@ -57,9 +56,12 @@ func New(obj map[string]interface{}) (kio.Filter, error) { if r.Source == nil { return nil, ErrBadConfiguration{Msg: "`from` must be specified in one replacement"} } - if r.Target == nil { + if r.Target == nil && r.Targets == nil { return nil, ErrBadConfiguration{Msg: "`to` must be specified in one replacement"} } + if r.Target != nil && r.Targets != nil { + return nil, ErrBadConfiguration{Msg: "only target OR targets is allowed in one replacement, not both"} + } if r.Source.ObjRef != nil && r.Source.Value != "" { return nil, ErrBadConfiguration{Msg: "only one of fieldref and value is allowed in one replacement"} } @@ -73,15 +75,22 @@ func (p *plugin) Filter(items []*yaml.RNode) ([]*yaml.RNode, error) { if err != nil { return nil, err } - - if err := replace(items, r.Target, val); err != nil { - return nil, err + if r.Target != nil { + if err := replace(items, r.Target, val); err != nil { + return nil, err + } + } + // range handles nil case as empty list + for _, t := range r.Targets { + if err := replace(items, t, val); err != nil { + return nil, err + } } } return items, nil } -func getValue(items []*yaml.RNode, source *types.ReplSource) (*yaml.RNode, error) { +func getValue(items []*yaml.RNode, source *airshipv1.ReplSource) (*yaml.RNode, error) { if source.Value != "" { return yaml.NewScalarRNode(source.Value), nil } @@ -128,7 +137,7 @@ func mutateField(rnSource *yaml.RNode) func([]*yaml.RNode) error { } } -func replace(items []*yaml.RNode, target *types.ReplTarget, value *yaml.RNode) error { +func replace(items []*yaml.RNode, target *airshipv1.ReplTarget, value *yaml.RNode) error { targets, err := kyamlutils.DocumentSelector{}. ByGVK(target.ObjRef.Group, target.ObjRef.Version, target.ObjRef.Kind). ByName(target.ObjRef.Name). diff --git a/pkg/document/plugin/replacement/transformer_test.go b/pkg/document/plugin/replacement/transformer_test.go index a7ea9b461..68f2b03e0 100644 --- a/pkg/document/plugin/replacement/transformer_test.go +++ b/pkg/document/plugin/replacement/transformer_test.go @@ -1225,6 +1225,143 @@ data: `, expectedErr: "Error while decoding base64 encoded string: abc", }, + { + cfg: ` +apiVersion: airshipit.org/v1alpha1 +kind: ReplacementTransformer +metadata: + name: Test_Case_25 +replacements: +- source: + value: nginx:newtag + targets: + - objref: + kind: Deployment + name: deploy1 + fieldrefs: + - spec.template.spec.containers[name=nginx.latest].image + - objref: + kind: Deployment + name: deploy2 + fieldrefs: + - spec.template.spec.containers[name=nginx.latest].image +- source: + value: postgres:latest + targets: + - objref: + kind: Deployment + name: deploy1 + fieldrefs: + - spec.template.spec.containers.3.image + - objref: + kind: Deployment + name: deploy2 + fieldrefs: + - spec.template.spec.containers.3.image +`, + + in: ` +apiVersion: v1 +group: apps +kind: Deployment +metadata: + name: deploy1 +spec: + template: + spec: + containers: + - image: nginx:1.7.9 + name: nginx-tagged + - image: nginx:latest + name: nginx.latest + - image: foobar:1 + name: replaced-with-digest + - image: postgres:1.8.0 + name: postgresdb + initContainers: + - image: nginx + name: nginx-notag + - image: nginx@sha256:111111111111111111 + name: nginx-sha256 + - image: alpine:1.8.0 + name: init-alpine +--- +apiVersion: v1 +group: apps +kind: Deployment +metadata: + name: deploy2 +spec: + template: + spec: + containers: + - image: nginx:1.7.9 + name: nginx-tagged + - image: nginx:latest + name: nginx.latest + - image: foobar:1 + name: replaced-with-digest + - image: postgres:1.8.0 + name: postgresdb + initContainers: + - image: nginx + name: nginx-notag + - image: nginx@sha256:111111111111111111 + name: nginx-sha256 + - image: alpine:1.8.0 + name: init-alpine +`, + expectedOut: `apiVersion: v1 +group: apps +kind: Deployment +metadata: + name: deploy1 +spec: + template: + spec: + containers: + - image: nginx:1.7.9 + name: nginx-tagged + - image: nginx:newtag + name: nginx.latest + - image: foobar:1 + name: replaced-with-digest + - image: postgres:latest + name: postgresdb + initContainers: + - image: nginx + name: nginx-notag + - image: nginx@sha256:111111111111111111 + name: nginx-sha256 + - image: alpine:1.8.0 + name: init-alpine +--- +apiVersion: v1 +group: apps +kind: Deployment +metadata: + name: deploy2 +spec: + template: + spec: + containers: + - image: nginx:1.7.9 + name: nginx-tagged + - image: nginx:newtag + name: nginx.latest + - image: foobar:1 + name: replaced-with-digest + - image: postgres:latest + name: postgresdb + initContainers: + - image: nginx + name: nginx-notag + - image: nginx@sha256:111111111111111111 + name: nginx-sha256 + - image: alpine:1.8.0 + name: init-alpine +`, + }, } func TestExec(t *testing.T) {