1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-28 10:28:36 +00:00

Merge branch 'master' into 120_policy_performance

This commit is contained in:
Shivkumar Dudhani 2019-08-07 18:57:00 -07:00 committed by GitHub
commit f9ad672027
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 101 additions and 74 deletions

View file

@ -34,9 +34,10 @@ metadata:
spec:
rules:
- name: check-pod-resources
resource:
kinds:
- Pod
match:
resources:
kinds:
- Pod
validate:
message: "CPU and memory resource requests and limits are required"
pattern:
@ -67,9 +68,10 @@ metadata:
spec:
rules:
- name: set-image-pull-policy
resource:
kinds:
- Deployment
match:
resources:
kinds:
- Deployment
mutate:
overlay:
spec:
@ -94,12 +96,13 @@ metadata:
spec:
rules:
- name: "zk-kafka-address"
resource:
kinds:
- Namespace
selector:
matchExpressions:
- {key: kafka, operator: Exists}
match:
resources:
kinds:
- Namespace
selector:
matchExpressions:
- {key: kafka, operator: Exists}
generate:
kind: ConfigMap
name: zk-kafka-address

View file

@ -1,7 +1,7 @@
apiVersion: kyverno.io/v1alpha1
kind: Policy
metadata:
name: "default-networkpolicy"
name: defaultgeneratenetworkpolicy
spec:
rules:
- name: "default-networkpolicy"
@ -12,7 +12,7 @@ spec:
name: "devtest"
generate:
kind: NetworkPolicy
name: default-networkpolicy
name: defaultnetworkpolicy
data:
spec:
# select all pods in the namespace

View file

