Skip to content

Commit

Permalink
Bug fix/1783 generate endlessly (#1804)
Browse files Browse the repository at this point in the history
* debug

Signed-off-by: NoSkillGirl <singhpooja240393@gmail.com>

* bug fix

Signed-off-by: NoSkillGirl <singhpooja240393@gmail.com>

* error handling

Signed-off-by: NoSkillGirl <singhpooja240393@gmail.com>

* added resource cache

Signed-off-by: NoSkillGirl <singhpooja240393@gmail.com>

* reverting back to api call attempt

Signed-off-by: NoSkillGirl <singhpooja240393@gmail.com>
  • Loading branch information
NoSkillGirl committed Apr 26, 2021
1 parent 1da4f74 commit 434a4cd
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 19 deletions.
4 changes: 3 additions & 1 deletion pkg/generate/generate.go
Expand Up @@ -377,7 +377,9 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
newResource.SetAPIVersion(genAPIVersion)
// manage labels
// - app.kubernetes.io/managed-by: kyverno
// - kyverno.io/generated-by: kind/namespace/name (trigger resource)
// "kyverno.io/generated-by-kind": kind (trigger resource)
// "kyverno.io/generated-by-namespace": namespace (trigger resource)
// "kyverno.io/generated-by-name": name (trigger resource)
manageLabels(newResource, resource)
// Add Synchronize label
label := newResource.GetLabels()
Expand Down
75 changes: 58 additions & 17 deletions pkg/webhooks/generation.go
Expand Up @@ -2,6 +2,7 @@ package webhooks

import (
contextdefault "context"
"encoding/json"
"fmt"
"reflect"
"sort"
Expand All @@ -14,10 +15,13 @@ import (
v1 "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/common"
"github.com/kyverno/kyverno/pkg/config"
client "github.com/kyverno/kyverno/pkg/dclient"
"github.com/kyverno/kyverno/pkg/engine"
"github.com/kyverno/kyverno/pkg/engine/context"
enginectx "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/response"
enginutils "github.com/kyverno/kyverno/pkg/engine/utils"
"github.com/kyverno/kyverno/pkg/engine/variables"
"github.com/kyverno/kyverno/pkg/event"
gen "github.com/kyverno/kyverno/pkg/generate"
kyvernoutils "github.com/kyverno/kyverno/pkg/utils"
Expand Down Expand Up @@ -147,27 +151,32 @@ func (ws *WebhookServer) handleUpdateTargetResource(request *v1beta1.AdmissionRe
if policy.GetName() == policyName {
for _, rule := range policy.Spec.Rules {
if rule.Generation.Kind == targetSourceKind && rule.Generation.Name == targetSourceName {
data := rule.Generation.DeepCopy().Data
if data != nil {
if _, err := gen.ValidateResourceWithPattern(logger, newRes.Object, data); err != nil {
enqueueBool = true
break
updatedRule, err := getGeneratedByResource(newRes, resLabels, ws.client, rule, logger)
if err != nil {
logger.V(4).Info("skipping generate policy and resource pattern validaton", "error", err)
} else {
data := updatedRule.Generation.DeepCopy().Data
if data != nil {
if _, err := gen.ValidateResourceWithPattern(logger, newRes.Object, data); err != nil {
enqueueBool = true
break
}
}
}

cloneName := rule.Generation.Clone.Name
if cloneName != "" {
obj, err := ws.client.GetResource("", rule.Generation.Kind, rule.Generation.Clone.Namespace, rule.Generation.Clone.Name)
if err != nil {
logger.Error(err, fmt.Sprintf("source resource %s/%s/%s not found.", rule.Generation.Kind, rule.Generation.Clone.Namespace, rule.Generation.Clone.Name))
continue
}
cloneName := updatedRule.Generation.Clone.Name
if cloneName != "" {
obj, err := ws.client.GetResource("", rule.Generation.Kind, rule.Generation.Clone.Namespace, rule.Generation.Clone.Name)
if err != nil {
logger.Error(err, fmt.Sprintf("source resource %s/%s/%s not found.", rule.Generation.Kind, rule.Generation.Clone.Namespace, rule.Generation.Clone.Name))
continue
}

sourceObj, newResObj := stripNonPolicyFields(obj.Object, newRes.Object, logger)
sourceObj, newResObj := stripNonPolicyFields(obj.Object, newRes.Object, logger)

if _, err := gen.ValidateResourceWithPattern(logger, newResObj, sourceObj); err != nil {
enqueueBool = true
break
if _, err := gen.ValidateResourceWithPattern(logger, newResObj, sourceObj); err != nil {
enqueueBool = true
break
}
}
}
}
Expand All @@ -186,6 +195,38 @@ func (ws *WebhookServer) handleUpdateTargetResource(request *v1beta1.AdmissionRe
}
}

func getGeneratedByResource(newRes *unstructured.Unstructured, resLabels map[string]string, client *client.Client, rule v1.Rule, logger logr.Logger) (v1.Rule, error) {
var apiVersion, kind, name, namespace string
sourceRequest := &v1beta1.AdmissionRequest{}
kind = resLabels["kyverno.io/generated-by-kind"]
name = resLabels["kyverno.io/generated-by-name"]
if kind != "Namespace" {
namespace = resLabels["kyverno.io/generated-by-namespace"]
}
obj, err := client.GetResource(apiVersion, kind, namespace, name)
if err != nil {
logger.Error(err, "source resource not found.")
return rule, err
}
rawObj, err := json.Marshal(obj)
if err != nil {
logger.Error(err, "failed to marshal resource")
return rule, err
}
sourceRequest.Object.Raw = rawObj
sourceRequest.Operation = "CREATE"
ctx := enginectx.NewContext()
if err := ctx.AddRequest(sourceRequest); err != nil {
logger.Error(err, "failed to load incoming request in context")
return rule, err
}
if rule, err = variables.SubstituteAllInRule(logger, ctx, rule); err != nil {
logger.Error(err, "variable substitution failed for rule %s", rule.Name)
return rule, err
}
return rule, nil
}

//stripNonPolicyFields - remove feilds which get updated with each request by kyverno and are non policy fields
func stripNonPolicyFields(obj, newRes map[string]interface{}, logger logr.Logger) (map[string]interface{}, map[string]interface{}) {

Expand Down
1 change: 0 additions & 1 deletion pkg/webhooks/server.go
Expand Up @@ -296,7 +296,6 @@ func writeResponse(rw http.ResponseWriter, admissionReview *v1beta1.AdmissionRev

// ResourceMutation mutates resource
func (ws *WebhookServer) ResourceMutation(request *v1beta1.AdmissionRequest) *v1beta1.AdmissionResponse {

logger := ws.log.WithName("ResourceMutation").WithValues("uid", request.UID, "kind", request.Kind.Kind, "namespace", request.Namespace, "name", request.Name, "operation", request.Operation)

if excludeKyvernoResources(request.Kind.Kind) {
Expand Down

0 comments on commit 434a4cd

Please sign in to comment.