1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2024-12-14 11:57:48 +00:00

Fix flaky e2e tests for generate policies (#3681)

* fix flaky generate e2e tests

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

* enable validate, verifyimage e2e tests

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

* set policy names different within a single test

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

* do not delete cloned resource when sync generate policy is deleted

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

* replace grLister by urLister

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

* re-queue pending URs only to fix clone policy deletion

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

* remove duplicate import

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

Co-authored-by: Sambhav Kothari <sambhavs.email@gmail.com>
Co-authored-by: Charles-Edouard Brétéché <charled.breteche@gmail.com>
This commit is contained in:
shuting 2022-04-27 03:18:24 +08:00 committed by GitHub
parent 25badfe4fb
commit d5f6167e56
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 239 additions and 88 deletions

View file

@ -92,6 +92,20 @@ func (r *Rule) IsMutateExisting() bool {
return r.Mutation.Targets != nil
}
// IsCloneSyncGenerate checks if the generate rule has the clone block with sync=true
func (r *Rule) GetCloneSyncForGenerate() (clone bool, sync bool) {
if !r.HasGenerate() {
return
}
if r.Generation.Clone.Name != "" {
clone = true
sync = r.Generation.Synchronize
}
return
}
func (r *Rule) GetAnyAllConditions() apiextensions.JSON {
return FromJSON(r.RawAnyAllConditions)
}

View file

@ -33,6 +33,8 @@ rules:
- clusterpolicies/status
- generaterequests
- generaterequests/status
- updaterequests
- updaterequests/status
- reportchangerequests
- reportchangerequests/status
- clusterreportchangerequests

View file

@ -82,21 +82,21 @@ func Test_Pod_CPU_Hog(t *testing.T) {
// ================== Litmus Chaos Experiment ==================
// Prepare chaosServiceAccount
By(fmt.Sprintf("\nPrepareing Chaos Service Account in %s", nspace))
_, err = e2eClient.CreateNamespacedResourceYaml(saGVR, nspace, ChaosServiceAccountYaml)
_, err = e2eClient.CreateNamespacedResourceYaml(saGVR, nspace, "", ChaosServiceAccountYaml)
Expect(err).NotTo(HaveOccurred())
_, err = e2eClient.CreateNamespacedResourceYaml(rGVR, nspace, ChaosRoleYaml)
_, err = e2eClient.CreateNamespacedResourceYaml(rGVR, nspace, "", ChaosRoleYaml)
Expect(err).NotTo(HaveOccurred())
_, err = e2eClient.CreateNamespacedResourceYaml(rbGVR, nspace, ChaosRoleBindingYaml)
_, err = e2eClient.CreateNamespacedResourceYaml(rbGVR, nspace, "", ChaosRoleBindingYaml)
Expect(err).NotTo(HaveOccurred())
// Deploy Pod CPU Hog Experiment
By(fmt.Sprintf("\nInstalling Litmus Chaos Experiment in %s", nspace))
_, err = e2eClient.CreateNamespacedResourceYaml(cpuGVR, nspace, PodCPUHogExperimentYaml)
_, err = e2eClient.CreateNamespacedResourceYaml(cpuGVR, nspace, "", PodCPUHogExperimentYaml)
Expect(err).NotTo(HaveOccurred())
// Prepare Chaos Engine
By(fmt.Sprintf("\nCreating ChaosEngine Resource in %s", nspace))
_, err = e2eClient.CreateNamespacedResourceYaml(ceGVR, nspace, ChaosEngineYaml)
_, err = e2eClient.CreateNamespacedResourceYaml(ceGVR, nspace, "", ChaosEngineYaml)
Expect(err).NotTo(HaveOccurred())
By(fmt.Sprintf("\nMonitoring status from ChaosResult in %s", nspace))
@ -121,12 +121,12 @@ func Test_Pod_CPU_Hog(t *testing.T) {
// Create disallow_cri_sock_mount policy
By(fmt.Sprintf("\nCreating Enforce Policy in %s", clPolNS))
_, err = e2eClient.CreateNamespacedResourceYaml(clPolGVR, clPolNS, DisallowAddingCapabilitiesYaml)
_, err = e2eClient.CreateNamespacedResourceYaml(clPolGVR, clPolNS, "", DisallowAddingCapabilitiesYaml)
Expect(err).NotTo(HaveOccurred())
// Deploy disallow_cri_sock_mount policy
By(fmt.Sprintf("\nDeploying Enforce Policy in %s", nspace))
_, err = e2eClient.CreateNamespacedResourceYaml(dcsmPolGVR, nspace, resource.manifest)
_, err = e2eClient.CreateNamespacedResourceYaml(dcsmPolGVR, nspace, "", resource.manifest)
Expect(err).To(HaveOccurred())
//CleanUp Resources

View file

@ -108,6 +108,7 @@ func NewController(
c.pLister = pInformer.Lister()
c.npLister = npInformer.Lister()
c.grLister = grInformer.Lister().GenerateRequests(config.KyvernoNamespace)
c.urLister = urInformer.Lister().UpdateRequests(config.KyvernoNamespace)
c.nsLister = namespaceInformer.Lister()
c.pSynced = pInformer.Informer().HasSynced
@ -148,7 +149,7 @@ func (c *Controller) deletePolicy(obj interface{}) {
"generate.kyverno.io/policy-name": p.Name,
}))
grList, err := c.grLister.List(selector)
grList, err := c.urLister.List(selector)
if err != nil {
logger.Error(err, "failed to get generate request for the resource", "label", "generate.kyverno.io/policy-name")
return
@ -161,7 +162,7 @@ func (c *Controller) deletePolicy(obj interface{}) {
}
if !generatePolicyWithClone {
grs, err := c.grLister.GetGenerateRequestsForClusterPolicy(p.Name)
grs, err := c.urLister.GetUpdateRequestsForClusterPolicy(p.Name)
if err != nil {
logger.Error(err, "failed to generate request for the policy", "name", p.Name)
return

View file

@ -17,6 +17,7 @@ import (
"github.com/kyverno/kyverno/pkg/background/common"
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
kyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
urlister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1beta1"
pkgcommon "github.com/kyverno/kyverno/pkg/common"
"github.com/kyverno/kyverno/pkg/config"
dclient "github.com/kyverno/kyverno/pkg/dclient"
@ -53,6 +54,9 @@ type GenerateController struct {
// grLister can list/get generate request from the shared informer's store
grLister kyvernolister.GenerateRequestNamespaceLister
// urLister can list/get update request from the shared informer's store
urLister urlister.UpdateRequestNamespaceLister
// nsLister can list/get namespaces from the shared informer's store
nsLister corelister.NamespaceLister
@ -72,6 +76,7 @@ func NewGenerateController(
policyLister kyvernolister.ClusterPolicyLister,
npolicyLister kyvernolister.PolicyLister,
grLister kyvernolister.GenerateRequestNamespaceLister,
urLister urlister.UpdateRequestNamespaceLister,
eventGen event.Interface,
nsLister corelister.NamespaceLister,
log logr.Logger,
@ -87,6 +92,7 @@ func NewGenerateController(
policyLister: policyLister,
npolicyLister: npolicyLister,
grLister: grLister,
urLister: urLister,
}
c.statusControl = common.StatusControl{Client: kyvernoClient}
@ -231,14 +237,14 @@ func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, g
"generate.kyverno.io/resource-kind": engineResponse.PolicyResponse.Resource.Kind,
"generate.kyverno.io/resource-namespace": engineResponse.PolicyResponse.Resource.Namespace,
}))
grList, err := c.grLister.List(selector)
grList, err := c.urLister.List(selector)
if err != nil {
logger.Error(err, "failed to get generate request for the resource", "kind", engineResponse.PolicyResponse.Resource.Kind, "name", engineResponse.PolicyResponse.Resource.Name, "namespace", engineResponse.PolicyResponse.Resource.Namespace)
continue
}
for _, v := range grList {
err := c.kyvernoClient.KyvernoV1().GenerateRequests(config.KyvernoNamespace).Delete(contextdefault.TODO(), v.GetName(), metav1.DeleteOptions{})
err := c.kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Delete(contextdefault.TODO(), v.GetName(), metav1.DeleteOptions{})
if err != nil {
logger.Error(err, "failed to delete generate request")
}

View file

@ -15,7 +15,7 @@ func (c *Controller) ProcessUR(ur *urkyverno.UpdateRequest) error {
case urkyverno.Generate:
ctrl, _ := generate.NewGenerateController(c.kyvernoClient, c.client,
c.policyLister, c.npolicyLister, c.grLister, c.eventGen, c.nsLister, c.log, c.Config,
c.policyLister, c.npolicyLister, c.grLister, c.urLister, c.eventGen, c.nsLister, c.log, c.Config,
)
return ctrl.ProcessGR(ur)
}

View file

@ -277,8 +277,7 @@ func (c *Controller) updatePolicy(old, cur interface{}) {
logger.V(4).Info("updating policy", "name", oldP.Name)
// get the list of GR for the current Policy version
grs, err := c.grLister.GetGenerateRequestsForClusterPolicy(curP.Name)
grs, err := c.urLister.GetUpdateRequestsForClusterPolicy(curP.Name)
if err != nil {
logger.Error(err, "failed to generate request for policy", "name", curP.Name)
return
@ -306,7 +305,7 @@ func (c *Controller) updateGR(old, cur interface{}) {
}
// only process the ones that are in "Pending"/"Completed" state
// if the Generate Request fails due to incorrect policy, it will be requeued during policy update
if curGr.Status.State == kyverno.Failed {
if curGr.Status.State != kyverno.Pending {
return
}
c.enqueueGenerateRequest(curGr)
@ -363,7 +362,7 @@ func (c *Controller) updateUR(old, cur interface{}) {
}
// only process the ones that are in "Pending"/"Completed" state
// if the Generate Request fails due to incorrect policy, it will be requeued during policy update
if curUr.Status.State == urkyverno.Failed {
if curUr.Status.State != urkyverno.Pending {
return
}
c.enqueueGenerateRequest(curUr)
@ -378,7 +377,7 @@ func (c *Controller) deleteUR(obj interface{}) {
logger.Info("Couldn't get object from tombstone", "obj", obj)
return
}
_, ok = tombstone.Obj.(*kyverno.GenerateRequest)
_, ok = tombstone.Obj.(*urkyverno.UpdateRequest)
if !ok {
logger.Info("tombstone contained object that is not a Generate Request CR", "obj", obj)
return

View file

@ -0,0 +1,38 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by lister-gen. DO NOT EDIT.
package v1beta1
import (
v1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
"k8s.io/apimachinery/pkg/labels"
)
func (s updateRequestNamespaceLister) GetUpdateRequestsForClusterPolicy(policy string) ([]*v1beta1.UpdateRequest, error) {
var list []*v1beta1.UpdateRequest
urs, err := s.List(labels.NewSelector())
if err != nil {
return nil, err
}
for idx, ur := range urs {
if ur.Spec.Policy == policy {
list = append(list, urs[idx])
}
}
return list, err
}

View file

@ -18,10 +18,16 @@ limitations under the License.
package v1beta1
import (
v1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
)
// UpdateRequestListerExpansion allows custom methods to be added to
// UpdateRequestLister.
type UpdateRequestListerExpansion interface{}
// UpdateRequestNamespaceListerExpansion allows custom methods to be added to
// UpdateRequestNamespaceLister.
type UpdateRequestNamespaceListerExpansion interface{}
type UpdateRequestNamespaceListerExpansion interface {
GetUpdateRequestsForClusterPolicy(policy string) ([]*v1beta1.UpdateRequest, error)
}

View file

@ -148,6 +148,7 @@ func ProcessDeletePolicyForCloneGenerateRule(rules []kyverno.Rule, client *dclie
break
}
}
break
}
}
@ -163,7 +164,7 @@ func updateSourceResource(pName string, rule kyverno.Rule, client *dclient.Clien
update := false
labels := obj.GetLabels()
update, labels = removePolicyFromLabels(pName, labels)
if update {
if !update {
return nil
}
@ -180,9 +181,14 @@ func removePolicyFromLabels(pName string, labels map[string]string) (bool, map[s
if labels["generate.kyverno.io/clone-policy-name"] != "" {
policyNames := labels["generate.kyverno.io/clone-policy-name"]
if strings.Contains(policyNames, pName) {
updatedPolicyNames := strings.Replace(policyNames, pName, "", -1)
labels["generate.kyverno.io/clone-policy-name"] = updatedPolicyNames
return true, labels
desiredLabels := make(map[string]string, len(labels)-1)
for k, v := range labels {
if k != "generate.kyverno.io/clone-policy-name" {
desiredLabels[k] = v
}
}
return true, desiredLabels
}
}

View file

@ -20,7 +20,6 @@ import (
urkyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1beta1"
kyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
urkyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1beta1"
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"
@ -277,17 +276,17 @@ func (pc *PolicyController) deletePolicy(obj interface{}) {
logger.Info("policy deleted", "uid", p.UID, "kind", "ClusterPolicy", "name", p.Name)
// we process policies that are not set of background processing
// as we need to clean up GRs when a policy is deleted
// skip generate policies with clone
pc.enqueueRCRDeletedPolicy(p.Name)
// do not clean up UR on generate clone (sync=true) policy deletion
rules := autogen.ComputeRules(p)
generatePolicyWithClone := pkgCommon.ProcessDeletePolicyForCloneGenerateRule(rules, pc.client, p.GetName(), logger)
if !generatePolicyWithClone {
pc.enqueuePolicy(p)
pc.enqueueRCRDeletedPolicy(p.Name)
for _, r := range rules {
clone, sync := r.GetCloneSyncForGenerate()
if clone && sync {
return
}
}
pc.enqueuePolicy(p)
}
func (pc *PolicyController) addNsPolicy(obj interface{}) {
@ -374,10 +373,17 @@ func (pc *PolicyController) deleteNsPolicy(obj interface{}) {
pol := p
// we process policies that are not set of background processing
// as we need to clean up GRs when a policy is deleted
pc.enqueuePolicy(pol)
pc.enqueueRCRDeletedPolicy(p.Name)
// do not clean up UR on generate clone (sync=true) policy deletion
rules := autogen.ComputeRules(pol)
for _, r := range rules {
clone, sync := r.GetCloneSyncForGenerate()
if clone && sync {
return
}
}
pc.enqueuePolicy(pol)
}
func (pc *PolicyController) enqueueRCRDeletedRule(old, cur kyverno.PolicyInterface) {
@ -547,6 +553,7 @@ func (pc *PolicyController) updateUR(policy kyverno.PolicyInterface, urList []*u
if err != nil {
pc.log.Error(err, "failed to create new UR for mutateExisting rule on policy update", "policy", policy.GetName(), "rule", rule.Name,
"target", fmt.Sprintf("%s/%s/%s/%s", trigger.APIVersion, trigger.Kind, trigger.Namespace, trigger.Name))
continue
} else {
pc.log.V(4).Info("successfully created UR for mutateExisting on policy update", "policy", policy.GetName(), "rule", rule.Name,
"target", fmt.Sprintf("%s/%s/%s/%s", trigger.APIVersion, trigger.Kind, trigger.Namespace, trigger.Name))
@ -654,9 +661,15 @@ func updateUR(kyvernoClient *kyvernoclient.Clientset, policyKey string, grList [
grLabels["policy-update"] = fmt.Sprintf("revision-count-%d", nBig.Int64())
gr.SetLabels(grLabels)
_, err = kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Update(context.TODO(), gr, metav1.UpdateOptions{})
new, err := kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Update(context.TODO(), gr, metav1.UpdateOptions{})
if err != nil {
logger.Error(err, "failed to update gr", "name", gr.GetName())
continue
}
new.Status.State = urkyverno.Pending
if _, err := kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).UpdateStatus(context.TODO(), new, metav1.UpdateOptions{}); err != nil {
logger.Error(err, "failed to set UpdateRequest state to Pending")
}
}
}

View file

@ -8,9 +8,12 @@ import (
"github.com/gardener/controller-manager-library/pkg/logger"
"github.com/go-logr/logr"
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
urkyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1beta1"
kyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
urkyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1beta1"
"github.com/kyverno/kyverno/pkg/config"
admissionv1 "k8s.io/api/admission/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -25,7 +28,7 @@ type GenerateRequests interface {
// GeneratorChannel ...
type GeneratorChannel struct {
spec kyverno.GenerateRequestSpec
spec urkyverno.UpdateRequestSpec
action admissionv1.Operation
}
@ -38,22 +41,28 @@ type Generator struct {
// grLister can list/get generate request from the shared informer's store
grLister kyvernolister.GenerateRequestNamespaceLister
grSynced cache.InformerSynced
// urLister can list/get update request from the shared informer's store
urLister urkyvernolister.UpdateRequestNamespaceLister
urSynced cache.InformerSynced
}
// NewGenerator returns a new instance of Generate-Request resource generator
func NewGenerator(client *kyvernoclient.Clientset, grInformer kyvernoinformer.GenerateRequestInformer, stopCh <-chan struct{}, log logr.Logger) *Generator {
func NewGenerator(client *kyvernoclient.Clientset, grInformer kyvernoinformer.GenerateRequestInformer, urInformer urkyvernoinformer.UpdateRequestInformer, stopCh <-chan struct{}, log logr.Logger) *Generator {
gen := &Generator{
client: client,
stopCh: stopCh,
log: log,
grLister: grInformer.Lister().GenerateRequests(config.KyvernoNamespace),
grSynced: grInformer.Informer().HasSynced,
urLister: urInformer.Lister().UpdateRequests(config.KyvernoNamespace),
urSynced: urInformer.Informer().HasSynced,
}
return gen
}
// Apply creates generate request resource (blocking call if channel is full)
func (g *Generator) Apply(gr kyverno.GenerateRequestSpec, action admissionv1.Operation) error {
func (g *Generator) Apply(gr urkyverno.UpdateRequestSpec, action admissionv1.Operation) error {
logger := g.log
logger.V(4).Info("creating Generate Request", "request", gr)
@ -72,10 +81,10 @@ func (g *Generator) processApply(m GeneratorChannel) {
}
}
func (g *Generator) generate(grSpec kyverno.GenerateRequestSpec, action admissionv1.Operation) error {
func (g *Generator) generate(grSpec urkyverno.UpdateRequestSpec, action admissionv1.Operation) error {
// create/update a generate request
if err := retryApplyResource(g.client, grSpec, g.log, action, g.grLister); err != nil {
if err := retryApplyResource(g.client, grSpec, g.log, action, g.grLister, g.urLister); err != nil {
return err
}
return nil
@ -84,8 +93,9 @@ func (g *Generator) generate(grSpec kyverno.GenerateRequestSpec, action admissio
// -> receiving channel to take requests to create request
// use worker pattern to read and create the CR resource
func retryApplyResource(client *kyvernoclient.Clientset, grSpec kyverno.GenerateRequestSpec,
log logr.Logger, action admissionv1.Operation, grLister kyvernolister.GenerateRequestNamespaceLister) error {
func retryApplyResource(client *kyvernoclient.Clientset, grSpec urkyverno.UpdateRequestSpec,
log logr.Logger, action admissionv1.Operation, grLister kyvernolister.GenerateRequestNamespaceLister,
urLister urkyvernolister.UpdateRequestNamespaceLister) error {
var i int
var err error
@ -95,7 +105,7 @@ func retryApplyResource(client *kyvernoclient.Clientset, grSpec kyverno.Generate
return err
}
applyResource := func() error {
gr := kyverno.GenerateRequest{
gr := urkyverno.UpdateRequest{
Spec: grSpec,
}
@ -111,7 +121,7 @@ func retryApplyResource(client *kyvernoclient.Clientset, grSpec kyverno.Generate
"generate.kyverno.io/resource-kind": grSpec.Resource.Kind,
"generate.kyverno.io/resource-namespace": grSpec.Resource.Namespace,
}))
grList, err := grLister.List(selector)
grList, err := urLister.List(selector)
if err != nil {
logger.Error(err, "failed to get generate request for the resource", "kind", grSpec.Resource.Kind, "name", grSpec.Resource.Name, "namespace", grSpec.Resource.Namespace)
return err
@ -129,10 +139,16 @@ func retryApplyResource(client *kyvernoclient.Clientset, grSpec kyverno.Generate
v.Spec.Policy = gr.Spec.Policy
v.Spec.Resource = gr.Spec.Resource
_, err = client.KyvernoV1().GenerateRequests(config.KyvernoNamespace).Update(context.TODO(), v, metav1.UpdateOptions{})
new, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Update(context.TODO(), v, metav1.UpdateOptions{})
if err != nil {
return err
}
new.Status.State = urkyverno.Pending
if _, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).UpdateStatus(context.TODO(), new, metav1.UpdateOptions{}); err != nil {
logger.Error(err, "failed to set UpdateRequest state to Pending")
}
isExist = true
}
@ -144,10 +160,16 @@ func retryApplyResource(client *kyvernoclient.Clientset, grSpec kyverno.Generate
"generate.kyverno.io/resource-kind": grSpec.Resource.Kind,
"generate.kyverno.io/resource-namespace": grSpec.Resource.Namespace,
})
_, err = client.KyvernoV1().GenerateRequests(config.KyvernoNamespace).Create(context.TODO(), &gr, metav1.CreateOptions{})
new, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Create(context.TODO(), &gr, metav1.CreateOptions{})
if err != nil {
return err
}
new.Status.State = urkyverno.Pending
if _, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).UpdateStatus(context.TODO(), new, metav1.UpdateOptions{}); err != nil {
logger.Error(err, "failed to set UpdateRequest state to Pending")
}
}
}

View file

@ -167,11 +167,15 @@ func (ws *WebhookServer) updateAnnotationInGR(gr *urkyverno.UpdateRequest, logge
gr.Annotations,
)
_, err := gencommon.PatchGenerateRequest(gr, patch, ws.kyvernoClient)
new, err := gencommon.PatchGenerateRequest(gr, patch, ws.kyvernoClient)
if err != nil {
logger.Error(err, "failed to update generate request update-time annotations for the resource", "generate request", gr.Name)
return
}
new.Status.State = urkyverno.Pending
if _, err := ws.kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).UpdateStatus(contextdefault.TODO(), new, metav1.UpdateOptions{}); err != nil {
logger.Error(err, "failed to set UpdateRequest state to Pending", "update request", gr.Name)
}
}
//handleUpdateGenerateTargetResource - handles update of target resource for generate policy
@ -365,14 +369,14 @@ func (ws *WebhookServer) deleteGR(logger logr.Logger, engineResponse *response.E
"generate.kyverno.io/resource-namespace": engineResponse.PolicyResponse.Resource.Namespace,
}))
grList, err := ws.grLister.List(selector)
grList, err := ws.urLister.List(selector)
if err != nil {
logger.Error(err, "failed to get generate request for the resource", "kind", engineResponse.PolicyResponse.Resource.Kind, "name", engineResponse.PolicyResponse.Resource.Name, "namespace", engineResponse.PolicyResponse.Resource.Namespace)
return
}
for _, v := range grList {
err := ws.kyvernoClient.KyvernoV1().GenerateRequests(config.KyvernoNamespace).Delete(contextdefault.TODO(), v.GetName(), metav1.DeleteOptions{})
err := ws.kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Delete(contextdefault.TODO(), v.GetName(), metav1.DeleteOptions{})
if err != nil {
logger.Error(err, "failed to update gr")
}

View file

@ -167,8 +167,9 @@ func retryApplyResource(client *kyvernoclient.Clientset, urSpec urkyverno.Update
new, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Update(context.TODO(), v, metav1.UpdateOptions{})
if err != nil {
log.V(4).Info("failed to update UpdateRequest, retrying", "retryCount", i, "name", ur.GetName(), "namespace", ur.GetNamespace())
log.V(4).Info("failed to update UpdateRequest, retrying", "retryCount", i, "name", ur.GetName(), "namespace", ur.GetNamespace(), "err", err.Error())
i++
return err
} else {
log.V(4).Info("successfully updated UpdateRequest", "retryCount", i, "name", ur.GetName(), "namespace", ur.GetNamespace())
}
@ -176,6 +177,7 @@ func retryApplyResource(client *kyvernoclient.Clientset, urSpec urkyverno.Update
new.Status.State = urkyverno.Pending
if _, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).UpdateStatus(context.TODO(), new, metav1.UpdateOptions{}); err != nil {
log.Error(err, "failed to set UpdateRequest state to Pending")
return err
}
isExist = true
@ -189,8 +191,9 @@ func retryApplyResource(client *kyvernoclient.Clientset, urSpec urkyverno.Update
new, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Create(context.TODO(), &ur, metav1.CreateOptions{})
if err != nil {
log.V(4).Info("failed to create UpdateRequest, retrying", "retryCount", i, "name", ur.GetGenerateName(), "namespace", ur.GetNamespace())
log.V(4).Info("failed to create UpdateRequest, retrying", "retryCount", i, "name", ur.GetGenerateName(), "namespace", ur.GetNamespace(), "err", err.Error())
i++
return err
} else {
log.V(4).Info("successfully created UpdateRequest", "retryCount", i, "name", new.GetName(), "namespace", ur.GetNamespace())
}
@ -198,10 +201,11 @@ func retryApplyResource(client *kyvernoclient.Clientset, urSpec urkyverno.Update
new.Status.State = urkyverno.Pending
if _, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).UpdateStatus(context.TODO(), new, metav1.UpdateOptions{}); err != nil {
log.Error(err, "failed to set UpdateRequest state to Pending")
return err
}
}
return err
return nil
}
exbackoff := &backoff.ExponentialBackOff{

View file

@ -34,7 +34,7 @@ var RoleTests = []struct {
Clone: false,
Sync: false,
Data: roleRoleBindingYamlWithSync,
PolicyName: "gen-role-policy",
PolicyName: "gen-role-policy-1",
},
{
TestName: "test-role-rolebinding-withsync-without-clone",
@ -44,7 +44,7 @@ var RoleTests = []struct {
Clone: false,
Sync: true,
Data: roleRoleBindingYamlWithSync,
PolicyName: "gen-role-policy",
PolicyName: "gen-role-policy-2",
},
{
TestName: "test-role-rolebinding-with-clone",
@ -57,7 +57,7 @@ var RoleTests = []struct {
CloneNamespace: "default",
Sync: false,
Data: roleRoleBindingYamlWithClone,
PolicyName: "gen-role-policy",
PolicyName: "gen-role-policy-3",
},
}
@ -98,7 +98,7 @@ var ClusterRoleTests = []struct {
Clone: false,
Sync: false,
Data: genClusterRoleYamlWithSync,
PolicyName: "gen-cluster-policy",
PolicyName: "gen-cluster-policy-1",
},
{
TestName: "test-clusterrole-clusterrolebinding-with-sync-without-clone",
@ -108,12 +108,12 @@ var ClusterRoleTests = []struct {
Clone: false,
Sync: true,
Data: genClusterRoleYamlWithSync,
PolicyName: "gen-cluster-policy",
PolicyName: "gen-cluster-policy-2",
},
{
TestName: "test-clusterrole-clusterrolebinding-with-sync-with-clone",
ClusterRoleName: "ns-cluster-role",
ClusterRoleBindingName: "ns-cluster-role-binding",
ClusterRoleName: "cloned-cluster-role",
ClusterRoleBindingName: "cloned-cluster-role-binding",
ResourceNamespace: "test",
Clone: true,
ClonerClusterRoleName: "base-cluster-role",
@ -121,8 +121,8 @@ var ClusterRoleTests = []struct {
CloneSourceClusterRoleData: baseClusterRoleData,
CloneSourceClusterRoleBindingData: baseClusterRoleBindingData,
Sync: false,
Data: genClusterRoleYamlWithSync,
PolicyName: "gen-cluster-policy",
Data: clusterRoleRoleBindingYamlWithClone,
PolicyName: "gen-cluster-policy-3",
},
}

View file

@ -94,7 +94,7 @@ func Test_ClusterRole_ClusterRoleBinding_Sets(t *testing.T) {
// ======== Create ClusterRole Policy =============
By(fmt.Sprintf("Creating Generate Role Policy: %s", tests.PolicyName))
_, err = e2eClient.CreateNamespacedResourceYaml(clPolGVR, clPolNS, tests.Data)
_, err = e2eClient.CreateNamespacedResourceYaml(clPolGVR, clPolNS, tests.PolicyName, tests.Data)
Expect(err).NotTo(HaveOccurred())
err = commonE2E.PolicyCreated(tests.PolicyName)
@ -114,7 +114,7 @@ func Test_ClusterRole_ClusterRoleBinding_Sets(t *testing.T) {
// =================================================
// ======= Create Namespace ==================
By(fmt.Sprintf("Creating Namespace which triggers generate %s \n", clPolNS))
By(fmt.Sprintf("Creating Namespace which triggers generate %s \n", tests.ResourceNamespace))
_, err = e2eClient.CreateClusteredResourceYaml(nsGVR, namespaceYaml)
Expect(err).NotTo(HaveOccurred())
@ -221,8 +221,8 @@ func Test_Role_RoleBinding_Sets(t *testing.T) {
Expect(err).NotTo(HaveOccurred())
// ======== Create Role Policy =============
By(fmt.Sprintf("\nCreating Generate Role Policy in %s", clPolNS))
_, err = e2eClient.CreateNamespacedResourceYaml(clPolGVR, clPolNS, tests.Data)
By(fmt.Sprintf("\nCreating Generate Role Policy %s", tests.PolicyName))
_, err = e2eClient.CreateNamespacedResourceYaml(clPolGVR, clPolNS, tests.PolicyName, tests.Data)
Expect(err).NotTo(HaveOccurred())
err = commonE2E.PolicyCreated(tests.PolicyName)
@ -233,9 +233,9 @@ func Test_Role_RoleBinding_Sets(t *testing.T) {
// === If Clone is true Create Source Resources ==
if tests.Clone {
By(fmt.Sprintf("Clone = true, Creating Cloner Resources in Namespace : %s", tests.CloneNamespace))
_, err := e2eClient.CreateNamespacedResourceYaml(rGVR, tests.CloneNamespace, tests.CloneSourceRoleData)
_, err := e2eClient.CreateNamespacedResourceYaml(rGVR, tests.CloneNamespace, "", tests.CloneSourceRoleData)
Expect(err).NotTo(HaveOccurred())
_, err = e2eClient.CreateNamespacedResourceYaml(rbGVR, tests.CloneNamespace, tests.CloneSourceRoleBindingData)
_, err = e2eClient.CreateNamespacedResourceYaml(rbGVR, tests.CloneNamespace, "", tests.CloneSourceRoleBindingData)
Expect(err).NotTo(HaveOccurred())
}
// ================================================
@ -350,7 +350,7 @@ func Test_Generate_NetworkPolicy(t *testing.T) {
// ======== Create Generate NetworkPolicy Policy =============
By("Creating Generate NetworkPolicy Policy")
_, err := e2eClient.CreateNamespacedResourceYaml(clPolGVR, npPolNS, test.Data)
_, err := e2eClient.CreateNamespacedResourceYaml(clPolGVR, npPolNS, test.PolicyName, test.Data)
Expect(err).NotTo(HaveOccurred())
err = commonE2E.PolicyCreated(test.PolicyName)
@ -445,7 +445,7 @@ func Test_Generate_Namespace_Label_Actions(t *testing.T) {
// ======== Create Generate NetworkPolicy Policy =============
By("Creating Generate NetworkPolicy Policy")
_, err = e2eClient.CreateNamespacedResourceYaml(clPolGVR, npPolNS, test.Data)
_, err = e2eClient.CreateNamespacedResourceYaml(clPolGVR, npPolNS, test.GeneratePolicyName, test.Data)
Expect(err).NotTo(HaveOccurred())
// ============================================
@ -639,7 +639,7 @@ func Test_Generate_Synchronize_Flag(t *testing.T) {
// ======== Create Generate NetworkPolicy Policy =============
By("Creating Generate NetworkPolicy Policy")
_, err = e2eClient.CreateNamespacedResourceYaml(clPolGVR, npPolNS, test.Data)
_, err = e2eClient.CreateNamespacedResourceYaml(clPolGVR, npPolNS, test.GeneratePolicyName, test.Data)
Expect(err).NotTo(HaveOccurred())
err = commonE2E.PolicyCreated(test.GeneratePolicyName)
@ -829,14 +829,14 @@ func Test_Source_Resource_Update_Replication(t *testing.T) {
// === If Clone is true Create Source Resources ==
if tests.Clone {
By(fmt.Sprintf("Clone = true, Creating Cloner Resources in Namespace : %s", tests.CloneNamespace))
_, err := e2eClient.CreateNamespacedResourceYaml(cmGVR, tests.CloneNamespace, tests.CloneSourceConfigMapData)
_, err := e2eClient.CreateNamespacedResourceYaml(cmGVR, tests.CloneNamespace, "", tests.CloneSourceConfigMapData)
Expect(err).NotTo(HaveOccurred())
}
// ================================================
// ======== Create Generate Policy =============
By(fmt.Sprintf("\nCreating Generate Policy in %s", clPolNS))
_, err = e2eClient.CreateNamespacedResourceYaml(clPolGVR, clPolNS, tests.Data)
_, err = e2eClient.CreateNamespacedResourceYaml(clPolGVR, clPolNS, tests.PolicyName, tests.Data)
Expect(err).NotTo(HaveOccurred())
err = commonE2E.PolicyCreated(tests.PolicyName)
@ -1038,14 +1038,14 @@ func Test_Generate_Policy_Deletion_for_Clone(t *testing.T) {
// === If Clone is true Create Source Resources ==
if tests.Clone {
By(fmt.Sprintf("Clone = true, Creating Cloner Resources in Namespace : %s", tests.CloneNamespace))
_, err := e2eClient.CreateNamespacedResourceYaml(cmGVR, tests.CloneNamespace, tests.CloneSourceConfigMapData)
_, err := e2eClient.CreateNamespacedResourceYaml(cmGVR, tests.CloneNamespace, "", tests.CloneSourceConfigMapData)
Expect(err).NotTo(HaveOccurred())
}
// ================================================
// ======== Create Generate Policy =============
By(fmt.Sprintf("\nCreating Generate Policy in %s", clPolNS))
_, err = e2eClient.CreateNamespacedResourceYaml(clPolGVR, clPolNS, tests.Data)
By(fmt.Sprintf("\nCreating Generate Policy %s", tests.PolicyName))
_, err = e2eClient.CreateNamespacedResourceYaml(clPolGVR, clPolNS, tests.PolicyName, tests.Data)
Expect(err).NotTo(HaveOccurred())
err = commonE2E.PolicyCreated(tests.PolicyName)

View file

@ -215,6 +215,39 @@ subjects:
namespace: kyverno
`)
// Cluster Policy to clone ClusterRole and ClusterRoleBinding
var clusterRoleRoleBindingYamlWithClone = []byte(`
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: "gen-cluster-policy-3"
spec:
background: false
rules:
- name: "gen-role"
match:
resources:
kinds:
- Namespace
generate:
kind: ClusterRole
name: "cloned-cluster-role"
synchronize: true
clone:
name: "base-cluster-role"
- name: "gen-role-binding"
match:
resources:
kinds:
- Namespace
generate:
kind: ClusterRoleBinding
name: "cloned-cluster-role-binding"
synchronize: true
clone:
name: "base-cluster-role-binding"
`)
var genNetworkPolicyYaml = []byte(`
apiVersion: kyverno.io/v1
kind: ClusterPolicy

View file

@ -77,12 +77,12 @@ func Test_Mutate_Sets(t *testing.T) {
// Create source CM
By(fmt.Sprintf("\nCreating source ConfigMap in %s", tests.ResourceNamespace))
_, err = e2eClient.CreateNamespacedResourceYaml(configMapGVR, tests.ResourceNamespace, sourceConfigMapYaml)
_, err = e2eClient.CreateNamespacedResourceYaml(configMapGVR, tests.ResourceNamespace, "", sourceConfigMapYaml)
Expect(err).NotTo(HaveOccurred())
// Create CM Policy
By(fmt.Sprintf("\nCreating Mutate ConfigMap Policy in %s", policyNamespace))
_, err = e2eClient.CreateNamespacedResourceYaml(policyGVR, policyNamespace, tests.Data)
_, err = e2eClient.CreateNamespacedResourceYaml(policyGVR, policyNamespace, "", tests.Data)
Expect(err).NotTo(HaveOccurred())
err = commonE2E.PolicyCreated(tests.PolicyName)
@ -90,7 +90,7 @@ func Test_Mutate_Sets(t *testing.T) {
// Create target CM
By(fmt.Sprintf("\nCreating target ConfigMap in %s", tests.ResourceNamespace))
_, err = e2eClient.CreateNamespacedResourceYaml(configMapGVR, tests.ResourceNamespace, targetConfigMapYaml)
_, err = e2eClient.CreateNamespacedResourceYaml(configMapGVR, tests.ResourceNamespace, "", targetConfigMapYaml)
Expect(err).NotTo(HaveOccurred())
// Verify created ConfigMap
@ -180,14 +180,14 @@ func Test_Mutate(t *testing.T) {
Expect(err).NotTo(HaveOccurred())
By("Creating Policy...")
_, err = e2eClient.CreateNamespacedResourceYaml(policyGVR, policyNamespace, test.PolicyRaw)
_, err = e2eClient.CreateNamespacedResourceYaml(policyGVR, policyNamespace, test.PolicyName, test.PolicyRaw)
Expect(err).NotTo(HaveOccurred())
err = commonE2E.PolicyCreated(test.PolicyName)
Expect(err).NotTo(HaveOccurred())
By("Creating Resource...")
_, err = e2eClient.CreateNamespacedResourceYaml(test.ResourceGVR, test.ResourceNamespace, test.ResourceRaw)
_, err = e2eClient.CreateNamespacedResourceYaml(test.ResourceGVR, test.ResourceNamespace, "", test.ResourceRaw)
Expect(err).NotTo(HaveOccurred())
By("Checking that resource is created...")
@ -291,7 +291,7 @@ func Test_Mutate_Ingress(t *testing.T) {
By(fmt.Sprintf("\n\nStart testing %s", test.testName))
gvr := e2e.GetGVR(test.group, test.version, test.rsc)
By(fmt.Sprintf("Creating Ingress %v in %s", gvr, nspace))
_, err = e2eClient.CreateNamespacedResourceYaml(gvr, nspace, test.resource)
_, err = e2eClient.CreateNamespacedResourceYaml(gvr, nspace, "", test.resource)
Expect(err).NotTo(HaveOccurred())
By(fmt.Sprintf("Verifying Ingress %v in the Namespace : %s", gvr, nspace))

View file

@ -116,12 +116,15 @@ func (e2e *E2EClient) ListNamespacedResources(gvr schema.GroupVersionResource, n
}
// CreateNamespacedResourceYaml creates namespaced resources like Pods, Services, Deployments etc
func (e2e *E2EClient) CreateNamespacedResourceYaml(gvr schema.GroupVersionResource, namespace string, resourceData []byte) (*unstructured.Unstructured, error) {
func (e2e *E2EClient) CreateNamespacedResourceYaml(gvr schema.GroupVersionResource, namespace, name string, resourceData []byte) (*unstructured.Unstructured, error) {
resource := unstructured.Unstructured{}
err := yaml.Unmarshal(resourceData, &resource)
if err != nil {
return nil, err
}
if name != "" {
resource.SetName(name)
}
result, err := e2e.Client.Resource(gvr).Namespace(namespace).Create(context.TODO(), &resource, metav1.CreateOptions{})
return result, err
}

View file

@ -69,7 +69,7 @@ func Test_Validate_Flux_Sets(t *testing.T) {
// Create policy
By(fmt.Sprintf("Creating policy in \"%s\"", policyNamespace))
_, err = e2eClient.CreateNamespacedResourceYaml(policyGVR, policyNamespace, test.PolicyRaw)
_, err = e2eClient.CreateNamespacedResourceYaml(policyGVR, policyNamespace, "", test.PolicyRaw)
Expect(err).NotTo(HaveOccurred())
// Create Flux CRD
@ -92,7 +92,7 @@ func Test_Validate_Flux_Sets(t *testing.T) {
// Create Kustomize resource
kustomizeGVR := e2e.GetGVR("kustomize.toolkit.fluxcd.io", "v1beta1", "kustomizations")
By(fmt.Sprintf("Creating Kustomize resource in \"%s\"", nspace))
_, err = e2eClient.CreateNamespacedResourceYaml(kustomizeGVR, nspace, test.ResourceRaw)
_, err = e2eClient.CreateNamespacedResourceYaml(kustomizeGVR, nspace, "", test.ResourceRaw)
if test.MustSucceed {
Expect(err).NotTo(HaveOccurred())
@ -169,14 +169,14 @@ func TestValidate(t *testing.T) {
Expect(err).NotTo(HaveOccurred())
By("Creating Policy...")
_, err = e2eClient.CreateNamespacedResourceYaml(policyGVR, policyNamespace, test.PolicyRaw)
_, err = e2eClient.CreateNamespacedResourceYaml(policyGVR, policyNamespace, test.PolicyName, test.PolicyRaw)
Expect(err).NotTo(HaveOccurred())
err = commonE2E.PolicyCreated(test.PolicyName)
Expect(err).NotTo(HaveOccurred())
By("Creating Resource...")
_, err = e2eClient.CreateNamespacedResourceYaml(test.ResourceGVR, test.ResourceNamespace, test.ResourceRaw)
_, err = e2eClient.CreateNamespacedResourceYaml(test.ResourceGVR, test.ResourceNamespace, test.PolicyName, test.ResourceRaw)
statusErr, ok := err.(*k8sErrors.StatusError)
validationError := (ok && statusErr.ErrStatus.Code == 400) // Validation error is always Bad Request

View file

@ -82,7 +82,7 @@ func TestImageVerify(t *testing.T) {
// Create policy
By(fmt.Sprintf("Creating policy in \"%s\"", policyNamespace))
_, err = e2eClient.CreateNamespacedResourceYaml(policyGVR, policyNamespace, test.PolicyRaw)
_, err = e2eClient.CreateNamespacedResourceYaml(policyGVR, policyNamespace, test.PolicyName, test.PolicyRaw)
Expect(err).NotTo(HaveOccurred())
if test.MustSucceed {