mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-11 17:12:51 +00:00
Implemented the following WNode methods:
* GetFieldValue * GetSlice * GetString * Map * SetAnnotations * SetGvk * SetLabels * SetName * SetNamespace
This commit is contained in:
@@ -6,6 +6,7 @@ require (
|
|||||||
github.com/evanphx/json-patch v4.5.0+incompatible
|
github.com/evanphx/json-patch v4.5.0+incompatible
|
||||||
github.com/go-openapi/spec v0.19.5
|
github.com/go-openapi/spec v0.19.5
|
||||||
github.com/golangci/golangci-lint v1.21.0
|
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/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||||
github.com/pkg/errors v0.8.1
|
github.com/pkg/errors v0.8.1
|
||||||
github.com/stretchr/testify v1.4.0
|
github.com/stretchr/testify v1.4.0
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020 The Kubernetes Authors.
|
// Copyright 2020 The Kubernetes Authors.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package wrappy_test
|
package wrappy
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
package wrappy
|
package wrappy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/api/ifc"
|
"sigs.k8s.io/kustomize/api/ifc"
|
||||||
"sigs.k8s.io/kustomize/api/resid"
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
@@ -54,10 +56,41 @@ func (wn *WNode) GetAnnotations() map[string]string {
|
|||||||
|
|
||||||
// GetFieldValue implements ifc.Kunstructured.
|
// GetFieldValue implements ifc.Kunstructured.
|
||||||
func (wn *WNode) GetFieldValue(path string) (interface{}, error) {
|
func (wn *WNode) GetFieldValue(path string) (interface{}, error) {
|
||||||
// The argument is a json path, e.g. "metadata.name"
|
fields := strings.Split(path, ".")
|
||||||
// fields := strings.Split(path, ".")
|
rn, err := wn.node.Pipe(yaml.Lookup(fields...))
|
||||||
// return wn.node.Pipe(yaml.Lookup(fields...))
|
if err != nil {
|
||||||
panic("TODO(#WNode): GetFieldValue; implement or drop from API")
|
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.
|
// GetGvk implements ifc.Kunstructured.
|
||||||
@@ -83,18 +116,37 @@ func (wn *WNode) GetName() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetSlice implements ifc.Kunstructured.
|
// GetSlice implements ifc.Kunstructured.
|
||||||
func (wn *WNode) GetSlice(string) ([]interface{}, error) {
|
func (wn *WNode) GetSlice(path string) ([]interface{}, error) {
|
||||||
panic("TODO(#WNode) GetSlice; implement or drop from API")
|
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.
|
// GetSlice implements ifc.Kunstructured.
|
||||||
func (wn *WNode) GetString(string) (string, error) {
|
func (wn *WNode) GetString(path string) (string, error) {
|
||||||
panic("TODO(#WNode) GetString; implement or drop from API")
|
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.
|
// Map implements ifc.Kunstructured.
|
||||||
func (wn *WNode) Map() map[string]interface{} {
|
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.
|
// MarshalJSON implements ifc.Kunstructured.
|
||||||
@@ -113,31 +165,51 @@ func (wn *WNode) MatchesLabelSelector(string) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetAnnotations implements ifc.Kunstructured.
|
// SetAnnotations implements ifc.Kunstructured.
|
||||||
func (wn *WNode) SetAnnotations(map[string]string) {
|
func (wn *WNode) SetAnnotations(annotations map[string]string) {
|
||||||
panic("TODO(#WNode) SetAnnotations; implement or drop from API")
|
wn.setField(yaml.NewMapRNode(&annotations), yaml.MetadataField, yaml.AnnotationsField)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetGvk implements ifc.Kunstructured.
|
// SetGvk implements ifc.Kunstructured.
|
||||||
func (wn *WNode) SetGvk(resid.Gvk) {
|
func (wn *WNode) SetGvk(gvk resid.Gvk) {
|
||||||
panic("TODO(#WNode) SetGvk; implement or drop from API")
|
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.
|
// SetLabels implements ifc.Kunstructured.
|
||||||
func (wn *WNode) SetLabels(map[string]string) {
|
func (wn *WNode) SetLabels(labels map[string]string) {
|
||||||
panic("TODO(#WNode) SetLabels; implement or drop from API")
|
wn.setField(yaml.NewMapRNode(&labels), yaml.MetadataField, yaml.LabelsField)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetName implements ifc.Kunstructured.
|
// SetName implements ifc.Kunstructured.
|
||||||
func (wn *WNode) SetName(string) {
|
func (wn *WNode) SetName(name string) {
|
||||||
panic("TODO(#WNode) SetName; implement or drop from API")
|
wn.setField(yaml.NewScalarRNode(name), yaml.MetadataField, yaml.NameField)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNamespace implements ifc.Kunstructured.
|
// SetNamespace implements ifc.Kunstructured.
|
||||||
func (wn *WNode) SetNamespace(string) {
|
func (wn *WNode) SetNamespace(ns string) {
|
||||||
panic("TODO(#WNode) SetNamespace; implement or drop from API")
|
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.
|
// UnmarshalJSON implements ifc.Kunstructured.
|
||||||
func (wn *WNode) UnmarshalJSON(data []byte) error {
|
func (wn *WNode) UnmarshalJSON(data []byte) error {
|
||||||
return wn.node.UnmarshalJSON(data)
|
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.
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package wrappy_test
|
package wrappy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"sigs.k8s.io/kustomize/api/resid"
|
||||||
|
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
. "sigs.k8s.io/kustomize/api/internal/wrappy"
|
|
||||||
kyaml "sigs.k8s.io/kustomize/kyaml/yaml"
|
kyaml "sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -337,3 +339,215 @@ func TestGettingFields(t *testing.T) {
|
|||||||
t.Fatalf("unexpected annotations '%v'", actualMap)
|
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