Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
32e16d09
Commit
32e16d09
authored
Oct 02, 2017
by
Phillip Wittrock
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Address PR comments
parent
df5fc7a2
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
180 additions
and
259 deletions
+180
-259
element.go
pkg/kubectl/apply/element.go
+96
-46
list_element.go
pkg/kubectl/apply/list_element.go
+15
-30
map_element.go
pkg/kubectl/apply/map_element.go
+15
-29
factory.go
pkg/kubectl/apply/parse/factory.go
+8
-30
item.go
pkg/kubectl/apply/parse/item.go
+0
-4
list_element.go
pkg/kubectl/apply/parse/list_element.go
+22
-36
map_element.go
pkg/kubectl/apply/parse/map_element.go
+14
-15
primitive_element.go
pkg/kubectl/apply/parse/primitive_element.go
+2
-7
type_element.go
pkg/kubectl/apply/parse/type_element.go
+2
-7
util.go
pkg/kubectl/apply/parse/util.go
+0
-16
primitive_element.go
pkg/kubectl/apply/primitive_element.go
+0
-12
merge.go
pkg/kubectl/apply/strategy/merge.go
+1
-19
merge_visitor.go
pkg/kubectl/apply/strategy/merge_visitor.go
+5
-4
type_element.go
pkg/kubectl/apply/type_element.go
+0
-4
No files found.
pkg/kubectl/apply/element.go
View file @
32e16d09
...
...
@@ -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 R
emote
// Value is the value of the primitive, should match
recorded, local and r
emote
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
}
pkg/kubectl/apply/list_element.go
View file @
32e16d09
...
...
@@ -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
{}
RawElementData
}
// Remote contains the value of the field from the recorded object
Remote
[]
interface
{}
// GetRecordedList returns the Recorded value as a list
func
(
e
ListElementData
)
GetRecordedList
()
[]
interface
{}
{
return
sliceCast
(
e
.
recorded
)
}
// GetRecorded implements Element.GetRecorded
func
(
e
ListElementData
)
GetRecorded
()
interface
{}
{
// https://golang.org/doc/faq#nil_error
if
e
.
Recorded
==
nil
{
return
nil
}
return
e
.
Recorded
// GetLocalList returns the Local value as a list
func
(
e
ListElementData
)
GetLocalList
()
[]
interface
{}
{
return
sliceCast
(
e
.
local
)
}
// 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
// GetRemoteList returns the Remote value as a list
func
(
e
ListElementData
)
GetRemoteList
()
[]
interface
{}
{
return
sliceCast
(
e
.
remote
)
}
// GetRemote implements Element.GetRemote
func
(
e
ListElementData
)
GetRemote
()
interface
{}
{
// https://golang.org/doc/faq#nil_error
if
e
.
Remote
==
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
e
.
Remote
return
i
.
([]
interface
{})
}
pkg/kubectl/apply/map_element.go
View file @
32e16d09
...
...
@@ -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
{}
RawElementData
}
// Remote contains the value of the field from the recorded object
Remote
map
[
string
]
interface
{}
// GetRecordedMap returns the Recorded value as a map
func
(
e
MapElementData
)
GetRecordedMap
()
map
[
string
]
interface
{}
{
return
mapCast
(
e
.
recorded
)
}
// GetRecorded implements Element.GetRecorded
func
(
e
MapElementData
)
GetRecorded
()
interface
{}
{
// https://golang.org/doc/faq#nil_error
if
e
.
Recorded
==
nil
{
return
nil
}
return
e
.
Recorded
// GetLocalMap returns the Local value as a map
func
(
e
MapElementData
)
GetLocalMap
()
map
[
string
]
interface
{}
{
return
mapCast
(
e
.
local
)
}
// 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
// GetRemoteMap returns the Remote value as a map
func
(
e
MapElementData
)
GetRemoteMap
()
map
[
string
]
interface
{}
{
return
mapCast
(
e
.
remote
)
}
// GetRemote implements Element.GetRemote
func
(
e
MapElementData
)
GetRemote
()
interface
{}
{
// https://golang.org/doc/faq#nil_error
if
e
.
Remote
==
nil
{
// 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
.
Remote
return
i
.
(
map
[
string
]
interface
{})
}
pkg/kubectl/apply/parse/factory.go
View file @
32e16d09
...
...
@@ -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
)
}
pkg/kubectl/apply/parse/item.go
View file @
32e16d09
...
...
@@ -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
}
...
...
pkg/kubectl/apply/parse/list_element.go
View file @
32e16d09
...
...
@@ -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
}
...
...
pkg/kubectl/apply/parse/map_element.go
View file @
32e16d09
...
...
@@ -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
}
...
...
pkg/kubectl/apply/parse/primitive_element.go
View file @
32e16d09
...
...
@@ -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
}
pkg/kubectl/apply/parse/type_element.go
View file @
32e16d09
...
...
@@ -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
}
pkg/kubectl/apply/parse/util.go
View file @
32e16d09
...
...
@@ -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
{}
...
...
pkg/kubectl/apply/primitive_element.go
View file @
32e16d09
...
...
@@ -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
{}
pkg/kubectl/apply/strategy/merge.go
View file @
32e16d09
...
...
@@ -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 R
emote
// FailOnConflict when true will fail patch creation if the
recorded and r
emote
// 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
)
pkg/kubectl/apply/strategy/merge_visitor.go
View file @
32e16d09
...
...
@@ -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
(
"
\n
Result %+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
))
}
}
...
...
pkg/kubectl/apply/type_element.go
View file @
32e16d09
...
...
@@ -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
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment