Merge pull request #2552 from pwittrock/krm

Write setter definitions to `Krmfile` instead of `kustomization`
This commit is contained in:
Kubernetes Prow Robot
2020-06-05 10:01:46 -07:00
committed by GitHub
15 changed files with 544 additions and 42 deletions

View File

@@ -105,6 +105,7 @@ func NewConfigCommand(name string) *cobra.Command {
root.AddCommand(commands.XArgsCommand())
root.AddCommand(commands.WrapCommand())
root.AddCommand(commands.InitCommand(name))
root.AddCommand(commands.SetCommand(name))
root.AddCommand(commands.ListSettersCommand(name))
root.AddCommand(commands.CreateSetterCommand(name))

View File

@@ -0,0 +1,18 @@
## init
[Alpha] Initialize a directory with a Krmfile.
### Synopsis
[Alpha] Initialize a directory with a Krmfile.
DIR:
Path to local directory.
### Examples
# create a Krmfile in the local directory
kustomize config init
# create a Krmfile in my-dir/
kustomize config init my-dir/

View File

@@ -3,10 +3,14 @@
package ext
import "path/filepath"
import (
"path/filepath"
"sigs.k8s.io/kustomize/kyaml/krmfile"
)
// GetOpenAPIFile returns the path to the file containing supplementary OpenAPI definitions.
// Maybe be overridden to configure which file to read OpenAPI definitions from.
var GetOpenAPIFile = func(args []string) (string, error) {
return filepath.Join(args[0], "kustomization"), nil
return filepath.Join(args[0], krmfile.KrmfileName), nil
}

View File

@@ -0,0 +1,60 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package commands
import (
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/krmfile"
)
// GetInitRunner returns a command InitRunner.
func GetInitRunner(name string) *InitRunner {
r := &InitRunner{}
c := &cobra.Command{
Use: "init DIR...",
Args: cobra.RangeArgs(0, 1),
Short: commands.InitShort,
Long: commands.InitLong,
Example: commands.InitExamples,
RunE: r.runE,
}
fixDocs(name, c)
r.Command = c
return r
}
func InitCommand(name string) *cobra.Command {
return GetInitRunner(name).Command
}
// InitRunner contains the init function
type InitRunner struct {
Command *cobra.Command
}
func (r *InitRunner) runE(c *cobra.Command, args []string) error {
var dir string
if len(args) == 0 {
dir = "."
} else {
dir = args[0]
}
filename := filepath.Join(dir, krmfile.KrmfileName)
if _, err := os.Stat(filename); err == nil || !os.IsNotExist(err) {
return errors.Errorf("directory already initialized with a Krmfile")
}
return ioutil.WriteFile(filename, []byte(strings.TrimSpace(`
apiVersion: config.k8s.io/v1alpha1
kind: Krmfile
`)), 0600)
}

View File

@@ -126,13 +126,9 @@ func (r *ListSettersRunner) ListSubstitutions(c *cobra.Command, args []string) e
s.Name, s.Pattern, setters})
}
if len(r.List.Substitutions) == 0 {
// exit non-0 if no matching substitutions are found
if ExitOnError {
os.Exit(1)
}
} else {
table.Render()
return nil
}
table.Render()
return nil
}

View File

@@ -0,0 +1,57 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package e2e
import (
"testing"
)
func TestCreateSetter(t *testing.T) {
tests := []test{
{
name: "create_setter",
args: []string{"create-setter", ".", "replicas", "3"},
files: map[string]string{
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
`,
"Krmfile": `
apiVersion: config.k8s.io/v1alpha1
kind: Krmfile
`,
},
expectedFiles: map[string]string{
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3 # {"$openapi":"replicas"}
`,
"Krmfile": `
apiVersion: config.k8s.io/v1alpha1
kind: Krmfile
openAPI:
definitions:
io.k8s.cli.setters.replicas:
x-k8s-cli:
setter:
name: replicas
value: "3"
`,
},
},
}
runTests(t, tests)
}

View File

