mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-11 17:12:51 +00:00
Rebase merge3 branch into master
This commit is contained in:
@@ -74,6 +74,7 @@ func NewConfigCommand(name string) *cobra.Command {
|
|||||||
root.AddCommand(commands.CatCommand(name))
|
root.AddCommand(commands.CatCommand(name))
|
||||||
root.AddCommand(commands.FmtCommand(name))
|
root.AddCommand(commands.FmtCommand(name))
|
||||||
root.AddCommand(commands.MergeCommand(name))
|
root.AddCommand(commands.MergeCommand(name))
|
||||||
|
root.AddCommand(commands.Merge3Command(name))
|
||||||
root.AddCommand(commands.CountCommand(name))
|
root.AddCommand(commands.CountCommand(name))
|
||||||
root.AddCommand(commands.RunFnCommand(name))
|
root.AddCommand(commands.RunFnCommand(name))
|
||||||
root.AddCommand(commands.SubCommand(name))
|
root.AddCommand(commands.SubCommand(name))
|
||||||
|
|||||||
25
cmd/config/docs/commands/merge3.md
Normal file
25
cmd/config/docs/commands/merge3.md
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
## merge3
|
||||||
|
|
||||||
|
[Alpha] Merge Resource configuration files (3-way)
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
[Alpha] Merge Resource configuration files (3-way)
|
||||||
|
|
||||||
|
Merge (3-way) reads Kubernetes Resource yaml configuration files from source packages and updated
|
||||||
|
packages then writes the result to stdout and a destination package.
|
||||||
|
|
||||||
|
Resources are merged using the Resource [apiVersion, kind, name, namespace] as the key. If any of
|
||||||
|
these are missing, merge will default the missing values to empty.
|
||||||
|
|
||||||
|
Resources specified in the updated packages have higher-precedence and Resources specified
|
||||||
|
in the original packages have lower-precedence. Resources specified in the destination
|
||||||
|
packages either keep, clear, or recursively merge their values.
|
||||||
|
|
||||||
|
For information on merge rules, run:
|
||||||
|
|
||||||
|
kustomize config docs merge3
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
kustomize config merge3 --ancestor a/ --from b/ --to c/
|
||||||
56
cmd/config/internal/commands/merge3.go
Normal file
56
cmd/config/internal/commands/merge3.go
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"sigs.k8s.io/kustomize/cmd/config/cmddocs/commands"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/kio/filters"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetMerge3Runner(name string) *Merge3Runner {
|
||||||
|
r := &Merge3Runner{}
|
||||||
|
c := &cobra.Command{
|
||||||
|
Use: "merge3 --ancestor [ORIGINAL_DIR] --from [UPDATED_DIR] --to [DESTINATION_DIR]",
|
||||||
|
Short: commands.Merge3Short,
|
||||||
|
Long: commands.Merge3Long,
|
||||||
|
Example: commands.Merge3Examples,
|
||||||
|
RunE: r.runE,
|
||||||
|
}
|
||||||
|
fixDocs(name, c)
|
||||||
|
//r.Command = c
|
||||||
|
c.Flags().StringVar(&r.ancestor, "ancestor", "",
|
||||||
|
"Path to original package")
|
||||||
|
c.Flags().StringVar(&r.fromDir, "from", "",
|
||||||
|
"Path to updated package")
|
||||||
|
c.Flags().StringVar(&r.toDir, "to", "",
|
||||||
|
"Path to destination package")
|
||||||
|
|
||||||
|
r.Command = c
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func Merge3Command(name string) *cobra.Command {
|
||||||
|
return GetMerge3Runner(name).Command
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge3Runner contains the run function
|
||||||
|
type Merge3Runner struct {
|
||||||
|
Command *cobra.Command
|
||||||
|
ancestor string
|
||||||
|
fromDir string
|
||||||
|
toDir string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Merge3Runner) runE(c *cobra.Command, args []string) error {
|
||||||
|
err := filters.Merge3{
|
||||||
|
OriginalPath: r.ancestor,
|
||||||
|
UpdatedPath: r.fromDir,
|
||||||
|
DestPath: r.toDir,
|
||||||
|
}.Merge()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
236
cmd/config/internal/commands/merge3_test.go
Normal file
236
cmd/config/internal/commands/merge3_test.go
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
// Copyright 2019 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"sigs.k8s.io/kustomize/cmd/config/internal/commands"
|
||||||
|
"sigs.k8s.io/kustomize/kyaml/copyutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestMerge3Command verifies the merge3 correctly applies the diff between 2 sets of resources into another
|
||||||
|
func TestMerge3Command(t *testing.T) {
|
||||||
|
datadir, err := ioutil.TempDir("", "test-data")
|
||||||
|
defer os.RemoveAll(datadir)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filepath.Join(datadir, "java-deployment.resource.yaml"), []byte(`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
|
||||||
|
`), 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
expected_dir, err := ioutil.TempDir("", "test-data-expected")
|
||||||
|
defer os.RemoveAll(expected_dir)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filepath.Join(expected_dir, "java-deployment.resource.yaml"), []byte(`apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: app
|
||||||
|
labels:
|
||||||
|
app: java
|
||||||
|
new-local: label
|
||||||
|
new-remote: label
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
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
|
||||||
|
- otherstuff
|
||||||
|
args:
|
||||||
|
- foo
|
||||||
|
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: 20
|
||||||
|
`), 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
updated_dir, err := ioutil.TempDir("", "test-data-updated")
|
||||||
|
defer os.RemoveAll(updated_dir)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filepath.Join(updated_dir, "java-deployment.resource.yaml"), []byte(`apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: app
|
||||||
|
labels:
|
||||||
|
app: java
|
||||||
|
new-remote: label
|
||||||
|
spec:
|
||||||
|
replicas: 3
|
||||||
|
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
|
||||||
|
- otherstuff
|
||||||
|
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
|
||||||
|
`), 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dest_dir, err := ioutil.TempDir("", "test-data-dest")
|
||||||
|
defer os.RemoveAll(dest_dir)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filepath.Join(dest_dir, "java-deployment.resource.yaml"), []byte(`apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: app
|
||||||
|
labels:
|
||||||
|
app: java
|
||||||
|
new-local: label
|
||||||
|
spec:
|
||||||
|
replicas: 2
|
||||||
|
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
|
||||||
|
args:
|
||||||
|
- foo
|
||||||
|
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: 20
|
||||||
|
`), 0600)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform merge3 with newly created sets
|
||||||
|
r := commands.GetMerge3Runner("")
|
||||||
|
r.Command.SetArgs([]string{
|
||||||
|
"--ancestor",
|
||||||
|
datadir,
|
||||||
|
"--from",
|
||||||
|
updated_dir,
|
||||||
|
"--to",
|
||||||
|
dest_dir,
|
||||||
|
})
|
||||||
|
if !assert.NoError(t, r.Command.Execute()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
diffs, err := copyutil.Diff(dest_dir, expected_dir)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify there are no diffs
|
||||||
|
if !assert.Empty(t, diffs.List()) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user