diff --git a/go.mod b/go.mod index 27b0eaa72..662d229c7 100644 --- a/go.mod +++ b/go.mod @@ -121,3 +121,7 @@ require ( ) go 1.20 + +replace github.com/codeready-toolchain/toolchain-common => github.com/filariow/toolchain-common v0.0.0-20240322165115-87027670d9b3 + +replace github.com/codeready-toolchain/api => github.com/filariow/toolchain-api v0.0.0-20240322163859-f974f2dbbc8e diff --git a/go.sum b/go.sum index 4b5ea205e..ee132c74e 100644 --- a/go.sum +++ b/go.sum @@ -123,10 +123,6 @@ github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:z github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/codeready-toolchain/api v0.0.0-20240322110702-5ab3840476e9 h1:Lm7bFLrzfJzrUiRGVqtsSaZMpj+akLiR/fvAFjjE9gM= -github.com/codeready-toolchain/api v0.0.0-20240322110702-5ab3840476e9/go.mod h1:cfNN6YPX4TORvhhZXMSjSPesqAHlB3nD/WAfGe4WLKQ= -github.com/codeready-toolchain/toolchain-common v0.0.0-20240322131000-8d44f7428e83 h1:j+3snE8RGTyB5MdwPUqIfmAm9C2aScCni+ma1EveC4c= -github.com/codeready-toolchain/toolchain-common v0.0.0-20240322131000-8d44f7428e83/go.mod h1:OJ3L9aaTRMGjxr2WeH/9l6m5OjExwEK3Bp/+P+efoGg= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -184,6 +180,10 @@ github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/filariow/toolchain-api v0.0.0-20240322163859-f974f2dbbc8e h1:h+uO6jYovPD3j9VIo9JajpmTZIyl7x6wSap/4RjS6aw= +github.com/filariow/toolchain-api v0.0.0-20240322163859-f974f2dbbc8e/go.mod h1:cfNN6YPX4TORvhhZXMSjSPesqAHlB3nD/WAfGe4WLKQ= +github.com/filariow/toolchain-common v0.0.0-20240322165115-87027670d9b3 h1:k1kjVkS1CUazxpA8Hu0X6M4ChubNhGmHSQUEUhfGo4I= +github.com/filariow/toolchain-common v0.0.0-20240322165115-87027670d9b3/go.mod h1:2vTPf4wRr6Q9Pq3zkJ5I3wBNagXEMvyjmdk8w0/UJRE= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= diff --git a/make/test.mk b/make/test.mk index b59ea3575..06fcdd56b 100644 --- a/make/test.mk +++ b/make/test.mk @@ -38,6 +38,14 @@ E2E_PARALLELISM=1 TESTS_RUN_FILTER_REGEXP ?= "" +.PHONY: test-e2e-community +test-e2e-community: prepare-e2e deploy-e2e e2e-run-community + @: + +.PHONY: test-e2e-community-local +test-e2e-community-local: prepare-e2e deploy-e2e-local e2e-run-community + @: + .PHONY: test-e2e ## Run the e2e tests test-e2e: INSTALL_OPERATOR=true @@ -116,15 +124,33 @@ test-e2e-registration-local: .PHONY: e2e-run-parallel e2e-run-parallel: @echo "Running e2e tests in parallel..." + oc patch -n ${HOST_NS} toolchainconfigs.toolchain.dev.openshift.com config --patch='{"spec":{"global":{"publicViewer":{"enabled":false}}}}' --type=merge + oc delete -n ${HOST_NS} pods -l control-plane=controller-manager + oc delete -n ${HOST_NS} pod -l name=registration-service + oc rollout -n ${HOST_NS} status deployment $(MAKE) execute-tests MEMBER_NS=${MEMBER_NS} MEMBER_NS_2=${MEMBER_NS_2} HOST_NS=${HOST_NS} REGISTRATION_SERVICE_NS=${REGISTRATION_SERVICE_NS} TESTS_TO_EXECUTE="./test/e2e/parallel" E2E_PARALLELISM=100 @echo "The parallel e2e tests successfully finished" .PHONY: e2e-run e2e-run: @echo "Running e2e tests..." + oc patch -n ${HOST_NS} toolchainconfigs.toolchain.dev.openshift.com config --patch='{"spec":{"global":{"publicViewer":{"enabled":false}}}}' --type=merge + oc delete -n ${HOST_NS} pods -l control-plane=controller-manager + oc delete -n ${HOST_NS} pod -l name=registration-service + oc rollout -n ${HOST_NS} status deployment $(MAKE) execute-tests MEMBER_NS=${MEMBER_NS} MEMBER_NS_2=${MEMBER_NS_2} HOST_NS=${HOST_NS} REGISTRATION_SERVICE_NS=${REGISTRATION_SERVICE_NS} TESTS_TO_EXECUTE="./test/e2e ./test/metrics" @echo "The e2e tests successfully finished" +.PHONY: e2e-run-community +e2e-run-community: + @echo "Running e2e community tests..." + oc patch -n ${HOST_NS} toolchainconfigs.toolchain.dev.openshift.com config --patch='{"spec":{"global":{"publicViewer":{"enabled":true,"username":"public-viewer"}}}}' --type=merge + oc delete -n ${HOST_NS} pods -l control-plane=controller-manager + oc delete -n ${HOST_NS} pod -l name=registration-service + oc rollout -n ${HOST_NS} status deployment + $(MAKE) execute-tests MEMBER_NS=${MEMBER_NS} MEMBER_NS_2=${MEMBER_NS_2} HOST_NS=${HOST_NS} REGISTRATION_SERVICE_NS=${REGISTRATION_SERVICE_NS} TESTS_TO_EXECUTE="./test/e2e/community" + @echo "The e2e community tests successfully finished" + .PHONY: execute-tests execute-tests: @echo "Present Spaces" diff --git a/test/e2e/community/proxy_test.go b/test/e2e/community/proxy_test.go new file mode 100644 index 000000000..7e7709f0d --- /dev/null +++ b/test/e2e/community/proxy_test.go @@ -0,0 +1,191 @@ +package community_test + +import ( + "context" + "testing" + + "github.com/gofrs/uuid" + "github.com/stretchr/testify/require" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/selection" + waitpoll "k8s.io/apimachinery/pkg/util/wait" + "sigs.k8s.io/controller-runtime/pkg/client" + + toolchainv1alpha1 "github.com/codeready-toolchain/api/api/v1alpha1" + commonauth "github.com/codeready-toolchain/toolchain-common/pkg/test/auth" + . "github.com/codeready-toolchain/toolchain-e2e/testsupport" + authsupport "github.com/codeready-toolchain/toolchain-e2e/testsupport/auth" + "github.com/codeready-toolchain/toolchain-e2e/testsupport/spacebinding" + "github.com/codeready-toolchain/toolchain-e2e/testsupport/tiers" + "github.com/codeready-toolchain/toolchain-e2e/testsupport/wait" +) + +type proxyUser struct { + expectedMemberCluster *wait.MemberAwaitility + username string + token string + identityID uuid.UUID + signup *toolchainv1alpha1.UserSignup + compliantUsername string +} + +// tests access to community-shared spaces +func TestPublicViewerProxy(t *testing.T) { + // given + + // make sure everything is ready before running the actual tests + awaitilities := WaitForDeployments(t) + hostAwait := awaitilities.Host() + memberAwait := awaitilities.Member1() + // we create a space to share , a new MUR and a SpaceBindingRequest + space, _, _ := NewSpaceBindingRequest(t, awaitilities, memberAwait, hostAwait, "admin") + + communityUser := &proxyUser{ + expectedMemberCluster: memberAwait, + username: "community-user", + identityID: uuid.Must(uuid.NewV4()), + } + createAppStudioUser(t, awaitilities, communityUser) + + communityUserProxyClient, err := hostAwait.CreateAPIProxyClient(t, communityUser.token, hostAwait.APIProxyURL) + require.NoError(t, err) + + t.Run("space is flagged as community", func(t *testing.T) { + // when + sb := CreateCommunitySpaceBinding(t, hostAwait, space.Name, space.Namespace) + require.NoError(t, err) + t.Logf("created space binding for public-viewer:\n%+v", sb) + + // Wait until space is flagged as community + require.NoError(t, + waitpoll.Poll(hostAwait.RetryInterval, hostAwait.Timeout, func() (bool, error) { + mr, err := labels.NewRequirement(toolchainv1alpha1.SpaceBindingMasterUserRecordLabelKey, selection.In, []string{"public-viewer"}) + if err != nil { + return false, err + } + + sr, err := labels.NewRequirement(toolchainv1alpha1.SpaceBindingSpaceLabelKey, selection.Equals, []string{space.Name}) + if err != nil { + return false, err + } + + opts := &client.ListOptions{ + Namespace: space.Namespace, + LabelSelector: labels.NewSelector().Add(*sr, *mr), + } + sbs := &toolchainv1alpha1.SpaceBindingList{} + if err := hostAwait.Client.List(context.TODO(), sbs, opts); err != nil { + return false, err + } + + return len(sbs.Items) == 1, nil + })) + + sp := toolchainv1alpha1.Space{} + err = hostAwait.Client.Get(context.TODO(), client.ObjectKeyFromObject(space), &sp) + require.NoError(t, err) + + /* + Given Space exists for user A + Given User community-user exists + When A flags their space visibility to "community" + Then community-user can view A's Space + And community-user cannot create resources in A's Space + */ + t.Run("community user access to community space", func(t *testing.T) { + require.NotEmpty(t, sp.Status.ProvisionedNamespaces) + + t.Run("community user can list config maps from community space", func(t *testing.T) { + // then + cms := corev1.ConfigMapList{} + + communityUserProxyClient, err := hostAwait.CreateAPIProxyClient(t, communityUser.token, hostAwait.ProxyURLWithWorkspaceContext(sp.Name)) + require.NoError(t, err) + + err = communityUserProxyClient.List(context.TODO(), &cms, client.InNamespace(sp.Status.ProvisionedNamespaces[0].Name)) + require.NoError(t, err) + }) + + t.Run("community user cannot create config maps into space", func(t *testing.T) { + cm := corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cm", + Namespace: sp.Status.ProvisionedNamespaces[0].Name, + }, + } + err := communityUserProxyClient.Create(context.TODO(), &cm) + require.Error(t, err) + }) + }) + + /* + Given Space exists for user A + Given SSO user joe exists + When A flags their space visibility to "community" + Then joe can view A's Space + And joe cannot create resources in A's Space + */ + t.Run("as sso user", func(t *testing.T) { + // Given + userIdentity := &commonauth.Identity{ + ID: uuid.Must(uuid.NewV4()), + Username: "joe", + } + claims := []commonauth.ExtraClaim{commonauth.WithEmailClaim("joe@joe.joe")} + token, err := authsupport.NewTokenFromIdentity(userIdentity, claims...) + require.NoError(t, err) + + joeCli, err := hostAwait.CreateAPIProxyClient(t, token, hostAwait.ProxyURLWithWorkspaceContext(sp.Name)) + require.NoError(t, err) + + t.Run("sso user can list config maps from space", func(t *testing.T) { + // then + cms := corev1.ConfigMapList{} + err := joeCli.List(context.TODO(), &cms, client.InNamespace(sp.Status.ProvisionedNamespaces[0].Name)) + require.NoError(t, err) + }) + + t.Run("sso user cannot create config maps into space", func(t *testing.T) { + // then + cm := corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cm", + Namespace: sp.Status.ProvisionedNamespaces[0].Name, + }, + } + err := joeCli.Create(context.TODO(), &cm) + require.Error(t, err) + }) + }) + }) +} + +func createAppStudioUser(t *testing.T, awaitilities wait.Awaitilities, user *proxyUser) { + // Create and approve signup + req := NewSignupRequest(awaitilities). + Username(user.username). + IdentityID(user.identityID). + ManuallyApprove(). + TargetCluster(user.expectedMemberCluster). + EnsureMUR(). + RequireConditions(wait.ConditionSet(wait.Default(), wait.ApprovedByAdmin())...). + Execute(t) + user.signup, _ = req.Resources() + user.token = req.GetToken() + tiers.MoveSpaceToTier(t, awaitilities.Host(), user.signup.Status.CompliantUsername, "appstudio") + VerifyResourcesProvisionedForSignup(t, awaitilities, user.signup, "deactivate30", "appstudio") + user.compliantUsername = user.signup.Status.CompliantUsername + _, err := awaitilities.Host().WaitForMasterUserRecord(t, user.compliantUsername, wait.UntilMasterUserRecordHasCondition(wait.Provisioned())) + require.NoError(t, err) +} + +func CreateCommunitySpaceBinding( + t *testing.T, + hostAwait *wait.HostAwaitility, + spaceName, spaceNamespace string, +) *toolchainv1alpha1.SpaceBinding { + return spacebinding.CreateSpaceBindingStr(t, hostAwait, "public-viewer", spaceName, spaceNamespace, "contributor") +} diff --git a/test/e2e/community/spacebindingrequest_test.go b/test/e2e/community/spacebindingrequest_test.go new file mode 100644 index 000000000..981d2bc19 --- /dev/null +++ b/test/e2e/community/spacebindingrequest_test.go @@ -0,0 +1,88 @@ +package community_test + +import ( + "sort" + "testing" + + "github.com/gofrs/uuid" + "github.com/stretchr/testify/require" + + "k8s.io/apimachinery/pkg/types" + + toolchainv1alpha1 "github.com/codeready-toolchain/api/api/v1alpha1" + + testspace "github.com/codeready-toolchain/toolchain-common/pkg/test/space" + spacebindingrequesttestcommon "github.com/codeready-toolchain/toolchain-common/pkg/test/spacebindingrequest" + . "github.com/codeready-toolchain/toolchain-e2e/testsupport" + testsupportspace "github.com/codeready-toolchain/toolchain-e2e/testsupport/space" + "github.com/codeready-toolchain/toolchain-e2e/testsupport/spacebinding" + "github.com/codeready-toolchain/toolchain-e2e/testsupport/wait" +) + +func NewSpaceBindingRequest( + t *testing.T, + awaitilities wait.Awaitilities, + memberAwait *wait.MemberAwaitility, + hostAwait *wait.HostAwaitility, + spaceRole string, +) ( + *toolchainv1alpha1.Space, + *toolchainv1alpha1.SpaceBindingRequest, + *toolchainv1alpha1.SpaceBinding, +) { + space, firstUserSignup, _ := testsupportspace.CreateSpace(t, awaitilities, testspace.WithTierName("appstudio"), testspace.WithSpecTargetCluster(memberAwait.ClusterName)) + // wait for the namespace to be provisioned since we will be creating the SpaceBindingRequest into it. + space, err := hostAwait.WaitForSpace(t, space.Name, wait.UntilSpaceHasAnyProvisionedNamespaces()) + require.NoError(t, err) + // let's create a new MUR that will have access to the space + username := uuid.Must(uuid.NewV4()).String() + _, secondUserMUR := NewSignupRequest(awaitilities). + Username(username). + Email(username + "@acme.com"). + ManuallyApprove(). + TargetCluster(memberAwait). + RequireConditions(wait.ConditionSet(wait.Default(), wait.ApprovedByAdmin())...). + NoSpace(). + WaitForMUR().Execute(t).Resources() + // create the spacebinding request + spaceBindingRequest := spacebinding.CreateSpaceBindingRequest(t, awaitilities, memberAwait.ClusterName, + spacebinding.WithSpecSpaceRole(spaceRole), + + spacebinding.WithSpecMasterUserRecord(secondUserMUR.GetName()), + spacebinding.WithNamespace(testsupportspace.GetDefaultNamespace(space.Status.ProvisionedNamespaces)), + ) + + // then + // check for the spaceBinding creation + spaceBinding, err := hostAwait.WaitForSpaceBinding(t, spaceBindingRequest.Spec.MasterUserRecord, space.Name, + wait.UntilSpaceBindingHasMurName(spaceBindingRequest.Spec.MasterUserRecord), + wait.UntilSpaceBindingHasSpaceName(space.Name), + wait.UntilSpaceBindingHasSpaceRole(spaceBindingRequest.Spec.SpaceRole), + wait.UntilSpaceBindingHasLabel(toolchainv1alpha1.SpaceBindingRequestLabelKey, spaceBindingRequest.GetName()), + wait.UntilSpaceBindingHasLabel(toolchainv1alpha1.SpaceBindingRequestNamespaceLabelKey, spaceBindingRequest.GetNamespace()), + ) + require.NoError(t, err) + // wait for spacebinding request status + spaceBindingRequest, err = memberAwait.WaitForSpaceBindingRequest(t, types.NamespacedName{Namespace: spaceBindingRequest.GetNamespace(), Name: spaceBindingRequest.GetName()}, + wait.UntilSpaceBindingRequestHasConditions(spacebindingrequesttestcommon.Ready()), + ) + require.NoError(t, err) + tier, err := awaitilities.Host().WaitForNSTemplateTier(t, space.Spec.TierName) + require.NoError(t, err) + if spaceRole == "admin" { + usernamesSorted := []string{firstUserSignup.Status.CompliantUsername, secondUserMUR.Name} + sort.Strings(usernamesSorted) + _, err = memberAwait.WaitForNSTmplSet(t, space.Name, + wait.UntilNSTemplateSetHasSpaceRoles( + wait.SpaceRole(tier.Spec.SpaceRoles[spaceRole].TemplateRef, usernamesSorted[0], usernamesSorted[1]))) + require.NoError(t, err) + } else { + _, err = memberAwait.WaitForNSTmplSet(t, space.Name, + wait.UntilNSTemplateSetHasSpaceRoles( + wait.SpaceRole(tier.Spec.SpaceRoles["admin"].TemplateRef, firstUserSignup.Status.CompliantUsername), + wait.SpaceRole(tier.Spec.SpaceRoles[spaceRole].TemplateRef, secondUserMUR.Name))) + require.NoError(t, err) + } + testsupportspace.VerifyResourcesProvisionedForSpace(t, awaitilities, space.Name) + return space, spaceBindingRequest, spaceBinding +} diff --git a/test/e2e/parallel/proxy_test.go b/test/e2e/parallel/proxy_test.go index 3ebe2d0dd..36b512903 100644 --- a/test/e2e/parallel/proxy_test.go +++ b/test/e2e/parallel/proxy_test.go @@ -20,7 +20,6 @@ import ( toolchainv1alpha1 "github.com/codeready-toolchain/api/api/v1alpha1" commonproxy "github.com/codeready-toolchain/toolchain-common/pkg/proxy" testspace "github.com/codeready-toolchain/toolchain-common/pkg/test/space" - spacebindingrequesttestcommon "github.com/codeready-toolchain/toolchain-common/pkg/test/spacebindingrequest" . "github.com/codeready-toolchain/toolchain-e2e/testsupport" appstudiov1 "github.com/codeready-toolchain/toolchain-e2e/testsupport/appstudio/api/v1alpha1" testsupportspace "github.com/codeready-toolchain/toolchain-e2e/testsupport/space" @@ -69,25 +68,7 @@ func (u *proxyUser) shareSpaceWith(t *testing.T, awaitilities wait.Awaitilities, ) _, err = awaitilities.Host().WaitForSpaceBinding(t, guestUserMur.GetName(), primaryUserSpace.GetName()) require.NoError(t, err) - return spaceBindingRequest -} -func (u *proxyUser) invalidShareSpaceWith(t *testing.T, awaitilities wait.Awaitilities, guestUser *proxyUser) *toolchainv1alpha1.SpaceBindingRequest { - // share primaryUser space with guestUser - guestUserMur, err := awaitilities.Host().GetMasterUserRecord(guestUser.compliantUsername) - require.NoError(t, err) - primaryUserSpace, err := awaitilities.Host().WaitForSpace(t, u.compliantUsername, wait.UntilSpaceHasAnyTargetClusterSet(), wait.UntilSpaceHasAnyTierNameSet(), wait.UntilSpaceHasAnyProvisionedNamespaces()) - require.NoError(t, err) - spaceBindingRequest := CreateSpaceBindingRequest(t, awaitilities, primaryUserSpace.Spec.TargetCluster, - WithSpecSpaceRole("invalidRole"), - WithSpecMasterUserRecord(guestUserMur.GetName()), - WithNamespace(testsupportspace.GetDefaultNamespace(primaryUserSpace.Status.ProvisionedNamespaces)), - ) - // wait for spacebinding request status to be set - _, err = awaitilities.Member1().WaitForSpaceBindingRequest(t, types.NamespacedName{Namespace: spaceBindingRequest.GetNamespace(), Name: spaceBindingRequest.GetName()}, - wait.UntilSpaceBindingRequestHasConditions(spacebindingrequesttestcommon.UnableToCreateSpaceBinding(fmt.Sprintf("invalid role 'invalidRole' for space '%s'", primaryUserSpace.Name))), - ) - require.NoError(t, err) return spaceBindingRequest } @@ -481,6 +462,7 @@ func TestProxyFlow(t *testing.T) { assert.Contains(t, string(r), fmt.Sprintf(`nodes is forbidden: User \"%s\" cannot list resource \"nodes\" in API group \"\" at the cluster scope`, user.compliantUsername)) }) } + }) // end of invalid request headers }) } // end users loop @@ -577,7 +559,9 @@ func TestProxyFlow(t *testing.T) { require.EqualError(t, err, fmt.Sprintf(`invalid workspace request: access to namespace '%s' in workspace '%s' is forbidden (get applications.appstudio.redhat.com %s)`, primaryUserNamespace, workspaceName, applicationName)) }) }) + }) + } // this test will: @@ -641,7 +625,7 @@ func runWatcher(t *testing.T, awaitilities wait.Awaitilities) *sync.WaitGroup { Get() t.Logf("stopping the watch after %s", time.Since(started)) - require.EqualError(t, err, "unexpected error when reading response body. Please retry. Original error: context deadline exceeded", "The call should be terminated by the context timeout") + assert.EqualError(t, err, "unexpected error when reading response body. Please retry. Original error: context deadline exceeded", "The call should be terminated by the context timeout") assert.NotContains(t, err.Error(), "unexpected EOF", "If it contains 'unexpected EOF' then the call was terminated on the server side, which is not expected.") }) }() @@ -685,8 +669,6 @@ func TestSpaceLister(t *testing.T) { busSBROnCarSpace := users["car"].shareSpaceWith(t, awaitilities, users["bus"]) bicycleSBROnCarSpace := users["car"].shareSpaceWith(t, awaitilities, users["bicycle"]) bicycleSBROnBusSpace := users["bus"].shareSpaceWith(t, awaitilities, users["bicycle"]) - // let's also create a failing SBR so that we can check if it's being added in the bindings list - failingSBR := users["bus"].invalidShareSpaceWith(t, awaitilities, users["car"]) t.Run("car lists workspaces", func(t *testing.T) { // when @@ -800,17 +782,10 @@ func TestSpaceLister(t *testing.T) { verifyHasExpectedWorkspace(t, expectedWorkspaceFor(t, awaitilities.Host(), "bus", commonproxy.WithType("home"), appStudioTierRolesWSOption, commonproxy.WithBindings([]toolchainv1alpha1.Binding{ {MasterUserRecord: "bus", Role: "admin", AvailableActions: []string(nil)}, // this is system generated so no actions for the user - // the failing SBR should be present in the list of bindings, so that the user can manage it - {MasterUserRecord: "car", Role: "invalidRole", AvailableActions: []string{"update", "delete"}, BindingRequest: &toolchainv1alpha1.BindingRequest{ - Name: failingSBR.GetName(), - Namespace: failingSBR.GetNamespace(), - }}, {MasterUserRecord: "road-bicycle", Role: "admin", AvailableActions: []string{"update", "delete"}, BindingRequest: &toolchainv1alpha1.BindingRequest{ Name: bicycleSBROnBusSpace.GetName(), Namespace: bicycleSBROnBusSpace.GetNamespace(), - }}, - })), - + }}})), *busWS) }) @@ -858,10 +833,6 @@ func TestSpaceLister(t *testing.T) { verifyHasExpectedWorkspace(t, expectedWorkspaceFor(t, awaitilities.Host(), "bus", appStudioTierRolesWSOption, commonproxy.WithBindings([]toolchainv1alpha1.Binding{ {MasterUserRecord: "bus", Role: "admin", AvailableActions: []string(nil)}, // this is system generated so no actions for the user - {MasterUserRecord: "car", Role: "invalidRole", AvailableActions: []string{"update", "delete"}, BindingRequest: &toolchainv1alpha1.BindingRequest{ - Name: failingSBR.GetName(), - Namespace: failingSBR.GetNamespace(), - }}, {MasterUserRecord: "road-bicycle", Role: "admin", AvailableActions: []string{"update", "delete"}, BindingRequest: &toolchainv1alpha1.BindingRequest{ Name: bicycleSBROnBusSpace.GetName(), Namespace: bicycleSBROnBusSpace.GetNamespace(), @@ -886,7 +857,7 @@ func TestSpaceLister(t *testing.T) { {MasterUserRecord: "road-bicycle", Role: "admin", AvailableActions: []string{"update", "delete"}, BindingRequest: &toolchainv1alpha1.BindingRequest{ Name: bicycleSBROnCarSpace.GetName(), Namespace: bicycleSBROnCarSpace.GetNamespace(), - }}}, + }}}, // this is system generated so no actions for the user ), ), *carWS) }) diff --git a/test/e2e/parallel/spacebindingrequest_test.go b/test/e2e/parallel/spacebindingrequest_test.go index 64397fde6..7714b01ad 100644 --- a/test/e2e/parallel/spacebindingrequest_test.go +++ b/test/e2e/parallel/spacebindingrequest_test.go @@ -36,7 +36,7 @@ func TestCreateSpaceBindingRequest(t *testing.T) { // we create a space to share , a new MUR and a SpaceBindingRequest space, spaceBindingRequest, spaceBinding := NewSpaceBindingRequest(t, awaitilities, memberAwait, hostAwait, "admin") - t.Run("spaceBinding is recreated if deleted", func(t *testing.T) { + t.Run("spaceBinding is recreated if deleted ", func(t *testing.T) { // now, delete the SpaceBinding, // a new SpaceBinding will be provisioned by the SpaceBindingRequest. // @@ -60,7 +60,7 @@ func TestCreateSpaceBindingRequest(t *testing.T) { ) require.NoError(t, err) - t.Run("SpaceBinding always reflects values from spaceBindingRequest", func(t *testing.T) { + t.Run("SpaceBinding always reflects values from spaceBindingRequest ", func(t *testing.T) { // given // something/someone updates the SpaceRole directly on the SpaceBinding object @@ -122,6 +122,7 @@ func TestCreateSpaceBindingRequest(t *testing.T) { ) // then + require.NoError(t, err) // wait for spacebinding request status to be set _, err = memberAwait.WaitForSpaceBindingRequest(t, types.NamespacedName{Namespace: spaceBindingRequest.GetNamespace(), Name: spaceBindingRequest.GetName()}, UntilSpaceBindingRequestHasConditions(spacebindingrequesttestcommon.UnableToCreateSpaceBinding(fmt.Sprintf("invalid role 'invalid' for space '%s'", space.Name))), @@ -145,6 +146,7 @@ func TestCreateSpaceBindingRequest(t *testing.T) { ) // then + require.NoError(t, err) // wait for spacebinding request status to be set _, err = memberAwait.WaitForSpaceBindingRequest(t, types.NamespacedName{Namespace: spaceBindingRequest.GetNamespace(), Name: spaceBindingRequest.GetName()}, UntilSpaceBindingRequestHasConditions(spacebindingrequesttestcommon.UnableToCreateSpaceBinding("unable to get MUR: MasterUserRecord.toolchain.dev.openshift.com \"invalidMUR\" not found")), diff --git a/testsupport/spacebinding/spacebinding.go b/testsupport/spacebinding/spacebinding.go index 856c36d88..24bb3ad46 100644 --- a/testsupport/spacebinding/spacebinding.go +++ b/testsupport/spacebinding/spacebinding.go @@ -30,6 +30,13 @@ func CreateSpaceBinding(t *testing.T, hostAwait *wait.HostAwaitility, mur *toolc return spaceBinding } +func CreateSpaceBindingStr(t *testing.T, hostAwait *wait.HostAwaitility, murName, spaceName, spaceNamespace, spaceRole string) *toolchainv1alpha1.SpaceBinding { + spaceBinding := NewSpaceBindingStr(murName, spaceName, spaceNamespace, spaceRole) + err := hostAwait.CreateWithCleanup(t, spaceBinding) + require.NoError(t, err) + return spaceBinding +} + // CreateSpaceBindingWithoutCleanup creates SpaceBinding resource for the given MUR & Space with the given space role; and doesn't mark the resource to be ready for cleanup func CreateSpaceBindingWithoutCleanup(t *testing.T, hostAwait *wait.HostAwaitility, mur *toolchainv1alpha1.MasterUserRecord, space *toolchainv1alpha1.Space, spaceRole string) *toolchainv1alpha1.SpaceBinding { spaceBinding := NewSpaceBinding(mur, space, spaceRole) @@ -61,3 +68,25 @@ func NewSpaceBinding(mur *toolchainv1alpha1.MasterUserRecord, space *toolchainv1 }, } } + +func NewSpaceBindingStr(murName, spaceName, spaceNamespace, spaceRole string) *toolchainv1alpha1.SpaceBinding { + namePrefix := fmt.Sprintf("%s-%s", murName, spaceName) + if len(namePrefix) > 50 { + namePrefix = namePrefix[0:50] + } + return &toolchainv1alpha1.SpaceBinding{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: namePrefix + "-", + Namespace: spaceNamespace, + Labels: map[string]string{ + toolchainv1alpha1.SpaceBindingMasterUserRecordLabelKey: murName, + toolchainv1alpha1.SpaceBindingSpaceLabelKey: spaceName, + }, + }, + Spec: toolchainv1alpha1.SpaceBindingSpec{ + MasterUserRecord: murName, + Space: spaceName, + SpaceRole: spaceRole, + }, + } +} diff --git a/testsupport/spacebinding/spacebindingrequest.go b/testsupport/spacebinding/spacebindingrequest.go index f18793b8d..5c2afce53 100644 --- a/testsupport/spacebinding/spacebindingrequest.go +++ b/testsupport/spacebinding/spacebindingrequest.go @@ -34,6 +34,11 @@ func WithNamespace(ns string) SpaceBindingRequestOption { func CreateSpaceBindingRequest(t *testing.T, awaitilities wait.Awaitilities, memberName string, opts ...SpaceBindingRequestOption) *toolchainv1alpha1.SpaceBindingRequest { memberAwait, err := awaitilities.Member(memberName) require.NoError(t, err) + + return CreateSpaceBindingRequestOnMember(t, memberAwait, opts...) +} + +func CreateSpaceBindingRequestOnMember(t *testing.T, memberAwait *wait.MemberAwaitility, opts ...SpaceBindingRequestOption) *toolchainv1alpha1.SpaceBindingRequest { namePrefix := util.NewObjectNamePrefix(t) spaceBindingRequest := &toolchainv1alpha1.SpaceBindingRequest{ @@ -44,7 +49,7 @@ func CreateSpaceBindingRequest(t *testing.T, awaitilities wait.Awaitilities, mem for _, apply := range opts { apply(spaceBindingRequest) } - err = memberAwait.CreateWithCleanup(t, spaceBindingRequest) + err := memberAwait.CreateWithCleanup(t, spaceBindingRequest) require.NoError(t, err) return spaceBindingRequest