2020-01-07 10:33:28 -08:00
package generate
import (
2022-11-29 14:59:40 +01:00
"context"
2020-02-04 12:13:41 -08:00
"encoding/json"
2024-08-14 22:32:49 +08:00
"errors"
2020-01-07 10:33:28 -08:00
"fmt"
2023-09-19 14:06:53 +02:00
"slices"
2020-12-08 01:34:46 +05:30
"strings"
2020-10-07 11:12:31 -07:00
"time"
2022-04-25 20:20:40 +08:00
"github.com/go-logr/logr"
2024-08-19 14:55:19 +08:00
gojmespath "github.com/kyverno/go-jmespath"
2022-05-17 13:12:43 +02:00
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
2024-06-20 11:44:43 +02:00
kyvernov2 "github.com/kyverno/kyverno/api/kyverno/v2"
2022-04-13 18:15:04 +05:30
"github.com/kyverno/kyverno/pkg/background/common"
2024-10-02 17:35:05 +05:30
"github.com/kyverno/kyverno/pkg/breaker"
2022-09-07 06:01:43 +02:00
"github.com/kyverno/kyverno/pkg/client/clientset/versioned"
2022-05-18 06:02:31 +02:00
kyvernov1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
2024-06-20 11:44:43 +02:00
kyvernov2listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v2"
2022-08-31 14:03:47 +08:00
"github.com/kyverno/kyverno/pkg/clients/dclient"
2020-10-07 11:12:31 -07:00
"github.com/kyverno/kyverno/pkg/config"
"github.com/kyverno/kyverno/pkg/engine"
2023-01-30 12:41:09 +01:00
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
2023-04-13 13:29:40 +02:00
"github.com/kyverno/kyverno/pkg/engine/jmespath"
2024-01-09 17:30:31 +08:00
regex "github.com/kyverno/kyverno/pkg/engine/variables/regex"
2022-04-25 20:20:40 +08:00
"github.com/kyverno/kyverno/pkg/event"
2023-03-11 01:17:10 +08:00
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
2022-12-21 21:30:45 +01:00
engineutils "github.com/kyverno/kyverno/pkg/utils/engine"
2022-09-08 10:17:09 +05:30
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
2024-10-02 17:35:05 +05:30
reportutils "github.com/kyverno/kyverno/pkg/utils/report"
2024-01-09 17:30:31 +08:00
validationpolicy "github.com/kyverno/kyverno/pkg/validation/policy"
2024-08-14 01:14:06 +08:00
"go.uber.org/multierr"
2023-03-11 01:17:10 +08:00
admissionv1 "k8s.io/api/admission/v1"
2020-01-09 17:53:27 -08:00
apierrors "k8s.io/apimachinery/pkg/api/errors"
2020-01-07 10:33:28 -08:00
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2023-04-04 16:31:06 +05:30
"k8s.io/apimachinery/pkg/runtime/schema"
2022-05-17 17:51:03 +02:00
corev1listers "k8s.io/client-go/listers/core/v1"
2022-03-29 18:34:33 +05:30
"k8s.io/client-go/tools/cache"
2020-01-07 10:33:28 -08:00
)
2022-04-13 18:15:04 +05:30
type GenerateController struct {
2022-05-24 12:27:26 +02:00
// clients
client dclient . Interface
2022-09-07 06:01:43 +02:00
kyvernoClient versioned . Interface
2022-04-13 18:15:04 +05:30
statusControl common . StatusControlInterface
2023-02-03 06:01:11 +01:00
engine engineapi . Engine
2022-04-13 18:15:04 +05:30
2022-05-24 12:27:26 +02:00
// listers
2024-06-20 11:44:43 +02:00
urLister kyvernov2listers . UpdateRequestNamespaceLister
2022-05-24 12:27:26 +02:00
nsLister corev1listers . NamespaceLister
policyLister kyvernov1listers . ClusterPolicyLister
2022-05-18 06:02:31 +02:00
npolicyLister kyvernov1listers . PolicyLister
2022-04-13 18:15:04 +05:30
2023-02-03 06:01:11 +01:00
configuration config . Configuration
eventGen event . Interface
2022-08-31 14:03:47 +08:00
log logr . Logger
2023-04-13 13:29:40 +02:00
jp jmespath . Interface
2024-10-02 17:35:05 +05:30
2024-10-11 15:12:29 +05:30
reportsConfig reportutils . ReportingConfiguration
reportsBreaker breaker . Breaker
2022-04-13 18:15:04 +05:30
}
2022-05-17 08:19:03 +02:00
// NewGenerateController returns an instance of the Generate-Request Controller
2022-04-13 18:15:04 +05:30
func NewGenerateController (
2022-05-03 07:30:04 +02:00
client dclient . Interface ,
2022-09-07 06:01:43 +02:00
kyvernoClient versioned . Interface ,
2022-05-24 12:27:26 +02:00
statusControl common . StatusControlInterface ,
2023-02-03 06:01:11 +01:00
engine engineapi . Engine ,
2022-05-18 06:02:31 +02:00
policyLister kyvernov1listers . ClusterPolicyLister ,
npolicyLister kyvernov1listers . PolicyLister ,
2024-06-20 11:44:43 +02:00
urLister kyvernov2listers . UpdateRequestNamespaceLister ,
2022-05-17 17:51:03 +02:00
nsLister corev1listers . NamespaceLister ,
2022-05-04 18:05:03 +02:00
dynamicConfig config . Configuration ,
2022-05-24 12:27:26 +02:00
eventGen event . Interface ,
log logr . Logger ,
2023-04-13 13:29:40 +02:00
jp jmespath . Interface ,
2024-10-11 15:12:29 +05:30
reportsConfig reportutils . ReportingConfiguration ,
2024-10-02 17:35:05 +05:30
reportsBreaker breaker . Breaker ,
2022-05-24 12:27:26 +02:00
) * GenerateController {
2022-04-13 18:15:04 +05:30
c := GenerateController {
2024-10-11 15:12:29 +05:30
client : client ,
kyvernoClient : kyvernoClient ,
statusControl : statusControl ,
engine : engine ,
policyLister : policyLister ,
npolicyLister : npolicyLister ,
urLister : urLister ,
nsLister : nsLister ,
configuration : dynamicConfig ,
eventGen : eventGen ,
log : log ,
jp : jp ,
reportsConfig : reportsConfig ,
reportsBreaker : reportsBreaker ,
2022-04-13 18:15:04 +05:30
}
2022-05-24 12:27:26 +02:00
return & c
2022-04-13 18:15:04 +05:30
}
2024-06-20 11:44:43 +02:00
func ( c * GenerateController ) ProcessUR ( ur * kyvernov2 . UpdateRequest ) error {
2024-08-14 01:14:06 +08:00
logger := c . log . WithValues ( "name" , ur . GetName ( ) , "policy" , ur . Spec . GetPolicyKey ( ) )
2022-05-17 13:12:43 +02:00
var genResources [ ] kyvernov1 . ResourceSpec
2022-05-17 12:26:12 +05:30
logger . Info ( "start processing UR" , "ur" , ur . Name , "resourceVersion" , ur . GetResourceVersion ( ) )
2020-07-20 08:00:02 -07:00
2024-08-14 01:14:06 +08:00
var failures [ ] error
2024-08-14 22:32:49 +08:00
policy , err := c . getPolicyObject ( * ur )
if err != nil && ! apierrors . IsNotFound ( err ) {
return fmt . Errorf ( "error in fetching policy: %v" , err )
}
2024-08-14 01:14:06 +08:00
for i := 0 ; i < len ( ur . Spec . RuleContext ) ; i ++ {
rule := ur . Spec . RuleContext [ i ]
trigger , err := c . getTrigger ( ur . Spec , i )
if err != nil || trigger == nil {
logger . V ( 4 ) . Info ( "the trigger resource does not exist or is pending creation" )
failures = append ( failures , fmt . Errorf ( "rule %s failed: failed to fetch trigger resource: %v" , rule . Rule , err ) )
continue
2023-12-19 14:25:12 +08:00
}
2024-08-14 22:32:49 +08:00
genResources , err = c . applyGenerate ( * trigger , * ur , policy , i )
2023-12-19 14:25:12 +08:00
if err != nil {
2024-08-14 01:14:06 +08:00
if strings . Contains ( err . Error ( ) , doesNotApply ) {
logger . V ( 4 ) . Info ( fmt . Sprintf ( "skipping rule %s: %v" , rule . Rule , err . Error ( ) ) )
}
2020-07-20 08:00:02 -07:00
2024-08-14 01:14:06 +08:00
events := event . NewBackgroundFailedEvent ( err , policy , ur . Spec . RuleContext [ i ] . Rule , event . GeneratePolicyController ,
kyvernov1 . ResourceSpec { Kind : trigger . GetKind ( ) , Namespace : trigger . GetNamespace ( ) , Name : trigger . GetName ( ) } )
c . eventGen . Add ( events ... )
}
2023-12-19 14:25:12 +08:00
}
2024-08-14 01:14:06 +08:00
return updateStatus ( c . statusControl , * ur , multierr . Combine ( failures ... ) , genResources )
2020-01-07 10:33:28 -08:00
}
2020-12-22 11:07:31 -08:00
const doesNotApply = "policy does not apply to resource"
2024-08-14 01:14:06 +08:00
func ( c * GenerateController ) getTrigger ( spec kyvernov2 . UpdateRequestSpec , i int ) ( * unstructured . Unstructured , error ) {
resourceSpec := spec . RuleContext [ i ] . Trigger
c . log . V ( 4 ) . Info ( "fetching trigger" , "trigger" , resourceSpec . String ( ) )
2023-04-04 16:31:06 +05:30
admissionRequest := spec . Context . AdmissionRequestInfo . AdmissionRequest
if admissionRequest == nil {
2024-08-14 01:14:06 +08:00
return common . GetResource ( c . client , resourceSpec , spec , c . log )
2023-03-11 01:17:10 +08:00
} else {
2023-04-04 16:31:06 +05:30
operation := spec . Context . AdmissionRequestInfo . Operation
if operation == admissionv1 . Delete {
2024-08-14 01:14:06 +08:00
return c . getTriggerForDeleteOperation ( spec , i )
2023-04-04 16:31:06 +05:30
} else if operation == admissionv1 . Create {
2024-08-14 01:14:06 +08:00
return c . getTriggerForCreateOperation ( spec , i )
2023-04-04 16:31:06 +05:30
} else {
newResource , oldResource , err := admissionutils . ExtractResources ( nil , * admissionRequest )
if err != nil {
c . log . Error ( err , "failed to extract resources from admission review request" )
return nil , err
}
trigger := & newResource
if newResource . Object == nil {
trigger = & oldResource
}
return trigger , nil
}
}
}
2024-08-14 01:14:06 +08:00
func ( c * GenerateController ) getTriggerForDeleteOperation ( spec kyvernov2 . UpdateRequestSpec , i int ) ( * unstructured . Unstructured , error ) {
2023-04-04 16:31:06 +05:30
request := spec . Context . AdmissionRequestInfo . AdmissionRequest
_ , oldResource , err := admissionutils . ExtractResources ( nil , * request )
if err != nil {
return nil , fmt . Errorf ( "failed to load resource from context: %w" , err )
}
labels := oldResource . GetLabels ( )
2024-08-14 01:14:06 +08:00
resourceSpec := spec . RuleContext [ i ] . Trigger
2023-04-04 16:31:06 +05:30
if labels [ common . GeneratePolicyLabel ] != "" {
// non-trigger deletion, get trigger from ur spec
c . log . V ( 4 ) . Info ( "non-trigger resource is deleted, fetching the trigger from the UR spec" , "trigger" , spec . Resource . String ( ) )
2024-08-14 01:14:06 +08:00
return common . GetResource ( c . client , resourceSpec , spec , c . log )
2023-03-11 01:17:10 +08:00
}
2023-04-04 16:31:06 +05:30
return & oldResource , nil
}
2024-08-14 01:14:06 +08:00
func ( c * GenerateController ) getTriggerForCreateOperation ( spec kyvernov2 . UpdateRequestSpec , i int ) ( * unstructured . Unstructured , error ) {
2023-04-04 16:31:06 +05:30
admissionRequest := spec . Context . AdmissionRequestInfo . AdmissionRequest
2024-08-14 01:14:06 +08:00
resourceSpec := spec . RuleContext [ i ] . Trigger
trigger , err := common . GetResource ( c . client , resourceSpec , spec , c . log )
2023-04-04 16:31:06 +05:30
if err != nil || trigger == nil {
if admissionRequest . SubResource == "" {
return nil , err
} else {
c . log . V ( 4 ) . Info ( "trigger resource not found for subresource, reverting to resource in AdmissionReviewRequest" , "subresource" , admissionRequest . SubResource )
newResource , _ , err := admissionutils . ExtractResources ( nil , * admissionRequest )
if err != nil {
c . log . Error ( err , "failed to extract resources from admission review request" )
return nil , err
}
2024-11-19 23:41:06 -08:00
return & newResource , nil
2023-04-04 16:31:06 +05:30
}
}
return trigger , err
2023-03-11 01:17:10 +08:00
}
2024-08-14 22:32:49 +08:00
func ( c * GenerateController ) applyGenerate ( trigger unstructured . Unstructured , ur kyvernov2 . UpdateRequest , policy kyvernov1 . PolicyInterface , i int ) ( [ ] kyvernov1 . ResourceSpec , error ) {
2024-08-14 01:14:06 +08:00
logger := c . log . WithValues ( "name" , ur . GetName ( ) , "policy" , ur . Spec . GetPolicyKey ( ) )
logger . V ( 3 ) . Info ( "applying generate policy" )
2020-12-01 12:30:08 -08:00
2024-08-14 01:14:06 +08:00
ruleContext := ur . Spec . RuleContext [ i ]
2024-08-14 22:32:49 +08:00
if ruleContext . DeleteDownstream || policy == nil {
return nil , c . deleteDownstream ( policy , ruleContext , & ur )
2023-03-01 11:48:18 +08:00
}
2024-08-14 22:32:49 +08:00
p , ok := buildPolicyWithAppliedRules ( policy , ruleContext . Rule )
if ! ok {
logger . V ( 4 ) . Info ( "skip rule application as the rule does not exist in the updaterequest" , "rule" , ruleContext . Rule )
2024-08-14 01:14:06 +08:00
return nil , nil
}
2024-08-14 22:32:49 +08:00
namespaceLabels := engineutils . GetNamespaceSelectorsFromNamespaceLister ( trigger . GetKind ( ) , trigger . GetNamespace ( ) , c . nsLister , logger )
2024-08-14 01:14:06 +08:00
policyContext , err := common . NewBackgroundContext ( logger , c . client , ur . Spec . Context , p , & trigger , c . configuration , c . jp , namespaceLabels )
2020-01-24 09:37:12 -08:00
if err != nil {
2023-03-01 23:49:05 +08:00
return nil , err
2020-01-07 10:33:28 -08:00
}
2023-04-04 16:31:06 +05:30
admissionRequest := ur . Spec . Context . AdmissionRequestInfo . AdmissionRequest
if admissionRequest != nil {
var gvk schema . GroupVersionKind
gvk , err = c . client . Discovery ( ) . GetGVKFromGVR ( schema . GroupVersionResource ( admissionRequest . Resource ) )
if err != nil {
return nil , err
}
policyContext = policyContext . WithResourceKind ( gvk , admissionRequest . SubResource )
}
2020-01-07 10:33:28 -08:00
// check if the policy still applies to the resource
2023-04-03 06:57:48 +02:00
engineResponse := c . engine . Generate ( context . Background ( ) , policyContext )
2020-01-07 10:33:28 -08:00
if len ( engineResponse . PolicyResponse . Rules ) == 0 {
2020-12-22 11:07:31 -08:00
logger . V ( 4 ) . Info ( doesNotApply )
2023-03-01 23:49:05 +08:00
return nil , errors . New ( doesNotApply )
2020-01-07 10:33:28 -08:00
}
2020-09-19 01:04:43 +05:30
2020-12-15 15:21:39 -08:00
var applicableRules [ ] string
2020-09-04 03:04:23 +05:30
for _ , r := range engineResponse . PolicyResponse . Rules {
2024-08-14 01:14:06 +08:00
if r . Status ( ) == engineapi . RuleStatusPass {
2023-04-05 12:35:38 +02:00
applicableRules = append ( applicableRules , r . Name ( ) )
2020-08-31 23:55:13 +05:30
}
}
2020-09-04 03:04:23 +05:30
2020-01-07 10:33:28 -08:00
// Apply the generate rule on resource
2024-10-15 12:29:18 +05:30
genResourcesMap , err := c . ApplyGeneratePolicy ( logger , policyContext , applicableRules )
if err != nil {
return nil , err
}
for i , v := range engineResponse . PolicyResponse . Rules {
if resources , ok := genResourcesMap [ v . Name ( ) ] ; ok {
unstResources , err := c . GetUnstrResources ( resources )
if err != nil {
c . log . Error ( err , "failed to get unst resource names report" )
}
engineResponse . PolicyResponse . Rules [ i ] = * v . WithGeneratedResources ( unstResources )
}
}
if c . needsReports ( trigger ) {
if err := c . createReports ( context . TODO ( ) , policyContext . NewResource ( ) , engineResponse ) ; err != nil {
c . log . Error ( err , "failed to create report" )
2023-07-10 14:22:28 +03:00
}
2024-10-15 12:29:18 +05:30
}
genResources := make ( [ ] kyvernov1 . ResourceSpec , 0 )
for _ , v := range genResourcesMap {
genResources = append ( genResources , v ... )
}
2023-07-10 14:22:28 +03:00
2024-10-15 12:29:18 +05:30
for _ , res := range genResources {
e := event . NewResourceGenerationEvent ( ur . Spec . Policy , ur . Spec . RuleContext [ i ] . Rule , event . GeneratePolicyController , res )
c . eventGen . Add ( e )
2023-07-10 14:22:28 +03:00
}
2024-10-15 12:29:18 +05:30
e := event . NewBackgroundSuccessEvent ( event . GeneratePolicyController , policy , genResources )
c . eventGen . Add ( e ... )
2023-07-10 14:22:28 +03:00
return genResources , err
2020-01-07 10:33:28 -08:00
}
2024-08-14 01:14:06 +08:00
// getPolicyObject gets the policy spec from the ClusterPolicy/Policy
func ( c * GenerateController ) getPolicyObject ( ur kyvernov2 . UpdateRequest ) ( kyvernov1 . PolicyInterface , error ) {
2022-04-29 19:05:49 +08:00
pNamespace , pName , err := cache . SplitMetaNamespaceKey ( ur . Spec . Policy )
2022-03-29 18:34:33 +05:30
if err != nil {
2023-02-22 18:49:09 +08:00
return nil , err
2022-03-29 18:34:33 +05:30
}
if pNamespace == "" {
policyObj , err := c . policyLister . Get ( pName )
if err != nil {
2023-02-22 18:49:09 +08:00
return nil , err
2022-03-29 18:34:33 +05:30
}
2023-02-22 18:49:09 +08:00
return policyObj , err
2022-03-29 18:34:33 +05:30
}
2022-09-08 10:17:09 +05:30
npolicyObj , err := c . npolicyLister . Policies ( pNamespace ) . Get ( pName )
if err != nil {
2023-02-22 18:49:09 +08:00
return nil , err
}
return npolicyObj , nil
2022-03-29 18:34:33 +05:30
}
2024-10-15 12:29:18 +05:30
func ( c * GenerateController ) ApplyGeneratePolicy ( log logr . Logger , policyContext * engine . PolicyContext , applicableRules [ ] string ) ( map [ string ] [ ] kyvernov1 . ResourceSpec , error ) {
genResources := make ( map [ string ] [ ] kyvernov1 . ResourceSpec )
2022-12-02 09:14:23 +01:00
policy := policyContext . Policy ( )
resource := policyContext . NewResource ( )
2020-08-31 23:55:13 +05:30
// To manage existing resources, we compare the creation time for the default resource to be generated and policy creation time
2020-03-04 13:11:48 +05:30
ruleNameToProcessingTime := make ( map [ string ] time . Duration )
2022-12-02 09:14:23 +01:00
applyRules := policy . GetSpec ( ) . GetApplyRules ( )
2022-07-29 00:02:26 -07:00
applyCount := 0
2024-08-19 14:55:19 +08:00
log = log . WithValues ( "policy" , policy . GetName ( ) , "trigger" , resource . GetNamespace ( ) + "/" + resource . GetName ( ) )
2022-07-29 00:02:26 -07:00
2024-08-14 22:32:49 +08:00
for _ , rule := range policy . GetSpec ( ) . Rules {
2021-04-13 21:44:43 +03:00
var err error
2020-01-07 10:33:28 -08:00
if ! rule . HasGenerate ( ) {
continue
}
2020-09-04 03:04:23 +05:30
2022-11-29 09:04:49 +01:00
if ! slices . Contains ( applicableRules , rule . Name ) {
2020-12-15 15:21:39 -08:00
continue
}
2024-01-09 17:30:31 +08:00
if rule . Generation . Synchronize {
ruleRaw , err := json . Marshal ( rule . DeepCopy ( ) )
if err != nil {
return nil , fmt . Errorf ( "failed to serialize the policy: %v" , err )
}
vars := regex . RegexVariables . FindAllStringSubmatch ( string ( ruleRaw ) , - 1 )
for _ , s := range vars {
for _ , banned := range validationpolicy . ForbiddenUserVariables {
if banned . Match ( [ ] byte ( s [ 2 ] ) ) {
log . Info ( "warning: resources with admission request variables may not be regenerated" , "policy" , policy . GetName ( ) , "rule" , rule . Name , "variable" , s [ 2 ] )
}
}
}
}
2020-11-12 16:44:57 -08:00
startTime := time . Now ( )
2022-09-08 10:17:09 +05:30
var genResource [ ] kyvernov1 . ResourceSpec
2022-07-29 00:02:26 -07:00
if applyRules == kyvernov1 . ApplyOne && applyCount > 0 {
break
}
2024-08-14 01:14:06 +08:00
logger := log . WithValues ( "rule" , rule . Name )
2024-08-19 14:55:19 +08:00
contextLoader := c . engine . ContextLoader ( policy , rule )
if err := contextLoader ( context . TODO ( ) , rule . Context , policyContext . JSONContext ( ) ) ; err != nil {
if _ , ok := err . ( gojmespath . NotFoundError ) ; ok {
logger . V ( 3 ) . Info ( "failed to load rule level context" , "reason" , err . Error ( ) )
} else {
logger . Error ( err , "failed to load rule level context" )
}
return nil , fmt . Errorf ( "failed to load rule level context: %v" , err )
2021-04-13 21:44:43 +03:00
}
2024-08-19 14:55:19 +08:00
if rule . Generation . ForEachGeneration != nil {
g := newForeachGenerator ( c . client , logger , policyContext , policy , rule , rule . Context , rule . GetAnyAllConditions ( ) , policyContext . NewResource ( ) , rule . Generation . ForEachGeneration , contextLoader )
genResource , err = g . generateForeach ( )
} else {
2024-08-29 19:59:22 +08:00
g := newGenerator ( c . client , logger , policyContext , policy , rule , rule . Context , rule . GetAnyAllConditions ( ) , policyContext . NewResource ( ) , rule . Generation . GeneratePattern , contextLoader )
2024-08-19 14:55:19 +08:00
genResource , err = g . generate ( )
2020-01-07 10:33:28 -08:00
}
2022-05-09 12:43:11 +05:30
2023-03-01 23:49:05 +08:00
if err != nil {
2024-08-19 14:55:19 +08:00
log . Error ( err , "failed to apply generate rule" )
2023-03-01 23:49:05 +08:00
return nil , err
2022-05-09 12:43:11 +05:30
}
2023-03-01 23:49:05 +08:00
ruleNameToProcessingTime [ rule . Name ] = time . Since ( startTime )
2024-10-15 12:29:18 +05:30
genResources [ rule . Name ] = genResource
2022-07-29 00:02:26 -07:00
applyCount ++
2020-01-07 10:33:28 -08:00
}
2023-03-01 23:49:05 +08:00
return genResources , nil
2020-01-07 10:33:28 -08:00
}
2022-05-25 19:56:22 +05:30
// NewGenerateControllerWithOnlyClient returns an instance of Controller with only the client.
2023-02-03 06:01:11 +01:00
func NewGenerateControllerWithOnlyClient ( client dclient . Interface , engine engineapi . Engine ) * GenerateController {
2022-05-25 19:56:22 +05:30
c := GenerateController {
2023-02-03 06:01:11 +01:00
client : client ,
engine : engine ,
2022-05-25 19:56:22 +05:30
}
return & c
}
// GetUnstrResource converts ResourceSpec object to type Unstructured
2024-10-15 12:29:18 +05:30
func ( c * GenerateController ) GetUnstrResources ( genResourceSpecs [ ] kyvernov1 . ResourceSpec ) ( [ ] * unstructured . Unstructured , error ) {
resources := [ ] * unstructured . Unstructured { }
for _ , genResourceSpec := range genResourceSpecs {
resource , err := c . client . GetResource ( context . TODO ( ) , genResourceSpec . APIVersion , genResourceSpec . Kind , genResourceSpec . Namespace , genResourceSpec . Name )
if err != nil {
return nil , err
}
resources = append ( resources , resource )
2022-05-25 19:56:22 +05:30
}
2024-10-15 12:29:18 +05:30
return resources , nil
2022-05-25 19:56:22 +05:30
}
2024-08-14 22:32:49 +08:00
2024-10-11 15:12:29 +05:30
func ( c * GenerateController ) needsReports ( trigger unstructured . Unstructured ) bool {
createReport := c . reportsConfig . GenerateReportsEnabled ( )
2024-10-02 17:35:05 +05:30
// check if the resource supports reporting
if ! reportutils . IsGvkSupported ( trigger . GroupVersionKind ( ) ) {
createReport = false
}
return createReport
}
func ( c * GenerateController ) createReports (
ctx context . Context ,
resource unstructured . Unstructured ,
engineResponses ... engineapi . EngineResponse ,
) error {
2024-11-15 15:07:31 +05:30
report := reportutils . BuildGenerateReport ( resource . GetNamespace ( ) , resource . GroupVersionKind ( ) , resource . GetName ( ) , resource . GetUID ( ) , engineResponses ... )
2024-10-02 17:35:05 +05:30
if len ( report . GetResults ( ) ) > 0 {
err := c . reportsBreaker . Do ( ctx , func ( ctx context . Context ) error {
_ , err := reportutils . CreateReport ( ctx , report , c . kyvernoClient )
return err
} )
if err != nil {
return err
}
}
return nil
}
2024-08-14 22:32:49 +08:00
func updateStatus ( statusControl common . StatusControlInterface , ur kyvernov2 . UpdateRequest , err error , genResources [ ] kyvernov1 . ResourceSpec ) error {
if err != nil {
if _ , err := statusControl . Failed ( ur . GetName ( ) , err . Error ( ) , genResources ) ; err != nil {
return err
}
} else {
if _ , err := statusControl . Success ( ur . GetName ( ) , genResources ) ; err != nil {
return err
}
}
return nil
}
func GetUnstrRule ( rule * kyvernov1 . Generation ) ( * unstructured . Unstructured , error ) {
ruleData , err := json . Marshal ( rule )
if err != nil {
return nil , err
}
return kubeutils . BytesToUnstructured ( ruleData )
}