Extended replacement plugin with Targets field
The user can use either `target` or `targets` that is list of several `target` objects. Change-Id: I38e457842e1250a2d048f93ba2aac9258758d163
This commit is contained in:
parent
6543f63ebf
commit
10b0385691
@ -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"`
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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).
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user