mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-11 17:12:51 +00:00
optionally use filepath as part of merge key for merge3
This commit is contained in:
@@ -25,6 +25,8 @@ func GetMerge3Runner(name string) *Merge3Runner {
|
|||||||
"Path to updated package")
|
"Path to updated package")
|
||||||
c.Flags().StringVar(&r.toDir, "to", "",
|
c.Flags().StringVar(&r.toDir, "to", "",
|
||||||
"Path to destination package")
|
"Path to destination package")
|
||||||
|
c.Flags().BoolVar(&r.path, "path-merge-key", false,
|
||||||
|
"Use the path as part of the merge key when merging resources")
|
||||||
|
|
||||||
r.Command = c
|
r.Command = c
|
||||||
return r
|
return r
|
||||||
@@ -40,6 +42,7 @@ type Merge3Runner struct {
|
|||||||
ancestor string
|
ancestor string
|
||||||
fromDir string
|
fromDir string
|
||||||
toDir string
|
toDir string
|
||||||
|
path bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Merge3Runner) runE(c *cobra.Command, args []string) error {
|
func (r *Merge3Runner) runE(c *cobra.Command, args []string) error {
|
||||||
@@ -47,6 +50,7 @@ func (r *Merge3Runner) runE(c *cobra.Command, args []string) error {
|
|||||||
OriginalPath: r.ancestor,
|
OriginalPath: r.ancestor,
|
||||||
UpdatedPath: r.fromDir,
|
UpdatedPath: r.fromDir,
|
||||||
DestPath: r.toDir,
|
DestPath: r.toDir,
|
||||||
|
MergeOnPath: r.path,
|
||||||
}.Merge()
|
}.Merge()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml/merge3"
|
"sigs.k8s.io/kustomize/kyaml/yaml/merge3"
|
||||||
)
|
)
|
||||||
@@ -24,6 +25,11 @@ type Merge3 struct {
|
|||||||
UpdatedPath string
|
UpdatedPath string
|
||||||
DestPath string
|
DestPath string
|
||||||
MatchFilesGlob []string
|
MatchFilesGlob []string
|
||||||
|
|
||||||
|
// MergeOnPath will use the relative filepath as part of the merge key.
|
||||||
|
// This may be necessary if the directory contains multiple copies of
|
||||||
|
// the same resource, or resources patches.
|
||||||
|
MergeOnPath bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m Merge3) Merge() error {
|
func (m Merge3) Merge() error {
|
||||||
@@ -61,7 +67,7 @@ func (m Merge3) Merge() error {
|
|||||||
// Filter combines Resources with the same GVK + N + NS into tuples, and then merges them
|
// Filter combines Resources with the same GVK + N + NS into tuples, and then merges them
|
||||||
func (m Merge3) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
func (m Merge3) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||||
// index the nodes by their identity
|
// index the nodes by their identity
|
||||||
tl := tuples{}
|
tl := tuples{mergeOnPath: m.MergeOnPath}
|
||||||
for i := range nodes {
|
for i := range nodes {
|
||||||
if err := tl.add(nodes[i]); err != nil {
|
if err := tl.add(nodes[i]); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -102,6 +108,37 @@ func (m Merge3) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
|||||||
// tuples combines nodes with the same GVK + N + NS
|
// tuples combines nodes with the same GVK + N + NS
|
||||||
type tuples struct {
|
type tuples struct {
|
||||||
list []*tuple
|
list []*tuple
|
||||||
|
|
||||||
|
// mergeOnPath if set to true will use the resource filepath
|
||||||
|
// as part of the merge key
|
||||||
|
mergeOnPath bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// isSameResource returns true if meta1 and meta2 are for the same logic resource
|
||||||
|
func (ts *tuples) isSameResource(meta1, meta2 yaml.ResourceMeta) bool {
|
||||||
|
if meta1.Name != meta2.Name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if meta1.Namespace != meta2.Namespace {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if meta1.APIVersion != meta2.APIVersion {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if meta1.Kind != meta2.Kind {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if ts.mergeOnPath {
|
||||||
|
// directories may contain multiple copies of a resource with the same
|
||||||
|
// name, namespace, apiVersion and kind -- e.g. kustomize patches, or
|
||||||
|
// multiple environments
|
||||||
|
// mergeOnPath configures the merge logic to use the path as part of the
|
||||||
|
// resource key
|
||||||
|
if meta1.Annotations[kioutil.PathAnnotation] != meta2.Annotations[kioutil.PathAnnotation] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// add adds a node to the list, combining it with an existing matching Resource if found
|
// add adds a node to the list, combining it with an existing matching Resource if found
|
||||||
@@ -112,8 +149,7 @@ func (ts *tuples) add(node *yaml.RNode) error {
|
|||||||
}
|
}
|
||||||
for i := range ts.list {
|
for i := range ts.list {
|
||||||
t := ts.list[i]
|
t := ts.list[i]
|
||||||
if t.meta.Name == nodeMeta.Name && t.meta.Namespace == nodeMeta.Namespace &&
|
if ts.isSameResource(t.meta, nodeMeta) {
|
||||||
t.meta.APIVersion == nodeMeta.APIVersion && t.meta.Kind == nodeMeta.Kind {
|
|
||||||
return t.add(node)
|
return t.add(node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,3 +54,78 @@ func TestMerge3_Merge(t *testing.T) {
|
|||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestMerge3_Merge_path tests that if the same resource is specified multiple times
|
||||||
|
// with MergeOnPath, that the resources will be merged by the filepath name.
|
||||||
|
func TestMerge3_Merge_path(t *testing.T) {
|
||||||
|
_, datadir, _, ok := runtime.Caller(0)
|
||||||
|
if !assert.True(t, ok) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
datadir = filepath.Join(filepath.Dir(datadir), "testdata2")
|
||||||
|
|
||||||
|
// setup the local directory
|
||||||
|
dir, err := ioutil.TempDir("", "kyaml-test")
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
if !assert.NoError(t, copyutil.CopyDir(
|
||||||
|
filepath.Join(datadir, "dataset1-localupdates"),
|
||||||
|
filepath.Join(dir, "dataset1"))) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
err = filters.Merge3{
|
||||||
|
OriginalPath: filepath.Join(datadir, "dataset1"),
|
||||||
|
UpdatedPath: filepath.Join(datadir, "dataset1-remoteupdates"),
|
||||||
|
DestPath: filepath.Join(dir, "dataset1"),
|
||||||
|
MergeOnPath: true,
|
||||||
|
}.Merge()
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
diffs, err := copyutil.Diff(
|
||||||
|
filepath.Join(dir, "dataset1"),
|
||||||
|
filepath.Join(datadir, "dataset1-expected"))
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if !assert.Empty(t, diffs.List()) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestMerge3_Merge_fail tests that if the same resource is defined multiple times
|
||||||
|
// that merge will fail
|
||||||
|
func TestMerge3_Merge_fail(t *testing.T) {
|
||||||
|
_, datadir, _, ok := runtime.Caller(0)
|
||||||
|
if !assert.True(t, ok) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
datadir = filepath.Join(filepath.Dir(datadir), "testdata2")
|
||||||
|
|
||||||
|
// setup the local directory
|
||||||
|
dir, err := ioutil.TempDir("", "kyaml-test")
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
if !assert.NoError(t, copyutil.CopyDir(
|
||||||
|
filepath.Join(datadir, "dataset1-localupdates"),
|
||||||
|
filepath.Join(dir, "dataset1"))) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
err = filters.Merge3{
|
||||||
|
OriginalPath: filepath.Join(datadir, "dataset1"),
|
||||||
|
UpdatedPath: filepath.Join(datadir, "dataset1-remoteupdates"),
|
||||||
|
DestPath: filepath.Join(dir, "dataset1"),
|
||||||
|
}.Merge()
|
||||||
|
if !assert.Error(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# Copyright 2019 The Kubernetes Authors.
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: app
|
||||||
|
labels:
|
||||||
|
app: java
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: java2
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: java2
|
||||||
|
spec:
|
||||||
|
restartPolicy: Always
|
||||||
|
containers:
|
||||||
|
- name: app
|
||||||
|
image: gcr.io/project/app:version
|
||||||
|
command:
|
||||||
|
- java
|
||||||
|
- -jar
|
||||||
|
- /app.jar
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: app-config
|
||||||
|
env:
|
||||||
|
- name: JAVA_OPTS
|
||||||
|
value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
|
||||||
|
-Djava.security.egd=file:/dev/./urandom
|
||||||
|
imagePullPolicy: Always
|
||||||
|
minReadySeconds: 15
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# Copyright 2019 The Kubernetes Authors.
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: app
|
||||||
|
labels:
|
||||||
|
app: java3
|
||||||
|
spec:
|
||||||
|
replicas: 4
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: java
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: java
|
||||||
|
spec:
|
||||||
|
restartPolicy: Always
|
||||||
|
containers:
|
||||||
|
- name: app
|
||||||
|
image: gcr.io/project/app:version
|
||||||
|
command:
|
||||||
|
- java
|
||||||
|
- -jar
|
||||||
|
- /app.jar
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: app-config
|
||||||
|
env:
|
||||||
|
- name: JAVA_OPTS
|
||||||
|
value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
|
||||||
|
-Djava.security.egd=file:/dev/./urandom
|
||||||
|
imagePullPolicy: Always
|
||||||
|
minReadySeconds: 25
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# Copyright 2019 The Kubernetes Authors.
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: app
|
||||||
|
labels:
|
||||||
|
app: java
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: java
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: java
|
||||||
|
spec:
|
||||||
|
restartPolicy: Always
|
||||||
|
containers:
|
||||||
|
- name: app
|
||||||
|
image: gcr.io/project/app:version
|
||||||
|
command:
|
||||||
|
- java
|
||||||
|
- -jar
|
||||||
|
- /app.jar
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: app-config
|
||||||
|
env:
|
||||||
|
- name: JAVA_OPTS
|
||||||
|
value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
|
||||||
|
-Djava.security.egd=file:/dev/./urandom
|
||||||
|
imagePullPolicy: Always
|
||||||
|
minReadySeconds: 15
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# Copyright 2019 The Kubernetes Authors.
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: app
|
||||||
|
labels:
|
||||||
|
app: java
|
||||||
|
spec:
|
||||||
|
replicas: 4
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: java
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: java
|
||||||
|
spec:
|
||||||
|
restartPolicy: Always
|
||||||
|
containers:
|
||||||
|
- name: app
|
||||||
|
image: gcr.io/project/app:version
|
||||||
|
command:
|
||||||
|
- java
|
||||||
|
- -jar
|
||||||
|
- /app.jar
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: app-config
|
||||||
|
env:
|
||||||
|
- name: JAVA_OPTS
|
||||||
|
value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
|
||||||
|
-Djava.security.egd=file:/dev/./urandom
|
||||||
|
imagePullPolicy: Always
|
||||||
|
minReadySeconds: 25
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# Copyright 2019 The Kubernetes Authors.
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: app
|
||||||
|
labels:
|
||||||
|
app: java
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: java2
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: java2
|
||||||
|
spec:
|
||||||
|
restartPolicy: Always
|
||||||
|
containers:
|
||||||
|
- name: app
|
||||||
|
image: gcr.io/project/app:version
|
||||||
|
command:
|
||||||
|
- java
|
||||||
|
- -jar
|
||||||
|
- /app.jar
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: app-config
|
||||||
|
env:
|
||||||
|
- name: JAVA_OPTS
|
||||||
|
value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
|
||||||
|
-Djava.security.egd=file:/dev/./urandom
|
||||||
|
imagePullPolicy: Always
|
||||||
|
minReadySeconds: 5
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# Copyright 2019 The Kubernetes Authors.
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: app
|
||||||
|
labels:
|
||||||
|
app: java3
|
||||||
|
spec:
|
||||||
|
replicas: 4
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: java
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: java
|
||||||
|
spec:
|
||||||
|
restartPolicy: Always
|
||||||
|
containers:
|
||||||
|
- name: app
|
||||||
|
image: gcr.io/project/app:version
|
||||||
|
command:
|
||||||
|
- java
|
||||||
|
- -jar
|
||||||
|
- /app.jar
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: app-config
|
||||||
|
env:
|
||||||
|
- name: JAVA_OPTS
|
||||||
|
value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
|
||||||
|
-Djava.security.egd=file:/dev/./urandom
|
||||||
|
imagePullPolicy: Always
|
||||||
|
minReadySeconds: 10
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# Copyright 2019 The Kubernetes Authors.
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: app
|
||||||
|
labels:
|
||||||
|
app: java
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: java
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: java
|
||||||
|
spec:
|
||||||
|
restartPolicy: Always
|
||||||
|
containers:
|
||||||
|
- name: app
|
||||||
|
image: gcr.io/project/app:version
|
||||||
|
command:
|
||||||
|
- java
|
||||||
|
- -jar
|
||||||
|
- /app.jar
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: app-config
|
||||||
|
env:
|
||||||
|
- name: JAVA_OPTS
|
||||||
|
value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
|
||||||
|
-Djava.security.egd=file:/dev/./urandom
|
||||||
|
imagePullPolicy: Always
|
||||||
|
minReadySeconds: 5
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# Copyright 2019 The Kubernetes Authors.
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: app
|
||||||
|
labels:
|
||||||
|
app: java
|
||||||
|
spec:
|
||||||
|
replicas: 4
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: java
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: java
|
||||||
|
spec:
|
||||||
|
restartPolicy: Always
|
||||||
|
containers:
|
||||||
|
- name: app
|
||||||
|
image: gcr.io/project/app:version
|
||||||
|
command:
|
||||||
|
- java
|
||||||
|
- -jar
|
||||||
|
- /app.jar
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: app-config
|
||||||
|
env:
|
||||||
|
- name: JAVA_OPTS
|
||||||
|
value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
|
||||||
|
-Djava.security.egd=file:/dev/./urandom
|
||||||
|
imagePullPolicy: Always
|
||||||
|
minReadySeconds: 10
|
||||||
Reference in New Issue
Block a user