@ -78,6 +78,16 @@ func (p *Policy) updatePolicy(obj *Policy, ruleType pinfo.RuleType) bool {
updates := false
// Check Mutation rules
switch ruleType {
case pinfo.All:
if p.compareMutationRules(obj.MutationRules) {
updates = true
}
if p.compareValidationRules(obj.ValidationRules) {
updates = true
}
if p.compareGenerationRules(obj.GenerationRules) {
updates = true
}
case pinfo.Mutation:
if p.compareMutationRules(obj.MutationRules) {
updates = true
@ -214,6 +224,59 @@ func ParseAnnotationsFromObject(bytes []byte) map[string]string {
return ann
}
func PatchAnnotations(ann map[string]string, pi *pinfo.PolicyInfo, ruleType pinfo.RuleType) ([]byte, error) {
if ruleType != pinfo.All && !pi.ContainsRuleType(ruleType) {
// the rule was not proceesed in the current policy application
return nil, nil
}
// transform the PolicyInfo to anotation struct
policyObj := newAnnotationForPolicy(pi)
if ann == nil {
ann = make(map[string]string, 0)
policyByte, err := json.Marshal(policyObj)
if err != nil {
return nil, err
}
// create a json patch to add annotation object
ann[BuildKeyString(pi.Name)] = string(policyByte)
// patch adds the annotation map with the policy information
jsonPatch, err := createAddJSONPatchMap(ann)
return jsonPatch, err
}
// if the annotations map already exists then we need to update it by adding a patch to the field inside the annotation
cPolicy, ok := ann[BuildKey(pi.Name)]
if !ok {
// annotations does not contain the policy
policyByte, err := json.Marshal(policyObj)
if err != nil {
return nil, err
}
jsonPatch, err := createAddJSONPatch(BuildKey(pi.Name), string(policyByte))
return jsonPatch, err
}
// an annotaion exists for the policy, we need to update the information if anything has changed
cPolicyObj := Policy{}
err := json.Unmarshal([]byte(cPolicy), &cPolicyObj)
if err != nil {
// error while unmarshallign the content
return nil, err
}
// update policy information inside the annotation
// 1> policy status
// 2> rule (name, status,changes,type)
update := cPolicyObj.updatePolicy(policyObj, ruleType)
if !update {
// there is not update, so we dont
return nil, nil
}
policyByte, err := json.Marshal(cPolicyObj)
if err != nil {
return nil, err
}
jsonPatch, err := createAddJSONPatch(BuildKey(pi.Name), string(policyByte))
return jsonPatch, err
}
//AddPolicyJSONPatch generate JSON Patch to add policy informatino JSON patch
func AddPolicyJSONPatch(ann map[string]string, pi *pinfo.PolicyInfo, ruleType pinfo.RuleType) (map[string]string, []byte, error) {
if !pi.ContainsRuleType(ruleType) {

View file

@ -5,8 +5,6 @@ import (
"reflect"
"time"
jsonpatch "github.com/evanphx/json-patch"
"github.com/nirmata/kyverno/pkg/annotations"
"github.com/nirmata/kyverno/pkg/info"
"github.com/nirmata/kyverno/pkg/utils"
@ -210,7 +208,6 @@ func (pc *PolicyController) syncHandler(obj interface{}) error {
func (pc *PolicyController) createAnnotations(policyInfos []*info.PolicyInfo) {
for _, pi := range policyInfos {
var patch []byte
//get resource
obj, err := pc.client.GetResource(pi.RKind, pi.RNamespace, pi.RName)
if err != nil {
@ -219,61 +216,14 @@ func (pc *PolicyController) createAnnotations(policyInfos []*info.PolicyInfo) {
}
// add annotation for policy application
ann := obj.GetAnnotations()
// Mutation rules
ann, mpatch, err := annotations.AddPolicyJSONPatch(ann, pi, info.Mutation)
if err != nil {
glog.Error(err)
continue
}
// Validation rules
ann, vpatch, err := annotations.AddPolicyJSONPatch(ann, pi, info.Validation)
if err != nil {
glog.Error(err)
}
// Generation rules
ann, gpatch, err := annotations.AddPolicyJSONPatch(ann, pi, info.Generation)
if err != nil {
glog.Error(err)
}
if mpatch == nil && vpatch == nil && gpatch == nil {
//nothing to patch
continue
}
// merge the patches
if mpatch != nil && vpatch != nil {
patch, err = jsonpatch.MergePatch(mpatch, vpatch)
if err != nil {
glog.Error(err)
continue
}
}
if mpatch == nil {
patch = vpatch
} else {
patch = mpatch
}
if gpatch != nil {
// generation
if patch != nil {
patch, err = jsonpatch.MergePatch(patch, gpatch)
if err != nil {
glog.Error(err)
continue
}
} else {
patch = gpatch
}
}
// if annotations are nil then create a map and patch
// else
// add the exact patch
patch, err := annotations.PatchAnnotations(ann, pi, info.All)
if patch == nil {
/// nothing to patch
return
}
// add the anotation to the resource
_, err = pc.client.PatchResource(pi.RKind, pi.RNamespace, pi.RName, patch)
if err != nil {
glog.Error(err)

View file

@ -21,7 +21,7 @@ func Generate(client *client.Client, policy *v1alpha1.Policy, ns unstructured.Un
continue
}
ri := info.NewRuleInfo(rule.Name, info.Generation)
err := applyRuleGenerator(client, ns, rule.Generation)
err := applyRuleGenerator(client, ns, rule.Generation, policy.Spec.ValidationFailureAction)
if err != nil {
ri.Fail()
ri.Addf("Rule %s: Failed to apply rule generator, err %v.", rule.Name, err)
@ -34,7 +34,7 @@ func Generate(client *client.Client, policy *v1alpha1.Policy, ns unstructured.Un
return ris
}
func applyRuleGenerator(client *client.Client, ns unstructured.Unstructured, gen *v1alpha1.Generation) error {
func applyRuleGenerator(client *client.Client, ns unstructured.Unstructured, gen *v1alpha1.Generation, validationFailureAction string) error {
var err error
resource := &unstructured.Unstructured{}
var rdata map[string]interface{}
@ -79,7 +79,16 @@ func applyRuleGenerator(client *client.Client, ns unstructured.Unstructured, gen
resource.SetNamespace(ns.GetName())
// Reset resource version
resource.SetResourceVersion("")
// TODO based on https://github.com/nirmata/kyverno/issues/268
// if validationFailureAction != "audit" {
// // if not audit, then enforce..
// // with enforce we will block the creation of resource and instead generate an error
// // the error will then create a policyViolation so that the resource owner can add the defaults
// return errors.New("policy flag validationFailureAction:'audit' blocked the creation of default resource for the namespace")
// }
// for "audit" mode, the resource will create the resource
// but wont generate a policy violation as the generate controller doesnt know if the generate request
// is a new resource via admission controller or via syncing its cache after a controller
_, err = client.CreateResource(gen.Kind, ns.GetName(), resource, false)
if err != nil {
return err

View file

@ -140,7 +140,7 @@ func (c *Controller) createAnnotations(pi *info.PolicyInfo) {
// add annotation for policy application
ann := obj.GetAnnotations()
// Generation rules
ann, gpatch, err := annotations.AddPolicyJSONPatch(ann, pi, info.Generation)
gpatch, err := annotations.PatchAnnotations(ann, pi, info.Generation)
if err != nil {
glog.Error(err)
return

View file

@ -99,6 +99,7 @@ const (
Mutation RuleType = iota
Validation
Generation
All
)
func (ri RuleType) String() string {
@ -106,6 +107,7 @@ func (ri RuleType) String() string {
"Mutation",
"Validation",
"Generation",
"All",
}[ri]
}

View file

@ -68,7 +68,7 @@ func addAnnotationsToResource(rawResource []byte, pi *info.PolicyInfo, ruleType
}
// get annotations
ann := annotations.ParseAnnotationsFromObject(rawResource)
ann, patch, err := annotations.AddPolicyJSONPatch(ann, pi, ruleType)
patch, err := annotations.PatchAnnotations(ann, pi, ruleType)
if err != nil {
glog.Error(err)
return nil