mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-28 18:38:40 +00:00
fix policy command (#8404)
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
parent
e43b78c6c7
commit
a5e6a7fa33
10 changed files with 475 additions and 53 deletions
|
@ -2,6 +2,7 @@ package fix
|
|||
|
||||
import (
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/command"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/commands/fix/policy"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/commands/fix/test"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
@ -19,6 +20,7 @@ func Command() *cobra.Command {
|
|||
},
|
||||
}
|
||||
cmd.AddCommand(
|
||||
policy.Command(),
|
||||
test.Command(),
|
||||
)
|
||||
return cmd
|
||||
|
|
26
cmd/cli/kubectl-kyverno/commands/fix/policy/command.go
Normal file
26
cmd/cli/kubectl-kyverno/commands/fix/policy/command.go
Normal file
|
@ -0,0 +1,26 @@
|
|||
package policy
|
||||
|
||||
import (
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/command"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func Command() *cobra.Command {
|
||||
var options options
|
||||
cmd := &cobra.Command{
|
||||
Use: "policy [dir]...",
|
||||
Short: command.FormatDescription(true, websiteUrl, true, description...),
|
||||
Long: command.FormatDescription(false, websiteUrl, true, description...),
|
||||
Example: command.FormatExamples(examples...),
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := options.validate(args...); err != nil {
|
||||
return err
|
||||
}
|
||||
return options.execute(cmd.OutOrStdout(), args...)
|
||||
},
|
||||
}
|
||||
cmd.Flags().BoolVar(&options.save, "save", false, "Save fixed file")
|
||||
return cmd
|
||||
}
|
65
cmd/cli/kubectl-kyverno/commands/fix/policy/command_test.go
Normal file
65
cmd/cli/kubectl-kyverno/commands/fix/policy/command_test.go
Normal file
|
@ -0,0 +1,65 @@
|
|||
package policy
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCommand(t *testing.T) {
|
||||
cmd := Command()
|
||||
assert.NotNil(t, cmd)
|
||||
err := cmd.Execute()
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestCommandInvalidFileName(t *testing.T) {
|
||||
cmd := Command()
|
||||
assert.NotNil(t, cmd)
|
||||
cmd.SetArgs([]string{"foo", "-f", ""})
|
||||
err := cmd.Execute()
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestCommandWithInvalidArg(t *testing.T) {
|
||||
cmd := Command()
|
||||
assert.NotNil(t, cmd)
|
||||
b := bytes.NewBufferString("")
|
||||
cmd.SetErr(b)
|
||||
err := cmd.Execute()
|
||||
assert.Error(t, err)
|
||||
out, err := io.ReadAll(b)
|
||||
assert.NoError(t, err)
|
||||
expected := `Error: requires at least 1 arg(s), only received 0`
|
||||
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(out)))
|
||||
}
|
||||
|
||||
func TestCommandWithInvalidFlag(t *testing.T) {
|
||||
cmd := Command()
|
||||
assert.NotNil(t, cmd)
|
||||
b := bytes.NewBufferString("")
|
||||
cmd.SetErr(b)
|
||||
cmd.SetArgs([]string{"--xxx"})
|
||||
err := cmd.Execute()
|
||||
assert.Error(t, err)
|
||||
out, err := io.ReadAll(b)
|
||||
assert.NoError(t, err)
|
||||
expected := `Error: unknown flag: --xxx`
|
||||
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(out)))
|
||||
}
|
||||
|
||||
func TestCommandHelp(t *testing.T) {
|
||||
cmd := Command()
|
||||
assert.NotNil(t, cmd)
|
||||
b := bytes.NewBufferString("")
|
||||
cmd.SetOut(b)
|
||||
cmd.SetArgs([]string{"--help"})
|
||||
err := cmd.Execute()
|
||||
assert.NoError(t, err)
|
||||
out, err := io.ReadAll(b)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, strings.HasPrefix(string(out), cmd.Long))
|
||||
}
|
19
cmd/cli/kubectl-kyverno/commands/fix/policy/doc.go
Normal file
19
cmd/cli/kubectl-kyverno/commands/fix/policy/doc.go
Normal file
|
@ -0,0 +1,19 @@
|
|||
package policy
|
||||
|
||||
// TODO
|
||||
var websiteUrl = ``
|
||||
|
||||
var description = []string{
|
||||
`Fix inconsistencies and deprecated usage in Kyverno policy files.`,
|
||||
}
|
||||
|
||||
var examples = [][]string{
|
||||
{
|
||||
`# Fix Kyverno policy files`,
|
||||
`KYVERNO_EXPERIMENTAL=true kyverno fix policy .`,
|
||||
},
|
||||
{
|
||||
`# Fix Kyverno policy files and save them back`,
|
||||
`KYVERNO_EXPERIMENTAL=true kyverno fix policy . --save`,
|
||||
},
|
||||
}
|
161
cmd/cli/kubectl-kyverno/commands/fix/policy/options.go
Normal file
161
cmd/cli/kubectl-kyverno/commands/fix/policy/options.go
Normal file
|
@ -0,0 +1,161 @@
|
|||
package policy
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/fix"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/policy"
|
||||
gitutils "github.com/kyverno/kyverno/pkg/utils/git"
|
||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
type options struct {
|
||||
save bool
|
||||
}
|
||||
|
||||
func (o options) validate(dirs ...string) error {
|
||||
if len(dirs) == 0 {
|
||||
return errors.New("at least one directory is required")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func find(path string) ([]string, error) {
|
||||
var files []string
|
||||
err := filepath.Walk(path, func(file string, info fs.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if gitutils.IsYaml(info) {
|
||||
files = append(files, file)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func (o options) execute(out io.Writer, dirs ...string) error {
|
||||
for _, dir := range dirs {
|
||||
files, err := find(dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, file := range files {
|
||||
o.processFile(out, file)
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(out, "Done.")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o options) processFile(out io.Writer, path string) {
|
||||
policies, vaps, err := policy.LoadWithLoader(policy.KubectlValidateLoader, nil, "", path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(policies) == 0 {
|
||||
return
|
||||
}
|
||||
var fixed []kyvernov1.PolicyInterface
|
||||
for _, policy := range policies {
|
||||
copy := policy.CreateDeepCopy()
|
||||
fmt.Fprintf(out, "Processing file (%s)...\n", path)
|
||||
messages, err := fix.FixPolicy(copy)
|
||||
for _, warning := range messages {
|
||||
fmt.Fprintln(out, " WARNING:", warning)
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Fprintln(out, " ERROR:", err)
|
||||
return
|
||||
}
|
||||
fixed = append(fixed, copy)
|
||||
}
|
||||
needsSave := !reflect.DeepEqual(policies, fixed)
|
||||
if o.save && needsSave {
|
||||
fmt.Fprintf(out, " Saving file (%s)...", path)
|
||||
fmt.Fprintln(out)
|
||||
var yamlBytes []byte
|
||||
for _, policy := range fixed {
|
||||
untyped, err := kubeutils.ObjToUnstructured(policy)
|
||||
if err != nil {
|
||||
fmt.Fprintf(out, " ERROR: converting to yaml: %s", err)
|
||||
fmt.Fprintln(out)
|
||||
return
|
||||
}
|
||||
// prune some fields
|
||||
unstructured.RemoveNestedField(untyped.UnstructuredContent(), "status")
|
||||
unstructured.RemoveNestedField(untyped.UnstructuredContent(), "metadata", "creationTimestamp")
|
||||
unstructured.RemoveNestedField(untyped.UnstructuredContent(), "metadata", "generation")
|
||||
unstructured.RemoveNestedField(untyped.UnstructuredContent(), "metadata", "uid")
|
||||
rules, ok, err := unstructured.NestedFieldNoCopy(untyped.UnstructuredContent(), "spec", "rules")
|
||||
if !ok || err != nil {
|
||||
return
|
||||
}
|
||||
for _, rule := range rules.([]interface{}) {
|
||||
rule := rule.(map[string]interface{})
|
||||
unstructured.RemoveNestedField(rule, "exclude", "resources")
|
||||
unstructured.RemoveNestedField(rule, "match", "resources")
|
||||
if item, _, _ := unstructured.NestedMap(rule, "generate", "clone"); len(item) == 0 {
|
||||
unstructured.RemoveNestedField(rule, "generate", "clone")
|
||||
}
|
||||
if item, _, _ := unstructured.NestedMap(rule, "generate", "cloneList"); len(item) == 0 {
|
||||
unstructured.RemoveNestedField(rule, "generate", "cloneList")
|
||||
}
|
||||
if item, _, _ := unstructured.NestedMap(rule, "generate"); len(item) == 0 {
|
||||
unstructured.RemoveNestedField(rule, "generate")
|
||||
}
|
||||
if item, _, _ := unstructured.NestedMap(rule, "mutate"); len(item) == 0 {
|
||||
unstructured.RemoveNestedField(rule, "mutate")
|
||||
}
|
||||
if item, _, _ := unstructured.NestedMap(rule, "exclude"); len(item) == 0 {
|
||||
unstructured.RemoveNestedField(rule, "exclude")
|
||||
}
|
||||
if item, _, _ := unstructured.NestedMap(rule, "match"); len(item) == 0 {
|
||||
unstructured.RemoveNestedField(rule, "match")
|
||||
}
|
||||
}
|
||||
jsonBytes, err := untyped.MarshalJSON()
|
||||
if err != nil {
|
||||
fmt.Fprintf(out, " ERROR: converting to yaml: %s", err)
|
||||
fmt.Fprintln(out)
|
||||
return
|
||||
}
|
||||
finalBytes, err := yaml.JSONToYAML(jsonBytes)
|
||||
if err != nil {
|
||||
fmt.Fprintf(out, " ERROR: converting to yaml: %s", err)
|
||||
fmt.Fprintln(out)
|
||||
return
|
||||
}
|
||||
yamlBytes = append(yamlBytes, []byte("---\n")...)
|
||||
yamlBytes = append(yamlBytes, finalBytes...)
|
||||
}
|
||||
for _, vap := range vaps {
|
||||
finalBytes, err := yaml.Marshal(vap)
|
||||
if err != nil {
|
||||
fmt.Fprintf(out, " ERROR: converting to yaml: %s", err)
|
||||
fmt.Fprintln(out)
|
||||
return
|
||||
}
|
||||
yamlBytes = append(yamlBytes, []byte("---\n")...)
|
||||
yamlBytes = append(yamlBytes, finalBytes...)
|
||||
}
|
||||
if err := os.WriteFile(path, yamlBytes, os.ModePerm); err != nil {
|
||||
fmt.Fprintf(out, " ERROR: saving file (%s): %s", path, err)
|
||||
fmt.Fprintln(out)
|
||||
return
|
||||
}
|
||||
fmt.Fprintln(out, " OK")
|
||||
}
|
||||
}
|
82
cmd/cli/kubectl-kyverno/fix/policy.go
Normal file
82
cmd/cli/kubectl-kyverno/fix/policy.go
Normal file
|
@ -0,0 +1,82 @@
|
|||
package fix
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
apiutils "github.com/kyverno/kyverno/pkg/utils/api"
|
||||
)
|
||||
|
||||
func FixPolicy(policy kyvernov1.PolicyInterface) ([]string, error) {
|
||||
var messages []string
|
||||
spec := policy.GetSpec()
|
||||
if spec.ValidationFailureAction.Enforce() {
|
||||
spec.ValidationFailureAction = kyvernov1.Enforce
|
||||
} else {
|
||||
spec.ValidationFailureAction = kyvernov1.Audit
|
||||
}
|
||||
for i := range spec.Rules {
|
||||
rule := &spec.Rules[i]
|
||||
if !reflect.DeepEqual(rule.MatchResources.ResourceDescription, kyvernov1.ResourceDescription{}) || !reflect.DeepEqual(rule.MatchResources.UserInfo, kyvernov1.UserInfo{}) {
|
||||
messages = append(messages, "match uses old syntax, moving to any")
|
||||
rule.MatchResources.Any = append(rule.MatchResources.Any, kyvernov1.ResourceFilter{
|
||||
ResourceDescription: rule.MatchResources.ResourceDescription,
|
||||
UserInfo: rule.MatchResources.UserInfo,
|
||||
})
|
||||
rule.MatchResources.ResourceDescription = kyvernov1.ResourceDescription{}
|
||||
rule.MatchResources.UserInfo = kyvernov1.UserInfo{}
|
||||
}
|
||||
if !reflect.DeepEqual(rule.ExcludeResources.ResourceDescription, kyvernov1.ResourceDescription{}) || !reflect.DeepEqual(rule.ExcludeResources.UserInfo, kyvernov1.UserInfo{}) {
|
||||
messages = append(messages, "exclude uses old syntax, moving to any")
|
||||
rule.ExcludeResources.Any = append(rule.ExcludeResources.Any, kyvernov1.ResourceFilter{
|
||||
ResourceDescription: rule.ExcludeResources.ResourceDescription,
|
||||
UserInfo: rule.ExcludeResources.UserInfo,
|
||||
})
|
||||
rule.ExcludeResources.ResourceDescription = kyvernov1.ResourceDescription{}
|
||||
rule.ExcludeResources.UserInfo = kyvernov1.UserInfo{}
|
||||
}
|
||||
preconditions := rule.GetAnyAllConditions()
|
||||
if preconditions != nil {
|
||||
cond, err := apiutils.ApiextensionsJsonToKyvernoConditions(preconditions)
|
||||
if err != nil {
|
||||
return messages, err
|
||||
}
|
||||
var newCond *kyvernov1.AnyAllConditions
|
||||
switch typedValue := cond.(type) {
|
||||
case kyvernov1.AnyAllConditions:
|
||||
newCond = &typedValue
|
||||
case []kyvernov1.Condition: // backwards compatibility
|
||||
newCond = &kyvernov1.AnyAllConditions{
|
||||
AllConditions: typedValue,
|
||||
}
|
||||
default:
|
||||
return messages, fmt.Errorf("unknown preconditions type: %T", typedValue)
|
||||
}
|
||||
fixCondition := func(c *kyvernov1.Condition) {
|
||||
switch c.Operator {
|
||||
case "Equal":
|
||||
messages = append(messages, "condition uses old operator `Equal`, updating")
|
||||
c.Operator = "Equals"
|
||||
case "NotEqual":
|
||||
messages = append(messages, "condition uses old operator `NotEqual`, updating")
|
||||
c.Operator = "NotEquals"
|
||||
case "In":
|
||||
messages = append(messages, "condition uses old operator `In`, updating")
|
||||
c.Operator = "AllIn"
|
||||
case "NotIn":
|
||||
messages = append(messages, "condition uses old operator `NotIn`, updating")
|
||||
c.Operator = "AnyNotIn"
|
||||
}
|
||||
}
|
||||
for c := range newCond.AnyConditions {
|
||||
fixCondition(&newCond.AnyConditions[c])
|
||||
}
|
||||
for c := range newCond.AllConditions {
|
||||
fixCondition(&newCond.AllConditions[c])
|
||||
}
|
||||
rule.SetAnyAllConditions(newCond)
|
||||
}
|
||||
}
|
||||
return messages, nil
|
||||
}
|
|
@ -32,15 +32,67 @@ var (
|
|||
clusterPolicyV2 = schema.GroupVersion(kyvernov2beta1.GroupVersion).WithKind("ClusterPolicy")
|
||||
vapV1 = v1alpha1.SchemeGroupVersion.WithKind("ValidatingAdmissionPolicy")
|
||||
client = openapiclient.NewComposite(
|
||||
openapiclient.NewHardcodedBuiltins("1.27"),
|
||||
openapiclient.NewHardcodedBuiltins("1.28"),
|
||||
openapiclient.NewLocalCRDFiles(data.Crds(), data.CrdsFolder),
|
||||
)
|
||||
LegacyLoader = yamlutils.GetPolicy
|
||||
KubectlValidateLoader = kubectlValidateLoader
|
||||
defaultLoader = func(bytes []byte) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
if experimental.UseKubectlValidate() {
|
||||
return KubectlValidateLoader(bytes)
|
||||
} else {
|
||||
return LegacyLoader(bytes)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
func getPolicies(bytes []byte) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
if !experimental.UseKubectlValidate() {
|
||||
return yamlutils.GetPolicy(bytes)
|
||||
type loader = func([]byte) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error)
|
||||
|
||||
func Load(fs billy.Filesystem, resourcePath string, paths ...string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
return LoadWithLoader(nil, fs, resourcePath, paths...)
|
||||
}
|
||||
|
||||
func LoadWithLoader(loader loader, fs billy.Filesystem, resourcePath string, paths ...string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
if loader == nil {
|
||||
loader = defaultLoader
|
||||
}
|
||||
var pols []kyvernov1.PolicyInterface
|
||||
var vaps []v1alpha1.ValidatingAdmissionPolicy
|
||||
for _, path := range paths {
|
||||
if source.IsStdin(path) {
|
||||
p, v, err := stdinLoad(loader)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
pols = append(pols, p...)
|
||||
vaps = append(vaps, v...)
|
||||
} else if fs != nil {
|
||||
p, v, err := gitLoad(loader, fs, filepath.Join(resourcePath, path))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
pols = append(pols, p...)
|
||||
vaps = append(vaps, v...)
|
||||
} else if source.IsHttp(path) {
|
||||
p, v, err := httpLoad(loader, path)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
pols = append(pols, p...)
|
||||
vaps = append(vaps, v...)
|
||||
} else {
|
||||
p, v, err := fsLoad(loader, path)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
pols = append(pols, p...)
|
||||
vaps = append(vaps, v...)
|
||||
}
|
||||
}
|
||||
return pols, vaps, nil
|
||||
}
|
||||
|
||||
func kubectlValidateLoader(bytes []byte) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
var policies []kyvernov1.PolicyInterface
|
||||
var validatingAdmissionPolicies []v1alpha1.ValidatingAdmissionPolicy
|
||||
documents, err := yamlutils.SplitDocuments(bytes)
|
||||
|
@ -81,44 +133,7 @@ func getPolicies(bytes []byte) ([]kyvernov1.PolicyInterface, []v1alpha1.Validati
|
|||
return policies, validatingAdmissionPolicies, nil
|
||||
}
|
||||
|
||||
func Load(fs billy.Filesystem, resourcePath string, paths ...string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
var pols []kyvernov1.PolicyInterface
|
||||
var vaps []v1alpha1.ValidatingAdmissionPolicy
|
||||
for _, path := range paths {
|
||||
if source.IsStdin(path) {
|
||||
p, v, err := stdinLoad()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
pols = append(pols, p...)
|
||||
vaps = append(vaps, v...)
|
||||
} else if fs != nil {
|
||||
p, v, err := gitLoad(fs, filepath.Join(resourcePath, path))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
pols = append(pols, p...)
|
||||
vaps = append(vaps, v...)
|
||||
} else if source.IsHttp(path) {
|
||||
p, v, err := httpLoad(path)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
pols = append(pols, p...)
|
||||
vaps = append(vaps, v...)
|
||||
} else {
|
||||
p, v, err := fsLoad(path)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
pols = append(pols, p...)
|
||||
vaps = append(vaps, v...)
|
||||
}
|
||||
}
|
||||
return pols, vaps, nil
|
||||
}
|
||||
|
||||
func fsLoad(path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
func fsLoad(loader loader, path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
var pols []kyvernov1.PolicyInterface
|
||||
var vaps []v1alpha1.ValidatingAdmissionPolicy
|
||||
fi, err := os.Stat(filepath.Clean(path))
|
||||
|
@ -131,7 +146,7 @@ func fsLoad(path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmi
|
|||
return nil, nil, err
|
||||
}
|
||||
for _, file := range files {
|
||||
p, v, err := fsLoad(filepath.Join(path, file.Name()))
|
||||
p, v, err := fsLoad(loader, filepath.Join(path, file.Name()))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -143,7 +158,7 @@ func fsLoad(path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmi
|
|||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
p, v, err := getPolicies(fileBytes)
|
||||
p, v, err := loader(fileBytes)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -153,7 +168,7 @@ func fsLoad(path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmi
|
|||
return pols, vaps, nil
|
||||
}
|
||||
|
||||
func httpLoad(path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
func httpLoad(loader loader, path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
// We accept here that a random URL might be called based on user provided input.
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, path, nil)
|
||||
if err != nil {
|
||||
|
@ -171,10 +186,10 @@ func httpLoad(path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAd
|
|||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to process %v: %v", path, err)
|
||||
}
|
||||
return getPolicies(fileBytes)
|
||||
return loader(fileBytes)
|
||||
}
|
||||
|
||||
func gitLoad(fs billy.Filesystem, path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
func gitLoad(loader loader, fs billy.Filesystem, path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
file, err := fs.Open(path)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -183,14 +198,14 @@ func gitLoad(fs billy.Filesystem, path string) ([]kyvernov1.PolicyInterface, []v
|
|||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return getPolicies(fileBytes)
|
||||
return loader(fileBytes)
|
||||
}
|
||||
|
||||
func stdinLoad() ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
func stdinLoad(loader loader) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
policyStr := ""
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
for scanner.Scan() {
|
||||
policyStr = policyStr + scanner.Text() + "\n"
|
||||
}
|
||||
return getPolicies([]byte(policyStr))
|
||||
return loader([]byte(policyStr))
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
|
||||
"github.com/go-git/go-billy/v5"
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/experimental"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"k8s.io/api/admissionregistration/v1alpha1"
|
||||
)
|
||||
|
@ -88,8 +87,7 @@ func TestLoadWithKubectlValidate(t *testing.T) {
|
|||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Setenv(experimental.KubectlValidateEnv, "true")
|
||||
policies, vaps, err := Load(tt.fs, tt.resourcePath, tt.paths...)
|
||||
policies, vaps, err := LoadWithLoader(KubectlValidateLoader, tt.fs, tt.resourcePath, tt.paths...)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Load() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
|
|
|
@ -49,5 +49,6 @@ kyverno fix [flags]
|
|||
### SEE ALSO
|
||||
|
||||
* [kyverno](kyverno.md) - Kubernetes Native Policy Management.
|
||||
* [kyverno fix policy](kyverno_fix_policy.md) - Fix inconsistencies and deprecated usage in Kyverno policy files.
|
||||
* [kyverno fix test](kyverno_fix_test.md) - Fix inconsistencies and deprecated usage in Kyverno test files.
|
||||
|
||||
|
|
53
docs/user/cli/kyverno_fix_policy.md
Normal file
53
docs/user/cli/kyverno_fix_policy.md
Normal file
|
@ -0,0 +1,53 @@
|
|||
## kyverno fix policy
|
||||
|
||||
Fix inconsistencies and deprecated usage in Kyverno policy files.
|
||||
|
||||
### Synopsis
|
||||
|
||||
Fix inconsistencies and deprecated usage in Kyverno policy files.
|
||||
|
||||
NOTE: This is an experimental command, use `KYVERNO_EXPERIMENTAL=true` to enable it.
|
||||
|
||||
```
|
||||
kyverno fix policy [dir]... [flags]
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
```
|
||||
# Fix Kyverno policy files
|
||||
KYVERNO_EXPERIMENTAL=true kyverno fix policy .
|
||||
|
||||
# Fix Kyverno policy files and save them back
|
||||
KYVERNO_EXPERIMENTAL=true kyverno fix policy . --save
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
-h, --help help for policy
|
||||
--save Save fixed file
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--add_dir_header If true, adds the file directory to the header of the log messages
|
||||
--alsologtostderr log to standard error as well as files (no effect when -logtostderr=true)
|
||||
--log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
|
||||
--log_dir string If non-empty, write log files in this directory (no effect when -logtostderr=true)
|
||||
--log_file string If non-empty, use this log file (no effect when -logtostderr=true)
|
||||
--log_file_max_size uint Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
|
||||
--logtostderr log to standard error instead of files (default true)
|
||||
--one_output If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true)
|
||||
--skip_headers If true, avoid header prefixes in the log messages
|
||||
--skip_log_headers If true, avoid headers when opening log files (no effect when -logtostderr=true)
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false) (default 2)
|
||||
-v, --v Level number for the log level verbosity
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
|
||||
* [kyverno fix](kyverno_fix.md) - Fix inconsistencies and deprecated usage of Kyverno resources.
|
||||
|
Loading…
Add table
Reference in a new issue