From f97406698dd5a67c913f0db39d268fa0fb3e6709 Mon Sep 17 00:00:00 2001
From: shivkumar dudhani <shivkumar@nirmata.com>
Date: Fri, 15 Nov 2019 12:03:58 -0800
Subject: [PATCH] remove namespace from resource spec

---
 pkg/api/kyverno/v1/types.go                  |   9 +-
 pkg/api/kyverno/v1/utils.go                  |  15 +-
 pkg/namespace/controller.go                  |   2 -
 pkg/policy/cleanup.go                        |   5 +-
 pkg/policy/controller.go                     |   2 +-
 pkg/policyviolation/clusterpv.go             | 152 +++++++++++++++
 pkg/policyviolation/controller.go            |  35 ++--
 pkg/policyviolation/generator.go             | 195 +------------------
 pkg/policyviolation/helpers.go               |  61 +++---
 pkg/policyviolation/namespacedpv.go          |  36 +++-
 pkg/policyviolation/namespacepvcontroller.go |  16 +-
 pkg/testrunner/scenario.go                   |   9 +-
 pkg/webhooks/report.go                       |   1 -
 13 files changed, 255 insertions(+), 283 deletions(-)
 create mode 100644 pkg/policyviolation/clusterpv.go

diff --git a/pkg/api/kyverno/v1/types.go b/pkg/api/kyverno/v1/types.go
index 0e90399be3..688ccfedc0 100644
--- a/pkg/api/kyverno/v1/types.go
+++ b/pkg/api/kyverno/v1/types.go
@@ -188,9 +188,8 @@ type PolicyViolationSpec struct {
 
 // ResourceSpec information to identify the resource
 type ResourceSpec struct {
-	Kind      string `json:"kind"`
-	Namespace string `json:"namespace,omitempty"`
-	Name      string `json:"name"`
+	Kind string `json:"kind"`
+	Name string `json:"name"`
 }
 
 // ViolatedRule stores the information regarding the rule
@@ -201,9 +200,10 @@ type ViolatedRule struct {
 	ManagedResource ManagedResourceSpec `json:"managedResource,omitempty"`
 }
 
+// ManagedResourceSpec is used when the violations is created on resource owner
+// to determing the kind of child resource that caused the violation
 type ManagedResourceSpec struct {
 	Kind            string `json:"kind,omitempty"`
-	Namespace       string `json:"namespace,omitempty"`
 	CreationBlocked bool   `json:"creationBlocked,omitempty"`
 }
 
@@ -212,5 +212,4 @@ type ManagedResourceSpec struct {
 //		LastUpdateTime : the time the polivy violation was updated
 type PolicyViolationStatus struct {
 	LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty"`
-	//TODO: having user information regarding the owner of resource can be helpful
 }
diff --git a/pkg/api/kyverno/v1/utils.go b/pkg/api/kyverno/v1/utils.go
index a330645929..31c755061b 100644
--- a/pkg/api/kyverno/v1/utils.go
+++ b/pkg/api/kyverno/v1/utils.go
@@ -57,18 +57,5 @@ func (gen *Generation) DeepCopyInto(out *Generation) {
 
 //ToKey generates the key string used for adding label to polivy violation
 func (rs ResourceSpec) ToKey() string {
-	if rs.Namespace == "" {
-		return rs.Kind + "." + rs.Name
-	}
-	return rs.Kind + "." + rs.Namespace + "." + rs.Name
-}
-
-//BuildKey builds the key
-func BuildResourceKey(kind, namespace, name string) string {
-	resource := ResourceSpec{
-		Kind:      kind,
-		Namespace: namespace,
-		Name:      name,
-	}
-	return resource.ToKey()
+	return rs.Kind + "." + rs.Name
 }
diff --git a/pkg/namespace/controller.go b/pkg/namespace/controller.go
index 4e4075ed74..d89ca6d19e 100644
--- a/pkg/namespace/controller.go
+++ b/pkg/namespace/controller.go
@@ -39,8 +39,6 @@ type NamespaceController struct {
 
 	//nsLister provides expansion to the namespace lister to inject GVK for the resource
 	nsLister NamespaceListerExpansion
-	// nLsister can list/get namespaces from the shared informer's store
-	// nsLister v1CoreLister.NamespaceLister
 	// nsListerSynced returns true if the Namespace store has been synced at least once
 	nsListerSynced cache.InformerSynced
 	// pvLister can list/get policy violation from the shared informer's store
diff --git a/pkg/policy/cleanup.go b/pkg/policy/cleanup.go
index 21a090d1cb..c52cffb312 100644
--- a/pkg/policy/cleanup.go
+++ b/pkg/policy/cleanup.go
@@ -152,7 +152,7 @@ func getNamespacedPVs(nspvLister kyvernolister.NamespacedPolicyViolationLister,
 }
 
 func getNamespacedPVOnResource(nspvLister kyvernolister.NamespacedPolicyViolationLister, policyName, kind, namespace, name string) (kyverno.NamespacedPolicyViolation, error) {
-	nspvs, err := nspvLister.List(labels.Everything())
+	nspvs, err := nspvLister.NamespacedPolicyViolations(namespace).List(labels.Everything())
 	if err != nil {
 		glog.V(2).Infof("failed to list namespaced pv: %v", err)
 		return kyverno.NamespacedPolicyViolation{}, fmt.Errorf("failed to list namespaced pv: %v", err)
@@ -162,7 +162,6 @@ func getNamespacedPVOnResource(nspvLister kyvernolister.NamespacedPolicyViolatio
 		// find a policy on same resource and policy combination
 		if nspv.Spec.Policy == policyName &&
 			nspv.Spec.ResourceSpec.Kind == kind &&
-			nspv.Spec.ResourceSpec.Namespace == namespace &&
 			nspv.Spec.ResourceSpec.Name == name {
 			return *nspv, nil
 		}
@@ -185,7 +184,7 @@ func getNamespacedPVonOwnerRef(nspvLister kyvernolister.NamespacedPolicyViolatio
 	// as we can have multiple top level owners to a resource
 	// check if pv exists on each one
 	for owner := range owners {
-		pv, err := getNamespacedPVOnResource(nspvLister, policyName, owner.Kind, owner.Namespace, owner.Name)
+		pv, err := getNamespacedPVOnResource(nspvLister, policyName, owner.Kind, namespace, owner.Name)
 		if err != nil {
 			glog.Errorf("error while fetching resource owners: %v", err)
 			continue
diff --git a/pkg/policy/controller.go b/pkg/policy/controller.go
index 7f40735750..7df41fc2c8 100644
--- a/pkg/policy/controller.go
+++ b/pkg/policy/controller.go
@@ -485,7 +485,7 @@ func (pc *PolicyController) syncPolicy(key string) error {
 	engineResponses := pc.processExistingResources(*p)
 	// report errors
 	pc.cleanupAndReport(engineResponses)
-	// fetch the policy again via the aggreagator to remain consistent
+	// sync active
 	return pc.syncStatusOnly(p, pvList, nspvList)
 }
 
diff --git a/pkg/policyviolation/clusterpv.go b/pkg/policyviolation/clusterpv.go
new file mode 100644
index 0000000000..26d50c790a
--- /dev/null
+++ b/pkg/policyviolation/clusterpv.go
@@ -0,0 +1,152 @@
+package policyviolation
+
+import (
+	"fmt"
+	"reflect"
+
+	"github.com/golang/glog"
+	kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
+	kyvernov1 "github.com/nirmata/kyverno/pkg/client/clientset/versioned/typed/kyverno/v1"
+	kyvernolister "github.com/nirmata/kyverno/pkg/client/listers/kyverno/v1"
+	client "github.com/nirmata/kyverno/pkg/dclient"
+	labels "k8s.io/apimachinery/pkg/labels"
+)
+
+func createPVS(dclient *client.Client, pvs []kyverno.ClusterPolicyViolation, pvLister kyvernolister.ClusterPolicyViolationLister, pvInterface kyvernov1.KyvernoV1Interface) error {
+	for _, pv := range pvs {
+		if err := createPVNew(dclient, pv, pvLister, pvInterface); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func (gen *Generator) createCusterPV(info Info) error {
+	var pvs []kyverno.ClusterPolicyViolation
+	if !info.Blocked {
+		pvs = append(pvs, buildPV(info))
+	} else {
+		// blocked
+		// get owners
+		pvs = buildPVWithOwners(gen.dclient, info)
+	}
+	// create policy violation
+	if err := createPVS(gen.dclient, pvs, gen.pvLister, gen.pvInterface); err != nil {
+		return err
+	}
+
+	glog.V(3).Infof("Created cluster policy violation policy=%s, resource=%s/%s/%s",
+		info.PolicyName, info.Resource.GetKind(), info.Resource.GetNamespace(), info.Resource.GetName())
+	return nil
+
+}
+func createPVNew(dclient *client.Client, pv kyverno.ClusterPolicyViolation, pvLister kyvernolister.ClusterPolicyViolationLister, pvInterface kyvernov1.KyvernoV1Interface) error {
+	var err error
+	// PV already exists
+	ePV, err := getExistingPVIfAny(pvLister, pv)
+	if err != nil {
+		glog.Error(err)
+		return fmt.Errorf("failed to get existing pv on resource '%s': %v", pv.Spec.ResourceSpec.ToKey(), err)
+	}
+	if ePV == nil {
+		// Create a New PV
+		glog.V(4).Infof("creating new policy violation for policy %s & resource %s/%s", pv.Spec.Policy, pv.Spec.ResourceSpec.Kind, pv.Spec.ResourceSpec.Name)
+		err := retryGetResource(pv.Namespace, dclient, pv.Spec.ResourceSpec)
+		if err != nil {
+			return fmt.Errorf("failed to retry getting resource for policy violation %s/%s: %v", pv.Name, pv.Spec.Policy, err)
+		}
+
+		_, err = pvInterface.ClusterPolicyViolations().Create(&pv)
+		if err != nil {
+			glog.Error(err)
+			return fmt.Errorf("failed to create cluster policy violation: %v", err)
+		}
+		glog.Infof("policy violation created for resource %v", pv.Spec.ResourceSpec)
+		return nil
+	}
+	// Update existing PV if there any changes
+	if reflect.DeepEqual(pv.Spec, ePV.Spec) {
+		glog.V(4).Infof("policy violation spec %v did not change so not updating it", pv.Spec)
+		return nil
+	}
+
+	pv.SetName(ePV.Name)
+	_, err = pvInterface.ClusterPolicyViolations().Update(&pv)
+	if err != nil {
+		glog.Error(err)
+		return fmt.Errorf("failed to update cluster polciy violation: %v", err)
+	}
+	glog.Infof("policy violation updated for resource %v", pv.Spec.ResourceSpec)
+	return nil
+}
+
+// build PV without owners
+func buildPV(info Info) kyverno.ClusterPolicyViolation {
+	pv := buildPVObj(info.PolicyName, kyverno.ResourceSpec{
+		Kind: info.Resource.GetKind(),
+		Name: info.Resource.GetName(),
+	}, info.Rules,
+	)
+	return pv
+}
+
+// build PV object
+func buildPVObj(policyName string, resourceSpec kyverno.ResourceSpec, rules []kyverno.ViolatedRule) kyverno.ClusterPolicyViolation {
+	pv := kyverno.ClusterPolicyViolation{
+		Spec: kyverno.PolicyViolationSpec{
+			Policy:        policyName,
+			ResourceSpec:  resourceSpec,
+			ViolatedRules: rules,
+		},
+	}
+
+	labelMap := map[string]string{
+		"policy":   policyName,
+		"resource": resourceSpec.ToKey(),
+	}
+	pv.SetLabels(labelMap)
+	pv.SetGenerateName("pv-")
+	return pv
+}
+
+// build PV with owners
+func buildPVWithOwners(dclient *client.Client, info Info) []kyverno.ClusterPolicyViolation {
+	var pvs []kyverno.ClusterPolicyViolation
+	// as its blocked resource, the violation is created on owner
+	ownerMap := map[kyverno.ResourceSpec]interface{}{}
+	GetOwner(dclient, ownerMap, info.Resource)
+
+	// standaloneresource, set pvResourceSpec with resource itself
+	if len(ownerMap) == 0 {
+		pvResourceSpec := kyverno.ResourceSpec{
+			Kind: info.Resource.GetKind(),
+			Name: info.Resource.GetName(),
+		}
+		return append(pvs, buildPVObj(info.PolicyName, pvResourceSpec, info.Rules))
+	}
+
+	// Generate owner on all owners
+	for owner := range ownerMap {
+		pv := buildPVObj(info.PolicyName, owner, info.Rules)
+		pvs = append(pvs, pv)
+	}
+	return pvs
+}
+
+func getExistingPVIfAny(pvLister kyvernolister.ClusterPolicyViolationLister, currpv kyverno.ClusterPolicyViolation) (*kyverno.ClusterPolicyViolation, error) {
+	pvs, err := pvLister.List(labels.Everything())
+	if err != nil {
+		glog.Errorf("unable to list policy violations : %v", err)
+		return nil, err
+	}
+
+	for _, pv := range pvs {
+		// find a policy on same resource and policy combination
+		if pv.Spec.Policy == currpv.Spec.Policy &&
+			pv.Spec.ResourceSpec.Kind == currpv.Spec.ResourceSpec.Kind &&
+			pv.Spec.ResourceSpec.Name == currpv.Spec.ResourceSpec.Name {
+			return pv, nil
+		}
+	}
+	return nil, nil
+}
diff --git a/pkg/policyviolation/controller.go b/pkg/policyviolation/controller.go
index 869d13ba8c..6f6a58429c 100644
--- a/pkg/policyviolation/controller.go
+++ b/pkg/policyviolation/controller.go
@@ -210,13 +210,13 @@ func (pvc *PolicyViolationController) syncPolicyViolation(key string) error {
 	// Deep-copy otherwise we are mutating our cache.
 	// TODO: Deep-copy only when needed.
 	pv := policyViolation.DeepCopy()
-	// TODO: Update Status to update ObserverdGeneration
-	// TODO: check if the policy violation refers to a resource thats active ? // done by policy controller
-	// TODO: remove the PV, if the corresponding policy is not present
-	// TODO: additional check on deleted webhook for a resource, to delete a policy violation it has a policy violation
-	// list the resource with label selectors, but this can be expensive for each delete request of a resource
+	// Check if the policy violation resource is active
 	if err := pvc.syncActiveResource(pv); err != nil {
-		glog.V(4).Infof("not syncing policy violation status")
+		return err
+	}
+	// If policy violations is on resource owner,
+	// check if the resource owner is active
+	if err := pvc.syncBlockedResource(pv); err != nil {
 		return err
 	}
 
@@ -227,30 +227,19 @@ func (pvc *PolicyViolationController) syncActiveResource(curPv *kyverno.ClusterP
 	// check if the resource is active or not ?
 	rspec := curPv.Spec.ResourceSpec
 	// get resource
-	_, err := pvc.client.GetResource(rspec.Kind, rspec.Namespace, rspec.Name)
+	_, err := pvc.client.GetResource(rspec.Kind, "", rspec.Name)
 	if errors.IsNotFound(err) {
-		// TODO: does it help to retry?
-		// resource is not found
-		// remove the violation
-
 		if err := pvc.pvControl.RemovePolicyViolation(curPv.Name); err != nil {
 			glog.Infof("unable to delete the policy violation %s: %v", curPv.Name, err)
 			return err
 		}
-		glog.V(4).Infof("removing policy violation %s as the corresponding resource %s/%s/%s does not exist anymore", curPv.Name, rspec.Kind, rspec.Namespace, rspec.Name)
+		glog.V(4).Infof("removing policy violation %s as the corresponding resource %s/%s does not exist anymore", curPv.Name, rspec.Kind, rspec.Name)
 		return nil
 	}
 	if err != nil {
-		glog.V(4).Infof("error while retrieved resource %s/%s/%s: %v", rspec.Kind, rspec.Namespace, rspec.Name, err)
+		glog.V(4).Infof("error while retrieved resource %s/%s: %v", rspec.Kind, rspec.Name, err)
 		return err
 	}
-
-	// cleanup pv with dependant
-	if err := pvc.syncBlockedResource(curPv); err != nil {
-		return err
-	}
-
-	//TODO- if the policy is not present, remove the policy violation
 	return nil
 }
 
@@ -264,7 +253,7 @@ func (pvc *PolicyViolationController) syncBlockedResource(curPv *kyverno.Cluster
 
 		// get resource
 		blockedResource := violatedRule.ManagedResource
-		resources, _ := pvc.client.ListResource(blockedResource.Kind, blockedResource.Namespace, nil)
+		resources, _ := pvc.client.ListResource(blockedResource.Kind, "", nil)
 
 		for _, resource := range resources.Items {
 			glog.V(4).Infof("getting owners for %s/%s/%s\n", resource.GetKind(), resource.GetNamespace(), resource.GetName())
@@ -286,8 +275,8 @@ func (pvc *PolicyViolationController) syncBlockedResource(curPv *kyverno.Cluster
 					glog.Infof("unable to delete the policy violation %s: %v", curPv.Name, err)
 					return err
 				}
-				glog.V(4).Infof("removed policy violation %s as the blocked resource %s/%s successfully created, owner: %s",
-					curPv.Name, blockedResource.Kind, blockedResource.Namespace, strings.ReplaceAll(curPv.Spec.ResourceSpec.ToKey(), ".", "/"))
+				glog.V(4).Infof("removed policy violation %s as the blocked resource %s successfully created, owner: %s",
+					curPv.Name, blockedResource.Kind, strings.ReplaceAll(curPv.Spec.ResourceSpec.ToKey(), ".", "/"))
 			}
 		}
 	}
diff --git a/pkg/policyviolation/generator.go b/pkg/policyviolation/generator.go
index cd9a715232..bb7b0c8744 100644
--- a/pkg/policyviolation/generator.go
+++ b/pkg/policyviolation/generator.go
@@ -1,7 +1,6 @@
 package policyviolation
 
 import (
-	"fmt"
 	"reflect"
 	"strconv"
 	"strings"
@@ -16,7 +15,6 @@ import (
 	client "github.com/nirmata/kyverno/pkg/dclient"
 	dclient "github.com/nirmata/kyverno/pkg/dclient"
 	unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
-	"k8s.io/apimachinery/pkg/labels"
 	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
 	"k8s.io/apimachinery/pkg/util/wait"
 	"k8s.io/client-go/util/workqueue"
@@ -201,195 +199,12 @@ func (gen *Generator) processNextWorkitem() bool {
 
 func (gen *Generator) syncHandler(info Info) error {
 	glog.V(4).Infof("recieved info:%v", info)
-	// cluster policy violations
+
+	// cluster scope resource generate a clusterpolicy violation
+	// namespaced resources generated a namespaced policy violation in the namespace of the resource
 	if info.Resource.GetNamespace() == "" {
-		var pvs []kyverno.ClusterPolicyViolation
-		if !info.Blocked {
-			pvs = append(pvs, buildPV(info))
-		} else {
-			// blocked
-			// get owners
-			pvs = buildPVWithOwners(gen.dclient, info)
-		}
-		// create policy violation
-		if err := createPVS(gen.dclient, pvs, gen.pvLister, gen.pvInterface); err != nil {
-			return err
-		}
-
-		glog.V(3).Infof("Created cluster policy violation policy=%s, resource=%s/%s/%s",
-			info.PolicyName, info.Resource.GetKind(), info.Resource.GetNamespace(), info.Resource.GetName())
-		return nil
+		return gen.createCusterPV(info)
 	}
+	return gen.createNamespacedPV(info)
 
-	// namespaced policy violations
-	var pvs []kyverno.NamespacedPolicyViolation
-	if !info.Blocked {
-		pvs = append(pvs, buildNamespacedPV(info))
-	} else {
-		pvs = buildNamespacedPVWithOwner(gen.dclient, info)
-	}
-
-	if err := createNamespacedPV(gen.dclient, gen.nspvLister, gen.pvInterface, pvs); err != nil {
-		return err
-	}
-
-	glog.V(3).Infof("Created namespaced policy violation policy=%s, resource=%s/%s/%s",
-		info.PolicyName, info.Resource.GetKind(), info.Resource.GetNamespace(), info.Resource.GetName())
-	return nil
-}
-
-func createPVS(dclient *client.Client, pvs []kyverno.ClusterPolicyViolation, pvLister kyvernolister.ClusterPolicyViolationLister, pvInterface kyvernov1.KyvernoV1Interface) error {
-	for _, pv := range pvs {
-		if err := createPVNew(dclient, pv, pvLister, pvInterface); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-func createPVNew(dclient *client.Client, pv kyverno.ClusterPolicyViolation, pvLister kyvernolister.ClusterPolicyViolationLister, pvInterface kyvernov1.KyvernoV1Interface) error {
-	var err error
-	// PV already exists
-	ePV, err := getExistingPVIfAny(pvLister, pv)
-	if err != nil {
-		glog.Error(err)
-		return fmt.Errorf("failed to get existing pv on resource '%s': %v", pv.Spec.ResourceSpec.ToKey(), err)
-	}
-	if ePV == nil {
-		// Create a New PV
-		glog.V(4).Infof("creating new policy violation for policy %s & resource %s/%s/%s", pv.Spec.Policy, pv.Spec.ResourceSpec.Kind, pv.Spec.ResourceSpec.Namespace, pv.Spec.ResourceSpec.Name)
-		err := retryGetResource(dclient, pv.Spec.ResourceSpec)
-		if err != nil {
-			return fmt.Errorf("failed to retry getting resource for policy violation %s/%s: %v", pv.Name, pv.Spec.Policy, err)
-		}
-
-		_, err = pvInterface.ClusterPolicyViolations().Create(&pv)
-		if err != nil {
-			glog.Error(err)
-			return fmt.Errorf("failed to create cluster policy violation: %v", err)
-		}
-		glog.Infof("policy violation created for resource %v", pv.Spec.ResourceSpec)
-		return nil
-	}
-	// Update existing PV if there any changes
-	if reflect.DeepEqual(pv.Spec, ePV.Spec) {
-		glog.V(4).Infof("policy violation spec %v did not change so not updating it", pv.Spec)
-		return nil
-	}
-
-	pv.SetName(ePV.Name)
-	_, err = pvInterface.ClusterPolicyViolations().Update(&pv)
-	if err != nil {
-		glog.Error(err)
-		return fmt.Errorf("failed to update cluster polciy violation: %v", err)
-	}
-	glog.Infof("policy violation updated for resource %v", pv.Spec.ResourceSpec)
-	return nil
-}
-
-func getExistingPVIfAny(pvLister kyvernolister.ClusterPolicyViolationLister, currpv kyverno.ClusterPolicyViolation) (*kyverno.ClusterPolicyViolation, error) {
-	pvs, err := pvLister.List(labels.Everything())
-	if err != nil {
-		glog.Errorf("unable to list policy violations : %v", err)
-		return nil, err
-	}
-
-	for _, pv := range pvs {
-		// find a policy on same resource and policy combination
-		if pv.Spec.Policy == currpv.Spec.Policy &&
-			pv.Spec.ResourceSpec.Kind == currpv.Spec.ResourceSpec.Kind &&
-			pv.Spec.ResourceSpec.Namespace == currpv.Spec.ResourceSpec.Namespace &&
-			pv.Spec.ResourceSpec.Name == currpv.Spec.ResourceSpec.Name {
-			return pv, nil
-		}
-	}
-	return nil, nil
-}
-
-// build PV without owners
-func buildPV(info Info) kyverno.ClusterPolicyViolation {
-	pv := buildPVObj(info.PolicyName, kyverno.ResourceSpec{
-		Kind:      info.Resource.GetKind(),
-		Namespace: info.Resource.GetNamespace(),
-		Name:      info.Resource.GetName(),
-	}, info.Rules,
-	)
-	return pv
-}
-
-// build PV object
-func buildPVObj(policyName string, resourceSpec kyverno.ResourceSpec, rules []kyverno.ViolatedRule) kyverno.ClusterPolicyViolation {
-	pv := kyverno.ClusterPolicyViolation{
-		Spec: kyverno.PolicyViolationSpec{
-			Policy:        policyName,
-			ResourceSpec:  resourceSpec,
-			ViolatedRules: rules,
-		},
-	}
-
-	labelMap := map[string]string{
-		"policy":   policyName,
-		"resource": resourceSpec.ToKey(),
-	}
-	pv.SetLabels(labelMap)
-	pv.SetGenerateName("pv-")
-	return pv
-}
-
-// build PV with owners
-func buildPVWithOwners(dclient *client.Client, info Info) []kyverno.ClusterPolicyViolation {
-	var pvs []kyverno.ClusterPolicyViolation
-	// as its blocked resource, the violation is created on owner
-	ownerMap := map[kyverno.ResourceSpec]interface{}{}
-	GetOwner(dclient, ownerMap, info.Resource)
-
-	// standaloneresource, set pvResourceSpec with resource itself
-	if len(ownerMap) == 0 {
-		pvResourceSpec := kyverno.ResourceSpec{
-			Namespace: info.Resource.GetNamespace(),
-			Kind:      info.Resource.GetKind(),
-			Name:      info.Resource.GetName(),
-		}
-		return append(pvs, buildPVObj(info.PolicyName, pvResourceSpec, info.Rules))
-	}
-
-	// Generate owner on all owners
-	for owner := range ownerMap {
-		pv := buildPVObj(info.PolicyName, owner, info.Rules)
-		pvs = append(pvs, pv)
-	}
-	return pvs
-}
-
-// GetOwner of a resource by iterating over ownerReferences
-func GetOwner(dclient *client.Client, ownerMap map[kyverno.ResourceSpec]interface{}, resource unstructured.Unstructured) {
-	var emptyInterface interface{}
-	resourceSpec := kyverno.ResourceSpec{
-		Kind:      resource.GetKind(),
-		Namespace: resource.GetNamespace(),
-		Name:      resource.GetName(),
-	}
-	if _, ok := ownerMap[resourceSpec]; ok {
-		// owner seen before
-		// breaking loop
-		return
-	}
-	rOwners := resource.GetOwnerReferences()
-	// if there are no resource owners then its top level resource
-	if len(rOwners) == 0 {
-		// add resource to map
-		ownerMap[resourceSpec] = emptyInterface
-		return
-	}
-	for _, rOwner := range rOwners {
-		// lookup resource via client
-		// owner has to be in same namespace
-		owner, err := dclient.GetResource(rOwner.Kind, resource.GetNamespace(), rOwner.Name)
-		if err != nil {
-			glog.Errorf("Failed to get resource owner for %s/%s/%s, err: %v", rOwner.Kind, resource.GetNamespace(), rOwner.Name, err)
-			// as we want to process other owners
-			continue
-		}
-		GetOwner(dclient, ownerMap, *owner)
-	}
 }
diff --git a/pkg/policyviolation/helpers.go b/pkg/policyviolation/helpers.go
index c771fe2c4f..19004ff692 100644
--- a/pkg/policyviolation/helpers.go
+++ b/pkg/policyviolation/helpers.go
@@ -7,6 +7,7 @@ import (
 
 	"github.com/golang/glog"
 	kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
+	client "github.com/nirmata/kyverno/pkg/dclient"
 	v1 "k8s.io/api/apps/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -30,21 +31,6 @@ func converLabelToSelector(labelMap map[string]string) (labels.Selector, error)
 	return policyViolationSelector, nil
 }
 
-func containsOwner(owners []kyverno.ResourceSpec, pvResourceSpec kyverno.ResourceSpec) bool {
-	curOwner := kyverno.ResourceSpec{
-		Kind:      pvResourceSpec.Kind,
-		Namespace: pvResourceSpec.Namespace,
-		Name:      pvResourceSpec.Name,
-	}
-
-	for _, targetOwner := range owners {
-		if reflect.DeepEqual(curOwner, targetOwner) {
-			return true
-		}
-	}
-	return false
-}
-
 // validDependantForDeployment checks if resource (pod) matches the intent of the given deployment
 // explicitly handles deployment-replicaset-pod relationship
 func validDependantForDeployment(client appsv1.AppsV1Interface, pvResourceSpec kyverno.ResourceSpec, resource unstructured.Unstructured) bool {
@@ -58,15 +44,14 @@ func validDependantForDeployment(client appsv1.AppsV1Interface, pvResourceSpec k
 	}
 
 	owner := kyverno.ResourceSpec{
-		Kind:      pvResourceSpec.Kind,
-		Namespace: pvResourceSpec.Namespace,
-		Name:      pvResourceSpec.Name,
+		Kind: pvResourceSpec.Kind,
+		Name: pvResourceSpec.Name,
 	}
 
 	start := time.Now()
-	deploy, err := client.Deployments(owner.Namespace).Get(owner.Name, metav1.GetOptions{})
+	deploy, err := client.Deployments(resource.GetNamespace()).Get(owner.Name, metav1.GetOptions{})
 	if err != nil {
-		glog.Errorf("failed to get resourceOwner deployment %s/%s/%s: %v", owner.Kind, owner.Namespace, owner.Name, err)
+		glog.Errorf("failed to get resourceOwner deployment %s/%s/%s: %v", owner.Kind, resource.GetNamespace(), owner.Name, err)
 		return false
 	}
 	glog.V(4).Infof("Time getting deployment %v", time.Since(start))
@@ -74,12 +59,12 @@ func validDependantForDeployment(client appsv1.AppsV1Interface, pvResourceSpec k
 	// TODO(shuting): replace typed client AppsV1Interface
 	expectReplicaset, err := deployutil.GetNewReplicaSet(deploy, client)
 	if err != nil {
-		glog.Errorf("failed to get replicaset owned by %s/%s/%s: %v", owner.Kind, owner.Namespace, owner.Name, err)
+		glog.Errorf("failed to get replicaset owned by %s/%s/%s: %v", owner.Kind, resource.GetNamespace(), owner.Name, err)
 		return false
 	}
 
 	if reflect.DeepEqual(expectReplicaset, v1.ReplicaSet{}) {
-		glog.V(2).Infof("no replicaset found for deploy %s/%s/%s", owner.Namespace, owner.Kind, owner.Name)
+		glog.V(2).Infof("no replicaset found for deploy %s/%s/%s", resource.GetNamespace(), owner.Kind, owner.Name)
 		return false
 	}
 	var actualReplicaset *v1.ReplicaSet
@@ -105,3 +90,35 @@ func validDependantForDeployment(client appsv1.AppsV1Interface, pvResourceSpec k
 	}
 	return false
 }
+
+// GetOwner of a resource by iterating over ownerReferences
+func GetOwner(dclient *client.Client, ownerMap map[kyverno.ResourceSpec]interface{}, resource unstructured.Unstructured) {
+	var emptyInterface interface{}
+	resourceSpec := kyverno.ResourceSpec{
+		Kind: resource.GetKind(),
+		Name: resource.GetName(),
+	}
+	if _, ok := ownerMap[resourceSpec]; ok {
+		// owner seen before
+		// breaking loop
+		return
+	}
+	rOwners := resource.GetOwnerReferences()
+	// if there are no resource owners then its top level resource
+	if len(rOwners) == 0 {
+		// add resource to map
+		ownerMap[resourceSpec] = emptyInterface
+		return
+	}
+	for _, rOwner := range rOwners {
+		// lookup resource via client
+		// owner has to be in same namespace
+		owner, err := dclient.GetResource(rOwner.Kind, resource.GetNamespace(), rOwner.Name)
+		if err != nil {
+			glog.Errorf("Failed to get resource owner for %s/%s/%s, err: %v", rOwner.Kind, resource.GetNamespace(), rOwner.Name, err)
+			// as we want to process other owners
+			continue
+		}
+		GetOwner(dclient, ownerMap, *owner)
+	}
+}
diff --git a/pkg/policyviolation/namespacedpv.go b/pkg/policyviolation/namespacedpv.go
index 2e270a9ad2..a2f9ef0c40 100644
--- a/pkg/policyviolation/namespacedpv.go
+++ b/pkg/policyviolation/namespacedpv.go
@@ -12,12 +12,29 @@ import (
 	labels "k8s.io/apimachinery/pkg/labels"
 )
 
+func (gen *Generator) createNamespacedPV(info Info) error {
+	// namespaced policy violations
+	var pvs []kyverno.NamespacedPolicyViolation
+	if !info.Blocked {
+		pvs = append(pvs, buildNamespacedPV(info))
+	} else {
+		pvs = buildNamespacedPVWithOwner(gen.dclient, info)
+	}
+
+	if err := createNamespacedPV(info.Resource.GetNamespace(), gen.dclient, gen.nspvLister, gen.pvInterface, pvs); err != nil {
+		return err
+	}
+
+	glog.V(3).Infof("Created namespaced policy violation policy=%s, resource=%s/%s/%s",
+		info.PolicyName, info.Resource.GetKind(), info.Resource.GetNamespace(), info.Resource.GetName())
+	return nil
+}
+
 func buildNamespacedPV(info Info) kyverno.NamespacedPolicyViolation {
 	return buildNamespacedPVObj(info.PolicyName,
 		kyverno.ResourceSpec{
-			Kind:      info.Resource.GetKind(),
-			Namespace: info.Resource.GetNamespace(),
-			Name:      info.Resource.GetName(),
+			Kind: info.Resource.GetKind(),
+			Name: info.Resource.GetName(),
 		},
 		info.Rules)
 }
@@ -49,9 +66,8 @@ func buildNamespacedPVWithOwner(dclient *dclient.Client, info Info) (pvs []kyver
 	// standaloneresource, set pvResourceSpec with resource itself
 	if len(ownerMap) == 0 {
 		pvResourceSpec := kyverno.ResourceSpec{
-			Namespace: info.Resource.GetNamespace(),
-			Kind:      info.Resource.GetKind(),
-			Name:      info.Resource.GetName(),
+			Kind: info.Resource.GetKind(),
+			Name: info.Resource.GetName(),
 		}
 		return append(pvs, buildNamespacedPVObj(info.PolicyName, pvResourceSpec, info.Rules))
 	}
@@ -62,7 +78,7 @@ func buildNamespacedPVWithOwner(dclient *dclient.Client, info Info) (pvs []kyver
 	return
 }
 
-func createNamespacedPV(dclient *dclient.Client, pvLister kyvernolister.NamespacedPolicyViolationLister, pvInterface kyvernov1.KyvernoV1Interface, pvs []kyverno.NamespacedPolicyViolation) error {
+func createNamespacedPV(namespace string, dclient *dclient.Client, pvLister kyvernolister.NamespacedPolicyViolationLister, pvInterface kyvernov1.KyvernoV1Interface, pvs []kyverno.NamespacedPolicyViolation) error {
 	for _, newPv := range pvs {
 		glog.V(4).Infof("creating namespaced policyViolation resource for policy %s and resource %s", newPv.Spec.Policy, newPv.Spec.ResourceSpec.ToKey())
 		// check if there was a previous policy voilation for policy & resource combination
@@ -76,11 +92,11 @@ func createNamespacedPV(dclient *dclient.Client, pvLister kyvernolister.Namespac
 			if reflect.DeepEqual(curPv, kyverno.NamespacedPolicyViolation{}) {
 				glog.V(4).Infof("creating new namespaced policy violation for policy %s & resource %s", newPv.Spec.Policy, newPv.Spec.ResourceSpec.ToKey())
 
-				if err := retryGetResource(dclient, newPv.Spec.ResourceSpec); err != nil {
+				if err := retryGetResource(newPv.Namespace, dclient, newPv.Spec.ResourceSpec); err != nil {
 					return fmt.Errorf("failed to get resource for policy violation on resource '%s': %v", newPv.Spec.ResourceSpec.ToKey(), err)
 				}
 
-				if _, err := pvInterface.NamespacedPolicyViolations(newPv.Spec.ResourceSpec.Namespace).Create(&newPv); err != nil {
+				if _, err := pvInterface.NamespacedPolicyViolations(namespace).Create(&newPv); err != nil {
 					return fmt.Errorf("failed to create namespaced policy violation: %v", err)
 				}
 
@@ -104,7 +120,7 @@ func createNamespacedPV(dclient *dclient.Client, pvLister kyvernolister.Namespac
 		glog.V(4).Infof("creating new policy violation for policy %s & resource %s", curPv.Spec.Policy, curPv.Spec.ResourceSpec.ToKey())
 		//TODO: using a generic name, but would it be helpful to have naming convention for policy violations
 		// as we can only have one policy violation for each (policy + resource) combination
-		if _, err = pvInterface.NamespacedPolicyViolations(newPv.Spec.ResourceSpec.Namespace).Update(&newPv); err != nil {
+		if _, err = pvInterface.NamespacedPolicyViolations(namespace).Update(&newPv); err != nil {
 			return fmt.Errorf("failed to update namespaced policy violation: %v", err)
 		}
 		glog.Infof("namespaced policy violation updated for resource %s", newPv.Spec.ResourceSpec.ToKey())
diff --git a/pkg/policyviolation/namespacepvcontroller.go b/pkg/policyviolation/namespacepvcontroller.go
index 59e1455807..96d0257a32 100644
--- a/pkg/policyviolation/namespacepvcontroller.go
+++ b/pkg/policyviolation/namespacepvcontroller.go
@@ -226,7 +226,7 @@ func (pvc *NamespacedPolicyViolationController) syncActiveResource(curPv *kyvern
 	// check if the resource is active or not ?
 	rspec := curPv.Spec.ResourceSpec
 	// get resource
-	_, err := pvc.client.GetResource(rspec.Kind, rspec.Namespace, rspec.Name)
+	_, err := pvc.client.GetResource(rspec.Kind, curPv.Namespace, rspec.Name)
 	if errors.IsNotFound(err) {
 		// TODO: does it help to retry?
 		// resource is not found
@@ -236,11 +236,11 @@ func (pvc *NamespacedPolicyViolationController) syncActiveResource(curPv *kyvern
 			glog.Infof("unable to delete the policy violation %s: %v", curPv.Name, err)
 			return err
 		}
-		glog.V(4).Infof("removing policy violation %s as the corresponding resource %s/%s/%s does not exist anymore", curPv.Name, rspec.Kind, rspec.Namespace, rspec.Name)
+		glog.V(4).Infof("removing policy violation %s as the corresponding resource %s/%s/%s does not exist anymore", curPv.Name, rspec.Kind, curPv.Namespace, rspec.Name)
 		return nil
 	}
 	if err != nil {
-		glog.V(4).Infof("error while retrieved resource %s/%s/%s: %v", rspec.Kind, rspec.Namespace, rspec.Name, err)
+		glog.V(4).Infof("error while retrieved resource %s/%s/%s: %v", rspec.Kind, curPv.Namespace, rspec.Name, err)
 		return err
 	}
 
@@ -263,7 +263,7 @@ func (pvc *NamespacedPolicyViolationController) syncBlockedResource(curPv *kyver
 
 		// get resource
 		blockedResource := violatedRule.ManagedResource
-		resources, _ := pvc.client.ListResource(blockedResource.Kind, blockedResource.Namespace, nil)
+		resources, _ := pvc.client.ListResource(blockedResource.Kind, curPv.Namespace, nil)
 
 		for _, resource := range resources.Items {
 			glog.V(4).Infof("getting owners for %s/%s/%s\n", resource.GetKind(), resource.GetNamespace(), resource.GetName())
@@ -285,7 +285,7 @@ func (pvc *NamespacedPolicyViolationController) syncBlockedResource(curPv *kyver
 					return err
 				}
 				glog.V(4).Infof("removed policy violation %s as the blocked resource %s/%s successfully created, owner: %s",
-					curPv.Name, blockedResource.Kind, blockedResource.Namespace, strings.ReplaceAll(curPv.Spec.ResourceSpec.ToKey(), ".", "/"))
+					curPv.Name, blockedResource.Kind, curPv.Namespace, strings.ReplaceAll(curPv.Spec.ResourceSpec.ToKey(), ".", "/"))
 			}
 		}
 	}
@@ -341,11 +341,11 @@ func (r RealNamespacedPVControl) RemovePolicyViolation(ns, name string) error {
 	return r.Client.KyvernoV1().NamespacedPolicyViolations(ns).Delete(name, &metav1.DeleteOptions{})
 }
 
-func retryGetResource(client *client.Client, rspec kyverno.ResourceSpec) error {
+func retryGetResource(namespace string, client *client.Client, rspec kyverno.ResourceSpec) error {
 	var i int
 	getResource := func() error {
-		_, err := client.GetResource(rspec.Kind, rspec.Namespace, rspec.Name)
-		glog.V(5).Infof("retry %v getting %s/%s/%s", i, rspec.Kind, rspec.Namespace, rspec.Name)
+		_, err := client.GetResource(rspec.Kind, namespace, rspec.Name)
+		glog.V(5).Infof("retry %v getting %s/%s/%s", i, rspec.Kind, namespace, rspec.Name)
 		i++
 		return err
 	}
diff --git a/pkg/testrunner/scenario.go b/pkg/testrunner/scenario.go
index 5d23fdaf57..752989bef9 100644
--- a/pkg/testrunner/scenario.go
+++ b/pkg/testrunner/scenario.go
@@ -181,7 +181,8 @@ func runTestCase(t *testing.T, tc scaseT) bool {
 			er = engine.Generate(policyContext)
 			t.Log(("---Generation---"))
 			validateResponse(t, er.PolicyResponse, tc.Expected.Generation.PolicyResponse)
-			validateGeneratedResources(t, client, *policy, tc.Expected.Generation.GeneratedResources)
+			// Expected generate resource will be in same namesapces as resource
+			validateGeneratedResources(t, client, *policy, resource.GetName(), tc.Expected.Generation.GeneratedResources)
 		}
 	}
 	return true
@@ -191,12 +192,12 @@ func createNamespace(client *client.Client, ns *unstructured.Unstructured) error
 	_, err := client.CreateResource("Namespace", "", ns, false)
 	return err
 }
-func validateGeneratedResources(t *testing.T, client *client.Client, policy kyverno.ClusterPolicy, expected []kyverno.ResourceSpec) {
+func validateGeneratedResources(t *testing.T, client *client.Client, policy kyverno.ClusterPolicy, namespace string, expected []kyverno.ResourceSpec) {
 	t.Log("--validate if resources are generated---")
 	// list of expected generated resources
 	for _, resource := range expected {
-		if _, err := client.GetResource(resource.Kind, resource.Namespace, resource.Name); err != nil {
-			t.Errorf("generated resource %s/%s/%s not found. %v", resource.Kind, resource.Namespace, resource.Name, err)
+		if _, err := client.GetResource(resource.Kind, namespace, resource.Name); err != nil {
+			t.Errorf("generated resource %s/%s/%s not found. %v", resource.Kind, namespace, resource.Name, err)
 		}
 	}
 }
diff --git a/pkg/webhooks/report.go b/pkg/webhooks/report.go
index ede22a20f5..516f164700 100644
--- a/pkg/webhooks/report.go
+++ b/pkg/webhooks/report.go
@@ -128,7 +128,6 @@ func buildViolatedRules(er engine.EngineResponse, blocked bool) []kyverno.Violat
 	// if resource was blocked we create dependent
 	dependant := kyverno.ManagedResourceSpec{
 		Kind:            er.PolicyResponse.Resource.Kind,
-		Namespace:       er.PolicyResponse.Resource.Namespace,
 		CreationBlocked: true,
 	}