mirror of
https://github.com/kyverno/kyverno.git
synced 2025-04-08 10:04:25 +00:00
refactor: introduce ur updater (#4535)
Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com> Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com>
This commit is contained in:
parent
aa6abd99f2
commit
ed31fb0326
5 changed files with 167 additions and 24 deletions
pkg/webhooks
|
@ -35,6 +35,7 @@ func NewFakeHandlers(ctx context.Context, policyCache policycache.Cache) webhook
|
|||
configuration := config.NewFakeConfig()
|
||||
rbLister := informers.Rbac().V1().RoleBindings().Lister()
|
||||
crbLister := informers.Rbac().V1().ClusterRoleBindings().Lister()
|
||||
urLister := kyvernoInformers.Kyverno().V1beta1().UpdateRequests().Lister().UpdateRequests(config.KyvernoNamespace())
|
||||
|
||||
return &handlers{
|
||||
client: dclient,
|
||||
|
@ -44,13 +45,14 @@ func NewFakeHandlers(ctx context.Context, policyCache policycache.Cache) webhook
|
|||
nsLister: informers.Core().V1().Namespaces().Lister(),
|
||||
rbLister: rbLister,
|
||||
crbLister: crbLister,
|
||||
urLister: kyvernoInformers.Kyverno().V1beta1().UpdateRequests().Lister().UpdateRequests(config.KyvernoNamespace()),
|
||||
urLister: urLister,
|
||||
prGenerator: policyreport.NewFake(),
|
||||
urGenerator: updaterequest.NewFake(),
|
||||
eventGen: event.NewFake(),
|
||||
auditHandler: newFakeAuditHandler(),
|
||||
openAPIController: openapi.NewFake(),
|
||||
pcBuilder: webhookutils.NewPolicyContextBuilder(configuration, dclient, rbLister, crbLister),
|
||||
urUpdater: webhookutils.NewUpdateRequestUpdater(kyvernoclient, urLister),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
gencommon "github.com/kyverno/kyverno/pkg/background/common"
|
||||
gen "github.com/kyverno/kyverno/pkg/background/generate"
|
||||
"github.com/kyverno/kyverno/pkg/common"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
|
@ -131,31 +130,12 @@ func (h *handlers) handleUpdateGenerateSourceResource(resLabels map[string]strin
|
|||
}
|
||||
|
||||
for _, ur := range urList {
|
||||
h.updateAnnotationInUR(ur, logger)
|
||||
h.urUpdater.UpdateAnnotation(logger, ur.GetName())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// updateAnnotationInUR - function used to update UR annotation
|
||||
// updating UR will trigger reprocessing of UR and recreation/updation of generated resource
|
||||
func (h *handlers) updateAnnotationInUR(ur *kyvernov1beta1.UpdateRequest, logger logr.Logger) {
|
||||
if _, err := gencommon.Update(h.kyvernoClient, h.urLister, ur.GetName(), func(ur *kyvernov1beta1.UpdateRequest) {
|
||||
urAnnotations := ur.Annotations
|
||||
if len(urAnnotations) == 0 {
|
||||
urAnnotations = make(map[string]string)
|
||||
}
|
||||
urAnnotations["generate.kyverno.io/updation-time"] = time.Now().String()
|
||||
ur.SetAnnotations(urAnnotations)
|
||||
}); err != nil {
|
||||
logger.Error(err, "failed to update update request update-time annotations for the resource", "update request", ur.Name)
|
||||
return
|
||||
}
|
||||
if _, err := gencommon.UpdateStatus(h.kyvernoClient, h.urLister, ur.GetName(), kyvernov1beta1.Pending, "", nil); err != nil {
|
||||
logger.Error(err, "failed to set UpdateRequest state to Pending", "update request", ur.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// handleUpdateGenerateTargetResource - handles update of target resource for generate policy
|
||||
func (h *handlers) handleUpdateGenerateTargetResource(request *admissionv1.AdmissionRequest, policies []kyvernov1.PolicyInterface, resLabels map[string]string, logger logr.Logger) {
|
||||
enqueueBool := false
|
||||
|
@ -214,7 +194,7 @@ func (h *handlers) handleUpdateGenerateTargetResource(request *admissionv1.Admis
|
|||
logger.Error(err, "failed to get update request", "name", urName)
|
||||
return
|
||||
}
|
||||
h.updateAnnotationInUR(ur, logger)
|
||||
h.urUpdater.UpdateAnnotation(logger, ur.GetName())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@ type handlers struct {
|
|||
auditHandler AuditHandler
|
||||
openAPIController openapi.ValidateInterface
|
||||
pcBuilder webhookutils.PolicyContextBuilder
|
||||
urUpdater webhookutils.UpdateRequestUpdater
|
||||
}
|
||||
|
||||
func NewHandlers(
|
||||
|
@ -95,6 +96,7 @@ func NewHandlers(
|
|||
auditHandler: auditHandler,
|
||||
openAPIController: openAPIController,
|
||||
pcBuilder: webhookutils.NewPolicyContextBuilder(configuration, client, rbLister, crbLister),
|
||||
urUpdater: webhookutils.NewUpdateRequestUpdater(kyvernoClient, urLister),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -406,6 +408,6 @@ func (h *handlers) handleDelete(logger logr.Logger, request *admissionv1.Admissi
|
|||
if ur.Spec.Type == kyvernov1beta1.Mutate {
|
||||
return
|
||||
}
|
||||
h.updateAnnotationInUR(ur, logger)
|
||||
h.urUpdater.UpdateAnnotation(logger, ur.GetName())
|
||||
}
|
||||
}
|
||||
|
|
52
pkg/webhooks/utils/update_request_updater.go
Normal file
52
pkg/webhooks/utils/update_request_updater.go
Normal file
|
@ -0,0 +1,52 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/background/common"
|
||||
"github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
kyvernov1beta1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1beta1"
|
||||
)
|
||||
|
||||
type UpdateRequestUpdater interface {
|
||||
// UpdateAnnotation updates UR annotation, triggering reprocessing of UR and recreation/updation of generated resource
|
||||
UpdateAnnotation(logger logr.Logger, name string)
|
||||
}
|
||||
|
||||
type updateRequestUpdater struct {
|
||||
client versioned.Interface
|
||||
lister kyvernov1beta1listers.UpdateRequestNamespaceLister
|
||||
}
|
||||
|
||||
func NewUpdateRequestUpdater(client versioned.Interface, lister kyvernov1beta1listers.UpdateRequestNamespaceLister) UpdateRequestUpdater {
|
||||
return &updateRequestUpdater{
|
||||
client: client,
|
||||
lister: lister,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *updateRequestUpdater) updateAnnotation(logger logr.Logger, name string) {
|
||||
if _, err := common.Update(h.client, h.lister, name, func(ur *kyvernov1beta1.UpdateRequest) {
|
||||
urAnnotations := ur.Annotations
|
||||
if len(urAnnotations) == 0 {
|
||||
urAnnotations = make(map[string]string)
|
||||
}
|
||||
urAnnotations["generate.kyverno.io/updation-time"] = time.Now().String()
|
||||
ur.SetAnnotations(urAnnotations)
|
||||
}); err != nil {
|
||||
logger.Error(err, "failed to update update request update-time annotations for the resource", "update request", name)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *updateRequestUpdater) setPendingStatus(logger logr.Logger, name string) {
|
||||
if _, err := common.UpdateStatus(h.client, h.lister, name, kyvernov1beta1.Pending, "", nil); err != nil {
|
||||
logger.Error(err, "failed to set UpdateRequest state to Pending", "update request", name)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *updateRequestUpdater) UpdateAnnotation(logger logr.Logger, name string) {
|
||||
h.updateAnnotation(logger, name)
|
||||
h.setPendingStatus(logger, name)
|
||||
}
|
107
pkg/webhooks/utils/update_request_updater_test.go
Normal file
107
pkg/webhooks/utils/update_request_updater_test.go
Normal file
|
@ -0,0 +1,107 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
"github.com/kyverno/kyverno/pkg/client/clientset/versioned/fake"
|
||||
kyvernoinformers "github.com/kyverno/kyverno/pkg/client/informers/externalversions"
|
||||
kyvernov1beta1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
"github.com/stretchr/testify/assert"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
func TestNewUpdateRequestUpdater(t *testing.T) {
|
||||
type args struct {
|
||||
client versioned.Interface
|
||||
lister kyvernov1beta1listers.UpdateRequestNamespaceLister
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want UpdateRequestUpdater
|
||||
}{{
|
||||
name: "nil",
|
||||
args: args{nil, nil},
|
||||
want: &updateRequestUpdater{nil, nil},
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := NewUpdateRequestUpdater(tt.args.client, tt.args.lister)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_updateRequestUpdater_updateAnnotation(t *testing.T) {
|
||||
type data struct {
|
||||
objects []runtime.Object
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
data data
|
||||
urName string
|
||||
updated bool
|
||||
}{{
|
||||
name: "success",
|
||||
data: data{
|
||||
[]runtime.Object{
|
||||
&kyvernov1beta1.UpdateRequest{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: "test",
|
||||
Namespace: config.KyvernoNamespace(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
urName: "test",
|
||||
updated: true,
|
||||
}, {
|
||||
name: "not found",
|
||||
data: data{
|
||||
[]runtime.Object{
|
||||
&kyvernov1beta1.UpdateRequest{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: "dummy",
|
||||
Namespace: config.KyvernoNamespace(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
urName: "dummy",
|
||||
updated: false,
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
done := ctx.Done()
|
||||
t.Cleanup(cancel)
|
||||
client := fake.NewSimpleClientset(tt.data.objects...)
|
||||
kyvernoInformers := kyvernoinformers.NewSharedInformerFactory(client, 0)
|
||||
lister := kyvernoInformers.Kyverno().V1beta1().UpdateRequests().Lister().UpdateRequests(config.KyvernoNamespace())
|
||||
kyvernoInformers.Start(done)
|
||||
kyvernoInformers.WaitForCacheSync(done)
|
||||
h := &updateRequestUpdater{
|
||||
client: client,
|
||||
lister: lister,
|
||||
}
|
||||
h.updateAnnotation(logr.Discard(), "test")
|
||||
ur, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace()).Get(ctx, tt.urName, v1.GetOptions{})
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, ur)
|
||||
if tt.updated {
|
||||
annotations := ur.GetAnnotations()
|
||||
assert.NotNil(t, annotations)
|
||||
assert.NotNil(t, annotations["generate.kyverno.io/updation-time"])
|
||||
} else {
|
||||
annotations := ur.GetAnnotations()
|
||||
assert.Nil(t, annotations)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue