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
1fef3121
Commit
1fef3121
authored
Oct 31, 2017
by
Phillip Wittrock
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Small refactorings for kubectl/apply merge packages
- move strings into constants - remove unnecessary interface - fix documentation - improve error messaging
parent
444a161d
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
46 additions
and
35 deletions
+46
-35
element.go
pkg/kubectl/apply/element.go
+3
-5
factory.go
pkg/kubectl/apply/parse/factory.go
+3
-3
list_element.go
pkg/kubectl/apply/parse/list_element.go
+2
-2
visitor.go
pkg/kubectl/apply/parse/visitor.go
+1
-1
merge_visitor.go
pkg/kubectl/apply/strategy/merge_visitor.go
+18
-12
strategic_visitor.go
pkg/kubectl/apply/strategy/strategic_visitor.go
+9
-7
visitor.go
pkg/kubectl/apply/visitor.go
+10
-5
No files found.
pkg/kubectl/apply/element.go
View file @
1fef3121
...
@@ -78,16 +78,14 @@ type FieldMeta interface {
...
@@ -78,16 +78,14 @@ type FieldMeta interface {
// FieldMetaImpl implements FieldMeta
// FieldMetaImpl implements FieldMeta
type
FieldMetaImpl
struct
{
type
FieldMetaImpl
struct
{
//
T
he type of merge strategy to use for this field
//
MergeType is t
he type of merge strategy to use for this field
// maybe "merge", "replace" or "retainkeys"
// maybe "merge", "replace" or "retainkeys"
// TODO: There maybe multiple strategies, so this may need to be a slice, map, or struct
// Address this in a follow up in the PR to introduce retainkeys strategy
MergeType
string
MergeType
string
//
The merge key
to use when the MergeType is "merge" and underlying type is a list
//
MergeKeys are the merge keys
to use when the MergeType is "merge" and underlying type is a list
MergeKeys
MergeKeys
MergeKeys
MergeKeys
// The openapi type of the field - "list", "primitive", "map"
// T
ype is t
he openapi type of the field - "list", "primitive", "map"
Type
string
Type
string
// Name contains of the field
// Name contains of the field
...
...
pkg/kubectl/apply/parse/factory.go
View file @
1fef3121
...
@@ -78,13 +78,13 @@ func (v *ElementBuildingVisitor) getItem(s proto.Schema, name string, data apply
...
@@ -78,13 +78,13 @@ func (v *ElementBuildingVisitor) getItem(s proto.Schema, name string, data apply
reflect
.
String
:
reflect
.
String
:
p
,
err
:=
getPrimitive
(
s
)
p
,
err
:=
getPrimitive
(
s
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"expected openapi Primitive, was %T for %v
"
,
s
,
kind
)
return
nil
,
fmt
.
Errorf
(
"expected openapi Primitive, was %T for %v
(%v)"
,
s
,
kind
,
err
)
}
}
return
&
primitiveItem
{
name
,
p
,
data
},
nil
return
&
primitiveItem
{
name
,
p
,
data
},
nil
case
reflect
.
Array
,
reflect
.
Slice
:
case
reflect
.
Array
,
reflect
.
Slice
:
a
,
err
:=
getArray
(
s
)
a
,
err
:=
getArray
(
s
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"expected openapi Array, was %T for %v
"
,
s
,
kind
)
return
nil
,
fmt
.
Errorf
(
"expected openapi Array, was %T for %v
(%v)"
,
s
,
kind
,
err
)
}
}
return
&
listItem
{
return
&
listItem
{
Name
:
name
,
Name
:
name
,
...
@@ -106,7 +106,7 @@ func (v *ElementBuildingVisitor) getItem(s proto.Schema, name string, data apply
...
@@ -106,7 +106,7 @@ func (v *ElementBuildingVisitor) getItem(s proto.Schema, name string, data apply
// If it looks like a map, and no openapi type is found, default to mapItem
// If it looks like a map, and no openapi type is found, default to mapItem
m
,
err
:=
getMap
(
s
)
m
,
err
:=
getMap
(
s
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"expected openapi Kind or Map, was %T for %v
"
,
s
,
kind
)
return
nil
,
fmt
.
Errorf
(
"expected openapi Kind or Map, was %T for %v
(%v)"
,
s
,
kind
,
err
)
}
}
return
&
mapItem
{
return
&
mapItem
{
Name
:
name
,
Name
:
name
,
...
...
pkg/kubectl/apply/parse/list_element.go
View file @
1fef3121
...
@@ -45,7 +45,7 @@ func (v ElementBuildingVisitor) mergeListElement(meta apply.FieldMetaImpl, item
...
@@ -45,7 +45,7 @@ func (v ElementBuildingVisitor) mergeListElement(meta apply.FieldMetaImpl, item
func
(
v
ElementBuildingVisitor
)
doPrimitiveList
(
meta
apply
.
FieldMetaImpl
,
item
*
listItem
)
(
*
apply
.
ListElement
,
error
)
{
func
(
v
ElementBuildingVisitor
)
doPrimitiveList
(
meta
apply
.
FieldMetaImpl
,
item
*
listItem
)
(
*
apply
.
ListElement
,
error
)
{
result
:=
&
apply
.
ListElement
{
result
:=
&
apply
.
ListElement
{
FieldMetaImpl
:
apply
.
FieldMetaImpl
{
FieldMetaImpl
:
apply
.
FieldMetaImpl
{
MergeType
:
"merge"
,
MergeType
:
apply
.
MergeStrategy
,
Name
:
item
.
Name
,
Name
:
item
.
Name
,
},
},
ListElementData
:
item
.
ListElementData
,
ListElementData
:
item
.
ListElementData
,
...
@@ -101,7 +101,7 @@ func (v ElementBuildingVisitor) doMapList(meta apply.FieldMetaImpl, item *listIt
...
@@ -101,7 +101,7 @@ func (v ElementBuildingVisitor) doMapList(meta apply.FieldMetaImpl, item *listIt
key
:=
meta
.
GetFieldMergeKeys
()
key
:=
meta
.
GetFieldMergeKeys
()
result
:=
&
apply
.
ListElement
{
result
:=
&
apply
.
ListElement
{
FieldMetaImpl
:
apply
.
FieldMetaImpl
{
FieldMetaImpl
:
apply
.
FieldMetaImpl
{
MergeType
:
"merge"
,
MergeType
:
apply
.
MergeStrategy
,
MergeKeys
:
key
,
MergeKeys
:
key
,
Name
:
item
.
Name
,
Name
:
item
.
Name
,
},
},
...
...
pkg/kubectl/apply/parse/visitor.go
View file @
1fef3121
...
@@ -54,7 +54,7 @@ func (v ElementBuildingVisitor) CreateListElement(item *listItem) (apply.Element
...
@@ -54,7 +54,7 @@ func (v ElementBuildingVisitor) CreateListElement(item *listItem) (apply.Element
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
if
meta
.
GetFieldMergeType
()
==
"merge"
{
if
meta
.
GetFieldMergeType
()
==
apply
.
MergeStrategy
{
return
v
.
mergeListElement
(
meta
,
item
)
return
v
.
mergeListElement
(
meta
,
item
)
}
}
return
v
.
replaceListElement
(
meta
,
item
)
return
v
.
replaceListElement
(
meta
,
item
)
...
...
pkg/kubectl/apply/strategy/merge_visitor.go
View file @
1fef3121
...
@@ -29,13 +29,13 @@ func createMergeStrategy(options Options, strategic *delegatingStrategy) mergeSt
...
@@ -29,13 +29,13 @@ func createMergeStrategy(options Options, strategic *delegatingStrategy) mergeSt
}
}
}
}
// mergeStrategy
creates a patch to merge a local file value into a remote field value
// mergeStrategy
merges the values in an Element into a single Result
type
mergeStrategy
struct
{
type
mergeStrategy
struct
{
strategic
*
delegatingStrategy
strategic
*
delegatingStrategy
options
Options
options
Options
}
}
// MergeList
creates a patch to merge a local list field value into a remote list field value
// MergeList
merges the lists in a ListElement into a single Result
func
(
v
mergeStrategy
)
MergeList
(
e
apply
.
ListElement
)
(
apply
.
Result
,
error
)
{
func
(
v
mergeStrategy
)
MergeList
(
e
apply
.
ListElement
)
(
apply
.
Result
,
error
)
{
// No merge logic if adding or deleting a field
// No merge logic if adding or deleting a field
if
result
,
done
:=
v
.
doAddOrDelete
(
e
);
done
{
if
result
,
done
:=
v
.
doAddOrDelete
(
e
);
done
{
...
@@ -70,26 +70,32 @@ func (v mergeStrategy) MergeList(e apply.ListElement) (apply.Result, error) {
...
@@ -70,26 +70,32 @@ func (v mergeStrategy) MergeList(e apply.ListElement) (apply.Result, error) {
return
apply
.
Result
{
Operation
:
apply
.
SET
,
MergedResult
:
merged
},
nil
return
apply
.
Result
{
Operation
:
apply
.
SET
,
MergedResult
:
merged
},
nil
}
}
// MergeMap
creates a patch to merge a local map field into a remote map field
// MergeMap
merges the maps in a MapElement into a single Result
func
(
v
mergeStrategy
)
MergeMap
(
e
apply
.
MapElement
)
(
apply
.
Result
,
error
)
{
func
(
v
mergeStrategy
)
MergeMap
(
e
apply
.
MapElement
)
(
apply
.
Result
,
error
)
{
return
v
.
doMergeMap
(
e
)
// No merge logic if adding or deleting a field
}
if
result
,
done
:=
v
.
doAddOrDelete
(
e
);
done
{
return
result
,
nil
}
// MergeType creates a patch to merge a local map field into a remote map field
return
v
.
doMergeMap
(
e
.
GetValues
())
func
(
v
mergeStrategy
)
MergeType
(
e
apply
.
TypeElement
)
(
apply
.
Result
,
error
)
{
return
v
.
doMergeMap
(
e
)
}
}
//
do merges a recorded, local and remote map into a new objec
t
//
MergeMap merges the type instances in a TypeElement into a single Resul
t
func
(
v
mergeStrategy
)
doMergeMap
(
e
apply
.
MapValues
Element
)
(
apply
.
Result
,
error
)
{
func
(
v
mergeStrategy
)
MergeType
(
e
apply
.
Type
Element
)
(
apply
.
Result
,
error
)
{
// No merge logic if adding or deleting a field
// No merge logic if adding or deleting a field
if
result
,
done
:=
v
.
doAddOrDelete
(
e
);
done
{
if
result
,
done
:=
v
.
doAddOrDelete
(
e
);
done
{
return
result
,
nil
return
result
,
nil
}
}
return
v
.
doMergeMap
(
e
.
GetValues
())
}
// do merges a recorded, local and remote map into a new object
func
(
v
mergeStrategy
)
doMergeMap
(
e
map
[
string
]
apply
.
Element
)
(
apply
.
Result
,
error
)
{
// Merge each item in the list
// Merge each item in the list
merged
:=
map
[
string
]
interface
{}{}
merged
:=
map
[
string
]
interface
{}{}
for
key
,
value
:=
range
e
.
GetValues
()
{
for
key
,
value
:=
range
e
{
// Recursively merge the map element before adding the value to the map
// Recursively merge the map element before adding the value to the map
result
,
err
:=
value
.
Merge
(
v
.
strategic
)
result
,
err
:=
value
.
Merge
(
v
.
strategic
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -134,7 +140,7 @@ func (v mergeStrategy) MergePrimitive(diff apply.PrimitiveElement) (apply.Result
...
@@ -134,7 +140,7 @@ func (v mergeStrategy) MergePrimitive(diff apply.PrimitiveElement) (apply.Result
return
apply
.
Result
{},
fmt
.
Errorf
(
"Cannot merge primitive element %v"
,
diff
.
Name
)
return
apply
.
Result
{},
fmt
.
Errorf
(
"Cannot merge primitive element %v"
,
diff
.
Name
)
}
}
// MergeEmpty
// MergeEmpty
returns an empty result
func
(
v
mergeStrategy
)
MergeEmpty
(
diff
apply
.
EmptyElement
)
(
apply
.
Result
,
error
)
{
func
(
v
mergeStrategy
)
MergeEmpty
(
diff
apply
.
EmptyElement
)
(
apply
.
Result
,
error
)
{
return
apply
.
Result
{
Operation
:
apply
.
SET
},
nil
return
apply
.
Result
{
Operation
:
apply
.
SET
},
nil
}
}
...
...
pkg/kubectl/apply/strategy/strategic_visitor.go
View file @
1fef3121
...
@@ -16,7 +16,9 @@ limitations under the License.
...
@@ -16,7 +16,9 @@ limitations under the License.
package
strategy
package
strategy
import
"k8s.io/kubernetes/pkg/kubectl/apply"
import
(
"k8s.io/kubernetes/pkg/kubectl/apply"
)
// delegatingStrategy delegates merging fields to other visitor implementations
// delegatingStrategy delegates merging fields to other visitor implementations
// based on the merge strategy preferred by the field.
// based on the merge strategy preferred by the field.
...
@@ -41,9 +43,9 @@ func createDelegatingStrategy(options Options) *delegatingStrategy {
...
@@ -41,9 +43,9 @@ func createDelegatingStrategy(options Options) *delegatingStrategy {
func
(
v
delegatingStrategy
)
MergeList
(
diff
apply
.
ListElement
)
(
apply
.
Result
,
error
)
{
func
(
v
delegatingStrategy
)
MergeList
(
diff
apply
.
ListElement
)
(
apply
.
Result
,
error
)
{
// TODO: Support retainkeys
// TODO: Support retainkeys
switch
diff
.
GetFieldMergeType
()
{
switch
diff
.
GetFieldMergeType
()
{
case
"merge"
:
case
apply
.
MergeStrategy
:
return
v
.
merge
.
MergeList
(
diff
)
return
v
.
merge
.
MergeList
(
diff
)
case
"replace"
:
case
apply
.
ReplaceStrategy
:
return
v
.
replace
.
MergeList
(
diff
)
return
v
.
replace
.
MergeList
(
diff
)
default
:
default
:
return
v
.
replace
.
MergeList
(
diff
)
return
v
.
replace
.
MergeList
(
diff
)
...
@@ -55,9 +57,9 @@ func (v delegatingStrategy) MergeList(diff apply.ListElement) (apply.Result, err
...
@@ -55,9 +57,9 @@ func (v delegatingStrategy) MergeList(diff apply.ListElement) (apply.Result, err
func
(
v
delegatingStrategy
)
MergeMap
(
diff
apply
.
MapElement
)
(
apply
.
Result
,
error
)
{
func
(
v
delegatingStrategy
)
MergeMap
(
diff
apply
.
MapElement
)
(
apply
.
Result
,
error
)
{
// TODO: Support retainkeys
// TODO: Support retainkeys
switch
diff
.
GetFieldMergeType
()
{
switch
diff
.
GetFieldMergeType
()
{
case
"merge"
:
case
apply
.
MergeStrategy
:
return
v
.
merge
.
MergeMap
(
diff
)
return
v
.
merge
.
MergeMap
(
diff
)
case
"replace"
:
case
apply
.
ReplaceStrategy
:
return
v
.
replace
.
MergeMap
(
diff
)
return
v
.
replace
.
MergeMap
(
diff
)
default
:
default
:
return
v
.
merge
.
MergeMap
(
diff
)
return
v
.
merge
.
MergeMap
(
diff
)
...
@@ -69,9 +71,9 @@ func (v delegatingStrategy) MergeMap(diff apply.MapElement) (apply.Result, error
...
@@ -69,9 +71,9 @@ func (v delegatingStrategy) MergeMap(diff apply.MapElement) (apply.Result, error
func
(
v
delegatingStrategy
)
MergeType
(
diff
apply
.
TypeElement
)
(
apply
.
Result
,
error
)
{
func
(
v
delegatingStrategy
)
MergeType
(
diff
apply
.
TypeElement
)
(
apply
.
Result
,
error
)
{
// TODO: Support retainkeys
// TODO: Support retainkeys
switch
diff
.
GetFieldMergeType
()
{
switch
diff
.
GetFieldMergeType
()
{
case
"merge"
:
case
apply
.
MergeStrategy
:
return
v
.
merge
.
MergeType
(
diff
)
return
v
.
merge
.
MergeType
(
diff
)
case
"replace"
:
case
apply
.
ReplaceStrategy
:
return
v
.
replace
.
MergeType
(
diff
)
return
v
.
replace
.
MergeType
(
diff
)
default
:
default
:
return
v
.
merge
.
MergeType
(
diff
)
return
v
.
merge
.
MergeType
(
diff
)
...
...
pkg/kubectl/apply/visitor.go
View file @
1fef3121
...
@@ -56,8 +56,13 @@ type Result struct {
...
@@ -56,8 +56,13 @@ type Result struct {
MergedResult
interface
{}
MergedResult
interface
{}
}
}
// MapValuesElement exposes how to get the field / key - value pairs out of a Map or Type Element
const
(
type
MapValuesElement
interface
{
// MergeStrategy is the strategy to merge the local and remote values
Element
MergeStrategy
=
"merge"
GetValues
()
map
[
string
]
Element
}
// RetainKeysStrategy is the strategy to merge the local and remote values, but drop any fields not defined locally
RetainKeysStrategy
=
"retainKeys"
// ReplaceStrategy is the strategy to replace the remote value with the local value
ReplaceStrategy
=
"replace"
)
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