From 2076f07b9fcd14f42537ea0e5ea3526416e70926 Mon Sep 17 00:00:00 2001 From: Abhinav Sinha <37282098+zeborg@users.noreply.github.com> Date: Mon, 20 Dec 2021 11:39:53 +0530 Subject: [PATCH] added support for --git-branch flag and directory in git path for kyverno test cmd (#2763) * added support for --git-branch flag and directory in git path for kyverno test cmd Signed-off-by: Abhinav Sinha * added cli tests Signed-off-by: Abhinav Sinha * replaced hard-coded Makefile test-cmd branch names with var GIT_BRANCH Signed-off-by: Abhinav Sinha * moved `test-cmd` job from Makefile to github workflow Signed-off-by: Abhinav Sinha * added `release*` branch to `e2e` workflow Signed-off-by: Abhinav Sinha Co-authored-by: shuting --- .github/workflows/e2e.yaml | 21 ++++++++++- Makefile | 11 +----- pkg/kyverno/test/git.go | 6 +++ pkg/kyverno/test/test_command.go | 64 ++++++++++++++++++++++---------- 4 files changed, 71 insertions(+), 31 deletions(-) diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index ead258916e..d990d1ee9e 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -3,6 +3,7 @@ on: push: branches: - 'main' + - 'release*' paths-ignore: - 'README.md' - 'docs/**' @@ -10,6 +11,7 @@ on: pull_request: branches: - 'main' + - 'release*' paths-ignore: - 'README.md' - 'docs/**' @@ -48,7 +50,24 @@ jobs: - name: Test Policy run: | - make test-cmd + if [[ ${{ github.event_name }} == "push" ]] + then + GIT_BRANCH=${GITHUB_REF##*/} + elif [[ ${{ github.event_name }} == "pull_request" ]] + then + GIT_BRANCH=${{ github.event.pull_request.base.ref }} + fi + + CLI_PATH=cmd/cli/kubectl-kyverno + + go run $PWD/$CLI_PATH/main.go test https://github.com/kyverno/policies/$GIT_BRANCH + go run $PWD/$CLI_PATH/main.go test https://github.com/kyverno/policies --git-branch $GIT_BRANCH + go run $PWD/$CLI_PATH/main.go test https://github.com/kyverno/policies/pod-security/restricted -b $GIT_BRANCH + go run $PWD/$CLI_PATH/main.go test ./test/cli/test-mutate + go run $PWD/$CLI_PATH/main.go test ./test/cli/test + go run $PWD/$CLI_PATH/main.go test ./test/cli/test-fail/missing-policy && exit 1 || exit 0 + go run $PWD/$CLI_PATH/main.go test ./test/cli/test-fail/missing-rule && exit 1 || exit 0 + go run $PWD/$CLI_PATH/main.go test ./test/cli/test-fail/missing-resource && exit 1 || exit 0 - name: gofmt check run: | diff --git a/Makefile b/Makefile index fd6c5e1cdb..7612af17d4 100644 --- a/Makefile +++ b/Makefile @@ -230,7 +230,7 @@ $(GO_ACC): # go-acc merges the result for pks so that it be used by # go tool cover for reporting -test: test-clean test-unit test-e2e test-cmd +test: test-clean test-unit test-e2e test-clean: @echo " cleaning test cache" @@ -267,15 +267,6 @@ test-e2e-local: kill $! $(eval export E2E="") -#Test TestCmd Policy -test-cmd: cli - $(PWD)/$(CLI_PATH)/kyverno test https://github.com/kyverno/policies/main - $(PWD)/$(CLI_PATH)/kyverno test ./test/cli/test-mutate - $(PWD)/$(CLI_PATH)/kyverno test ./test/cli/test - $(PWD)/$(CLI_PATH)/kyverno test ./test/cli/test-fail/missing-policy && exit 1 || exit 0 - $(PWD)/$(CLI_PATH)/kyverno test ./test/cli/test-fail/missing-rule && exit 1 || exit 0 - $(PWD)/$(CLI_PATH)/kyverno test ./test/cli/test-fail/missing-resource && exit 1 || exit 0 - # godownloader create downloading script for kyverno-cli godownloader: godownloader .goreleaser.yml --repo kyverno/kyverno -o ./scripts/install-cli.sh --source="raw" diff --git a/pkg/kyverno/test/git.go b/pkg/kyverno/test/git.go index efd28f66d9..44c325a273 100644 --- a/pkg/kyverno/test/git.go +++ b/pkg/kyverno/test/git.go @@ -22,11 +22,17 @@ func clone(path string, fs billy.Filesystem, branch string) (*git.Repository, er func listYAMLs(fs billy.Filesystem, path string) ([]string, error) { path = filepath.Clean(path) + + if _, err := fs.Stat(path); err != nil { + return nil, err + } + fis, err := fs.ReadDir(path) if err != nil { return nil, err } yamls := make([]string, 0) + for _, fi := range fis { name := filepath.Join(path, fi.Name()) if fi.IsDir() { diff --git a/pkg/kyverno/test/test_command.go b/pkg/kyverno/test/test_command.go index b88342f107..3fd4d43457 100644 --- a/pkg/kyverno/test/test_command.go +++ b/pkg/kyverno/test/test_command.go @@ -42,18 +42,22 @@ var longHelp = ` The test command provides a facility to test resources against policies by comparing expected results, declared ahead of time in a test.yaml file, to actual results reported by Kyverno. Users provide the path to the folder containing a test.yaml file where the location could be on a local filesystem or a remote git repository ` var exampleHelp = ` -kyverno test https://github.com/kyverno/policies/main +kyverno test https://github.com/kyverno/policies/pod-security --git-branch main - Executing disallow-cri-sock-mount... - applying 1 policy to 1 resource... - │───│────────────────────────────────│────────────────────────────────│────────────────────────────│────────│ - │ # │ POLICY │ RULE │ RESOURCE │ RESULT │ - │───│────────────────────────────────│────────────────────────────────│────────────────────────────│────────│ - │ 1 │ disallow-container-sock-mounts │ validate-docker-sock-mount │ pod-with-docker-sock-mount │ Pass │ - │ 2 │ disallow-container-sock-mounts │ validate-containerd-sock-mount │ pod-with-docker-sock-mount │ Pass │ - │ 3 │ disallow-container-sock-mounts │ validate-crio-sock-mount │ pod-with-docker-sock-mount │ Pass │ - │───│────────────────────────────────│────────────────────────────────│────────────────────────────│────────│ + Executing require-non-root-groups... + applying 1 policy to 2 resources... + + │───│─────────────────────────│──────────────────────────│──────────────────────────────────│────────│ + │ # │ POLICY │ RULE │ RESOURCE │ RESULT │ + │───│─────────────────────────│──────────────────────────│──────────────────────────────────│────────│ + │ 1 │ require-non-root-groups │ check-runasgroup │ default/Pod/fs-group0 │ Pass │ + │ 2 │ require-non-root-groups │ check-supplementalGroups │ default/Pod/fs-group0 │ Pass │ + │ 3 │ require-non-root-groups │ check-fsGroup │ default/Pod/fs-group0 │ Pass │ + │ 4 │ require-non-root-groups │ check-supplementalGroups │ default/Pod/supplemental-groups0 │ Pass │ + │ 5 │ require-non-root-groups │ check-fsGroup │ default/Pod/supplemental-groups0 │ Pass │ + │ 6 │ require-non-root-groups │ check-runasgroup │ default/Pod/supplemental-groups0 │ Pass │ + │───│─────────────────────────│──────────────────────────│──────────────────────────────────│────────│ @@ -135,9 +139,9 @@ For more information visit https://kyverno.io/docs/kyverno-cli/#test // Command returns version command func Command() *cobra.Command { var cmd *cobra.Command - var valuesFile, fileName string + var valuesFile, fileName, gitBranch string cmd = &cobra.Command{ - Use: "test [flags]\n kyverno test ", + Use: "test [flags]\n kyverno test --git-branch ", Args: cobra.ExactArgs(1), Short: "run tests from directory", Long: longHelp, @@ -152,7 +156,7 @@ func Command() *cobra.Command { } }() - _, err = testCommandExecute(dirPath, valuesFile, fileName) + _, err = testCommandExecute(dirPath, valuesFile, fileName, gitBranch) if err != nil { log.Log.V(3).Info("a directory is required") return err @@ -162,6 +166,7 @@ func Command() *cobra.Command { }, } cmd.Flags().StringVarP(&fileName, "file-name", "f", "kyverno-test.yaml", "test filename") + cmd.Flags().StringVarP(&gitBranch, "git-branch", "b", "", "test github repository branch") return cmd } @@ -217,7 +222,7 @@ type resultCounts struct { Fail int } -func testCommandExecute(dirPath []string, valuesFile string, fileName string) (rc *resultCounts, err error) { +func testCommandExecute(dirPath []string, valuesFile string, fileName string, gitBranch string) (rc *resultCounts, err error) { var errors []error fs := memfs.New() rc = &resultCounts{} @@ -236,26 +241,45 @@ func testCommandExecute(dirPath []string, valuesFile string, fileName string) (r pathElems := strings.Split(gitURL.Path[1:], "/") if len(pathElems) <= 1 { - err := fmt.Errorf("invalid URL path %s - expected https://github.com/:owner/:repository/:branch", gitURL.Path) + err := fmt.Errorf("invalid URL path %s - expected https://github.com/:owner/:repository/:branch (without --git-branch flag) OR https://github.com/:owner/:repository/:directory (with --git-branch flag)", gitURL.Path) fmt.Printf("Error: failed to parse URL \nCause: %s\n", err) os.Exit(1) } gitURL.Path = strings.Join([]string{pathElems[0], pathElems[1]}, "/") repoURL := gitURL.String() - branch := strings.ReplaceAll(dirPath[0], repoURL+"/", "") - if branch == "" { - branch = "main" + + var gitPathToYamls string + if gitBranch == "" { + gitPathToYamls = "/" + + if string(dirPath[0][len(dirPath[0])-1]) == "/" { + gitBranch = strings.ReplaceAll(dirPath[0], repoURL+"/", "") + } else { + gitBranch = strings.ReplaceAll(dirPath[0], repoURL, "") + } + + if gitBranch == "" { + gitBranch = "main" + } else if string(gitBranch[0]) == "/" { + gitBranch = gitBranch[1:] + } + } else { + if string(dirPath[0][len(dirPath[0])-1]) == "/" { + gitPathToYamls = strings.ReplaceAll(dirPath[0], repoURL+"/", "/") + } else { + gitPathToYamls = strings.ReplaceAll(dirPath[0], repoURL, "/") + } } - _, cloneErr := clone(repoURL, fs, branch) + _, cloneErr := clone(repoURL, fs, gitBranch) if cloneErr != nil { fmt.Printf("Error: failed to clone repository \nCause: %s\n", cloneErr) log.Log.V(3).Info(fmt.Sprintf("failed to clone repository %v as it is not valid", repoURL), "error", cloneErr) os.Exit(1) } - policyYamls, err := listYAMLs(fs, "/") + policyYamls, err := listYAMLs(fs, gitPathToYamls) if err != nil { return rc, sanitizederror.NewWithError("failed to list YAMLs in repository", err) }