Skip to content

Commit

Permalink
Merge pull request #1500 from harishsurf/scoped-e2e
Browse files Browse the repository at this point in the history
Convert scoped_client_test to ginkgo
  • Loading branch information
openshift-merge-robot authored Oct 29, 2020
2 parents 8e5ad4d + 9d9cb57 commit 684ef55
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 67 deletions.
89 changes: 36 additions & 53 deletions test/e2e/scoped_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,14 @@ package e2e

import (
"context"
"time"

. "github.com/onsi/ginkgo"
"github.com/onsi/ginkgo/extensions/table"
. "github.com/onsi/gomega"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/rest"

Expand All @@ -22,17 +19,18 @@ import (
"github.com/operator-framework/operator-lifecycle-manager/test/e2e/ctx"
)

var _ = Describe("Scoped Client", func() {
var _ = Describe("Scoped Client bound to a service account can be used to make API calls", func() {
// TestScopedClient ensures that we can create a scoped client bound to a
// service account and then we can use the scoped client to make API calls.
var (
config *rest.Config

var config *rest.Config

var kubeclient operatorclient.ClientInterface
var crclient versioned.Interface
var dynamicclient dynamic.Interface
kubeclient operatorclient.ClientInterface
crclient versioned.Interface
dynamicclient dynamic.Interface

var logger *logrus.Logger
logger *logrus.Logger
)

BeforeEach(func() {
config = ctx.Ctx().RESTConfig()
Expand All @@ -42,6 +40,7 @@ var _ = Describe("Scoped Client", func() {
dynamicclient = ctx.Ctx().DynamicClient()

logger = logrus.New()
logger.SetOutput(GinkgoWriter)
})

type testParameter struct {
Expand All @@ -55,30 +54,28 @@ var _ = Describe("Scoped Client", func() {
// scoped client has enough permission, we expect a NotFound error code.
// Otherwise, we expect a 'Forbidden' error code due to lack of permission.

table.Entry("ServiceAccountDoesNotHaveAnyPermission", testParameter{
table.Entry("returns error on API calls as ServiceAccount does not have any permission", testParameter{
// The service account does not have any permission granted to it.
// We expect the get api call to return 'Forbidden' error due to
// lack of permission.
name: "ServiceAccountDoesNotHaveAnyPermission",
assertFunc: func(errGot error) {
require.True(GinkgoT(), k8serrors.IsForbidden(errGot))
Expect(k8serrors.IsForbidden(errGot)).To(BeTrue())
},
}),
table.Entry("ServiceAccountHasPermission", testParameter{
table.Entry("successfully allows API calls to be made when ServiceAccount has permission", testParameter{
// The service account does have permission granted to it.
// We expect the get api call to return 'NotFound' error.
name: "ServiceAccountHasPermission",
grant: func(namespace, name string) (cleanup cleanupFunc) {
cleanup = grantPermission(GinkgoT(), kubeclient, namespace, name)
return
},
assertFunc: func(errGot error) {
require.True(GinkgoT(), k8serrors.IsNotFound(errGot))
Expect(k8serrors.IsNotFound(errGot)).To(BeTrue())
},
}),
}

table.DescribeTable("Test", func(tt testParameter) {
table.DescribeTable("API call using scoped client", func(tc testParameter) {
// Steps:
// 1. Create a new namespace
// 2. Create a service account.
Expand All @@ -91,63 +88,49 @@ var _ = Describe("Scoped Client", func() {
defer cleanupNS()

saName := genName("user-defined-")
sa, cleanupSA := newServiceAccount(GinkgoT(), kubeclient, namespace, saName)
sa, cleanupSA := newServiceAccount(kubeclient, namespace, saName)
defer cleanupSA()

waitForServiceAccountSecretAvailable(GinkgoT(), kubeclient, sa.GetNamespace(), sa.GetName())
By("Wait for ServiceAccount secret to be available")
Eventually(func() (*corev1.ServiceAccount, error) {
sa, err := kubeclient.KubernetesInterface().CoreV1().ServiceAccounts(sa.GetNamespace()).Get(context.TODO(), sa.GetName(), metav1.GetOptions{})
return sa, err
}).ShouldNot(WithTransform(func(v *corev1.ServiceAccount) []corev1.ObjectReference {
return v.Secrets
}, BeEmpty()))

strategy := scoped.NewClientAttenuator(logger, config, kubeclient, crclient, dynamicclient)
getter := func() (reference *corev1.ObjectReference, err error) {
reference = &corev1.ObjectReference{
Namespace: namespace,
Name: saName,
}

return
}

if tt.grant != nil {
cleanupPerm := tt.grant(sa.GetNamespace(), sa.GetName())
if tc.grant != nil {
cleanupPerm := tc.grant(sa.GetNamespace(), sa.GetName())
defer cleanupPerm()
}

// We expect to get scoped client instance(s).
By("Get scoped client instance(s)")
kubeclientGot, crclientGot, dynamicClientGot, errGot := strategy.AttenuateClient(getter)
require.NoError(GinkgoT(), errGot)
require.NotNil(GinkgoT(), kubeclientGot)
require.NotNil(GinkgoT(), crclientGot)
Expect(errGot).ToNot(HaveOccurred())
Expect(kubeclientGot).ToNot(BeNil())
Expect(crclientGot).ToNot(BeNil())
Expect(dynamicClientGot).ToNot(BeNil())

_, errGot = kubeclientGot.KubernetesInterface().CoreV1().ConfigMaps(namespace).Get(context.TODO(), genName("does-not-exist-"), metav1.GetOptions{})
require.Error(GinkgoT(), errGot)
tt.assertFunc(errGot)
Expect(errGot).To(HaveOccurred())
tc.assertFunc(errGot)

_, errGot = crclientGot.OperatorsV1alpha1().CatalogSources(namespace).Get(context.TODO(), genName("does-not-exist-"), metav1.GetOptions{})
require.Error(GinkgoT(), errGot)
tt.assertFunc(errGot)
Expect(errGot).To(HaveOccurred())
tc.assertFunc(errGot)

gvr := schema.GroupVersionResource{Group: "", Version: "v1", Resource: "ConfigMap"}
_, errGot = dynamicClientGot.Resource(gvr).Namespace(namespace).Get(context.TODO(), genName("does-not-exist-"), metav1.GetOptions{})
require.Error(GinkgoT(), errGot)
tt.assertFunc(errGot)
Expect(errGot).To(HaveOccurred())
tc.assertFunc(errGot)
}, tableEntries...)
})

func waitForServiceAccountSecretAvailable(t GinkgoTInterface, client operatorclient.ClientInterface, namespace, name string) *corev1.ServiceAccount {
var sa *corev1.ServiceAccount
err := wait.Poll(5*time.Second, time.Minute, func() (bool, error) {
sa, err := client.KubernetesInterface().CoreV1().ServiceAccounts(namespace).Get(context.TODO(), name, metav1.GetOptions{})
if err != nil {
return false, err
}

if len(sa.Secrets) > 0 {
return true, nil
}

return false, nil

})

require.NoError(t, err)
return sa
}
28 changes: 14 additions & 14 deletions test/e2e/user_defined_sa_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ var _ = Describe("User defined service account", func() {

// Create a service account, but add no permission to it.
saName := genName("scoped-sa-")
_, cleanupSA := newServiceAccount(GinkgoT(), kubeclient, namespace, saName)
_, cleanupSA := newServiceAccount(kubeclient, namespace, saName)
defer cleanupSA()

// Add an OperatorGroup and specify the service account.
ogName := genName("scoped-og-")
_, cleanupOG := newOperatorGroupWithServiceAccount(GinkgoT(), crclient, namespace, ogName, saName)
_, cleanupOG := newOperatorGroupWithServiceAccount(crclient, namespace, ogName, saName)
defer cleanupOG()

permissions := deploymentPermissions()
Expand Down Expand Up @@ -91,14 +91,14 @@ var _ = Describe("User defined service account", func() {

// Create a service account, add enough permission to it so that operator install is successful.
saName := genName("scoped-sa")
_, cleanupSA := newServiceAccount(GinkgoT(), kubeclient, namespace, saName)
_, cleanupSA := newServiceAccount(kubeclient, namespace, saName)
defer cleanupSA()
cleanupPerm := grantPermission(GinkgoT(), kubeclient, namespace, saName)
defer cleanupPerm()

// Add an OperatorGroup and specify the service account.
ogName := genName("scoped-og-")
_, cleanupOG := newOperatorGroupWithServiceAccount(GinkgoT(), crclient, namespace, ogName, saName)
_, cleanupOG := newOperatorGroupWithServiceAccount(crclient, namespace, ogName, saName)
defer cleanupOG()

permissions := deploymentPermissions()
Expand Down Expand Up @@ -147,12 +147,12 @@ var _ = Describe("User defined service account", func() {

// Create a service account, but add no permission to it.
saName := genName("scoped-sa-")
_, cleanupSA := newServiceAccount(GinkgoT(), kubeclient, namespace, saName)
_, cleanupSA := newServiceAccount(kubeclient, namespace, saName)
defer cleanupSA()

// Add an OperatorGroup and specify the service account.
ogName := genName("scoped-og-")
_, cleanupOG := newOperatorGroupWithServiceAccount(GinkgoT(), crclient, namespace, ogName, saName)
_, cleanupOG := newOperatorGroupWithServiceAccount(crclient, namespace, ogName, saName)
defer cleanupOG()

permissions := deploymentPermissions()
Expand Down Expand Up @@ -216,7 +216,7 @@ func newNamespace(client operatorclient.ClientInterface, name string) (ns *corev
return
}

func newServiceAccount(t GinkgoTInterface, client operatorclient.ClientInterface, namespace, name string) (sa *corev1.ServiceAccount, cleanup cleanupFunc) {
func newServiceAccount(client operatorclient.ClientInterface, namespace, name string) (sa *corev1.ServiceAccount, cleanup cleanupFunc) {
request := &corev1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
Namespace: namespace,
Expand All @@ -225,18 +225,18 @@ func newServiceAccount(t GinkgoTInterface, client operatorclient.ClientInterface
}

sa, err := client.KubernetesInterface().CoreV1().ServiceAccounts(namespace).Create(context.TODO(), request, metav1.CreateOptions{})
require.NoError(t, err)
require.NotNil(t, sa)
Expect(err).ToNot(HaveOccurred())
Expect(sa).ToNot(BeNil())

cleanup = func() {
err := client.KubernetesInterface().CoreV1().ServiceAccounts(sa.GetNamespace()).Delete(context.TODO(), sa.GetName(), metav1.DeleteOptions{})
require.NoError(t, err)
Expect(err).ToNot(HaveOccurred())
}

return
}

func newOperatorGroupWithServiceAccount(t GinkgoTInterface, client versioned.Interface, namespace, name, serviceAccountName string) (og *v1.OperatorGroup, cleanup cleanupFunc) {
func newOperatorGroupWithServiceAccount(client versioned.Interface, namespace, name, serviceAccountName string) (og *v1.OperatorGroup, cleanup cleanupFunc) {
request := &v1.OperatorGroup{
ObjectMeta: metav1.ObjectMeta{
Namespace: namespace,
Expand All @@ -251,12 +251,12 @@ func newOperatorGroupWithServiceAccount(t GinkgoTInterface, client versioned.Int
}

og, err := client.OperatorsV1().OperatorGroups(namespace).Create(context.TODO(), request, metav1.CreateOptions{})
require.NoError(t, err)
require.NotNil(t, og)
Expect(err).ToNot(HaveOccurred())
Expect(og).ToNot(BeNil())

cleanup = func() {
err := client.OperatorsV1().OperatorGroups(og.GetNamespace()).Delete(context.TODO(), og.GetName(), metav1.DeleteOptions{})
require.NoError(t, err)
Expect(err).ToNot(HaveOccurred())
}

return
Expand Down

0 comments on commit 684ef55

Please sign in to comment.