From 34d610a38d60cb718725edb471f9d77d5dca6d1c Mon Sep 17 00:00:00 2001 From: Phani Teja Marupaka Date: Tue, 8 Sep 2020 15:28:49 -0700 Subject: [PATCH] Fmt with subpackages --- cmd/config/internal/commands/fmt.go | 94 +++++++++++++++++------- cmd/config/internal/commands/fmt_test.go | 70 ++++++++++++++++++ 2 files changed, 137 insertions(+), 27 deletions(-) diff --git a/cmd/config/internal/commands/fmt.go b/cmd/config/internal/commands/fmt.go index 3a481d36b2..9a50e4726b 100644 --- a/cmd/config/internal/commands/fmt.go +++ b/cmd/config/internal/commands/fmt.go @@ -4,7 +4,11 @@ package commands import ( + "fmt" + "io" + "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/kio" "sigs.k8s.io/kustomize/kyaml/kio/filters" @@ -33,6 +37,8 @@ formatting substitution verbs {'%n': 'metadata.name', '%s': 'metadata.namespace' `if true, override existing filepath annotations.`) c.Flags().BoolVar(&r.UseSchema, "use-schema", false, `if true, uses openapi resource schema to format resources.`) + c.Flags().BoolVarP(&r.RecurseSubPackages, "recurse-subpackages", "R", false, + "formats resource files recursively in all the nested subpackages") r.Command = c return r } @@ -43,12 +49,13 @@ func FmtCommand(name string) *cobra.Command { // FmtRunner contains the run function type FmtRunner struct { - Command *cobra.Command - FilenamePattern string - SetFilenames bool - KeepAnnotations bool - Override bool - UseSchema bool + Command *cobra.Command + FilenamePattern string + SetFilenames bool + KeepAnnotations bool + Override bool + UseSchema bool + RecurseSubPackages bool } func (r *FmtRunner) preRunE(c *cobra.Command, args []string) error { @@ -59,17 +66,6 @@ func (r *FmtRunner) preRunE(c *cobra.Command, args []string) error { } func (r *FmtRunner) runE(c *cobra.Command, args []string) error { - f := []kio.Filter{filters.FormatFilter{ - UseSchema: r.UseSchema, - }} - - // format with file names - if r.SetFilenames { - f = append(f, &filters.FileSetter{ - FilenamePattern: r.FilenamePattern, - Override: r.Override, - }) - } // format stdin if there are no args if len(args) == 0 { @@ -79,20 +75,64 @@ func (r *FmtRunner) runE(c *cobra.Command, args []string) error { KeepReaderAnnotations: r.KeepAnnotations, } return handleError(c, kio.Pipeline{ - Inputs: []kio.Reader{rw}, Filters: f, Outputs: []kio.Writer{rw}}.Execute()) + Inputs: []kio.Reader{rw}, Filters: r.fmtFilters(), Outputs: []kio.Writer{rw}}.Execute()) } - for i := range args { - path := args[i] - rw := &kio.LocalPackageReadWriter{ - NoDeleteFiles: true, - PackagePath: path, - KeepReaderAnnotations: r.KeepAnnotations} - err := kio.Pipeline{ - Inputs: []kio.Reader{rw}, Filters: f, Outputs: []kio.Writer{rw}}.Execute() + for _, rootPkgPath := range args { + e := executeCmdOnPkgs{ + writer: c.OutOrStdout(), + needOpenAPI: false, + recurseSubPackages: r.RecurseSubPackages, + cmdRunner: r, + rootPkgPath: rootPkgPath, + } + + err := e.execute() if err != nil { - return handleError(c, err) + return err } } return nil } + +func (r *FmtRunner) executeCmd(w io.Writer, pkgPath string) error { + openAPIFileName, err := ext.OpenAPIFileName() + if err != nil { + return err + } + + rw := &kio.LocalPackageReadWriter{ + NoDeleteFiles: true, + PackagePath: pkgPath, + KeepReaderAnnotations: r.KeepAnnotations, PackageFileName: openAPIFileName} + err = kio.Pipeline{ + Inputs: []kio.Reader{rw}, Filters: r.fmtFilters(), Outputs: []kio.Writer{rw}}.Execute() + + if err != nil { + // return err if RecurseSubPackages is false + if !r.RecurseSubPackages { + return err + } else { + // print error message and continue if RecurseSubPackages is true + fmt.Fprintf(w, "%s in package %q\n", err.Error(), pkgPath) + } + } else { + fmt.Fprintf(w, "formatted resource files in package %q\n", pkgPath) + } + return nil +} + +func (r *FmtRunner) fmtFilters() []kio.Filter { + fmtFilters := []kio.Filter{filters.FormatFilter{ + UseSchema: r.UseSchema, + }} + + // format with file names + if r.SetFilenames { + fmtFilters = append(fmtFilters, &filters.FileSetter{ + FilenamePattern: r.FilenamePattern, + Override: r.Override, + }) + } + return fmtFilters +} diff --git a/cmd/config/internal/commands/fmt_test.go b/cmd/config/internal/commands/fmt_test.go index 5896d0767a..9670eb28bb 100644 --- a/cmd/config/internal/commands/fmt_test.go +++ b/cmd/config/internal/commands/fmt_test.go @@ -7,12 +7,15 @@ import ( "bytes" "io/ioutil" "os" + "path/filepath" "strings" "testing" "github.com/stretchr/testify/assert" "sigs.k8s.io/kustomize/cmd/config/internal/commands" + "sigs.k8s.io/kustomize/kyaml/copyutil" "sigs.k8s.io/kustomize/kyaml/kio/filters/testyaml" + "sigs.k8s.io/kustomize/kyaml/openapi" "sigs.k8s.io/kustomize/kyaml/testutil" ) @@ -163,3 +166,70 @@ func TestCmd_failFileContents(t *testing.T) { // expect an error assert.EqualError(t, err, "yaml: line 1: did not find expected node content") } + +func TestFmtSubPackages(t *testing.T) { + var tests = []struct { + name string + dataset string + packagePath string + args []string + expected string + }{ + { + name: "fmt-recurse-subpackages", + dataset: "dataset-with-setters", + args: []string{"-R"}, + expected: ` +formatted resource files in package "${baseDir}/mysql" +formatted resource files in package "${baseDir}/mysql/nosetters" +formatted resource files in package "${baseDir}/mysql/storage" +`, + }, + { + name: "fmt-top-level-pkg-no-recurse-subpackages", + dataset: "dataset-without-setters", + packagePath: "mysql", + expected: `formatted resource files in package "${baseDir}/mysql"`, + }, + { + name: "fmt-nested-pkg-no-recurse-subpackages", + dataset: "dataset-without-setters", + packagePath: "mysql/storage", + expected: `formatted resource files in package "${baseDir}/mysql/storage"`, + }, + } + for i := range tests { + test := tests[i] + t.Run(test.name, func(t *testing.T) { + // reset the openAPI afterward + openapi.ResetOpenAPI() + defer openapi.ResetOpenAPI() + sourceDir := filepath.Join("test", "testdata", test.dataset) + baseDir, err := ioutil.TempDir("", "") + if !assert.NoError(t, err) { + t.FailNow() + } + copyutil.CopyDir(sourceDir, baseDir) + defer os.RemoveAll(baseDir) + runner := commands.GetFmtRunner("") + actual := &bytes.Buffer{} + runner.Command.SetOut(actual) + runner.Command.SetArgs(append([]string{filepath.Join(baseDir, test.packagePath)}, test.args...)) + err = runner.Command.Execute() + if !assert.NoError(t, err) { + t.FailNow() + } + + // normalize path format for windows + actualNormalized := strings.Replace( + strings.Replace(actual.String(), "\\", "/", -1), + "//", "/", -1) + + expected := strings.Replace(test.expected, "${baseDir}", baseDir, -1) + expectedNormalized := strings.Replace(expected, "\\", "/", -1) + if !assert.Equal(t, strings.TrimSpace(expectedNormalized), strings.TrimSpace(actualNormalized)) { + t.FailNow() + } + }) + } +}