mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-05-17 18:25:26 +00:00
Merge pull request #3118 from brianpursley/kustomize-2893
Implement WNode methods
This commit is contained in:
@@ -6,6 +6,7 @@ require (
|
||||
github.com/evanphx/json-patch v4.5.0+incompatible
|
||||
github.com/go-openapi/spec v0.19.5
|
||||
github.com/golangci/golangci-lint v1.21.0
|
||||
github.com/google/go-cmp v0.3.0
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||
github.com/hashicorp/go-multierror v1.1.0
|
||||
github.com/pkg/errors v0.8.1
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package wrappy_test
|
||||
package wrappy
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
package wrappy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/ifc"
|
||||
"sigs.k8s.io/kustomize/api/resid"
|
||||
@@ -54,10 +56,41 @@ func (wn *WNode) GetAnnotations() map[string]string {
|
||||
|
||||
// GetFieldValue implements ifc.Kunstructured.
|
||||
func (wn *WNode) GetFieldValue(path string) (interface{}, error) {
|
||||
// The argument is a json path, e.g. "metadata.name"
|
||||
// fields := strings.Split(path, ".")
|
||||
// return wn.node.Pipe(yaml.Lookup(fields...))
|
||||
panic("TODO(#WNode): GetFieldValue; implement or drop from API")
|
||||
fields := strings.Split(path, ".")
|
||||
rn, err := wn.node.Pipe(yaml.Lookup(fields...))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if rn == nil {
|
||||
return nil, NoFieldError{path}
|
||||
}
|
||||
yn := rn.YNode()
|
||||
|
||||
// If this is an alias node, resolve it
|
||||
if yn.Kind == yaml.AliasNode {
|
||||
yn = yn.Alias
|
||||
}
|
||||
|
||||
// Return value as map for DocumentNode and MappingNode kinds
|
||||
if yn.Kind == yaml.DocumentNode || yn.Kind == yaml.MappingNode {
|
||||
var result map[string]interface{}
|
||||
if err := yn.Decode(&result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
// Return value as slice for SequenceNode kind
|
||||
if yn.Kind == yaml.SequenceNode {
|
||||
var result []interface{}
|
||||
for _, node := range yn.Content {
|
||||
result = append(result, node.Value)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Return value value directly for all other (ScalarNode) kinds
|
||||
return yn.Value, nil
|
||||
}
|
||||
|
||||
// GetGvk implements ifc.Kunstructured.
|
||||
@@ -83,18 +116,37 @@ func (wn *WNode) GetName() string {
|
||||
}
|
||||
|
||||
// GetSlice implements ifc.Kunstructured.
|
||||
func (wn *WNode) GetSlice(string) ([]interface{}, error) {
|
||||
panic("TODO(#WNode) GetSlice; implement or drop from API")
|
||||
func (wn *WNode) GetSlice(path string) ([]interface{}, error) {
|
||||
value, err := wn.GetFieldValue(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if sliceValue, ok := value.([]interface{}); ok {
|
||||
return sliceValue, nil
|
||||
}
|
||||
return nil, fmt.Errorf("node %s is not a slice", path)
|
||||
}
|
||||
|
||||
// GetSlice implements ifc.Kunstructured.
|
||||
func (wn *WNode) GetString(string) (string, error) {
|
||||
panic("TODO(#WNode) GetString; implement or drop from API")
|
||||
func (wn *WNode) GetString(path string) (string, error) {
|
||||
value, err := wn.GetFieldValue(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if v, ok := value.(string); ok {
|
||||
return v, nil
|
||||
}
|
||||
return "", fmt.Errorf("node %s is not a string: %v", path, value)
|
||||
}
|
||||
|
||||
// Map implements ifc.Kunstructured.
|
||||
func (wn *WNode) Map() map[string]interface{} {
|
||||
panic("TODO(#WNode) Map; implement or drop from API")
|
||||
var result map[string]interface{}
|
||||
if err := wn.node.YNode().Decode(&result); err != nil {
|
||||
// Log and die since interface doesn't allow error.
|
||||
log.Fatalf("failed to decode ynode: %v", err)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// MarshalJSON implements ifc.Kunstructured.
|
||||
@@ -113,31 +165,51 @@ func (wn *WNode) MatchesLabelSelector(string) (bool, error) {
|
||||
}
|
||||
|
||||
// SetAnnotations implements ifc.Kunstructured.
|
||||
func (wn *WNode) SetAnnotations(map[string]string) {
|
||||
panic("TODO(#WNode) SetAnnotations; implement or drop from API")
|
||||
func (wn *WNode) SetAnnotations(annotations map[string]string) {
|
||||
wn.setField(yaml.NewMapRNode(&annotations), yaml.MetadataField, yaml.AnnotationsField)
|
||||
}
|
||||
|
||||
// SetGvk implements ifc.Kunstructured.
|
||||
func (wn *WNode) SetGvk(resid.Gvk) {
|
||||
panic("TODO(#WNode) SetGvk; implement or drop from API")
|
||||
func (wn *WNode) SetGvk(gvk resid.Gvk) {
|
||||
wn.setField(yaml.NewScalarRNode(gvk.Kind), yaml.KindField)
|
||||
wn.setField(yaml.NewScalarRNode(fmt.Sprintf("%s/%s", gvk.Group, gvk.Version)), yaml.APIVersionField)
|
||||
}
|
||||
|
||||
// SetLabels implements ifc.Kunstructured.
|
||||
func (wn *WNode) SetLabels(map[string]string) {
|
||||
panic("TODO(#WNode) SetLabels; implement or drop from API")
|
||||
func (wn *WNode) SetLabels(labels map[string]string) {
|
||||
wn.setField(yaml.NewMapRNode(&labels), yaml.MetadataField, yaml.LabelsField)
|
||||
}
|
||||
|
||||
// SetName implements ifc.Kunstructured.
|
||||
func (wn *WNode) SetName(string) {
|
||||
panic("TODO(#WNode) SetName; implement or drop from API")
|
||||
func (wn *WNode) SetName(name string) {
|
||||
wn.setField(yaml.NewScalarRNode(name), yaml.MetadataField, yaml.NameField)
|
||||
}
|
||||
|
||||
// SetNamespace implements ifc.Kunstructured.
|
||||
func (wn *WNode) SetNamespace(string) {
|
||||
panic("TODO(#WNode) SetNamespace; implement or drop from API")
|
||||
func (wn *WNode) SetNamespace(ns string) {
|
||||
wn.setField(yaml.NewScalarRNode(ns), yaml.MetadataField, yaml.NamespaceField)
|
||||
}
|
||||
|
||||
func (wn *WNode) setField(value *yaml.RNode, path ...string) {
|
||||
err := wn.node.PipeE(
|
||||
yaml.LookupCreate(yaml.MappingNode, path[0:len(path)-1]...),
|
||||
yaml.SetField(path[len(path)-1], value),
|
||||
)
|
||||
if err != nil {
|
||||
// Log and die since interface doesn't allow error.
|
||||
log.Fatalf("failed to set field %v: %v", path, err)
|
||||
}
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements ifc.Kunstructured.
|
||||
func (wn *WNode) UnmarshalJSON(data []byte) error {
|
||||
return wn.node.UnmarshalJSON(data)
|
||||
}
|
||||
|
||||
type NoFieldError struct {
|
||||
Field string
|
||||
}
|
||||
|
||||
func (e NoFieldError) Error() string {
|
||||
return fmt.Sprintf("no field named '%s'", e.Field)
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package wrappy_test
|
||||
package wrappy
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"sigs.k8s.io/kustomize/api/resid"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
. "sigs.k8s.io/kustomize/api/internal/wrappy"
|
||||
kyaml "sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
@@ -337,3 +339,215 @@ func TestGettingFields(t *testing.T) {
|
||||
t.Fatalf("unexpected annotations '%v'", actualMap)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFieldValueReturnsMap(t *testing.T) {
|
||||
wn := NewWNode()
|
||||
if err := wn.UnmarshalJSON([]byte(deploymentBiggerJson)); err != nil {
|
||||
t.Fatalf("unexpected unmarshaljson err: %v", err)
|
||||
}
|
||||
expected := map[string]interface{}{
|
||||
"fruit": "apple",
|
||||
"veggie": "carrot",
|
||||
}
|
||||
actual, err := wn.GetFieldValue("metadata.labels")
|
||||
if err != nil {
|
||||
t.Fatalf("error getting field value: %v", err)
|
||||
}
|
||||
if diff := cmp.Diff(expected, actual); diff != "" {
|
||||
t.Fatalf("actual map does not deep equal expected map:\n%v", diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFieldValueReturnsSlice(t *testing.T) {
|
||||
bytes, err := yaml.Marshal(makeBigMap())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected yaml.Marshal err: %v", err)
|
||||
}
|
||||
rNode, err := kyaml.Parse(string(bytes))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected yaml.Marshal err: %v", err)
|
||||
}
|
||||
wn := FromRNode(rNode)
|
||||
expected := []interface{}{"idx0", "idx1", "idx2", "idx3"}
|
||||
actual, err := wn.GetFieldValue("that")
|
||||
if err != nil {
|
||||
t.Fatalf("error getting slice: %v", err)
|
||||
}
|
||||
if diff := cmp.Diff(expected, actual); diff != "" {
|
||||
t.Fatalf("actual slice does not deep equal expected slice:\n%v", diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFieldValueReturnsString(t *testing.T) {
|
||||
wn := NewWNode()
|
||||
if err := wn.UnmarshalJSON([]byte(deploymentBiggerJson)); err != nil {
|
||||
t.Fatalf("unexpected unmarshaljson err: %v", err)
|
||||
}
|
||||
actual, err := wn.GetFieldValue("metadata.labels.fruit")
|
||||
if err != nil {
|
||||
t.Fatalf("error getting field value: %v", err)
|
||||
}
|
||||
v, ok := actual.(string)
|
||||
if !ok || v != "apple" {
|
||||
t.Fatalf("unexpected value '%v'", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFieldValueResolvesAlias(t *testing.T) {
|
||||
yamlWithAlias := `
|
||||
foo: &a theValue
|
||||
bar: *a
|
||||
`
|
||||
rNode, err := kyaml.Parse(yamlWithAlias)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected yaml parse error: %v", err)
|
||||
}
|
||||
wn := FromRNode(rNode)
|
||||
actual, err := wn.GetFieldValue("bar")
|
||||
if err != nil {
|
||||
t.Fatalf("error getting field value: %v", err)
|
||||
}
|
||||
v, ok := actual.(string)
|
||||
if !ok || v != "theValue" {
|
||||
t.Fatalf("unexpected value '%v'", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetString(t *testing.T) {
|
||||
wn := NewWNode()
|
||||
if err := wn.UnmarshalJSON([]byte(deploymentBiggerJson)); err != nil {
|
||||
t.Fatalf("unexpected unmarshaljson err: %v", err)
|
||||
}
|
||||
expected := "carrot"
|
||||
actual, err := wn.GetString("metadata.labels.veggie")
|
||||
if err != nil {
|
||||
t.Fatalf("error getting string: %v", err)
|
||||
}
|
||||
if expected != actual {
|
||||
t.Fatalf("expected '%s', got '%s'", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSlice(t *testing.T) {
|
||||
bytes, err := yaml.Marshal(makeBigMap())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected yaml.Marshal err: %v", err)
|
||||
}
|
||||
rNode, err := kyaml.Parse(string(bytes))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected yaml.Marshal err: %v", err)
|
||||
}
|
||||
wn := FromRNode(rNode)
|
||||
expected := []interface{}{"idx0", "idx1", "idx2", "idx3"}
|
||||
actual, err := wn.GetSlice("that")
|
||||
if err != nil {
|
||||
t.Fatalf("error getting slice: %v", err)
|
||||
}
|
||||
if diff := cmp.Diff(expected, actual); diff != "" {
|
||||
t.Fatalf("actual slice does not deep equal expected slice:\n%v", diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMap(t *testing.T) {
|
||||
wn := NewWNode()
|
||||
if err := wn.UnmarshalJSON([]byte(deploymentLittleJson)); err != nil {
|
||||
t.Fatalf("unexpected unmarshaljson err: %v", err)
|
||||
}
|
||||
|
||||
expected := map[string]interface{}{
|
||||
"apiVersion": "apps/v1",
|
||||
"kind": "Deployment",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "homer",
|
||||
"namespace": "simpsons",
|
||||
},
|
||||
}
|
||||
|
||||
actual := wn.Map()
|
||||
if diff := cmp.Diff(expected, actual); diff != "" {
|
||||
t.Fatalf("actual map does not deep equal expected map:\n%v", diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetName(t *testing.T) {
|
||||
wn := NewWNode()
|
||||
if err := wn.UnmarshalJSON([]byte(deploymentBiggerJson)); err != nil {
|
||||
t.Fatalf("unexpected unmarshaljson err: %v", err)
|
||||
}
|
||||
wn.SetName("marge")
|
||||
if expected, actual := "marge", wn.GetName(); expected != actual {
|
||||
t.Fatalf("expected '%s', got '%s'", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetNamespace(t *testing.T) {
|
||||
wn := NewWNode()
|
||||
if err := wn.UnmarshalJSON([]byte(deploymentBiggerJson)); err != nil {
|
||||
t.Fatalf("unexpected unmarshaljson err: %v", err)
|
||||
}
|
||||
wn.SetNamespace("flanders")
|
||||
meta, _ := wn.node.GetMeta()
|
||||
if expected, actual := "flanders", meta.Namespace; expected != actual {
|
||||
t.Fatalf("expected '%s', got '%s'", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetLabels(t *testing.T) {
|
||||
wn := NewWNode()
|
||||
if err := wn.UnmarshalJSON([]byte(deploymentBiggerJson)); err != nil {
|
||||
t.Fatalf("unexpected unmarshaljson err: %v", err)
|
||||
}
|
||||
wn.SetLabels(map[string]string{
|
||||
"label1": "foo",
|
||||
"label2": "bar",
|
||||
})
|
||||
labels := wn.GetLabels()
|
||||
if expected, actual := 2, len(labels); expected != actual {
|
||||
t.Fatalf("expected '%d', got '%d'", expected, actual)
|
||||
}
|
||||
if expected, actual := "foo", labels["label1"]; expected != actual {
|
||||
t.Fatalf("expected '%s', got '%s'", expected, actual)
|
||||
}
|
||||
if expected, actual := "bar", labels["label2"]; expected != actual {
|
||||
t.Fatalf("expected '%s', got '%s'", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAnnotations(t *testing.T) {
|
||||
wn := NewWNode()
|
||||
if err := wn.UnmarshalJSON([]byte(deploymentBiggerJson)); err != nil {
|
||||
t.Fatalf("unexpected unmarshaljson err: %v", err)
|
||||
}
|
||||
wn.SetAnnotations(map[string]string{
|
||||
"annotation1": "foo",
|
||||
"annotation2": "bar",
|
||||
})
|
||||
annotations := wn.GetAnnotations()
|
||||
if expected, actual := 2, len(annotations); expected != actual {
|
||||
t.Fatalf("expected '%d', got '%d'", expected, actual)
|
||||
}
|
||||
if expected, actual := "foo", annotations["annotation1"]; expected != actual {
|
||||
t.Fatalf("expected '%s', got '%s'", expected, actual)
|
||||
}
|
||||
if expected, actual := "bar", annotations["annotation2"]; expected != actual {
|
||||
t.Fatalf("expected '%s', got '%s'", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetGvk(t *testing.T) {
|
||||
wn := NewWNode()
|
||||
if err := wn.UnmarshalJSON([]byte(deploymentBiggerJson)); err != nil {
|
||||
t.Fatalf("unexpected unmarshaljson err: %v", err)
|
||||
}
|
||||
wn.SetGvk(resid.GvkFromString("grp_ver_knd"))
|
||||
gvk := wn.GetGvk()
|
||||
if expected, actual := "grp", gvk.Group; expected != actual {
|
||||
t.Fatalf("expected '%s', got '%s'", expected, actual)
|
||||
}
|
||||
if expected, actual := "ver", gvk.Version; expected != actual {
|
||||
t.Fatalf("expected '%s', got '%s'", expected, actual)
|
||||
}
|
||||
if expected, actual := "knd", gvk.Kind; expected != actual {
|
||||
t.Fatalf("expected '%s', got '%s'", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user