From 53e2e38cd32c4c0d0db9a41bcb5dfb9e71a64580 Mon Sep 17 00:00:00 2001 From: NoSkillGirl Date: Wed, 16 Dec 2020 19:44:28 +0530 Subject: [PATCH] enqueing gr on getting deleted --- cmd/kyverno/main.go | 1 + pkg/generate/generate.go | 41 ++++++++++++----------------- pkg/generate/generate_controller.go | 5 ++++ pkg/webhooks/generate/generate.go | 4 +-- pkg/webhooks/generation.go | 1 - pkg/webhooks/server.go | 28 +++++++++++++++++--- 6 files changed, 50 insertions(+), 30 deletions(-) diff --git a/cmd/kyverno/main.go b/cmd/kyverno/main.go index ab39ffae77..707f0e54a1 100755 --- a/cmd/kyverno/main.go +++ b/cmd/kyverno/main.go @@ -328,6 +328,7 @@ func main() { log.Log.WithName("WebhookServer"), openAPIController, rCache, + grc, ) if err != nil { diff --git a/pkg/generate/generate.go b/pkg/generate/generate.go index 9540c1bb43..bfa7a82430 100644 --- a/pkg/generate/generate.go +++ b/pkg/generate/generate.go @@ -147,7 +147,7 @@ func (c *Controller) applyGenerate(resource unstructured.Unstructured, gr kyvern "policyName": engineResponse.PolicyResponse.Policy, "resourceName": engineResponse.PolicyResponse.Resource.Name, "resourceKind": engineResponse.PolicyResponse.Resource.Kind, - "ResourceNamespace": engineResponse.PolicyResponse.Resource.Namespace, + "resourceNamespace": engineResponse.PolicyResponse.Resource.Namespace, })) grList, err := c.grLister.List(selector) if err != nil { @@ -179,9 +179,7 @@ func updateStatus(statusControl StatusControlInterface, gr kyverno.GenerateReque return statusControl.Success(gr, genResources) } -func (c *Controller) applyGeneratePolicy(log logr.Logger, policyContext engine.PolicyContext, gr kyverno.GenerateRequest, applicableRules []string) ([]kyverno.ResourceSpec, error) { - // List of generatedResources - var genResources []kyverno.ResourceSpec +func (c *Controller) applyGeneratePolicy(log logr.Logger, policyContext engine.PolicyContext, gr kyverno.GenerateRequest, applicableRules []string) (genResources []kyverno.ResourceSpec, err error) { // Get the response as the actions to be performed on the resource // - - substitute values policy := policyContext.Policy @@ -203,14 +201,13 @@ func (c *Controller) applyGeneratePolicy(log logr.Logger, policyContext engine.P startTime := time.Now() processExisting := false + var genResource kyverno.ResourceSpec if len(rule.MatchResources.Kinds) > 0 { if len(rule.MatchResources.Annotations) == 0 && rule.MatchResources.Selector == nil { - processExisting = func() bool { - rcreationTime := resource.GetCreationTimestamp() - pcreationTime := policy.GetCreationTimestamp() - return rcreationTime.Before(&pcreationTime) - }() + rcreationTime := resource.GetCreationTimestamp() + pcreationTime := policy.GetCreationTimestamp() + processExisting = rcreationTime.Before(&pcreationTime) } } @@ -220,15 +217,16 @@ func (c *Controller) applyGeneratePolicy(log logr.Logger, policyContext engine.P return nil, err } - genResource, err := applyRule(log, c.client, rule, resource, jsonContext, policy.Name, gr, processExisting) - if err != nil { - log.Error(err, "failed to apply generate rule", "policy", policy.Name, - "rule", rule.Name, "resource", resource.GetName()) - return nil, err + if !processExisting { + genResource, err = applyRule(log, c.client, rule, resource, ctx, policy.Name, gr) + if err != nil { + log.Error(err, "failed to apply generate rule", "policy", policy.Name, + "rule", rule.Name, "resource", resource.GetName()) + return nil, err + } + ruleNameToProcessingTime[rule.Name] = time.Since(startTime) + genResources = append(genResources, genResource) } - - ruleNameToProcessingTime[rule.Name] = time.Since(startTime) - genResources = append(genResources, genResource) } if gr.Status.State == "" && len(genResources) > 0 { @@ -300,12 +298,11 @@ func getResourceInfo(object map[string]interface{}) (kind, name, namespace, apiv return } -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) { +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) { var rdata map[string]interface{} var err error var mode ResourceMode var noGenResource kyverno.ResourceSpec - genUnst, err := getUnstrRule(rule.Generation.DeepCopy()) if err != nil { return noGenResource, err @@ -364,10 +361,6 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou return newGenResource, nil } - if processExisting { - return noGenResource, nil - } - // build the resource template newResource := &unstructured.Unstructured{} newResource.SetUnstructuredContent(rdata) @@ -386,7 +379,6 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou label := newResource.GetLabels() 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" @@ -396,6 +388,7 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou // Reset resource version newResource.SetResourceVersion("") + newResource.SetLabels(label) // Create the resource _, err = client.CreateResource(genAPIVersion, genKind, genNamespace, newResource, false) if err != nil { diff --git a/pkg/generate/generate_controller.go b/pkg/generate/generate_controller.go index 3254173983..228d366de2 100644 --- a/pkg/generate/generate_controller.go +++ b/pkg/generate/generate_controller.go @@ -343,3 +343,8 @@ func (c *Controller) syncGenerateRequest(key string) error { return c.processGR(gr) } + +// EnqueueGenerateRequestFromWebhook - enqueing generate requests from webhook +func (c *Controller) EnqueueGenerateRequestFromWebhook(gr *kyverno.GenerateRequest) { + c.enqueueGenerateRequest(gr) +} diff --git a/pkg/webhooks/generate/generate.go b/pkg/webhooks/generate/generate.go index e264007c43..e13fe48f42 100644 --- a/pkg/webhooks/generate/generate.go +++ b/pkg/webhooks/generate/generate.go @@ -144,7 +144,7 @@ func retryApplyResource(client *kyvernoclient.Clientset, grSpec kyverno.Generate "policyName": grSpec.Policy, "resourceName": grSpec.Resource.Name, "resourceKind": grSpec.Resource.Kind, - "ResourceNamespace": grSpec.Resource.Namespace, + "resourceNamespace": grSpec.Resource.Namespace, })) grList, err := grLister.List(selector) if err != nil { @@ -174,7 +174,7 @@ func retryApplyResource(client *kyvernoclient.Clientset, grSpec kyverno.Generate "policyName": grSpec.Policy, "resourceName": grSpec.Resource.Name, "resourceKind": grSpec.Resource.Kind, - "ResourceNamespace": grSpec.Resource.Namespace, + "resourceNamespace": grSpec.Resource.Namespace, }) _, err = client.KyvernoV1().GenerateRequests(config.KyvernoNamespace).Create(context.TODO(), &gr, metav1.CreateOptions{}) if err != nil { diff --git a/pkg/webhooks/generation.go b/pkg/webhooks/generation.go index 03eef0bdc3..ef02fde804 100644 --- a/pkg/webhooks/generation.go +++ b/pkg/webhooks/generation.go @@ -59,7 +59,6 @@ func (ws *WebhookServer) HandleGenerate(request *v1beta1.AdmissionRequest, polic ws.deleteGR(logger, engineResponse) continue } - rules = append(rules, rule) } diff --git a/pkg/webhooks/server.go b/pkg/webhooks/server.go index 00585f5bb3..f2eb794700 100644 --- a/pkg/webhooks/server.go +++ b/pkg/webhooks/server.go @@ -19,7 +19,9 @@ import ( "github.com/kyverno/kyverno/pkg/config" client "github.com/kyverno/kyverno/pkg/dclient" context2 "github.com/kyverno/kyverno/pkg/engine/context" + enginutils "github.com/kyverno/kyverno/pkg/engine/utils" "github.com/kyverno/kyverno/pkg/event" + "github.com/kyverno/kyverno/pkg/generate" "github.com/kyverno/kyverno/pkg/openapi" "github.com/kyverno/kyverno/pkg/policycache" "github.com/kyverno/kyverno/pkg/policyreport" @@ -29,7 +31,7 @@ import ( userinfo "github.com/kyverno/kyverno/pkg/userinfo" "github.com/kyverno/kyverno/pkg/utils" "github.com/kyverno/kyverno/pkg/webhookconfig" - "github.com/kyverno/kyverno/pkg/webhooks/generate" + webhookgenerate "github.com/kyverno/kyverno/pkg/webhooks/generate" v1beta1 "k8s.io/api/admission/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" rbacinformer "k8s.io/client-go/informers/rbac/v1" @@ -104,7 +106,7 @@ type WebhookServer struct { prGenerator policyreport.GeneratorInterface // generate request generator - grGenerator *generate.Generator + grGenerator *webhookgenerate.Generator auditHandler AuditHandler @@ -116,6 +118,8 @@ type WebhookServer struct { // resCache - controls creation and fetching of resource informer cache resCache resourcecache.ResourceCacheIface + + grController *generate.Controller } // NewWebhookServer creates new instance of WebhookServer accordingly to given configuration @@ -137,13 +141,14 @@ func NewWebhookServer( statusSync policystatus.Listener, configHandler config.Interface, prGenerator policyreport.GeneratorInterface, - grGenerator *generate.Generator, + grGenerator *webhookgenerate.Generator, auditHandler AuditHandler, supportMutateValidate bool, cleanUp chan<- struct{}, log logr.Logger, openAPIController *openapi.Controller, resCache resourcecache.ResourceCacheIface, + grc *generate.Controller, ) (*WebhookServer, error) { if tlsPair == nil { @@ -182,6 +187,7 @@ func NewWebhookServer( webhookMonitor: webhookMonitor, prGenerator: prGenerator, grGenerator: grGenerator, + grController: grc, auditHandler: auditHandler, log: log, openAPIController: openAPIController, @@ -372,6 +378,22 @@ func (ws *WebhookServer) ResourceMutation(request *v1beta1.AdmissionRequest) *v1 func (ws *WebhookServer) resourceValidation(request *v1beta1.AdmissionRequest) *v1beta1.AdmissionResponse { logger := ws.log.WithName("Validate").WithValues("uid", request.UID, "kind", request.Kind.Kind, "namespace", request.Namespace, "name", request.Name, "operation", request.Operation) + if request.Operation == v1beta1.Delete { + resource, err := enginutils.ConvertToUnstructured(request.OldObject.Raw) + if err != nil { + logger.Error(err, "failed to convert object resource to unstructured format") + } + + resLabels := resource.GetLabels() + if resLabels["app.kubernetes.io/managed-by"] == "kyverno" && resLabels["policy.kyverno.io/synchronize"] == "enable" { + grName := resLabels["policy.kyverno.io/gr-name"] + gr, err := ws.grLister.Get(grName) + if err != nil { + logger.Error(err, "failed to get generate request", "name", grName) + } + ws.grController.EnqueueGenerateRequestFromWebhook(gr) + } + } if !ws.supportMutateValidate { logger.Info("mutate and validate rules are not supported prior to Kubernetes 1.14.0")