added ut for for event handler
Signed-off-by: GautamBytes <manchandanigautam@gmail.com>
This commit is contained in:
parent
deaa5f38b5
commit
742921a592
|
|
@ -0,0 +1,204 @@
|
||||||
|
package deployment
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||||
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/client-go/util/workqueue"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/event"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||||
|
|
||||||
|
"github.com/openkruise/rollouts/api/v1alpha1"
|
||||||
|
"github.com/openkruise/rollouts/pkg/webhook/util/configuration"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newScheme() *runtime.Scheme {
|
||||||
|
scheme := runtime.NewScheme()
|
||||||
|
_ = appsv1.AddToScheme(scheme)
|
||||||
|
_ = admissionregistrationv1.AddToScheme(scheme)
|
||||||
|
return scheme
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDeployment(namespace, name string, withLabel, withRollingUpdate bool) *appsv1.Deployment {
|
||||||
|
dep := &appsv1.Deployment{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: namespace,
|
||||||
|
Name: name,
|
||||||
|
Labels: make(map[string]string),
|
||||||
|
},
|
||||||
|
Spec: appsv1.DeploymentSpec{
|
||||||
|
Strategy: appsv1.DeploymentStrategy{
|
||||||
|
Type: appsv1.RecreateDeploymentStrategyType,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if withLabel {
|
||||||
|
dep.Labels[v1alpha1.AdvancedDeploymentControlLabel] = "true"
|
||||||
|
}
|
||||||
|
if withRollingUpdate {
|
||||||
|
dep.Spec.Strategy.Type = appsv1.RollingUpdateDeploymentStrategyType
|
||||||
|
}
|
||||||
|
return dep
|
||||||
|
}
|
||||||
|
|
||||||
|
func newWebhook(name string, withTimestamp bool) *admissionregistrationv1.MutatingWebhookConfiguration {
|
||||||
|
wh := &admissionregistrationv1.MutatingWebhookConfiguration{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: name,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if withTimestamp {
|
||||||
|
now := metav1.Now()
|
||||||
|
wh.DeletionTimestamp = &now
|
||||||
|
}
|
||||||
|
return wh
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMutatingWebhookEventHandler(t *testing.T) {
|
||||||
|
matchingDep := newDeployment("ns", "matching-dep", true, false)
|
||||||
|
fakeClient := fake.NewClientBuilder().WithScheme(newScheme()).WithObjects(matchingDep).Build()
|
||||||
|
handler := MutatingWebhookEventHandler{Reader: fakeClient}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
event interface{}
|
||||||
|
expectEnqueue bool
|
||||||
|
handlerFunc func(e interface{}, q workqueue.RateLimitingInterface)
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Create: Correct webhook should NOT enqueue (timestamp is zero)",
|
||||||
|
event: event.CreateEvent{Object: newWebhook(configuration.MutatingWebhookConfigurationName, false)},
|
||||||
|
expectEnqueue: false,
|
||||||
|
handlerFunc: func(e interface{}, q workqueue.RateLimitingInterface) {
|
||||||
|
handler.Create(e.(event.CreateEvent), q)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Create: Correct webhook with deletion timestamp SHOULD enqueue",
|
||||||
|
event: event.CreateEvent{Object: newWebhook(configuration.MutatingWebhookConfigurationName, true)},
|
||||||
|
expectEnqueue: true,
|
||||||
|
handlerFunc: func(e interface{}, q workqueue.RateLimitingInterface) {
|
||||||
|
handler.Create(e.(event.CreateEvent), q)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Create: Wrong webhook name should NOT enqueue",
|
||||||
|
event: event.CreateEvent{Object: newWebhook("wrong-name", false)},
|
||||||
|
expectEnqueue: false,
|
||||||
|
handlerFunc: func(e interface{}, q workqueue.RateLimitingInterface) {
|
||||||
|
handler.Create(e.(event.CreateEvent), q)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Create: Wrong object type should NOT enqueue",
|
||||||
|
event: event.CreateEvent{Object: matchingDep},
|
||||||
|
expectEnqueue: false,
|
||||||
|
handlerFunc: func(e interface{}, q workqueue.RateLimitingInterface) {
|
||||||
|
handler.Create(e.(event.CreateEvent), q)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Update: Correct webhook should NOT enqueue (timestamp is zero)",
|
||||||
|
event: event.UpdateEvent{ObjectNew: newWebhook(configuration.MutatingWebhookConfigurationName, false)},
|
||||||
|
expectEnqueue: false,
|
||||||
|
handlerFunc: func(e interface{}, q workqueue.RateLimitingInterface) {
|
||||||
|
handler.Update(e.(event.UpdateEvent), q)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Update: Correct webhook with deletion timestamp SHOULD enqueue",
|
||||||
|
event: event.UpdateEvent{ObjectNew: newWebhook(configuration.MutatingWebhookConfigurationName, true)},
|
||||||
|
expectEnqueue: true,
|
||||||
|
handlerFunc: func(e interface{}, q workqueue.RateLimitingInterface) {
|
||||||
|
handler.Update(e.(event.UpdateEvent), q)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Delete: Correct webhook should enqueue",
|
||||||
|
event: event.DeleteEvent{Object: newWebhook(configuration.MutatingWebhookConfigurationName, false)},
|
||||||
|
expectEnqueue: true,
|
||||||
|
handlerFunc: func(e interface{}, q workqueue.RateLimitingInterface) {
|
||||||
|
handler.Delete(e.(event.DeleteEvent), q)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Generic: Correct webhook should NOT enqueue (timestamp is zero)",
|
||||||
|
event: event.GenericEvent{Object: newWebhook(configuration.MutatingWebhookConfigurationName, false)},
|
||||||
|
expectEnqueue: false,
|
||||||
|
handlerFunc: func(e interface{}, q workqueue.RateLimitingInterface) {
|
||||||
|
handler.Generic(e.(event.GenericEvent), q)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Generic: Correct webhook with deletion timestamp SHOULD enqueue",
|
||||||
|
event: event.GenericEvent{Object: newWebhook(configuration.MutatingWebhookConfigurationName, true)},
|
||||||
|
expectEnqueue: true,
|
||||||
|
handlerFunc: func(e interface{}, q workqueue.RateLimitingInterface) {
|
||||||
|
handler.Generic(e.(event.GenericEvent), q)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
q := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter())
|
||||||
|
tc.handlerFunc(tc.event, q)
|
||||||
|
|
||||||
|
if tc.expectEnqueue {
|
||||||
|
assert.Equal(t, 1, q.Len(), "Expected item to be enqueued")
|
||||||
|
// Verify enqueued item matches our deployment
|
||||||
|
item, _ := q.Get()
|
||||||
|
req := item.(reconcile.Request)
|
||||||
|
assert.Equal(t, "matching-dep", req.Name)
|
||||||
|
assert.Equal(t, "ns", req.Namespace)
|
||||||
|
} else {
|
||||||
|
assert.Equal(t, 0, q.Len(), "Expected queue to be empty")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnqueue(t *testing.T) {
|
||||||
|
depMatch := newDeployment("ns1", "dep-match", true, false)
|
||||||
|
depWrongStrategy := newDeployment("ns1", "dep-wrong-strategy", true, true)
|
||||||
|
depNoLabel := newDeployment("ns2", "dep-no-label", false, false)
|
||||||
|
depMatch2 := newDeployment("ns3", "dep-match-2", true, false)
|
||||||
|
|
||||||
|
fakeClient := fake.NewClientBuilder().WithScheme(newScheme()).WithObjects(
|
||||||
|
depMatch, depWrongStrategy, depNoLabel, depMatch2,
|
||||||
|
).Build()
|
||||||
|
handler := MutatingWebhookEventHandler{Reader: fakeClient}
|
||||||
|
|
||||||
|
t.Run("Enqueues multiple matching deployments", func(t *testing.T) {
|
||||||
|
q := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter())
|
||||||
|
handler.enqueue(q)
|
||||||
|
|
||||||
|
assert.Equal(t, 2, q.Len())
|
||||||
|
// Verify both deployments are enqueued
|
||||||
|
items := []reconcile.Request{}
|
||||||
|
for q.Len() > 0 {
|
||||||
|
item, _ := q.Get()
|
||||||
|
req := item.(reconcile.Request)
|
||||||
|
items = append(items, req)
|
||||||
|
q.Done(item)
|
||||||
|
}
|
||||||
|
assert.ElementsMatch(t, []reconcile.Request{
|
||||||
|
{NamespacedName: client.ObjectKey{Namespace: "ns1", Name: "dep-match"}},
|
||||||
|
{NamespacedName: client.ObjectKey{Namespace: "ns3", Name: "dep-match-2"}},
|
||||||
|
}, items)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Does not enqueue when no deployments match", func(t *testing.T) {
|
||||||
|
clientNoMatch := fake.NewClientBuilder().WithScheme(newScheme()).WithObjects(depWrongStrategy, depNoLabel).Build()
|
||||||
|
handlerNoMatch := MutatingWebhookEventHandler{Reader: clientNoMatch}
|
||||||
|
q := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter())
|
||||||
|
handlerNoMatch.enqueue(q)
|
||||||
|
assert.Equal(t, 0, q.Len())
|
||||||
|
})
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue