diff --git a/cmd/config/internal/commands/cmdlistsetters.go b/cmd/config/internal/commands/cmdlistsetters.go index 5cf5afea6..c4a8e29b5 100644 --- a/cmd/config/internal/commands/cmdlistsetters.go +++ b/cmd/config/internal/commands/cmdlistsetters.go @@ -4,9 +4,15 @@ package commands import ( + "fmt" + "io" + "os" + + "github.com/olekukonko/tablewriter" "github.com/spf13/cobra" "sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands" "sigs.k8s.io/kustomize/kyaml/setters" + "sigs.k8s.io/kustomize/kyaml/setters2" ) // NewListSettersRunner returns a command runner. @@ -33,15 +39,57 @@ func ListSettersCommand(parent string) *cobra.Command { type ListSettersRunner struct { Command *cobra.Command Lookup setters.LookupSetters + List setters2.List } func (r *ListSettersRunner) preRunE(c *cobra.Command, args []string) error { if len(args) > 1 { r.Lookup.Name = args[1] + r.List.Name = args[1] } + + initSetterVersion(c, args) return nil } func (r *ListSettersRunner) runE(c *cobra.Command, args []string) error { + if setterVersion == "v2" { + // use setters v2 + path, err := GetOpenAPIFile(args) + if err != nil { + return err + } + if err := r.List.List(path, args[0]); err != nil { + return err + } + table := newTable(c.OutOrStdout()) + table.SetHeader([]string{"NAME", "VALUE", "SET BY", "DESCRIPTION", "COUNT"}) + for i := range r.List.Setters { + s := r.List.Setters[i] + table.Append([]string{ + s.Name, s.Value, s.SetBy, s.Description, fmt.Sprintf("%d", s.Count)}) + } + table.Render() + + if len(r.List.Setters) == 0 { + // exit non-0 if no matching setters are found + if ExitOnError { + os.Exit(1) + } + } + return nil + } + return handleError(c, lookup(r.Lookup, c, args)) } + +func newTable(o io.Writer) *tablewriter.Table { + table := tablewriter.NewWriter(o) + table.SetRowLine(false) + table.SetBorder(false) + table.SetHeaderLine(false) + table.SetColumnSeparator(" ") + table.SetCenterSeparator(" ") + table.SetAlignment(tablewriter.ALIGN_LEFT) + return table +} diff --git a/cmd/config/internal/commands/cmdlistsetters_test.go b/cmd/config/internal/commands/cmdlistsetters_test.go new file mode 100644 index 000000000..017ba6ce7 --- /dev/null +++ b/cmd/config/internal/commands/cmdlistsetters_test.go @@ -0,0 +1,296 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package commands_test + +import ( + "bytes" + "io/ioutil" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "sigs.k8s.io/kustomize/cmd/config/internal/commands" + "sigs.k8s.io/kustomize/kyaml/openapi" +) + +func TestListSettersCommand(t *testing.T) { + var tests = []struct { + name string + openapi string + input string + args []string + expected string + }{ + { + name: "list-replicas", + openapi: ` +openAPI: + definitions: + io.k8s.cli.setters.replicas: + x-k8s-cli: + setter: + name: replicas + value: "3" + setBy: me + description: "hello world" + `, + input: ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + replicas: 3 # {"$ref": "#/definitions/io.k8s.cli.setters.replicas"} + `, + expected: ` NAME VALUE SET BY DESCRIPTION COUNT + replicas 3 me hello world 1 +`, + }, + { + name: "list-multiple", + openapi: ` +openAPI: + definitions: + io.k8s.cli.setters.replicas: + description: "hello world 1" + x-k8s-cli: + setter: + name: replicas + value: "3" + setBy: me1 + io.k8s.cli.setters.image: + description: "hello world 2" + x-k8s-cli: + setter: + name: image + value: "nginx" + setBy: me2 + io.k8s.cli.setters.tag: + description: "hello world 3" + x-k8s-cli: + setter: + name: tag + value: "1.7.9" + setBy: me3 + io.k8s.cli.substitutions.image: + x-k8s-cli: + substitution: + name: image + pattern: IMAGE:TAG + values: + - marker: IMAGE + ref: '#/definitions/io.k8s.cli.setters.image' + - marker: TAG + ref: '#/definitions/io.k8s.cli.setters.tag' + `, + input: ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + replicas: 3 # {"$ref": "#/definitions/io.k8s.cli.setters.replicas"} + template: + spec: + containers: + - name: nginx + image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"} + - name: nginx2 + image: nginx # {"$ref": "#/definitions/io.k8s.cli.setters.image"} + `, + expected: ` NAME VALUE SET BY DESCRIPTION COUNT + image nginx me2 hello world 2 2 + replicas 3 me1 hello world 1 1 + tag 1.7.9 me3 hello world 3 1 +`, + }, + { + name: "list-multiple-resources", + openapi: ` +openAPI: + definitions: + io.k8s.cli.setters.replicas: + description: "hello world 1" + x-k8s-cli: + setter: + name: replicas + value: "3" + setBy: me1 + io.k8s.cli.setters.image: + description: "hello world 2" + x-k8s-cli: + setter: + name: image + value: "nginx" + setBy: me2 + io.k8s.cli.setters.tag: + description: "hello world 3" + x-k8s-cli: + setter: + name: tag + value: "1.7.9" + setBy: me3 + io.k8s.cli.substitutions.image: + x-k8s-cli: + substitution: + name: image + pattern: IMAGE:TAG + values: + - marker: IMAGE + ref: '#/definitions/io.k8s.cli.setters.image' + - marker: TAG + ref: '#/definitions/io.k8s.cli.setters.tag' + `, + input: ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment-1 +spec: + replicas: 3 # {"$ref": "#/definitions/io.k8s.cli.setters.replicas"} + template: + spec: + containers: + - name: nginx + image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"} + - name: nginx2 + image: nginx # {"$ref": "#/definitions/io.k8s.cli.setters.image"} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment-2 +spec: + replicas: 3 # {"$ref": "#/definitions/io.k8s.cli.setters.replicas"} + template: + spec: + containers: + - name: nginx + image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"} + - name: nginx2 + image: nginx +`, + expected: ` NAME VALUE SET BY DESCRIPTION COUNT + image nginx me2 hello world 2 3 + replicas 3 me1 hello world 1 2 + tag 1.7.9 me3 hello world 3 2 +`, + }, + { + name: "list-name", + args: []string{"image"}, + openapi: ` +openAPI: + definitions: + io.k8s.cli.setters.replicas: + description: "hello world 1" + x-k8s-cli: + setter: + name: replicas + value: "3" + setBy: me1 + io.k8s.cli.setters.image: + description: "hello world 2" + x-k8s-cli: + setter: + name: image + value: "nginx" + setBy: me2 + io.k8s.cli.setters.tag: + description: "hello world 3" + x-k8s-cli: + setter: + name: tag + value: "1.7.9" + setBy: me3 + io.k8s.cli.substitutions.image: + x-k8s-cli: + substitution: + name: image + pattern: IMAGE:TAG + values: + - marker: IMAGE + ref: '#/definitions/io.k8s.cli.setters.image' + - marker: TAG + ref: '#/definitions/io.k8s.cli.setters.tag' + `, + input: ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment-1 +spec: + replicas: 3 # {"$ref": "#/definitions/io.k8s.cli.setters.replicas"} + template: + spec: + containers: + - name: nginx + image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"} + - name: nginx2 + image: nginx # {"$ref": "#/definitions/io.k8s.cli.setters.image"} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment-2 +spec: + replicas: 3 # {"$ref": "#/definitions/io.k8s.cli.setters.replicas"} + template: + spec: + containers: + - name: nginx + image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"} + - name: nginx2 + image: nginx +`, + expected: ` NAME VALUE SET BY DESCRIPTION COUNT + image nginx me2 hello world 2 3 +`, + }, + } + for i := range tests { + test := tests[i] + t.Run(test.name, func(t *testing.T) { + // reset the openAPI afterward + openapi.ResetOpenAPI() + defer openapi.ResetOpenAPI() + + f, err := ioutil.TempFile("", "k8s-cli-") + if !assert.NoError(t, err) { + t.FailNow() + } + defer os.Remove(f.Name()) + commands.GetOpenAPIFile = func(args []string) (s string, err error) { + err = ioutil.WriteFile(f.Name(), []byte(test.openapi), 0600) + if !assert.NoError(t, err) { + t.FailNow() + } + return f.Name(), nil + } + + r, err := ioutil.TempFile("", "k8s-cli-*.yaml") + if !assert.NoError(t, err) { + t.FailNow() + } + defer os.Remove(r.Name()) + err = ioutil.WriteFile(r.Name(), []byte(test.input), 0600) + if !assert.NoError(t, err) { + t.FailNow() + } + + runner := commands.NewListSettersRunner("") + actual := &bytes.Buffer{} + runner.Command.SetOut(actual) + runner.Command.SetArgs(append([]string{r.Name()}, test.args...)) + err = runner.Command.Execute() + if !assert.NoError(t, err) { + t.FailNow() + } + + if !assert.Equal(t, test.expected, actual.String()) { + t.FailNow() + } + }) + } +}