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

[Improvement] Kyverno should not delete downstream resources when a generate policy using the clone behavior has synchronize: true (#1880)

* debuging issue

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

* issue fixed

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

* remove policy name in source resource

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

* fixed deletion of GR on source updation

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

* added function in common

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

* removing comments

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

* added generated resource list to the log

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

* small improvement

Signed-off-by: NoSkillGirl <singhpooja240393@gmail.com>
This commit is contained in:
Pooja Singh 2021-07-01 00:30:02 +05:30 committed by GitHub
parent 2c9e52af98
commit cd9e596e7e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 106 additions and 15 deletions

1
go.sum
View file

@ -1019,6 +1019,7 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.8.0 h1:nfhvjKcUMhBMVqbKHJlk5RPrrfYr/NMo3692g0dwfWU=
github.com/sirupsen/logrus v1.8.0/go.mod h1:4GuYW9TZmE769R5STWrRakJc4UqQ3+QQ95fyz7ENv1A=

View file

@ -7,6 +7,8 @@ import (
"time"
"github.com/go-logr/logr"
kyverno "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
dclient "github.com/kyverno/kyverno/pkg/dclient"
enginutils "github.com/kyverno/kyverno/pkg/engine/utils"
"github.com/pkg/errors"
v1 "k8s.io/api/core/v1"
@ -136,3 +138,47 @@ func RetryFunc(retryInterval, timeout time.Duration, run func() error, logger lo
return nil
}
}
func ProcessDeletePolicyForCloneGenerateRule(rules []kyverno.Rule, client *dclient.Client, pName string, logger logr.Logger) bool {
generatePolicyWithClone := false
for _, rule := range rules {
if rule.Generation.Clone.Name != "" {
logger.V(4).Info("generate policy with clone, skipping deletion of generate request")
generatePolicyWithClone = true
obj, err := 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
}
updateSource := true
label := obj.GetLabels()
logger.V(4).Info("removing policy name from label of source resource")
if len(label) != 0 {
if label["generate.kyverno.io/clone-policy-name"] != "" {
policyNames := label["generate.kyverno.io/clone-policy-name"]
if strings.Contains(policyNames, pName) {
updatedPolicyNames := strings.Replace(policyNames, pName, "", -1)
label["generate.kyverno.io/clone-policy-name"] = updatedPolicyNames
} else {
updateSource = false
}
}
}
if updateSource {
logger.V(4).Info("updating existing clone source")
obj.SetLabels(label)
_, err = client.UpdateResource(obj.GetAPIVersion(), rule.Generation.Kind, rule.Generation.Clone.Namespace, obj, false)
if err != nil {
logger.Error(err, "failed to update source", "kind", obj.GetKind(), "name", obj.GetName(), "namespace", obj.GetNamespace())
continue
}
logger.V(4).Info("updated source", "kind", obj.GetKind(), "name", obj.GetName(), "namespace", obj.GetNamespace())
}
}
}
return generatePolicyWithClone
}

View file

@ -10,10 +10,12 @@ import (
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
kyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
pkgCommon "github.com/kyverno/kyverno/pkg/common"
"github.com/kyverno/kyverno/pkg/config"
dclient "github.com/kyverno/kyverno/pkg/dclient"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/labels"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/dynamic/dynamicinformer"
@ -139,14 +141,37 @@ func (c *Controller) deletePolicy(obj interface{}) {
// clean up the GR
// Get the corresponding GR
// get the list of GR for the current Policy version
grs, err := c.grLister.GetGenerateRequestsForClusterPolicy(p.Name)
rules := p.Spec.Rules
generatePolicyWithClone := pkgCommon.ProcessDeletePolicyForCloneGenerateRule(rules, c.client, p.GetName(), logger)
// get the generated resource name from generate request for log
selector := labels.SelectorFromSet(labels.Set(map[string]string{
"generate.kyverno.io/policy-name": p.Name,
}))
grList, err := c.grLister.List(selector)
if err != nil {
logger.Error(err, "failed to generate request CR for the policy", "name", p.Name)
logger.Error(err, "failed to get generate request for the resource", "label", "generate.kyverno.io/policy-name")
return
}
for _, gr := range grs {
c.addGR(gr)
for _, gr := range grList {
for _, generatedResource := range gr.Status.GeneratedResources {
logger.Info("retaining resource", "APIVersion", generatedResource.APIVersion, "Kind", generatedResource.Kind, "Name", generatedResource.Name, "Nmaespace", generatedResource.Namespace)
}
}
if !generatePolicyWithClone {
grs, err := c.grLister.GetGenerateRequestsForClusterPolicy(p.Name)
if err != nil {
logger.Error(err, "failed to generate request CR for the policy", "name", p.Name)
return
}
for _, gr := range grs {
c.addGR(gr)
}
}
}

View file

@ -15,6 +15,7 @@ import (
"github.com/kyverno/kyverno/pkg/client/clientset/versioned/scheme"
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
kyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
pkgCommon "github.com/kyverno/kyverno/pkg/common"
"github.com/kyverno/kyverno/pkg/config"
client "github.com/kyverno/kyverno/pkg/dclient"
"github.com/kyverno/kyverno/pkg/event"
@ -341,8 +342,15 @@ func (pc *PolicyController) deletePolicy(obj interface{}) {
// we process policies that are not set of background processing
// as we need to clean up GRs when a policy is deleted
pc.enqueuePolicy(p)
pc.enqueueRCRDeletedPolicy(p.Name)
// skip generate policies with clone
rules := p.Spec.Rules
generatePolicyWithClone := pkgCommon.ProcessDeletePolicyForCloneGenerateRule(rules, pc.client, p.GetName(), logger)
if !generatePolicyWithClone {
pc.enqueuePolicy(p)
pc.enqueueRCRDeletedPolicy(p.Name)
}
}
func (pc *PolicyController) registerPolicyRuleInfoMetricAddNsPolicy(logger logr.Logger, p *kyverno.Policy) {

View file

@ -154,18 +154,29 @@ func (ws *WebhookServer) handleUpdate(request *v1beta1.AdmissionRequest, policie
func (ws *WebhookServer) handleUpdateCloneSourceResource(resLabels map[string]string, logger logr.Logger) {
policyNames := strings.Split(resLabels["generate.kyverno.io/clone-policy-name"], ",")
for _, policyName := range policyNames {
selector := labels.SelectorFromSet(labels.Set(map[string]string{
"generate.kyverno.io/policy-name": policyName,
}))
grList, err := ws.grLister.List(selector)
// check if the policy exists
_, err := ws.kyvernoClient.KyvernoV1().ClusterPolicies().Get(contextdefault.TODO(), policyName, metav1.GetOptions{})
if err != nil {
logger.Error(err, "failed to get generate request for the resource", "label", "generate.kyverno.io/policy-name")
return
}
for _, gr := range grList {
ws.updateAnnotationInGR(gr, logger)
if strings.Contains(err.Error(), "not found") {
logger.V(4).Info("skipping updation of generate request as policy is deleted")
} else {
logger.Error(err, "failed to get generate policy", "Name", policyName)
selector := labels.SelectorFromSet(labels.Set(map[string]string{
"generate.kyverno.io/policy-name": policyName,
}))
grList, err := ws.grLister.List(selector)
if err != nil {
logger.Error(err, "failed to get generate request for the resource", "label", "generate.kyverno.io/policy-name")
return
}
for _, gr := range grList {
ws.updateAnnotationInGR(gr, logger)
}
}
}
}
}