mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-12 01:14:22 +00:00
Merge pull request #2713 from Shell32-Natsu/empty-list-in-patch
Keep empty array in output
This commit is contained in:
48
api/krusty/keepemptyarray_test.go
Normal file
48
api/krusty/keepemptyarray_test.go
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package krusty_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestKeepEmptyArray(t *testing.T) {
|
||||||
|
th := kusttest_test.MakeHarness(t)
|
||||||
|
th.WriteF("/app/resources.yaml", `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: testing123
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector: null
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: event
|
||||||
|
image: testing123
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
imagePullSecrets: []`)
|
||||||
|
|
||||||
|
th.WriteK("/app", `
|
||||||
|
resources:
|
||||||
|
- resources.yaml`)
|
||||||
|
|
||||||
|
m := th.Run("/app", th.MakeDefaultOptions())
|
||||||
|
th.AssertActualEqualsExpected(m, `
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: testing123
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector: null
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: testing123
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
name: event
|
||||||
|
imagePullSecrets: []
|
||||||
|
`)
|
||||||
|
}
|
||||||
@@ -16,3 +16,8 @@ exclude (
|
|||||||
github.com/russross/blackfriday v2.0.0+incompatible
|
github.com/russross/blackfriday v2.0.0+incompatible
|
||||||
sigs.k8s.io/kustomize/api v0.2.0
|
sigs.k8s.io/kustomize/api v0.2.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
replace (
|
||||||
|
sigs.k8s.io/kustomize/api => ../api
|
||||||
|
sigs.k8s.io/kustomize/kyaml => ../kyaml
|
||||||
|
)
|
||||||
|
|||||||
@@ -28,27 +28,20 @@ func NullNode() *RNode {
|
|||||||
|
|
||||||
// IsMissingOrNull returns true if the RNode is nil or contains and explicitly null value.
|
// IsMissingOrNull returns true if the RNode is nil or contains and explicitly null value.
|
||||||
func IsMissingOrNull(node *RNode) bool {
|
func IsMissingOrNull(node *RNode) bool {
|
||||||
if node == nil || node.YNode() == nil || node.YNode().Tag == NullNodeTag {
|
return node == nil || node.YNode() == nil || node.YNode().Tag == NullNodeTag
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsEmpty returns true if the RNode is MissingOrNull, or is either a MappingNode with
|
// IsEmpty returns true if the RNode is MissingOrNull, or is either a MappingNode with
|
||||||
// no fields, or a SequenceNode with no elements.
|
// no fields.
|
||||||
func IsEmpty(node *RNode) bool {
|
func IsEmpty(node *RNode) bool {
|
||||||
if node == nil || node.YNode() == nil || node.YNode().Tag == NullNodeTag {
|
if IsMissingOrNull(node) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.YNode().Kind == yaml.MappingNode && len(node.YNode().Content) == 0 {
|
// Empty sequence is a special case and temporarily not considered as empty here.
|
||||||
return true
|
// Some users may want to keep empty sequence for compatibility reason.
|
||||||
}
|
// For example, use JSON 6902 patch.
|
||||||
if node.YNode().Kind == yaml.SequenceNode && len(node.YNode().Content) == 0 {
|
return node.YNode().Kind == yaml.MappingNode && len(node.YNode().Content) == 0
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsNull(node *RNode) bool {
|
func IsNull(node *RNode) bool {
|
||||||
@@ -189,6 +182,28 @@ func NewListRNode(values ...string) *RNode {
|
|||||||
return seq
|
return seq
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewMapRNode returns a new Map *RNode containing the provided values
|
||||||
|
func NewMapRNode(values *map[string]string) *RNode {
|
||||||
|
m := &RNode{value: &yaml.Node{
|
||||||
|
Kind: yaml.MappingNode,
|
||||||
|
}}
|
||||||
|
if values == nil {
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range *values {
|
||||||
|
m.value.Content = append(m.value.Content, &yaml.Node{
|
||||||
|
Kind: yaml.ScalarNode,
|
||||||
|
Value: k,
|
||||||
|
}, &yaml.Node{
|
||||||
|
Kind: yaml.ScalarNode,
|
||||||
|
Value: v,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
// NewRNode returns a new RNode pointer containing the provided Node.
|
// NewRNode returns a new RNode pointer containing the provided Node.
|
||||||
func NewRNode(value *yaml.Node) *RNode {
|
func NewRNode(value *yaml.Node) *RNode {
|
||||||
return &RNode{value: value}
|
return &RNode{value: value}
|
||||||
|
|||||||
@@ -166,3 +166,74 @@ type: string
|
|||||||
}
|
}
|
||||||
assert.Equal(t, expected, actual)
|
assert.Equal(t, expected, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsMissingOrNull(t *testing.T) {
|
||||||
|
if !IsMissingOrNull(nil) {
|
||||||
|
t.Fatalf("input: nil")
|
||||||
|
}
|
||||||
|
// missing value or null value
|
||||||
|
if !IsMissingOrNull(NewRNode(nil)) {
|
||||||
|
t.Fatalf("input: nil value")
|
||||||
|
}
|
||||||
|
|
||||||
|
if IsMissingOrNull(NewScalarRNode("foo")) {
|
||||||
|
t.Fatalf("input: valid node")
|
||||||
|
}
|
||||||
|
// node with NullNodeTag
|
||||||
|
if !IsMissingOrNull(NullNode()) {
|
||||||
|
t.Fatalf("input: with NullNodeTag")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsEmpty(t *testing.T) {
|
||||||
|
if !IsEmpty(nil) {
|
||||||
|
t.Fatalf("input: nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
// missing value or null value
|
||||||
|
if !IsEmpty(NewRNode(nil)) {
|
||||||
|
t.Fatalf("input: nil value")
|
||||||
|
}
|
||||||
|
// not array or map
|
||||||
|
if IsEmpty(NewScalarRNode("foo")) {
|
||||||
|
t.Fatalf("input: not array or map")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsEmpty_Arrays(t *testing.T) {
|
||||||
|
node := NewListRNode()
|
||||||
|
// empty array. empty array is not expected as empty
|
||||||
|
if IsEmpty(node) {
|
||||||
|
t.Fatalf("input: empty array")
|
||||||
|
}
|
||||||
|
// array with 1 item
|
||||||
|
node = NewListRNode("foo")
|
||||||
|
if IsEmpty(node) {
|
||||||
|
t.Fatalf("input: array with 1 item")
|
||||||
|
}
|
||||||
|
// delete the item in array
|
||||||
|
node.value.Content = nil
|
||||||
|
if IsEmpty(node) {
|
||||||
|
t.Fatalf("input: empty array")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsEmpty_Maps(t *testing.T) {
|
||||||
|
node := NewMapRNode(nil)
|
||||||
|
// empty map
|
||||||
|
if !IsEmpty(node) {
|
||||||
|
t.Fatalf("input: empty map")
|
||||||
|
}
|
||||||
|
// map with 1 item
|
||||||
|
node = NewMapRNode(&map[string]string{
|
||||||
|
"foo": "bar",
|
||||||
|
})
|
||||||
|
if IsEmpty(node) {
|
||||||
|
t.Fatalf("input: map with 1 item")
|
||||||
|
}
|
||||||
|
// delete the item in map
|
||||||
|
node.value.Content = nil
|
||||||
|
if !IsEmpty(node) {
|
||||||
|
t.Fatalf("input: empty map")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user