From 108195185fc575d2c44183689cb4e94cfe24873a Mon Sep 17 00:00:00 2001 From: Phani Teja Marupaka Date: Mon, 20 Jul 2020 00:50:04 -0700 Subject: [PATCH] List and set setters in folders recursively --- .../internal/commands/cmdlistsetters.go | 44 ++++++++++++------- .../internal/commands/cmdlistsetters_test.go | 30 +++++-------- cmd/config/internal/commands/cmdset.go | 39 ++++++++++++++-- cmd/config/internal/commands/cmdset_test.go | 30 +++++-------- .../commands/e2e/list_setters_test.go | 4 +- kyaml/pathutil/pathutil.go | 35 +++++++++++++++ kyaml/printutil/printutil.go | 23 ++++++++++ kyaml/setters2/set.go | 6 ++- kyaml/setters2/set_test.go | 2 +- 9 files changed, 153 insertions(+), 60 deletions(-) create mode 100644 kyaml/pathutil/pathutil.go create mode 100644 kyaml/printutil/printutil.go diff --git a/cmd/config/internal/commands/cmdlistsetters.go b/cmd/config/internal/commands/cmdlistsetters.go index 2d6b641f7..2d44de54c 100644 --- a/cmd/config/internal/commands/cmdlistsetters.go +++ b/cmd/config/internal/commands/cmdlistsetters.go @@ -13,7 +13,10 @@ import ( "github.com/spf13/cobra" "sigs.k8s.io/kustomize/cmd/config/ext" "sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands" + "sigs.k8s.io/kustomize/kyaml/errors" "sigs.k8s.io/kustomize/kyaml/fieldmeta" + "sigs.k8s.io/kustomize/kyaml/pathutil" + "sigs.k8s.io/kustomize/kyaml/printutil" "sigs.k8s.io/kustomize/kyaml/setters" "sigs.k8s.io/kustomize/kyaml/setters2" ) @@ -63,11 +66,28 @@ func (r *ListSettersRunner) preRunE(c *cobra.Command, args []string) error { func (r *ListSettersRunner) runE(c *cobra.Command, args []string) error { if setterVersion == "v2" { - if err := r.ListSetters(c, args); err != nil { + openAPIFileName, err := ext.GetOpenAPIFile([]string{"."}) + if err != nil { return err } - if r.IncludeSubst { - return r.ListSubstitutions(c, args) + openAPIPaths, err := pathutil.SubDirsWithFile(args[0], openAPIFileName) + if err != nil { + return err + } + if len(openAPIPaths) == 0 { + return errors.Errorf("unable to find %s in %s", openAPIFileName, args[0]) + } + for _, openAPIPath := range openAPIPaths { + resourcePath := strings.TrimSuffix(openAPIPath, openAPIFileName) + printutil.GreenPrintf(c.OutOrStdout(), "\nsetters in package: %s\n", resourcePath) + if err := r.ListSetters(c, openAPIPath, resourcePath); err != nil { + return err + } + if r.IncludeSubst { + if err := r.ListSubstitutions(c, openAPIPath); err != nil { + return err + } + } } return nil } @@ -75,13 +95,9 @@ func (r *ListSettersRunner) runE(c *cobra.Command, args []string) error { return handleError(c, lookup(r.Lookup, c, args)) } -func (r *ListSettersRunner) ListSetters(c *cobra.Command, args []string) error { +func (r *ListSettersRunner) ListSetters(c *cobra.Command, openAPIPath, resourcePath string) error { // use setters v2 - path, err := ext.GetOpenAPIFile(args) - if err != nil { - return err - } - if err := r.List.ListSetters(path, args[0]); err != nil { + if err := r.List.ListSetters(openAPIPath, resourcePath); err != nil { return err } table := newTable(c.OutOrStdout(), r.Markdown) @@ -112,16 +128,13 @@ func (r *ListSettersRunner) ListSetters(c *cobra.Command, args []string) error { os.Exit(1) } } + r.List.Setters = r.List.Setters[:0] return nil } -func (r *ListSettersRunner) ListSubstitutions(c *cobra.Command, args []string) error { +func (r *ListSettersRunner) ListSubstitutions(c *cobra.Command, openAPIPath string) error { // use setters v2 - path, err := ext.GetOpenAPIFile(args) - if err != nil { - return err - } - if err := r.List.ListSubst(path); err != nil { + if err := r.List.ListSubst(openAPIPath); err != nil { return err } table := newTable(c.OutOrStdout(), r.Markdown) @@ -147,6 +160,7 @@ func (r *ListSettersRunner) ListSubstitutions(c *cobra.Command, args []string) e return nil } table.Render() + r.List.Substitutions = r.List.Substitutions[:0] return nil } diff --git a/cmd/config/internal/commands/cmdlistsetters_test.go b/cmd/config/internal/commands/cmdlistsetters_test.go index 606550242..e3f02f3ce 100644 --- a/cmd/config/internal/commands/cmdlistsetters_test.go +++ b/cmd/config/internal/commands/cmdlistsetters_test.go @@ -7,11 +7,11 @@ import ( "bytes" "io/ioutil" "os" + "path/filepath" "strings" "testing" "github.com/stretchr/testify/assert" - "sigs.k8s.io/kustomize/cmd/config/ext" "sigs.k8s.io/kustomize/cmd/config/internal/commands" "sigs.k8s.io/kustomize/kyaml/openapi" ) @@ -408,27 +408,19 @@ openAPI: openapi.ResetOpenAPI() defer openapi.ResetOpenAPI() - f, err := ioutil.TempFile("", "k8s-cli-") + dir, err := ioutil.TempDir("", "") if !assert.NoError(t, err) { t.FailNow() } - defer os.Remove(f.Name()) - old := ext.GetOpenAPIFile - defer func() { ext.GetOpenAPIFile = old }() - ext.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") + defer os.RemoveAll(dir) + + err = ioutil.WriteFile(filepath.Join(dir, "Krmfile"), []byte(test.openapi), 0600) if !assert.NoError(t, err) { t.FailNow() } - defer os.Remove(r.Name()) - err = ioutil.WriteFile(r.Name(), []byte(test.input), 0600) + + err = ioutil.WriteFile(filepath.Join(dir, "deployment.yaml"), []byte(test.input), 0600) if !assert.NoError(t, err) { t.FailNow() } @@ -436,18 +428,18 @@ openAPI: runner := commands.NewListSettersRunner("") actual := &bytes.Buffer{} runner.Command.SetOut(actual) - runner.Command.SetArgs(append([]string{r.Name()}, test.args...)) + runner.Command.SetArgs(append([]string{dir}, test.args...)) err = runner.Command.Execute() if !assert.NoError(t, err) { t.FailNow() } - if !assert.Equal(t, test.expected, actual.String()) { + if !assert.Contains(t, actual.String(), test.expected) { t.FailNow() } // make sure that the resources are not altered - actualResources, err := ioutil.ReadFile(r.Name()) + actualResources, err := ioutil.ReadFile(filepath.Join(dir, "deployment.yaml")) if !assert.NoError(t, err) { t.FailNow() } @@ -457,7 +449,7 @@ openAPI: t.FailNow() } - actualOpenAPI, err := ioutil.ReadFile(f.Name()) + actualOpenAPI, err := ioutil.ReadFile(filepath.Join(dir, "Krmfile")) if !assert.NoError(t, err) { t.FailNow() } diff --git a/cmd/config/internal/commands/cmdset.go b/cmd/config/internal/commands/cmdset.go index 6d7143b7a..bb969d1c7 100644 --- a/cmd/config/internal/commands/cmdset.go +++ b/cmd/config/internal/commands/cmdset.go @@ -6,6 +6,7 @@ package commands import ( "fmt" "os" + "strings" "github.com/olekukonko/tablewriter" "github.com/spf13/cobra" @@ -13,7 +14,10 @@ import ( "sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands" "sigs.k8s.io/kustomize/kyaml/errors" "sigs.k8s.io/kustomize/kyaml/kio" + "sigs.k8s.io/kustomize/kyaml/pathutil" + "sigs.k8s.io/kustomize/kyaml/printutil" "sigs.k8s.io/kustomize/kyaml/setters" + "sigs.k8s.io/kustomize/kyaml/setters2" "sigs.k8s.io/kustomize/kyaml/setters2/settersutil" ) @@ -132,9 +136,27 @@ func (r *SetRunner) preRunE(c *cobra.Command, args []string) error { func (r *SetRunner) runE(c *cobra.Command, args []string) error { if setterVersion == "v2" { - count, err := r.Set.Set(r.OpenAPIFile, args[0]) - fmt.Fprintf(c.OutOrStdout(), "set %d fields\n", count) - return handleError(c, err) + openAPIFileName, err := ext.GetOpenAPIFile([]string{"."}) + if err != nil { + return err + } + openAPIPaths, err := pathutil.SubDirsWithFile(args[0], openAPIFileName) + if err != nil { + return err + } + if len(openAPIPaths) == 0 { + return errors.Errorf("unable to find %s in %s", openAPIFileName, args[0]) + } + for _, openAPIPath := range openAPIPaths { + resourcePath := strings.TrimSuffix(openAPIPath, openAPIFileName) + fmt.Fprintf(c.OutOrStdout(), "\nfinding %s setter in package %s\n", r.Set.Name, resourcePath) + count, err := r.Set.Set(openAPIPath, resourcePath) + if setErr := handleSetError(c, err); setErr != nil { + return setErr + } + fmt.Fprintf(c.OutOrStdout(), "set %d fields in package %s\n", count, resourcePath) + } + return nil } if len(args) > 2 || c.Flag("values").Changed { return handleError(c, r.perform(c, args)) @@ -142,6 +164,17 @@ func (r *SetRunner) runE(c *cobra.Command, args []string) error { return handleError(c, lookup(r.Lookup, c, args)) } +func handleSetError(c *cobra.Command, err error) error { + if err == nil { + return nil + } + if strings.Contains(err.Error(), setters2.SetterNotFoundWarn) { + printutil.WarnPrintf(c.OutOrStdout(), "%s\n", err.Error()) + return nil + } + return handleError(c, err) +} + func lookup(l setters.LookupSetters, c *cobra.Command, args []string) error { // lookup the setters err := kio.Pipeline{ diff --git a/cmd/config/internal/commands/cmdset_test.go b/cmd/config/internal/commands/cmdset_test.go index 78db9a8f0..d3c5824b2 100644 --- a/cmd/config/internal/commands/cmdset_test.go +++ b/cmd/config/internal/commands/cmdset_test.go @@ -7,11 +7,11 @@ import ( "bytes" "io/ioutil" "os" + "path/filepath" "strings" "testing" "github.com/stretchr/testify/assert" - "sigs.k8s.io/kustomize/cmd/config/ext" "sigs.k8s.io/kustomize/cmd/config/internal/commands" "sigs.k8s.io/kustomize/kyaml/openapi" ) @@ -949,27 +949,19 @@ spec: openapi.ResetOpenAPI() defer openapi.ResetOpenAPI() - f, err := ioutil.TempFile("", "k8s-cli-") + dir, err := ioutil.TempDir("", "") if !assert.NoError(t, err) { t.FailNow() } - defer os.Remove(f.Name()) - err = ioutil.WriteFile(f.Name(), []byte(test.inputOpenAPI), 0600) - if !assert.NoError(t, err) { - t.FailNow() - } - old := ext.GetOpenAPIFile - defer func() { ext.GetOpenAPIFile = old }() - ext.GetOpenAPIFile = func(args []string) (s string, err error) { - return f.Name(), nil - } - r, err := ioutil.TempFile("", "k8s-cli-*.yaml") + defer os.RemoveAll(dir) + + err = ioutil.WriteFile(filepath.Join(dir, "Krmfile"), []byte(test.inputOpenAPI), 0600) if !assert.NoError(t, err) { t.FailNow() } - defer os.Remove(r.Name()) - err = ioutil.WriteFile(r.Name(), []byte(test.input), 0600) + + err = ioutil.WriteFile(filepath.Join(dir, "deployment.yaml"), []byte(test.input), 0600) if !assert.NoError(t, err) { t.FailNow() } @@ -977,7 +969,7 @@ spec: runner := commands.NewSetRunner("") out := &bytes.Buffer{} runner.Command.SetOut(out) - runner.Command.SetArgs(append([]string{r.Name()}, test.args...)) + runner.Command.SetArgs(append([]string{dir}, test.args...)) err = runner.Command.Execute() if test.errMsg != "" { if !assert.NotNil(t, err) { @@ -992,11 +984,11 @@ spec: t.FailNow() } - if test.errMsg == "" && !assert.Equal(t, test.out, out.String()) { + if test.errMsg == "" && !assert.Contains(t, out.String(), strings.Trim(test.out, "\n")) { t.FailNow() } - actualResources, err := ioutil.ReadFile(r.Name()) + actualResources, err := ioutil.ReadFile(filepath.Join(dir, "deployment.yaml")) if !assert.NoError(t, err) { t.FailNow() } @@ -1006,7 +998,7 @@ spec: t.FailNow() } - actualOpenAPI, err := ioutil.ReadFile(f.Name()) + actualOpenAPI, err := ioutil.ReadFile(filepath.Join(dir, "Krmfile")) if !assert.NoError(t, err) { t.FailNow() } diff --git a/cmd/config/internal/commands/e2e/list_setters_test.go b/cmd/config/internal/commands/e2e/list_setters_test.go index 0b8cd541f..688daf240 100644 --- a/cmd/config/internal/commands/e2e/list_setters_test.go +++ b/cmd/config/internal/commands/e2e/list_setters_test.go @@ -34,7 +34,9 @@ openAPI: `, }, expectedStdOut: ` -NAME VALUE SET BY DESCRIPTION COUNT REQUIRED + +setters in package: [./] + NAME VALUE SET BY DESCRIPTION COUNT REQUIRED replicas 3 1 No `, }, diff --git a/kyaml/pathutil/pathutil.go b/kyaml/pathutil/pathutil.go new file mode 100644 index 000000000..f3f10f299 --- /dev/null +++ b/kyaml/pathutil/pathutil.go @@ -0,0 +1,35 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package pathutil + +import ( + "os" + "path/filepath" + "strings" + + "sigs.k8s.io/kustomize/kyaml/errors" +) + +// SubDirsWithFile takes the root directory path and returns all the paths of +// sub-directories which contain file with input fileName including itself +func SubDirsWithFile(root, fileName string) ([]string, error) { + var res []string + err := filepath.Walk(root, + func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if strings.HasSuffix(path, fileName) { + if root == "." { + path = root + "/" + path + } + res = append(res, path) + } + return nil + }) + if err != nil { + return res, errors.Wrap(err) + } + return res, nil +} diff --git a/kyaml/printutil/printutil.go b/kyaml/printutil/printutil.go new file mode 100644 index 000000000..5fcaae4e3 --- /dev/null +++ b/kyaml/printutil/printutil.go @@ -0,0 +1,23 @@ +// Copyright 2019 The Kubernetes Authors. +// SPDX-License-Identifier: Apache-2.0 + +package printutil + +import ( + "fmt" + "io" +) + +// GreenPrintf formats according to a format specifier and prints the resulting string +// in green color to the writer +func GreenPrintf(w io.Writer, format string, args ...string) { + msg := fmt.Sprintf(format, args) + fmt.Fprintf(w, "\033[1;32m%s\033[0m", msg) +} + +// WarnPrintf formats according to a format specifier and prints the resulting string +// in yellow color to the writer +func WarnPrintf(w io.Writer, format string, args ...string) { + msg := fmt.Sprintf(format, args) + fmt.Fprintf(w, "\033[1;33m%s\033[0m", msg) +} diff --git a/kyaml/setters2/set.go b/kyaml/setters2/set.go index cb5594e55..5db7a4cee 100644 --- a/kyaml/setters2/set.go +++ b/kyaml/setters2/set.go @@ -34,6 +34,8 @@ type Set struct { SetAll bool } +const SetterNotFoundWarn = "unable to find setter with name " + // Filter implements Set as a yaml.Filter func (s *Set) Filter(object *yaml.RNode) (*yaml.RNode, error) { return object, accept(s, object) @@ -328,14 +330,14 @@ func (s SetOpenAPI) Filter(object *yaml.RNode) (*yaml.RNode, error) { return nil, err } if oa == nil { - return nil, errors.Errorf("no setter %s found", s.Name) + return nil, errors.Errorf(SetterNotFoundWarn + s.Name) } def, err := oa.Pipe(yaml.Lookup("x-k8s-cli", "setter")) if err != nil { return nil, err } if def == nil { - return nil, errors.Errorf("no setter %s found", s.Name) + return nil, errors.Errorf(SetterNotFoundWarn + s.Name) } // record the OpenAPI type for the setter diff --git a/kyaml/setters2/set_test.go b/kyaml/setters2/set_test.go index 0352393e3..0e3dfd69d 100644 --- a/kyaml/setters2/set_test.go +++ b/kyaml/setters2/set_test.go @@ -1209,7 +1209,7 @@ openAPI: { name: "error", setter: "replicas", - err: "no setter replicas found", + err: "unable to find setter with name replicas", input: ` openAPI: definitions: