1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-31 03:45:17 +00:00

fix: avoid creating duplicate urs for background policies (#10431)

* feat: add generator abstraction

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* feat: replace urgenerator

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* fix: ko build

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* feat: load threshold from kyverno configmap

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* feat: add metadata client to get ur count

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* feat: add helm option to preserve configmap settings during upgrade

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* feat: add helm option to preserve configmap settings during upgrade 2

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* chore: rename imports

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* chore: update codegen manifests

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* fix: handle nil value

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* fix: linter issue

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* chore: update threshold to 1000

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* fix: avoid duplicate URs creation

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* fix: revert false changes

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* fix: simplify background applications

Signed-off-by: ShutingZhao <shuting@nirmata.com>

---------

Signed-off-by: ShutingZhao <shuting@nirmata.com>
This commit is contained in:
shuting 2024-06-12 23:23:53 +08:00 committed by GitHub
parent 73e6aaaae2
commit fe8c429e78
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 60 additions and 39 deletions

View file

@ -48,6 +48,7 @@ type UpdateRequestStatus struct {
// +kubebuilder:storageversion
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Policy",type="string",JSONPath=".spec.policy"
// +kubebuilder:printcolumn:name="Rule",type="string",JSONPath=".spec.rule"
// +kubebuilder:printcolumn:name="RuleType",type="string",JSONPath=".spec.requestType"
// +kubebuilder:printcolumn:name="ResourceKind",type="string",JSONPath=".spec.resource.kind"
// +kubebuilder:printcolumn:name="ResourceName",type="string",JSONPath=".spec.resource.name"

View file

@ -28,6 +28,9 @@ spec:
- jsonPath: .spec.policy
name: Policy
type: string
- jsonPath: .spec.rule
name: Rule
type: string
- jsonPath: .spec.requestType
name: RuleType
type: string

View file

@ -22,6 +22,9 @@ spec:
- jsonPath: .spec.policy
name: Policy
type: string
- jsonPath: .spec.rule
name: Rule
type: string
- jsonPath: .spec.requestType
name: RuleType
type: string

View file

@ -46169,6 +46169,9 @@ spec:
- jsonPath: .spec.policy
name: Policy
type: string
- jsonPath: .spec.rule
name: Rule
type: string
- jsonPath: .spec.requestType
name: RuleType
type: string

View file

@ -13,6 +13,7 @@ import (
"github.com/kyverno/kyverno/pkg/config"
"go.uber.org/multierr"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
func (pc *policyController) handleGenerate(policyKey string, policy kyvernov1.PolicyInterface) error {
@ -38,14 +39,19 @@ func (pc *policyController) handleGenerate(policyKey string, policy kyvernov1.Po
func (pc *policyController) handleGenerateForExisting(policy kyvernov1.PolicyInterface) error {
var errors []error
for _, rule := range policy.GetSpec().Rules {
var triggers []*unstructured.Unstructured
ruleType := kyvernov1beta1.Generate
triggers := getTriggers(pc.client, rule, policy.IsNamespaced(), policy.GetNamespace(), pc.log)
policyNew := policy.CreateDeepCopy()
policyNew.GetSpec().Rules = nil
for _, rule := range policy.GetSpec().Rules {
triggers = getTriggers(pc.client, rule, policy.IsNamespaced(), policy.GetNamespace(), pc.log)
policyNew.GetSpec().SetRules([]kyvernov1.Rule{rule})
for _, trigger := range triggers {
ur := newUR(policy, common.ResourceSpecFromUnstructured(*trigger), rule.Name, ruleType, false)
skip, err := pc.handleUpdateRequest(ur, trigger, rule, policy)
ur := newUR(policyNew, common.ResourceSpecFromUnstructured(*trigger), rule.Name, ruleType, false)
skip, err := pc.handleUpdateRequest(ur, trigger, rule.Name, policyNew)
if err != nil {
pc.log.Error(err, "failed to create new UR on policy update", "policy", policy.GetName(), "rule", rule.Name, "rule type", ruleType,
pc.log.Error(err, "failed to create new UR on policy update", "policy", policyNew.GetName(), "rule", rule.Name, "rule type", ruleType,
"target", fmt.Sprintf("%s/%s/%s/%s", trigger.GetAPIVersion(), trigger.GetKind(), trigger.GetNamespace(), trigger.GetName()))
errors = append(errors, err)
continue
@ -55,7 +61,7 @@ func (pc *policyController) handleGenerateForExisting(policy kyvernov1.PolicyInt
continue
}
pc.log.V(4).Info("successfully created UR on policy update", "policy", policy.GetName(), "rule", rule.Name, "rule type", ruleType,
pc.log.V(4).Info("successfully created UR on policy update", "policy", policyNew.GetName(), "rule", rule.Name, "rule type", ruleType,
"target", fmt.Sprintf("%s/%s/%s/%s", trigger.GetAPIVersion(), trigger.GetKind(), trigger.GetNamespace(), trigger.GetName()))
}
}
@ -112,15 +118,11 @@ func (pc *policyController) syncDataRulechanges(policy kyvernov1.PolicyInterface
labels := downstream.GetLabels()
trigger := generateutils.TriggerFromLabels(labels)
ur := newUR(policy, trigger, rule.Name, kyvernov1beta1.Generate, deleteDownstream)
created, err := pc.urGenerator.Generate(context.TODO(), pc.kyvernoClient, ur, pc.log)
created, err := pc.kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace()).Create(context.TODO(), ur, metav1.CreateOptions{})
if err != nil {
errorList = append(errorList, err)
continue
}
if created == nil {
continue
}
updated := created.DeepCopy()
updated.Status = newURStatus(downstream)
_, err = pc.kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace()).UpdateStatus(context.TODO(), updated, metav1.UpdateOptions{})

View file

@ -12,13 +12,19 @@ import (
func (pc *policyController) handleMutate(policyKey string, policy kyvernov1.PolicyInterface) error {
logger := pc.log.WithName("handleMutate").WithName(policyKey)
logger.Info("update URs on policy event")
ruleType := kyvernov1beta1.Mutate
policyNew := policy.CreateDeepCopy()
policyNew.GetSpec().Rules = nil
for _, rule := range policy.GetSpec().Rules {
var ruleType kyvernov1beta1.RequestType
if rule.HasMutateExisting() {
ruleType = kyvernov1beta1.Mutate
triggers := getTriggers(pc.client, rule, policy.IsNamespaced(), policy.GetNamespace(), pc.log)
if !rule.HasMutateExisting() {
continue
}
policyNew.GetSpec().SetRules([]kyvernov1.Rule{rule})
triggers := getTriggers(pc.client, rule, policyNew.IsNamespaced(), policyNew.GetNamespace(), pc.log)
for _, trigger := range triggers {
murs := pc.listMutateURs(policyKey, trigger)
if murs != nil {
@ -28,20 +34,19 @@ func (pc *policyController) handleMutate(policyKey string, policy kyvernov1.Poli
logger.Info("creating new UR for mutate")
ur := newUR(policy, backgroundcommon.ResourceSpecFromUnstructured(*trigger), rule.Name, ruleType, false)
skip, err := pc.handleUpdateRequest(ur, trigger, rule, policy)
skip, err := pc.handleUpdateRequest(ur, trigger, rule.Name, policyNew)
if err != nil {
pc.log.Error(err, "failed to create new UR on policy update", "policy", policy.GetName(), "rule", rule.Name, "rule type", ruleType,
pc.log.Error(err, "failed to create new UR on policy update", "policy", policyNew.GetName(), "rule", rule.Name, "rule type", ruleType,
"target", fmt.Sprintf("%s/%s/%s/%s", trigger.GetAPIVersion(), trigger.GetKind(), trigger.GetNamespace(), trigger.GetName()))
continue
}
if skip {
continue
}
pc.log.V(2).Info("successfully created UR on policy update", "policy", policy.GetName(), "rule", rule.Name, "rule type", ruleType,
pc.log.V(2).Info("successfully created UR on policy update", "policy", policyNew.GetName(), "rule", rule.Name, "rule type", ruleType,
"target", fmt.Sprintf("%s/%s/%s/%s", trigger.GetAPIVersion(), trigger.GetKind(), trigger.GetNamespace(), trigger.GetName()))
}
}
}
return nil
}

View file

@ -396,11 +396,11 @@ func (pc *policyController) requeuePolicies() {
}
}
func (pc *policyController) handleUpdateRequest(ur *kyvernov1beta1.UpdateRequest, triggerResource *unstructured.Unstructured, rule kyvernov1.Rule, policy kyvernov1.PolicyInterface) (skip bool, err error) {
func (pc *policyController) handleUpdateRequest(ur *kyvernov1beta1.UpdateRequest, triggerResource *unstructured.Unstructured, ruleName string, policy kyvernov1.PolicyInterface) (skip bool, err error) {
namespaceLabels := engineutils.GetNamespaceSelectorsFromNamespaceLister(triggerResource.GetKind(), triggerResource.GetNamespace(), pc.nsLister, pc.log)
policyContext, err := backgroundcommon.NewBackgroundContext(pc.log, pc.client, ur, policy, triggerResource, pc.configuration, pc.jp, namespaceLabels)
if err != nil {
return false, fmt.Errorf("failed to build policy context for rule %s: %w", rule.Name, err)
return false, fmt.Errorf("failed to build policy context for rule %s: %w", ruleName, err)
}
engineResponse := pc.engine.ApplyBackgroundChecks(context.TODO(), policyContext)
@ -410,7 +410,11 @@ func (pc *policyController) handleUpdateRequest(ur *kyvernov1beta1.UpdateRequest
for _, ruleResponse := range engineResponse.PolicyResponse.Rules {
if ruleResponse.Status() != engineapi.RuleStatusPass {
pc.log.V(4).Info("skip creating URs on policy update", "policy", policy.GetName(), "rule", rule.Name, "rule.Status", ruleResponse.Status())
pc.log.V(4).Info("skip creating URs on policy update", "policy", policy.GetName(), "rule", ruleName, "rule.Status", ruleResponse.Status())
continue
}
if ruleResponse.Name() != ur.Spec.GetRuleName() {
continue
}