mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-28 18:38:40 +00:00
refactor: cli proper error handling (#8360)
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
parent
44f0de5c53
commit
dde312e65d
12 changed files with 173 additions and 238 deletions
|
@ -22,7 +22,6 @@ import (
|
|||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/store"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/userinfo"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/common"
|
||||
sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/variables"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
|
@ -76,14 +75,6 @@ func Command() *cobra.Command {
|
|||
Example: command.FormatExamples(examples...),
|
||||
RunE: func(cmd *cobra.Command, policyPaths []string) (err error) {
|
||||
color.InitColors(removeColor)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if !sanitizederror.IsErrorSanitized(err) {
|
||||
log.Log.Error(err, "failed to sanitize")
|
||||
err = fmt.Errorf("internal error")
|
||||
}
|
||||
}
|
||||
}()
|
||||
applyCommandConfig.PolicyPaths = policyPaths
|
||||
rc, _, skipInvalidPolicies, responses, err := applyCommandConfig.applyCommandHelper()
|
||||
if err != nil {
|
||||
|
@ -140,19 +131,16 @@ func (c *ApplyCommandConfig) applyCommandHelper() (*processor.ResultCounts, []*u
|
|||
if c.UserInfoPath != "" {
|
||||
userInfo, err = userinfo.Load(nil, c.UserInfoPath, "")
|
||||
if err != nil {
|
||||
return nil, nil, skipInvalidPolicies, nil, sanitizederror.NewWithError("Error: failed to load request info", err)
|
||||
return nil, nil, skipInvalidPolicies, nil, fmt.Errorf("failed to load request info (%w)", err)
|
||||
}
|
||||
}
|
||||
variables, err := variables.New(nil, "", c.ValuesFile, nil, c.Variables...)
|
||||
if err != nil {
|
||||
if !sanitizederror.IsErrorSanitized(err) {
|
||||
return nil, nil, skipInvalidPolicies, nil, sanitizederror.NewWithError("failed to decode yaml", err)
|
||||
}
|
||||
return nil, nil, skipInvalidPolicies, nil, err
|
||||
return nil, nil, skipInvalidPolicies, nil, fmt.Errorf("failed to decode yaml (%w)", err)
|
||||
}
|
||||
openApiManager, err := openapi.NewManager(log.Log)
|
||||
if err != nil {
|
||||
return nil, nil, skipInvalidPolicies, nil, sanitizederror.NewWithError("failed to initialize openAPIController", err)
|
||||
return nil, nil, skipInvalidPolicies, nil, fmt.Errorf("failed to initialize openAPIController (%w)", err)
|
||||
}
|
||||
rc, resources1, skipInvalidPolicies, responses1, err, dClient := c.initStoreAndClusterClient(skipInvalidPolicies)
|
||||
if err != nil {
|
||||
|
@ -200,10 +188,7 @@ func (c *ApplyCommandConfig) applyCommandHelper() (*processor.ResultCounts, []*u
|
|||
func (c *ApplyCommandConfig) getMutateLogPathIsDir(skipInvalidPolicies SkippedInvalidPolicies) (*processor.ResultCounts, []*unstructured.Unstructured, SkippedInvalidPolicies, []engineapi.EngineResponse, error, bool) {
|
||||
mutateLogPathIsDir, err := checkMutateLogPath(c.MutateLogPath)
|
||||
if err != nil {
|
||||
if !sanitizederror.IsErrorSanitized(err) {
|
||||
return nil, nil, skipInvalidPolicies, nil, sanitizederror.NewWithError("failed to create file/folder", err), false
|
||||
}
|
||||
return nil, nil, skipInvalidPolicies, nil, err, false
|
||||
return nil, nil, skipInvalidPolicies, nil, fmt.Errorf("failed to create file/folder (%w)", err), false
|
||||
}
|
||||
return nil, nil, skipInvalidPolicies, nil, err, mutateLogPathIsDir
|
||||
}
|
||||
|
@ -226,7 +211,7 @@ func (c *ApplyCommandConfig) applyValidatingAdmissionPolicytoResource(
|
|||
}
|
||||
ers, err := processor.ApplyPolicyOnResource()
|
||||
if err != nil {
|
||||
return responses, sanitizederror.NewWithError(fmt.Errorf("failed to apply policies on resource %s", resource.GetName()).Error(), err)
|
||||
return responses, fmt.Errorf("failed to apply policies on resource %s (%w)", resource.GetName(), err)
|
||||
}
|
||||
responses = append(responses, ers...)
|
||||
}
|
||||
|
@ -295,7 +280,7 @@ func (c *ApplyCommandConfig) applyPolicytoResource(
|
|||
}
|
||||
ers, err := processor.ApplyPoliciesOnResource()
|
||||
if err != nil {
|
||||
return &rc, resources, responses, sanitizederror.NewWithError(fmt.Errorf("failed to apply policies on resource %v", resource.GetName()).Error(), err)
|
||||
return &rc, resources, responses, fmt.Errorf("failed to apply policies on resource %v (%w)", resource.GetName(), err)
|
||||
}
|
||||
responses = append(responses, ers...)
|
||||
}
|
||||
|
@ -305,7 +290,7 @@ func (c *ApplyCommandConfig) applyPolicytoResource(
|
|||
func (c *ApplyCommandConfig) loadResources(policies []kyvernov1.PolicyInterface, validatingAdmissionPolicies []v1alpha1.ValidatingAdmissionPolicy, dClient dclient.Interface) ([]*unstructured.Unstructured, error) {
|
||||
resources, err := common.GetResourceAccordingToResourcePath(nil, c.ResourcePaths, c.Cluster, policies, validatingAdmissionPolicies, dClient, c.Namespace, c.PolicyReport, "")
|
||||
if err != nil {
|
||||
return resources, fmt.Errorf("Error: failed to load resources\nCause: %s\n", err)
|
||||
return resources, fmt.Errorf("failed to load resources (%w)", err)
|
||||
}
|
||||
return resources, nil
|
||||
}
|
||||
|
@ -321,13 +306,13 @@ func (c *ApplyCommandConfig) loadPolicies(skipInvalidPolicies SkippedInvalidPoli
|
|||
if isGit {
|
||||
gitSourceURL, err := url.Parse(path)
|
||||
if err != nil {
|
||||
return nil, nil, skipInvalidPolicies, nil, sanitizederror.NewWithError("Error: failed to load policies", err), nil, nil
|
||||
return nil, nil, skipInvalidPolicies, nil, fmt.Errorf("failed to load policies (%w)", err), nil, nil
|
||||
}
|
||||
|
||||
pathElems := strings.Split(gitSourceURL.Path[1:], "/")
|
||||
if len(pathElems) <= 1 {
|
||||
err := fmt.Errorf("invalid URL path %s - expected https://<any_git_source_domain>/:owner/:repository/:branch (without --git-branch flag) OR https://<any_git_source_domain>/:owner/:repository/:directory (with --git-branch flag)", gitSourceURL.Path)
|
||||
return nil, nil, skipInvalidPolicies, nil, sanitizederror.NewWithError("Error: failed to parse URL", err), nil, nil
|
||||
return nil, nil, skipInvalidPolicies, nil, fmt.Errorf("failed to parse URL (%w)", err), nil, nil
|
||||
}
|
||||
gitSourceURL.Path = strings.Join([]string{pathElems[0], pathElems[1]}, "/")
|
||||
repoURL := gitSourceURL.String()
|
||||
|
@ -336,11 +321,11 @@ func (c *ApplyCommandConfig) loadPolicies(skipInvalidPolicies SkippedInvalidPoli
|
|||
fs := memfs.New()
|
||||
if _, err := gitutils.Clone(repoURL, fs, c.GitBranch); err != nil {
|
||||
log.Log.V(3).Info(fmt.Sprintf("failed to clone repository %v as it is not valid", repoURL), "error", err)
|
||||
return nil, nil, skipInvalidPolicies, nil, sanitizederror.NewWithError("Error: failed to clone repository", err), nil, nil
|
||||
return nil, nil, skipInvalidPolicies, nil, fmt.Errorf("failed to clone repository (%w)", err), nil, nil
|
||||
}
|
||||
policyYamls, err := gitutils.ListYamls(fs, gitPathToYamls)
|
||||
if err != nil {
|
||||
return nil, nil, skipInvalidPolicies, nil, sanitizederror.NewWithError("failed to list YAMLs in repository", err), nil, nil
|
||||
return nil, nil, skipInvalidPolicies, nil, fmt.Errorf("failed to list YAMLs in repository (%w)", err), nil, nil
|
||||
}
|
||||
for _, policyYaml := range policyYamls {
|
||||
policiesFromFile, admissionPoliciesFromFile, err := policy.Load(fs, "", policyYaml)
|
||||
|
@ -353,7 +338,7 @@ func (c *ApplyCommandConfig) loadPolicies(skipInvalidPolicies SkippedInvalidPoli
|
|||
} else {
|
||||
policiesFromFile, admissionPoliciesFromFile, err := policy.Load(nil, "", path)
|
||||
if err != nil {
|
||||
return nil, nil, skipInvalidPolicies, nil, sanitizederror.NewWithError("Error: failed to load policies", err), nil, nil
|
||||
return nil, nil, skipInvalidPolicies, nil, fmt.Errorf("failed to load policies (%w)", err), nil, nil
|
||||
}
|
||||
policies = append(policies, policiesFromFile...)
|
||||
validatingAdmissionPolicies = append(validatingAdmissionPolicies, admissionPoliciesFromFile...)
|
||||
|
@ -400,10 +385,7 @@ func (c *ApplyCommandConfig) cleanPreviousContent(mutateLogPathIsDir bool, skipI
|
|||
// Necessary for us to include the file via variable as it is part of the CLI.
|
||||
_, err := os.OpenFile(c.MutateLogPath, os.O_TRUNC|os.O_WRONLY, 0o600) // #nosec G304
|
||||
if err != nil {
|
||||
if !sanitizederror.IsErrorSanitized(err) {
|
||||
return nil, nil, skipInvalidPolicies, nil, sanitizederror.NewWithError("failed to truncate the existing file at "+c.MutateLogPath, err)
|
||||
}
|
||||
return nil, nil, skipInvalidPolicies, nil, err
|
||||
return nil, nil, skipInvalidPolicies, nil, fmt.Errorf("failed to truncate the existing file at %s (%w)", c.MutateLogPath, err)
|
||||
}
|
||||
}
|
||||
return nil, nil, skipInvalidPolicies, nil, nil
|
||||
|
@ -412,16 +394,16 @@ func (c *ApplyCommandConfig) cleanPreviousContent(mutateLogPathIsDir bool, skipI
|
|||
func (c *ApplyCommandConfig) checkArguments() (*processor.ResultCounts, []*unstructured.Unstructured, SkippedInvalidPolicies, []engineapi.EngineResponse, error) {
|
||||
var skipInvalidPolicies SkippedInvalidPolicies
|
||||
if c.ValuesFile != "" && c.Variables != nil {
|
||||
return nil, nil, skipInvalidPolicies, nil, sanitizederror.New("pass the values either using set flag or values_file flag")
|
||||
return nil, nil, skipInvalidPolicies, nil, fmt.Errorf("pass the values either using set flag or values_file flag")
|
||||
}
|
||||
if len(c.PolicyPaths) == 0 {
|
||||
return nil, nil, skipInvalidPolicies, nil, sanitizederror.New("require policy")
|
||||
return nil, nil, skipInvalidPolicies, nil, fmt.Errorf("require policy")
|
||||
}
|
||||
if (len(c.PolicyPaths) > 0 && c.PolicyPaths[0] == "-") && len(c.ResourcePaths) > 0 && c.ResourcePaths[0] == "-" {
|
||||
return nil, nil, skipInvalidPolicies, nil, sanitizederror.New("a stdin pipe can be used for either policies or resources, not both")
|
||||
return nil, nil, skipInvalidPolicies, nil, fmt.Errorf("a stdin pipe can be used for either policies or resources, not both")
|
||||
}
|
||||
if len(c.ResourcePaths) == 0 && !c.Cluster {
|
||||
return nil, nil, skipInvalidPolicies, nil, sanitizederror.New("resource file(s) or cluster required")
|
||||
return nil, nil, skipInvalidPolicies, nil, fmt.Errorf("resource file(s) or cluster required")
|
||||
}
|
||||
return nil, nil, skipInvalidPolicies, nil, nil
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
package apply
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError"
|
||||
)
|
||||
|
||||
// checkMutateLogPath - checking path for printing mutated resource (-o flag)
|
||||
|
@ -21,10 +20,7 @@ func checkMutateLogPath(mutateLogPath string) (mutateLogPathIsDir bool, err erro
|
|||
|
||||
err := createFileOrFolder(mutateLogPath, mutateLogPathIsDir)
|
||||
if err != nil {
|
||||
if !sanitizederror.IsErrorSanitized(err) {
|
||||
return mutateLogPathIsDir, sanitizederror.NewWithError("failed to create file/folder.", err)
|
||||
}
|
||||
return mutateLogPathIsDir, err
|
||||
return mutateLogPathIsDir, fmt.Errorf("failed to create file/folder (%w)", err)
|
||||
}
|
||||
}
|
||||
return mutateLogPathIsDir, err
|
||||
|
@ -47,7 +43,7 @@ func createFileOrFolder(mutateLogPath string, mutateLogPathIsDir bool) error {
|
|||
if os.IsNotExist(err) {
|
||||
errDir := os.MkdirAll(folderPath, 0o750)
|
||||
if errDir != nil {
|
||||
return sanitizederror.NewWithError("failed to create directory", err)
|
||||
return fmt.Errorf("failed to create directory (%w)", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,21 +52,21 @@ func createFileOrFolder(mutateLogPath string, mutateLogPathIsDir bool) error {
|
|||
// Necessary for us to create the file via variable as it is part of the CLI.
|
||||
file, err := os.OpenFile(mutateLogPath, os.O_RDONLY|os.O_CREATE, 0o600) // #nosec G304
|
||||
if err != nil {
|
||||
return sanitizederror.NewWithError("failed to create file", err)
|
||||
return fmt.Errorf("failed to create file (%w)", err)
|
||||
}
|
||||
|
||||
err = file.Close()
|
||||
if err != nil {
|
||||
return sanitizederror.NewWithError("failed to close file", err)
|
||||
return fmt.Errorf("failed to close file (%w)", err)
|
||||
}
|
||||
} else {
|
||||
errDir := os.MkdirAll(mutateLogPath, 0o750)
|
||||
if errDir != nil {
|
||||
return sanitizederror.NewWithError("failed to create directory", err)
|
||||
return fmt.Errorf("failed to create directory (%w)", err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return sanitizederror.NewWithError("failed to describe file", err)
|
||||
return fmt.Errorf("failed to describe file (%w)", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,123 +1,28 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
testapi "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/apis/test"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/command"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/test"
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
func Command() *cobra.Command {
|
||||
var fileName string
|
||||
var save bool
|
||||
var compress bool
|
||||
var options options
|
||||
cmd := &cobra.Command{
|
||||
Use: "test [folder]...",
|
||||
Short: command.FormatDescription(true, websiteUrl, true, description...),
|
||||
Long: command.FormatDescription(false, websiteUrl, true, description...),
|
||||
Example: command.FormatExamples(examples...),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
var testCases []test.TestCase
|
||||
for _, arg := range args {
|
||||
tests, err := test.LoadTests(arg, fileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
testCases = append(testCases, tests...)
|
||||
if err := options.validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
fmt.Printf("Processing test file (%s)...", testCase.Path)
|
||||
fmt.Println()
|
||||
if testCase.Err != nil {
|
||||
fmt.Printf(" ERROR: loading test file (%s): %s", testCase.Path, testCase.Err)
|
||||
fmt.Println()
|
||||
continue
|
||||
}
|
||||
test := testCase.Test
|
||||
needsSave := false
|
||||
if test.Name == "" {
|
||||
fmt.Println(" WARNING: name is not set")
|
||||
test.Name = filepath.Base(testCase.Path)
|
||||
needsSave = true
|
||||
}
|
||||
if len(test.Policies) == 0 {
|
||||
fmt.Println(" WARNING: test has no policies")
|
||||
}
|
||||
if len(test.Resources) == 0 {
|
||||
fmt.Println(" WARNING: test has no resources")
|
||||
}
|
||||
for i := range test.Results {
|
||||
result := &test.Results[i]
|
||||
if result.Resource != "" && len(result.Resources) != 0 {
|
||||
fmt.Println(" WARNING: test result should not use both `resource` and `resources` fields")
|
||||
}
|
||||
if result.Resource != "" {
|
||||
fmt.Println(" WARNING: test result uses deprecated `resource` field, moving it into the `resources` field")
|
||||
result.Resources = append(result.Resources, result.Resource)
|
||||
result.Resource = ""
|
||||
needsSave = true
|
||||
}
|
||||
if result.Namespace != "" {
|
||||
fmt.Println(" WARNING: test result uses deprecated `namespace` field, replacing `policy` with a `<namespace>/<name>` pattern")
|
||||
result.Policy = fmt.Sprintf("%s/%s", result.Namespace, result.Policy)
|
||||
result.Namespace = ""
|
||||
needsSave = true
|
||||
}
|
||||
if result.Status != "" && result.Result != "" {
|
||||
fmt.Println(" ERROR: test result should not use both `status` and `result` fields")
|
||||
}
|
||||
if result.Status != "" && result.Result == "" {
|
||||
fmt.Println(" WARNING: test result uses deprecated `status` field, moving it into the `result` field")
|
||||
result.Result = result.Status
|
||||
result.Status = ""
|
||||
needsSave = true
|
||||
}
|
||||
}
|
||||
if compress {
|
||||
compressed := map[testapi.TestResultBase][]string{}
|
||||
for _, result := range test.Results {
|
||||
compressed[result.TestResultBase] = append(compressed[result.TestResultBase], result.Resources...)
|
||||
}
|
||||
if len(compressed) != len(test.Results) {
|
||||
needsSave = true
|
||||
}
|
||||
test.Results = nil
|
||||
for k, v := range compressed {
|
||||
test.Results = append(test.Results, testapi.TestResult{
|
||||
TestResultBase: k,
|
||||
Resources: v,
|
||||
})
|
||||
}
|
||||
}
|
||||
if save && needsSave {
|
||||
fmt.Printf(" Saving test file (%s)...", testCase.Path)
|
||||
fmt.Println()
|
||||
yamlBytes, err := yaml.Marshal(test)
|
||||
if err != nil {
|
||||
fmt.Printf(" ERROR: converting test to yaml: %s", err)
|
||||
fmt.Println()
|
||||
continue
|
||||
}
|
||||
if err := os.WriteFile(testCase.Path, yamlBytes, os.ModePerm); err != nil {
|
||||
fmt.Printf(" ERROR: saving test file (%s): %s", testCase.Path, err)
|
||||
fmt.Println()
|
||||
continue
|
||||
}
|
||||
fmt.Println(" OK")
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
fmt.Println("Done.")
|
||||
return nil
|
||||
cmd.SilenceUsage = true
|
||||
cmd.SilenceErrors = true
|
||||
return options.execute(args...)
|
||||
},
|
||||
}
|
||||
cmd.Flags().StringVarP(&fileName, "file-name", "f", "kyverno-test.yaml", "Test filename")
|
||||
cmd.Flags().BoolVar(&save, "save", false, "Save fixed file")
|
||||
cmd.Flags().BoolVar(&compress, "compress", false, "Compress test results")
|
||||
cmd.Flags().StringVarP(&options.fileName, "file-name", "f", "kyverno-test.yaml", "Test filename")
|
||||
cmd.Flags().BoolVar(&options.save, "save", false, "Save fixed file")
|
||||
cmd.Flags().BoolVar(&options.compress, "compress", false, "Compress test results")
|
||||
return cmd
|
||||
}
|
||||
|
|
120
cmd/cli/kubectl-kyverno/commands/fix/test/options.go
Normal file
120
cmd/cli/kubectl-kyverno/commands/fix/test/options.go
Normal file
|
@ -0,0 +1,120 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
testapi "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/apis/test"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/test"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
type options struct {
|
||||
fileName string
|
||||
save bool
|
||||
compress bool
|
||||
}
|
||||
|
||||
func (o options) validate() error {
|
||||
if o.fileName == "" {
|
||||
return errors.New("file-name must not be set to an empty string")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o options) execute(args ...string) error {
|
||||
var testCases []test.TestCase
|
||||
for _, arg := range args {
|
||||
tests, err := test.LoadTests(arg, o.fileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
testCases = append(testCases, tests...)
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
fmt.Printf("Processing test file (%s)...", testCase.Path)
|
||||
fmt.Println()
|
||||
if testCase.Err != nil {
|
||||
fmt.Printf(" ERROR: loading test file (%s): %s", testCase.Path, testCase.Err)
|
||||
fmt.Println()
|
||||
continue
|
||||
}
|
||||
test := testCase.Test
|
||||
needsSave := false
|
||||
if test.Name == "" {
|
||||
fmt.Println(" WARNING: name is not set")
|
||||
test.Name = filepath.Base(testCase.Path)
|
||||
needsSave = true
|
||||
}
|
||||
if len(test.Policies) == 0 {
|
||||
fmt.Println(" WARNING: test has no policies")
|
||||
}
|
||||
if len(test.Resources) == 0 {
|
||||
fmt.Println(" WARNING: test has no resources")
|
||||
}
|
||||
for i := range test.Results {
|
||||
result := &test.Results[i]
|
||||
if result.Resource != "" && len(result.Resources) != 0 {
|
||||
fmt.Println(" WARNING: test result should not use both `resource` and `resources` fields")
|
||||
}
|
||||
if result.Resource != "" {
|
||||
fmt.Println(" WARNING: test result uses deprecated `resource` field, moving it into the `resources` field")
|
||||
result.Resources = append(result.Resources, result.Resource)
|
||||
result.Resource = ""
|
||||
needsSave = true
|
||||
}
|
||||
if result.Namespace != "" {
|
||||
fmt.Println(" WARNING: test result uses deprecated `namespace` field, replacing `policy` with a `<namespace>/<name>` pattern")
|
||||
result.Policy = fmt.Sprintf("%s/%s", result.Namespace, result.Policy)
|
||||
result.Namespace = ""
|
||||
needsSave = true
|
||||
}
|
||||
if result.Status != "" && result.Result != "" {
|
||||
fmt.Println(" ERROR: test result should not use both `status` and `result` fields")
|
||||
}
|
||||
if result.Status != "" && result.Result == "" {
|
||||
fmt.Println(" WARNING: test result uses deprecated `status` field, moving it into the `result` field")
|
||||
result.Result = result.Status
|
||||
result.Status = ""
|
||||
needsSave = true
|
||||
}
|
||||
}
|
||||
if o.compress {
|
||||
compressed := map[testapi.TestResultBase][]string{}
|
||||
for _, result := range test.Results {
|
||||
compressed[result.TestResultBase] = append(compressed[result.TestResultBase], result.Resources...)
|
||||
}
|
||||
if len(compressed) != len(test.Results) {
|
||||
needsSave = true
|
||||
}
|
||||
test.Results = nil
|
||||
for k, v := range compressed {
|
||||
test.Results = append(test.Results, testapi.TestResult{
|
||||
TestResultBase: k,
|
||||
Resources: v,
|
||||
})
|
||||
}
|
||||
}
|
||||
if o.save && needsSave {
|
||||
fmt.Printf(" Saving test file (%s)...", testCase.Path)
|
||||
fmt.Println()
|
||||
yamlBytes, err := yaml.Marshal(test)
|
||||
if err != nil {
|
||||
fmt.Printf(" ERROR: converting test to yaml: %s", err)
|
||||
fmt.Println()
|
||||
continue
|
||||
}
|
||||
if err := os.WriteFile(testCase.Path, yamlBytes, os.ModePerm); err != nil {
|
||||
fmt.Printf(" ERROR: saving test file (%s): %s", testCase.Path, err)
|
||||
fmt.Println()
|
||||
continue
|
||||
}
|
||||
fmt.Println(" OK")
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
fmt.Println("Done.")
|
||||
return nil
|
||||
}
|
|
@ -13,7 +13,6 @@ import (
|
|||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/report"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/store"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/test/filter"
|
||||
sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
"github.com/kyverno/kyverno/pkg/openapi"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -32,14 +31,6 @@ func Command() *cobra.Command {
|
|||
Example: command.FormatExamples(examples...),
|
||||
RunE: func(cmd *cobra.Command, dirPath []string) (err error) {
|
||||
color.InitColors(removeColor)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if !sanitizederror.IsErrorSanitized(err) {
|
||||
log.Log.Error(err, "failed to sanitize")
|
||||
err = fmt.Errorf("internal error")
|
||||
}
|
||||
}
|
||||
}()
|
||||
store.SetRegistryAccess(registryAccess)
|
||||
return testCommandExecute(dirPath, fileName, gitBranch, testCase, failOnly, detailedResults)
|
||||
},
|
||||
|
@ -70,7 +61,7 @@ func testCommandExecute(
|
|||
) (err error) {
|
||||
// check input dir
|
||||
if len(dirPath) == 0 {
|
||||
return sanitizederror.NewWithError("a directory is required", err)
|
||||
return fmt.Errorf("a directory is required")
|
||||
}
|
||||
// parse filter
|
||||
filter, errors := filter.ParseFilter(testCase)
|
||||
|
@ -130,11 +121,11 @@ func testCommandExecute(
|
|||
resourcePath := filepath.Dir(test.Path)
|
||||
responses, err := runTest(openApiManager, test, false)
|
||||
if err != nil {
|
||||
return sanitizederror.NewWithError("failed to run test", err)
|
||||
return fmt.Errorf("failed to run test (%w)", err)
|
||||
}
|
||||
t, err := printTestResult(filteredResults, responses, rc, failOnly, detailedResults, test.Fs, resourcePath)
|
||||
if err != nil {
|
||||
return sanitizederror.NewWithError("failed to print test result:", err)
|
||||
return fmt.Errorf("failed to print test result (%w)", err)
|
||||
}
|
||||
table.AddFailed(t.RawRows...)
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
"github.com/go-git/go-billy/v5/memfs"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/source"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/test"
|
||||
sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError"
|
||||
gitutils "github.com/kyverno/kyverno/pkg/utils/git"
|
||||
)
|
||||
|
||||
|
@ -65,7 +64,7 @@ func loadTest(path string, fileName string, gitBranch string) (test.TestCases, e
|
|||
}
|
||||
yamlFiles, err := gitutils.ListYamls(fs, gitPathToYamls)
|
||||
if err != nil {
|
||||
return nil, sanitizederror.NewWithError("failed to list YAMLs in repository", err)
|
||||
return nil, fmt.Errorf("failed to list YAMLs in repository (%w)", err)
|
||||
}
|
||||
sort.Strings(yamlFiles)
|
||||
for _, yamlFilePath := range yamlFiles {
|
||||
|
|
|
@ -15,7 +15,6 @@ import (
|
|||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/userinfo"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/common"
|
||||
pathutils "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/path"
|
||||
sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/variables"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
"github.com/kyverno/kyverno/pkg/background/generate"
|
||||
|
@ -40,9 +39,7 @@ func runTest(openApiManager openapi.Manager, testCase test.TestCase, auditWarn b
|
|||
fmt.Println(" Loading values/variables", "...")
|
||||
vars, err := variables.New(testCase.Fs, testDir, testCase.Test.Variables, testCase.Test.Values)
|
||||
if err != nil {
|
||||
if !sanitizederror.IsErrorSanitized(err) {
|
||||
err = sanitizederror.NewWithError("failed to decode yaml", err)
|
||||
}
|
||||
err = fmt.Errorf("failed to decode yaml (%w)", err)
|
||||
return nil, err
|
||||
}
|
||||
// user info
|
||||
|
@ -157,8 +154,7 @@ func runTest(openApiManager openapi.Manager, testCase test.TestCase, auditWarn b
|
|||
}
|
||||
ers, err := processor.ApplyPoliciesOnResource()
|
||||
if err != nil {
|
||||
message := fmt.Sprintf("failed to apply policies on resource %v", resource.GetName())
|
||||
return nil, sanitizederror.NewWithError(message, err)
|
||||
return nil, fmt.Errorf("failed to apply policies on resource %v (%w)", resource.GetName(), err)
|
||||
}
|
||||
engineResponses = append(engineResponses, ers...)
|
||||
}
|
||||
|
@ -171,8 +167,7 @@ func runTest(openApiManager openapi.Manager, testCase test.TestCase, auditWarn b
|
|||
}
|
||||
ers, err := processor.ApplyPolicyOnResource()
|
||||
if err != nil {
|
||||
message := fmt.Sprintf("failed to apply policies on resource %s", resource.GetName())
|
||||
return nil, sanitizederror.NewWithError(message, err)
|
||||
return nil, fmt.Errorf("failed to apply policies on resource %s (%w)", resource.GetName(), err)
|
||||
}
|
||||
engineResponses = append(engineResponses, ers...)
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ import (
|
|||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/log"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/store"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/common"
|
||||
sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/variables"
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
|
@ -104,9 +103,7 @@ func (p *PolicyProcessor) ApplyPoliciesOnResource() ([]engineapi.EngineResponse,
|
|||
mutateResponse := eng.Mutate(context.Background(), policyContext)
|
||||
err = p.processMutateEngineResponse(mutateResponse, resPath)
|
||||
if err != nil {
|
||||
if !sanitizederror.IsErrorSanitized(err) {
|
||||
return responses, sanitizederror.NewWithError("failed to print mutated result", err)
|
||||
}
|
||||
return responses, fmt.Errorf("failed to print mutated result (%w)", err)
|
||||
}
|
||||
responses = append(responses, mutateResponse)
|
||||
resource = mutateResponse.PatchedResource
|
||||
|
@ -199,12 +196,11 @@ func (p *PolicyProcessor) makePolicyContext(
|
|||
kindOnwhichPolicyIsApplied := common.GetKindsFromPolicy(policy, p.Variables.Subresources(), p.Client)
|
||||
vals, err := p.Variables.ComputeVariables(policy.GetName(), resource.GetName(), resource.GetKind(), kindOnwhichPolicyIsApplied /*matches...*/)
|
||||
if err != nil {
|
||||
message := fmt.Sprintf(
|
||||
"policy `%s` have variables. pass the values for the variables for resource `%s` using set/values_file flag",
|
||||
return nil, fmt.Errorf("policy `%s` have variables. pass the values for the variables for resource `%s` using set/values_file flag (%w)",
|
||||
policy.GetName(),
|
||||
resource.GetName(),
|
||||
err,
|
||||
)
|
||||
return nil, sanitizederror.NewWithError(message, err)
|
||||
}
|
||||
resourceValues = vals
|
||||
}
|
||||
|
@ -239,7 +235,7 @@ func (p *PolicyProcessor) processMutateEngineResponse(response engineapi.EngineR
|
|||
if printMutatedRes && p.PrintPatchResource {
|
||||
yamlEncodedResource, err := yamlv2.Marshal(response.PatchedResource.Object)
|
||||
if err != nil {
|
||||
return sanitizederror.NewWithError("failed to marshal", err)
|
||||
return fmt.Errorf("failed to marshal (%w)", err)
|
||||
}
|
||||
|
||||
if p.MutateLogPath == "" {
|
||||
|
@ -253,7 +249,7 @@ func (p *PolicyProcessor) processMutateEngineResponse(response engineapi.EngineR
|
|||
} else {
|
||||
err := p.printMutatedOutput(string(yamlEncodedResource))
|
||||
if err != nil {
|
||||
return sanitizederror.NewWithError("failed to print mutated result", err)
|
||||
return fmt.Errorf("failed to print mutated result (%w)", err)
|
||||
}
|
||||
fmt.Printf("\n\nMutation:\nMutation has been applied successfully. Check the files.")
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
|
||||
"github.com/go-git/go-billy/v5"
|
||||
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
|
@ -26,7 +25,7 @@ func load(fs billy.Filesystem, path string, resourcePath string) ([]byte, error)
|
|||
} else {
|
||||
bytes, err := os.ReadFile(filepath.Clean(filepath.Join(resourcePath, path)))
|
||||
if err != nil {
|
||||
return nil, sanitizederror.NewWithError("unable to read yaml", err)
|
||||
return nil, fmt.Errorf("unable to read yaml (%w)", err)
|
||||
}
|
||||
return bytes, err
|
||||
}
|
||||
|
@ -35,11 +34,11 @@ func load(fs billy.Filesystem, path string, resourcePath string) ([]byte, error)
|
|||
func Load(fs billy.Filesystem, path string, resourcePath string) (*kyvernov1beta1.RequestInfo, error) {
|
||||
bytes, err := load(fs, path, resourcePath)
|
||||
if err != nil {
|
||||
return nil, sanitizederror.NewWithError("unable to read yaml", err)
|
||||
return nil, fmt.Errorf("unable to read yaml (%w)", err)
|
||||
}
|
||||
var userInfo kyvernov1beta1.RequestInfo
|
||||
if err := yaml.UnmarshalStrict(bytes, &userInfo); err != nil {
|
||||
return nil, sanitizederror.NewWithError("failed to decode yaml", err)
|
||||
return nil, fmt.Errorf("failed to decode yaml (%w)", err)
|
||||
}
|
||||
return &userInfo, nil
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
valuesapi "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/apis/values"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/resource"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/source"
|
||||
sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||
|
@ -38,7 +37,7 @@ func GetResourceAccordingToResourcePath(
|
|||
if fs != nil {
|
||||
resources, err = GetResourcesWithTest(fs, policies, resourcePaths, policyResourcePath)
|
||||
if err != nil {
|
||||
return nil, sanitizederror.NewWithError("failed to extract the resources", err)
|
||||
return nil, fmt.Errorf("failed to extract the resources (%w)", err)
|
||||
}
|
||||
} else {
|
||||
if len(resourcePaths) > 0 && resourcePaths[0] == "-" {
|
||||
|
@ -52,7 +51,7 @@ func GetResourceAccordingToResourcePath(
|
|||
yamlBytes := []byte(resourceStr)
|
||||
resources, err = resource.GetUnstructuredResources(yamlBytes)
|
||||
if err != nil {
|
||||
return nil, sanitizederror.NewWithError("failed to extract the resources", err)
|
||||
return nil, fmt.Errorf("failed to extract the resources (%w)", err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -64,7 +63,7 @@ func GetResourceAccordingToResourcePath(
|
|||
if fileDesc.IsDir() {
|
||||
files, err := os.ReadDir(resourcePaths[0])
|
||||
if err != nil {
|
||||
return nil, sanitizederror.NewWithError(fmt.Sprintf("failed to parse %v", resourcePaths[0]), err)
|
||||
return nil, fmt.Errorf("failed to parse %v (%w)", resourcePaths[0], err)
|
||||
}
|
||||
listOfFiles := make([]string, 0)
|
||||
for _, file := range files {
|
||||
|
@ -145,7 +144,7 @@ func getSubresourceKind(groupVersion, parentKind, subresourceName string, subres
|
|||
}
|
||||
}
|
||||
}
|
||||
return "", sanitizederror.NewWithError(fmt.Sprintf("subresource %s not found for parent resource %s", subresourceName, parentKind), nil)
|
||||
return "", fmt.Errorf("subresource %s not found for parent resource %s", subresourceName, parentKind)
|
||||
}
|
||||
|
||||
func GetGitBranchOrPolicyPaths(gitBranch, repoURL string, policyPaths ...string) (string, string) {
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
package sanitizederror
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type customError struct {
|
||||
message string
|
||||
}
|
||||
|
||||
func (c customError) Error() string {
|
||||
return c.message
|
||||
}
|
||||
|
||||
func New(msg string) error {
|
||||
return customError{message: msg}
|
||||
}
|
||||
|
||||
func NewWithErrors(message string, errors []error) error {
|
||||
bldr := strings.Builder{}
|
||||
bldr.WriteString(message + "\n")
|
||||
for _, err := range errors {
|
||||
bldr.WriteString(err.Error() + "\n")
|
||||
}
|
||||
|
||||
return customError{message: bldr.String()}
|
||||
}
|
||||
|
||||
// NewWithError creates a new sanitized error with given message and error
|
||||
func NewWithError(message string, err error) error {
|
||||
if err == nil {
|
||||
return customError{message: message}
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("%s \nCause: %s", message, err.Error())
|
||||
return customError{message: msg}
|
||||
}
|
||||
|
||||
// IsErrorSanitized checks if the error is sanitized error
|
||||
func IsErrorSanitized(err error) bool {
|
||||
if _, ok := err.(customError); !ok {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
|
@ -6,7 +6,6 @@ import (
|
|||
|
||||
"github.com/go-git/go-billy/v5"
|
||||
valuesapi "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/apis/values"
|
||||
sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/values"
|
||||
)
|
||||
|
||||
|
@ -15,7 +14,7 @@ func New(fs billy.Filesystem, resourcePath string, path string, vals *valuesapi.
|
|||
if vals == nil && path != "" {
|
||||
v, err := values.Load(fs, filepath.Join(resourcePath, path))
|
||||
if err != nil {
|
||||
return nil, sanitizederror.NewWithError("unable to read yaml", fmt.Errorf("Unable to load variable file: %s (%w)", path, err))
|
||||
return nil, fmt.Errorf("Unable to load variable file: %s (%w)", path, err)
|
||||
}
|
||||
vals = v
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue