Add different behavior for configmaps in overlay
This commit is contained in:
parent
7fa986e55b
commit
7772932f7f
|
|
@ -132,6 +132,12 @@ type ConfigMap struct {
|
|||
// hash(content of configmap).
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
|
||||
// Behavior of the configmap, must be one of create, merge and replace
|
||||
// 'create': create a new one;
|
||||
// 'replace': replace the existing one;
|
||||
// 'merge': merge the existing one.
|
||||
Behavior string `json:"behavior,omitempty" yaml:"behavior,omitempty"`
|
||||
|
||||
// DataSources for configmap.
|
||||
DataSources `json:",inline,omitempty" yaml:",inline,omitempty"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ import (
|
|||
type Application interface {
|
||||
// Resources computes and returns the resources for the app.
|
||||
Resources() (resource.ResourceCollection, error)
|
||||
// SemiResources computes and returns the resources without name hash and name reference for the app
|
||||
SemiResources() (resource.ResourceCollection, error)
|
||||
// RawResources computes and returns the raw resources from the manifest.
|
||||
// It contains resources from 1) untransformed resources from current manifest 2) transformed resources from sub packages
|
||||
RawResources() (resource.ResourceCollection, error)
|
||||
|
|
@ -63,9 +65,28 @@ func New(loader loader.Loader) (Application, error) {
|
|||
}
|
||||
|
||||
// Resources computes and returns the resources from the manifest.
|
||||
// The namehashing for configmap/secrets and resolving name reference is only done
|
||||
// in the most top overlay once at the end of getting resources.
|
||||
func (a *applicationImpl) Resources() (resource.ResourceCollection, error) {
|
||||
res, err := a.SemiResources()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t, err := a.getHashAndReferenceTransformer()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = t.Transform(res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// SemiResources computes and returns the resources without name hash and name reference for the app
|
||||
func (a *applicationImpl) SemiResources() (resource.ResourceCollection, error) {
|
||||
errs := &interror.ManifestErrors{}
|
||||
raw, err := a.RawResources()
|
||||
raw, err := a.rawResources()
|
||||
if err != nil {
|
||||
errs.Append(err)
|
||||
}
|
||||
|
|
@ -82,9 +103,8 @@ func (a *applicationImpl) Resources() (resource.ResourceCollection, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Only append hash for generated configmaps and secrets.
|
||||
nht := transformers.NewNameHashTransformer()
|
||||
err = nht.Transform(res)
|
||||
|
||||
allRes, err := resource.MergeWithOverride(raw, res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -98,37 +118,11 @@ func (a *applicationImpl) Resources() (resource.ResourceCollection, error) {
|
|||
return nil, errs
|
||||
}
|
||||
|
||||
// Reindex the Raw Resources (resources from sub package and resources field of this package).
|
||||
// raw is a ResourceCollection (map) from <GVK, original name> to object with the transformed name.
|
||||
// transRaw is a ResourceCollection (map) from <GVK, transformed name> to object with the transformed name.
|
||||
transRaw := reindexResourceCollection(raw)
|
||||
// allRes contains the resources that are indexed by the original names (old names).
|
||||
// allTransRes contains the resources that are indexed by the transformed names (new names).
|
||||
// allRes and allTransRes point to the same set of objects with new names.
|
||||
allTransRes, err := resource.Merge(res, transRaw)
|
||||
t, err := a.getTransformer(patches)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
allRes, err := resource.Merge(res, raw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ot, err := transformers.NewOverlayTransformer(patches)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Overlay transformer uses the ResourceCollection indexed by the original names.
|
||||
err = ot.Transform(allRes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t, err := a.getTransformer()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = t.Transform(allTransRes)
|
||||
err = t.Transform(allRes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -137,7 +131,25 @@ func (a *applicationImpl) Resources() (resource.ResourceCollection, error) {
|
|||
}
|
||||
|
||||
// RawResources computes and returns the raw resources from the manifest.
|
||||
// The namehashing for configmap/secrets and resolving name reference is only done
|
||||
// in the most top overlay once at the end of getting resources.
|
||||
func (a *applicationImpl) RawResources() (resource.ResourceCollection, error) {
|
||||
res, err := a.rawResources()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t, err := a.getHashAndReferenceTransformer()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = t.Transform(res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (a *applicationImpl) rawResources() (resource.ResourceCollection, error) {
|
||||
subAppResources, errs := a.subAppResources()
|
||||
resources, err := resource.NewFromResources(a.loader, a.manifest.Resources)
|
||||
if err != nil {
|
||||
|
|
@ -166,7 +178,7 @@ func (a *applicationImpl) subAppResources() (resource.ResourceCollection, *inter
|
|||
continue
|
||||
}
|
||||
// Gather all transformed resources from subpackages.
|
||||
subAppResources, err := subapp.Resources()
|
||||
subAppResources, err := subapp.SemiResources()
|
||||
if err != nil {
|
||||
errs.Append(err)
|
||||
continue
|
||||
|
|
@ -181,13 +193,19 @@ func (a *applicationImpl) subAppResources() (resource.ResourceCollection, *inter
|
|||
}
|
||||
|
||||
// getTransformer generates the following transformers:
|
||||
// 1) name prefix
|
||||
// 2) apply labels
|
||||
// 3) apply annotations
|
||||
// 4) update name reference
|
||||
func (a *applicationImpl) getTransformer() (transformers.Transformer, error) {
|
||||
// 1) apply overlay
|
||||
// 2) name prefix
|
||||
// 3) apply labels
|
||||
// 4) apply annotations
|
||||
func (a *applicationImpl) getTransformer(patches []*resource.Resource) (transformers.Transformer, error) {
|
||||
ts := []transformers.Transformer{}
|
||||
|
||||
ot, err := transformers.NewOverlayTransformer(patches)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ts = append(ts, ot)
|
||||
|
||||
npt, err := transformers.NewDefaultingNamePrefixTransformer(string(a.manifest.NamePrefix))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -206,6 +224,17 @@ func (a *applicationImpl) getTransformer() (transformers.Transformer, error) {
|
|||
}
|
||||
ts = append(ts, at)
|
||||
|
||||
return transformers.NewMultiTransformer(ts), nil
|
||||
}
|
||||
|
||||
// getHashAndReferenceTransformer generates the following transformers:
|
||||
// 1) name hash for configmap and secrests
|
||||
// 2) apply name reference
|
||||
func (a *applicationImpl) getHashAndReferenceTransformer() (transformers.Transformer, error) {
|
||||
ts := []transformers.Transformer{}
|
||||
nht := transformers.NewNameHashTransformer()
|
||||
ts = append(ts, nht)
|
||||
|
||||
nrt, err := transformers.NewDefaultingNameReferenceTransformer()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -214,17 +243,6 @@ func (a *applicationImpl) getTransformer() (transformers.Transformer, error) {
|
|||
return transformers.NewMultiTransformer(ts), nil
|
||||
}
|
||||
|
||||
// reindexResourceCollection returns a new instance of ResourceCollection which
|
||||
// is indexed using the new name in the object.
|
||||
func reindexResourceCollection(rc resource.ResourceCollection) resource.ResourceCollection {
|
||||
result := resource.ResourceCollection{}
|
||||
for gvkn, res := range rc {
|
||||
gvkn.Name = res.Data.GetName()
|
||||
result[gvkn] = res
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func unmarshal(y []byte, o interface{}) error {
|
||||
j, err := yaml.YAMLToJSON(y)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ func TestResources(t *testing.T) {
|
|||
"apiVersion": "v1",
|
||||
"kind": "ConfigMap",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "foo-literalConfigMap-h25f8c59t4",
|
||||
"name": "foo-literalConfigMap-mc92bgcbh5",
|
||||
"labels": map[string]interface{}{
|
||||
"app": "nginx",
|
||||
},
|
||||
|
|
@ -146,7 +146,7 @@ func TestResources(t *testing.T) {
|
|||
"apiVersion": "v1",
|
||||
"kind": "Secret",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "foo-secret-2c9kh7fh8t",
|
||||
"name": "foo-secret-877fcfhgt5",
|
||||
"labels": map[string]interface{}{
|
||||
"app": "nginx",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -39,12 +39,12 @@ diff -u -N /tmp/noop/extensions_v1beta1_Deployment_mungebot.yaml /tmp/transforme
|
|||
+ valueFrom:
|
||||
+ configMapKeyRef:
|
||||
+ key: somekey
|
||||
+ name: test-infra-app-env-hf26mf2f2f
|
||||
+ name: test-infra-app-env-bh449c299k
|
||||
+ - name: BAR
|
||||
+ valueFrom:
|
||||
+ secretKeyRef:
|
||||
+ key: somekey
|
||||
+ name: test-infra-app-tls-4d47hbbh9m
|
||||
+ name: test-infra-app-tls-6hkmhf2224
|
||||
- name: foo
|
||||
value: bar
|
||||
- image: nginx
|
||||
|
|
@ -56,9 +56,9 @@ diff -u -N /tmp/noop/extensions_v1beta1_Deployment_mungebot.yaml /tmp/transforme
|
|||
+ - configMapRef:
|
||||
+ name: someConfigMap
|
||||
+ - configMapRef:
|
||||
+ name: test-infra-app-env-hf26mf2f2f
|
||||
+ name: test-infra-app-env-bh449c299k
|
||||
+ - secretRef:
|
||||
+ name: test-infra-app-tls-4d47hbbh9m
|
||||
+ name: test-infra-app-tls-6hkmhf2224
|
||||
+ image: busybox
|
||||
+ name: busybox
|
||||
+ volumeMounts:
|
||||
|
|
@ -68,11 +68,11 @@ diff -u -N /tmp/noop/extensions_v1beta1_Deployment_mungebot.yaml /tmp/transforme
|
|||
+ name: app-tls
|
||||
+ volumes:
|
||||
+ - configMap:
|
||||
+ name: test-infra-app-env-hf26mf2f2f
|
||||
+ name: test-infra-app-env-bh449c299k
|
||||
+ name: app-env
|
||||
+ - name: app-tls
|
||||
+ secret:
|
||||
+ secretName: test-infra-app-tls-4d47hbbh9m
|
||||
+ secretName: test-infra-app-tls-6hkmhf2224
|
||||
diff -u -N /tmp/noop/v1_ConfigMap_app-config.yaml /tmp/transformed/v1_ConfigMap_app-config.yaml
|
||||
--- /tmp/noop/v1_ConfigMap_app-config.yaml YYYY-MM-DD HH:MM:SS
|
||||
+++ /tmp/transformed/v1_ConfigMap_app-config.yaml YYYY-MM-DD HH:MM:SS
|
||||
|
|
@ -91,7 +91,7 @@ diff -u -N /tmp/noop/v1_ConfigMap_app-config.yaml /tmp/transformed/v1_ConfigMap_
|
|||
+ app: mungebot
|
||||
+ org: kubernetes
|
||||
+ repo: test-infra
|
||||
+ name: test-infra-app-config-ht8ck65bcg
|
||||
+ name: test-infra-app-config-hf5424hg8g
|
||||
diff -u -N /tmp/noop/v1_ConfigMap_app-env.yaml /tmp/transformed/v1_ConfigMap_app-env.yaml
|
||||
--- /tmp/noop/v1_ConfigMap_app-env.yaml YYYY-MM-DD HH:MM:SS
|
||||
+++ /tmp/transformed/v1_ConfigMap_app-env.yaml YYYY-MM-DD HH:MM:SS
|
||||
|
|
@ -109,7 +109,7 @@ diff -u -N /tmp/noop/v1_ConfigMap_app-env.yaml /tmp/transformed/v1_ConfigMap_app
|
|||
+ app: mungebot
|
||||
+ org: kubernetes
|
||||
+ repo: test-infra
|
||||
+ name: test-infra-app-env-hf26mf2f2f
|
||||
+ name: test-infra-app-env-bh449c299k
|
||||
diff -u -N /tmp/noop/v1_Secret_app-tls.yaml /tmp/transformed/v1_Secret_app-tls.yaml
|
||||
--- /tmp/noop/v1_Secret_app-tls.yaml YYYY-MM-DD HH:MM:SS
|
||||
+++ /tmp/transformed/v1_Secret_app-tls.yaml YYYY-MM-DD HH:MM:SS
|
||||
|
|
@ -127,7 +127,7 @@ diff -u -N /tmp/noop/v1_Secret_app-tls.yaml /tmp/transformed/v1_Secret_app-tls.y
|
|||
+ app: mungebot
|
||||
+ org: kubernetes
|
||||
+ repo: test-infra
|
||||
+ name: test-infra-app-tls-4d47hbbh9m
|
||||
+ name: test-infra-app-tls-6hkmhf2224
|
||||
+type: kubernetes.io/tls
|
||||
diff -u -N /tmp/noop/v1_Service_mungebot-service.yaml /tmp/transformed/v1_Service_mungebot-service.yaml
|
||||
--- /tmp/noop/v1_Service_mungebot-service.yaml YYYY-MM-DD HH:MM:SS
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ metadata:
|
|||
app: mungebot
|
||||
org: kubernetes
|
||||
repo: test-infra
|
||||
name: test-infra-app-config-ht8ck65bcg
|
||||
name: test-infra-app-config-hf5424hg8g
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
|
|
@ -27,7 +27,7 @@ metadata:
|
|||
app: mungebot
|
||||
org: kubernetes
|
||||
repo: test-infra
|
||||
name: test-infra-app-env-hf26mf2f2f
|
||||
name: test-infra-app-env-bh449c299k
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
|
|
@ -42,7 +42,7 @@ metadata:
|
|||
app: mungebot
|
||||
org: kubernetes
|
||||
repo: test-infra
|
||||
name: test-infra-app-tls-4d47hbbh9m
|
||||
name: test-infra-app-tls-6hkmhf2224
|
||||
type: kubernetes.io/tls
|
||||
---
|
||||
apiVersion: v1
|
||||
|
|
@ -103,12 +103,12 @@ spec:
|
|||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: somekey
|
||||
name: test-infra-app-env-hf26mf2f2f
|
||||
name: test-infra-app-env-bh449c299k
|
||||
- name: BAR
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
key: somekey
|
||||
name: test-infra-app-tls-4d47hbbh9m
|
||||
name: test-infra-app-tls-6hkmhf2224
|
||||
- name: foo
|
||||
value: bar
|
||||
image: nginx:1.7.9
|
||||
|
|
@ -119,9 +119,9 @@ spec:
|
|||
- configMapRef:
|
||||
name: someConfigMap
|
||||
- configMapRef:
|
||||
name: test-infra-app-env-hf26mf2f2f
|
||||
name: test-infra-app-env-bh449c299k
|
||||
- secretRef:
|
||||
name: test-infra-app-tls-4d47hbbh9m
|
||||
name: test-infra-app-tls-6hkmhf2224
|
||||
image: busybox
|
||||
name: busybox
|
||||
volumeMounts:
|
||||
|
|
@ -131,8 +131,8 @@ spec:
|
|||
name: app-tls
|
||||
volumes:
|
||||
- configMap:
|
||||
name: test-infra-app-env-hf26mf2f2f
|
||||
name: test-infra-app-env-bh449c299k
|
||||
name: app-env
|
||||
- name: app-tls
|
||||
secret:
|
||||
secretName: test-infra-app-tls-4d47hbbh9m
|
||||
secretName: test-infra-app-tls-6hkmhf2224
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
diff -u -N /tmp/noop/apps_v1beta2_Deployment_nginx.yaml /tmp/transformed/apps_v1beta2_Deployment_nginx.yaml
|
||||
--- /tmp/noop/apps_v1beta2_Deployment_nginx.yaml YYYY-MM-DD HH:MM:SS
|
||||
+++ /tmp/transformed/apps_v1beta2_Deployment_nginx.yaml YYYY-MM-DD HH:MM:SS
|
||||
@@ -5,13 +5,15 @@
|
||||
@@ -5,23 +5,26 @@
|
||||
note: This is a test annotation
|
||||
labels:
|
||||
app: mynginx
|
||||
+ env: staging
|
||||
org: example.com
|
||||
team: foo
|
||||
- team: foo
|
||||
- name: team-foo-nginx
|
||||
+ team: override-foo
|
||||
+ name: staging-team-foo-nginx
|
||||
spec:
|
||||
selector:
|
||||
|
|
@ -16,16 +17,21 @@ diff -u -N /tmp/noop/apps_v1beta2_Deployment_nginx.yaml /tmp/transformed/apps_v1
|
|||
app: mynginx
|
||||
+ env: staging
|
||||
org: example.com
|
||||
team: foo
|
||||
- team: foo
|
||||
+ team: override-foo
|
||||
template:
|
||||
@@ -20,6 +22,7 @@
|
||||
metadata:
|
||||
annotations:
|
||||
note: This is a test annotation
|
||||
labels:
|
||||
app: mynginx
|
||||
+ env: staging
|
||||
org: example.com
|
||||
team: foo
|
||||
- team: foo
|
||||
+ team: override-foo
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx
|
||||
@@ -30,8 +33,12 @@
|
||||
- mountPath: /tmp/ps
|
||||
name: nginx-persistent-storage
|
||||
|
|
@ -35,28 +41,37 @@ diff -u -N /tmp/noop/apps_v1beta2_Deployment_nginx.yaml /tmp/transformed/apps_v1
|
|||
+ pdName: nginx-persistent-storage
|
||||
name: nginx-persistent-storage
|
||||
- configMap:
|
||||
- name: team-foo-configmap-in-base-72t84tc949
|
||||
+ name: staging-configmap-in-overlay-h4hbb8fckf
|
||||
- name: team-foo-configmap-in-base-bbdmdh7m8t
|
||||
+ name: staging-configmap-in-overlay-k7cbc75tg8
|
||||
+ name: configmap-in-overlay
|
||||
+ - configMap:
|
||||
+ name: staging-team-foo-configmap-in-base-72t84tc949
|
||||
+ name: staging-team-foo-configmap-in-base-gh9d7t85gb
|
||||
name: configmap-in-base
|
||||
diff -u -N /tmp/noop/v1_ConfigMap_configmap-in-base.yaml /tmp/transformed/v1_ConfigMap_configmap-in-base.yaml
|
||||
--- /tmp/noop/v1_ConfigMap_configmap-in-base.yaml YYYY-MM-DD HH:MM:SS
|
||||
+++ /tmp/transformed/v1_ConfigMap_configmap-in-base.yaml YYYY-MM-DD HH:MM:SS
|
||||
@@ -1,6 +1,6 @@
|
||||
apiVersion: v1
|
||||
data:
|
||||
- foo: bar
|
||||
+ foo: override-bar
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
annotations:
|
||||
@@ -8,6 +8,7 @@
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app: mynginx
|
||||
+ env: staging
|
||||
org: example.com
|
||||
team: foo
|
||||
- name: team-foo-configmap-in-base-72t84tc949
|
||||
+ name: staging-team-foo-configmap-in-base-72t84tc949
|
||||
- team: foo
|
||||
- name: team-foo-configmap-in-base-bbdmdh7m8t
|
||||
+ team: override-foo
|
||||
+ name: staging-team-foo-configmap-in-base-gh9d7t85gb
|
||||
diff -u -N /tmp/noop/v1_ConfigMap_configmap-in-overlay.yaml /tmp/transformed/v1_ConfigMap_configmap-in-overlay.yaml
|
||||
--- /tmp/noop/v1_ConfigMap_configmap-in-overlay.yaml YYYY-MM-DD HH:MM:SS
|
||||
+++ /tmp/transformed/v1_ConfigMap_configmap-in-overlay.yaml YYYY-MM-DD HH:MM:SS
|
||||
@@ -0,0 +1,9 @@
|
||||
@@ -0,0 +1,10 @@
|
||||
+apiVersion: v1
|
||||
+data:
|
||||
+ hello: world
|
||||
|
|
@ -65,7 +80,8 @@ diff -u -N /tmp/noop/v1_ConfigMap_configmap-in-overlay.yaml /tmp/transformed/v1_
|
|||
+ creationTimestamp: null
|
||||
+ labels:
|
||||
+ env: staging
|
||||
+ name: staging-configmap-in-overlay-h4hbb8fckf
|
||||
+ team: override-foo
|
||||
+ name: staging-configmap-in-overlay-k7cbc75tg8
|
||||
diff -u -N /tmp/noop/v1_Service_nginx.yaml /tmp/transformed/v1_Service_nginx.yaml
|
||||
--- /tmp/noop/v1_Service_nginx.yaml YYYY-MM-DD HH:MM:SS
|
||||
+++ /tmp/transformed/v1_Service_nginx.yaml YYYY-MM-DD HH:MM:SS
|
||||
|
|
@ -75,8 +91,9 @@ diff -u -N /tmp/noop/v1_Service_nginx.yaml /tmp/transformed/v1_Service_nginx.yam
|
|||
app: mynginx
|
||||
+ env: staging
|
||||
org: example.com
|
||||
team: foo
|
||||
- team: foo
|
||||
- name: team-foo-nginx
|
||||
+ team: override-foo
|
||||
+ name: staging-team-foo-nginx
|
||||
spec:
|
||||
ports:
|
||||
|
|
@ -85,4 +102,5 @@ diff -u -N /tmp/noop/v1_Service_nginx.yaml /tmp/transformed/v1_Service_nginx.yam
|
|||
app: mynginx
|
||||
+ env: staging
|
||||
org: example.com
|
||||
team: foo
|
||||
- team: foo
|
||||
+ team: override-foo
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
apiVersion: v1
|
||||
data:
|
||||
foo: bar
|
||||
foo: override-bar
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
annotations:
|
||||
|
|
@ -10,8 +10,8 @@ metadata:
|
|||
app: mynginx
|
||||
env: staging
|
||||
org: example.com
|
||||
team: foo
|
||||
name: staging-team-foo-configmap-in-base-72t84tc949
|
||||
team: override-foo
|
||||
name: staging-team-foo-configmap-in-base-gh9d7t85gb
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
|
|
@ -21,7 +21,8 @@ metadata:
|
|||
creationTimestamp: null
|
||||
labels:
|
||||
env: staging
|
||||
name: staging-configmap-in-overlay-h4hbb8fckf
|
||||
team: override-foo
|
||||
name: staging-configmap-in-overlay-k7cbc75tg8
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
|
|
@ -32,7 +33,7 @@ metadata:
|
|||
app: mynginx
|
||||
env: staging
|
||||
org: example.com
|
||||
team: foo
|
||||
team: override-foo
|
||||
name: staging-team-foo-nginx
|
||||
spec:
|
||||
ports:
|
||||
|
|
@ -41,7 +42,7 @@ spec:
|
|||
app: mynginx
|
||||
env: staging
|
||||
org: example.com
|
||||
team: foo
|
||||
team: override-foo
|
||||
---
|
||||
apiVersion: apps/v1beta2
|
||||
kind: Deployment
|
||||
|
|
@ -52,7 +53,7 @@ metadata:
|
|||
app: mynginx
|
||||
env: staging
|
||||
org: example.com
|
||||
team: foo
|
||||
team: override-foo
|
||||
name: staging-team-foo-nginx
|
||||
spec:
|
||||
selector:
|
||||
|
|
@ -60,7 +61,7 @@ spec:
|
|||
app: mynginx
|
||||
env: staging
|
||||
org: example.com
|
||||
team: foo
|
||||
team: override-foo
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
|
|
@ -69,7 +70,7 @@ spec:
|
|||
app: mynginx
|
||||
env: staging
|
||||
org: example.com
|
||||
team: foo
|
||||
team: override-foo
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx
|
||||
|
|
@ -82,8 +83,8 @@ spec:
|
|||
pdName: nginx-persistent-storage
|
||||
name: nginx-persistent-storage
|
||||
- configMap:
|
||||
name: staging-configmap-in-overlay-h4hbb8fckf
|
||||
name: staging-configmap-in-overlay-k7cbc75tg8
|
||||
name: configmap-in-overlay
|
||||
- configMap:
|
||||
name: staging-team-foo-configmap-in-base-72t84tc949
|
||||
name: staging-team-foo-configmap-in-base-gh9d7t85gb
|
||||
name: configmap-in-base
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ metadata:
|
|||
namePrefix: staging-
|
||||
objectLabels:
|
||||
env: staging
|
||||
team: override-foo
|
||||
patches:
|
||||
- deployment.yaml
|
||||
bases:
|
||||
|
|
@ -13,3 +14,7 @@ configmaps:
|
|||
- name: configmap-in-overlay
|
||||
literals:
|
||||
- hello=world
|
||||
- name: configmap-in-base
|
||||
behavior: replace
|
||||
literals:
|
||||
- foo=override-bar
|
||||
|
|
|
|||
|
|
@ -19,3 +19,8 @@ package constants
|
|||
// KubeManifestFileName is the Well-Known File Name for a kubernetes app manifest.
|
||||
const KubeManifestSuffix = ".yaml"
|
||||
const KubeManifestFileName = "Kube-manifest" + KubeManifestSuffix
|
||||
|
||||
// Configmap behaviors
|
||||
const CreateBehavior = "create"
|
||||
const ReplaceBehavior = "replace"
|
||||
const MergeBehavior = "merge"
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ func newFromConfigMap(l loader.Loader, cm manifest.ConfigMap) (*Resource, error)
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Resource{Data: data}, nil
|
||||
return &Resource{Data: data, Behavior: cm.Behavior}, nil
|
||||
}
|
||||
|
||||
func makeConfigMap(l loader.Loader, cm manifest.ConfigMap) (*corev1.ConfigMap, error) {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import (
|
|||
// ConfigMap etc.
|
||||
type Resource struct {
|
||||
Data *unstructured.Unstructured
|
||||
Behavior string
|
||||
}
|
||||
|
||||
// GVKN returns Group/Version/Kind/Name for the resource.
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import (
|
|||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
k8syaml "k8s.io/apimachinery/pkg/util/yaml"
|
||||
"k8s.io/kubectl/pkg/kinflate/constants"
|
||||
)
|
||||
|
||||
// decode decodes a list of objects in byte array format
|
||||
|
|
@ -90,3 +91,75 @@ func Merge(rcs ...ResourceCollection) (ResourceCollection, error) {
|
|||
|
||||
return all, nil
|
||||
}
|
||||
|
||||
// MergeWithOverride will merge all of the entries in the slice of ResourceCollection with Override
|
||||
// If there is already an entry with the same GVKN exists, different actions are performed according to value of Behavior field
|
||||
// 'create': create a new one;
|
||||
// 'replace': replace the data only; keep the labels and annotations
|
||||
// 'merge': merge the data; keep the labels and annotations
|
||||
func MergeWithOverride(rcs ...ResourceCollection) (ResourceCollection, error) {
|
||||
all := ResourceCollection{}
|
||||
|
||||
for _, rc := range rcs {
|
||||
for gvkn, obj := range rc {
|
||||
if _, found := all[gvkn]; found {
|
||||
switch obj.Behavior {
|
||||
case "", constants.CreateBehavior:
|
||||
return nil, fmt.Errorf("Create an existing gvkn %#v is not allowed", gvkn)
|
||||
case constants.ReplaceBehavior:
|
||||
obj.replace(all[gvkn])
|
||||
all[gvkn] = obj
|
||||
case constants.MergeBehavior:
|
||||
obj.merge(all[gvkn])
|
||||
all[gvkn] = obj
|
||||
default:
|
||||
return nil, fmt.Errorf("The behavior of %#v must be one of merge and replace since it already exists in the base", gvkn)
|
||||
}
|
||||
} else {
|
||||
switch obj.Behavior {
|
||||
case "", constants.CreateBehavior:
|
||||
all[gvkn] = obj
|
||||
case constants.MergeBehavior, constants.ReplaceBehavior:
|
||||
return nil, fmt.Errorf("No merge or replace is allowed for non existing gvkn %#v", gvkn)
|
||||
default:
|
||||
return nil, fmt.Errorf("The behavior of %#v must be create since it doesn't exist", gvkn)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return all, nil
|
||||
}
|
||||
func (r *Resource) replace(other *Resource) {
|
||||
r.Data.SetLabels(mergeMap(other.Data.GetLabels(), r.Data.GetLabels()))
|
||||
r.Data.SetAnnotations(mergeMap(other.Data.GetAnnotations(), r.Data.GetAnnotations()))
|
||||
r.Data.SetName(other.Data.GetName())
|
||||
}
|
||||
|
||||
func (r *Resource) merge(other *Resource) {
|
||||
r.replace(other)
|
||||
mergeConfigmap(r.Data.Object, other.Data.Object, r.Data.Object)
|
||||
}
|
||||
|
||||
func mergeMap(maps ...map[string]string) map[string]string {
|
||||
mergedMap := map[string]string{}
|
||||
for _, m := range maps {
|
||||
for key, value := range m {
|
||||
mergedMap[key] = value
|
||||
}
|
||||
}
|
||||
return mergedMap
|
||||
}
|
||||
|
||||
// TODO: Add BinaryData once we sync to new k8s.io/api
|
||||
func mergeConfigmap(mergedTo map[string]interface{}, maps ...map[string]interface{}) {
|
||||
mergedMap := map[string]interface{}{}
|
||||
for _, m := range maps {
|
||||
datamap, ok := m["data"].(map[string]interface{})
|
||||
if ok {
|
||||
for key, value := range datamap {
|
||||
mergedMap[key] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
mergedTo["data"] = mergedMap
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue