From b7524467a3a8fa22bc8c9f3a1e911fb1e2f38a71 Mon Sep 17 00:00:00 2001
From: Yuvraj <10830562+evalsocket@users.noreply.github.com>
Date: Fri, 4 Sep 2020 03:04:23 +0530
Subject: [PATCH] Reconcile Generate request on policy update  (#1096)

* policy report crd added

* added namespaced rule

* remove extra field from crd

* revert crd change

* remove policy report chnages

* remove policy report chnages

* remove policy report chnages

* remove policy report chnages

* added logic for gr

* revert changes

* fixed generate rules

* fixed generate rules

* fixed generate rules

* fixed generate rules

* remove extra logs

* remove extra logs

* fixed e2e test

* remove extra logs

* crd issue resolved

* added check for sync

* add labels update

* add label update

* added permission to role

* roles added to helm

* roles added to helm
---
 charts/kyverno/templates/clusterrole.yaml |   2 +
 cmd/kyverno/main.go                       |   1 +
 definitions/crds/crds.yaml                | 312 +++++++++++-----------
 definitions/install.yaml                  |   2 +
 definitions/install_debug.yaml            |   2 +
 definitions/k8s-resource/rbac.yaml        |   2 +
 pkg/engine/response/response.go           |   1 +
 pkg/generate/cleanup/controller.go        |   4 +-
 pkg/generate/controller.go                |   6 +-
 pkg/generate/generate.go                  | 145 ++++++----
 pkg/policy/controller.go                  |  47 +++-
 pkg/webhooks/generate/generate.go         |   3 +-
 pkg/webhooks/generation.go                |  17 +-
 13 files changed, 313 insertions(+), 231 deletions(-)

diff --git a/charts/kyverno/templates/clusterrole.yaml b/charts/kyverno/templates/clusterrole.yaml
index 25e6ff2c86..2f27846027 100644
--- a/charts/kyverno/templates/clusterrole.yaml
+++ b/charts/kyverno/templates/clusterrole.yaml
@@ -131,6 +131,7 @@ rules:
   - limitranges
   - clusterroles
   - rolebindings
+  - namespaces
   - clusterrolebindings
   {{- range .Values.generatecontrollerExtraResources }}
   - {{ . }}
@@ -139,6 +140,7 @@ rules:
   - create
   - update
   - delete
+  - list
   - get
 # dynamic watches on trigger resources for generate rules
 # re-evaluate the policy if the resource is updated
diff --git a/cmd/kyverno/main.go b/cmd/kyverno/main.go
index d3f9bbe0cc..83ed6b7808 100644
--- a/cmd/kyverno/main.go
+++ b/cmd/kyverno/main.go
@@ -194,6 +194,7 @@ func main() {
 		pInformer.Kyverno().V1().Policies(),
 		pInformer.Kyverno().V1().ClusterPolicyViolations(),
 		pInformer.Kyverno().V1().PolicyViolations(),
+		pInformer.Kyverno().V1().GenerateRequests(),
 		configData,
 		eventGenerator,
 		pvgen,
diff --git a/definitions/crds/crds.yaml b/definitions/crds/crds.yaml
index d57c2721a4..4efe95fb44 100644
--- a/definitions/crds/crds.yaml
+++ b/definitions/crds/crds.yaml
@@ -14,7 +14,7 @@ spec:
     plural: clusterpolicies
     singular: clusterpolicy
     shortNames:
-    - cpol
+      - cpol
   subresources:
     status: {}
   validation:
@@ -23,14 +23,14 @@ spec:
         status: {}
         spec:
           required:
-          - rules
+            - rules
           properties:
-          # default values to be handled by user
+            # default values to be handled by user
             validationFailureAction:
               type: string
-              enum: 
-              - enforce # blocks the resorce api-reques if a rule fails.
-              - audit # allows resource creation and reports the failed validation rules as violations. Default
+              enum:
+                - enforce # blocks the resorce api-reques if a rule fails.
+                - audit # allows resource creation and reports the failed validation rules as violations. Default
             background:
               type: boolean
             rules:
@@ -38,15 +38,15 @@ spec:
               items:
                 type: object
                 required:
-                - name
-                - match
+                  - name
+                  - match
                 properties:
                   name:
                     type: string
                   match:
                     type: object
                     required:
-                    - resources
+                      - resources
                     properties:
                       roles:
                         type: array
@@ -61,8 +61,8 @@ spec:
                         items:
                           type: object
                           required:
-                          - kind
-                          - name
+                            - kind
+                            - name
                           properties:
                             kind:
                               type: string
@@ -101,8 +101,8 @@ spec:
                                 items:
                                   type: object
                                   required:
-                                  - key
-                                  - operator
+                                    - key
+                                    - operator
                                   properties:
                                     key:
                                       type: string
@@ -128,8 +128,8 @@ spec:
                         items:
                           type: object
                           required:
-                          - kind
-                          - name
+                            - kind
+                            - name
                           properties:
                             kind:
                               type: string
@@ -167,8 +167,8 @@ spec:
                                 items:
                                   type: object
                                   required:
-                                  - key
-                                  - operator
+                                    - key
+                                    - operator
                                   properties:
                                     key:
                                       type: string
@@ -183,9 +183,9 @@ spec:
                     items:
                       type: object
                       required:
-                      - key  # can be of any type
-                      - operator # typed
-                      - value # can be of any type
+                        - key  # can be of any type
+                        - operator # typed
+                        - value # can be of any type
                   mutate:
                     type: object
                     properties:
@@ -198,17 +198,17 @@ spec:
                         items:
                           type: object
                           required:
-                          - path
-                          - op
+                            - path
+                            - op
                           properties:
                             path:
                               type: string
                             op:
                               type: string
                               enum:
-                              - add
-                              - replace
-                              - remove
+                                - add
+                                - replace
+                                - remove
                             value: {}
                   validate:
                     type: object
@@ -231,24 +231,24 @@ spec:
                                 operator:
                                   type: string
                                   enum:
-                                  - Equal
-                                  - Equals
-                                  - NotEqual
-                                  - NotEquals
-                                  - In
-                                  - NotIn
+                                    - Equal
+                                    - Equals
+                                    - NotEqual
+                                    - NotEquals
+                                    - In
+                                    - NotIn
                                 key:
                                   type: string
                                 value:
                                   anyOf:
-                                  - type: string
-                                  - type: array
-                                    items: {}
+                                    - type: string
+                                    - type: array
+                                      items: {}
                   generate:
                     type: object
                     required:
-                    - kind
-                    - name
+                      - kind
+                      - name
                     properties:
                       apiVersion:
                         type: string
@@ -260,11 +260,11 @@ spec:
                         type: string
                       synchronize:
                         type: boolean
-                      clone: 
+                      clone:
                         type: object
                         required:
-                        - namespace
-                        - name
+                          - namespace
+                          - name
                         properties:
                           namespace:
                             type: string
@@ -288,7 +288,7 @@ spec:
     plural: policies
     singular: policy
     shortNames:
-    - pol
+      - pol
   subresources:
     status: {}
   validation:
@@ -297,14 +297,14 @@ spec:
         status: {}
         spec:
           required:
-          - rules
+            - rules
           properties:
-          # default values to be handled by user
+            # default values to be handled by user
             validationFailureAction:
               type: string
-              enum: 
-              - enforce # blocks the resorce api-reques if a rule fails.
-              - audit # allows resource creation and reports the failed validation rules as violations. Default
+              enum:
+                - enforce # blocks the resorce api-reques if a rule fails.
+                - audit # allows resource creation and reports the failed validation rules as violations. Default
             background:
               type: boolean
             rules:
@@ -312,15 +312,15 @@ spec:
               items:
                 type: object
                 required:
-                - name
-                - match
+                  - name
+                  - match
                 properties:
                   name:
                     type: string
                   match:
                     type: object
                     required:
-                    - resources
+                      - resources
                     properties:
                       roles:
                         type: array
@@ -335,8 +335,8 @@ spec:
                         items:
                           type: object
                           required:
-                          - kind
-                          - name
+                            - kind
+                            - name
                           properties:
                             kind:
                               type: string
@@ -367,8 +367,8 @@ spec:
                                 items:
                                   type: object
                                   required:
-                                  - key
-                                  - operator
+                                    - key
+                                    - operator
                                   properties:
                                     key:
                                       type: string
@@ -394,8 +394,8 @@ spec:
                         items:
                           type: object
                           required:
-                          - kind
-                          - name
+                            - kind
+                            - name
                           properties:
                             kind:
                               type: string
@@ -425,8 +425,8 @@ spec:
                                 items:
                                   type: object
                                   required:
-                                  - key
-                                  - operator
+                                    - key
+                                    - operator
                                   properties:
                                     key:
                                       type: string
@@ -441,9 +441,9 @@ spec:
                     items:
                       type: object
                       required:
-                      - key  # can be of any type
-                      - operator # typed
-                      - value # can be of any type
+                        - key  # can be of any type
+                        - operator # typed
+                        - value # can be of any type
                   mutate:
                     type: object
                     properties:
@@ -456,17 +456,17 @@ spec:
                         items:
                           type: object
                           required:
-                          - path
-                          - op
+                            - path
+                            - op
                           properties:
                             path:
                               type: string
                             op:
                               type: string
                               enum:
-                              - add
-                              - replace
-                              - remove
+                                - add
+                                - replace
+                                - remove
                             value: {}
                   validate:
                     type: object
@@ -489,24 +489,24 @@ spec:
                                 operator:
                                   type: string
                                   enum:
-                                  - Equal
-                                  - Equals
-                                  - NotEqual
-                                  - NotEquals
-                                  - In
-                                  - NotIn
+                                    - Equal
+                                    - Equals
+                                    - NotEqual
+                                    - NotEquals
+                                    - In
+                                    - NotIn
                                 key:
                                   type: string
                                 value:
                                   anyOf:
-                                  - type: string
-                                  - type: array
-                                    items: {}
+                                    - type: string
+                                    - type: array
+                                      items: {}
                   generate:
                     type: object
                     required:
-                    - kind
-                    - name
+                      - kind
+                      - name
                     properties:
                       apiVersion:
                         type: string
@@ -518,11 +518,11 @@ spec:
                         type: string
                       synchronize:
                         type: boolean
-                      clone: 
+                      clone:
                         type: object
                         required:
-                        - namespace
-                        - name
+                          - namespace
+                          - name
                         properties:
                           namespace:
                             type: string
@@ -546,41 +546,41 @@ spec:
     plural: clusterpolicyviolations
     singular: clusterpolicyviolation
     shortNames:
-    - cpolv
+      - cpolv
   subresources:
     status: {}
   additionalPrinterColumns:
-  - name: Policy
-    type: string
-    description: The policy that resulted in the violation
-    JSONPath: .spec.policy
-  - name: ResourceKind
-    type: string
-    description: The resource kind that cause the violation
-    JSONPath: .spec.resource.kind
-  - name: ResourceName
-    type: string
-    description: The resource name that caused the violation
-    JSONPath: .spec.resource.name
-  - name: Age
-    type: date
-    JSONPath: .metadata.creationTimestamp
+    - name: Policy
+      type: string
+      description: The policy that resulted in the violation
+      JSONPath: .spec.policy
+    - name: ResourceKind
+      type: string
+      description: The resource kind that cause the violation
+      JSONPath: .spec.resource.kind
+    - name: ResourceName
+      type: string
+      description: The resource name that caused the violation
+      JSONPath: .spec.resource.name
+    - name: Age
+      type: date
+      JSONPath: .metadata.creationTimestamp
   validation:
     openAPIV3Schema:
       properties:
         spec:
           required:
-          - policy
-          - resource
-          - rules
+            - policy
+            - resource
+            - rules
           properties:
             policy:
               type: string
             resource:
               type: object
               required:
-              - kind
-              - name
+                - kind
+                - name
               properties:
                 kind:
                   type: string
@@ -591,9 +591,9 @@ spec:
               items:
                 type: object
                 required:
-                - name
-                - type
-                - message
+                  - name
+                  - type
+                  - message
                 properties:
                   name:
                     type: string
@@ -618,41 +618,41 @@ spec:
     plural: policyviolations
     singular: policyviolation
     shortNames:
-    - polv
+      - polv
   subresources:
     status: {}
   additionalPrinterColumns:
-  - name: Policy
-    type: string
-    description: The policy that resulted in the violation
-    JSONPath: .spec.policy
-  - name: ResourceKind
-    type: string
-    description: The resource kind that cause the violation
-    JSONPath: .spec.resource.kind
-  - name: ResourceName
-    type: string
-    description: The resource name that caused the violation
-    JSONPath: .spec.resource.name
-  - name: Age
-    type: date
-    JSONPath: .metadata.creationTimestamp
+    - name: Policy
+      type: string
+      description: The policy that resulted in the violation
+      JSONPath: .spec.policy
+    - name: ResourceKind
+      type: string
+      description: The resource kind that cause the violation
+      JSONPath: .spec.resource.kind
+    - name: ResourceName
+      type: string
+      description: The resource name that caused the violation
+      JSONPath: .spec.resource.name
+    - name: Age
+      type: date
+      JSONPath: .metadata.creationTimestamp
   validation:
     openAPIV3Schema:
       properties:
         spec:
           required:
-          - policy
-          - resource
-          - rules
+            - policy
+            - resource
+            - rules
           properties:
             policy:
               type: string
             resource:
               type: object
               required:
-              - kind
-              - name
+                - kind
+                - name
               properties:
                 kind:
                   type: string
@@ -663,9 +663,9 @@ spec:
               items:
                 type: object
                 required:
-                - name
-                - type
-                - message
+                  - name
+                  - type
+                  - message
                 properties:
                   name:
                     type: string
@@ -690,52 +690,52 @@ spec:
     plural: generaterequests
     singular: generaterequest
     shortNames:
-    - gr
+      - gr
   subresources:
     status: {}
   additionalPrinterColumns:
-  - name: Policy
-    type: string
-    description: The policy that resulted in the violation
-    JSONPath: .spec.policy
-  - name: ResourceKind
-    type: string
-    description: The resource kind that cause the violation
-    JSONPath: .spec.resource.kind
-  - name: ResourceName
-    type: string
-    description: The resource name that caused the violation
-    JSONPath: .spec.resource.name
-  - name: ResourceNamespace
-    type: string
-    description: The resource namespace that caused the violation
-    JSONPath: .spec.resource.namespace
-  - name: status
-    type : string
-    description: Current state of generate request
-    JSONPath: .status.state
-  - name: Age
-    type: date
-    JSONPath: .metadata.creationTimestamp
+    - name: Policy
+      type: string
+      description: The policy that resulted in the violation
+      JSONPath: .spec.policy
+    - name: ResourceKind
+      type: string
+      description: The resource kind that cause the violation
+      JSONPath: .spec.resource.kind
+    - name: ResourceName
+      type: string
+      description: The resource name that caused the violation
+      JSONPath: .spec.resource.name
+    - name: ResourceNamespace
+      type: string
+      description: The resource namespace that caused the violation
+      JSONPath: .spec.resource.namespace
+    - name: status
+      type : string
+      description: Current state of generate request
+      JSONPath: .status.state
+    - name: Age
+      type: date
+      JSONPath: .metadata.creationTimestamp
   validation:
     openAPIV3Schema:
       properties:
         spec:
           required:
-          - policy
-          - resource
+            - policy
+            - resource
           properties:
             policy:
               type: string
             resource:
               type: object
               required:
-              - kind 
-              - name
+                - kind
+                - name
               properties:
                 kind:
                   type: string
-                name: 
+                name:
                   type: string
                 namespace:
-                  type: string    
+                  type: string
diff --git a/definitions/install.yaml b/definitions/install.yaml
index b6e262c314..9564adeacf 100644
--- a/definitions/install.yaml
+++ b/definitions/install.yaml
@@ -832,8 +832,10 @@ rules:
   - rolebindings
   - clusterrolebindings
   - configmaps
+  - namespaces
   verbs:
   - watch
+  - list
 ---
 apiVersion: rbac.authorization.k8s.io/v1
 kind: ClusterRole
diff --git a/definitions/install_debug.yaml b/definitions/install_debug.yaml
index 738d7bea89..ca8d0baee2 100644
--- a/definitions/install_debug.yaml
+++ b/definitions/install_debug.yaml
@@ -832,8 +832,10 @@ rules:
   - rolebindings
   - clusterrolebindings
   - configmaps
+  - namespaces
   verbs:
   - watch
+  - list
 ---
 apiVersion: rbac.authorization.k8s.io/v1
 kind: ClusterRole
diff --git a/definitions/k8s-resource/rbac.yaml b/definitions/k8s-resource/rbac.yaml
index 60d08a993f..bab25f1201 100644
--- a/definitions/k8s-resource/rbac.yaml
+++ b/definitions/k8s-resource/rbac.yaml
@@ -158,8 +158,10 @@ rules:
   - rolebindings
   - clusterrolebindings
   - configmaps
+  - namespaces
   verbs:
   - watch
+  - list
 ---
 apiVersion: rbac.authorization.k8s.io/v1
 kind: ClusterRole
diff --git a/pkg/engine/response/response.go b/pkg/engine/response/response.go
index eeb37dd2cb..2809ee4abf 100644
--- a/pkg/engine/response/response.go
+++ b/pkg/engine/response/response.go
@@ -27,6 +27,7 @@ type PolicyResponse struct {
 	Rules []RuleResponse `json:"rules"`
 	// ValidationFailureAction: audit(default if not set),enforce
 	ValidationFailureAction string
+
 }
 
 //ResourceSpec resource action applied on
diff --git a/pkg/generate/cleanup/controller.go b/pkg/generate/cleanup/controller.go
index 95f5e3c60e..9e4f0e2031 100644
--- a/pkg/generate/cleanup/controller.go
+++ b/pkg/generate/cleanup/controller.go
@@ -175,12 +175,14 @@ func (c *Controller) deleteGR(obj interface{}) {
 	for _, resource := range gr.Status.GeneratedResources {
 		r, err := c.client.GetResource(resource.APIVersion, resource.Kind, resource.Namespace, resource.Name)
 		if err != nil {
-			logger.Error(err, "Generated resource is not deleted", "Resource", r.GetName())
+			logger.Error(err, "Generated resource is not deleted", "Resource", resource.Name)
+			return
 		}
 		labels := r.GetLabels()
 		if labels["policy.kyverno.io/synchronize"] == "enable" {
 			if err := c.client.DeleteResource(r.GetAPIVersion(), r.GetKind(), r.GetNamespace(), r.GetName(), false); err != nil {
 				logger.Error(err, "Generated resource is not deleted", "Resource", r.GetName())
+				return
 			}
 		}
 	}
diff --git a/pkg/generate/controller.go b/pkg/generate/controller.go
index 4bbdcf2ffa..4eae6fbfbb 100644
--- a/pkg/generate/controller.go
+++ b/pkg/generate/controller.go
@@ -1,8 +1,6 @@
 package generate
 
 import (
-	"time"
-
 	"github.com/go-logr/logr"
 	kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
 	kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned"
@@ -20,6 +18,7 @@ import (
 	"k8s.io/client-go/informers"
 	"k8s.io/client-go/tools/cache"
 	"k8s.io/client-go/util/workqueue"
+	"time"
 )
 
 const (
@@ -204,7 +203,8 @@ func (c *Controller) deleteGR(obj interface{}) {
 	for _, resource := range gr.Status.GeneratedResources {
 		r, err := c.client.GetResource(resource.APIVersion, resource.Kind, resource.Namespace, resource.Name)
 		if err != nil {
-			logger.Error(err, "Generated resource is not deleted", "Resource", r.GetName())
+			logger.Error(err, "Generated resource is not deleted", "Resource", resource.Name)
+			continue
 		}
 		labels := r.GetLabels()
 		if labels["policy.kyverno.io/synchronize"] == "enable" {
diff --git a/pkg/generate/generate.go b/pkg/generate/generate.go
index 03f3fd80aa..8bc18cea31 100644
--- a/pkg/generate/generate.go
+++ b/pkg/generate/generate.go
@@ -108,8 +108,8 @@ func (c *Controller) applyGenerate(resource unstructured.Unstructured, gr kyvern
 		logger.V(4).Info("policy does not apply to resource")
 		return nil, fmt.Errorf("policy %s, dont not apply to resource %v", gr.Spec.Policy, gr.Spec.Resource)
 	}
-
-	for i, r := range engineResponse.PolicyResponse.Rules {
+	var rules []response.RuleResponse
+	for _, r := range engineResponse.PolicyResponse.Rules {
 		if !r.Success {
 			grList, err := c.kyvernoClient.KyvernoV1().GenerateRequests(config.KubePolicyNamespace).List(metav1.ListOptions{})
 			if err != nil {
@@ -123,14 +123,24 @@ func (c *Controller) applyGenerate(resource unstructured.Unstructured, gr kyvern
 					}
 				}
 			}
-			if len(engineResponse.PolicyResponse.Rules) > 1 {
-				engineResponse.PolicyResponse.Rules = append(engineResponse.PolicyResponse.Rules[:i], engineResponse.PolicyResponse.Rules[i+1:]...)
-				continue
-			} else if len(engineResponse.PolicyResponse.Rules) == 1 {
-				engineResponse.PolicyResponse.Rules = []response.RuleResponse{}
+		} else {
+			rules = append(rules, r)
+		}
+	}
+	engineResponse.PolicyResponse.Rules = []response.RuleResponse{}
+
+	for _, v := range policy.Spec.Rules {
+		for _, r := range rules {
+			if policy.Name == engineResponse.PolicyResponse.Policy && r.Name == v.Name {
+				if len(v.MatchResources.ResourceDescription.Kinds) > 0 && (len(v.MatchResources.ResourceDescription.Annotations) == 0 || len(v.MatchResources.ResourceDescription.Selector.MatchLabels) == 0) {
+					continue
+				} else {
+					engineResponse.PolicyResponse.Rules = append(engineResponse.PolicyResponse.Rules, r)
+				}
 			}
 		}
 	}
+
 	// Apply the generate rule on resource
 	return c.applyGeneratePolicy(logger, policyContext, gr)
 }
@@ -160,7 +170,23 @@ func (c *Controller) applyGeneratePolicy(log logr.Logger, policyContext engine.P
 			continue
 		}
 		startTime := time.Now()
-		genResource, err := applyRule(log, c.client, rule, resource, ctx, policy.Name, gr)
+
+		processExisting := false
+
+		for _, v := range policy.Spec.Rules {
+			if policy.Name == gr.Spec.Policy {
+				if len(v.MatchResources.ResourceDescription.Kinds) > 0 && (len(v.MatchResources.ResourceDescription.Annotations) == 0 || len(v.MatchResources.ResourceDescription.Selector.MatchLabels) == 0) {
+					processExisting = func() bool {
+						rcreationTime := resource.GetCreationTimestamp()
+						pcreationTime := policy.GetCreationTimestamp()
+						return rcreationTime.Before(&pcreationTime)
+					}()
+				}
+			}
+		}
+
+		genResource, err := applyRule(log, c.client, rule, resource, ctx, policy.Name, gr, processExisting)
+
 		if err != nil {
 			return nil, err
 		}
@@ -217,7 +243,7 @@ func updateGenerateExecutionTime(newTime time.Duration, oldAverageTimeString str
 	return time.Duration(newAverageTimeInNanoSeconds) * time.Nanosecond
 }
 
-func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resource unstructured.Unstructured, ctx context.EvalInterface, policy string, gr kyverno.GenerateRequest) (kyverno.ResourceSpec, error) {
+func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resource unstructured.Unstructured, ctx context.EvalInterface, policy string, gr kyverno.GenerateRequest, processExisting bool) (kyverno.ResourceSpec, error) {
 	var rdata map[string]interface{}
 	var err error
 	var mode ResourceMode
@@ -227,7 +253,6 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
 	if err != nil {
 		return noGenResource, err
 	}
-
 	// Variable substitutions
 	// format : {{<variable_name}}
 	// - if there is variables that are not defined the context -> results in error and rule is not applied
@@ -255,7 +280,6 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
 	if err != nil {
 		return noGenResource, err
 	}
-
 	// Resource to be generated
 	newGenResource := kyverno.ResourceSpec{
 		APIVersion: genAPIVersion,
@@ -271,7 +295,6 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
 	if err != nil {
 		return noGenResource, err
 	}
-
 	if genData != nil {
 		rdata, mode, err = manageData(log, genAPIVersion, genKind, genNamespace, genName, genData, client, resource)
 	} else {
@@ -286,7 +309,9 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
 		// existing resource contains the configuration
 		return newGenResource, nil
 	}
-
+	if processExisting {
+		return noGenResource, nil
+	}
 	logger := log.WithValues("genKind", genKind, "genAPIVersion", genAPIVersion, "genNamespace", genNamespace, "genName", genName)
 
 	// build the resource template
@@ -297,24 +322,23 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
 	if newResource.GetKind() == "" {
 		newResource.SetKind(genKind)
 	}
+
 	newResource.SetAPIVersion(genAPIVersion)
 	// manage labels
 	// - app.kubernetes.io/managed-by: kyverno
 	// - kyverno.io/generated-by: kind/namespace/name (trigger resource)
 	manageLabels(newResource, resource)
-
 	// Add Synchronize label
 	label := newResource.GetLabels()
-	if rule.Generation.Synchronize {
-		label["policy.kyverno.io/synchronize"] = "enable"
-	} else {
-		label["policy.kyverno.io/synchronize"] = "disable"
-	}
 	label["policy.kyverno.io/policy-name"] = policy
 	label["policy.kyverno.io/gr-name"] = gr.Name
 	newResource.SetLabels(label)
-
 	if mode == Create {
+		if rule.Generation.Synchronize {
+			label["policy.kyverno.io/synchronize"] = "enable"
+		} else {
+			label["policy.kyverno.io/synchronize"] = "disable"
+		}
 		// Reset resource version
 		newResource.SetResourceVersion("")
 		// Create the resource
@@ -327,25 +351,48 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
 		logger.V(4).Info("created new resource")
 
 	} else if mode == Update {
+		var isUpdate bool
 		label := newResource.GetLabels()
-		if label != nil {
-			if rule.Generation.Synchronize {
-				logger.V(4).Info("updating existing resource")
-				// Update the resource
-				_, err := client.UpdateResource(genAPIVersion, genKind, genNamespace, newResource, false)
-				if err != nil {
-					logger.Error(err, "updating existing resource")
-					// Failed to update resource
-					return noGenResource, err
-				}
-				logger.V(4).Info("updated new resource")
-
-			} else {
-				logger.V(4).Info("Synchronize resource is disabled")
+		isUpdate = false
+		if rule.Generation.Synchronize {
+			if label["policy.kyverno.io/synchronize"] == "enable" {
+				isUpdate = true
 			}
 		} else {
-			logger.V(4).Info("Synchronize resource is disabled")
+			if label["policy.kyverno.io/synchronize"] == "enable" {
+				isUpdate = true
+			}
 		}
+		if rule.Generation.Synchronize {
+			label["policy.kyverno.io/synchronize"] = "enable"
+		} else {
+			label["policy.kyverno.io/synchronize"] = "disable"
+		}
+		if isUpdate {
+			logger.V(4).Info("updating existing resource")
+			// Update the resource
+			newResource.SetLabels(label)
+			_, err := client.UpdateResource(genAPIVersion, genKind, genNamespace, newResource, false)
+			if err != nil {
+				logger.Error(err, "updating existing resource")
+				// Failed to update resource
+				return noGenResource, err
+			}
+			logger.V(4).Info("updated new resource")
+		}else{
+			resource := &unstructured.Unstructured{}
+			resource.SetUnstructuredContent(rdata)
+			resource.SetLabels(label)
+			_, err := client.UpdateResource(genAPIVersion, genKind, genNamespace, resource, false)
+			if err != nil {
+				logger.Error(err, "updating existing resource")
+				// Failed to update resource
+				return noGenResource, err
+			}
+			logger.V(4).Info("updated new resource")
+		}
+		logger.V(4).Info("Synchronize resource is disabled")
+
 	}
 	return newGenResource, nil
 }
@@ -353,24 +400,19 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
 func manageData(log logr.Logger, apiVersion, kind, namespace, name string, data map[string]interface{}, client *dclient.Client, resource unstructured.Unstructured) (map[string]interface{}, ResourceMode, error) {
 	// check if resource to be generated exists
 	obj, err := client.GetResource(apiVersion, kind, namespace, name)
-	if apierrors.IsNotFound(err) {
-		log.Error(err, "resource does not exist, will try to create", "genKind", kind, "genAPIVersion", apiVersion, "genNamespace", namespace, "genName", name)
-		return data, Create, nil
-	}
 	if err != nil {
+		if apierrors.IsNotFound(err) {
+			log.Error(err, "resource does not exist, will try to create", "genKind", kind, "genAPIVersion", apiVersion, "genNamespace", namespace, "genName", name)
+			return data, Create, nil
+		}
 		//something wrong while fetching resource
 		// client-errors
 		return nil, Skip, err
 	}
-	// Resource exists; verfiy the content of the resource
-	err = checkResource(log, data, obj)
-	if err == nil {
-		// Existing resource does contain the mentioned configuration in spec, skip processing the resource as it is already in expected state
-		return nil, Skip, nil
-	}
-	log.Info("to be generated resoruce already exists, but is missing the specifeid configurations, will try to update", "genKind", kind, "genAPIVersion", apiVersion, "genNamespace", namespace, "genName", name)
-	return data, Update, nil
-
+	updateObj := &unstructured.Unstructured{}
+	updateObj.SetUnstructuredContent(data)
+	updateObj.SetResourceVersion(obj.GetResourceVersion())
+	return updateObj.UnstructuredContent(), Update, nil
 }
 
 func manageClone(log logr.Logger, apiVersion, kind, namespace, name string, clone map[string]interface{}, client *dclient.Client, resource unstructured.Unstructured) (map[string]interface{}, ResourceMode, error) {
@@ -409,13 +451,6 @@ func manageClone(log logr.Logger, apiVersion, kind, namespace, name string, clon
 		return obj.UnstructuredContent(), Update, nil
 	}
 
-	//TODO: check this
-	if !apierrors.IsNotFound(err) {
-		log.Error(err, "reference/clone resource is not found", "genKind", kind, "genAPIVersion", apiVersion, "genNamespace", namespace, "genName", name)
-		//something wrong while fetching resource
-		return nil, Skip, err
-	}
-
 	// create the resource based on the reference clone
 	return obj.UnstructuredContent(), Create, nil
 
diff --git a/pkg/policy/controller.go b/pkg/policy/controller.go
index 8cfc6c18f0..da5391d426 100644
--- a/pkg/policy/controller.go
+++ b/pkg/policy/controller.go
@@ -1,6 +1,9 @@
 package policy
 
 import (
+	"fmt"
+	"k8s.io/apimachinery/pkg/labels"
+	"math/rand"
 	"time"
 
 	informers "k8s.io/client-go/informers/core/v1"
@@ -58,6 +61,9 @@ type PolicyController struct {
 	// npLister can list/get namespace policy from the shared informer's store
 	npLister kyvernolister.PolicyLister
 
+	// grLister can list/get generate request from the shared informer's store
+	grLister kyvernolister.GenerateRequestLister
+
 	// pvLister can list/get policy violation from the shared informer's store
 	cpvLister kyvernolister.ClusterPolicyViolationLister
 
@@ -82,6 +88,8 @@ type PolicyController struct {
 	// nsListerSynced returns true if the namespace store has been synced at least once
 	nsListerSynced cache.InformerSynced
 
+	// grListerSynced returns true if the generate request store has been synced at least once
+	grListerSynced cache.InformerSynced
 	// Resource manager, manages the mapping for already processed resource
 	rm resourceManager
 
@@ -91,6 +99,7 @@ type PolicyController struct {
 	// policy violation generator
 	pvGenerator policyviolation.GeneratorInterface
 
+
 	// resourceWebhookWatcher queues the webhook creation request, creates the webhook
 	resourceWebhookWatcher *webhookconfig.ResourceWebhookRegister
 
@@ -104,6 +113,7 @@ func NewPolicyController(kyvernoClient *kyvernoclient.Clientset,
 	npInformer kyvernoinformer.PolicyInformer,
 	cpvInformer kyvernoinformer.ClusterPolicyViolationInformer,
 	nspvInformer kyvernoinformer.PolicyViolationInformer,
+	grInformer kyvernoinformer.GenerateRequestInformer,
 	configHandler config.Interface, eventGen event.Interface,
 	pvGenerator policyviolation.GeneratorInterface,
 	resourceWebhookWatcher *webhookconfig.ResourceWebhookRegister,
@@ -162,12 +172,13 @@ func NewPolicyController(kyvernoClient *kyvernoclient.Clientset,
 	pc.cpvLister = cpvInformer.Lister()
 	pc.nspvLister = nspvInformer.Lister()
 	pc.nsLister = namespaces.Lister()
-
+	pc.grLister = grInformer.Lister()
 	pc.pListerSynced = pInformer.Informer().HasSynced
 	pc.npListerSynced = npInformer.Informer().HasSynced
 	pc.cpvListerSynced = cpvInformer.Informer().HasSynced
 	pc.nspvListerSynced = nspvInformer.Informer().HasSynced
 	pc.nsListerSynced = namespaces.Informer().HasSynced
+	pc.grListerSynced = grInformer.Informer().HasSynced
 
 	// resource manager
 	// rebuild after 300 seconds/ 5 mins
@@ -308,7 +319,7 @@ func (pc *PolicyController) Run(workers int, stopCh <-chan struct{}) {
 	logger.Info("starting")
 	defer logger.Info("shutting down")
 
-	if !cache.WaitForCacheSync(stopCh, pc.pListerSynced, pc.cpvListerSynced, pc.nspvListerSynced, pc.nsListerSynced) {
+	if !cache.WaitForCacheSync(stopCh, pc.pListerSynced, pc.cpvListerSynced, pc.nspvListerSynced, pc.nsListerSynced,pc.grListerSynced) {
 		logger.Info("failed to sync informer cache")
 		return
 	}
@@ -373,6 +384,11 @@ func (pc *PolicyController) syncPolicy(key string) error {
 	namespace, key, isNamespacedPolicy := getIsNamespacedPolicy(key)
 	var policy *kyverno.ClusterPolicy
 	var err error
+	grList, err := pc.grLister.List(labels.Everything())
+	if err != nil {
+		logger.Error(err, "failed to list generate request")
+	}
+
 	if !isNamespacedPolicy {
 		policy, err = pc.pLister.Get(key)
 	} else {
@@ -380,9 +396,17 @@ func (pc *PolicyController) syncPolicy(key string) error {
 		nspolicy, err = pc.npLister.Policies(namespace).Get(key)
 		policy = convertPolicyToClusterPolicy(nspolicy)
 	}
-	if errors.IsNotFound(err) {
-		go pc.deletePolicyViolations(key)
 
+	if errors.IsNotFound(err) {
+		for _, v := range grList {
+			if key == v.Spec.Policy {
+				err := pc.kyvernoClient.KyvernoV1().GenerateRequests(config.KubePolicyNamespace).Delete(v.GetName(),&metav1.DeleteOptions{})
+				if err != nil {
+					logger.Error(err, "failed to delete gr")
+				}
+			}
+		}
+		go pc.deletePolicyViolations(key)
 		// remove webhook configurations if there are no policies
 		if err := pc.removeResourceWebhookConfiguration(); err != nil {
 			logger.Error(err, "failed to remove resource webhook configurations")
@@ -390,11 +414,20 @@ func (pc *PolicyController) syncPolicy(key string) error {
 
 		return nil
 	}
-
-	if err != nil {
-		return err
+	for _, v := range grList {
+		if policy.Name == v.Spec.Policy {
+			v.SetLabels(map[string]string{
+				"policy-update" :fmt.Sprintf("revision-count-%d",rand.Intn(100000)),
+			})
+			_,err := pc.kyvernoClient.KyvernoV1().GenerateRequests(config.KubePolicyNamespace).Update(v)
+			if err != nil {
+				logger.Error(err, "failed to update gr")
+				return err
+			}
+		}
 	}
 
+
 	pc.resourceWebhookWatcher.RegisterResourceWebhook()
 
 	engineResponses := pc.processExistingResources(policy)
diff --git a/pkg/webhooks/generate/generate.go b/pkg/webhooks/generate/generate.go
index 6066b674e5..c2a707c266 100644
--- a/pkg/webhooks/generate/generate.go
+++ b/pkg/webhooks/generate/generate.go
@@ -90,6 +90,7 @@ func (g *Generator) processApply() {
 
 func (g *Generator) generate(grSpec kyverno.GenerateRequestSpec, action v1beta1.Operation) error {
 	// create/update a generate request
+
 	if err := retryApplyResource(g.client, grSpec, g.log, action); err != nil {
 		return err
 	}
@@ -125,10 +126,10 @@ func retryApplyResource(client *kyvernoclient.Clientset,
 			}
 			for i, v := range grList.Items {
 				if grSpec.Policy == v.Spec.Policy && grSpec.Resource.Name == v.Spec.Resource.Name && grSpec.Resource.Kind == v.Spec.Resource.Kind && grSpec.Resource.Namespace == v.Spec.Resource.Namespace {
-
 					gr.SetLabels(map[string]string{
 						"resources-update": "true",
 					})
+
 					v.Spec.Context = gr.Spec.Context
 					v.Spec.Policy = gr.Spec.Policy
 					v.Spec.Resource = gr.Spec.Resource
diff --git a/pkg/webhooks/generation.go b/pkg/webhooks/generation.go
index dab3ef07eb..5f1a910c23 100644
--- a/pkg/webhooks/generation.go
+++ b/pkg/webhooks/generation.go
@@ -47,10 +47,11 @@ func (ws *WebhookServer) HandleGenerate(request *v1beta1.AdmissionRequest, polic
 	}
 
 	// engine.Generate returns a list of rules that are applicable on this resource
+	var rules []response.RuleResponse
 	for _, policy := range policies {
 		policyContext.Policy = *policy
 		engineResponse := engine.Generate(policyContext)
-		for i, rule := range engineResponse.PolicyResponse.Rules {
+		for _, rule := range engineResponse.PolicyResponse.Rules {
 			if !rule.Success {
 				grList, err := ws.kyvernoClient.KyvernoV1().GenerateRequests(config.KubePolicyNamespace).List(metav1.ListOptions{})
 				if err != nil {
@@ -64,15 +65,14 @@ func (ws *WebhookServer) HandleGenerate(request *v1beta1.AdmissionRequest, polic
 						}
 					}
 				}
-				if len(engineResponse.PolicyResponse.Rules) > 1 {
-					engineResponse.PolicyResponse.Rules = append(engineResponse.PolicyResponse.Rules[:i], engineResponse.PolicyResponse.Rules[i+1:]...)
-					continue
-				} else if len(engineResponse.PolicyResponse.Rules) == 1 {
-					engineResponse.PolicyResponse.Rules = []response.RuleResponse{}
-				}
+			}else{
+				rules = append(rules,rule)
 			}
 		}
-		if len(engineResponse.PolicyResponse.Rules) > 0 {
+
+
+		if len(rules) > 0 {
+			engineResponse.PolicyResponse.Rules = rules
 			// some generate rules do apply to the resource
 			engineResponses = append(engineResponses, engineResponse)
 			ws.statusListener.Send(generateStats{
@@ -81,6 +81,7 @@ func (ws *WebhookServer) HandleGenerate(request *v1beta1.AdmissionRequest, polic
 		}
 
 	}
+
 	// Adds Generate Request to a channel(queue size 1000) to generators
 	if failedResponse := applyGenerateRequest(ws.grGenerator, userRequestInfo, request.Operation, engineResponses...); err != nil {
 		// report failure event