From 404ff7c5586e126d69a3dddfd7b82a27f5e51ab1 Mon Sep 17 00:00:00 2001 From: Nicolas Bigler Date: Tue, 26 Nov 2024 15:08:13 +0100 Subject: [PATCH] Add tests for the nextcloud webhooks Signed-off-by: Nicolas Bigler --- .../webhooks/default_handler_test.go | 94 +++++----- pkg/controller/webhooks/nextcloud.go | 13 +- pkg/controller/webhooks/nextcloud_test.go | 164 ++++++++++++++++++ 3 files changed, 217 insertions(+), 54 deletions(-) create mode 100644 pkg/controller/webhooks/nextcloud_test.go diff --git a/pkg/controller/webhooks/default_handler_test.go b/pkg/controller/webhooks/default_handler_test.go index ef48a8368..9f9102b4a 100644 --- a/pkg/controller/webhooks/default_handler_test.go +++ b/pkg/controller/webhooks/default_handler_test.go @@ -32,23 +32,23 @@ func TestSetupWebhookHandlerWithManager_ValidateCreate(t *testing.T) { WithObjects(claimNS). Build() - handler := NextcloudWebhookHandler{ + handler := KeycloakWebhookHandler{ DefaultWebhookHandler: DefaultWebhookHandler{ client: fclient, log: logr.Discard(), withQuota: true, - obj: &vshnv1.VSHNNextcloud{}, - name: "nextcloud", + obj: &vshnv1.VSHNKeycloak{}, + name: "keycloak", }, } - redisOrig := &vshnv1.VSHNNextcloud{ + keycloakOrig := &vshnv1.VSHNKeycloak{ ObjectMeta: metav1.ObjectMeta{ Name: "myinstance", Namespace: "claimns", }, - Spec: vshnv1.VSHNNextcloudSpec{ - Parameters: vshnv1.VSHNNextcloudParameters{ + Spec: vshnv1.VSHNKeycloakSpec{ + Parameters: vshnv1.VSHNKeycloakParameters{ Size: vshnv1.VSHNSizeSpec{ Requests: vshnv1.VSHNDBaaSSizeRequestsSpec{ CPU: "500m", @@ -59,71 +59,71 @@ func TestSetupWebhookHandlerWithManager_ValidateCreate(t *testing.T) { } // When within quota - _, err := handler.ValidateCreate(ctx, redisOrig) + _, err := handler.ValidateCreate(ctx, keycloakOrig) //Then no err assert.NoError(t, err) // When quota breached // CPU Requests - nextcloudInvalid := redisOrig.DeepCopy() - nextcloudInvalid.Spec.Parameters.Size.Requests.CPU = "5000m" - _, err = handler.ValidateCreate(ctx, nextcloudInvalid) + keycloakInvalid := keycloakOrig.DeepCopy() + keycloakInvalid.Spec.Parameters.Size.Requests.CPU = "5000m" + _, err = handler.ValidateCreate(ctx, keycloakInvalid) assert.Error(t, err) // CPU Limit - nextcloudInvalid = redisOrig.DeepCopy() - nextcloudInvalid.Spec.Parameters.Size.CPU = "5000m" - _, err = handler.ValidateCreate(ctx, nextcloudInvalid) + keycloakInvalid = keycloakOrig.DeepCopy() + keycloakInvalid.Spec.Parameters.Size.CPU = "5000m" + _, err = handler.ValidateCreate(ctx, keycloakInvalid) assert.Error(t, err) // Memory Limit - nextcloudInvalid = redisOrig.DeepCopy() - nextcloudInvalid.Spec.Parameters.Size.Memory = "25Gi" - _, err = handler.ValidateCreate(ctx, nextcloudInvalid) + keycloakInvalid = keycloakOrig.DeepCopy() + keycloakInvalid.Spec.Parameters.Size.Memory = "25Gi" + _, err = handler.ValidateCreate(ctx, keycloakInvalid) assert.Error(t, err) // Memory Requests - nextcloudInvalid = redisOrig.DeepCopy() - nextcloudInvalid.Spec.Parameters.Size.Requests.Memory = "25Gi" - _, err = handler.ValidateCreate(ctx, nextcloudInvalid) + keycloakInvalid = keycloakOrig.DeepCopy() + keycloakInvalid.Spec.Parameters.Size.Requests.Memory = "25Gi" + _, err = handler.ValidateCreate(ctx, keycloakInvalid) assert.Error(t, err) // Disk - nextcloudInvalid = redisOrig.DeepCopy() - nextcloudInvalid.Spec.Parameters.Size.Disk = "25Ti" - _, err = handler.ValidateCreate(ctx, nextcloudInvalid) + keycloakInvalid = keycloakOrig.DeepCopy() + keycloakInvalid.Spec.Parameters.Size.Disk = "25Ti" + _, err = handler.ValidateCreate(ctx, keycloakInvalid) assert.Error(t, err) //When invalid size // CPU Requests - nextcloudInvalid = redisOrig.DeepCopy() - nextcloudInvalid.Spec.Parameters.Size.Requests.CPU = "foo" - _, err = handler.ValidateCreate(ctx, nextcloudInvalid) + keycloakInvalid = keycloakOrig.DeepCopy() + keycloakInvalid.Spec.Parameters.Size.Requests.CPU = "foo" + _, err = handler.ValidateCreate(ctx, keycloakInvalid) assert.Error(t, err) // CPU Limit - nextcloudInvalid = redisOrig.DeepCopy() - nextcloudInvalid.Spec.Parameters.Size.CPU = "foo" - _, err = handler.ValidateCreate(ctx, nextcloudInvalid) + keycloakInvalid = keycloakOrig.DeepCopy() + keycloakInvalid.Spec.Parameters.Size.CPU = "foo" + _, err = handler.ValidateCreate(ctx, keycloakInvalid) assert.Error(t, err) // Memory Limit - nextcloudInvalid = redisOrig.DeepCopy() - nextcloudInvalid.Spec.Parameters.Size.Memory = "foo" - _, err = handler.ValidateCreate(ctx, nextcloudInvalid) + keycloakInvalid = keycloakOrig.DeepCopy() + keycloakInvalid.Spec.Parameters.Size.Memory = "foo" + _, err = handler.ValidateCreate(ctx, keycloakInvalid) assert.Error(t, err) // Memory Requests - nextcloudInvalid = redisOrig.DeepCopy() - nextcloudInvalid.Spec.Parameters.Size.Requests.Memory = "foo" - _, err = handler.ValidateCreate(ctx, nextcloudInvalid) + keycloakInvalid = keycloakOrig.DeepCopy() + keycloakInvalid.Spec.Parameters.Size.Requests.Memory = "foo" + _, err = handler.ValidateCreate(ctx, keycloakInvalid) assert.Error(t, err) // Disk - nextcloudInvalid = redisOrig.DeepCopy() - nextcloudInvalid.Spec.Parameters.Size.Disk = "foo" - _, err = handler.ValidateCreate(ctx, nextcloudInvalid) + keycloakInvalid = keycloakOrig.DeepCopy() + keycloakInvalid.Spec.Parameters.Size.Disk = "foo" + _, err = handler.ValidateCreate(ctx, keycloakInvalid) assert.Error(t, err) } @@ -146,23 +146,23 @@ func TestSetupWebhookHandlerWithManager_ValidateDelete(t *testing.T) { WithObjects(claimNS). Build() - handler := NextcloudWebhookHandler{ + handler := KeycloakWebhookHandler{ DefaultWebhookHandler: DefaultWebhookHandler{ client: fclient, log: logr.Discard(), withQuota: true, - obj: &vshnv1.VSHNNextcloud{}, - name: "nextcloud", + obj: &vshnv1.VSHNKeycloak{}, + name: "keycloak", }, } - nextcloudOrig := &vshnv1.VSHNNextcloud{ + keycloakOrig := &vshnv1.VSHNKeycloak{ ObjectMeta: metav1.ObjectMeta{ Name: "myinstance", Namespace: "claimns", }, - Spec: vshnv1.VSHNNextcloudSpec{ - Parameters: vshnv1.VSHNNextcloudParameters{ + Spec: vshnv1.VSHNKeycloakSpec{ + Parameters: vshnv1.VSHNKeycloakParameters{ Security: vshnv1.Security{ DeletionProtection: true, }, @@ -171,16 +171,16 @@ func TestSetupWebhookHandlerWithManager_ValidateDelete(t *testing.T) { } // When within quota - _, err := handler.ValidateDelete(ctx, nextcloudOrig) + _, err := handler.ValidateDelete(ctx, keycloakOrig) //Then err assert.Error(t, err) //Instances - nextcloudDeletable := nextcloudOrig.DeepCopy() - nextcloudDeletable.Spec.Parameters.Security.DeletionProtection = false + keycloakDeletable := keycloakOrig.DeepCopy() + keycloakDeletable.Spec.Parameters.Security.DeletionProtection = false - _, err = handler.ValidateDelete(ctx, nextcloudDeletable) + _, err = handler.ValidateDelete(ctx, keycloakDeletable) //Then no err assert.NoError(t, err) diff --git a/pkg/controller/webhooks/nextcloud.go b/pkg/controller/webhooks/nextcloud.go index 49be9dda3..280fd4c91 100644 --- a/pkg/controller/webhooks/nextcloud.go +++ b/pkg/controller/webhooks/nextcloud.go @@ -2,7 +2,6 @@ package webhooks import ( "context" - "errors" "fmt" valid "github.com/asaskevich/govalidator" @@ -61,16 +60,16 @@ func (n *NextcloudWebhookHandler) ValidateCreate(ctx context.Context, obj runtim } if len(nx.Spec.Parameters.Service.FQDN) == 0 { - return nil, fmt.Errorf("FQDN array is empty, but requires at least one entry: %w", errors.New("empty fqdn")) + return nil, fmt.Errorf("FQDN array is empty, but requires at least one entry") } if err := validateFQDNs(nx.Spec.Parameters.Service.FQDN); err != nil { - return nil, fmt.Errorf("FQDN is not a valid DNS name: %w", err) + return nil, err } if nx.Spec.Parameters.Service.Collabora.Enabled { if err := validateFQDNs([]string{nx.Spec.Parameters.Service.Collabora.FQDN}); err != nil { - return nil, fmt.Errorf("FQDN is not a valid DNS name: %w", err) + return nil, err } } @@ -89,16 +88,16 @@ func (n *NextcloudWebhookHandler) ValidateUpdate(ctx context.Context, oldObj, ne } if len(nx.Spec.Parameters.Service.FQDN) == 0 { - return nil, fmt.Errorf("FQDN array is empty, but requires at least one entry: %w", errors.New("empty fqdn")) + return nil, fmt.Errorf("FQDN array is empty, but requires at least one entry") } if err := validateFQDNs(nx.Spec.Parameters.Service.FQDN); err != nil { - return nil, fmt.Errorf("FQDN is not a valid DNS name: %w", err) + return nil, err } if nx.Spec.Parameters.Service.Collabora.Enabled { if err := validateFQDNs([]string{nx.Spec.Parameters.Service.Collabora.FQDN}); err != nil { - return nil, fmt.Errorf("FQDN is not a valid DNS name: %w", err) + return nil, err } } diff --git a/pkg/controller/webhooks/nextcloud_test.go b/pkg/controller/webhooks/nextcloud_test.go new file mode 100644 index 000000000..7250e0509 --- /dev/null +++ b/pkg/controller/webhooks/nextcloud_test.go @@ -0,0 +1,164 @@ +package webhooks + +import ( + "context" + "fmt" + "testing" + + "github.com/go-logr/logr" + "github.com/stretchr/testify/assert" + vshnv1 "github.com/vshn/appcat/v4/apis/vshn/v1" + "github.com/vshn/appcat/v4/pkg" + "github.com/vshn/appcat/v4/pkg/common/utils" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client/fake" +) + +func TestWebhookHandlerWithManager_ValidateCreate_FQDN(t *testing.T) { + // Given + claimNS := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "claimns", + Labels: map[string]string{ + utils.OrgLabelName: "myorg", + }, + }, + } + + ctx := context.TODO() + + fclient := fake.NewClientBuilder(). + WithScheme(pkg.SetupScheme()). + WithObjects(claimNS). + Build() + + handler := NextcloudWebhookHandler{ + DefaultWebhookHandler: DefaultWebhookHandler{ + client: fclient, + log: logr.Discard(), + withQuota: true, + obj: &vshnv1.VSHNNextcloud{}, + name: "nextcloud", + }, + } + + nextcloudOrig := &vshnv1.VSHNNextcloud{ + ObjectMeta: metav1.ObjectMeta{ + Name: "myinstance", + Namespace: "claimns", + }, + Spec: vshnv1.VSHNNextcloudSpec{ + Parameters: vshnv1.VSHNNextcloudParameters{ + Service: vshnv1.VSHNNextcloudServiceSpec{ + FQDN: []string{ + "mynextcloud.example.tld", + }, + }, + Size: vshnv1.VSHNSizeSpec{ + Requests: vshnv1.VSHNDBaaSSizeRequestsSpec{ + CPU: "500m", + }, + }, + }, + }, + } + + _, err := handler.ValidateCreate(ctx, nextcloudOrig) + + //Then no err + assert.NoError(t, err) + + // When FQDN empty + nextcloudInvalid := nextcloudOrig.DeepCopy() + nextcloudInvalid.Spec.Parameters.Service.FQDN = []string{} + + _, err = handler.ValidateCreate(ctx, nextcloudInvalid) + assert.Error(t, err) + assert.Equal(t, fmt.Errorf("FQDN array is empty, but requires at least one entry"), err) + + // When FQDN invalid + nextcloudInvalid = nextcloudOrig.DeepCopy() + nextcloudInvalid.Spec.Parameters.Service.FQDN = []string{ + "n€xtcloud.example.tld", + } + + _, err = handler.ValidateCreate(ctx, nextcloudInvalid) + assert.Error(t, err) + assert.Equal(t, fmt.Errorf("FQDN n€xtcloud.example.tld is not a valid DNS name"), err) +} + +func TestWebhookHandlerWithManager_ValidateUpdate_FQDN(t *testing.T) { + // Given + claimNS := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "claimns", + Labels: map[string]string{ + utils.OrgLabelName: "myorg", + }, + }, + } + + ctx := context.TODO() + + fclient := fake.NewClientBuilder(). + WithScheme(pkg.SetupScheme()). + WithObjects(claimNS). + Build() + + handler := NextcloudWebhookHandler{ + DefaultWebhookHandler: DefaultWebhookHandler{ + client: fclient, + log: logr.Discard(), + withQuota: true, + obj: &vshnv1.VSHNNextcloud{}, + name: "nextcloud", + }, + } + + nextcloudOrig := &vshnv1.VSHNNextcloud{ + ObjectMeta: metav1.ObjectMeta{ + Name: "myinstance", + Namespace: "claimns", + }, + Spec: vshnv1.VSHNNextcloudSpec{ + Parameters: vshnv1.VSHNNextcloudParameters{ + Service: vshnv1.VSHNNextcloudServiceSpec{ + FQDN: []string{ + "mynextcloud.example.tld", + }, + }, + Size: vshnv1.VSHNSizeSpec{ + Requests: vshnv1.VSHNDBaaSSizeRequestsSpec{ + CPU: "500m", + }, + }, + }, + }, + } + nextcloudNew := nextcloudOrig.DeepCopy() + nextcloudNew.Spec.Parameters.Service.FQDN = append(nextcloudNew.Spec.Parameters.Service.FQDN, "myother-nexctloud.example.tld") + + _, err := handler.ValidateUpdate(ctx, nextcloudOrig, nextcloudNew) + + //Then no err + assert.NoError(t, err) + + // When FQDN empty + nextcloudInvalid := nextcloudOrig.DeepCopy() + nextcloudInvalid.Spec.Parameters.Service.FQDN = []string{} + + _, err = handler.ValidateUpdate(ctx, nextcloudOrig, nextcloudInvalid) + assert.Error(t, err) + assert.Equal(t, fmt.Errorf("FQDN array is empty, but requires at least one entry"), err) + + // When FQDN invalid + nextcloudInvalid = nextcloudOrig.DeepCopy() + nextcloudInvalid.Spec.Parameters.Service.FQDN = []string{ + "n€xtcloud.example.tld", + } + + _, err = handler.ValidateUpdate(ctx, nextcloudOrig, nextcloudInvalid) + assert.Error(t, err) + assert.Equal(t, fmt.Errorf("FQDN n€xtcloud.example.tld is not a valid DNS name"), err) +}