Merge "Replacement transformer improvement"

This commit is contained in:
Zuul 2020-04-29 22:46:14 +00:00 committed by Gerrit Code Review
commit e6a6a655e1
3 changed files with 135 additions and 7 deletions

View File

@ -91,3 +91,13 @@ type ErrIndexOutOfBound struct {
func (e ErrIndexOutOfBound) Error() string {
return fmt.Sprintf("index %v is out of bound", e.Index)
}
// ErrMapNotFound returned if map specified in fieldRef option was not found in a list
type ErrMapNotFound struct {
Key, Value, ListKey string
}
func (e ErrMapNotFound) Error() string {
return fmt.Sprintf("unable to find map key '%s' with the value '%s' in list under '%s' key",
e.Key, e.Value, e.ListKey)
}

View File

@ -28,6 +28,10 @@ var (
substringPatternRegex = regexp.MustCompile(`(\S+)%(\S+)%$`)
)
const (
dotReplacer = "$$$$"
)
// GetGVK returns group, version, kind object used to register version
// of the plugin
func GetGVK() schema.GroupVersionKind {
@ -151,7 +155,23 @@ func substitute(m resmap.ResMap, to *types.ReplTarget, replacement interface{})
}
for _, r := range resources {
for _, p := range to.FieldRefs {
// TODO (dukov) rework this using k8s.io/client-go/util/jsonpath
parts := strings.Split(p, "[")
var tmp []string
for _, part := range parts {
if strings.Contains(part, "]") {
filter := strings.Split(part, "]")
filter[0] = strings.ReplaceAll(filter[0], ".", dotReplacer)
part = strings.Join(filter, "]")
}
tmp = append(tmp, part)
}
p = strings.Join(tmp, "[")
pathSlice := strings.Split(p, ".")
for i, part := range pathSlice {
pathSlice[i] = strings.ReplaceAll(part, dotReplacer, ".")
}
if err := updateField(r.Map(), pathSlice, replacement); err != nil {
return err
}
@ -246,15 +266,15 @@ func updateMapField(m map[string]interface{}, pathToField []string, replacement
}
switch typedV := v.(type) {
case []interface{}:
for _, item := range typedV {
for i, item := range typedV {
typedItem, ok := item.(map[string]interface{})
if !ok {
return ErrTypeMismatch{Actual: item, Expectation: fmt.Sprintf("is expected to be %T", typedItem)}
}
if actualValue, ok := typedItem[key]; ok {
if value == actualValue {
// TODO (dukov) should not we do 'item = replacement' here?
typedItem[key] = value
typedV[i] = replacement
return nil
}
}
}
@ -273,7 +293,7 @@ func updateSliceField(m []interface{}, pathToField []string, replacement interfa
if len(pathToField) == 0 {
return nil
}
_, key, value, isArray := getFirstPathSegment(pathToField[0])
path, key, value, isArray := getFirstPathSegment(pathToField[0])
if isArray {
for _, item := range m {
@ -287,6 +307,7 @@ func updateSliceField(m []interface{}, pathToField []string, replacement interfa
}
}
}
return ErrMapNotFound{Key: key, Value: value, ListKey: path}
}
index, err := strconv.Atoi(pathToField[0])

View File

@ -89,7 +89,7 @@ replacements:
objref:
kind: Deployment
fieldrefs:
- spec.template.spec.containers[name=nginx-latest].image
- spec.template.spec.containers[name=nginx.latest].image
- source:
value: postgres:latest
target:
@ -112,7 +112,7 @@ spec:
- image: nginx:1.7.9
name: nginx-tagged
- image: nginx:latest
name: nginx-latest
name: nginx.latest
- image: foobar:1
name: replaced-with-digest
- image: postgres:1.8.0
@ -137,7 +137,7 @@ spec:
- image: nginx:1.7.9
name: nginx-tagged
- image: nginx:newtag
name: nginx-latest
name: nginx.latest
- image: foobar:1
name: replaced-with-digest
- image: postgres:latest
@ -455,6 +455,65 @@ kind: ReplacementTransformer
metadata:
name: notImportantHere
replacements:
- source:
objref:
kind: Pod
name: pod
fieldref: spec.containers[0]
target:
objref:
kind: Deployment
fieldrefs:
- spec.template.spec.containers[name=myapp-container]`,
in: `
apiVersion: v1
kind: Pod
metadata:
name: pod
spec:
containers:
- name: repl
image: repl
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy2
spec:
template:
spec:
containers:
- image: busybox
name: myapp-container
`,
expectedOut: `apiVersion: v1
kind: Pod
metadata:
name: pod
spec:
containers:
- image: repl
name: repl
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy2
spec:
template:
spec:
containers:
- image: repl
name: repl
`,
},
{
cfg: `
apiVersion: airshipit.org/v1alpha1
kind: ReplacementTransformer
metadata:
name: notImportantHere
replacements:
- source:
objref:
kind: Pod
@ -782,6 +841,44 @@ spec:
name: nginx-latest`,
expectedErr: "pattern 'TAG' is defined in configuration but was not found in target value nginx:latest",
},
{
cfg: `
apiVersion: airshipit.org/v1alpha1
kind: ReplacementTransformer
metadata:
name: notImportantHere
replacements:
- source:
value: 12345678
target:
objref:
kind: KubeadmControlPlane
fieldrefs:
- spec.kubeadmConfigSpec.files[path=konfigadm].content%{k8s-version}%
`,
in: `
kind: KubeadmControlPlane
metadata:
name: cluster-controlplane
spec:
infrastructureTemplate:
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3
kind: Metal3MachineTemplate
name: $(cluster-name)
kubeadmConfigSpec:
files:
- content: |
kubernetes:
version: {k8s-version}
container_runtime:
type: docker
owner: root:root
path: konfigadm_bug_
permissions: "0640"
`,
expectedErr: "unable to find map key 'path' with the value 'konfigadm' in list under 'files' key",
},
}
for _, tc := range testCases {