diff --git a/pkg/kubectl/apply/element.go b/pkg/kubectl/apply/element.go index 8060552931b..44b90d85aad 100644 --- a/pkg/kubectl/apply/element.go +++ b/pkg/kubectl/apply/element.go @@ -76,33 +76,6 @@ type FieldMeta interface { GetFieldType() string } -// HasElementData contains whether a field was set in the recorded, local and remote sources -type HasElementData struct { - // RecordedSet is true if the field was found in the recorded object - RecordedSet bool - - // LocalSet is true if the field was found in the local object - LocalSet bool - - // RemoteSet is true if the field was found in the remote object - RemoteSet bool -} - -// HasRecorded implements Element.HasRecorded -func (e HasElementData) HasRecorded() bool { - return e.RecordedSet -} - -// HasLocal implements Element.HasLocal -func (e HasElementData) HasLocal() bool { - return e.LocalSet -} - -// HasRemote implements Element.HasRemote -func (e HasElementData) HasRemote() bool { - return e.RemoteSet -} - // FieldMetaImpl implements FieldMeta type FieldMetaImpl struct { // The type of merge strategy to use for this field @@ -195,7 +168,7 @@ type CombinedPrimitiveSlice struct { // PrimitiveListItem represents a single value in a slice of primitives type PrimitiveListItem struct { - // Value is the value of the primitive, should match Recorded, Local and Remote + // Value is the value of the primitive, should match recorded, local and remote Value interface{} RawElementData @@ -230,21 +203,27 @@ func (s *CombinedPrimitiveSlice) upsert(l interface{}) *PrimitiveListItem { // slice for either the local or remote, set on that value as the recorded value // Otherwise append a new item to the list with the recorded value. func (s *CombinedPrimitiveSlice) UpsertRecorded(l interface{}) { - s.upsert(l).Recorded = l + v := s.upsert(l) + v.recorded = l + v.recordedSet = true } // UpsertLocal adds l to the slice. If there is already a value of l in the // slice for either the recorded or remote, set on that value as the local value // Otherwise append a new item to the list with the local value. func (s *CombinedPrimitiveSlice) UpsertLocal(l interface{}) { - s.upsert(l).Local = l + v := s.upsert(l) + v.local = l + v.localSet = true } // UpsertRemote adds l to the slice. If there is already a value of l in the // slice for either the local or recorded, set on that value as the remote value // Otherwise append a new item to the list with the remote value. func (s *CombinedPrimitiveSlice) UpsertRemote(l interface{}) { - s.upsert(l).Recorded = l + v := s.upsert(l) + v.remote = l + v.remoteSet = true } // ListItem represents a single value in a slice of maps or types @@ -299,7 +278,8 @@ func (s *CombinedMapSlice) UpsertRecorded(key MergeKeys, l interface{}) error { if err != nil { return err } - item.Recorded = l + item.recorded = l + item.recordedSet = true return nil } @@ -311,7 +291,8 @@ func (s *CombinedMapSlice) UpsertLocal(key MergeKeys, l interface{}) error { if err != nil { return err } - item.Local = l + item.local = l + item.localSet = true return nil } @@ -323,7 +304,8 @@ func (s *CombinedMapSlice) UpsertRemote(key MergeKeys, l interface{}) error { if err != nil { return err } - item.Remote = l + item.remote = l + item.remoteSet = true return nil } @@ -345,29 +327,97 @@ func IsAdd(e Element) bool { return e.HasLocal() && !e.HasRemote() } +// NewRawElementData returns a new RawElementData, setting IsSet to true for +// non-nil values, and leaving IsSet false for nil values. +// Note: use this only when you want a nil-value to be considered "unspecified" +// (ignore) and not "unset" (deleted). +func NewRawElementData(recorded, local, remote interface{}) RawElementData { + data := RawElementData{} + if recorded != nil { + data.SetRecorded(recorded) + } + if local != nil { + data.SetLocal(local) + } + if remote != nil { + data.SetRemote(remote) + } + return data +} + // RawElementData contains the raw recorded, local and remote data +// and metadata about whethere or not each was set type RawElementData struct { - // recorded contains the value of the field from the recorded object - Recorded interface{} + HasElementData - // Local contains the value of the field from the recorded object - Local interface{} + recorded interface{} + local interface{} + remote interface{} +} - // Remote contains the value of the field from the recorded object - Remote interface{} +// SetRecorded sets the recorded value +func (b *RawElementData) SetRecorded(value interface{}) { + b.recorded = value + b.recordedSet = true +} + +// SetLocal sets the recorded value +func (b *RawElementData) SetLocal(value interface{}) { + b.local = value + b.localSet = true +} + +// SetRemote sets the recorded value +func (b *RawElementData) SetRemote(value interface{}) { + b.remote = value + b.remoteSet = true } // GetRecorded implements Element.GetRecorded -func (e RawElementData) GetRecorded() interface{} { - return e.Recorded +func (b RawElementData) GetRecorded() interface{} { + // https://golang.org/doc/faq#nil_error + if b.recorded == nil { + return nil + } + return b.recorded } // GetLocal implements Element.GetLocal -func (e RawElementData) GetLocal() interface{} { - return e.Local +func (b RawElementData) GetLocal() interface{} { + // https://golang.org/doc/faq#nil_error + if b.local == nil { + return nil + } + return b.local } // GetRemote implements Element.GetRemote -func (e RawElementData) GetRemote() interface{} { - return e.Remote +func (b RawElementData) GetRemote() interface{} { + // https://golang.org/doc/faq#nil_error + if b.remote == nil { + return nil + } + return b.remote +} + +// HasElementData contains whether a field was set in the recorded, local and remote sources +type HasElementData struct { + recordedSet bool + localSet bool + remoteSet bool +} + +// HasRecorded implements Element.HasRecorded +func (e HasElementData) HasRecorded() bool { + return e.recordedSet +} + +// HasLocal implements Element.HasLocal +func (e HasElementData) HasLocal() bool { + return e.localSet +} + +// HasRemote implements Element.HasRemote +func (e HasElementData) HasRemote() bool { + return e.remoteSet } diff --git a/pkg/kubectl/apply/list_element.go b/pkg/kubectl/apply/list_element.go index d14161fa9a4..86be39ed1f4 100644 --- a/pkg/kubectl/apply/list_element.go +++ b/pkg/kubectl/apply/list_element.go @@ -22,10 +22,6 @@ type ListElement struct { // FieldMetaImpl contains metadata about the field from openapi FieldMetaImpl - // HasElementData contains whether the field was set - HasElementData - - // ListElementData contains the value a field was set to ListElementData // Values contains the combined recorded-local-remote value of each item in the list @@ -44,39 +40,28 @@ var _ Element = &ListElement{} // ListElementData contains the recorded, local and remote data for a list type ListElementData struct { - // recorded contains the value of the field from the recorded object - Recorded []interface{} - - // Local contains the value of the field from the recorded object - Local []interface{} - - // Remote contains the value of the field from the recorded object - Remote []interface{} + RawElementData } -// GetRecorded implements Element.GetRecorded -func (e ListElementData) GetRecorded() interface{} { - // https://golang.org/doc/faq#nil_error - if e.Recorded == nil { +// GetRecordedList returns the Recorded value as a list +func (e ListElementData) GetRecordedList() []interface{} { + return sliceCast(e.recorded) +} + +// GetLocalList returns the Local value as a list +func (e ListElementData) GetLocalList() []interface{} { + return sliceCast(e.local) +} + +// GetRemoteList returns the Remote value as a list +func (e ListElementData) GetRemoteList() []interface{} { + return sliceCast(e.remote) +} + +// sliceCast casts i to a slice if it is non-nil, otherwise returns nil +func sliceCast(i interface{}) []interface{} { + if i == nil { return nil } - return e.Recorded -} - -// GetLocal implements Element.GetLocal -func (e ListElementData) GetLocal() interface{} { - // https://golang.org/doc/faq#nil_error - if e.Local == nil { - return nil - } - return e.Local -} - -// GetRemote implements Element.GetRemote -func (e ListElementData) GetRemote() interface{} { - // https://golang.org/doc/faq#nil_error - if e.Remote == nil { - return nil - } - return e.Remote + return i.([]interface{}) } diff --git a/pkg/kubectl/apply/map_element.go b/pkg/kubectl/apply/map_element.go index 583429bb383..9fcd4e86b88 100644 --- a/pkg/kubectl/apply/map_element.go +++ b/pkg/kubectl/apply/map_element.go @@ -22,9 +22,6 @@ type MapElement struct { // FieldMetaImpl contains metadata about the field from openapi FieldMetaImpl - // HasElementData contains whether the field was set - HasElementData - // MapElementData contains the value a field was set to MapElementData @@ -48,39 +45,28 @@ var _ Element = &MapElement{} // MapElementData contains the recorded, local and remote data for a map or type type MapElementData struct { - // recorded contains the value of the field from the recorded object - Recorded map[string]interface{} - - // Local contains the value of the field from the recorded object - Local map[string]interface{} - - // Remote contains the value of the field from the recorded object - Remote map[string]interface{} + RawElementData } -// GetRecorded implements Element.GetRecorded -func (e MapElementData) GetRecorded() interface{} { - // https://golang.org/doc/faq#nil_error - if e.Recorded == nil { +// GetRecordedMap returns the Recorded value as a map +func (e MapElementData) GetRecordedMap() map[string]interface{} { + return mapCast(e.recorded) +} + +// GetLocalMap returns the Local value as a map +func (e MapElementData) GetLocalMap() map[string]interface{} { + return mapCast(e.local) +} + +// GetRemoteMap returns the Remote value as a map +func (e MapElementData) GetRemoteMap() map[string]interface{} { + return mapCast(e.remote) +} + +// mapCast casts i to a map if it is non-nil, otherwise returns nil +func mapCast(i interface{}) map[string]interface{} { + if i == nil { return nil } - return e.Recorded -} - -// GetLocal implements Element.GetLocal -func (e MapElementData) GetLocal() interface{} { - // https://golang.org/doc/faq#nil_error - if e.Local == nil { - return nil - } - return e.Local -} - -// GetRemote implements Element.GetRemote -func (e MapElementData) GetRemote() interface{} { - // https://golang.org/doc/faq#nil_error - if e.Remote == nil { - return nil - } - return e.Remote + return i.(map[string]interface{}) } diff --git a/pkg/kubectl/apply/parse/factory.go b/pkg/kubectl/apply/parse/factory.go index a497b4cfcb3..7bd20c43530 100644 --- a/pkg/kubectl/apply/parse/factory.go +++ b/pkg/kubectl/apply/parse/factory.go @@ -48,14 +48,9 @@ func (b *Factory) CreateElement(recorded, local, remote map[string]interface{}) return nil, err } - // Get the item for the type - hasRecorded := recorded != nil - hasLocal := local != nil - hasRemote := remote != nil + data := apply.NewRawElementData(recorded, local, remote) fieldName := "" - item, err := visitor.getItem(oapiKind, fieldName, - apply.RawElementData{recorded, local, remote}, - apply.HasElementData{hasRecorded, hasLocal, hasRemote}) + item, err := visitor.getItem(oapiKind, fieldName, data) if err != nil { return nil, err } @@ -65,10 +60,8 @@ func (b *Factory) CreateElement(recorded, local, remote map[string]interface{}) } // getItem returns the appropriate Item based on the underlying type of the arguments -func (v *ElementBuildingVisitor) getItem(s openapi.Schema, name string, - data apply.RawElementData, - isSet apply.HasElementData) (Item, error) { - kind, err := getType(data.Recorded, data.Local, data.Remote) +func (v *ElementBuildingVisitor) getItem(s openapi.Schema, name string, data apply.RawElementData) (Item, error) { + kind, err := getType(data.GetRecorded(), data.GetLocal(), data.GetRemote()) if err != nil { return nil, err } @@ -86,38 +79,23 @@ func (v *ElementBuildingVisitor) getItem(s openapi.Schema, name string, if err != nil { return nil, fmt.Errorf("expected openapi Primitive, was %T for %v", s, kind) } - return &primitiveItem{name, p, isSet, data}, nil + return &primitiveItem{name, p, data}, nil case reflect.Array, reflect.Slice: a, err := getArray(s) if err != nil { return nil, fmt.Errorf("expected openapi Array, was %T for %v", s, kind) } - return &listItem{name, a, isSet, - apply.ListElementData{ - sliceCast(data.Recorded), - sliceCast(data.Local), - sliceCast(data.Remote), - }}, nil + return &listItem{name, a, apply.ListElementData{data}}, nil case reflect.Map: if k, err := getKind(s); err == nil { - return &typeItem{name, k, isSet, - apply.MapElementData{ - mapCast(data.Recorded), - mapCast(data.Local), - mapCast(data.Remote), - }}, nil + return &typeItem{name, k, apply.MapElementData{data}}, nil } // If it looks like a map, and no openapi type is found, default to mapItem m, err := getMap(s) if err != nil { return nil, fmt.Errorf("expected openapi Kind or Map, was %T for %v", s, kind) } - return &mapItem{name, m, isSet, - apply.MapElementData{ - mapCast(data.Recorded), - mapCast(data.Local), - mapCast(data.Remote), - }}, nil + return &mapItem{name, m, apply.MapElementData{data}}, nil } return nil, fmt.Errorf("unsupported type type %v", kind) } diff --git a/pkg/kubectl/apply/parse/item.go b/pkg/kubectl/apply/parse/item.go index 87cc7728c8c..e2642a760f4 100644 --- a/pkg/kubectl/apply/parse/item.go +++ b/pkg/kubectl/apply/parse/item.go @@ -33,7 +33,6 @@ type primitiveItem struct { Name string Primitive *openapi.Primitive - apply.HasElementData apply.RawElementData } @@ -54,7 +53,6 @@ type listItem struct { Name string Array *openapi.Array - apply.HasElementData apply.ListElementData } @@ -75,7 +73,6 @@ type mapItem struct { Name string Map *openapi.Map - apply.HasElementData apply.MapElementData } @@ -96,7 +93,6 @@ type typeItem struct { Name string Type *openapi.Kind - apply.HasElementData apply.MapElementData } diff --git a/pkg/kubectl/apply/parse/list_element.go b/pkg/kubectl/apply/parse/list_element.go index 0edfa0a8165..ed9a59dd2fa 100644 --- a/pkg/kubectl/apply/parse/list_element.go +++ b/pkg/kubectl/apply/parse/list_element.go @@ -47,7 +47,6 @@ func (v ElementBuildingVisitor) doPrimitiveList(meta apply.FieldMetaImpl, item * MergeType: "merge", Name: item.Name, }, - HasElementData: item.HasElementData, ListElementData: item.ListElementData, Values: []apply.Element{}, } @@ -57,32 +56,26 @@ func (v ElementBuildingVisitor) doPrimitiveList(meta apply.FieldMetaImpl, item * // Locally defined items come first and retain their order // as defined locally - for _, l := range item.Local { + for _, l := range item.GetLocalList() { orderedKeys.UpsertLocal(l) } // Mixin remote values, adding any that are not present locally - for _, l := range item.Remote { + for _, l := range item.GetRemoteList() { orderedKeys.UpsertRemote(l) } // Mixin recorded values, adding any that are not present locally // or remotely - for _, l := range item.Recorded { + for _, l := range item.GetRecordedList() { orderedKeys.UpsertRecorded(l) } for i, l := range orderedKeys.Items { - recordedSet := l.Recorded != nil - localSet := l.Local != nil - remoteSet := l.Remote != nil - var s openapi.Schema if item.Array != nil && item.Array.SubType != nil { s = item.Array.SubType } - subitem, err := v.getItem(s, fmt.Sprintf("%d", i), - l.RawElementData, - apply.HasElementData{recordedSet, localSet, remoteSet}) + subitem, err := v.getItem(s, fmt.Sprintf("%d", i), l.RawElementData) if err != nil { return nil, err @@ -111,7 +104,6 @@ func (v ElementBuildingVisitor) doMapList(meta apply.FieldMetaImpl, item *listIt MergeKeys: key, Name: item.Name, }, - HasElementData: item.HasElementData, ListElementData: item.ListElementData, Values: []apply.Element{}, } @@ -121,31 +113,25 @@ func (v ElementBuildingVisitor) doMapList(meta apply.FieldMetaImpl, item *listIt // Locally defined items come first and retain their order // as defined locally - for _, l := range item.Local { + for _, l := range item.GetLocalList() { orderedKeys.UpsertLocal(key, l) } // Mixin remote values, adding any that are not present locally - for _, l := range item.Remote { + for _, l := range item.GetRemoteList() { orderedKeys.UpsertRemote(key, l) } // Mixin recorded values, adding any that are not present locally // or remotely - for _, l := range item.Recorded { + for _, l := range item.GetRecordedList() { orderedKeys.UpsertRecorded(key, l) } for i, l := range orderedKeys.Items { - recordedSet := l.Recorded != nil - localSet := l.Local != nil - remoteSet := l.Remote != nil - var s openapi.Schema if item.Array != nil && item.Array.SubType != nil { s = item.Array.SubType } - subitem, err := v.getItem(s, fmt.Sprintf("%d", i), - l.RawElementData, - apply.HasElementData{recordedSet, localSet, remoteSet}) + subitem, err := v.getItem(s, fmt.Sprintf("%d", i), l.RawElementData) if err != nil { return nil, err } @@ -166,30 +152,30 @@ func (v ElementBuildingVisitor) doMapList(meta apply.FieldMetaImpl, item *listIt // replaceListElement builds a new ListElement from a listItem // Uses the "replace" strategy and identify "same" elements across lists by their index func (v ElementBuildingVisitor) replaceListElement(meta apply.FieldMetaImpl, item *listItem) (*apply.ListElement, error) { - result := &apply.ListElement{ - FieldMetaImpl: meta, - ListElementData: item.ListElementData, - HasElementData: item.HasElementData, - Values: []apply.Element{}, - } - result.Name = item.Name + meta.Name = item.Name + result := &apply.ListElement{meta, item.ListElementData, []apply.Element{}} // Use the max length to iterate over the slices - for i := 0; i < max(len(item.Recorded), len(item.Local), len(item.Remote)); i++ { + for i := 0; i < max(len(item.GetRecordedList()), len(item.GetLocalList()), len(item.GetRemoteList())); i++ { // Lookup the item from each list - recorded, recordedSet := boundsSafeLookup(i, item.Recorded) - local, localSet := boundsSafeLookup(i, item.Local) - remote, remoteSet := boundsSafeLookup(i, item.Remote) + data := apply.RawElementData{} + if recorded, recordedSet := boundsSafeLookup(i, item.GetRecordedList()); recordedSet { + data.SetRecorded(recorded) + } + if local, localSet := boundsSafeLookup(i, item.GetLocalList()); localSet { + data.SetLocal(local) + } + if remote, remoteSet := boundsSafeLookup(i, item.GetRemoteList()); remoteSet { + data.SetRemote(remote) + } // Create the Item var s openapi.Schema if item.Array != nil && item.Array.SubType != nil { s = item.Array.SubType } - subitem, err := v.getItem(s, fmt.Sprintf("%d", i), - apply.RawElementData{recorded, local, remote}, - apply.HasElementData{recordedSet, localSet, remoteSet}) + subitem, err := v.getItem(s, fmt.Sprintf("%d", i), data) if err != nil { return nil, err } diff --git a/pkg/kubectl/apply/parse/map_element.go b/pkg/kubectl/apply/parse/map_element.go index c1a4e0fe120..6f21c566fb3 100644 --- a/pkg/kubectl/apply/parse/map_element.go +++ b/pkg/kubectl/apply/parse/map_element.go @@ -33,18 +33,13 @@ func (v ElementBuildingVisitor) mapElement(meta apply.FieldMetaImpl, item *mapIt } // Collect same fields from multiple maps into a map of elements - values, err := v.createMapValues(fn, meta, item.HasElementData, item.MapElementData) + values, err := v.createMapValues(fn, meta, item.MapElementData) if err != nil { return nil, err } // Return the result - return &apply.MapElement{ - FieldMetaImpl: meta, - HasElementData: item.HasElementData, - MapElementData: item.MapElementData, - Values: values, - }, nil + return &apply.MapElement{meta, item.MapElementData, values}, nil } // schemaFn returns the schema for a field or map value based on its name or key @@ -55,20 +50,24 @@ type schemaFn func(key string) openapi.Schema func (v ElementBuildingVisitor) createMapValues( schemaFn schemaFn, meta apply.FieldMetaImpl, - hasData apply.HasElementData, data apply.MapElementData) (map[string]apply.Element, error) { // Collate each key in the map values := map[string]apply.Element{} - for _, key := range keysUnion(data.Recorded, data.Local, data.Remote) { - recorded, recordedSet := nilSafeLookup(key, data.Recorded) - local, localSet := nilSafeLookup(key, data.Local) - remote, remoteSet := nilSafeLookup(key, data.Remote) + for _, key := range keysUnion(data.GetRecordedMap(), data.GetLocalMap(), data.GetRemoteMap()) { + combined := apply.RawElementData{} + if recorded, recordedSet := nilSafeLookup(key, data.GetRecordedMap()); recordedSet { + combined.SetRecorded(recorded) + } + if local, localSet := nilSafeLookup(key, data.GetLocalMap()); localSet { + combined.SetLocal(local) + } + if remote, remoteSet := nilSafeLookup(key, data.GetRemoteMap()); remoteSet { + combined.SetRemote(remote) + } // Create an item for the field - field, err := v.getItem(schemaFn(key), key, - apply.RawElementData{recorded, local, remote}, - apply.HasElementData{recordedSet, localSet, remoteSet}) + field, err := v.getItem(schemaFn(key), key, combined) if err != nil { return nil, err } diff --git a/pkg/kubectl/apply/parse/primitive_element.go b/pkg/kubectl/apply/parse/primitive_element.go index 0133117bd5c..5fac5ce04ee 100644 --- a/pkg/kubectl/apply/parse/primitive_element.go +++ b/pkg/kubectl/apply/parse/primitive_element.go @@ -20,11 +20,6 @@ import "k8s.io/kubernetes/pkg/kubectl/apply" // primitiveElement builds a new primitiveElement from a PrimitiveItem func (v ElementBuildingVisitor) primitiveElement(item *primitiveItem) (*apply.PrimitiveElement, error) { - result := &apply.PrimitiveElement{ - HasElementData: item.HasElementData, - RawElementData: item.RawElementData, - } - result.Name = item.Name - - return result, nil + meta := apply.FieldMetaImpl{Name: item.Name} + return &apply.PrimitiveElement{meta, item.RawElementData}, nil } diff --git a/pkg/kubectl/apply/parse/type_element.go b/pkg/kubectl/apply/parse/type_element.go index 39474129c64..0eabd9df020 100644 --- a/pkg/kubectl/apply/parse/type_element.go +++ b/pkg/kubectl/apply/parse/type_element.go @@ -32,16 +32,11 @@ func (v ElementBuildingVisitor) typeElement(meta apply.FieldMetaImpl, item *type } // Collect same fields from multiple maps into a map of elements - values, err := v.createMapValues(fn, meta, item.HasElementData, item.MapElementData) + values, err := v.createMapValues(fn, meta, item.MapElementData) if err != nil { return nil, err } // Return the result - return &apply.TypeElement{ - FieldMetaImpl: meta, - HasElementData: item.HasElementData, - MapElementData: item.MapElementData, - Values: values, - }, nil + return &apply.TypeElement{meta, item.MapElementData, values}, nil } diff --git a/pkg/kubectl/apply/parse/util.go b/pkg/kubectl/apply/parse/util.go index 6614877ac92..d9eb9ff6ef5 100644 --- a/pkg/kubectl/apply/parse/util.go +++ b/pkg/kubectl/apply/parse/util.go @@ -95,22 +95,6 @@ func getType(args ...interface{}) (reflect.Type, error) { return reflect.TypeOf(last), nil } -// sliceCast casts i to a slice if it is non-nil, otherwise returns nil -func sliceCast(i interface{}) []interface{} { - if i == nil { - return nil - } - return i.([]interface{}) -} - -// mapCast casts i to a map if it is non-nil, otherwise returns nil -func mapCast(i interface{}) map[string]interface{} { - if i == nil { - return nil - } - return i.(map[string]interface{}) -} - // getFieldMeta parses the metadata about the field from the openapi spec func getFieldMeta(s openapi.Schema, name string) (apply.FieldMetaImpl, error) { m := apply.FieldMetaImpl{} diff --git a/pkg/kubectl/apply/primitive_element.go b/pkg/kubectl/apply/primitive_element.go index 5ab2b7d733d..847ee1a29ab 100644 --- a/pkg/kubectl/apply/primitive_element.go +++ b/pkg/kubectl/apply/primitive_element.go @@ -16,19 +16,12 @@ limitations under the License. package apply -import ( - "fmt" -) - // PrimitiveElement contains the recorded, local and remote values for a field // of type primitive type PrimitiveElement struct { // FieldMetaImpl contains metadata about the field from openapi FieldMetaImpl - // HasElementData contains whether the field was set - HasElementData - // RawElementData contains the values the field was set to RawElementData } @@ -38,9 +31,4 @@ func (e PrimitiveElement) Merge(v Strategy) (Result, error) { return v.MergePrimitive(e) } -// String returns a string representation of the PrimitiveElement -func (e PrimitiveElement) String() string { - return fmt.Sprintf("name: %s recorded: %v local: %v remote: %v", e.Name, e.Recorded, e.Local, e.Remote) -} - var _ Element = &PrimitiveElement{} diff --git a/pkg/kubectl/apply/strategy/merge.go b/pkg/kubectl/apply/strategy/merge.go index 9e807941da9..393ffc0a250 100644 --- a/pkg/kubectl/apply/strategy/merge.go +++ b/pkg/kubectl/apply/strategy/merge.go @@ -20,32 +20,14 @@ import "k8s.io/kubernetes/pkg/kubectl/apply" // Options controls how a merge will be executed type Options struct { - // FailOnConflict when true will fail patch creation if the Recorded and Remote + // FailOnConflict when true will fail patch creation if the recorded and remote // have 2 fields set for the same value that cannot be merged. // e.g. primitive values, list values with replace strategy, and map values with do // strategy FailOnConflict bool - - // ListOrder controls the order of items in a list after it is merged - ListOrder ListOrder } // Create returns a new apply.Visitor for merging multiple objects together func Create(options Options) apply.Strategy { return createDelegatingStrategy(options) } - -// ListOrder allows the caller to controller how ordering is determined when merging -// lists -// TODO: Implement this -type ListOrder int - -const ( - // RemoteOnlyLast appends items only appearing in the remote list to the end - RemoteOnlyLast ListOrder = iota - // RemoteOnlyFirst prepends items only appearing in the remote list to the beginning - RemoteOnlyFirst - // RemoteCollated will try to preserve the order of elements as much as possible by - // interleaving items - RemoteCollated -) diff --git a/pkg/kubectl/apply/strategy/merge_visitor.go b/pkg/kubectl/apply/strategy/merge_visitor.go index 2f62420603f..3a3c414fcb4 100644 --- a/pkg/kubectl/apply/strategy/merge_visitor.go +++ b/pkg/kubectl/apply/strategy/merge_visitor.go @@ -46,19 +46,20 @@ func (v mergeStrategy) MergeList(e apply.ListElement) (apply.Result, error) { merged := []interface{}{} for _, value := range e.Values { // Recursively merge the list element before adding the value to the list - result, err := value.Merge(v.strategic) + m, err := value.Merge(v.strategic) if err != nil { return apply.Result{}, err } - switch result.Operation { + fmt.Printf("\nResult %+v\n%+v\n", m.MergedResult, value) + switch m.Operation { case apply.SET: // Keep the list item value - merged = append(merged, result.MergedResult) + merged = append(merged, m.MergedResult) case apply.DROP: // Drop the list item value default: - panic(fmt.Errorf("Unexpected result operation type %+v", result)) + panic(fmt.Errorf("Unexpected result operation type %+v", m)) } } diff --git a/pkg/kubectl/apply/type_element.go b/pkg/kubectl/apply/type_element.go index c28267228a6..0462123fb10 100644 --- a/pkg/kubectl/apply/type_element.go +++ b/pkg/kubectl/apply/type_element.go @@ -22,10 +22,6 @@ type TypeElement struct { // FieldMetaImpl contains metadata about the field from openapi FieldMetaImpl - // HasElementData contains whether the field was set - HasElementData - - // ListElementData contains the value a field was set to MapElementData // Values contains the combined recorded-local-remote value of each field in the type