kustomize transformers to create fields if they are null

This commit is contained in:
Phillip Wittrock
2020-05-15 12:30:59 -07:00
parent dd3a79bcf7
commit 77b5a4a215
11 changed files with 143 additions and 0 deletions

View File

@@ -32,6 +32,7 @@ func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
FsSlice: f.FsSlice,
SetValue: fsslice.SetEntry(k, f.Annotations[k], yaml.StringTag),
CreateKind: yaml.MappingNode, // Annotations are MappingNodes.
CreateTag: "!!map",
}); err != nil {
return nil, err
}

View File

@@ -186,6 +186,30 @@ metadata:
"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 {

View File

@@ -23,6 +23,8 @@ type fieldSpecFilter struct {
// CreateKind defines the type of node to create if the field is not found
CreateKind yaml.Kind
CreateTag string
// path keeps internal state about the current path
path []string
}
@@ -63,6 +65,8 @@ func (fltr fieldSpecFilter) field(obj *yaml.RNode) error {
// lookup the field matching the next path element
var lookupField yaml.Filter
var kind yaml.Kind
var tag string
switch {
case !fltr.FieldSpec.CreateIfNotPresent || fltr.CreateKind == 0 || isSeq:
// 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:
// create the field if it is missing: use the provided node kind
lookupField = yaml.LookupCreate(fltr.CreateKind, fieldName)
kind = fltr.CreateKind
tag = fltr.CreateTag
default:
// create the field if it is missing: must be a mapping node
lookupField = yaml.LookupCreate(yaml.MappingNode, fieldName)
kind = yaml.MappingNode
tag = "!!map"
}
// 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)
}
// 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
var next = fltr
// call filter for the next path element on the matching field

View File

@@ -49,6 +49,9 @@ type Filter struct {
// CreateKind is used to create fields that do not exist
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) {
@@ -60,6 +63,7 @@ func (fltr Filter) Filter(obj *yaml.RNode) (*yaml.RNode, error) {
FieldSpec: fltr.FsSlice[i],
SetValue: fltr.SetValue,
CreateKind: fltr.CreateKind,
CreateTag: fltr.CreateTag,
}).Filter(obj)
if err != nil {
return nil, err

View File

@@ -33,6 +33,7 @@ func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
FsSlice: f.FsSlice,
SetValue: fsslice.SetEntry(k, f.Labels[k], yaml.StringTag),
CreateKind: yaml.MappingNode, // Labels are MappingNodes.
CreateTag: "!!map",
}); err != nil {
return nil, err
}

View File

@@ -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 {

View File

@@ -44,6 +44,7 @@ func (ns Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
FsSlice: ns.FsSlice,
SetValue: fsslice.SetScalar(ns.Namespace),
CreateKind: yaml.ScalarNode, // Namespace is a ScalarNode
CreateTag: yaml.StringTag,
})
return node, err
}

View File

@@ -44,6 +44,37 @@ metadata:
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",
input: `

View File

@@ -33,6 +33,7 @@ func (ns Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
FsSlice: ns.FsSlice,
SetValue: ns.set,
CreateKind: yaml.ScalarNode, // Name is a ScalarNode
CreateTag: yaml.StringTag,
})
return node, err
}

View File

@@ -39,6 +39,7 @@ func (rc Filter) run(node *yaml.RNode) (*yaml.RNode, error) {
FsSlice: rc.FsSlice,
SetValue: rc.set,
CreateKind: yaml.ScalarNode, // replicas is a ScalarNode
CreateTag: yaml.IntTag,
})
return node, err
}

View File

@@ -61,6 +61,41 @@ spec:
expected: `
apiVersion: custom/v1
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:
name: cus
spec: