Skip to content
This repository has been archived by the owner on Jun 6, 2024. It is now read-only.

Commit

Permalink
feat: add flag --exclude paths regex (#932)
Browse files Browse the repository at this point in the history
* feat:exclude paths regex

* change to 'excludeRegex'

* add validation for exclude flag

* add test case for FilterFiles
  • Loading branch information
Meyazhagan authored May 10, 2023
1 parent 5daac43 commit ca2b4de
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 7 deletions.
2 changes: 1 addition & 1 deletion cmd/kustomize/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ type ReaderMock struct {
mock.Mock
}

func (rm *ReaderMock) FilterFiles(paths []string) ([]string, error) {
func (rm *ReaderMock) FilterFiles(paths []string, excludePattern string) ([]string, error) {
args := rm.Called(paths)
return args.Get(0).([]string), nil
}
Expand Down
15 changes: 12 additions & 3 deletions cmd/test/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ type K8sValidator interface {
type TestCommandFlags struct {
Output string
K8sVersion string
ExcludePattern string
IgnoreMissingSchemas bool
OnlyK8sFiles bool
Verbose bool
Expand All @@ -70,6 +71,7 @@ func NewTestCommandFlags() *TestCommandFlags {
return &TestCommandFlags{
Output: "",
K8sVersion: "",
ExcludePattern: "",
IgnoreMissingSchemas: false,
OnlyK8sFiles: false,
Verbose: false,
Expand Down Expand Up @@ -102,7 +104,6 @@ func (flags *TestCommandFlags) Validate() error {
}

err := validateK8sVersionFormatIfProvided(flags.K8sVersion)

if err != nil {
return err
}
Expand All @@ -112,6 +113,11 @@ func (flags *TestCommandFlags) Validate() error {
return err
}

_, err = regexp.Compile(flags.ExcludePattern)
if err != nil {
return fmt.Errorf("invalid --exclude flag: " + err.Error())
}

return nil

}
Expand All @@ -127,7 +133,7 @@ type EvaluationPrinter interface {
}

type Reader interface {
FilterFiles(paths []string) ([]string, error)
FilterFiles(paths []string, excludePattern string) ([]string, error)
}

type LocalConfig interface {
Expand All @@ -144,6 +150,7 @@ type CliClient interface {
type TestCommandData struct {
Output string
K8sVersion string
ExcludePattern string
IgnoreMissingSchemas bool
OnlyK8sFiles bool
Verbose bool
Expand Down Expand Up @@ -262,6 +269,7 @@ func (flags *TestCommandFlags) AddFlags(cmd *cobra.Command) {

cmd.Flags().StringVarP(&flags.K8sVersion, "schema-version", "s", "", "Set kubernetes version to validate against. Defaults to 1.24.0")
cmd.Flags().StringVarP(&flags.PolicyName, "policy", "p", "", "Policy name to run against")
cmd.Flags().StringVarP(&flags.ExcludePattern, "exclude", "", "", "Exclude paths pattern (regex)")

cmd.Flags().StringVar(&flags.PolicyConfig, "policy-config", "", "Path for local policies configuration file")
cmd.Flags().BoolVar(&flags.OnlyK8sFiles, "only-k8s-files", false, "Evaluate only valid yaml files with the properties 'apiVersion' and 'kind'. Ignore everything else")
Expand Down Expand Up @@ -342,6 +350,7 @@ func GenerateTestCommandData(testCommandFlags *TestCommandFlags, localConfigCont

testCommandOptions := &TestCommandData{Output: testCommandFlags.Output,
K8sVersion: k8sVersion,
ExcludePattern: testCommandFlags.ExcludePattern,
IgnoreMissingSchemas: testCommandFlags.IgnoreMissingSchemas,
OnlyK8sFiles: testCommandFlags.OnlyK8sFiles,
Verbose: testCommandFlags.Verbose,
Expand Down Expand Up @@ -414,7 +423,7 @@ func test(ctx *TestCommandContext, paths []string, testCommandData *TestCommandD
paths = []string{tempFile.Name()}
}

filesPaths, err := ctx.Reader.FilterFiles(paths)
filesPaths, err := ctx.Reader.FilterFiles(paths, testCommandData.ExcludePattern)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/test/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ type ReaderMock struct {
mock.Mock
}

func (rm *ReaderMock) FilterFiles(paths []string) ([]string, error) {
func (rm *ReaderMock) FilterFiles(paths []string, excludePattern string) ([]string, error) {
args := rm.Called(paths)
return args.Get(0).([]string), nil
}
Expand Down
11 changes: 9 additions & 2 deletions pkg/fileReader/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package fileReader
import (
"os"
"path/filepath"
"regexp"

"github.com/bmatcuk/doublestar/v2"
)
Expand Down Expand Up @@ -55,16 +56,22 @@ func CreateFileReader(opts *FileReaderOptions) *FileReader {
return fileReader
}

func (fr *FileReader) FilterFiles(paths []string) ([]string, error) {
func (fr *FileReader) FilterFiles(paths []string, excludePattern string) ([]string, error) {
var filePaths []string

excludeRegex, err := regexp.Compile(excludePattern)
if err != nil {
return nil, err
}

for _, path := range paths {
stat, err := fr.stat(path)
if err != nil {
return []string{}, err
}

if !stat.IsDir() {
isMatched := excludePattern != "" && excludeRegex.MatchString(path)
if !stat.IsDir() && !isMatched {
filePaths = append(filePaths, path)
}
}
Expand Down
69 changes: 69 additions & 0 deletions pkg/fileReader/reader_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fileReader

import (
"io/fs"
"os"
"reflect"
"testing"
Expand Down Expand Up @@ -118,6 +119,74 @@ func (c *absMock) Abs(path string) (string, error) {
return args.Get(0).(string), args.Error(1)
}

type filterFilesTestCase struct {
name string
args struct {
paths []string
excludePattern string
}
mock struct {
stat struct {
response fs.FileInfo
err error
}
}
expected struct {
filePaths []string
}
}

func TestFilterFiles(t *testing.T) {
stat := statMock{}
fileInfo := &MockFileInfo{}

tests := []filterFilesTestCase{
{
name: "success",
args: struct {
paths []string
excludePattern string
}{
paths: []string{"file1.yaml", "file2.yaml", "file3-exclude.yaml", "file4.yaml", "file5-exclude.yaml"},
excludePattern: "exclude.yaml",
},
mock: struct {
stat struct {
response fs.FileInfo
err error
}
}{
stat: struct {
response fs.FileInfo
err error
}{
response: fileInfo,
err: nil,
},
},
expected: struct{ filePaths []string }{
filePaths: []string{"file1.yaml", "file2.yaml", "file4.yaml"},
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
stat.On("Stat", mock.Anything).Return(tt.mock.stat.response, tt.mock.stat.err)
fileInfo.On("IsDir", mock.Anything).Return(false)
fileReader := &FileReader{
glob: nil,
stat: stat.Stat,
}

filteredfiles, _ := fileReader.FilterFiles(tt.args.paths, tt.args.excludePattern)
stat.AssertCalled(t, "Stat", tt.expected.filePaths[0])
fileInfo.AssertCalled(t, "IsDir")
assert.Equal(t, tt.expected.filePaths, filteredfiles)
})
}
}

func TestCreateFileReader(t *testing.T) {
glob := globMock{}
io := ioMock{}
Expand Down

0 comments on commit ca2b4de

Please sign in to comment.