mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-07-17 17:52:12 +00:00
kustomize transformers to create fields if they are null
This commit is contained in:
@@ -32,6 +32,7 @@ func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
|||||||
FsSlice: f.FsSlice,
|
FsSlice: f.FsSlice,
|
||||||
SetValue: fsslice.SetEntry(k, f.Annotations[k], yaml.StringTag),
|
SetValue: fsslice.SetEntry(k, f.Annotations[k], yaml.StringTag),
|
||||||
CreateKind: yaml.MappingNode, // Annotations are MappingNodes.
|
CreateKind: yaml.MappingNode, // Annotations are MappingNodes.
|
||||||
|
CreateTag: "!!map",
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,6 +186,30 @@ metadata:
|
|||||||
"f": "true1",
|
"f": "true1",
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// test quoting of values which are not considered strings in yaml 1.1
|
||||||
|
"null_annotations": {
|
||||||
|
input: `
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
|
name: instance
|
||||||
|
annotations: null
|
||||||
|
`,
|
||||||
|
expectedOutput: `
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
|
name: instance
|
||||||
|
annotations:
|
||||||
|
a: a1
|
||||||
|
b: b1
|
||||||
|
`,
|
||||||
|
filter: Filter{Annotations: annoMap{
|
||||||
|
"a": "a1",
|
||||||
|
"b": "b1",
|
||||||
|
}},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for tn, tc := range testCases {
|
for tn, tc := range testCases {
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ type fieldSpecFilter struct {
|
|||||||
// CreateKind defines the type of node to create if the field is not found
|
// CreateKind defines the type of node to create if the field is not found
|
||||||
CreateKind yaml.Kind
|
CreateKind yaml.Kind
|
||||||
|
|
||||||
|
CreateTag string
|
||||||
|
|
||||||
// path keeps internal state about the current path
|
// path keeps internal state about the current path
|
||||||
path []string
|
path []string
|
||||||
}
|
}
|
||||||
@@ -63,6 +65,8 @@ func (fltr fieldSpecFilter) field(obj *yaml.RNode) error {
|
|||||||
|
|
||||||
// lookup the field matching the next path element
|
// lookup the field matching the next path element
|
||||||
var lookupField yaml.Filter
|
var lookupField yaml.Filter
|
||||||
|
var kind yaml.Kind
|
||||||
|
var tag string
|
||||||
switch {
|
switch {
|
||||||
case !fltr.FieldSpec.CreateIfNotPresent || fltr.CreateKind == 0 || isSeq:
|
case !fltr.FieldSpec.CreateIfNotPresent || fltr.CreateKind == 0 || isSeq:
|
||||||
// dont' create the field if we don't find it
|
// dont' create the field if we don't find it
|
||||||
@@ -70,9 +74,13 @@ func (fltr fieldSpecFilter) field(obj *yaml.RNode) error {
|
|||||||
case len(fltr.path) <= 1:
|
case len(fltr.path) <= 1:
|
||||||
// create the field if it is missing: use the provided node kind
|
// create the field if it is missing: use the provided node kind
|
||||||
lookupField = yaml.LookupCreate(fltr.CreateKind, fieldName)
|
lookupField = yaml.LookupCreate(fltr.CreateKind, fieldName)
|
||||||
|
kind = fltr.CreateKind
|
||||||
|
tag = fltr.CreateTag
|
||||||
default:
|
default:
|
||||||
// create the field if it is missing: must be a mapping node
|
// create the field if it is missing: must be a mapping node
|
||||||
lookupField = yaml.LookupCreate(yaml.MappingNode, fieldName)
|
lookupField = yaml.LookupCreate(yaml.MappingNode, fieldName)
|
||||||
|
kind = yaml.MappingNode
|
||||||
|
tag = "!!map"
|
||||||
}
|
}
|
||||||
|
|
||||||
// locate (or maybe create) the field
|
// locate (or maybe create) the field
|
||||||
@@ -81,6 +89,13 @@ func (fltr fieldSpecFilter) field(obj *yaml.RNode) error {
|
|||||||
return errors.WrapPrefixf(err, "fieldName: %s", fieldName)
|
return errors.WrapPrefixf(err, "fieldName: %s", fieldName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if the value exists, but is null, then change it to the creation type
|
||||||
|
// TODO: update yaml.LookupCreate to support this
|
||||||
|
if field.YNode().Tag == "!!null" {
|
||||||
|
field.YNode().Kind = kind
|
||||||
|
field.YNode().Tag = tag
|
||||||
|
}
|
||||||
|
|
||||||
// copy the current fltr and change the path on the copy
|
// copy the current fltr and change the path on the copy
|
||||||
var next = fltr
|
var next = fltr
|
||||||
// call filter for the next path element on the matching field
|
// call filter for the next path element on the matching field
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ type Filter struct {
|
|||||||
|
|
||||||
// CreateKind is used to create fields that do not exist
|
// CreateKind is used to create fields that do not exist
|
||||||
CreateKind yaml.Kind
|
CreateKind yaml.Kind
|
||||||
|
|
||||||
|
// CreateTag is used to set the tag if encountering a null field
|
||||||
|
CreateTag string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fltr Filter) Filter(obj *yaml.RNode) (*yaml.RNode, error) {
|
func (fltr Filter) Filter(obj *yaml.RNode) (*yaml.RNode, error) {
|
||||||
@@ -60,6 +63,7 @@ func (fltr Filter) Filter(obj *yaml.RNode) (*yaml.RNode, error) {
|
|||||||
FieldSpec: fltr.FsSlice[i],
|
FieldSpec: fltr.FsSlice[i],
|
||||||
SetValue: fltr.SetValue,
|
SetValue: fltr.SetValue,
|
||||||
CreateKind: fltr.CreateKind,
|
CreateKind: fltr.CreateKind,
|
||||||
|
CreateTag: fltr.CreateTag,
|
||||||
}).Filter(obj)
|
}).Filter(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
|||||||
FsSlice: f.FsSlice,
|
FsSlice: f.FsSlice,
|
||||||
SetValue: fsslice.SetEntry(k, f.Labels[k], yaml.StringTag),
|
SetValue: fsslice.SetEntry(k, f.Labels[k], yaml.StringTag),
|
||||||
CreateKind: yaml.MappingNode, // Labels are MappingNodes.
|
CreateKind: yaml.MappingNode, // Labels are MappingNodes.
|
||||||
|
CreateTag: "!!map",
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -370,6 +370,35 @@ metadata:
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"null_labels": {
|
||||||
|
input: `
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
|
name: instance
|
||||||
|
labels: null
|
||||||
|
`,
|
||||||
|
expectedOutput: `
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
|
name: instance
|
||||||
|
labels:
|
||||||
|
a: a1
|
||||||
|
`,
|
||||||
|
filter: Filter{
|
||||||
|
Labels: labelMap{
|
||||||
|
"a": "a1",
|
||||||
|
},
|
||||||
|
FsSlice: []types.FieldSpec{
|
||||||
|
{
|
||||||
|
Path: "metadata/labels",
|
||||||
|
CreateIfNotPresent: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for tn, tc := range testCases {
|
for tn, tc := range testCases {
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ func (ns Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
|
|||||||
FsSlice: ns.FsSlice,
|
FsSlice: ns.FsSlice,
|
||||||
SetValue: fsslice.SetScalar(ns.Namespace),
|
SetValue: fsslice.SetScalar(ns.Namespace),
|
||||||
CreateKind: yaml.ScalarNode, // Namespace is a ScalarNode
|
CreateKind: yaml.ScalarNode, // Namespace is a ScalarNode
|
||||||
|
CreateTag: yaml.StringTag,
|
||||||
})
|
})
|
||||||
return node, err
|
return node, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,37 @@ metadata:
|
|||||||
filter: namespace.Filter{Namespace: "foo"},
|
filter: namespace.Filter{Namespace: "foo"},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "null_ns",
|
||||||
|
input: `
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
|
name: instance
|
||||||
|
namespace: null
|
||||||
|
---
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Bar
|
||||||
|
metadata:
|
||||||
|
name: instance
|
||||||
|
namespace: null
|
||||||
|
`,
|
||||||
|
expected: `
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
|
name: instance
|
||||||
|
namespace: foo
|
||||||
|
---
|
||||||
|
apiVersion: example.com/v1
|
||||||
|
kind: Bar
|
||||||
|
metadata:
|
||||||
|
name: instance
|
||||||
|
namespace: foo
|
||||||
|
`,
|
||||||
|
filter: namespace.Filter{Namespace: "foo"},
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "add-recurse",
|
name: "add-recurse",
|
||||||
input: `
|
input: `
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ func (ns Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
|
|||||||
FsSlice: ns.FsSlice,
|
FsSlice: ns.FsSlice,
|
||||||
SetValue: ns.set,
|
SetValue: ns.set,
|
||||||
CreateKind: yaml.ScalarNode, // Name is a ScalarNode
|
CreateKind: yaml.ScalarNode, // Name is a ScalarNode
|
||||||
|
CreateTag: yaml.StringTag,
|
||||||
})
|
})
|
||||||
return node, err
|
return node, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ func (rc Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
|
|||||||
FsSlice: rc.FsSlice,
|
FsSlice: rc.FsSlice,
|
||||||
SetValue: rc.set,
|
SetValue: rc.set,
|
||||||
CreateKind: yaml.ScalarNode, // replicas is a ScalarNode
|
CreateKind: yaml.ScalarNode, // replicas is a ScalarNode
|
||||||
|
CreateTag: yaml.IntTag,
|
||||||
})
|
})
|
||||||
return node, err
|
return node, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,41 @@ spec:
|
|||||||
expected: `
|
expected: `
|
||||||
apiVersion: custom/v1
|
apiVersion: custom/v1
|
||||||
kind: Custom
|
kind: Custom
|
||||||
|
metadata:
|
||||||
|
name: cus
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
other: something
|
||||||
|
replicas: 42
|
||||||
|
`,
|
||||||
|
filter: Filter{
|
||||||
|
Replica: types.Replica{
|
||||||
|
Name: "cus",
|
||||||
|
Count: 42,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fsslice: types.FsSlice{
|
||||||
|
{
|
||||||
|
Path: "spec/template/replicas",
|
||||||
|
CreateIfNotPresent: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"add_field_null": {
|
||||||
|
input: `
|
||||||
|
apiVersion: custom/v1
|
||||||
|
kind: Custom
|
||||||
|
metadata:
|
||||||
|
name: cus
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
other: something
|
||||||
|
replicas: null
|
||||||
|
`,
|
||||||
|
expected: `
|
||||||
|
apiVersion: custom/v1
|
||||||
|
kind: Custom
|
||||||
metadata:
|
metadata:
|
||||||
name: cus
|
name: cus
|
||||||
spec:
|
spec:
|
||||||
|
|||||||
Reference in New Issue
Block a user