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).
|
// hash(content of configmap).
|
||||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
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 for configmap.
|
||||||
DataSources `json:",inline,omitempty" yaml:",inline,omitempty"`
|
DataSources `json:",inline,omitempty" yaml:",inline,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@ import (
|
||||||
type Application interface {
|
type Application interface {
|
||||||
// Resources computes and returns the resources for the app.
|
// Resources computes and returns the resources for the app.
|
||||||
Resources() (resource.ResourceCollection, error)
|
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.
|
// 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
|
// It contains resources from 1) untransformed resources from current manifest 2) transformed resources from sub packages
|
||||||
RawResources() (resource.ResourceCollection, error)
|
RawResources() (resource.ResourceCollection, error)
|
||||||
|
|
@ -63,9 +65,28 @@ func New(loader loader.Loader) (Application, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resources computes and returns the resources from the manifest.
|
// 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) {
|
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{}
|
errs := &interror.ManifestErrors{}
|
||||||
raw, err := a.RawResources()
|
raw, err := a.rawResources()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs.Append(err)
|
errs.Append(err)
|
||||||
}
|
}
|
||||||
|
|
@ -82,9 +103,8 @@ func (a *applicationImpl) Resources() (resource.ResourceCollection, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Only append hash for generated configmaps and secrets.
|
|
||||||
nht := transformers.NewNameHashTransformer()
|
allRes, err := resource.MergeWithOverride(raw, res)
|
||||||
err = nht.Transform(res)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -98,37 +118,11 @@ func (a *applicationImpl) Resources() (resource.ResourceCollection, error) {
|
||||||
return nil, errs
|
return nil, errs
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reindex the Raw Resources (resources from sub package and resources field of this package).
|
t, err := a.getTransformer(patches)
|
||||||
// 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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
allRes, err := resource.Merge(res, raw)
|
err = t.Transform(allRes)
|
||||||
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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -137,7 +131,25 @@ func (a *applicationImpl) Resources() (resource.ResourceCollection, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RawResources computes and returns the raw resources from the manifest.
|
// 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) {
|
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()
|
subAppResources, errs := a.subAppResources()
|
||||||
resources, err := resource.NewFromResources(a.loader, a.manifest.Resources)
|
resources, err := resource.NewFromResources(a.loader, a.manifest.Resources)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -166,7 +178,7 @@ func (a *applicationImpl) subAppResources() (resource.ResourceCollection, *inter
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Gather all transformed resources from subpackages.
|
// Gather all transformed resources from subpackages.
|
||||||
subAppResources, err := subapp.Resources()
|
subAppResources, err := subapp.SemiResources()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs.Append(err)
|
errs.Append(err)
|
||||||
continue
|
continue
|
||||||
|
|
@ -181,13 +193,19 @@ func (a *applicationImpl) subAppResources() (resource.ResourceCollection, *inter
|
||||||
}
|
}
|
||||||
|
|
||||||
// getTransformer generates the following transformers:
|
// getTransformer generates the following transformers:
|
||||||
// 1) name prefix
|
// 1) apply overlay
|
||||||
// 2) apply labels
|
// 2) name prefix
|
||||||
// 3) apply annotations
|
// 3) apply labels
|
||||||
// 4) update name reference
|
// 4) apply annotations
|
||||||
func (a *applicationImpl) getTransformer() (transformers.Transformer, error) {
|
func (a *applicationImpl) getTransformer(patches []*resource.Resource) (transformers.Transformer, error) {
|
||||||
ts := []transformers.Transformer{}
|
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))
|
npt, err := transformers.NewDefaultingNamePrefixTransformer(string(a.manifest.NamePrefix))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -206,6 +224,17 @@ func (a *applicationImpl) getTransformer() (transformers.Transformer, error) {
|
||||||
}
|
}
|
||||||
ts = append(ts, at)
|
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()
|
nrt, err := transformers.NewDefaultingNameReferenceTransformer()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -214,17 +243,6 @@ func (a *applicationImpl) getTransformer() (transformers.Transformer, error) {
|
||||||
return transformers.NewMultiTransformer(ts), nil
|
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 {
|
func unmarshal(y []byte, o interface{}) error {
|
||||||
j, err := yaml.YAMLToJSON(y)
|
j, err := yaml.YAMLToJSON(y)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ func TestResources(t *testing.T) {
|
||||||
"apiVersion": "v1",
|
"apiVersion": "v1",
|
||||||
"kind": "ConfigMap",
|
"kind": "ConfigMap",
|
||||||
"metadata": map[string]interface{}{
|
"metadata": map[string]interface{}{
|
||||||
"name": "foo-literalConfigMap-h25f8c59t4",
|
"name": "foo-literalConfigMap-mc92bgcbh5",
|
||||||
"labels": map[string]interface{}{
|
"labels": map[string]interface{}{
|
||||||
"app": "nginx",
|
"app": "nginx",
|
||||||
},
|
},
|
||||||
|
|
@ -146,7 +146,7 @@ func TestResources(t *testing.T) {
|
||||||
"apiVersion": "v1",
|
"apiVersion": "v1",
|
||||||
"kind": "Secret",
|
"kind": "Secret",
|
||||||
"metadata": map[string]interface{}{
|
"metadata": map[string]interface{}{
|
||||||
"name": "foo-secret-2c9kh7fh8t",
|
"name": "foo-secret-877fcfhgt5",
|
||||||
"labels": map[string]interface{}{
|
"labels": map[string]interface{}{
|
||||||
"app": "nginx",
|
"app": "nginx",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -39,12 +39,12 @@ diff -u -N /tmp/noop/extensions_v1beta1_Deployment_mungebot.yaml /tmp/transforme
|
||||||
+ valueFrom:
|
+ valueFrom:
|
||||||
+ configMapKeyRef:
|
+ configMapKeyRef:
|
||||||
+ key: somekey
|
+ key: somekey
|
||||||
+ name: test-infra-app-env-hf26mf2f2f
|
+ name: test-infra-app-env-bh449c299k
|
||||||
+ - name: BAR
|
+ - name: BAR
|
||||||
+ valueFrom:
|
+ valueFrom:
|
||||||
+ secretKeyRef:
|
+ secretKeyRef:
|
||||||
+ key: somekey
|
+ key: somekey
|
||||||
+ name: test-infra-app-tls-4d47hbbh9m
|
+ name: test-infra-app-tls-6hkmhf2224
|
||||||
- name: foo
|
- name: foo
|
||||||
value: bar
|
value: bar
|
||||||
- image: nginx
|
- image: nginx
|
||||||
|
|
@ -56,9 +56,9 @@ diff -u -N /tmp/noop/extensions_v1beta1_Deployment_mungebot.yaml /tmp/transforme
|
||||||
+ - configMapRef:
|
+ - configMapRef:
|
||||||
+ name: someConfigMap
|
+ name: someConfigMap
|
||||||
+ - configMapRef:
|
+ - configMapRef:
|
||||||
+ name: test-infra-app-env-hf26mf2f2f
|
+ name: test-infra-app-env-bh449c299k
|
||||||
+ - secretRef:
|
+ - secretRef:
|
||||||
+ name: test-infra-app-tls-4d47hbbh9m
|
+ name: test-infra-app-tls-6hkmhf2224
|
||||||
+ image: busybox
|
+ image: busybox
|
||||||
+ name: busybox
|
+ name: busybox
|
||||||
+ volumeMounts:
|
+ volumeMounts:
|
||||||
|
|
@ -68,11 +68,11 @@ diff -u -N /tmp/noop/extensions_v1beta1_Deployment_mungebot.yaml /tmp/transforme
|
||||||
+ name: app-tls
|
+ name: app-tls
|
||||||
+ volumes:
|
+ volumes:
|
||||||
+ - configMap:
|
+ - configMap:
|
||||||
+ name: test-infra-app-env-hf26mf2f2f
|
+ name: test-infra-app-env-bh449c299k
|
||||||
+ name: app-env
|
+ name: app-env
|
||||||
+ - name: app-tls
|
+ - name: app-tls
|
||||||
+ secret:
|
+ 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
|
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/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
|
+++ /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
|
+ app: mungebot
|
||||||
+ org: kubernetes
|
+ org: kubernetes
|
||||||
+ repo: test-infra
|
+ 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
|
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/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
|
+++ /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
|
+ app: mungebot
|
||||||
+ org: kubernetes
|
+ org: kubernetes
|
||||||
+ repo: test-infra
|
+ 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
|
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/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
|
+++ /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
|
+ app: mungebot
|
||||||
+ org: kubernetes
|
+ org: kubernetes
|
||||||
+ repo: test-infra
|
+ repo: test-infra
|
||||||
+ name: test-infra-app-tls-4d47hbbh9m
|
+ name: test-infra-app-tls-6hkmhf2224
|
||||||
+type: kubernetes.io/tls
|
+type: kubernetes.io/tls
|
||||||
diff -u -N /tmp/noop/v1_Service_mungebot-service.yaml /tmp/transformed/v1_Service_mungebot-service.yaml
|
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
|
--- /tmp/noop/v1_Service_mungebot-service.yaml YYYY-MM-DD HH:MM:SS
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ metadata:
|
||||||
app: mungebot
|
app: mungebot
|
||||||
org: kubernetes
|
org: kubernetes
|
||||||
repo: test-infra
|
repo: test-infra
|
||||||
name: test-infra-app-config-ht8ck65bcg
|
name: test-infra-app-config-hf5424hg8g
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
data:
|
data:
|
||||||
|
|
@ -27,7 +27,7 @@ metadata:
|
||||||
app: mungebot
|
app: mungebot
|
||||||
org: kubernetes
|
org: kubernetes
|
||||||
repo: test-infra
|
repo: test-infra
|
||||||
name: test-infra-app-env-hf26mf2f2f
|
name: test-infra-app-env-bh449c299k
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
data:
|
data:
|
||||||
|
|
@ -42,7 +42,7 @@ metadata:
|
||||||
app: mungebot
|
app: mungebot
|
||||||
org: kubernetes
|
org: kubernetes
|
||||||
repo: test-infra
|
repo: test-infra
|
||||||
name: test-infra-app-tls-4d47hbbh9m
|
name: test-infra-app-tls-6hkmhf2224
|
||||||
type: kubernetes.io/tls
|
type: kubernetes.io/tls
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
|
@ -103,12 +103,12 @@ spec:
|
||||||
valueFrom:
|
valueFrom:
|
||||||
configMapKeyRef:
|
configMapKeyRef:
|
||||||
key: somekey
|
key: somekey
|
||||||
name: test-infra-app-env-hf26mf2f2f
|
name: test-infra-app-env-bh449c299k
|
||||||
- name: BAR
|
- name: BAR
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
key: somekey
|
key: somekey
|
||||||
name: test-infra-app-tls-4d47hbbh9m
|
name: test-infra-app-tls-6hkmhf2224
|
||||||
- name: foo
|
- name: foo
|
||||||
value: bar
|
value: bar
|
||||||
image: nginx:1.7.9
|
image: nginx:1.7.9
|
||||||
|
|
@ -119,9 +119,9 @@ spec:
|
||||||
- configMapRef:
|
- configMapRef:
|
||||||
name: someConfigMap
|
name: someConfigMap
|
||||||
- configMapRef:
|
- configMapRef:
|
||||||
name: test-infra-app-env-hf26mf2f2f
|
name: test-infra-app-env-bh449c299k
|
||||||
- secretRef:
|
- secretRef:
|
||||||
name: test-infra-app-tls-4d47hbbh9m
|
name: test-infra-app-tls-6hkmhf2224
|
||||||
image: busybox
|
image: busybox
|
||||||
name: busybox
|
name: busybox
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
|
|
@ -131,8 +131,8 @@ spec:
|
||||||
name: app-tls
|
name: app-tls
|
||||||
volumes:
|
volumes:
|
||||||
- configMap:
|
- configMap:
|
||||||
name: test-infra-app-env-hf26mf2f2f
|
name: test-infra-app-env-bh449c299k
|
||||||
name: app-env
|
name: app-env
|
||||||
- name: app-tls
|
- name: app-tls
|
||||||
secret:
|
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
|
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/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
|
+++ /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
|
note: This is a test annotation
|
||||||
labels:
|
labels:
|
||||||
app: mynginx
|
app: mynginx
|
||||||
+ env: staging
|
+ env: staging
|
||||||
org: example.com
|
org: example.com
|
||||||
team: foo
|
- team: foo
|
||||||
- name: team-foo-nginx
|
- name: team-foo-nginx
|
||||||
|
+ team: override-foo
|
||||||
+ name: staging-team-foo-nginx
|
+ name: staging-team-foo-nginx
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
|
|
@ -16,16 +17,21 @@ diff -u -N /tmp/noop/apps_v1beta2_Deployment_nginx.yaml /tmp/transformed/apps_v1
|
||||||
app: mynginx
|
app: mynginx
|
||||||
+ env: staging
|
+ env: staging
|
||||||
org: example.com
|
org: example.com
|
||||||
team: foo
|
- team: foo
|
||||||
|
+ team: override-foo
|
||||||
template:
|
template:
|
||||||
@@ -20,6 +22,7 @@
|
metadata:
|
||||||
|
annotations:
|
||||||
note: This is a test annotation
|
note: This is a test annotation
|
||||||
labels:
|
labels:
|
||||||
app: mynginx
|
app: mynginx
|
||||||
+ env: staging
|
+ env: staging
|
||||||
org: example.com
|
org: example.com
|
||||||
team: foo
|
- team: foo
|
||||||
|
+ team: override-foo
|
||||||
spec:
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: nginx
|
||||||
@@ -30,8 +33,12 @@
|
@@ -30,8 +33,12 @@
|
||||||
- mountPath: /tmp/ps
|
- mountPath: /tmp/ps
|
||||||
name: nginx-persistent-storage
|
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
|
+ pdName: nginx-persistent-storage
|
||||||
name: nginx-persistent-storage
|
name: nginx-persistent-storage
|
||||||
- configMap:
|
- configMap:
|
||||||
- name: team-foo-configmap-in-base-72t84tc949
|
- name: team-foo-configmap-in-base-bbdmdh7m8t
|
||||||
+ name: staging-configmap-in-overlay-h4hbb8fckf
|
+ name: staging-configmap-in-overlay-k7cbc75tg8
|
||||||
+ name: configmap-in-overlay
|
+ name: configmap-in-overlay
|
||||||
+ - configMap:
|
+ - configMap:
|
||||||
+ name: staging-team-foo-configmap-in-base-72t84tc949
|
+ name: staging-team-foo-configmap-in-base-gh9d7t85gb
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
diff -u -N /tmp/noop/v1_ConfigMap_configmap-in-base.yaml /tmp/transformed/v1_ConfigMap_configmap-in-base.yaml
|
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/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
|
+++ /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 @@
|
@@ -8,6 +8,7 @@
|
||||||
creationTimestamp: null
|
creationTimestamp: null
|
||||||
labels:
|
labels:
|
||||||
app: mynginx
|
app: mynginx
|
||||||
+ env: staging
|
+ env: staging
|
||||||
org: example.com
|
org: example.com
|
||||||
team: foo
|
- team: foo
|
||||||
- name: team-foo-configmap-in-base-72t84tc949
|
- name: team-foo-configmap-in-base-bbdmdh7m8t
|
||||||
+ name: staging-team-foo-configmap-in-base-72t84tc949
|
+ 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
|
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/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
|
+++ /tmp/transformed/v1_ConfigMap_configmap-in-overlay.yaml YYYY-MM-DD HH:MM:SS
|
||||||
@@ -0,0 +1,9 @@
|
@@ -0,0 +1,10 @@
|
||||||
+apiVersion: v1
|
+apiVersion: v1
|
||||||
+data:
|
+data:
|
||||||
+ hello: world
|
+ hello: world
|
||||||
|
|
@ -65,7 +80,8 @@ diff -u -N /tmp/noop/v1_ConfigMap_configmap-in-overlay.yaml /tmp/transformed/v1_
|
||||||
+ creationTimestamp: null
|
+ creationTimestamp: null
|
||||||
+ labels:
|
+ labels:
|
||||||
+ env: staging
|
+ 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
|
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/noop/v1_Service_nginx.yaml YYYY-MM-DD HH:MM:SS
|
||||||
+++ /tmp/transformed/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
|
app: mynginx
|
||||||
+ env: staging
|
+ env: staging
|
||||||
org: example.com
|
org: example.com
|
||||||
team: foo
|
- team: foo
|
||||||
- name: team-foo-nginx
|
- name: team-foo-nginx
|
||||||
|
+ team: override-foo
|
||||||
+ name: staging-team-foo-nginx
|
+ name: staging-team-foo-nginx
|
||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
|
|
@ -85,4 +102,5 @@ diff -u -N /tmp/noop/v1_Service_nginx.yaml /tmp/transformed/v1_Service_nginx.yam
|
||||||
app: mynginx
|
app: mynginx
|
||||||
+ env: staging
|
+ env: staging
|
||||||
org: example.com
|
org: example.com
|
||||||
team: foo
|
- team: foo
|
||||||
|
+ team: override-foo
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
data:
|
data:
|
||||||
foo: bar
|
foo: override-bar
|
||||||
kind: ConfigMap
|
kind: ConfigMap
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
|
|
@ -10,8 +10,8 @@ metadata:
|
||||||
app: mynginx
|
app: mynginx
|
||||||
env: staging
|
env: staging
|
||||||
org: example.com
|
org: example.com
|
||||||
team: foo
|
team: override-foo
|
||||||
name: staging-team-foo-configmap-in-base-72t84tc949
|
name: staging-team-foo-configmap-in-base-gh9d7t85gb
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
data:
|
data:
|
||||||
|
|
@ -21,7 +21,8 @@ metadata:
|
||||||
creationTimestamp: null
|
creationTimestamp: null
|
||||||
labels:
|
labels:
|
||||||
env: staging
|
env: staging
|
||||||
name: staging-configmap-in-overlay-h4hbb8fckf
|
team: override-foo
|
||||||
|
name: staging-configmap-in-overlay-k7cbc75tg8
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
|
|
@ -32,7 +33,7 @@ metadata:
|
||||||
app: mynginx
|
app: mynginx
|
||||||
env: staging
|
env: staging
|
||||||
org: example.com
|
org: example.com
|
||||||
team: foo
|
team: override-foo
|
||||||
name: staging-team-foo-nginx
|
name: staging-team-foo-nginx
|
||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
|
|
@ -41,7 +42,7 @@ spec:
|
||||||
app: mynginx
|
app: mynginx
|
||||||
env: staging
|
env: staging
|
||||||
org: example.com
|
org: example.com
|
||||||
team: foo
|
team: override-foo
|
||||||
---
|
---
|
||||||
apiVersion: apps/v1beta2
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
|
|
@ -52,7 +53,7 @@ metadata:
|
||||||
app: mynginx
|
app: mynginx
|
||||||
env: staging
|
env: staging
|
||||||
org: example.com
|
org: example.com
|
||||||
team: foo
|
team: override-foo
|
||||||
name: staging-team-foo-nginx
|
name: staging-team-foo-nginx
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
|
|
@ -60,7 +61,7 @@ spec:
|
||||||
app: mynginx
|
app: mynginx
|
||||||
env: staging
|
env: staging
|
||||||
org: example.com
|
org: example.com
|
||||||
team: foo
|
team: override-foo
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
|
|
@ -69,7 +70,7 @@ spec:
|
||||||
app: mynginx
|
app: mynginx
|
||||||
env: staging
|
env: staging
|
||||||
org: example.com
|
org: example.com
|
||||||
team: foo
|
team: override-foo
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- image: nginx
|
- image: nginx
|
||||||
|
|
@ -82,8 +83,8 @@ spec:
|
||||||
pdName: nginx-persistent-storage
|
pdName: nginx-persistent-storage
|
||||||
name: nginx-persistent-storage
|
name: nginx-persistent-storage
|
||||||
- configMap:
|
- configMap:
|
||||||
name: staging-configmap-in-overlay-h4hbb8fckf
|
name: staging-configmap-in-overlay-k7cbc75tg8
|
||||||
name: configmap-in-overlay
|
name: configmap-in-overlay
|
||||||
- configMap:
|
- configMap:
|
||||||
name: staging-team-foo-configmap-in-base-72t84tc949
|
name: staging-team-foo-configmap-in-base-gh9d7t85gb
|
||||||
name: configmap-in-base
|
name: configmap-in-base
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ metadata:
|
||||||
namePrefix: staging-
|
namePrefix: staging-
|
||||||
objectLabels:
|
objectLabels:
|
||||||
env: staging
|
env: staging
|
||||||
|
team: override-foo
|
||||||
patches:
|
patches:
|
||||||
- deployment.yaml
|
- deployment.yaml
|
||||||
bases:
|
bases:
|
||||||
|
|
@ -13,3 +14,7 @@ configmaps:
|
||||||
- name: configmap-in-overlay
|
- name: configmap-in-overlay
|
||||||
literals:
|
literals:
|
||||||
- hello=world
|
- 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.
|
// KubeManifestFileName is the Well-Known File Name for a kubernetes app manifest.
|
||||||
const KubeManifestSuffix = ".yaml"
|
const KubeManifestSuffix = ".yaml"
|
||||||
const KubeManifestFileName = "Kube-manifest" + KubeManifestSuffix
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
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) {
|
func makeConfigMap(l loader.Loader, cm manifest.ConfigMap) (*corev1.ConfigMap, error) {
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,8 @@ import (
|
||||||
// Resource represents a Kubernetes Resource Object for ex. Deployment, Server
|
// Resource represents a Kubernetes Resource Object for ex. Deployment, Server
|
||||||
// ConfigMap etc.
|
// ConfigMap etc.
|
||||||
type Resource struct {
|
type Resource struct {
|
||||||
Data *unstructured.Unstructured
|
Data *unstructured.Unstructured
|
||||||
|
Behavior string
|
||||||
}
|
}
|
||||||
|
|
||||||
// GVKN returns Group/Version/Kind/Name for the resource.
|
// GVKN returns Group/Version/Kind/Name for the resource.
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import (
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
k8syaml "k8s.io/apimachinery/pkg/util/yaml"
|
k8syaml "k8s.io/apimachinery/pkg/util/yaml"
|
||||||
|
"k8s.io/kubectl/pkg/kinflate/constants"
|
||||||
)
|
)
|
||||||
|
|
||||||
// decode decodes a list of objects in byte array format
|
// decode decodes a list of objects in byte array format
|
||||||
|
|
@ -90,3 +91,75 @@ func Merge(rcs ...ResourceCollection) (ResourceCollection, error) {
|
||||||
|
|
||||||
return all, nil
|
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