From ae0ecf41d4640dc8531fe8161bf400543fa4b833 Mon Sep 17 00:00:00 2001 From: Simon Beck Date: Mon, 4 Sep 2023 11:00:13 +0200 Subject: [PATCH] Add unit tests for webhooks --- operator/user/webhook.go | 23 ++- operator/user/webhook_test.go | 152 +++++++++++++++++- test/e2e/kuttl-test.yaml | 1 - test/e2e/policy/00-assert.yaml | 26 --- test/e2e/policy/00-install.yaml | 17 -- test/e2e/policy/01-assert.yaml | 29 ++++ test/e2e/policy/01-install.yaml | 17 ++ .../policy/{01-upload.yaml => 02-upload.yaml} | 0 8 files changed, 210 insertions(+), 55 deletions(-) create mode 100644 test/e2e/policy/01-assert.yaml create mode 100644 test/e2e/policy/01-install.yaml rename test/e2e/policy/{01-upload.yaml => 02-upload.yaml} (100%) diff --git a/operator/user/webhook.go b/operator/user/webhook.go index 1254012..0dc826d 100644 --- a/operator/user/webhook.go +++ b/operator/user/webhook.go @@ -2,6 +2,7 @@ package user import ( "context" + "encoding/json" "fmt" "github.com/go-logr/logr" @@ -14,7 +15,15 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) -var _ admission.CustomValidator = &Validator{} +var ( + _ admission.CustomValidator = &Validator{} + getProviderConfigFn = getProviderConfig + getMinioAdminFn = getMinioAdmin +) + +type cannedPolicyLister interface { + ListCannedPolicies(context.Context) (map[string]json.RawMessage, error) +} // Validator validates admission requests. type Validator struct { @@ -86,12 +95,12 @@ func (v *Validator) doesPolicyExist(ctx context.Context, user *miniov1.User) err return nil } - config, err := v.getProviderConfig(ctx, user) + config, err := getProviderConfigFn(ctx, user, v.kube) if err != nil { return err } - ma, err := minioutil.NewMinioAdmin(ctx, v.kube, config) + ma, err := getMinioAdminFn(ctx, v.kube, config) if err != nil { return err } @@ -111,9 +120,13 @@ func (v *Validator) doesPolicyExist(ctx context.Context, user *miniov1.User) err return nil } -func (v *Validator) getProviderConfig(ctx context.Context, user *miniov1.User) (*providerv1.ProviderConfig, error) { +func getProviderConfig(ctx context.Context, user *miniov1.User, kube client.Client) (*providerv1.ProviderConfig, error) { configName := user.GetProviderConfigReference().Name config := &providerv1.ProviderConfig{} - err := v.kube.Get(ctx, client.ObjectKey{Name: configName}, config) + err := kube.Get(ctx, client.ObjectKey{Name: configName}, config) return config, err } + +func getMinioAdmin(ctx context.Context, kube client.Client, config *providerv1.ProviderConfig) (cannedPolicyLister, error) { + return minioutil.NewMinioAdmin(ctx, kube, config) +} diff --git a/operator/user/webhook_test.go b/operator/user/webhook_test.go index 2efe2af..a005d4f 100644 --- a/operator/user/webhook_test.go +++ b/operator/user/webhook_test.go @@ -2,18 +2,26 @@ package user import ( "context" + "encoding/json" "testing" xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" "github.com/go-logr/logr" miniov1 "github.com/vshn/provider-minio/apis/minio/v1" + providerv1 "github.com/vshn/provider-minio/apis/provider/v1" + "sigs.k8s.io/controller-runtime/pkg/client" ) +type mockAdminClient struct { + policies map[string]json.RawMessage +} + func TestValidator_ValidateCreate(t *testing.T) { tests := []struct { - name string - obj *miniov1.User - wantErr bool + name string + obj *miniov1.User + wantErr bool + wantPolicies map[string]json.RawMessage }{ { name: "GivenValidObject_ThenNoError", @@ -32,8 +40,51 @@ func TestValidator_ValidateCreate(t *testing.T) { wantErr: true, obj: &miniov1.User{}, }, + { + name: "GivenNotExistingPolicies_ThenError", + wantErr: true, + obj: &miniov1.User{ + Spec: miniov1.UserSpec{ + ForProvider: miniov1.UserParameters{ + Policies: []string{ + "foo", + }, + }, + ResourceSpec: xpv1.ResourceSpec{ + ProviderConfigReference: &xpv1.Reference{ + Name: "test", + }, + }, + }, + }, + }, + { + name: "GivenExistingPolicies_ThenNoError", + obj: &miniov1.User{ + Spec: miniov1.UserSpec{ + ForProvider: miniov1.UserParameters{ + Policies: []string{ + "foo", + }, + }, + ResourceSpec: xpv1.ResourceSpec{ + ProviderConfigReference: &xpv1.Reference{ + Name: "test", + }, + }, + }, + }, + wantPolicies: map[string]json.RawMessage{ + "foo": []byte("foo"), + }, + }, } + for _, tt := range tests { + + getMinioAdminFn = getMockMinioAdmin(tt.wantPolicies) + getProviderConfigFn = getMockProviderConfig + t.Run(tt.name, func(t *testing.T) { v := &Validator{ log: logr.Discard(), @@ -44,6 +95,10 @@ func TestValidator_ValidateCreate(t *testing.T) { return } }) + + getMinioAdminFn = getMinioAdmin + getProviderConfigFn = getProviderConfig + } } @@ -53,13 +108,15 @@ func TestValidator_ValidateUpdate(t *testing.T) { newObj *miniov1.User } tests := []struct { - name string - args args - wantErr bool + name string + args args + wantErr bool + wantPolicies map[string]json.RawMessage }{ { name: "GivenSameObject_ThenNoError", args: args{ + oldObj: &miniov1.User{ Spec: miniov1.UserSpec{ ResourceSpec: xpv1.ResourceSpec{ @@ -130,8 +187,72 @@ func TestValidator_ValidateUpdate(t *testing.T) { }, }, }, + { + name: "GivenNotExistingPolicies_ThenError", + wantErr: true, + args: args{ + oldObj: &miniov1.User{ + Spec: miniov1.UserSpec{ + ResourceSpec: xpv1.ResourceSpec{ + ProviderConfigReference: &xpv1.Reference{ + Name: "provider", + }, + }, + }, + }, + newObj: &miniov1.User{ + Spec: miniov1.UserSpec{ + ForProvider: miniov1.UserParameters{ + Policies: []string{ + "foo", + }, + }, + ResourceSpec: xpv1.ResourceSpec{ + ProviderConfigReference: &xpv1.Reference{ + Name: "test", + }, + }, + }, + }, + }, + }, + { + name: "GivenExistingPolicies_ThenNoError", + args: args{ + oldObj: &miniov1.User{ + Spec: miniov1.UserSpec{ + ResourceSpec: xpv1.ResourceSpec{ + ProviderConfigReference: &xpv1.Reference{ + Name: "provider", + }, + }, + }, + }, + newObj: &miniov1.User{ + Spec: miniov1.UserSpec{ + ForProvider: miniov1.UserParameters{ + Policies: []string{ + "foo", + }, + }, + ResourceSpec: xpv1.ResourceSpec{ + ProviderConfigReference: &xpv1.Reference{ + Name: "test", + }, + }, + }, + }, + }, + wantPolicies: map[string]json.RawMessage{ + "foo": []byte("foo"), + }, + }, } for _, tt := range tests { + + getMinioAdminFn = getMockMinioAdmin(tt.wantPolicies) + getProviderConfigFn = getMockProviderConfig + t.Run(tt.name, func(t *testing.T) { v := &Validator{ log: logr.Discard(), @@ -143,5 +264,24 @@ func TestValidator_ValidateUpdate(t *testing.T) { } }) + + getMinioAdminFn = getMinioAdmin + getProviderConfigFn = getProviderConfig + } +} + +func getMockProviderConfig(context.Context, *miniov1.User, client.Client) (*providerv1.ProviderConfig, error) { + return &providerv1.ProviderConfig{}, nil +} + +func getMockMinioAdmin(policies map[string]json.RawMessage) func(context.Context, client.Client, *providerv1.ProviderConfig) (cannedPolicyLister, error) { + return func(context.Context, client.Client, *providerv1.ProviderConfig) (cannedPolicyLister, error) { + return &mockAdminClient{ + policies: policies, + }, nil } } + +func (m *mockAdminClient) ListCannedPolicies(ctx context.Context) (map[string]json.RawMessage, error) { + return m.policies, nil +} diff --git a/test/e2e/kuttl-test.yaml b/test/e2e/kuttl-test.yaml index cfb87bf..10d8c3f 100644 --- a/test/e2e/kuttl-test.yaml +++ b/test/e2e/kuttl-test.yaml @@ -4,4 +4,3 @@ testDirs: - ./test/e2e/ namespace: default timeout: 60 -parallel: 1 diff --git a/test/e2e/policy/00-assert.yaml b/test/e2e/policy/00-assert.yaml index 785b0a3..5cbe988 100644 --- a/test/e2e/policy/00-assert.yaml +++ b/test/e2e/policy/00-assert.yaml @@ -26,32 +26,6 @@ status: endpointURL: http://minio-server.minio.svc:9000/ --- apiVersion: minio.crossplane.io/v1 -kind: User -metadata: - name: testuser-policy -spec: - forProvider: {} - providerConfigRef: - name: provider-config - writeConnectionSecretToRef: - name: testuser-policy - namespace: default -status: - atProvider: - userName: testuser-policy - status: enabled - conditions: - - status: 'True' - - status: 'True' ---- -apiVersion: v1 -kind: Secret -metadata: - name: testuser-policy - namespace: default -type: connection.crossplane.io/v1alpha1 ---- -apiVersion: minio.crossplane.io/v1 kind: Policy metadata: name: e2e-test-policy diff --git a/test/e2e/policy/00-install.yaml b/test/e2e/policy/00-install.yaml index 741c2a4..1ea8eb2 100644 --- a/test/e2e/policy/00-install.yaml +++ b/test/e2e/policy/00-install.yaml @@ -23,20 +23,3 @@ spec: name: provider-config status: atProvider: {} ---- -apiVersion: minio.crossplane.io/v1 -kind: User -metadata: - name: testuser-policy -spec: - forProvider: - policies: - - e2e-test-policy - providerConfigRef: - name: provider-config - writeConnectionSecretToRef: - name: testuser-policy - namespace: default -status: - atProvider: {} ---- diff --git a/test/e2e/policy/01-assert.yaml b/test/e2e/policy/01-assert.yaml new file mode 100644 index 0000000..1fff660 --- /dev/null +++ b/test/e2e/policy/01-assert.yaml @@ -0,0 +1,29 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +--- +apiVersion: minio.crossplane.io/v1 +kind: User +metadata: + name: testuser-policy +spec: + forProvider: {} + providerConfigRef: + name: provider-config + writeConnectionSecretToRef: + name: testuser-policy + namespace: default +status: + atProvider: + userName: testuser-policy + status: enabled + conditions: + - status: 'True' + - status: 'True' +--- +apiVersion: v1 +kind: Secret +metadata: + name: testuser-policy + namespace: default +type: connection.crossplane.io/v1alpha1 diff --git a/test/e2e/policy/01-install.yaml b/test/e2e/policy/01-install.yaml new file mode 100644 index 0000000..96d0ba8 --- /dev/null +++ b/test/e2e/policy/01-install.yaml @@ -0,0 +1,17 @@ +--- +apiVersion: minio.crossplane.io/v1 +kind: User +metadata: + name: testuser-policy +spec: + forProvider: + policies: + - e2e-test-policy + providerConfigRef: + name: provider-config + writeConnectionSecretToRef: + name: testuser-policy + namespace: default +status: + atProvider: {} +--- diff --git a/test/e2e/policy/01-upload.yaml b/test/e2e/policy/02-upload.yaml similarity index 100% rename from test/e2e/policy/01-upload.yaml rename to test/e2e/policy/02-upload.yaml