diff --git a/pkg/apis/policy/v1alpha1/types_validation.go b/pkg/apis/policy/v1alpha1/types_validation.go
index 1330d3293f..32872f90bf 100644
--- a/pkg/apis/policy/v1alpha1/types_validation.go
+++ b/pkg/apis/policy/v1alpha1/types_validation.go
@@ -67,8 +67,7 @@ func (pr *PolicyResource) Validate() error {
 	}
 
 	if pr.Name != nil {
-		// // make non-regexp a regexp to match exactly to the given name
-		// *pr.Name = "^" + *pr.Name + "$"
+		// make non-regexp a regexp to match exactly to the given name
 		if _, err := regexp.Compile(*pr.Name); err != nil {
 			return fmt.Errorf("invalied regex, err: %v", err)
 		}
diff --git a/webhooks/admission.go b/webhooks/admission.go
index 6fcdcb4929..cf146e7ce1 100644
--- a/webhooks/admission.go
+++ b/webhooks/admission.go
@@ -1,7 +1,6 @@
 package webhooks
 
 import (
-	"fmt"
 	"regexp"
 
 	types "github.com/nirmata/kube-policy/pkg/apis/policy/v1alpha1"
@@ -64,7 +63,6 @@ func IsRuleApplicableToResource(kind string, resourceRaw []byte, policyResource
 		if policyResource.Name != nil {
 
 			policyResourceName, isRegex := parseRegexPolicyResourceName(*policyResource.Name)
-			fmt.Println("policyResourceName, name, isRegex", policyResourceName, name, isRegex)
 
 			// if no regex used, check if names are matched, return directly
 			if !isRegex && policyResourceName != name {
diff --git a/webhooks/mutation.go b/webhooks/mutation.go
index 722bfc4799..b787874f3f 100644
--- a/webhooks/mutation.go
+++ b/webhooks/mutation.go
@@ -6,6 +6,8 @@ import (
 	"log"
 	"os"
 
+	"github.com/nirmata/kube-policy/pkg/violation"
+
 	controller "github.com/nirmata/kube-policy/controller"
 	kubeclient "github.com/nirmata/kube-policy/kubeclient"
 	types "github.com/nirmata/kube-policy/pkg/apis/policy/v1alpha1"
@@ -104,59 +106,88 @@ func getPolicyPatchingSets(policy types.Policy) PatchingSets {
 // Applies all policy rules to the created object and returns list of processed JSON patches.
 // May return nil patches if it is not necessary to create patches for requested object.
 // Returns error ONLY in case when creation of resource should be denied.
-func (mw *MutationWebhook) applyPolicyRules(request *v1beta1.AdmissionRequest, policy types.Policy) ([]PatchBytes, int, error) {
+func (mw *MutationWebhook) applyPolicyRules(request *v1beta1.AdmissionRequest, policy types.Policy) ([]PatchBytes, []violation.Info, error) {
 	return mw.applyPolicyRulesOnResource(request.Kind.Kind, request.Object.Raw, policy)
 }
 
 // TODO: add another violation field in return elements
 // kind is the type of object being manipulated
-func (mw *MutationWebhook) applyPolicyRulesOnResource(kind string, rawResource []byte, policy types.Policy) ([]PatchBytes, int, error) {
+func (mw *MutationWebhook) applyPolicyRulesOnResource(kind string, rawResource []byte, policy types.Policy) ([]PatchBytes, []violation.Info, error) {
 	patchingSets := getPolicyPatchingSets(policy)
 	var policyPatches []PatchBytes
-	violationCount := 0
+	var violations []violation.Info
+
+	meta := parseMetadataFromObject(rawResource)
+	resourceKind := parseKindFromObject(rawResource)
+	resourceName := parseNameFromMetadata(meta)
+	ns := parseNamespaceFromMetadata(meta)
 
 	for ruleIdx, rule := range policy.Spec.Rules {
 		err := rule.Validate()
 		if err != nil {
 			mw.logger.Printf("Invalid rule detected: #%d in policy %s, err: %v\n", ruleIdx, policy.ObjectMeta.Name, err)
-			violationCount++
 			continue
 		}
 
 		if ok, err := IsRuleApplicableToResource(kind, rawResource, rule.Resource); !ok {
-			mw.logger.Printf("Rule %d of policy %s does not match the request", ruleIdx, policy.Name)
-			violationCount++
-			return nil, violationCount, err
+			mw.logger.Printf("Rule %d of policy %s is not applicable to the request", ruleIdx, policy.Name)
+			return nil, nil, err
 		}
 
 		// configMapGenerator and secretGenerator can be applied only to namespaces
 		if kind == "Namespace" {
 			err = mw.applyRuleGenerators(rawResource, rule)
-			if err != nil && patchingSets == PatchingSetsStopOnError {
-				violationCount++
-				return nil, violationCount, fmt.Errorf("Failed to apply generators from rule #%d: %s", ruleIdx, err)
+			if err != nil {
+				violations = append(violations, violation.Info{
+					Kind:     resourceKind,
+					Resource: ns + "/" + resourceName,
+					Policy:   policy.Name,
+					RuleName: string(ruleIdx),
+					Reason:   err.Error(),
+				})
+
+				if patchingSets == PatchingSetsStopOnError {
+					return nil, violations, fmt.Errorf("Failed to apply generators from rule #%d: %s", ruleIdx, err)
+				}
 			}
 		}
+
 		rulePatchesProcessed, err := ProcessPatches(rule.Patches, rawResource, patchingSets)
 		if err != nil {
-			violationCount++
-			return nil, violationCount, fmt.Errorf("Failed to process patches from rule #%d: %s", ruleIdx, err)
+			violations = append(violations, violation.Info{
+				Kind:     resourceKind,
+				Resource: ns + "/" + resourceName,
+				Policy:   policy.Name,
+				RuleName: string(ruleIdx),
+				Reason:   err.Error(),
+			})
+			return nil, violations, fmt.Errorf("Failed to process patches from rule #%d: %s", ruleIdx, err)
 		}
 
 		if rulePatchesProcessed != nil {
 			policyPatches = append(policyPatches, rulePatchesProcessed...)
 			mw.logger.Printf("Rule %d: prepared %d patches", ruleIdx, len(rulePatchesProcessed))
+
+			if len(rulePatchesProcessed) < len(rule.Patches) {
+				violations = append(violations, violation.Info{
+					Kind:     resourceKind,
+					Resource: ns + "/" + resourceName,
+					Policy:   policy.Name,
+					RuleName: string(ruleIdx),
+					Reason:   fmt.Sprintf("%v out of %v patches prepared", len(rulePatchesProcessed), len(rule.Patches)),
+				})
+			}
 		} else {
 			mw.logger.Printf("Rule %d: no patches prepared", ruleIdx)
 		}
 	}
 
-	// if no rules are validate, return error to deny resource creation
+	// empty patch, return error to deny resource creation
 	if policyPatches == nil {
-		return nil, violationCount, fmt.Errorf("no patches prepared, violations: %v", violationCount)
+		return nil, nil, fmt.Errorf("no patches prepared")
 	}
 
-	return policyPatches, violationCount, nil
+	return policyPatches, violations, nil
 }
 
 // Applies "configMapGenerator" and "secretGenerator" described in PolicyRule
diff --git a/webhooks/utils.go b/webhooks/utils.go
index 42a463681f..fcca09f150 100644
--- a/webhooks/utils.go
+++ b/webhooks/utils.go
@@ -14,6 +14,13 @@ func parseMetadataFromObject(bytes []byte) map[string]interface{} {
 	return objectJSON["metadata"].(map[string]interface{})
 }
 
+func parseKindFromObject(bytes []byte) string {
+	var objectJSON map[string]interface{}
+	json.Unmarshal(bytes, &objectJSON)
+
+	return objectJSON["kind"].(string)
+}
+
 func parseLabelsFromMetadata(meta map[string]interface{}) labels.Set {
 	if interfaceMap, ok := meta["labels"].(map[string]interface{}); ok {
 		labelMap := make(labels.Set, len(interfaceMap))