1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-07 00:17:13 +00:00
kyverno/pkg/background/generate/cleanup.go
Shivam Kumar 30d475aaae
Passed the deleteOptions to the DeleteResource client (#11484)
* Passed the deleteOptions to the DeleteResource client

Signed-off-by: ShivamJha2436 <shivamkumar87148@gmail.com>

* fix:minor change in the DeleteResource client

Signed-off-by: ShivamJha2436 <shivamkumar87148@gmail.com>

---------

Signed-off-by: ShivamJha2436 <shivamkumar87148@gmail.com>
Co-authored-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
2024-11-19 09:26:17 +00:00

164 lines
6.7 KiB
Go

package generate
import (
"context"
"fmt"
"github.com/kyverno/kyverno/api/kyverno"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
kyvernov2 "github.com/kyverno/kyverno/api/kyverno/v2"
"github.com/kyverno/kyverno/pkg/background/common"
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
"go.uber.org/multierr"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
func (c *GenerateController) deleteDownstream(policy kyvernov1.PolicyInterface, ruleContext kyvernov2.RuleContext, ur *kyvernov2.UpdateRequest) (err error) {
// handle data policy/rule deletion
if ur.Status.GeneratedResources != nil {
c.log.V(4).Info("policy/rule no longer exists, deleting the downstream resource based on synchronize", "ur", ur.Name, "policy", ur.Spec.Policy)
var errs []error
failedDownstreams := []kyvernov1.ResourceSpec{}
for _, e := range ur.Status.GeneratedResources {
if err := c.client.DeleteResource(context.TODO(), e.GetAPIVersion(), e.GetKind(), e.GetNamespace(), e.GetName(), false, metav1.DeleteOptions{}); err != nil && !apierrors.IsNotFound(err) {
failedDownstreams = append(failedDownstreams, e)
errs = append(errs, err)
}
}
if len(errs) != 0 {
c.log.Error(multierr.Combine(errs...), "failed to clean up downstream resources on policy deletion")
_, err = c.statusControl.Failed(ur.GetName(),
fmt.Sprintf("failed to clean up downstream resources on policy deletion: %v", multierr.Combine(errs...)),
failedDownstreams)
} else {
_, err = c.statusControl.Success(ur.GetName(), nil)
}
return
}
if policy == nil {
return nil
}
return c.handleNonPolicyChanges(policy, ruleContext, ur)
}
func (c *GenerateController) handleNonPolicyChanges(policy kyvernov1.PolicyInterface, ruleContext kyvernov2.RuleContext, ur *kyvernov2.UpdateRequest) error {
logger := c.log.V(4).WithValues("ur", ur.Name, "policy", ur.Spec.Policy, "rule", ruleContext.Rule)
logger.Info("synchronize for none-policy changes")
for _, rule := range policy.GetSpec().Rules {
if ruleContext.Rule != rule.Name {
continue
}
logger.Info("deleting the downstream resource based on synchronize")
labels := map[string]string{
common.GeneratePolicyLabel: policy.GetName(),
common.GeneratePolicyNamespaceLabel: policy.GetNamespace(),
// common.GenerateRuleLabel: rule.Name,
kyverno.LabelAppManagedBy: kyverno.ValueKyvernoApp,
}
downstreams, err := c.getDownstreams(rule, labels, &ruleContext)
if err != nil {
return fmt.Errorf("failed to fetch downstream resources: %v", err)
}
if len(downstreams) == 0 {
logger.V(4).Info("no downstream resources found by label selectors", "labels", labels)
return nil
}
var errs []error
failedDownstreams := []kyvernov1.ResourceSpec{}
for _, downstream := range downstreams {
spec := common.ResourceSpecFromUnstructured(downstream)
if err := c.client.DeleteResource(context.TODO(), downstream.GetAPIVersion(), downstream.GetKind(), downstream.GetNamespace(), downstream.GetName(), false, metav1.DeleteOptions{}); err != nil && !apierrors.IsNotFound(err) {
failedDownstreams = append(failedDownstreams, spec)
errs = append(errs, err)
} else {
logger.Info("downstream resource deleted", "spec", spec.String())
}
}
if len(errs) != 0 {
_, err = c.statusControl.Failed(ur.GetName(),
fmt.Sprintf("failed to clean up downstream resources on source deletion: %v", multierr.Combine(errs...)),
failedDownstreams)
} else {
_, err = c.statusControl.Success(ur.GetName(), nil)
}
if err != nil {
logger.Error(err, "failed to update ur status")
}
}
return nil
}
func (c *GenerateController) getDownstreams(rule kyvernov1.Rule, selector map[string]string, ruleContext *kyvernov2.RuleContext) ([]unstructured.Unstructured, error) {
gv, err := ruleContext.Trigger.GetGroupVersion()
if err != nil {
return nil, err
}
selector[common.GenerateTriggerUIDLabel] = string(ruleContext.Trigger.GetUID())
selector[common.GenerateTriggerNSLabel] = ruleContext.Trigger.GetNamespace()
selector[common.GenerateTriggerKindLabel] = ruleContext.Trigger.GetKind()
selector[common.GenerateTriggerGroupLabel] = gv.Group
selector[common.GenerateTriggerVersionLabel] = gv.Version
for _, g := range rule.Generation.ForEachGeneration {
return c.fetch(g.GeneratePattern, selector, ruleContext)
}
return c.fetch(rule.Generation.GeneratePattern, selector, ruleContext)
}
func (c *GenerateController) fetch(generatePattern kyvernov1.GeneratePattern, selector map[string]string, ruleContext *kyvernov2.RuleContext) ([]unstructured.Unstructured, error) {
downstreamResources := []unstructured.Unstructured{}
if generatePattern.GetKind() != "" {
// Fetch downstream resources using trigger uid label
c.log.V(4).Info("fetching downstream resource by the UID", "APIVersion", generatePattern.GetAPIVersion(), "kind", generatePattern.GetKind(), "selector", selector)
dsList, err := common.FindDownstream(c.client, generatePattern.GetAPIVersion(), generatePattern.GetKind(), selector)
if err != nil {
return nil, err
}
if len(dsList.Items) == 0 {
// Fetch downstream resources using the trigger name label
delete(selector, common.GenerateTriggerUIDLabel)
selector[common.GenerateTriggerNameLabel] = ruleContext.Trigger.GetName()
c.log.V(4).Info("fetching downstream resource by the name", "APIVersion", generatePattern.GetAPIVersion(), "kind", generatePattern.GetKind(), "selector", selector)
dsList, err = common.FindDownstream(c.client, generatePattern.GetAPIVersion(), generatePattern.GetKind(), selector)
if err != nil {
return nil, err
}
}
downstreamResources = append(downstreamResources, dsList.Items...)
return downstreamResources, err
}
for _, kind := range generatePattern.CloneList.Kinds {
apiVersion, kind := kubeutils.GetKindFromGVK(kind)
c.log.V(4).Info("fetching downstream cloneList resources by the UID", "APIVersion", apiVersion, "kind", kind, "selector", selector)
dsList, err := common.FindDownstream(c.client, apiVersion, kind, selector)
if err != nil {
return nil, err
}
if len(dsList.Items) == 0 {
delete(selector, common.GenerateTriggerUIDLabel)
selector[common.GenerateTriggerNameLabel] = ruleContext.Trigger.GetName()
c.log.V(4).Info("fetching downstream resource by the name", "APIVersion", generatePattern.GetAPIVersion(), "kind", generatePattern.GetKind(), "selector", selector)
dsList, err = common.FindDownstream(c.client, generatePattern.GetAPIVersion(), generatePattern.GetKind(), selector)
if err != nil {
return nil, err
}
}
downstreamResources = append(downstreamResources, dsList.Items...)
}
return downstreamResources, nil
}