mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-10 16:42: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.FmtCommand(name))
|
||||
root.AddCommand(commands.MergeCommand(name))
|
||||
root.AddCommand(commands.Merge3Command(name))
|
||||
root.AddCommand(commands.CountCommand(name))
|
||||
root.AddCommand(commands.RunFnCommand(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