Count with Subpackages

This commit is contained in:
Phani Teja Marupaka
2020-09-08 16:28:01 -07:00
parent 678ae12115
commit 43ab7a8e71
2 changed files with 130 additions and 22 deletions

View File

@@ -5,9 +5,11 @@ package commands
import ( import (
"fmt" "fmt"
"io"
"sort" "sort"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"sigs.k8s.io/kustomize/cmd/config/ext"
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands" "sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
"sigs.k8s.io/kustomize/kyaml/kio" "sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/sets" "sigs.k8s.io/kustomize/kyaml/sets"
@@ -17,18 +19,18 @@ import (
func GetCountRunner(name string) *CountRunner { func GetCountRunner(name string) *CountRunner {
r := &CountRunner{} r := &CountRunner{}
c := &cobra.Command{ c := &cobra.Command{
Use: "count DIR...", Use: "count [DIR]",
Args: cobra.MaximumNArgs(1),
Short: commands.CountShort, Short: commands.CountShort,
Long: commands.CountLong, Long: commands.CountLong,
Example: commands.CountExamples, Example: commands.CountExamples,
RunE: r.runE, RunE: r.runE,
} }
fixDocs(name, c) fixDocs(name, c)
c.Flags().BoolVar(&r.IncludeSubpackages, "include-subpackages", true,
"also print resources from subpackages.")
c.Flags().BoolVar(&r.Kind, "kind", true, c.Flags().BoolVar(&r.Kind, "kind", true,
"count resources by kind.") "count resources by kind.")
c.Flags().BoolVarP(&r.RecurseSubPackages, "recurse-subpackages", "R", true,
"prints count of resources recursively in all the nested subpackages")
r.Command = c r.Command = c
return r return r
} }
@@ -42,20 +44,57 @@ type CountRunner struct {
IncludeSubpackages bool IncludeSubpackages bool
Kind bool Kind bool
Command *cobra.Command Command *cobra.Command
RecurseSubPackages bool
} }
func (r *CountRunner) runE(c *cobra.Command, args []string) error { func (r *CountRunner) runE(c *cobra.Command, args []string) error {
var inputs []kio.Reader if len(args) == 0 {
for _, a := range args { input := &kio.ByteReader{Reader: c.InOrStdin()}
inputs = append(inputs, kio.LocalPackageReader{
PackagePath: a, return handleError(c, kio.Pipeline{
IncludeSubpackages: r.IncludeSubpackages, Inputs: []kio.Reader{input},
}) Outputs: r.out(c.OutOrStdout()),
} }.Execute())
if len(inputs) == 0 {
inputs = append(inputs, &kio.ByteReader{Reader: c.InOrStdin()})
} }
e := executeCmdOnPkgs{
writer: c.OutOrStdout(),
needOpenAPI: false,
recurseSubPackages: r.RecurseSubPackages,
cmdRunner: r,
rootPkgPath: args[0],
}
return e.execute()
}
func (r *CountRunner) executeCmd(w io.Writer, pkgPath string) error {
openAPIFileName, err := ext.OpenAPIFileName()
if err != nil {
return err
}
input := kio.LocalPackageReader{PackagePath: pkgPath, PackageFileName: openAPIFileName}
fmt.Fprintf(w, "%q:\n", pkgPath)
err = kio.Pipeline{
Inputs: []kio.Reader{input},
Outputs: r.out(w),
}.Execute()
if err != nil {
// return err if there is only package
if !r.RecurseSubPackages {
return err
} else {
// print error message and continue if there are multiple packages to annotate
fmt.Fprintf(w, "%s in package %q\n", err.Error(), pkgPath)
}
}
return nil
}
func (r *CountRunner) out(w io.Writer) []kio.Writer {
var out []kio.Writer var out []kio.Writer
if r.Kind { if r.Kind {
out = append(out, kio.WriterFunc(func(nodes []*yaml.RNode) error { out = append(out, kio.WriterFunc(func(nodes []*yaml.RNode) error {
@@ -69,20 +108,15 @@ func (r *CountRunner) runE(c *cobra.Command, args []string) error {
order := k.List() order := k.List()
sort.Strings(order) sort.Strings(order)
for _, k := range order { for _, k := range order {
fmt.Fprintf(c.OutOrStdout(), "%s: %d\n", k, count[k]) fmt.Fprintf(w, "%s: %d\n", k, count[k])
} }
return nil return nil
})) }))
} else { } else {
out = append(out, kio.WriterFunc(func(nodes []*yaml.RNode) error { out = append(out, kio.WriterFunc(func(nodes []*yaml.RNode) error {
fmt.Fprintf(c.OutOrStdout(), "%d\n", len(nodes)) fmt.Fprintf(w, "%d\n", len(nodes))
return nil return nil
})) }))
} }
return handleError(c, kio.Pipeline{ return out
Inputs: inputs,
Outputs: out,
}.Execute())
} }

View File

@@ -8,10 +8,13 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"sigs.k8s.io/kustomize/cmd/config/internal/commands" "sigs.k8s.io/kustomize/cmd/config/internal/commands"
"sigs.k8s.io/kustomize/kyaml/copyutil"
"sigs.k8s.io/kustomize/kyaml/openapi"
) )
func TestCountCommand_files(t *testing.T) { func TestCountCommand_files(t *testing.T) {
@@ -67,7 +70,78 @@ spec:
return return
} }
if !assert.Equal(t, "Deployment: 2\nService: 1\n", b.String()) { if !assert.Contains(t, b.String(), "Deployment: 2\nService: 1\n") {
return return
} }
} }
func TestCountSubPackages(t *testing.T) {
var tests = []struct {
name string
dataset string
packagePath string
args []string
expected string
}{
{
name: "count-recurse-subpackages",
dataset: "dataset-without-setters",
expected: `
"${baseDir}/mysql":
Deployment: 1
"${baseDir}/mysql/storage":
Deployment: 1
`,
},
{
name: "count-top-level-pkg-no-recurse-subpackages",
dataset: "dataset-without-setters",
args: []string{"-R=false"},
packagePath: "mysql",
expected: `"${baseDir}/mysql":
Deployment: 1`,
},
{
name: "count-nested-pkg-no-recurse-subpackages",
dataset: "dataset-without-setters",
packagePath: "mysql/storage",
args: []string{"-R=false"},
expected: `"${baseDir}/mysql/storage":
Deployment: 1`,
},
}
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.GetCountRunner("")
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()
}
})
}
}