mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-07-17 02:06:23 +00:00
convert ManagedFields to internal type
This commit is contained in:
8
Godeps/Godeps.json
generated
8
Godeps/Godeps.json
generated
@@ -4008,6 +4008,14 @@
|
||||
"ImportPath": "k8s.io/utils/pointer",
|
||||
"Rev": "66066c83e385e385ccc3c964b44fd7dcd413d0ed"
|
||||
},
|
||||
{
|
||||
"ImportPath": "sigs.k8s.io/structured-merge-diff/fieldpath",
|
||||
"Rev": "261cd9791e59cf384903eff0e7281c6522f5cec7"
|
||||
},
|
||||
{
|
||||
"ImportPath": "sigs.k8s.io/structured-merge-diff/value",
|
||||
"Rev": "261cd9791e59cf384903eff0e7281c6522f5cec7"
|
||||
},
|
||||
{
|
||||
"ImportPath": "vbom.ml/util/sortorder",
|
||||
"Rev": "db5cfe13f5cc80a4990d98e2e1b0707a4d1a5394"
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package apply
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"sigs.k8s.io/structured-merge-diff/fieldpath"
|
||||
"sigs.k8s.io/structured-merge-diff/value"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// DecodeManagedFields converts ManagedFields from the wire format (api format)
|
||||
// to the format used by sigs.k8s.io/structured-merge-diff
|
||||
func DecodeManagedFields(encodedManagedFields map[string]metav1.VersionedFieldSet) (managedFields fieldpath.ManagedFields, err error) {
|
||||
managedFields = make(map[string]*fieldpath.VersionedSet, len(encodedManagedFields))
|
||||
for manager, encodedVersionedSet := range encodedManagedFields {
|
||||
managedFields[manager], err = decodeVersionedSet(&encodedVersionedSet)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding versioned set for %v: %v", manager, err)
|
||||
}
|
||||
}
|
||||
return managedFields, nil
|
||||
}
|
||||
|
||||
func decodeVersionedSet(encodedVersionedSet *metav1.VersionedFieldSet) (versionedSet *fieldpath.VersionedSet, err error) {
|
||||
versionedSet = &fieldpath.VersionedSet{}
|
||||
versionedSet.APIVersion = fieldpath.APIVersion(encodedVersionedSet.APIVersion)
|
||||
versionedSet.Set = &fieldpath.Set{}
|
||||
err = decodeSetInto(&encodedVersionedSet.Fields, versionedSet.Set)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding set: %v", err)
|
||||
}
|
||||
return versionedSet, nil
|
||||
}
|
||||
|
||||
func decodeSetInto(encodedSet *metav1.FieldSet, set *fieldpath.Set) (err error) {
|
||||
m, err := decodePathElementSet(encodedSet.Members)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error decoding path element set: %v", err)
|
||||
}
|
||||
set.Members = *m
|
||||
c, err := decodeSetNodeMap(encodedSet.Children)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error decoding children: %v", err)
|
||||
}
|
||||
set.Children = *c
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodePathElementSet(encodedPathElementSet []metav1.FieldPathElement) (pathElementSet *fieldpath.PathElementSet, err error) {
|
||||
pathElementSet = &fieldpath.PathElementSet{}
|
||||
for _, encodedPathElement := range encodedPathElementSet {
|
||||
pathElement, err := decodePathElement(&encodedPathElement)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding path element: %v", err)
|
||||
}
|
||||
pathElementSet.Insert(*pathElement)
|
||||
}
|
||||
return pathElementSet, nil
|
||||
}
|
||||
|
||||
func decodeSetNodeMap(encodedSetNodeMap []metav1.FieldSetNode) (setNodeMap *fieldpath.SetNodeMap, err error) {
|
||||
setNodeMap = &fieldpath.SetNodeMap{}
|
||||
for _, encodedSetNode := range encodedSetNodeMap {
|
||||
pathElement, err := decodePathElement(&encodedSetNode.PathElement)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding path element: %v", err)
|
||||
}
|
||||
set := setNodeMap.Descend(*pathElement)
|
||||
decodeSetInto(encodedSetNode.Set, set)
|
||||
}
|
||||
return setNodeMap, nil
|
||||
}
|
||||
|
||||
func decodePathElement(encodedPathElement *metav1.FieldPathElement) (pathElement *fieldpath.PathElement, err error) {
|
||||
if encodedPathElement == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if !validateOneOf(encodedPathElement.FieldName, encodedPathElement.Key, encodedPathElement.Value, encodedPathElement.Index) {
|
||||
return nil, fmt.Errorf("too many fields set: %v", encodedPathElement)
|
||||
}
|
||||
|
||||
pathElement = &fieldpath.PathElement{}
|
||||
pathElement.FieldName = encodedPathElement.FieldName
|
||||
if encodedPathElement.Key != nil {
|
||||
pathElement.Key = make([]value.Field, len(encodedPathElement.Key))
|
||||
for i, encodedField := range encodedPathElement.Key {
|
||||
pathElement.Key[i], err = decodeField(&encodedField)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding field: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
pathElement.Value, err = decodeValue(encodedPathElement.Value)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding value: %v", err)
|
||||
}
|
||||
if encodedPathElement.Index != nil {
|
||||
v := int(*encodedPathElement.Index)
|
||||
pathElement.Index = &v
|
||||
}
|
||||
return pathElement, nil
|
||||
}
|
||||
|
||||
func decodeField(encodedField *metav1.FieldNameValuePair) (field value.Field, err error) {
|
||||
field = value.Field{}
|
||||
if encodedField == nil {
|
||||
return field, fmt.Errorf("unexpected nil pointer")
|
||||
}
|
||||
field.Name = encodedField.Name
|
||||
v, err := decodeValue(&encodedField.Value)
|
||||
if err != nil {
|
||||
return field, fmt.Errorf("error decoding value: %v", err)
|
||||
}
|
||||
if v != nil {
|
||||
field.Value = *v
|
||||
}
|
||||
return field, nil
|
||||
}
|
||||
|
||||
func decodeValue(encodedValue *metav1.FieldValue) (v *value.Value, err error) {
|
||||
if encodedValue == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if !validateOneOf(encodedValue.FloatValue, encodedValue.IntValue, encodedValue.StringValue, encodedValue.BooleanValue) {
|
||||
return nil, fmt.Errorf("too many fields set: %v", encodedValue)
|
||||
}
|
||||
|
||||
v = &value.Value{}
|
||||
if encodedValue.FloatValue != nil {
|
||||
f, err := strconv.ParseFloat(*encodedValue.FloatValue, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing float: %v", err)
|
||||
}
|
||||
v.FloatValue = (*value.Float)(&f)
|
||||
}
|
||||
if encodedValue.IntValue != nil {
|
||||
i := int64(*encodedValue.IntValue)
|
||||
v.IntValue = (*value.Int)(&i)
|
||||
}
|
||||
v.StringValue = (*value.String)(encodedValue.StringValue)
|
||||
v.BooleanValue = (*value.Boolean)(encodedValue.BooleanValue)
|
||||
v.Null = encodedValue.Null
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func validateOneOf(fields ...interface{}) bool {
|
||||
nonNilCount := 0
|
||||
for _, field := range fields {
|
||||
if !reflect.ValueOf(field).IsNil() {
|
||||
nonNilCount++
|
||||
}
|
||||
}
|
||||
return nonNilCount <= 1
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package apply
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestValidateOneOf tests that validateOneOf returns true if <= 1
|
||||
// non-nil fields are passed to it are and false otherwise
|
||||
func TestValidateOneOf(t *testing.T) {
|
||||
var nilValue *string
|
||||
nonNilValue := strPtr("test")
|
||||
|
||||
tests := []struct {
|
||||
fields []interface{}
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
fields: []interface{}{},
|
||||
expected: true,
|
||||
}, {
|
||||
fields: []interface{}{nilValue},
|
||||
expected: true,
|
||||
}, {
|
||||
fields: []interface{}{nonNilValue},
|
||||
expected: true,
|
||||
}, {
|
||||
fields: []interface{}{nilValue, nonNilValue, nilValue},
|
||||
expected: true,
|
||||
}, {
|
||||
fields: []interface{}{nonNilValue, nonNilValue},
|
||||
expected: false,
|
||||
}, {
|
||||
fields: []interface{}{nilValue, nonNilValue, nonNilValue, nilValue},
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range tests {
|
||||
actual := validateOneOf(tc.fields...)
|
||||
if actual != tc.expected {
|
||||
t.Errorf("[%v]expected validateOneOf(%v) to return:\n\t%+v\nbut got:\n\t%+v", i, tc.fields, tc.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func strPtr(s string) *string {
|
||||
return &s
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package apply
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
"sigs.k8s.io/structured-merge-diff/fieldpath"
|
||||
"sigs.k8s.io/structured-merge-diff/value"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// EncodeManagedFields converts ManagedFields from the the format used by
|
||||
// sigs.k8s.io/structured-merge-diff to the the wire format (api format)
|
||||
func EncodeManagedFields(managedFields fieldpath.ManagedFields) (encodedManagedFields map[string]metav1.VersionedFieldSet, err error) {
|
||||
encodedManagedFields = make(map[string]metav1.VersionedFieldSet, len(managedFields))
|
||||
for manager, versionedSet := range managedFields {
|
||||
v, err := encodeVersionedSet(versionedSet)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error encoding versioned set for %v: %v", manager, err)
|
||||
}
|
||||
encodedManagedFields[manager] = *v
|
||||
}
|
||||
return encodedManagedFields, nil
|
||||
}
|
||||
|
||||
func encodeVersionedSet(versionedSet *fieldpath.VersionedSet) (encodedVersionedSet *metav1.VersionedFieldSet, err error) {
|
||||
encodedVersionedSet = &metav1.VersionedFieldSet{}
|
||||
encodedVersionedSet.APIVersion = string(versionedSet.APIVersion)
|
||||
f, err := encodeSet(versionedSet.Set)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error encoding set: %v", err)
|
||||
}
|
||||
encodedVersionedSet.Fields = *f
|
||||
return encodedVersionedSet, nil
|
||||
}
|
||||
|
||||
func encodeSet(set *fieldpath.Set) (encodedSet *metav1.FieldSet, err error) {
|
||||
encodedSet = &metav1.FieldSet{}
|
||||
encodedSet.Members, err = encodePathElementSet(&set.Members)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error encoding path element set: %v", err)
|
||||
}
|
||||
encodedSet.Children, err = encodeSetNodeMap(&set.Children)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error encoding children: %v", err)
|
||||
}
|
||||
return encodedSet, nil
|
||||
}
|
||||
|
||||
func encodePathElementSet(pathElementSet *fieldpath.PathElementSet) (encodedPathElementSet []metav1.FieldPathElement, err error) {
|
||||
// Get a list of the elements in the pathElementSet and sort it
|
||||
pathElementList := make(sortablePathElementList, 0)
|
||||
pathElementSet.Iterate(func(pathElement fieldpath.PathElement) {
|
||||
pathElementList = append(pathElementList, &pathElement)
|
||||
})
|
||||
sort.Sort(pathElementList)
|
||||
if len(pathElementList) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
encodedPathElementSet = make([]metav1.FieldPathElement, len(pathElementList))
|
||||
for i, pathElement := range pathElementList {
|
||||
encodedPathElement, err := encodePathElement(pathElement)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error encoding path element: %v", err)
|
||||
}
|
||||
encodedPathElementSet[i] = encodedPathElement
|
||||
}
|
||||
return encodedPathElementSet, nil
|
||||
}
|
||||
|
||||
func encodeSetNodeMap(setNodeMap *fieldpath.SetNodeMap) (encodedSetNodeMap []metav1.FieldSetNode, err error) {
|
||||
// Get a list of the keys in the setNodeMap and sort it
|
||||
pathElementList := make(sortablePathElementList, 0)
|
||||
setNodeMap.Iterate(func(pathElement fieldpath.PathElement) {
|
||||
pathElementList = append(pathElementList, &pathElement)
|
||||
})
|
||||
sort.Sort(pathElementList)
|
||||
if len(pathElementList) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
encodedSetNodeMap = make([]metav1.FieldSetNode, len(pathElementList))
|
||||
for i, pathElement := range pathElementList {
|
||||
encodedPathElement, err := encodePathElement(pathElement)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error encoding path element %v: %v", pathElement.String(), err)
|
||||
}
|
||||
set, ok := setNodeMap.Get(*pathElement)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("error looking up path element %v", pathElement.String())
|
||||
}
|
||||
encodedSet, err := encodeSet(set)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error encoding set for %v: %v", pathElement.String(), err)
|
||||
}
|
||||
encodedSetNodeMap[i] = metav1.FieldSetNode{
|
||||
PathElement: encodedPathElement,
|
||||
Set: encodedSet,
|
||||
}
|
||||
}
|
||||
return encodedSetNodeMap, nil
|
||||
}
|
||||
|
||||
func encodePathElement(pathElement *fieldpath.PathElement) (encodedPathElement metav1.FieldPathElement, err error) {
|
||||
encodedPathElement = metav1.FieldPathElement{}
|
||||
if pathElement == nil {
|
||||
return encodedPathElement, nil
|
||||
}
|
||||
encodedPathElement.FieldName = pathElement.FieldName
|
||||
if pathElement.Key != nil {
|
||||
encodedPathElement.Key = make([]metav1.FieldNameValuePair, len(pathElement.Key))
|
||||
for i, field := range pathElement.Key {
|
||||
encodedPathElement.Key[i], err = encodeField(&field)
|
||||
if err != nil {
|
||||
return encodedPathElement, fmt.Errorf("error encoding field: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
encodedPathElement.Value, err = encodeValue(pathElement.Value)
|
||||
if err != nil {
|
||||
return encodedPathElement, fmt.Errorf("error encoding value: %v", err)
|
||||
}
|
||||
if pathElement.Index != nil {
|
||||
v := int32(*pathElement.Index)
|
||||
encodedPathElement.Index = &v
|
||||
}
|
||||
return encodedPathElement, nil
|
||||
}
|
||||
|
||||
func encodeField(field *value.Field) (encodedField metav1.FieldNameValuePair, err error) {
|
||||
encodedField = metav1.FieldNameValuePair{}
|
||||
if field == nil {
|
||||
return encodedField, fmt.Errorf("unexpected nil pointer")
|
||||
}
|
||||
encodedField.Name = field.Name
|
||||
v, err := encodeValue(&field.Value)
|
||||
if err != nil {
|
||||
return encodedField, fmt.Errorf("error encoding value: %v", err)
|
||||
}
|
||||
if v != nil {
|
||||
encodedField.Value = *v
|
||||
}
|
||||
return encodedField, nil
|
||||
}
|
||||
|
||||
func encodeValue(v *value.Value) (encodedValue *metav1.FieldValue, err error) {
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
}
|
||||
encodedValue = &metav1.FieldValue{}
|
||||
if v.FloatValue != nil {
|
||||
f := strconv.FormatFloat(float64(*v.FloatValue), 'f', -1, 64)
|
||||
encodedValue.FloatValue = &f
|
||||
}
|
||||
if v.IntValue != nil {
|
||||
i := int32(int64(*v.IntValue))
|
||||
encodedValue.IntValue = &i
|
||||
}
|
||||
encodedValue.StringValue = (*string)(v.StringValue)
|
||||
encodedValue.BooleanValue = (*bool)(v.BooleanValue)
|
||||
encodedValue.Null = v.Null
|
||||
return encodedValue, nil
|
||||
}
|
||||
|
||||
type sortablePathElementList []*fieldpath.PathElement
|
||||
|
||||
func (p sortablePathElementList) Len() int { return len(p) }
|
||||
func (p sortablePathElementList) Less(i, j int) bool { return p[i].String() < p[j].String() }
|
||||
func (p sortablePathElementList) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
||||
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package apply
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
)
|
||||
|
||||
// TestRoundTripManagedFields will roundtrip ManagedFields from the format used by
|
||||
// sigs.k8s.io/structured-merge-diff to the wire format (api format) and back
|
||||
func TestRoundTripManagedFields(t *testing.T) {
|
||||
tests := []struct {
|
||||
yaml []byte
|
||||
errString string
|
||||
}{
|
||||
{
|
||||
yaml: []byte(`foo:
|
||||
apiVersion: v1
|
||||
fields:
|
||||
children:
|
||||
- pathElement:
|
||||
index: 5
|
||||
set:
|
||||
members:
|
||||
- fieldName: i
|
||||
- pathElement:
|
||||
value:
|
||||
floatValue: 3.1415
|
||||
set:
|
||||
members:
|
||||
- fieldName: pi
|
||||
- pathElement:
|
||||
value:
|
||||
intValue: 3
|
||||
set:
|
||||
members:
|
||||
- fieldName: alsoPi
|
||||
- pathElement:
|
||||
value:
|
||||
booleanValue: false
|
||||
set:
|
||||
members:
|
||||
- fieldName: notTrue`),
|
||||
}, {
|
||||
yaml: []byte(`foo:
|
||||
apiVersion: v1
|
||||
fields:
|
||||
children:
|
||||
- pathElement:
|
||||
fieldName: spec
|
||||
set:
|
||||
children:
|
||||
- pathElement:
|
||||
fieldName: containers
|
||||
set:
|
||||
children:
|
||||
- pathElement:
|
||||
key:
|
||||
- name: name
|
||||
value:
|
||||
stringValue: c
|
||||
'null': false
|
||||
set:
|
||||
members:
|
||||
- fieldName: image
|
||||
- fieldName: name`),
|
||||
}, {
|
||||
yaml: []byte(`foo:
|
||||
apiVersion: v1
|
||||
fields:
|
||||
members:
|
||||
- fieldName: apiVersion
|
||||
- fieldName: kind
|
||||
children:
|
||||
- pathElement:
|
||||
fieldName: metadata
|
||||
set:
|
||||
members:
|
||||
- fieldName: name
|
||||
children:
|
||||
- pathElement:
|
||||
fieldName: labels
|
||||
set:
|
||||
members:
|
||||
- fieldName: app
|
||||
- pathElement:
|
||||
fieldName: spec
|
||||
set:
|
||||
members:
|
||||
- fieldName: replicas
|
||||
children:
|
||||
- pathElement:
|
||||
fieldName: selector
|
||||
set:
|
||||
children:
|
||||
- pathElement:
|
||||
fieldName: matchLabels
|
||||
set:
|
||||
members:
|
||||
- fieldName: app
|
||||
- pathElement:
|
||||
fieldName: template
|
||||
set:
|
||||
children:
|
||||
- pathElement:
|
||||
fieldName: metadata
|
||||
set:
|
||||
children:
|
||||
- pathElement:
|
||||
fieldName: labels
|
||||
set:
|
||||
members:
|
||||
- fieldName: app
|
||||
- pathElement:
|
||||
fieldName: spec
|
||||
set:
|
||||
children:
|
||||
- pathElement:
|
||||
fieldName: containers
|
||||
set:
|
||||
children:
|
||||
- pathElement:
|
||||
key:
|
||||
- name: name
|
||||
value:
|
||||
stringValue: nginx
|
||||
'null': false
|
||||
set:
|
||||
members:
|
||||
- fieldName: image
|
||||
- fieldName: name
|
||||
children:
|
||||
- pathElement:
|
||||
fieldName: ports
|
||||
set:
|
||||
children:
|
||||
- pathElement:
|
||||
index: 0
|
||||
set:
|
||||
members:
|
||||
- fieldName: containerPort`),
|
||||
}, {
|
||||
yaml: []byte(`foo:
|
||||
apiVersion: v1
|
||||
fields:
|
||||
members:
|
||||
- fieldName: allowVolumeExpansion
|
||||
- fieldName: apiVersion
|
||||
- fieldName: kind
|
||||
- fieldName: provisioner
|
||||
children:
|
||||
- pathElement:
|
||||
fieldName: metadata
|
||||
set:
|
||||
members:
|
||||
- fieldName: name
|
||||
- pathElement:
|
||||
fieldName: parameters
|
||||
set:
|
||||
members:
|
||||
- fieldName: resturl
|
||||
- fieldName: restuser
|
||||
- fieldName: secretName
|
||||
- fieldName: secretNamespace`),
|
||||
}, {
|
||||
yaml: []byte(`foo:
|
||||
apiVersion: v1
|
||||
fields:
|
||||
members:
|
||||
- fieldName: apiVersion
|
||||
- fieldName: kind
|
||||
children:
|
||||
- pathElement:
|
||||
fieldName: metadata
|
||||
set:
|
||||
members:
|
||||
- fieldName: name
|
||||
- pathElement:
|
||||
fieldName: spec
|
||||
set:
|
||||
members:
|
||||
- fieldName: group
|
||||
- fieldName: scope
|
||||
children:
|
||||
- pathElement:
|
||||
fieldName: names
|
||||
set:
|
||||
members:
|
||||
- fieldName: kind
|
||||
- fieldName: plural
|
||||
- fieldName: singular
|
||||
children:
|
||||
- pathElement:
|
||||
fieldName: shortNames
|
||||
set:
|
||||
members:
|
||||
- index: 0
|
||||
- pathElement:
|
||||
fieldName: versions
|
||||
set:
|
||||
children:
|
||||
- pathElement:
|
||||
key:
|
||||
- name: name
|
||||
value:
|
||||
stringValue: v1
|
||||
'null': false
|
||||
set:
|
||||
members:
|
||||
- fieldName: name
|
||||
- fieldName: served
|
||||
- fieldName: storage`),
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range tests {
|
||||
var original map[string]metav1.VersionedFieldSet
|
||||
if err := yaml.Unmarshal(tc.yaml, &original); err != nil {
|
||||
t.Errorf("[%v]did not expect yaml unmarshalling error but got: %v", i, err)
|
||||
continue
|
||||
}
|
||||
|
||||
decoded, err := DecodeManagedFields(original)
|
||||
if err == nil && len(tc.errString) > 0 {
|
||||
t.Errorf("[%v]expected error but got none.", i)
|
||||
continue
|
||||
}
|
||||
if err != nil && len(tc.errString) == 0 {
|
||||
t.Errorf("[%v]did not expect error but got: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if err != nil && len(tc.errString) > 0 && !strings.Contains(err.Error(), tc.errString) {
|
||||
t.Errorf("[%v]expected error with %q but got: %v", i, tc.errString, err)
|
||||
continue
|
||||
}
|
||||
encoded, err := EncodeManagedFields(decoded)
|
||||
if err != nil {
|
||||
t.Errorf("[%v]did not expect round trip error but got: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(encoded, original) {
|
||||
t.Errorf("[%v]expected:\n\t%+v\nbut got:\n\t%+v", i, original, encoded)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user