diff --git a/cmd/config/ext/ext.go b/cmd/config/ext/ext.go index d9d64f2c1..4ebbea5f9 100644 --- a/cmd/config/ext/ext.go +++ b/cmd/config/ext/ext.go @@ -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 } diff --git a/cmd/config/internal/commands/cmdlistsetters.go b/cmd/config/internal/commands/cmdlistsetters.go index d5fc93610..273d9c671 100644 --- a/cmd/config/internal/commands/cmdlistsetters.go +++ b/cmd/config/internal/commands/cmdlistsetters.go @@ -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 } diff --git a/cmd/config/internal/commands/cmdset.go b/cmd/config/internal/commands/cmdset.go index 6886d16ed..b0c364bef 100644 --- a/cmd/config/internal/commands/cmdset.go +++ b/cmd/config/internal/commands/cmdset.go @@ -159,6 +159,7 @@ func lookup(l setters.LookupSetters, c *cobra.Command, args []string) error { } table.Render() + fmt.Println(l.SetterCounts) if len(l.SetterCounts) == 0 { // exit non-0 if no matching setters are found os.Exit(1) diff --git a/cmd/config/internal/commands/e2e/create_setter_test.go b/cmd/config/internal/commands/e2e/create_setter_test.go new file mode 100644 index 000000000..294022f1e --- /dev/null +++ b/cmd/config/internal/commands/e2e/create_setter_test.go @@ -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) +} diff --git a/cmd/config/internal/commands/e2e/e2e_test.go b/cmd/config/internal/commands/e2e/e2e_test.go index 6ac3d7c5a..6fa2ce32f 100644 --- a/cmd/config/internal/commands/e2e/e2e_test.go +++ b/cmd/config/internal/commands/e2e/e2e_test.go @@ -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 ( diff --git a/cmd/config/internal/commands/e2e/list_setters_test.go b/cmd/config/internal/commands/e2e/list_setters_test.go new file mode 100644 index 000000000..1358eacd3 --- /dev/null +++ b/cmd/config/internal/commands/e2e/list_setters_test.go @@ -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) +} diff --git a/cmd/config/internal/commands/e2e/set_test.go b/cmd/config/internal/commands/e2e/set_test.go new file mode 100644 index 000000000..1d751ee07 --- /dev/null +++ b/cmd/config/internal/commands/e2e/set_test.go @@ -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) +} diff --git a/cmd/config/internal/commands/e2e/test_util_test.go b/cmd/config/internal/commands/e2e/test_util_test.go new file mode 100644 index 000000000..6835c4a0c --- /dev/null +++ b/cmd/config/internal/commands/e2e/test_util_test.go @@ -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() + } + } + }) + } +} diff --git a/kyaml/krmfile/doc.go b/kyaml/krmfile/doc.go new file mode 100644 index 000000000..1c87e0b06 --- /dev/null +++ b/kyaml/krmfile/doc.go @@ -0,0 +1,19 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +// Package krmfile provides functionality for working with Krmfiles. +// +// Example Krmfile +// +// apiVersion: config.k8s.io/v1alpha1 +// kind: Krmfile +// openAPI: +// definitions: +// io.k8s.cli.setters.replicas: +// x-k8s-cli: +// setter: +// name: replicas +// value: "3" +// setBy: me +// description: "hello world" +package krmfile diff --git a/kyaml/krmfile/krmfile.go b/kyaml/krmfile/krmfile.go new file mode 100644 index 000000000..dbf5a9999 --- /dev/null +++ b/kyaml/krmfile/krmfile.go @@ -0,0 +1,10 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package krmfile + +// KRMFileName is the file where Krm metadata is stored +const ( + // KrmfileName is the name of the file that KRM metadata is written to + KrmfileName = "Krmfile" +)