vendor: Update vendor logic

This commit is contained in:
Clayton Coleman 2020-04-08 14:34:43 -04:00
parent c6ac5cbc87
commit 4ca64b85f0
No known key found for this signature in database
GPG key ID: 3D16906B4F1C5CB3
1540 changed files with 265304 additions and 91616 deletions

View file

@ -76,6 +76,9 @@ func printManager(manager string) string {
return fmt.Sprintf("%q", manager)
}
if encodedManager.Operation == metav1.ManagedFieldsOperationUpdate {
if encodedManager.Time == nil {
return fmt.Sprintf("%q using %v", encodedManager.Manager, encodedManager.APIVersion)
}
return fmt.Sprintf("%q using %v at %v", encodedManager.Manager, encodedManager.APIVersion, encodedManager.Time.UTC().Format(time.RFC3339))
}
return fmt.Sprintf("%q", encodedManager.Manager)

View file

@ -17,79 +17,31 @@ limitations under the License.
package internal
import (
"bytes"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/structured-merge-diff/fieldpath"
)
func newFields() metav1.Fields {
return metav1.Fields{Map: map[string]metav1.Fields{}}
}
func fieldsSet(f metav1.Fields, path fieldpath.Path, set *fieldpath.Set) error {
if len(f.Map) == 0 {
set.Insert(path)
}
for k := range f.Map {
if k == "." {
set.Insert(path)
continue
}
pe, err := NewPathElement(k)
if err != nil {
return err
}
path = append(path, pe)
err = fieldsSet(f.Map[k], path, set)
if err != nil {
return err
}
path = path[:len(path)-1]
}
return nil
}
// FieldsToSet creates a set paths from an input trie of fields
func FieldsToSet(f metav1.Fields) (fieldpath.Set, error) {
set := fieldpath.Set{}
return set, fieldsSet(f, fieldpath.Path{}, &set)
}
func removeUselessDots(f metav1.Fields) metav1.Fields {
if _, ok := f.Map["."]; ok && len(f.Map) == 1 {
delete(f.Map, ".")
return f
}
for k, tf := range f.Map {
f.Map[k] = removeUselessDots(tf)
// EmptyFields represents a set with no paths
// It looks like metav1.Fields{Raw: []byte("{}")}
var EmptyFields metav1.FieldsV1 = func() metav1.FieldsV1 {
f, err := SetToFields(*fieldpath.NewSet())
if err != nil {
panic("should never happen")
}
return f
}()
// FieldsToSet creates a set paths from an input trie of fields
func FieldsToSet(f metav1.FieldsV1) (s fieldpath.Set, err error) {
err = s.FromJSON(bytes.NewReader(f.Raw))
return s, err
}
// SetToFields creates a trie of fields from an input set of paths
func SetToFields(s fieldpath.Set) (metav1.Fields, error) {
var err error
f := newFields()
s.Iterate(func(path fieldpath.Path) {
if err != nil {
return
}
tf := f
for _, pe := range path {
var str string
str, err = PathElementString(pe)
if err != nil {
break
}
if _, ok := tf.Map[str]; ok {
tf = tf.Map[str]
} else {
tf.Map[str] = newFields()
tf = tf.Map[str]
}
}
tf.Map["."] = newFields()
})
f = removeUselessDots(f)
func SetToFields(s fieldpath.Set) (f metav1.FieldsV1, err error) {
f.Raw, err = s.ToJSON()
return f, err
}

View file

@ -35,16 +35,17 @@ type gvkParser struct {
parser typed.Parser
}
func (p *gvkParser) Type(gvk schema.GroupVersionKind) typed.ParseableType {
func (p *gvkParser) Type(gvk schema.GroupVersionKind) *typed.ParseableType {
typeName, ok := p.gvks[gvk]
if !ok {
return nil
}
return p.parser.Type(typeName)
t := p.parser.Type(typeName)
return &t
}
func newGVKParser(models proto.Models) (*gvkParser, error) {
typeSchema, err := schemaconv.ToSchema(models)
func newGVKParser(models proto.Models, preserveUnknownFields bool) (*gvkParser, error) {
typeSchema, err := schemaconv.ToSchemaWithPreserveUnknownFields(models, preserveUnknownFields)
if err != nil {
return nil, fmt.Errorf("failed to convert models to schema: %v", err)
}

View file

@ -28,6 +28,40 @@ import (
"sigs.k8s.io/structured-merge-diff/fieldpath"
)
// ManagedInterface groups a fieldpath.ManagedFields together with the timestamps associated with each operation.
type ManagedInterface interface {
// Fields gets the fieldpath.ManagedFields.
Fields() fieldpath.ManagedFields
// Times gets the timestamps associated with each operation.
Times() map[string]*metav1.Time
}
type managedStruct struct {
fields fieldpath.ManagedFields
times map[string]*metav1.Time
}
var _ ManagedInterface = &managedStruct{}
// Fields implements ManagedInterface.
func (m *managedStruct) Fields() fieldpath.ManagedFields {
return m.fields
}
// Times implements ManagedInterface.
func (m *managedStruct) Times() map[string]*metav1.Time {
return m.times
}
// NewManaged creates a ManagedInterface from a fieldpath.ManagedFields and the timestamps associated with each operation.
func NewManaged(f fieldpath.ManagedFields, t map[string]*metav1.Time) ManagedInterface {
return &managedStruct{
fields: f,
times: t,
}
}
// RemoveObjectManagedFields removes the ManagedFields from the object
// before we merge so that it doesn't appear in the ManagedFields
// recursively.
@ -40,9 +74,9 @@ func RemoveObjectManagedFields(obj runtime.Object) {
}
// DecodeObjectManagedFields extracts and converts the objects ManagedFields into a fieldpath.ManagedFields.
func DecodeObjectManagedFields(from runtime.Object) (fieldpath.ManagedFields, error) {
func DecodeObjectManagedFields(from runtime.Object) (ManagedInterface, error) {
if from == nil {
return make(map[string]*fieldpath.VersionedSet), nil
return &managedStruct{}, nil
}
accessor, err := meta.Accessor(from)
if err != nil {
@ -53,54 +87,61 @@ func DecodeObjectManagedFields(from runtime.Object) (fieldpath.ManagedFields, er
if err != nil {
return nil, fmt.Errorf("failed to convert managed fields from API: %v", err)
}
return managed, err
return &managed, nil
}
// EncodeObjectManagedFields converts and stores the fieldpathManagedFields into the objects ManagedFields
func EncodeObjectManagedFields(obj runtime.Object, fields fieldpath.ManagedFields) error {
func EncodeObjectManagedFields(obj runtime.Object, managed ManagedInterface) error {
accessor, err := meta.Accessor(obj)
if err != nil {
panic(fmt.Sprintf("couldn't get accessor: %v", err))
}
managed, err := encodeManagedFields(fields)
encodedManagedFields, err := encodeManagedFields(managed)
if err != nil {
return fmt.Errorf("failed to convert back managed fields to API: %v", err)
}
accessor.SetManagedFields(managed)
accessor.SetManagedFields(encodedManagedFields)
return nil
}
// decodeManagedFields converts ManagedFields from the wire format (api format)
// to the format used by sigs.k8s.io/structured-merge-diff
func decodeManagedFields(encodedManagedFields []metav1.ManagedFieldsEntry) (managedFields fieldpath.ManagedFields, err error) {
managedFields = make(map[string]*fieldpath.VersionedSet, len(encodedManagedFields))
func decodeManagedFields(encodedManagedFields []metav1.ManagedFieldsEntry) (managed managedStruct, err error) {
managed.fields = make(fieldpath.ManagedFields, len(encodedManagedFields))
managed.times = make(map[string]*metav1.Time, len(encodedManagedFields))
for _, encodedVersionedSet := range encodedManagedFields {
manager, err := BuildManagerIdentifier(&encodedVersionedSet)
if err != nil {
return nil, fmt.Errorf("error decoding manager from %v: %v", encodedVersionedSet, err)
return managedStruct{}, fmt.Errorf("error decoding manager from %v: %v", encodedVersionedSet, err)
}
managedFields[manager], err = decodeVersionedSet(&encodedVersionedSet)
managed.fields[manager], err = decodeVersionedSet(&encodedVersionedSet)
if err != nil {
return nil, fmt.Errorf("error decoding versioned set from %v: %v", encodedVersionedSet, err)
return managedStruct{}, fmt.Errorf("error decoding versioned set from %v: %v", encodedVersionedSet, err)
}
managed.times[manager] = encodedVersionedSet.Time
}
return managedFields, nil
return managed, nil
}
// BuildManagerIdentifier creates a manager identifier string from a ManagedFieldsEntry
func BuildManagerIdentifier(encodedManager *metav1.ManagedFieldsEntry) (manager string, err error) {
encodedManagerCopy := *encodedManager
// Never include the fields in the manager identifier
encodedManagerCopy.Fields = nil
// Never include fields type in the manager identifier
encodedManagerCopy.FieldsType = ""
// For appliers, don't include the APIVersion or Time in the manager identifier,
// Never include the fields in the manager identifier
encodedManagerCopy.FieldsV1 = nil
// Never include the time in the manager identifier
encodedManagerCopy.Time = nil
// For appliers, don't include the APIVersion in the manager identifier,
// so it will always have the same manager identifier each time it applied.
if encodedManager.Operation == metav1.ManagedFieldsOperationApply {
encodedManagerCopy.APIVersion = ""
encodedManagerCopy.Time = nil
}
// Use the remaining fields to build the manager identifier
@ -112,42 +153,34 @@ func BuildManagerIdentifier(encodedManager *metav1.ManagedFieldsEntry) (manager
return string(b), nil
}
func decodeVersionedSet(encodedVersionedSet *metav1.ManagedFieldsEntry) (versionedSet *fieldpath.VersionedSet, err error) {
versionedSet = &fieldpath.VersionedSet{}
versionedSet.APIVersion = fieldpath.APIVersion(encodedVersionedSet.APIVersion)
if encodedVersionedSet.Operation == metav1.ManagedFieldsOperationApply {
versionedSet.Applied = true
}
fields := metav1.Fields{}
if encodedVersionedSet.Fields != nil {
fields = *encodedVersionedSet.Fields
func decodeVersionedSet(encodedVersionedSet *metav1.ManagedFieldsEntry) (versionedSet fieldpath.VersionedSet, err error) {
fields := EmptyFields
if encodedVersionedSet.FieldsV1 != nil {
fields = *encodedVersionedSet.FieldsV1
}
set, err := FieldsToSet(fields)
if err != nil {
return nil, fmt.Errorf("error decoding set: %v", err)
}
versionedSet.Set = &set
return versionedSet, nil
return fieldpath.NewVersionedSet(&set, fieldpath.APIVersion(encodedVersionedSet.APIVersion), encodedVersionedSet.Operation == metav1.ManagedFieldsOperationApply), nil
}
// 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 []metav1.ManagedFieldsEntry, err error) {
// Sort the keys so a predictable order will be used.
managers := []string{}
for manager := range managedFields {
managers = append(managers, manager)
// encodeManagedFields converts ManagedFields from the format used by
// sigs.k8s.io/structured-merge-diff to the wire format (api format)
func encodeManagedFields(managed ManagedInterface) (encodedManagedFields []metav1.ManagedFieldsEntry, err error) {
if len(managed.Fields()) == 0 {
return nil, nil
}
sort.Strings(managers)
encodedManagedFields = []metav1.ManagedFieldsEntry{}
for _, manager := range managers {
versionedSet := managedFields[manager]
for manager := range managed.Fields() {
versionedSet := managed.Fields()[manager]
v, err := encodeManagerVersionedSet(manager, versionedSet)
if err != nil {
return nil, fmt.Errorf("error encoding versioned set for %v: %v", manager, err)
}
if t, ok := managed.Times()[manager]; ok {
v.Time = t
}
encodedManagedFields = append(encodedManagedFields, *v)
}
return sortEncodedManagedFields(encodedManagedFields)
@ -172,13 +205,16 @@ func sortEncodedManagedFields(encodedManagedFields []metav1.ManagedFieldsEntry)
return p.Time.Before(q.Time)
}
return p.Manager < q.Manager
if p.Manager != q.Manager {
return p.Manager < q.Manager
}
return p.APIVersion < q.APIVersion
})
return encodedManagedFields, nil
}
func encodeManagerVersionedSet(manager string, versionedSet *fieldpath.VersionedSet) (encodedVersionedSet *metav1.ManagedFieldsEntry, err error) {
func encodeManagerVersionedSet(manager string, versionedSet fieldpath.VersionedSet) (encodedVersionedSet *metav1.ManagedFieldsEntry, err error) {
encodedVersionedSet = &metav1.ManagedFieldsEntry{}
// Get as many fields as we can from the manager identifier
@ -188,15 +224,16 @@ func encodeManagerVersionedSet(manager string, versionedSet *fieldpath.Versioned
}
// Get the APIVersion, Operation, and Fields from the VersionedSet
encodedVersionedSet.APIVersion = string(versionedSet.APIVersion)
if versionedSet.Applied {
encodedVersionedSet.APIVersion = string(versionedSet.APIVersion())
if versionedSet.Applied() {
encodedVersionedSet.Operation = metav1.ManagedFieldsOperationApply
}
fields, err := SetToFields(*versionedSet.Set)
encodedVersionedSet.FieldsType = "FieldsV1"
fields, err := SetToFields(*versionedSet.Set())
if err != nil {
return nil, fmt.Errorf("error encoding set: %v", err)
}
encodedVersionedSet.Fields = &fields
encodedVersionedSet.FieldsV1 = &fields
return encodedVersionedSet, nil
}

View file

@ -77,7 +77,7 @@ func NewPathElement(s string) (fieldpath.PathElement, error) {
if err != nil {
return fieldpath.PathElement{}, err
}
fields := []value.Field{}
fields := value.FieldList{}
for k, v := range kv {
b, err := json.Marshal(v)
if err != nil {
@ -94,7 +94,7 @@ func NewPathElement(s string) (fieldpath.PathElement, error) {
})
}
return fieldpath.PathElement{
Key: fields,
Key: &fields,
}, nil
default:
// Ignore unknown key types
@ -107,9 +107,9 @@ func PathElementString(pe fieldpath.PathElement) (string, error) {
switch {
case pe.FieldName != nil:
return Field + Separator + *pe.FieldName, nil
case len(pe.Key) > 0:
case pe.Key != nil:
kv := map[string]json.RawMessage{}
for _, k := range pe.Key {
for _, k := range *pe.Key {
b, err := k.Value.ToJSON()
if err != nil {
return "", err

View file

@ -25,15 +25,13 @@ import (
"k8s.io/kube-openapi/pkg/util/proto"
"sigs.k8s.io/structured-merge-diff/typed"
"sigs.k8s.io/structured-merge-diff/value"
"sigs.k8s.io/yaml"
)
// TypeConverter allows you to convert from runtime.Object to
// typed.TypedValue and the other way around.
type TypeConverter interface {
ObjectToTyped(runtime.Object) (typed.TypedValue, error)
YAMLToTyped([]byte) (typed.TypedValue, error)
TypedToObject(typed.TypedValue) (runtime.Object, error)
ObjectToTyped(runtime.Object) (*typed.TypedValue, error)
TypedToObject(*typed.TypedValue) (runtime.Object, error)
}
// DeducedTypeConverter is a TypeConverter for CRDs that don't have a
@ -50,22 +48,17 @@ type DeducedTypeConverter struct{}
var _ TypeConverter = DeducedTypeConverter{}
// ObjectToTyped converts an object into a TypedValue with a "deduced type".
func (DeducedTypeConverter) ObjectToTyped(obj runtime.Object) (typed.TypedValue, error) {
func (DeducedTypeConverter) ObjectToTyped(obj runtime.Object) (*typed.TypedValue, error) {
u, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj)
if err != nil {
return nil, err
}
return typed.DeducedParseableType{}.FromUnstructured(u)
}
// YAMLToTyped parses a yaml object into a TypedValue with a "deduced type".
func (DeducedTypeConverter) YAMLToTyped(from []byte) (typed.TypedValue, error) {
return typed.DeducedParseableType{}.FromYAML(typed.YAMLObject(from))
return typed.DeducedParseableType.FromUnstructured(u)
}
// TypedToObject transforms the typed value into a runtime.Object. That
// is not specific to deduced type.
func (DeducedTypeConverter) TypedToObject(value typed.TypedValue) (runtime.Object, error) {
func (DeducedTypeConverter) TypedToObject(value *typed.TypedValue) (runtime.Object, error) {
return valueToObject(value.AsValue())
}
@ -78,15 +71,15 @@ var _ TypeConverter = &typeConverter{}
// NewTypeConverter builds a TypeConverter from a proto.Models. This
// will automatically find the proper version of the object, and the
// corresponding schema information.
func NewTypeConverter(models proto.Models) (TypeConverter, error) {
parser, err := newGVKParser(models)
func NewTypeConverter(models proto.Models, preserveUnknownFields bool) (TypeConverter, error) {
parser, err := newGVKParser(models, preserveUnknownFields)
if err != nil {
return nil, err
}
return &typeConverter{parser: parser}, nil
}
func (c *typeConverter) ObjectToTyped(obj runtime.Object) (typed.TypedValue, error) {
func (c *typeConverter) ObjectToTyped(obj runtime.Object) (*typed.TypedValue, error) {
u, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj)
if err != nil {
return nil, err
@ -99,22 +92,7 @@ func (c *typeConverter) ObjectToTyped(obj runtime.Object) (typed.TypedValue, err
return t.FromUnstructured(u)
}
func (c *typeConverter) YAMLToTyped(from []byte) (typed.TypedValue, error) {
unstructured := &unstructured.Unstructured{Object: map[string]interface{}{}}
if err := yaml.Unmarshal(from, &unstructured.Object); err != nil {
return nil, fmt.Errorf("error decoding YAML: %v", err)
}
gvk := unstructured.GetObjectKind().GroupVersionKind()
t := c.parser.Type(gvk)
if t == nil {
return nil, newNoCorrespondingTypeError(gvk)
}
return t.FromYAML(typed.YAMLObject(string(from)))
}
func (c *typeConverter) TypedToObject(value typed.TypedValue) (runtime.Object, error) {
func (c *typeConverter) TypedToObject(value *typed.TypedValue) (runtime.Object, error) {
return valueToObject(value.AsValue())
}

View file

@ -60,7 +60,7 @@ func NewCRDVersionConverter(t TypeConverter, o runtime.ObjectConvertor, h schema
}
// Convert implements sigs.k8s.io/structured-merge-diff/merge.Converter
func (v *versionConverter) Convert(object typed.TypedValue, version fieldpath.APIVersion) (typed.TypedValue, error) {
func (v *versionConverter) Convert(object *typed.TypedValue, version fieldpath.APIVersion) (*typed.TypedValue, error) {
// Convert the smd typed value to a kubernetes object.
objectToConvert, err := v.typeConverter.TypedToObject(object)
if err != nil {