-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test(e2e): implement ginkgo as e2e suite
Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>
- Loading branch information
1 parent
f505ba5
commit 896cb62
Showing
49 changed files
with
430 additions
and
3 deletions.
There are no files selected for viewing
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
name: e2e | ||
permissions: {} | ||
|
||
on: | ||
push: | ||
branches: [ "*" ] | ||
paths: | ||
- '.github/workflows/e2e.yml' | ||
- 'api/**' | ||
- 'controllers/**' | ||
- 'internal/**' | ||
- 'e2e/*' | ||
- 'Dockerfile' | ||
- 'go.*' | ||
- 'main.go' | ||
- 'Makefile' | ||
pull_request: | ||
branches: [ "*" ] | ||
paths: | ||
- '.github/workflows/e2e.yml' | ||
- 'api/**' | ||
- 'controllers/**' | ||
- 'internal/**' | ||
- 'e2e/*' | ||
- 'Dockerfile' | ||
- 'go.*' | ||
- 'main.go' | ||
- 'Makefile' | ||
|
||
concurrency: | ||
group: ${{ github.workflow }}-${{ github.ref }} | ||
cancel-in-progress: true | ||
|
||
jobs: | ||
kind: | ||
name: Kubernetes | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
k8s-version: [ 'v1.24.7', 'v1.25.3', 'v1.26.3', 'v1.27.2', 'v1.28.0', 'v1.29.0', 'v1.30.0', 'v1.31.0' ] | ||
runs-on: ubuntu-20.04 | ||
steps: | ||
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 | ||
with: | ||
fetch-depth: 0 | ||
- uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 | ||
with: | ||
go-version-file: 'go.mod' | ||
- uses: engineerd/setup-kind@aa272fe2a7309878ffc2a81c56cfe3ef108ae7d0 # v0.5.0 | ||
with: | ||
skipClusterCreation: true | ||
version: v0.14.0 | ||
- uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v3 | ||
with: | ||
version: v3.14.2 | ||
- name: e2e testing | ||
run: KIND_K8S_VERSION=${{ matrix.k8s-version }} make e2e |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
apiVersion: kind.x-k8s.io/v1alpha4 | ||
networking: | ||
apiServerAddress: "127.0.0.1" | ||
apiServerPort: 6443 | ||
kind: Cluster | ||
nodes: | ||
- role: control-plane | ||
- role: worker | ||
extraPortMappings: | ||
- hostPort: 9001 | ||
containerPort: 9001 | ||
- role: worker | ||
extraPortMappings: | ||
- hostPort: 9002 | ||
containerPort: 9002 |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package e2e_test | ||
|
||
import ( | ||
"testing" | ||
|
||
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
func TestE2e(t *testing.T) { | ||
t.Parallel() | ||
RegisterFailHandler(Fail) | ||
RunSpecs(t, "E2e Suite") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
package e2e_test | ||
|
||
import ( | ||
"context" | ||
|
||
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
rbacv1 "k8s.io/api/rbac/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/client-go/kubernetes" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
|
||
v1beta1 "github.com/projectcapsule/capsule-proxy/api/v1beta1" | ||
) | ||
|
||
var _ = Describe("GlobalProxySettings", func() { | ||
var aliceClient, bobClient *kubernetes.Clientset | ||
|
||
BeforeEach(func() { | ||
var err error | ||
|
||
aliceClient, err = loadKubeConfig("alice") | ||
Expect(err).ToNot(HaveOccurred()) | ||
bobClient, err = loadKubeConfig("bob") | ||
Expect(err).ToNot(HaveOccurred()) | ||
|
||
// Create Global Proxy Settings | ||
settings := []*v1beta1.GlobalProxySettings{ | ||
{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: "global-proxy-settings", | ||
Labels: e2eLabels(), | ||
}, | ||
Spec: v1beta1.GlobalProxySettingsSpec{ | ||
Rules: []v1beta1.GlobalSubjectSpec{ | ||
{ | ||
ClusterResources: []v1beta1.ClusterResource{ | ||
{ | ||
APIGroups: []string{"rbac.authorization.k8s.io/*"}, | ||
Resources: []string{"*"}, | ||
Operations: []v1beta1.ClusterResourceOperation{v1beta1.ClusterResourceOperationList}, | ||
Selector: &metav1.LabelSelector{ | ||
MatchLabels: e2eLabels(), | ||
}, | ||
}, | ||
{ | ||
APIGroups: []string{"capsule.clastix.io/*"}, | ||
Resources: []string{"*"}, | ||
Operations: []v1beta1.ClusterResourceOperation{v1beta1.ClusterResourceOperationList}, | ||
Selector: &metav1.LabelSelector{ | ||
MatchLabels: e2eLabels(), | ||
}, | ||
}, | ||
}, | ||
Subjects: []v1beta1.GlobalSubject{ | ||
{ | ||
Kind: "User", | ||
Name: "alice", | ||
}, | ||
{ | ||
Kind: "User", | ||
Name: "bob", | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
for _, tran := range settings { | ||
Eventually(func() error { | ||
tran.ResourceVersion = "" | ||
|
||
return k8sClient.Create(context.TODO(), tran) | ||
}).Should(Succeed()) | ||
} | ||
|
||
// Load Alice's kubeconfig | ||
aliceClient, err = loadKubeConfig("alice") | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
// Load Bob's kubeconfig | ||
bobClient, err = loadKubeConfig("bob") | ||
Expect(err).NotTo(HaveOccurred()) | ||
}) | ||
|
||
JustAfterEach(func() { | ||
// Define Resources which are lifecycled after each test | ||
resourcesToClean := []client.Object{ | ||
&v1beta1.GlobalProxySettings{}, | ||
&rbacv1.ClusterRole{}, | ||
} | ||
|
||
Eventually(func() error { | ||
return cleanResources(resourcesToClean, e2eSelector()) | ||
}, defaultTimeoutInterval, defaultPollInterval).Should(Succeed()) | ||
}) | ||
|
||
It("Allow listing specific clusterroles (without tenants)", func() { | ||
roles := []*rbacv1.ClusterRole{ | ||
{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: "tenant-viewer", | ||
Labels: e2eLabels(), | ||
}, | ||
Rules: []rbacv1.PolicyRule{ | ||
{ | ||
APIGroups: []string{""}, | ||
Resources: []string{"pods"}, | ||
Verbs: []string{"list"}, | ||
}, | ||
}, | ||
}, | ||
{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: "tenant-editor", | ||
Labels: e2eLabels(), | ||
}, | ||
Rules: []rbacv1.PolicyRule{ | ||
{ | ||
APIGroups: []string{""}, | ||
Resources: []string{"pods"}, | ||
Verbs: []string{"*"}, | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
for _, role := range roles { | ||
Eventually(func() error { | ||
role.ResourceVersion = "" | ||
|
||
return k8sClient.Create(context.Background(), role) | ||
}).Should(Succeed()) | ||
} | ||
|
||
listClusterRoles := func(clientset *kubernetes.Clientset) ([]string, error) { | ||
clusterRoles, err := clientset.RbacV1().ClusterRoles().List(context.Background(), metav1.ListOptions{}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
var roleNames []string | ||
for _, role := range clusterRoles.Items { | ||
roleNames = append(roleNames, role.Name) | ||
} | ||
|
||
return roleNames, nil | ||
} | ||
|
||
// Should only list the clusterroles that are allowed by the GlobalProxySettings | ||
expectedRoles := []string{"tenant-editor", "tenant-viewer"} | ||
|
||
// Check Alice's access to ClusterRoles | ||
Eventually(func() ([]string, error) { | ||
return listClusterRoles(aliceClient) | ||
}).Should(Equal(expectedRoles), "Alice should only have access to the specified cluster roles") | ||
|
||
// Check Bob's access to ClusterRoles (must contain only the expected roles) | ||
Eventually(func() ([]string, error) { | ||
return listClusterRoles(bobClient) | ||
}).Should(Equal(expectedRoles), "Bob should only have access to the specified cluster roles") | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package e2e_test | ||
|
||
import ( | ||
"context" | ||
"time" | ||
|
||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
) | ||
|
||
type e2eClient struct { | ||
client.Client | ||
} | ||
|
||
func (e *e2eClient) sleep() { | ||
time.Sleep(250 * time.Millisecond) | ||
} | ||
|
||
func (e *e2eClient) Get(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error { | ||
defer e.sleep() | ||
|
||
return e.Client.Get(ctx, key, obj, opts...) | ||
} | ||
|
||
func (e *e2eClient) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error { | ||
defer e.sleep() | ||
|
||
return e.Client.List(ctx, list, opts...) | ||
} | ||
|
||
func (e *e2eClient) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error { | ||
defer e.sleep() | ||
|
||
return e.Client.Create(ctx, obj, opts...) | ||
} | ||
|
||
func (e *e2eClient) Delete(ctx context.Context, obj client.Object, opts ...client.DeleteOption) error { | ||
defer e.sleep() | ||
|
||
return e.Client.Delete(ctx, obj, opts...) | ||
} | ||
|
||
func (e *e2eClient) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { | ||
defer e.sleep() | ||
|
||
return e.Client.Update(ctx, obj, opts...) | ||
} | ||
|
||
func (e *e2eClient) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error { | ||
defer e.sleep() | ||
|
||
return e.Client.Patch(ctx, obj, patch, opts...) | ||
} | ||
|
||
func (e *e2eClient) DeleteAllOf(ctx context.Context, obj client.Object, opts ...client.DeleteAllOfOption) error { | ||
defer e.sleep() | ||
|
||
return e.Client.DeleteAllOf(ctx, obj, opts...) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package e2e_test | ||
|
||
import ( | ||
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
"k8s.io/client-go/rest" | ||
"k8s.io/kubectl/pkg/scheme" | ||
"k8s.io/utils/ptr" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
"sigs.k8s.io/controller-runtime/pkg/envtest" | ||
logf "sigs.k8s.io/controller-runtime/pkg/log" | ||
"sigs.k8s.io/controller-runtime/pkg/log/zap" | ||
|
||
v1beta1 "github.com/projectcapsule/capsule-proxy/api/v1beta1" | ||
) | ||
|
||
//nolint:gochecknoglobals | ||
var ( | ||
cfg *rest.Config | ||
k8sClient client.Client | ||
testEnv *envtest.Environment | ||
) | ||
|
||
var _ = BeforeSuite(func() { | ||
logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter))) | ||
|
||
By("bootstrapping test environment") | ||
testEnv = &envtest.Environment{ | ||
UseExistingCluster: ptr.To(true), | ||
} | ||
|
||
var err error | ||
cfg, err = testEnv.Start() | ||
Expect(err).ToNot(HaveOccurred()) | ||
Expect(cfg).ToNot(BeNil()) | ||
|
||
Expect(v1beta1.AddToScheme(scheme.Scheme)).NotTo(HaveOccurred()) | ||
|
||
ctrlClient, err := client.New(cfg, client.Options{Scheme: scheme.Scheme}) | ||
Expect(err).ToNot(HaveOccurred()) | ||
Expect(ctrlClient).ToNot(BeNil()) | ||
|
||
k8sClient = &e2eClient{Client: ctrlClient} | ||
}) | ||
|
||
var _ = AfterSuite(func() { | ||
By("tearing down the test environment") | ||
Expect(testEnv.Stop()).ToNot(HaveOccurred()) | ||
}) |
Oops, something went wrong.