@@ -12,6 +12,7 @@ import (
"path/filepath"
"runtime"
"strings"
"sync"
"testing"
"github.com/stretchr/testify/assert"
@@ -19,12 +20,7 @@ import (
)
func TestRunE2e(t *testing.T) {
binDir, err := ioutil.TempDir("", "kustomize-test-")
if !assert.NoError(t, err) {
t.FailNow()
}
defer os.RemoveAll(binDir)
build(t, binDir)
binDir := build()
tests := []struct {
name string
@@ -661,6 +657,7 @@ metadata:
},
}
// TODO: dedup this with the shared version
for i := range tests {
tt := tests[i]
t.Run(tt.name, func(t *testing.T) {
@@ -710,36 +707,54 @@ metadata:
}
}
func build(t *testing.T, binDir string) {
build := exec.Command("go", "build", "-o",
filepath.Join(binDir, e2econtainerconfigBin))
build.Dir = "e2econtainerconfig"
build.Stdout = os.Stdout
build.Stderr = os.Stderr
build.Env = os.Environ()
if !assert.NoError(t, build.Run()) {
t.FailNow()
}
var buildOnce sync.Once
var binDir string
build = exec.Command("go", "build", "-o", filepath.Join(binDir, kyamlBin))
build.Dir = filepath.Join("..", "..", "..")
build.Stdout = os.Stdout
build.Stderr = os.Stderr
if !assert.NoError(t, build.Run()) {
t.FailNow()
}
func build() string {
// only build the binaries once
buildOnce.Do(func() {
var err error
binDir, err = ioutil.TempDir("", "kustomize-test-")
if err != nil {
panic(err)
}
if os.Getenv("KUSTOMIZE_DOCKER_E2E") == "false" {
return
}
build = exec.Command(
"docker", "build", ".", "-t", "gcr.io/kustomize-functions/e2econtainerconfig")
build.Dir = "e2econtainerconfig"
build.Stdout = os.Stdout
build.Stderr = os.Stderr
if !assert.NoError(t, build.Run()) {
t.FailNow()
}
build := exec.Command("go", "build", "-o",
filepath.Join(binDir, e2econtainerconfigBin))
build.Dir = "e2econtainerconfig"
build.Stdout = os.Stdout
build.Stderr = os.Stderr
build.Env = os.Environ()
err = build.Run()
if err != nil {
panic(err)
}
build = exec.Command("go", "build", "-o", filepath.Join(binDir, kyamlBin))
build.Dir = filepath.Join("..", "..", "..")
build.Stdout = os.Stdout
build.Stderr = os.Stderr
err = build.Run()
if err != nil {
panic(err)
}
if os.Getenv("KUSTOMIZE_DOCKER_E2E") == "false" {
return
}
build = exec.Command(
"docker", "build", ".", "-t", "gcr.io/kustomize-functions/e2econtainerconfig")
build.Dir = "e2econtainerconfig"
build.Stdout = os.Stdout
build.Stderr = os.Stderr
err = build.Run()
if err != nil {
panic(err)
}
})
return binDir
}
var (

View File

@@ -0,0 +1,33 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package e2e
import "testing"
func TestInit(t *testing.T) {
tests := []test{
{
name: "init",
args: []string{"init"},
expectedFiles: map[string]string{
"Krmfile": `
apiVersion: config.k8s.io/v1alpha1
kind: Krmfile
`,
},
},
{
name: "init",
args: []string{"init", "."},
expectedFiles: map[string]string{
"Krmfile": `
apiVersion: config.k8s.io/v1alpha1
kind: Krmfile
`,
},
},
}
runTests(t, tests)
}

View File

@@ -0,0 +1,43 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package e2e
import "testing"
func TestListSetters(t *testing.T) {
tests := []test{
{
name: "set",
args: []string{"list-setters", "."},
files: map[string]string{
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3 # {"$openapi":"replicas"}
`,
"Krmfile": `
apiVersion: config.k8s.io/v1alpha1
kind: Krmfile
openAPI:
definitions:
io.k8s.cli.setters.replicas:
x-k8s-cli:
setter:
name: replicas
value: "3"
`,
},
expectedStdOut: `
NAME VALUE SET BY DESCRIPTION COUNT
replicas 3 1
`,
},
}
runTests(t, tests)
}

View File

@@ -0,0 +1,62 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package e2e
import "testing"
func TestSet(t *testing.T) {
tests := []test{
{
name: "set",
args: []string{"set", ".", "replicas", "4"},
files: map[string]string{
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3 # {"$openapi":"replicas"}
`,
"Krmfile": `
apiVersion: config.k8s.io/v1alpha1
kind: Krmfile
openAPI:
definitions:
io.k8s.cli.setters.replicas:
x-k8s-cli:
setter:
name: replicas
value: "3"
`,
},
expectedFiles: map[string]string{
"deployment.yaml": `
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 4 # {"$openapi":"replicas"}
`,
"Krmfile": `
apiVersion: config.k8s.io/v1alpha1
kind: Krmfile
openAPI:
definitions:
io.k8s.cli.setters.replicas:
x-k8s-cli:
setter:
name: replicas
value: "4"
`,
},
},
}
runTests(t, tests)
}

View File

@@ -0,0 +1,86 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package e2e
import (
"bytes"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/kyaml/testutil"
)
func TestMain(m *testing.M) {
d := build()
defer os.RemoveAll(d)
os.Exit(m.Run())
}
type test struct {
name string
args []string
files map[string]string
expectedFiles map[string]string
expectedErr string
expectedStdOut string
}
func runTests(t *testing.T, tests []test) {
dir := build()
bin := filepath.Join(dir, kyamlBin)
for i := range tests {
tt := tests[i]
t.Run(tt.name, func(t *testing.T) {
dataDir, err := ioutil.TempDir("", "kustomize-test-data-")
if !assert.NoError(t, err) {
t.FailNow()
}
defer os.RemoveAll(dataDir)
os.Chdir(dataDir)
// write the input
for path, data := range tt.files {
err := ioutil.WriteFile(path, []byte(data), 0600)
testutil.AssertNoError(t, err)
}
cmd := exec.Command(bin, tt.args...)
cmd.Dir = dataDir
var stdErr, stdOut bytes.Buffer
cmd.Stdout = &stdOut
cmd.Stderr = &stdErr
cmd.Env = os.Environ()
err = cmd.Run()
if tt.expectedErr != "" {
if !assert.Contains(t, stdErr.String(), tt.expectedErr, stdErr.String()) {
t.FailNow()
}
return
}
testutil.AssertNoError(t, err, stdErr.String(), stdOut.String())
if tt.expectedStdOut != "" {
if !assert.Equal(t, strings.TrimSpace(stdOut.String()), strings.TrimSpace(tt.expectedStdOut)) {
t.FailNow()
}
}
for path, data := range tt.expectedFiles {
b, err := ioutil.ReadFile(path)
testutil.AssertNoError(t, err, stdErr.String())
if !assert.Equal(t, strings.TrimSpace(data), strings.TrimSpace(string(b)), stdErr.String()) {
t.FailNow()
}
}
})
}
}

View File

@@ -0,0 +1,84 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package commands_test
import (
"bytes"
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/cmd/config/internal/commands"
)
func TestInit_args(t *testing.T) {
d, err := ioutil.TempDir("", "kustomize-cat-test")
if !assert.NoError(t, err) {
return
}
defer os.RemoveAll(d)
// fmt the files
b := &bytes.Buffer{}
r := commands.GetInitRunner("")
r.Command.SetArgs([]string{d})
r.Command.SetOut(b)
if !assert.NoError(t, r.Command.Execute()) {
t.FailNow()
}
actual, err := ioutil.ReadFile(filepath.Join(d, "Krmfile"))
if !assert.NoError(t, err) {
t.FailNow()
}
if !assert.Equal(t, strings.TrimSpace(`
apiVersion: config.k8s.io/v1alpha1
kind: Krmfile
`), strings.TrimSpace(string(actual))) {
t.FailNow()
}
if !assert.Equal(t, "", b.String()) {
t.FailNow()
}
}
func TestInit_noargs(t *testing.T) {
d, err := ioutil.TempDir("", "kustomize-test-")
if !assert.NoError(t, err) {
return
}
defer os.RemoveAll(d)
if !assert.NoError(t, os.Chdir(d)) {
t.FailNow()
}
b := &bytes.Buffer{}
r := commands.GetInitRunner("")
r.Command.SetOut(b)
if !assert.NoError(t, r.Command.Execute()) {
t.FailNow()
}
actual, err := ioutil.ReadFile(filepath.Join(d, "Krmfile"))
if !assert.NoError(t, err) {
t.FailNow()
}
if !assert.Equal(t, strings.TrimSpace(`
apiVersion: config.k8s.io/v1alpha1
kind: Krmfile
`), strings.TrimSpace(string(actual))) {
t.FailNow()
}
if !assert.Equal(t, "", b.String()) {
t.FailNow()
}
}

View File

@@ -156,6 +156,20 @@ var GrepExamples = `
# look for Resources matching a specific container image
kustomize config grep "spec.template.spec.containers[name=nginx].image=nginx:1\.7\.9" my-dir/ | kustomize config tree`
var InitShort = `[Alpha] Initialize a directory with a Krmfile.`
var InitLong = `
[Alpha] Initialize a directory with a Krmfile.
DIR:
Path to local directory.
`
var InitExamples = `
# create a Krmfile in the local directory
kustomize config init
# create a Krmfile in my-dir/
kustomize config init my-dir/`
var ListSettersShort = `[Alpha] List setters for Resources.`
var ListSettersLong = `
List setters for Resources.