package exception import ( "fmt" "os" "path/filepath" kyvernov2 "github.com/kyverno/kyverno/api/kyverno/v2" kyvernov2beta1 "github.com/kyverno/kyverno/api/kyverno/v2beta1" policiesv1alpha1 "github.com/kyverno/kyverno/api/policies.kyverno.io/v1alpha1" "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/data" "github.com/kyverno/kyverno/ext/resource/convert" resourceloader "github.com/kyverno/kyverno/ext/resource/loader" yamlutils "github.com/kyverno/kyverno/ext/yaml" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" "sigs.k8s.io/kubectl-validate/pkg/openapiclient" ) var ( exceptionV2beta1 = schema.GroupVersion(kyvernov2beta1.GroupVersion).WithKind("PolicyException") exceptionV2 = schema.GroupVersion(kyvernov2.GroupVersion).WithKind("PolicyException") celExceptionV1alpha1 = schema.GroupVersion(policiesv1alpha1.GroupVersion).WithKind("CELPolicyException") ) type LoaderResults struct { Exceptions []*kyvernov2.PolicyException CELExceptions []*policiesv1alpha1.CELPolicyException } func Load(paths ...string) (*LoaderResults, error) { loaderResults := &LoaderResults{} for _, path := range paths { bytes, err := os.ReadFile(filepath.Clean(path)) if err != nil { return nil, fmt.Errorf("unable to read yaml (%w)", err) } results, err := load(bytes) if err != nil { return nil, fmt.Errorf("unable to load exceptions (%w)", err) } loaderResults.Exceptions = append(loaderResults.Exceptions, results.Exceptions...) loaderResults.CELExceptions = append(loaderResults.CELExceptions, results.CELExceptions...) } return loaderResults, nil } func load(content []byte) (*LoaderResults, error) { results := &LoaderResults{} documents, err := yamlutils.SplitDocuments(content) if err != nil { return nil, err } crds, err := data.Crds() if err != nil { return nil, err } factory, err := resourceloader.New(openapiclient.NewComposite(openapiclient.NewLocalCRDFiles(crds))) if err != nil { return nil, err } for _, document := range documents { gvk, untyped, err := factory.Load(document) if err != nil { return nil, err } switch gvk { case exceptionV2beta1, exceptionV2: exception, err := convert.To[kyvernov2.PolicyException](untyped) if err != nil { return nil, err } results.Exceptions = append(results.Exceptions, exception) case celExceptionV1alpha1: exception, err := convert.To[policiesv1alpha1.CELPolicyException](untyped) if err != nil { return nil, err } results.CELExceptions = append(results.CELExceptions, exception) default: return nil, fmt.Errorf("policy exception type not supported %s", gvk) } } return results, nil } func SelectFrom(resources []*unstructured.Unstructured) []*kyvernov2.PolicyException { var exceptions []*kyvernov2.PolicyException for _, resource := range resources { switch resource.GroupVersionKind() { case exceptionV2beta1, exceptionV2: exception, err := convert.To[kyvernov2.PolicyException](*resource) if err == nil { exceptions = append(exceptions, exception) } } } return exceptions }