mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-10-25 18:09:10 +00:00
Add structured-merge-diff vendor
This is where most of the logic actually lives.
This commit is contained in:
234
vendor/sigs.k8s.io/structured-merge-diff/value/unstructured.go
generated
vendored
Normal file
234
vendor/sigs.k8s.io/structured-merge-diff/value/unstructured.go
generated
vendored
Normal file
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
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 value
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// FromYAML is a helper function for reading a YAML document; it attempts to
|
||||
// preserve order of keys within maps/structs. This is as a convenience to
|
||||
// humans keeping YAML documents, not because there is a behavior difference.
|
||||
//
|
||||
// Known bug: objects with top-level arrays don't parse correctly.
|
||||
func FromYAML(input []byte) (Value, error) {
|
||||
var decoded interface{}
|
||||
|
||||
if len(input) == 0 || (len(input) == 4 && string(input) == "null") {
|
||||
// Special case since the yaml package doesn't accurately
|
||||
// preserve this.
|
||||
return Value{Null: true}, nil
|
||||
}
|
||||
|
||||
// This attempts to enable order sensitivity; note the yaml package is
|
||||
// broken for documents that have root-level arrays, hence the two-step
|
||||
// approach. TODO: This is a horrific hack. Is it worth it?
|
||||
var ms yaml.MapSlice
|
||||
if err := yaml.Unmarshal(input, &ms); err == nil {
|
||||
decoded = ms
|
||||
} else if err := yaml.Unmarshal(input, &decoded); err != nil {
|
||||
return Value{}, err
|
||||
}
|
||||
|
||||
v, err := FromUnstructured(decoded)
|
||||
if err != nil {
|
||||
return Value{}, fmt.Errorf("failed to interpret (%v):\n%s", err, input)
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// FromJSON is a helper function for reading a JSON document
|
||||
func FromJSON(input []byte) (Value, error) {
|
||||
var decoded interface{}
|
||||
|
||||
if err := json.Unmarshal(input, &decoded); err != nil {
|
||||
return Value{}, err
|
||||
}
|
||||
|
||||
v, err := FromUnstructured(decoded)
|
||||
if err != nil {
|
||||
return Value{}, fmt.Errorf("failed to interpret (%v):\n%s", err, input)
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// FromUnstructured will convert a go interface to a Value.
|
||||
// It's most commonly expected to be used with map[string]interface{} as the
|
||||
// input. `in` must not have any structures with cycles in them.
|
||||
// yaml.MapSlice may be used for order-preservation.
|
||||
func FromUnstructured(in interface{}) (Value, error) {
|
||||
if in == nil {
|
||||
return Value{Null: true}, nil
|
||||
}
|
||||
switch t := in.(type) {
|
||||
case map[interface{}]interface{}:
|
||||
m := Map{}
|
||||
for rawKey, rawVal := range t {
|
||||
k, ok := rawKey.(string)
|
||||
if !ok {
|
||||
return Value{}, fmt.Errorf("key %#v: not a string", k)
|
||||
}
|
||||
v, err := FromUnstructured(rawVal)
|
||||
if err != nil {
|
||||
return Value{}, fmt.Errorf("key %v: %v", k, err)
|
||||
}
|
||||
m.Set(k, v)
|
||||
}
|
||||
return Value{MapValue: &m}, nil
|
||||
case map[string]interface{}:
|
||||
m := Map{}
|
||||
for k, rawVal := range t {
|
||||
v, err := FromUnstructured(rawVal)
|
||||
if err != nil {
|
||||
return Value{}, fmt.Errorf("key %v: %v", k, err)
|
||||
}
|
||||
m.Set(k, v)
|
||||
}
|
||||
return Value{MapValue: &m}, nil
|
||||
case yaml.MapSlice:
|
||||
m := Map{}
|
||||
for _, item := range t {
|
||||
k, ok := item.Key.(string)
|
||||
if !ok {
|
||||
return Value{}, fmt.Errorf("key %#v is not a string", item.Key)
|
||||
}
|
||||
v, err := FromUnstructured(item.Value)
|
||||
if err != nil {
|
||||
return Value{}, fmt.Errorf("key %v: %v", k, err)
|
||||
}
|
||||
m.Set(k, v)
|
||||
}
|
||||
return Value{MapValue: &m}, nil
|
||||
case []interface{}:
|
||||
l := List{}
|
||||
for i, rawVal := range t {
|
||||
v, err := FromUnstructured(rawVal)
|
||||
if err != nil {
|
||||
return Value{}, fmt.Errorf("index %v: %v", i, err)
|
||||
}
|
||||
l.Items = append(l.Items, v)
|
||||
}
|
||||
return Value{ListValue: &l}, nil
|
||||
case int:
|
||||
n := Int(t)
|
||||
return Value{IntValue: &n}, nil
|
||||
case int8:
|
||||
n := Int(t)
|
||||
return Value{IntValue: &n}, nil
|
||||
case int16:
|
||||
n := Int(t)
|
||||
return Value{IntValue: &n}, nil
|
||||
case int32:
|
||||
n := Int(t)
|
||||
return Value{IntValue: &n}, nil
|
||||
case int64:
|
||||
n := Int(t)
|
||||
return Value{IntValue: &n}, nil
|
||||
case uint:
|
||||
n := Int(t)
|
||||
return Value{IntValue: &n}, nil
|
||||
case uint8:
|
||||
n := Int(t)
|
||||
return Value{IntValue: &n}, nil
|
||||
case uint16:
|
||||
n := Int(t)
|
||||
return Value{IntValue: &n}, nil
|
||||
case uint32:
|
||||
n := Int(t)
|
||||
return Value{IntValue: &n}, nil
|
||||
case float32:
|
||||
f := Float(t)
|
||||
return Value{FloatValue: &f}, nil
|
||||
case float64:
|
||||
f := Float(t)
|
||||
return Value{FloatValue: &f}, nil
|
||||
case string:
|
||||
return StringValue(t), nil
|
||||
case bool:
|
||||
return BooleanValue(t), nil
|
||||
default:
|
||||
return Value{}, fmt.Errorf("type unimplemented: %t", in)
|
||||
}
|
||||
}
|
||||
|
||||
// ToYAML is a helper function for producing a YAML document; it attempts to
|
||||
// preserve order of keys within maps/structs. This is as a convenience to
|
||||
// humans keeping YAML documents, not because there is a behavior difference.
|
||||
func (v *Value) ToYAML() ([]byte, error) {
|
||||
return yaml.Marshal(v.ToUnstructured(true))
|
||||
}
|
||||
|
||||
// ToJSON is a helper function for producing a JSon document.
|
||||
func (v *Value) ToJSON() ([]byte, error) {
|
||||
return json.Marshal(v.ToUnstructured(false))
|
||||
}
|
||||
|
||||
// ToUnstructured will convert the Value into a go-typed object.
|
||||
// If preserveOrder is true, then maps will be converted to the yaml.MapSlice
|
||||
// type. Otherwise, map[string]interface{} must be used-- this destroys
|
||||
// ordering information and is not recommended if the result of this will be
|
||||
// serialized. Other types:
|
||||
// * list -> []interface{}
|
||||
// * others -> corresponding go type, wrapped in an interface{}
|
||||
//
|
||||
// Of note, floats and ints will always come out as float64 and int64,
|
||||
// respectively.
|
||||
func (v *Value) ToUnstructured(preserveOrder bool) interface{} {
|
||||
switch {
|
||||
case v.FloatValue != nil:
|
||||
f := float64(*v.FloatValue)
|
||||
return f
|
||||
case v.IntValue != nil:
|
||||
i := int64(*v.IntValue)
|
||||
return i
|
||||
case v.StringValue != nil:
|
||||
return string(*v.StringValue)
|
||||
case v.BooleanValue != nil:
|
||||
return bool(*v.BooleanValue)
|
||||
case v.ListValue != nil:
|
||||
out := []interface{}{}
|
||||
for _, item := range v.ListValue.Items {
|
||||
out = append(out, item.ToUnstructured(preserveOrder))
|
||||
}
|
||||
return out
|
||||
case v.MapValue != nil:
|
||||
m := v.MapValue
|
||||
if preserveOrder {
|
||||
ms := make(yaml.MapSlice, len(m.Items))
|
||||
for i := range m.Items {
|
||||
ms[i] = yaml.MapItem{
|
||||
Key: m.Items[i].Name,
|
||||
Value: m.Items[i].Value.ToUnstructured(preserveOrder),
|
||||
}
|
||||
}
|
||||
return ms
|
||||
}
|
||||
// This case is unavoidably lossy.
|
||||
out := map[string]interface{}{}
|
||||
for i := range m.Items {
|
||||
out[m.Items[i].Name] = m.Items[i].Value.ToUnstructured(preserveOrder)
|
||||
}
|
||||
return out
|
||||
default:
|
||||
fallthrough
|
||||
case v.Null == true:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user