Merge pull request #2958 from phanimarupaka/GrepWithSubpkgs

Grep with subpackages
This commit is contained in:
Kubernetes Prow Robot
2020-09-08 21:09:52 -07:00
committed by GitHub
2 changed files with 202 additions and 26 deletions

View File

@@ -5,10 +5,12 @@ package commands
import ( import (
"fmt" "fmt"
"io"
"strings" "strings"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
"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/kio/filters" "sigs.k8s.io/kustomize/kyaml/kio/filters"
@@ -18,13 +20,13 @@ import (
func GetGrepRunner(name string) *GrepRunner { func GetGrepRunner(name string) *GrepRunner {
r := &GrepRunner{} r := &GrepRunner{}
c := &cobra.Command{ c := &cobra.Command{
Use: "grep QUERY [DIR]...", Use: "grep QUERY [DIR]",
Short: commands.GrepShort, Short: commands.GrepShort,
Long: commands.GrepLong, Long: commands.GrepLong,
Example: commands.GrepExamples, Example: commands.GrepExamples,
PreRunE: r.preRunE, PreRunE: r.preRunE,
RunE: r.runE, RunE: r.runE,
Args: cobra.MinimumNArgs(1), Args: cobra.MaximumNArgs(2),
} }
fixDocs(name, c) fixDocs(name, c)
c.Flags().BoolVar(&r.IncludeSubpackages, "include-subpackages", true, c.Flags().BoolVar(&r.IncludeSubpackages, "include-subpackages", true,
@@ -33,7 +35,8 @@ func GetGrepRunner(name string) *GrepRunner {
"annotate resources with their file origins.") "annotate resources with their file origins.")
c.Flags().BoolVarP(&r.InvertMatch, "invert-match", "", false, c.Flags().BoolVarP(&r.InvertMatch, "invert-match", "", false,
"Selected Resources are those not matching any of the specified patterns..") "Selected Resources are those not matching any of the specified patterns..")
c.Flags().BoolVarP(&r.RecurseSubPackages, "recurse-subpackages", "R", true,
"also print resources recursively in all the nested subpackages")
r.Command = c r.Command = c
return r return r
} }
@@ -48,7 +51,8 @@ type GrepRunner struct {
KeepAnnotations bool KeepAnnotations bool
Command *cobra.Command Command *cobra.Command
filters.GrepFilter filters.GrepFilter
Format bool Format bool
RecurseSubPackages bool
} }
func (r *GrepRunner) preRunE(c *cobra.Command, args []string) error { func (r *GrepRunner) preRunE(c *cobra.Command, args []string) error {
@@ -101,25 +105,56 @@ func (r *GrepRunner) preRunE(c *cobra.Command, args []string) error {
} }
func (r *GrepRunner) runE(c *cobra.Command, args []string) error { func (r *GrepRunner) runE(c *cobra.Command, args []string) error {
var filters = []kio.Filter{r.GrepFilter} if len(args) == 1 {
input := &kio.ByteReader{Reader: c.InOrStdin()}
var inputs []kio.Reader return handleError(c, kio.Pipeline{
for _, a := range args[1:] { Inputs: []kio.Reader{input},
inputs = append(inputs, kio.LocalPackageReader{ Filters: []kio.Filter{r.GrepFilter},
PackagePath: a, Outputs: []kio.Writer{kio.ByteWriter{
IncludeSubpackages: r.IncludeSubpackages, Writer: c.OutOrStdout(),
}) KeepReaderAnnotations: r.KeepAnnotations,
} }},
if len(inputs) == 0 { }.Execute())
inputs = append(inputs, &kio.ByteReader{Reader: c.InOrStdin()})
} }
return handleError(c, kio.Pipeline{ e := executeCmdOnPkgs{
Inputs: inputs, writer: c.OutOrStdout(),
Filters: filters, needOpenAPI: false,
recurseSubPackages: r.RecurseSubPackages,
cmdRunner: r,
rootPkgPath: args[1],
}
return e.execute()
}
func (r *GrepRunner) 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},
Filters: []kio.Filter{r.GrepFilter},
Outputs: []kio.Writer{kio.ByteWriter{ Outputs: []kio.Writer{kio.ByteWriter{
Writer: c.OutOrStdout(), Writer: w,
KeepReaderAnnotations: r.KeepAnnotations, KeepReaderAnnotations: r.KeepAnnotations,
}}, }},
}.Execute()) }.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
} }

View File

@@ -8,10 +8,12 @@ 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"
) )
// TestGrepCommand_files verifies grep reads the files and filters them // TestGrepCommand_files verifies grep reads the files and filters them
@@ -68,7 +70,7 @@ spec:
return return
} }
if !assert.Equal(t, `kind: Deployment if !assert.Contains(t, b.String(), `kind: Deployment
metadata: metadata:
labels: labels:
app: nginx2 app: nginx2
@@ -90,7 +92,7 @@ metadata:
spec: spec:
selector: selector:
app: nginx app: nginx
`, b.String()) { `) {
return return
} }
} }
@@ -136,7 +138,7 @@ spec:
return return
} }
if !assert.Equal(t, `kind: Deployment if !assert.Contains(t, b.String(), `kind: Deployment
metadata: metadata:
labels: labels:
app: nginx2 app: nginx2
@@ -156,7 +158,7 @@ metadata:
spec: spec:
selector: selector:
app: nginx app: nginx
`, b.String()) { `) {
return return
} }
} }
@@ -250,7 +252,7 @@ spec:
if !assert.NoError(t, err) { if !assert.NoError(t, err) {
return return
} }
if !assert.Equal(t, `kind: Deployment if !assert.Contains(t, b.String(), `kind: Deployment
metadata: metadata:
labels: labels:
app: nginx1.7 app: nginx1.7
@@ -264,7 +266,146 @@ spec:
containers: containers:
- name: nginx - name: nginx
image: nginx:1.7.9 image: nginx:1.7.9
`, b.String()) { `) {
return return
} }
} }
func TestGrepSubPackages(t *testing.T) {
var tests = []struct {
name string
dataset string
packagePath string
args []string
expected string
}{
{
name: "grep-recurse-subpackages",
dataset: "dataset-without-setters",
args: []string{"kind=Deployment"},
expected: `
"${baseDir}/mysql":
# Copyright 2019 The Kubernetes Authors.
# SPDX-License-Identifier: Apache-2.0
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: myspace
name: mysql-deployment
annotations:
config.kubernetes.io/index: '0'
config.kubernetes.io/path: 'deployment.yaml'
spec:
replicas: 3
template:
spec:
containers:
- name: mysql
image: mysql:1.7.9
"${baseDir}/mysql/storage":
# Copyright 2019 The Kubernetes Authors.
# SPDX-License-Identifier: Apache-2.0
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: myspace
name: storage-deployment
annotations:
config.kubernetes.io/index: '0'
config.kubernetes.io/path: 'deployment.yaml'
spec:
replicas: 4
template:
spec:
containers:
- name: storage
image: storage:1.7.7
`,
},
{
name: "grep-top-level-pkg-no-recurse-subpackages",
dataset: "dataset-without-setters",
args: []string{"kind=Deployment", "-R=false"},
packagePath: "mysql",
expected: `
"${baseDir}/mysql":
# Copyright 2019 The Kubernetes Authors.
# SPDX-License-Identifier: Apache-2.0
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: myspace
name: mysql-deployment
annotations:
config.kubernetes.io/index: '0'
config.kubernetes.io/path: 'deployment.yaml'
spec:
replicas: 3
template:
spec:
containers:
- name: mysql
image: mysql:1.7.9`,
},
{
name: "grep-nested-pkg-no-recurse-subpackages",
dataset: "dataset-without-setters",
packagePath: "mysql/storage",
args: []string{"kind=Deployment", "-R=false"},
expected: `
"${baseDir}/mysql/storage":
# Copyright 2019 The Kubernetes Authors.
# SPDX-License-Identifier: Apache-2.0
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: myspace
name: storage-deployment
annotations:
config.kubernetes.io/index: '0'
config.kubernetes.io/path: 'deployment.yaml'
spec:
replicas: 4
template:
spec:
containers:
- name: storage
image: storage:1.7.7`,
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
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.GetGrepRunner("")
actual := &bytes.Buffer{}
runner.Command.SetOut(actual)
runner.Command.SetArgs(append(test.args, filepath.Join(baseDir, test.packagePath)))
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()
}
})
}
}