Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement public API that will open SpaceBindings to end users through proxy part 2 #350

Merged
merged 33 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
49aa7e7
add available roles to workspace api
mfrancisc Sep 20, 2023
9e08ece
replace toolchain-common
mfrancisc Sep 20, 2023
b6a4d8f
update common
mfrancisc Sep 20, 2023
44eee9d
fix linter
mfrancisc Sep 20, 2023
c3639a3
add nstemplatetier to informer start
mfrancisc Sep 20, 2023
f333b61
create HandleSpaceGetRequest handler in proxy
mfrancisc Sep 21, 2023
3eeb8fd
add notes for modifying registration-service.yaml
mfrancisc Sep 21, 2023
9278a66
Merge branch 'master' into sbapi
mfrancisc Sep 25, 2023
cc77790
Update pkg/proxy/handlers/spacelister.go
mfrancisc Sep 25, 2023
e83efa4
update name
mfrancisc Sep 25, 2023
1305bcf
use NSTemplateTierFunc from informer
mfrancisc Sep 26, 2023
db915bf
Update pkg/proxy/handlers/spacelister.go
mfrancisc Sep 27, 2023
0175925
move usersignup retrieval , retrun error in case of more the one spac…
mfrancisc Sep 27, 2023
a1507b3
populate binding list in workspace type
mfrancisc Sep 29, 2023
01124e8
Merge branch 'master' into sbapi
mfrancisc Sep 29, 2023
4704269
fix spacelist unit test
mfrancisc Sep 29, 2023
0b72c66
Merge branch 'sbapi' into sbapi2
mfrancisc Oct 1, 2023
5e393f3
go sum
mfrancisc Oct 2, 2023
7130609
update common
mfrancisc Oct 2, 2023
e3d2fec
Merge branch 'master' into sbapi2
mfrancisc Oct 9, 2023
9160b2e
Update pkg/proxy/handlers/spacelister.go
mfrancisc Oct 9, 2023
418ef6a
wip add sbr to bindings request
mfrancisc Oct 9, 2023
64ba7ba
check for SBR label and populate bindingRequest field
mfrancisc Oct 9, 2023
31c54dd
small typo
mfrancisc Oct 9, 2023
485a52e
handle sbr created on parent space case
mfrancisc Oct 9, 2023
e8eee83
avoid checking for multiple spacebindings for user
mfrancisc Oct 10, 2023
075917a
update api
mfrancisc Oct 10, 2023
3e1a9d0
Merge branch 'master' into sbapi2
alexeykazakov Oct 10, 2023
819cd5f
Update pkg/proxy/handlers/spacelister.go
mfrancisc Oct 11, 2023
6ae41cc
Update pkg/proxy/handlers/spacelister.go
mfrancisc Oct 11, 2023
e433e7f
update api and common
mfrancisc Oct 11, 2023
7da2560
Merge branch 'master' into sbapi2
mfrancisc Oct 12, 2023
105c90a
update common
mfrancisc Oct 12, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.19
require (
github.com/aws/aws-sdk-go v1.44.100
github.com/codeready-toolchain/api v0.0.0-20230918195153-739e8fb09a33
github.com/codeready-toolchain/toolchain-common v0.0.0-20231002120847-bf3a59c8351b
github.com/codeready-toolchain/toolchain-common v0.0.0-20230710095440-719b09376de3
github.com/go-logr/logr v1.2.3
github.com/gofrs/uuid v4.2.0+incompatible
github.com/pkg/errors v0.9.1
Expand Down Expand Up @@ -144,3 +144,5 @@ require (
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

replace github.com/codeready-toolchain/toolchain-common => github.com/mfrancisc/toolchain-common v0.0.0-20231002145157-94054ae52f2e
16 changes: 14 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,11 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA=
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g=
Expand Down Expand Up @@ -109,8 +113,6 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/codeready-toolchain/api v0.0.0-20230918195153-739e8fb09a33 h1:hxXfcFq2JgFISVxrkISg8m9DZMzpcPWRjPspx3M3Sxo=
github.com/codeready-toolchain/api v0.0.0-20230918195153-739e8fb09a33/go.mod h1:nn3W6eKb9PFIVwSwZW7wDeLACMBOwAV+4kddGuN+ARM=
github.com/codeready-toolchain/toolchain-common v0.0.0-20231002120847-bf3a59c8351b h1:3nk69kWcILOiu6Ul9DZZTRmx4pItVit+9uOAmjrYCfM=
github.com/codeready-toolchain/toolchain-common v0.0.0-20231002120847-bf3a59c8351b/go.mod h1:o/JGPWZ/9rVh/np0tcaPRXnreZ+X743o0Gxp1eP62/w=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
Expand Down Expand Up @@ -293,6 +295,7 @@ github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslC
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/huandu/xstrings v1.3.1 h1:4jgBlKK6tLKFvO8u5pmYjG91cqytmDCDvGh7ECVFfFs=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
Expand Down Expand Up @@ -368,8 +371,12 @@ github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APP
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/mfrancisc/toolchain-common v0.0.0-20231002145157-94054ae52f2e h1:P4C77qKcRLx9BJ8vnYaX6MC84SUCrz6EldhhiIazHHA=
github.com/mfrancisc/toolchain-common v0.0.0-20231002145157-94054ae52f2e/go.mod h1:o/JGPWZ/9rVh/np0tcaPRXnreZ+X743o0Gxp1eP62/w=
github.com/migueleliasweb/go-github-mock v0.0.18 h1:0lWt9MYmZQGnQE2rFtjlft/YtD6hzxuN6JJRFpujzEI=
github.com/migueleliasweb/go-github-mock v0.0.18/go.mod h1:CcgXcbMoRnf3rRVHqGssuBquZDIcaplxL2W6G+xs7kM=
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand Down Expand Up @@ -408,14 +415,17 @@ github.com/prometheus/common v0.40.0 h1:Afz7EVRqGg2Mqqf4JuF9vdvp1pi220m55Pi9T2Jn
github.com/prometheus/common v0.40.0/go.mod h1:L65ZJPSmfn/UBWLQIHV7dBrKFidB/wPlF1y5TlSt9OE=
github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
github.com/redhat-cop/operator-utils v1.3.3-0.20220121120056-862ef22b8cdf h1:fsZiv9XuFo8G7IyzFWjG02vqzJG7kSqFvD1Wiq3V/o8=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
Expand Down Expand Up @@ -974,13 +984,15 @@ k8s.io/apiserver v0.25.0 h1:8kl2ifbNffD440MyvHtPaIz1mw4mGKVgWqM0nL+oyu4=
k8s.io/apiserver v0.25.0/go.mod h1:BKwsE+PTC+aZK+6OJQDPr0v6uS91/HWxX7evElAH6xo=
k8s.io/client-go v0.25.0 h1:CVWIaCETLMBNiTUta3d5nzRbXvY5Hy9Dpl+VvREpu5E=
k8s.io/client-go v0.25.0/go.mod h1:lxykvypVfKilxhTklov0wz1FoaUZ8X4EwbhS6rpRfN8=
k8s.io/component-base v0.25.0 h1:haVKlLkPCFZhkcqB6WCvpVxftrg6+FK5x1ZuaIDaQ5Y=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ=
k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA=
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU=
k8s.io/kubectl v0.24.0 h1:nA+WtMLVdXUs4wLogGd1mPTAesnLdBpCVgCmz3I7dXo=
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4=
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
Expand Down
135 changes: 87 additions & 48 deletions pkg/proxy/handlers/spacelister.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"net/http"
"sort"

"time"

toolchainv1alpha1 "github.com/codeready-toolchain/api/api/v1alpha1"
"github.com/codeready-toolchain/registration-service/pkg/application"
"github.com/codeready-toolchain/registration-service/pkg/application/service"
Expand All @@ -14,8 +16,8 @@
"github.com/codeready-toolchain/registration-service/pkg/metrics"
"github.com/codeready-toolchain/registration-service/pkg/signup"
commonproxy "github.com/codeready-toolchain/toolchain-common/pkg/proxy"
"github.com/codeready-toolchain/toolchain-common/pkg/spacebinding"
"github.com/gin-gonic/gin"
"time"

"github.com/labstack/echo/v4"
errs "github.com/pkg/errors"
Expand All @@ -26,6 +28,15 @@
"k8s.io/apimachinery/pkg/selection"
)

const (
// UpdateBindingAction specifies that the current binding can be updated by providing a different Space Role.
UpdateBindingAction = "update"
// DeleteBindingAction specifies that the current binding can be deleted in order to revoke user access to the Space.
DeleteBindingAction = "delete"
// OverrideBindingAction specifies that the current binding can be overridden by creating a SpaceBinding containing the same MUR but different Space Role.
mfrancisc marked this conversation as resolved.
Show resolved Hide resolved
OverrideBindingAction = "override"
)

type SpaceLister struct {
GetSignupFunc func(ctx *gin.Context, userID, username string, checkUserSignupCompleted bool) (*signup.Signup, error)
GetInformerServiceFunc func() service.InformerService
Expand Down Expand Up @@ -71,6 +82,7 @@
func (s *SpaceLister) GetUserWorkspace(ctx echo.Context) (*toolchainv1alpha1.Workspace, error) {
userID, _ := ctx.Get(context.SubKey).(string)
username, _ := ctx.Get(context.UsernameKey).(string)
workspaceName := ctx.Param("workspace")

userSignup, err := s.GetSignupFunc(nil, userID, username, false)
if err != nil {
Expand All @@ -84,38 +96,57 @@
return nil, nil

}
murName := userSignup.CompliantUsername
spaceBinding, err := s.listSpaceBindingForUserAndSpace(ctx, murName)
space, err := s.GetInformerServiceFunc().GetSpace(workspaceName)
if err != nil {
ctx.Logger().Error(errs.Wrap(err, "error listing space bindings"))
return nil, err
}
if spaceBinding == nil {
// spacebinding not found, let's return a nil workspace which causes the handler to respond with a 404 status code
ctx.Logger().Error(errs.Wrap(err, "unable to get space"))
return nil, nil
}

space, err := s.getSpace(spaceBinding)
// recursively get all the spacebindings for the current workspace
listSpaceBindingsFunc := func(spaceName string) ([]toolchainv1alpha1.SpaceBinding, error) {
spaceSelector, err := labels.NewRequirement(toolchainv1alpha1.SpaceBindingSpaceLabelKey, selection.Equals, []string{spaceName})
if err != nil {
return nil, err
}

Check warning on line 110 in pkg/proxy/handlers/spacelister.go

View check run for this annotation

Codecov / codecov/patch

pkg/proxy/handlers/spacelister.go#L109-L110

Added lines #L109 - L110 were not covered by tests
return s.GetInformerServiceFunc().ListSpaceBindings(*spaceSelector)
}
getSpaceFunc := func(spaceName string) (*toolchainv1alpha1.Space, error) {
return s.GetInformerServiceFunc().GetSpace(spaceName)
}
spaceBindingLister := spacebinding.NewLister(listSpaceBindingsFunc, getSpaceFunc)
mfrancisc marked this conversation as resolved.
Show resolved Hide resolved
allSpaceBindings, err := spaceBindingLister.ListForSpace(space, []toolchainv1alpha1.SpaceBinding{})
if err != nil {
ctx.Logger().Error(errs.Wrap(err, "unable to get space"))
ctx.Logger().Error(err, "failed to list space bindings")
return nil, err
}

// -------------
// TODO recursively get all the spacebindings for the current workspace
// and build the Bindings list with the available actions
// check if user has access to this workspace
userBindings := filterUserSpaceBindings(userSignup.CompliantUsername, allSpaceBindings)
if len(userBindings) == 0 {
// let's only log the issue and consider this as not found
ctx.Logger().Error(fmt.Sprintf("expected only 1 spacebinding, got 0 for user %s and workspace %s", userSignup.CompliantUsername, workspaceName))
return nil, nil
} else if len(userBindings) > 1 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't a user have multiple SpaceBindings in a hierarchy of the spaces? Even if we don't really support it now we could support it in the future, right? Do we really need to make sure there is no than one here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, aren't we already checking that user has access to the workspace? Do we need to do this additional SpaceBinding check?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't a user have multiple SpaceBindings in a hierarchy of the spaces? Even if we don't really support it now we could support it in the future, right? Do we really need to make sure there is no than one here?

We could avoid the check, but right now:

allSpaceBindings, err := spaceBindingLister.ListForSpace(space, []toolchainv1alpha1.SpaceBinding{}) at line 117

should return only 1 spacebinding for the given Space and MUR (since it merges them based on the MUR name). So that's why I'm checking that there is no more than one returned from there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, aren't we already checking that user has access to the workspace? Do we need to do this additional SpaceBinding check?

before those changes there was this function here checking for the binding: https://github.com/codeready-toolchain/registration-service/pull/350/files#diff-cffbabd2ac8378a758970ae247dbee7b644f1d94e702181d836d5d5d19a048c5L88

I've replaced that with filterUserSpaceBindings which searches for the user binding from the list of all bindings that has already fetched above using the new spaceBindingLister.ListForSpace .

I don't see any other place where we check if user has access to the workspace 🤷‍♂️ , but maybe I'm missing something.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

before those changes there was this function here checking for the binding:

Ah.. OK. I missed that. So you are replacing the current check with the new one.

// internal server error
cause := fmt.Errorf("expected only 1 spacebinding, got %d for user %s and workspace %s", len(userBindings), userSignup.CompliantUsername, workspaceName)
ctx.Logger().Error(cause.Error())
return nil, cause
}
// build the Bindings list with the available actions
// this field is populated only for the GET workspace request
// -------------
bindings := generateWorkspaceBindings(space, allSpaceBindings)

// add available roles, this field is populated only for the GET workspace request
nsTemplateTier, err := s.GetInformerServiceFunc().GetNSTemplateTier(space.Spec.TierName)
if err != nil {
ctx.Logger().Error(errs.Wrap(err, "unable to get nstemplatetier"))
return nil, err
}
getOnlyWSOptions := commonproxy.WithAvailableRoles(getRolesFromNSTemplateTier(nsTemplateTier))

return createWorkspaceObject(userSignup.Name, space, spaceBinding, getOnlyWSOptions), nil
return createWorkspaceObject(userSignup.Name, space, &userBindings[0],
commonproxy.WithAvailableRoles(getRolesFromNSTemplateTier(nsTemplateTier)),
commonproxy.WithBindings(bindings),
), nil
}

func (s *SpaceLister) ListUserWorkspaces(ctx echo.Context) ([]toolchainv1alpha1.Workspace, error) {
Expand Down Expand Up @@ -151,38 +182,6 @@
return s.GetInformerServiceFunc().ListSpaceBindings(requirements...)
}

func (s *SpaceLister) listSpaceBindingForUserAndSpace(ctx echo.Context, murName string) (*toolchainv1alpha1.SpaceBinding, error) {
workspaceName := ctx.Param("workspace")
murSelector, err := labels.NewRequirement(toolchainv1alpha1.SpaceBindingMasterUserRecordLabelKey, selection.Equals, []string{murName})
if err != nil {
return nil, err
}
// specific workspace requested so add label requirement to match the space
spaceSelector, err := labels.NewRequirement(toolchainv1alpha1.SpaceBindingSpaceLabelKey, selection.Equals, []string{workspaceName})
if err != nil {
return nil, err
}
requirements := []labels.Requirement{*murSelector, *spaceSelector}

spaceBindings, err := s.GetInformerServiceFunc().ListSpaceBindings(requirements...)
if err != nil {
return nil, err
}

if len(spaceBindings) == 0 {
// let's only log the issue and consider this as not found
ctx.Logger().Error(fmt.Sprintf("expected only 1 spacebinding, got 0 for user %s and workspace %s", murName, workspaceName))
return nil, nil
} else if len(spaceBindings) > 1 {
// internal server error
cause := fmt.Errorf("expected only 1 spacebinding, got %d for user %s and workspace %s", len(spaceBindings), murName, workspaceName)
ctx.Logger().Error(cause.Error())
return nil, cause
}

return &spaceBindings[0], nil
}

func (s *SpaceLister) workspacesFromSpaceBindings(signupName string, spaceBindings []toolchainv1alpha1.SpaceBinding) []toolchainv1alpha1.Workspace {
workspaces := []toolchainv1alpha1.Workspace{}
for i := range spaceBindings {
Expand Down Expand Up @@ -265,3 +264,43 @@
ctx.Response().Writer.WriteHeader(int(err.ErrStatus.Code))
return json.NewEncoder(ctx.Response().Writer).Encode(err.ErrStatus)
}

// filterUserSpaceBindings returns all the spacebindings for a given username
func filterUserSpaceBindings(username string, allSpaceBindings []toolchainv1alpha1.SpaceBinding) (outputBindings []toolchainv1alpha1.SpaceBinding) {
for _, binding := range allSpaceBindings {
if binding.Spec.MasterUserRecord == username {
outputBindings = append(outputBindings, binding)
}
}
return outputBindings
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could change it so we wouldn't care about if the user has more than one SpaceBinding. What we care is if the user has access to the Space at all, not about the actual content

Suggested change
func filterUserSpaceBindings(username string, allSpaceBindings []toolchainv1alpha1.SpaceBinding) (outputBindings []toolchainv1alpha1.SpaceBinding) {
for _, binding := range allSpaceBindings {
if binding.Spec.MasterUserRecord == username {
outputBindings = append(outputBindings, binding)
}
}
return outputBindings
}
func filterUserSpaceBindings(username string, allSpaceBindings []toolchainv1alpha1.SpaceBinding) *toolchainv1alpha1.SpaceBinding {
for _, binding := range allSpaceBindings {
if binding.Spec.MasterUserRecord == username {
return &binding
}
}
return nil
}

I think that it would simplify the code a bit and it wouldn't have any negative impact on the functional aspects.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes this makes it easier!

I think we would just not be able to report in case there are issues with the system , generating more spacebindings for the same MUR (let's say for whatever reason, a bug in Space controller or SBR controller or other parts of the system like the sandbox-cli ... ). If this is acceptable then yes, the code can be simplified.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as decided earlier today, let's not return this error to the user. I'm not checking only for the user binding as you suggested. Plz check e8eee83


// generateWorkspaceBindings generates the bindings list starting from the spacebindings found on a given space resource and an all parent spaces.
// The Bindings list has the available actions for each entry in the list.
func generateWorkspaceBindings(space *toolchainv1alpha1.Space, spaceBindings []toolchainv1alpha1.SpaceBinding) []toolchainv1alpha1.Binding {
var bindings []toolchainv1alpha1.Binding
for _, spaceBinding := range spaceBindings {
binding := toolchainv1alpha1.Binding{
MasterUserRecord: spaceBinding.Spec.MasterUserRecord,
Role: spaceBinding.Spec.SpaceRole,
AvailableActions: []string{},
}
if name, exists := spaceBinding.GetLabels()[toolchainv1alpha1.SpaceBindingSpaceLabelKey]; exists && name == space.GetName() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should check the SBR labels instead - if the SpaceBinding was created by the UserSignup controller (as the default SpaceBinding) then the users cannot do anything with it. They can only update/delete those that have corresponding SBR CR in the namespace.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I think the logic was incorrect here 🤦‍♂️

I'm now checking for SBR label on the SB resource. Plz take a look mainly at: 64ba7ba

Thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There were actually a few cases missing:

  • the case in which there should be no available action, since the spacebinding was generated by the system or system admin
  • spacebinding was generated from SBR but on the parentSpace, so in this case it can only be overridden , and not updated/deleted as SBRs generated on the current space.

Please check also 485a52e

// this is a binding that was created on the current space, it can be updated or deleted
binding.AvailableActions = []string{UpdateBindingAction, DeleteBindingAction}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how does the client (UI) know which SBR it should either update or delete?
I think that the API is missing the bindingRequest field, right?
https://docs.google.com/document/d/1hWaFvCfsEXrbqs8ndDR0JPjKROXYJkvj1ZCnio4P1WU/edit#bookmark=id.tttpu2pbe4a6

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh jeez 🤦‍♂️ , I missed that field in the original API pr and totally forgot about it! Great catch!

I've raised codeready-toolchain/api#378 for this. And I'm updating this PR and e2e tests to use it!

Thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm now populating the bindingRequest field as well. PTAL at 64ba7ba

} else {
// this is a binding that was inherited from a parent space,
// it can only be overridden by another spacebinding containing the same MUR but different role.
binding.AvailableActions = []string{OverrideBindingAction}
}
bindings = append(bindings, binding)
}

// let's sort the list based on username,
// in order to make it deterministic
sort.Slice(bindings, func(i, j int) bool {
return bindings[i].MasterUserRecord < bindings[j].MasterUserRecord
})

return bindings
}
Loading
Loading