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"
2020-12-22 11:07:31 -08:00
"errors"
2020-01-07 10:33:28 -08:00
"fmt"
2020-10-07 11:12:31 -07:00
"reflect"
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"
2022-05-17 13:12:43 +02:00
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
2022-03-28 16:01:27 +02:00
"github.com/kyverno/kyverno/pkg/autogen"
2022-04-13 18:15:04 +05:30
"github.com/kyverno/kyverno/pkg/background/common"
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"
kyvernov1beta1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1beta1"
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"
2022-11-29 14:59:40 +01:00
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
2020-10-07 11:12:31 -07:00
"github.com/kyverno/kyverno/pkg/engine/variables"
2022-04-25 20:20:40 +08:00
"github.com/kyverno/kyverno/pkg/event"
2022-12-22 07:39:54 +01:00
datautils "github.com/kyverno/kyverno/pkg/utils/data"
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"
2022-11-29 09:04:49 +01:00
"golang.org/x/exp/slices"
2020-01-09 17:53:27 -08:00
apierrors "k8s.io/apimachinery/pkg/api/errors"
2020-08-31 23:55:13 +05:30
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2020-01-07 10:33:28 -08:00
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2020-12-15 04:22:13 +05:30
"k8s.io/apimachinery/pkg/labels"
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
urLister kyvernov1beta1listers . UpdateRequestNamespaceLister
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
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 ,
urLister kyvernov1beta1listers . 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 ,
) * GenerateController {
2022-04-13 18:15:04 +05:30
c := GenerateController {
2023-02-03 06:01:11 +01:00
client : client ,
kyvernoClient : kyvernoClient ,
statusControl : statusControl ,
engine : engine ,
policyLister : policyLister ,
npolicyLister : npolicyLister ,
urLister : urLister ,
nsLister : nsLister ,
configuration : dynamicConfig ,
eventGen : eventGen ,
log : log ,
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
}
2022-05-17 13:12:43 +02:00
func ( c * GenerateController ) ProcessUR ( ur * kyvernov1beta1 . UpdateRequest ) error {
2023-02-10 22:56:17 +08:00
logger := c . log . WithValues ( "name" , ur . GetName ( ) , "policy" , ur . Spec . GetPolicyKey ( ) , "resource" , ur . Spec . GetResource ( ) . String ( ) )
2020-01-07 15:13:57 -08:00
var err error
var resource * unstructured . Unstructured
2022-05-17 13:12:43 +02:00
var genResources [ ] kyvernov1 . ResourceSpec
2021-11-09 09:41:29 +05:30
var precreatedResource bool
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
2022-05-18 00:10:47 +08:00
// 1 - Check if the trigger exists
2022-04-29 19:05:49 +08:00
resource , err = common . GetResource ( c . client , ur . Spec , c . log )
2020-01-07 10:33:28 -08:00
if err != nil {
2020-12-21 11:04:19 -08:00
// Don't update status
2022-04-29 19:05:49 +08:00
// re-queueing the UR by updating the annotation
2021-10-11 14:40:45 +05:30
// retry - 5 times
2023-02-10 18:22:11 +08:00
logger . V ( 3 ) . Info ( "resource does not exist or is pending creation, re-queueing" , "details" , err . Error ( ) )
retry , urAnnotations , err := increaseRetryAnnotation ( ur )
if err != nil {
return err
}
if retry > 5 {
err = c . kyvernoClient . KyvernoV1beta1 ( ) . UpdateRequests ( config . KyvernoNamespace ( ) ) . Delete ( context . TODO ( ) , ur . GetName ( ) , metav1 . DeleteOptions { } )
if err != nil {
logger . Error ( err , "exceeds retry limit, failed to delete the UR" , "update request" , ur . Name , "retry" , retry , "resourceVersion" , ur . GetResourceVersion ( ) )
return err
2021-10-11 14:40:45 +05:30
}
}
2022-05-18 00:10:47 +08:00
ur . SetAnnotations ( urAnnotations )
2023-02-10 18:22:11 +08:00
_ , err = c . kyvernoClient . KyvernoV1beta1 ( ) . UpdateRequests ( config . KyvernoNamespace ( ) ) . Update ( context . TODO ( ) , ur , metav1 . UpdateOptions { } )
2022-05-18 00:10:47 +08:00
if err != nil {
2023-02-10 18:22:11 +08:00
logger . Error ( err , "failed to update annotation in update request for the resource" , "update request" , ur . Name , "resourceVersion" , ur . GetResourceVersion ( ) , "annotations" , urAnnotations , "retry" , retry )
2022-05-18 00:10:47 +08:00
return err
2021-10-11 14:40:45 +05:30
}
2020-01-07 10:33:28 -08:00
}
2020-07-20 08:00:02 -07:00
2020-11-20 14:14:59 -08:00
// trigger resource is being terminated
if resource == nil {
return nil
}
2020-01-07 10:33:28 -08:00
// 2 - Apply the generate policy on the resource
2022-12-21 21:30:45 +01:00
namespaceLabels := engineutils . GetNamespaceSelectorsFromNamespaceLister ( resource . GetKind ( ) , resource . GetNamespace ( ) , c . nsLister , logger )
2022-04-29 19:05:49 +08:00
genResources , precreatedResource , err = c . applyGenerate ( * resource , * ur , namespaceLabels )
2020-12-22 11:07:31 -08:00
if err != nil {
2022-04-29 19:05:49 +08:00
// Need not update the status when policy doesn't apply on resource, because all the update requests are removed by the cleanup controller
2020-12-22 11:07:31 -08:00
if strings . Contains ( err . Error ( ) , doesNotApply ) {
2022-04-29 19:05:49 +08:00
logger . V ( 4 ) . Info ( "skipping updating status of update request" )
2020-12-22 11:07:31 -08:00
return nil
}
2020-07-20 08:00:02 -07:00
2020-12-22 11:07:31 -08:00
// 3 - Report failure Events
2022-05-01 22:14:32 -07:00
events := event . NewBackgroundFailedEvent ( err , ur . Spec . Policy , "" , event . GeneratePolicyController , resource )
2020-12-22 11:07:31 -08:00
c . eventGen . Add ( events ... )
2020-12-08 01:34:46 +05:30
}
2020-01-07 10:33:28 -08:00
// 4 - Update Status
2022-04-29 19:05:49 +08:00
return updateStatus ( c . statusControl , * ur , err , genResources , precreatedResource )
2020-01-07 10:33:28 -08:00
}
2020-12-22 11:07:31 -08:00
const doesNotApply = "policy does not apply to resource"
2022-05-17 13:12:43 +02:00
func ( c * GenerateController ) applyGenerate ( resource unstructured . Unstructured , ur kyvernov1beta1 . UpdateRequest , namespaceLabels map [ string ] string ) ( [ ] kyvernov1 . ResourceSpec , bool , error ) {
2023-02-10 22:56:17 +08:00
logger := c . log . WithValues ( "name" , ur . GetName ( ) , "policy" , ur . Spec . GetPolicyKey ( ) , "resource" , ur . Spec . GetResource ( ) . String ( ) )
2020-12-01 12:30:08 -08:00
logger . V ( 3 ) . Info ( "applying generate policy rule" )
2022-04-29 19:05:49 +08:00
policy , err := c . getPolicySpec ( ur )
2020-01-07 10:33:28 -08:00
if err != nil {
2020-07-08 08:01:47 -07:00
if apierrors . IsNotFound ( err ) {
2022-04-29 19:05:49 +08:00
for _ , e := range ur . Status . GeneratedResources {
2022-05-05 18:56:27 +08:00
if err := c . cleanupClonedResource ( e ) ; err != nil {
logger . Error ( err , "failed to clean up cloned resource on policy deletion" )
2020-07-10 17:06:16 -07:00
}
2020-07-08 14:22:32 -07:00
}
2021-11-09 09:41:29 +05:30
return nil , false , nil
2020-07-08 08:01:47 -07:00
}
2020-11-12 16:44:57 -08:00
logger . Error ( err , "error in fetching policy" )
2021-11-09 09:41:29 +05:30
return nil , false , err
2020-01-07 10:33:28 -08:00
}
2020-07-08 14:22:32 -07:00
2023-02-22 18:49:09 +08:00
policyContext , precreatedResource , err := common . NewBackgroundContext ( c . client , & ur , policy , & resource , c . configuration , namespaceLabels , logger )
2020-01-24 09:37:12 -08:00
if err != nil {
2022-04-25 20:20:40 +08:00
return nil , precreatedResource , err
2020-01-07 10:33:28 -08:00
}
// check if the policy still applies to the resource
2023-02-08 06:55:03 +01:00
engineResponse := c . engine . GenerateResponse ( context . Background ( ) , policyContext , ur )
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 )
2021-11-09 09:41:29 +05:30
return nil , false , 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
2022-04-29 19:05:49 +08:00
// Removing UR if rule is failed. Used when the generate condition failed but ur exist
2020-09-04 03:04:23 +05:30
for _ , r := range engineResponse . PolicyResponse . Rules {
2023-01-30 12:41:09 +01:00
if r . Status != engineapi . RuleStatusPass {
2022-04-29 19:05:49 +08:00
logger . V ( 4 ) . Info ( "querying all update requests" )
2020-12-15 04:22:13 +05:30
selector := labels . SelectorFromSet ( labels . Set ( map [ string ] string {
2023-02-10 09:11:21 +01:00
kyvernov1beta1 . URGeneratePolicyLabel : engineResponse . Policy . GetName ( ) ,
2023-02-10 15:04:41 +01:00
kyvernov1beta1 . URGenerateResourceNameLabel : engineResponse . Resource . GetName ( ) ,
kyvernov1beta1 . URGenerateResourceKindLabel : engineResponse . Resource . GetKind ( ) ,
kyvernov1beta1 . URGenerateResourceNSLabel : engineResponse . Resource . GetNamespace ( ) ,
2020-12-15 04:22:13 +05:30
} ) )
2022-04-29 19:05:49 +08:00
urList , err := c . urLister . List ( selector )
2020-08-31 23:55:13 +05:30
if err != nil {
2023-02-10 15:04:41 +01:00
logger . Error ( err , "failed to get update request for the resource" , "kind" , engineResponse . Resource . GetKind ( ) , "name" , engineResponse . Resource . GetName ( ) , "namespace" , engineResponse . Resource . GetNamespace ( ) )
2020-08-31 23:55:13 +05:30
continue
}
2020-11-12 16:44:57 -08:00
2022-04-29 19:05:49 +08:00
for _ , v := range urList {
2022-11-29 14:59:40 +01:00
err := c . kyvernoClient . KyvernoV1beta1 ( ) . UpdateRequests ( config . KyvernoNamespace ( ) ) . Delete ( context . TODO ( ) , v . GetName ( ) , metav1 . DeleteOptions { } )
2020-12-15 15:21:39 -08:00
if err != nil {
2022-04-29 19:05:49 +08:00
logger . Error ( err , "failed to delete update request" )
2020-08-31 23:55:13 +05:30
}
}
2020-12-15 15:21:39 -08:00
} else {
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
2022-05-25 19:56:22 +05:30
return c . ApplyGeneratePolicy ( logger , policyContext , ur , applicableRules )
2020-01-07 10:33:28 -08:00
}
2022-05-05 18:56:27 +08:00
// cleanupClonedResource deletes cloned resource if sync is not enabled for the clone policy
2022-05-17 13:12:43 +02:00
func ( c * GenerateController ) cleanupClonedResource ( targetSpec kyvernov1 . ResourceSpec ) error {
2022-11-29 14:59:40 +01:00
target , err := c . client . GetResource ( context . TODO ( ) , targetSpec . APIVersion , targetSpec . Kind , targetSpec . Namespace , targetSpec . Name )
2022-05-05 18:56:27 +08:00
if err != nil {
if ! apierrors . IsNotFound ( err ) {
return fmt . Errorf ( "failed to find generated resource %s/%s: %v" , targetSpec . Namespace , targetSpec . Name , err )
}
}
if target == nil {
return nil
}
labels := target . GetLabels ( )
2023-02-10 21:26:51 +08:00
syncEnabled := labels [ LabelSynchronize ] == "enable"
clone := labels [ LabelClonePolicyName ] != ""
2022-05-05 18:56:27 +08:00
if syncEnabled && ! clone {
2022-11-29 14:59:40 +01:00
if err := c . client . DeleteResource ( context . TODO ( ) , target . GetAPIVersion ( ) , target . GetKind ( ) , target . GetNamespace ( ) , target . GetName ( ) , false ) ; err != nil {
2022-05-05 18:56:27 +08:00
return fmt . Errorf ( "cloned resource is not deleted %s/%s: %v" , targetSpec . Namespace , targetSpec . Name , err )
}
}
return nil
}
2022-03-29 18:34:33 +05:30
// getPolicySpec gets the policy spec from the ClusterPolicy/Policy
2023-02-22 18:49:09 +08:00
func ( c * GenerateController ) getPolicySpec ( ur kyvernov1beta1 . 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
}
2022-05-17 13:12:43 +02:00
func updateStatus ( statusControl common . StatusControlInterface , ur kyvernov1beta1 . UpdateRequest , err error , genResources [ ] kyvernov1 . ResourceSpec , precreatedResource bool ) error {
2020-01-07 10:33:28 -08:00
if err != nil {
2022-05-19 18:06:56 +02:00
if _ , err := statusControl . Failed ( ur . GetName ( ) , err . Error ( ) , genResources ) ; err != nil {
return err
}
2021-11-09 09:41:29 +05:30
} else if precreatedResource {
2022-05-19 18:06:56 +02:00
if _ , err := statusControl . Skip ( ur . GetName ( ) , genResources ) ; err != nil {
return err
}
} else {
if _ , err := statusControl . Success ( ur . GetName ( ) , genResources ) ; err != nil {
return err
}
2020-01-07 10:33:28 -08:00
}
2022-05-19 18:06:56 +02:00
return nil
2020-01-07 10:33:28 -08:00
}
2022-05-25 19:56:22 +05:30
func ( c * GenerateController ) ApplyGeneratePolicy ( log logr . Logger , policyContext * engine . PolicyContext , ur kyvernov1beta1 . UpdateRequest , applicableRules [ ] string ) ( genResources [ ] kyvernov1 . ResourceSpec , processExisting bool , err error ) {
2020-01-07 10:33:28 -08:00
// Get the response as the actions to be performed on the resource
// - - substitute values
2022-12-02 09:14:23 +01:00
policy := policyContext . Policy ( )
resource := policyContext . NewResource ( )
jsonContext := policyContext . JSONContext ( )
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
2022-03-30 15:04:30 +02:00
for _ , rule := range autogen . ComputeRules ( policy ) {
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
}
2020-11-12 16:44:57 -08:00
startTime := time . Now ( )
2021-11-09 09:41:29 +05:30
processExisting = false
2022-09-08 10:17:09 +05:30
var genResource [ ] kyvernov1 . ResourceSpec
2020-09-04 03:04:23 +05:30
2020-09-19 01:04:43 +05:30
if len ( rule . MatchResources . Kinds ) > 0 {
if len ( rule . MatchResources . Annotations ) == 0 && rule . MatchResources . Selector == nil {
2020-12-16 19:44:28 +05:30
rcreationTime := resource . GetCreationTimestamp ( )
pcreationTime := policy . GetCreationTimestamp ( )
processExisting = rcreationTime . Before ( & pcreationTime )
2020-09-04 03:04:23 +05:30
}
}
2020-09-23 02:41:49 +05:30
2022-07-29 00:02:26 -07:00
if applyRules == kyvernov1 . ApplyOne && applyCount > 0 {
break
}
2020-09-23 02:41:49 +05:30
// add configmap json data to context
2023-02-08 06:55:03 +01:00
if err := c . engine . ContextLoader ( policyContext . Policy ( ) , rule ) ( context . TODO ( ) , rule . Context , policyContext . JSONContext ( ) ) ; err != nil {
2021-04-13 21:44:43 +03:00
log . Error ( err , "cannot add configmaps to context" )
2021-11-09 09:41:29 +05:30
return nil , processExisting , err
2021-04-13 21:44:43 +03:00
}
2022-12-02 09:14:23 +01:00
if rule , err = variables . SubstituteAllInRule ( log , policyContext . JSONContext ( ) , rule ) ; err != nil {
2021-04-13 21:44:43 +03:00
log . Error ( err , "variable substitution failed for rule %s" , rule . Name )
2021-11-09 09:41:29 +05:30
return nil , processExisting , err
2020-09-23 02:41:49 +05:30
}
2023-02-22 18:49:09 +08:00
if ur . Spec . DeleteDownstream {
pKey := common . PolicyKey ( policy . GetNamespace ( ) , policy . GetName ( ) )
err = c . deleteResource ( pKey , rule , ur )
return nil , false , err
}
2022-05-09 12:43:11 +05:30
if policy . GetSpec ( ) . IsGenerateExistingOnPolicyUpdate ( ) || ! processExisting {
genResource , err = applyRule ( log , c . client , rule , resource , jsonContext , policy , ur )
2020-12-16 19:44:28 +05:30
if err != nil {
2022-03-30 15:04:30 +02:00
log . Error ( err , "failed to apply generate rule" , "policy" , policy . GetName ( ) ,
2021-06-11 01:18:26 +05:30
"rule" , rule . Name , "resource" , resource . GetName ( ) , "suggestion" , "users need to grant Kyverno's service account additional privileges" )
2021-11-09 09:41:29 +05:30
return nil , processExisting , err
2020-12-16 19:44:28 +05:30
}
ruleNameToProcessingTime [ rule . Name ] = time . Since ( startTime )
2022-09-08 10:17:09 +05:30
genResources = append ( genResources , genResource ... )
2020-01-07 10:33:28 -08:00
}
2022-05-09 12:43:11 +05:30
if policy . GetSpec ( ) . IsGenerateExistingOnPolicyUpdate ( ) {
processExisting = false
}
2022-07-29 00:02:26 -07:00
applyCount ++
2020-01-07 10:33:28 -08:00
}
2021-11-09 09:41:29 +05:30
return genResources , processExisting , nil
2020-01-07 10:33:28 -08:00
}
2020-12-04 10:04:46 -08:00
func getResourceInfo ( object map [ string ] interface { } ) ( kind , name , namespace , apiversion string , err error ) {
if kind , _ , err = unstructured . NestedString ( object , "kind" ) ; err != nil {
return "" , "" , "" , "" , err
}
if name , _ , err = unstructured . NestedString ( object , "name" ) ; err != nil {
return "" , "" , "" , "" , err
}
if namespace , _ , err = unstructured . NestedString ( object , "namespace" ) ; err != nil {
return "" , "" , "" , "" , err
}
if apiversion , _ , err = unstructured . NestedString ( object , "apiVersion" ) ; err != nil {
return "" , "" , "" , "" , err
}
return
}
2022-09-08 10:17:09 +05:30
func getResourceInfoForDataAndClone ( rule kyvernov1 . Rule ) ( kind , name , namespace , apiversion string , err error ) {
if len ( rule . Generation . CloneList . Kinds ) == 0 {
if kind = rule . Generation . Kind ; kind == "" {
return "" , "" , "" , "" , fmt . Errorf ( "%s" , "kind can not be empty" )
}
if name = rule . Generation . Name ; name == "" {
return "" , "" , "" , "" , fmt . Errorf ( "%s" , "name can not be empty" )
}
}
namespace = rule . Generation . Namespace
apiversion = rule . Generation . APIVersion
return
}
2022-11-29 14:59:40 +01:00
func applyRule ( log logr . Logger , client dclient . Interface , rule kyvernov1 . Rule , resource unstructured . Unstructured , ctx enginecontext . EvalInterface , policy kyvernov1 . PolicyInterface , ur kyvernov1beta1 . UpdateRequest ) ( [ ] kyvernov1 . ResourceSpec , error ) {
2022-09-08 10:17:09 +05:30
rdatas := [ ] GenerateResponse { }
var cresp , dresp map [ string ] interface { }
2020-01-07 10:33:28 -08:00
var err error
2020-02-04 12:13:41 -08:00
var mode ResourceMode
2022-05-17 13:12:43 +02:00
var noGenResource kyvernov1 . ResourceSpec
2022-09-08 10:17:09 +05:30
var newGenResources [ ] kyvernov1 . ResourceSpec
2020-12-14 02:43:16 -08:00
2022-09-08 10:17:09 +05:30
genKind , genName , genNamespace , genAPIVersion , err := getResourceInfoForDataAndClone ( rule )
2020-02-13 13:57:48 -08:00
if err != nil {
2022-09-08 10:17:09 +05:30
newGenResources = append ( newGenResources , noGenResource )
return newGenResources , err
2020-01-10 11:59:05 -08:00
}
2020-12-14 02:43:16 -08:00
logger := log . WithValues ( "genKind" , genKind , "genAPIVersion" , genAPIVersion , "genNamespace" , genNamespace , "genName" , genName )
2022-09-08 10:17:09 +05:30
if rule . Generation . Clone . Name != "" {
2023-02-22 18:49:09 +08:00
cresp , mode , err = manageClone ( logger , genAPIVersion , genKind , genNamespace , genName , policy , ur , rule , client )
2022-09-08 10:17:09 +05:30
rdatas = append ( rdatas , GenerateResponse {
Data : cresp ,
Action : mode ,
GenName : genName ,
GenKind : genKind ,
GenNamespace : genNamespace ,
GenAPIVersion : genAPIVersion ,
Error : err ,
} )
} else if len ( rule . Generation . CloneList . Kinds ) != 0 {
2023-02-22 18:49:09 +08:00
rdatas = manageCloneList ( logger , genNamespace , ur , policy , rule , client )
2020-02-13 13:57:48 -08:00
} else {
2022-10-21 01:11:57 +05:30
dresp , mode , err = manageData ( logger , genAPIVersion , genKind , genNamespace , genName , rule . Generation . RawData , rule . Generation . Synchronize , ur , client )
2022-09-08 10:17:09 +05:30
rdatas = append ( rdatas , GenerateResponse {
Data : dresp ,
Action : mode ,
GenName : genName ,
GenKind : genKind ,
GenNamespace : genNamespace ,
GenAPIVersion : genAPIVersion ,
Error : err ,
} )
}
for _ , rdata := range rdatas {
if rdata . Error != nil {
logger . Error ( err , "failed to generate resource" , "mode" , rdata . Action )
newGenResources = append ( newGenResources , noGenResource )
return newGenResources , err
}
2020-12-14 02:43:16 -08:00
2022-09-08 10:17:09 +05:30
logger . V ( 3 ) . Info ( "applying generate rule" , "mode" , rdata . Action )
2020-09-04 03:04:23 +05:30
2022-09-08 10:17:09 +05:30
// skip processing the response in case of skip action
if rdata . Action == Skip {
continue
}
2022-05-09 12:43:11 +05:30
2022-09-08 10:17:09 +05:30
if rdata . Data == nil && rdata . Action == Update {
logger . V ( 4 ) . Info ( "no changes required for generate target resource" )
newGenResources = append ( newGenResources , noGenResource )
return newGenResources , nil
}
2022-05-09 12:43:11 +05:30
2022-09-08 10:17:09 +05:30
// build the resource template
newResource := & unstructured . Unstructured { }
newResource . SetUnstructuredContent ( rdata . Data )
newResource . SetName ( rdata . GenName )
newResource . SetNamespace ( rdata . GenNamespace )
if newResource . GetKind ( ) == "" {
newResource . SetKind ( rdata . GenKind )
2020-09-04 03:04:23 +05:30
}
2020-12-14 02:43:16 -08:00
2022-09-08 10:17:09 +05:30
newResource . SetAPIVersion ( rdata . GenAPIVersion )
2023-02-22 18:49:09 +08:00
common . ManageLabels ( newResource , resource , policy , rule . Name )
2022-09-08 10:17:09 +05:30
// Add Synchronize label
label := newResource . GetLabels ( )
// Add background gen-rule label if generate rule applied on existing resource
if policy . GetSpec ( ) . IsGenerateExistingOnPolicyUpdate ( ) {
2023-02-10 21:26:51 +08:00
label [ LabelBackgroundGenRuleName ] = rule . Name
2020-02-04 12:13:41 -08:00
}
2020-12-01 12:30:08 -08:00
2023-02-10 21:26:51 +08:00
label [ LabelDataPolicyName ] = policy . GetName ( )
label [ LabelURName ] = ur . Name
2022-09-08 10:17:09 +05:30
if rdata . Action == Create {
2021-10-26 04:58:11 +05:30
if rule . Generation . Synchronize {
2023-02-10 21:26:51 +08:00
label [ LabelSynchronize ] = "enable"
2022-09-08 10:17:09 +05:30
} else {
2023-02-10 21:26:51 +08:00
label [ LabelSynchronize ] = "disable"
2022-09-08 10:17:09 +05:30
}
// Reset resource version
newResource . SetResourceVersion ( "" )
newResource . SetLabels ( label )
2021-10-26 04:58:11 +05:30
2022-09-08 10:17:09 +05:30
// Create the resource
2022-11-29 14:59:40 +01:00
_ , err = client . CreateResource ( context . TODO ( ) , rdata . GenAPIVersion , rdata . GenKind , rdata . GenNamespace , newResource , false )
2022-09-08 10:17:09 +05:30
if err != nil {
if ! apierrors . IsAlreadyExists ( err ) {
newGenResources = append ( newGenResources , noGenResource )
return newGenResources , err
2021-10-29 14:54:39 +05:30
}
2022-09-08 10:17:09 +05:30
}
logger . V ( 2 ) . Info ( "created generate target resource" )
newGenResources = append ( newGenResources , newGenResource ( rdata . GenAPIVersion , rdata . GenKind , rdata . GenNamespace , rdata . GenName ) )
} else if rdata . Action == Update {
2022-11-29 14:59:40 +01:00
generatedObj , err := client . GetResource ( context . TODO ( ) , rdata . GenAPIVersion , rdata . GenKind , rdata . GenNamespace , rdata . GenName )
2022-09-08 10:17:09 +05:30
if err != nil {
logger . Error ( err , fmt . Sprintf ( "generated resource not found name:%v namespace:%v kind:%v" , genName , genNamespace , genKind ) )
logger . V ( 2 ) . Info ( fmt . Sprintf ( "creating generate resource name:name:%v namespace:%v kind:%v" , genName , genNamespace , genKind ) )
2022-11-29 14:59:40 +01:00
_ , err = client . CreateResource ( context . TODO ( ) , rdata . GenAPIVersion , rdata . GenKind , rdata . GenNamespace , newResource , false )
2022-09-08 10:17:09 +05:30
if err != nil {
newGenResources = append ( newGenResources , noGenResource )
return newGenResources , err
2021-10-29 14:54:39 +05:30
}
2022-09-08 10:17:09 +05:30
newGenResources = append ( newGenResources , newGenResource ( rdata . GenAPIVersion , rdata . GenKind , rdata . GenNamespace , rdata . GenName ) )
} else {
// if synchronize is true - update the label and generated resource with generate policy data
if rule . Generation . Synchronize {
logger . V ( 4 ) . Info ( "updating existing resource" )
2023-02-10 21:26:51 +08:00
label [ LabelSynchronize ] = "enable"
2022-09-08 10:17:09 +05:30
newResource . SetLabels ( label )
if rdata . GenAPIVersion == "" {
generatedResourceAPIVersion := generatedObj . GetAPIVersion ( )
newResource . SetAPIVersion ( generatedResourceAPIVersion )
}
if rdata . GenNamespace == "" {
newResource . SetNamespace ( "default" )
}
2021-10-29 14:54:39 +05:30
2022-09-08 10:17:09 +05:30
if _ , err := ValidateResourceWithPattern ( logger , generatedObj . Object , newResource . Object ) ; err != nil {
2022-11-29 14:59:40 +01:00
_ , err = client . UpdateResource ( context . TODO ( ) , rdata . GenAPIVersion , rdata . GenKind , rdata . GenNamespace , newResource , false )
2022-09-08 10:17:09 +05:30
if err != nil {
logger . Error ( err , "failed to update resource" )
newGenResources = append ( newGenResources , noGenResource )
return newGenResources , err
}
2021-10-26 04:58:11 +05:30
}
2022-09-08 10:17:09 +05:30
} else {
currentGeneratedResourcelabel := generatedObj . GetLabels ( )
2023-02-10 21:26:51 +08:00
currentSynclabel := currentGeneratedResourcelabel [ LabelSynchronize ]
2022-09-08 10:17:09 +05:30
// update only if the labels mismatches
if ( ! rule . Generation . Synchronize && currentSynclabel == "enable" ) ||
( rule . Generation . Synchronize && currentSynclabel == "disable" ) {
logger . V ( 4 ) . Info ( "updating label in existing resource" )
2023-02-10 21:26:51 +08:00
currentGeneratedResourcelabel [ LabelSynchronize ] = "disable"
2022-09-08 10:17:09 +05:30
generatedObj . SetLabels ( currentGeneratedResourcelabel )
2022-11-29 14:59:40 +01:00
_ , err = client . UpdateResource ( context . TODO ( ) , rdata . GenAPIVersion , rdata . GenKind , rdata . GenNamespace , generatedObj , false )
2022-09-08 10:17:09 +05:30
if err != nil {
logger . Error ( err , "failed to update label in existing resource" )
newGenResources = append ( newGenResources , noGenResource )
return newGenResources , err
}
2021-10-26 04:58:11 +05:30
}
2021-08-13 17:23:39 +05:30
}
}
2022-09-08 10:17:09 +05:30
logger . V ( 3 ) . Info ( "updated generate target resource" )
2020-02-04 12:13:41 -08:00
}
2020-01-07 10:33:28 -08:00
}
2022-09-08 10:17:09 +05:30
return newGenResources , nil
}
2020-12-14 02:43:16 -08:00
2022-09-08 10:17:09 +05:30
func newGenResource ( genAPIVersion , genKind , genNamespace , genName string ) kyvernov1 . ResourceSpec {
// Resource to be generated
newGenResource := kyvernov1 . ResourceSpec {
APIVersion : genAPIVersion ,
Kind : genKind ,
Namespace : genNamespace ,
Name : genName ,
}
return newGenResource
2020-01-07 10:33:28 -08:00
}
2022-10-21 01:11:57 +05:30
func manageData ( log logr . Logger , apiVersion , kind , namespace , name string , data interface { } , synchronize bool , ur kyvernov1beta1 . UpdateRequest , client dclient . Interface ) ( map [ string ] interface { } , ResourceMode , error ) {
2022-12-22 07:39:54 +01:00
resource , err := datautils . ToMap ( data )
2022-09-08 10:17:09 +05:30
if err != nil {
return nil , Skip , err
}
2022-11-29 14:59:40 +01:00
obj , err := client . GetResource ( context . TODO ( ) , apiVersion , kind , namespace , name )
2020-01-07 10:33:28 -08:00
if err != nil {
2022-10-21 01:11:57 +05:30
if apierrors . IsNotFound ( err ) && len ( ur . Status . GeneratedResources ) != 0 && ! synchronize {
log . V ( 4 ) . Info ( "synchronize is disable - skip re-create" , "resource" , obj )
return nil , Skip , nil
}
2020-09-04 03:04:23 +05:30
if apierrors . IsNotFound ( err ) {
2022-09-08 10:17:09 +05:30
return resource , Create , nil
2020-09-04 03:04:23 +05:30
}
2020-12-12 21:19:37 -08:00
2020-12-14 02:43:16 -08:00
log . Error ( err , "failed to get resource" )
2020-02-04 12:13:41 -08:00
return nil , Skip , err
2020-01-07 10:33:28 -08:00
}
2020-12-12 21:19:37 -08:00
2021-01-04 12:33:00 +05:30
log . V ( 3 ) . Info ( "found target resource" , "resource" , obj )
2020-12-14 02:43:16 -08:00
if data == nil {
2021-01-04 12:33:00 +05:30
log . V ( 3 ) . Info ( "data is nil - skipping update" , "resource" , obj )
2020-12-14 02:43:16 -08:00
return nil , Skip , nil
}
2020-09-04 03:04:23 +05:30
updateObj := & unstructured . Unstructured { }
2022-09-08 10:17:09 +05:30
updateObj . SetUnstructuredContent ( resource )
2020-09-04 03:04:23 +05:30
updateObj . SetResourceVersion ( obj . GetResourceVersion ( ) )
return updateObj . UnstructuredContent ( ) , Update , nil
2020-01-07 10:33:28 -08:00
}
2023-02-22 18:49:09 +08:00
func manageClone ( log logr . Logger , apiVersion , kind , namespace , name string , policy kyvernov1 . PolicyInterface , ur kyvernov1beta1 . UpdateRequest , rule kyvernov1 . Rule , client dclient . Interface ) ( map [ string ] interface { } , ResourceMode , error ) {
clone := rule . Generation
2022-09-08 10:17:09 +05:30
// resource namespace can be nil in case of clusters scope resource
rNamespace := clone . Clone . Namespace
if rNamespace == "" {
log . V ( 4 ) . Info ( "resource namespace %s , optional in case of cluster scope resource" , rNamespace )
2020-01-07 10:33:28 -08:00
}
2020-12-14 02:43:16 -08:00
2022-09-08 10:17:09 +05:30
rName := clone . Clone . Name
if rName == "" {
return nil , Skip , fmt . Errorf ( "failed to find source name" )
2020-02-13 13:57:48 -08:00
}
2020-08-07 09:47:33 +05:30
2020-12-14 02:43:16 -08:00
if rNamespace == namespace && rName == name {
log . V ( 4 ) . Info ( "skip resource self-clone" )
2020-02-13 13:57:48 -08:00
return nil , Skip , nil
}
2020-06-22 18:49:43 -07:00
2020-02-13 13:57:48 -08:00
// check if the resource as reference in clone exists?
2022-11-29 14:59:40 +01:00
obj , err := client . GetResource ( context . TODO ( ) , apiVersion , kind , rNamespace , rName )
2020-01-07 10:33:28 -08:00
if err != nil {
2020-12-14 02:43:16 -08:00
return nil , Skip , fmt . Errorf ( "source resource %s %s/%s/%s not found. %v" , apiVersion , kind , rNamespace , rName , err )
2020-01-07 10:33:28 -08:00
}
2022-11-10 17:13:24 +05:30
2023-02-22 18:49:09 +08:00
if err := updateSourceLabel ( client , obj , ur . Spec . Resource , policy , rule ) ; err != nil {
log . Error ( err , "failed to add labels to the source" , "kind" , obj . GetKind ( ) , "namespace" , obj . GetNamespace ( ) , "name" , obj . GetName ( ) )
}
2022-11-10 17:13:24 +05:30
// check if cloned resource exists
2022-11-29 14:59:40 +01:00
cobj , err := client . GetResource ( context . TODO ( ) , apiVersion , kind , namespace , name )
2022-11-10 17:13:24 +05:30
if err != nil {
if apierrors . IsNotFound ( err ) && len ( ur . Status . GeneratedResources ) != 0 && ! clone . Synchronize {
log . V ( 4 ) . Info ( "synchronization is disabled, recreation will be skipped" , "resource" , cobj )
return nil , Skip , nil
}
}
2021-08-24 16:02:12 +02:00
// remove ownerReferences when cloning resources to other namespace
if rNamespace != namespace && obj . GetOwnerReferences ( ) != nil {
obj . SetOwnerReferences ( nil )
}
2020-06-22 18:49:43 -07:00
// check if resource to be generated exists
2022-11-29 14:59:40 +01:00
newResource , err := client . GetResource ( context . TODO ( ) , apiVersion , kind , namespace , name )
2020-06-22 18:49:43 -07:00
if err == nil {
obj . SetUID ( newResource . GetUID ( ) )
obj . SetSelfLink ( newResource . GetSelfLink ( ) )
obj . SetCreationTimestamp ( newResource . GetCreationTimestamp ( ) )
obj . SetManagedFields ( newResource . GetManagedFields ( ) )
obj . SetResourceVersion ( newResource . GetResourceVersion ( ) )
if reflect . DeepEqual ( obj , newResource ) {
return nil , Skip , nil
}
return obj . UnstructuredContent ( ) , Update , nil
}
2020-02-04 12:13:41 -08:00
// create the resource based on the reference clone
return obj . UnstructuredContent ( ) , Create , nil
2020-01-07 10:33:28 -08:00
}
2023-02-22 18:49:09 +08:00
func manageCloneList ( log logr . Logger , namespace string , ur kyvernov1beta1 . UpdateRequest , policy kyvernov1 . PolicyInterface , rule kyvernov1 . Rule , client dclient . Interface ) [ ] GenerateResponse {
2022-09-08 10:17:09 +05:30
var response [ ] GenerateResponse
2023-02-22 18:49:09 +08:00
clone := rule . Generation
2022-09-08 10:17:09 +05:30
rNamespace := clone . CloneList . Namespace
if rNamespace == "" {
log . V ( 4 ) . Info ( "resource namespace %s , optional in case of cluster scope resource" , rNamespace )
}
kinds := clone . CloneList . Kinds
if len ( kinds ) == 0 {
response = append ( response , GenerateResponse {
Data : nil ,
Action : Skip ,
Error : fmt . Errorf ( "failed to find kinds list" ) ,
} )
}
for _ , kind := range kinds {
apiVersion , kind := kubeutils . GetKindFromGVK ( kind )
2022-11-29 14:59:40 +01:00
resources , err := client . ListResource ( context . TODO ( ) , apiVersion , kind , rNamespace , clone . CloneList . Selector )
2022-09-08 10:17:09 +05:30
if err != nil {
response = append ( response , GenerateResponse {
Data : nil ,
Action : Skip ,
Error : fmt . Errorf ( "failed to list resource %s %s/%s. %v" , apiVersion , kind , rNamespace , err ) ,
} )
}
for _ , rName := range resources . Items {
if rNamespace == namespace {
log . V ( 4 ) . Info ( "skip resource self-clone" )
response = append ( response , GenerateResponse {
Data : nil ,
Action : Skip ,
Error : nil ,
} )
}
// check if the resource as reference in clone exists?
2022-11-29 14:59:40 +01:00
obj , err := client . GetResource ( context . TODO ( ) , apiVersion , kind , rNamespace , rName . GetName ( ) )
2022-09-08 10:17:09 +05:30
if err != nil {
2023-02-22 18:49:09 +08:00
log . Error ( err , "failed to get resource" , apiVersion , "apiVersion" , kind , "kind" , rNamespace , "rNamespace" , rName . GetName ( ) , "name" )
2022-09-08 10:17:09 +05:30
response = append ( response , GenerateResponse {
Data : nil ,
Action : Skip ,
Error : fmt . Errorf ( "source resource %s %s/%s/%s not found. %v" , apiVersion , kind , rNamespace , rName . GetName ( ) , err ) ,
} )
return response
}
2023-02-22 18:49:09 +08:00
if err := updateSourceLabel ( client , obj , ur . Spec . Resource , policy , rule ) ; err != nil {
log . Error ( err , "failed to add labels to the source" , "kind" , obj . GetKind ( ) , "namespace" , obj . GetNamespace ( ) , "name" , obj . GetName ( ) )
}
2022-11-10 17:13:24 +05:30
// check if cloned resource exists
2022-11-29 14:59:40 +01:00
cobj , err := client . GetResource ( context . TODO ( ) , apiVersion , kind , namespace , rName . GetName ( ) )
2022-11-10 17:13:24 +05:30
if apierrors . IsNotFound ( err ) && len ( ur . Status . GeneratedResources ) != 0 && ! clone . Synchronize {
log . V ( 4 ) . Info ( "synchronization is disabled, recreation will be skipped" , "resource" , cobj )
response = append ( response , GenerateResponse {
Data : nil ,
Action : Skip ,
Error : nil ,
} )
}
2022-09-08 10:17:09 +05:30
// remove ownerReferences when cloning resources to other namespace
if rNamespace != namespace && obj . GetOwnerReferences ( ) != nil {
obj . SetOwnerReferences ( nil )
}
// check if resource to be generated exists
2022-11-29 14:59:40 +01:00
newResource , err := client . GetResource ( context . TODO ( ) , apiVersion , kind , namespace , rName . GetName ( ) )
2022-09-08 10:17:09 +05:30
if err == nil && newResource != nil {
obj . SetUID ( newResource . GetUID ( ) )
obj . SetSelfLink ( newResource . GetSelfLink ( ) )
obj . SetCreationTimestamp ( newResource . GetCreationTimestamp ( ) )
obj . SetManagedFields ( newResource . GetManagedFields ( ) )
obj . SetResourceVersion ( newResource . GetResourceVersion ( ) )
if reflect . DeepEqual ( obj , newResource ) {
response = append ( response , GenerateResponse {
Data : nil ,
Action : Skip ,
Error : nil ,
} )
} else {
response = append ( response , GenerateResponse {
Data : obj . UnstructuredContent ( ) ,
Action : Update ,
GenKind : kind ,
GenName : rName . GetName ( ) ,
GenNamespace : namespace ,
GenAPIVersion : apiVersion ,
Error : nil ,
} )
}
}
// create the resource based on the reference clone
response = append ( response , GenerateResponse {
Data : obj . UnstructuredContent ( ) ,
Action : Create ,
GenKind : kind ,
GenName : rName . GetName ( ) ,
GenNamespace : namespace ,
GenAPIVersion : apiVersion ,
Error : nil ,
} )
}
}
return response
}
type GenerateResponse struct {
Data map [ string ] interface { }
Action ResourceMode
GenKind , GenName , GenNamespace , GenAPIVersion string
Error error
}
2020-02-13 13:57:48 -08:00
// ResourceMode defines the mode for generated resource
type ResourceMode string
const (
2022-05-17 08:19:03 +02:00
// Skip : failed to process rule, will not update the resource
2020-02-13 13:57:48 -08:00
Skip ResourceMode = "SKIP"
2022-05-17 08:19:03 +02:00
// Create : create a new resource
2020-02-13 13:57:48 -08:00
Create = "CREATE"
2022-05-17 08:19:03 +02:00
// Update : update/overwrite the new resource
2020-02-13 13:57:48 -08:00
Update = "UPDATE"
)
2022-05-25 19:56:22 +05:30
func GetUnstrRule ( rule * kyvernov1 . Generation ) ( * unstructured . Unstructured , error ) {
2020-02-13 13:57:48 -08:00
ruleData , err := json . Marshal ( rule )
if err != nil {
return nil , err
}
2023-01-03 13:02:15 +01:00
return kubeutils . BytesToUnstructured ( ruleData )
2020-01-07 10:33:28 -08:00
}
2022-05-18 00:10:47 +08:00
2022-05-25 19:56:22 +05:30
func ( c * GenerateController ) ApplyResource ( resource * unstructured . Unstructured ) error {
kind , _ , namespace , apiVersion , err := getResourceInfo ( resource . Object )
if err != nil {
return err
}
2022-11-29 14:59:40 +01:00
_ , err = c . client . CreateResource ( context . TODO ( ) , apiVersion , kind , namespace , resource , false )
2022-05-25 19:56:22 +05:30
if err != nil {
return err
}
return nil
}
// 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
func ( c * GenerateController ) GetUnstrResource ( genResourceSpec kyvernov1 . ResourceSpec ) ( * unstructured . Unstructured , error ) {
2022-11-29 14:59:40 +01:00
resource , err := c . client . GetResource ( context . TODO ( ) , genResourceSpec . APIVersion , genResourceSpec . Kind , genResourceSpec . Namespace , genResourceSpec . Name )
2022-05-25 19:56:22 +05:30
if err != nil {
return nil , err
}
return resource , nil
}
2023-02-22 18:49:09 +08:00
func ( c * GenerateController ) deleteResource ( policyKey string , rule kyvernov1 . Rule , ur kyvernov1beta1 . UpdateRequest ) error {
if policyKey != ur . Spec . Policy {
return nil
}
if rule . Name == ur . Spec . Rule {
return c . client . DeleteResource ( context . TODO ( ) , rule . Generation . GetAPIVersion ( ) , rule . Generation . GetKind ( ) , rule . Generation . GetNamespace ( ) , rule . Generation . GetName ( ) , false )
}
return nil
}