From 444549d9b75d563e5ddabfa1fc1a8d32b568d630 Mon Sep 17 00:00:00 2001 From: shivkumar dudhani Date: Fri, 28 Jun 2019 17:22:00 -0700 Subject: [PATCH] ctr get policy->client notfrom plister(kind empty) --- pkg/controller/controller.go | 7 +- pkg/dclient/client.go | 4 +- pkg/engine/mutation.go | 2 +- pkg/violation/builder.go | 133 ++++++++++++++++++++++++++--------- pkg/webhooks/server.go | 1 - 5 files changed, 110 insertions(+), 37 deletions(-) diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go index 8205904b13..01347ee09a 100644 --- a/pkg/controller/controller.go +++ b/pkg/controller/controller.go @@ -2,6 +2,7 @@ package controller import ( "fmt" + "reflect" "strings" "time" @@ -64,7 +65,11 @@ func (pc *PolicyController) createPolicyHandler(resource interface{}) { func (pc *PolicyController) updatePolicyHandler(oldResource, newResource interface{}) { newPolicy := newResource.(*types.Policy) oldPolicy := oldResource.(*types.Policy) - if newPolicy.ResourceVersion == oldPolicy.ResourceVersion { + newPolicy.Status = types.Status{} + oldPolicy.Status = types.Status{} + newPolicy.ResourceVersion = "" + oldPolicy.ResourceVersion = "" + if reflect.DeepEqual(newPolicy.ResourceVersion, oldPolicy.ResourceVersion) { return } pc.enqueuePolicy(newResource) diff --git a/pkg/dclient/client.go b/pkg/dclient/client.go index c2bb6e14ff..2fee1e7d82 100644 --- a/pkg/dclient/client.go +++ b/pkg/dclient/client.go @@ -107,8 +107,8 @@ func (c *Client) getGroupVersionMapper(resource string) schema.GroupVersionResou } // GetResource returns the resource in unstructured/json format -func (c *Client) GetResource(resource string, namespace string, name string) (*unstructured.Unstructured, error) { - return c.getResourceInterface(resource, namespace).Get(name, meta.GetOptions{}) +func (c *Client) GetResource(resource string, namespace string, name string, subresources ...string) (*unstructured.Unstructured, error) { + return c.getResourceInterface(resource, namespace).Get(name, meta.GetOptions{}, subresources...) } // ListResource returns the list of resources in unstructured/json format diff --git a/pkg/engine/mutation.go b/pkg/engine/mutation.go index e9c1a3501d..10d5bbda46 100644 --- a/pkg/engine/mutation.go +++ b/pkg/engine/mutation.go @@ -21,7 +21,7 @@ func Mutate(policy kubepolicy.Policy, rawResource []byte, gvk metav1.GroupVersio ok := ResourceMeetsDescription(rawResource, rule.ResourceDescription, gvk) if !ok { - glog.V(3).Info("Not applicable on specified resource kind%s", gvk.Kind) + glog.V(3).Infof("Not applicable on specified resource kind%s", gvk.Kind) continue } // Process Overlay diff --git a/pkg/violation/builder.go b/pkg/violation/builder.go index be94f1ad4a..d3dec2ac39 100644 --- a/pkg/violation/builder.go +++ b/pkg/violation/builder.go @@ -1,13 +1,15 @@ package violation import ( + "errors" + "reflect" + "github.com/golang/glog" types "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1" v1alpha1 "github.com/nirmata/kyverno/pkg/client/listers/policy/v1alpha1" client "github.com/nirmata/kyverno/pkg/dclient" event "github.com/nirmata/kyverno/pkg/event" "github.com/nirmata/kyverno/pkg/sharedinformer" - "k8s.io/client-go/tools/cache" ) //Generator to generate policy violation @@ -25,7 +27,7 @@ type builder struct { type Builder interface { Generator processViolation(info *Info) error - isActive(kind string, resource string) (bool, error) + isActive(kind string, rname string, rnamespace string) (bool, error) } //NewPolicyViolationBuilder returns new violation builder @@ -49,50 +51,116 @@ func (b *builder) Add(infos ...*Info) error { } func (b *builder) processViolation(info *Info) error { - policy, err := b.policyLister.Get(info.Policy) + currentViolations := []interface{}{} + statusMap := map[string]interface{}{} + var ok bool + //TODO: hack get from client + p1, err := b.client.GetResource("policies", "", info.Policy, "status") if err != nil { - glog.Error(err) return err } - modifiedPolicy := policy.DeepCopy() - modifiedViolations := []types.Violation{} - - // Create new violation - newViolation := info.Violation - - for _, violation := range modifiedPolicy.Status.Violations { - ok, err := b.isActive(info.Kind, violation.Name) - if err != nil { - glog.Error(err) - continue + unstr := p1.UnstructuredContent() + // check if "status" field exists + status, ok := unstr["status"] + if ok { + // status is already present then we append violations + if statusMap, ok = status.(map[string]interface{}); !ok { + return errors.New("Unable to parse status subresource") } + violations, ok := statusMap["violations"] if !ok { - glog.Info("removed violation") + glog.Info("violation not present") + } + glog.Info(reflect.TypeOf(violations)) + if currentViolations, ok = violations.([]interface{}); !ok { + return errors.New("Unable to parse violations") } } - // If violation already exists for this rule, we update the violation - //TODO: update violation, instead of re-creating one every time - modifiedViolations = append(modifiedViolations, newViolation) - - modifiedPolicy.Status.Violations = modifiedViolations - // Violations are part of the status sub resource, so we can use the Update Status api instead of updating the policy object - _, err = b.client.UpdateStatusResource("policies", "", modifiedPolicy, false) + newViolation := info.Violation + for _, violation := range currentViolations { + glog.Info(reflect.TypeOf(violation)) + if v, ok := violation.(map[string]interface{}); ok { + if name, ok := v["name"].(string); ok { + if namespace, ok := v["namespace"].(string); ok { + ok, err := b.isActive(info.Kind, name, namespace) + if err != nil { + glog.Error(err) + continue + } + if !ok { + //TODO remove the violation as it corresponds to resource that does not exist + glog.Info("removed violation") + } + } + } + } + } + currentViolations = append(currentViolations, newViolation) + // update violations + // set the updated status + statusMap["violations"] = currentViolations + unstr["status"] = statusMap + p1.SetUnstructuredContent(unstr) + _, err = b.client.UpdateStatusResource("policies", "", p1, false) if err != nil { return err } return nil + // modifiedViolations := []types.Violation{} + // modifiedViolations = append(modifiedViolations, types.Violation{Name: "name", Kind: "Deploymeny"}) + // unstr["status"] = modifiedViolations + // p1.SetUnstructuredContent(unstr) + // rdata, err := p1.MarshalJSON() + // if err != nil { + // glog.Info(err) + // } + // glog.Info(string(rdata)) + // _, err = b.client.UpdateStatusResource("policies", "", p1, false) + // if err != nil { + // glog.Info(err) + // } + + // p, err := b.policyLister.Get(info.Policy) + // if err != nil { + // glog.Error(err) + // return err + // } + + // glog.Info(p.TypeMeta.Kind) + // glog.Info(p.Kind) + // modifiedPolicy := p.DeepCopy() + // glog.Info(modifiedPolicy.Kind) + // // Create new violation + // newViolation := info.Violation + + // for _, violation := range modifiedPolicy.Status.Violations { + // ok, err := b.isActive(info.Kind, violation.Name) + // if err != nil { + // glog.Error(err) + // continue + // } + // if !ok { + // glog.Info("removed violation") + // } + // } + // // If violation already exists for this rule, we update the violation + // //TODO: update violation, instead of re-creating one every time + // modifiedViolations = append(modifiedViolations, newViolation) + // modifiedPolicy.Status.Violations = modifiedViolations + // // Violations are part of the status sub resource, so we can use the Update Status api instead of updating the policy object + // _, err = b.client.UpdateStatusResource("policies", "", *modifiedPolicy, false) + // if err != nil { + // glog.Info(err) + // return err + // } + // return nil } -func (b *builder) isActive(kind string, resource string) (bool, error) { - namespace, name, err := cache.SplitMetaNamespaceKey(resource) - if err != nil { - glog.Errorf("invalid resource key: %s", resource) - return false, err - } +func (b *builder) isActive(kind string, rname string, rnamespace string) (bool, error) { // Generate Merge Patch - _, err = b.client.GetResource(kind, namespace, name) + _, err := b.client.GetResource(b.client.DiscoveryClient.GetGVRFromKind(kind).Resource, rnamespace, rname) if err != nil { - glog.Errorf("unable to get resource %s ", resource) + glog.Errorf("unable to get resource %s/%s ", rnamespace, rname) return false, err } return true, nil @@ -118,7 +186,8 @@ func NewViolationFromEvent(e *event.Info, pName string, rKind string, rName stri Kind: rKind, Name: rName, Namespace: rnamespace, - Reason: e.Message, + Reason: e.Reason, + Message: e.Message, }, } } diff --git a/pkg/webhooks/server.go b/pkg/webhooks/server.go index 08dbb1c88e..e60cf4425f 100644 --- a/pkg/webhooks/server.go +++ b/pkg/webhooks/server.go @@ -149,7 +149,6 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest) *v1be var allPatches []engine.PatchBytes policyInfos := []*info.PolicyInfo{} for _, policy := range policies { - // check if policy has a rule for the admission request kind if !StringInSlice(request.Kind.Kind, getApplicableKindsForPolicy(policy)) { continue