Skip to content

Commit 78d7e48

Browse files
author
Yehudit Kerido
committed
test(ws): Notebooks 2.0 // Backend // Add tests
Signed-off-by: Yehudit Kerido <[email protected]>
1 parent 2c3e75e commit 78d7e48

File tree

9 files changed

+797
-0
lines changed

9 files changed

+797
-0
lines changed

workspaces/backend/go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ require (
99
github.com/kubeflow/notebooks/workspaces/controller v0.0.0
1010
github.com/onsi/ginkgo/v2 v2.19.0
1111
github.com/onsi/gomega v1.33.1
12+
github.com/stretchr/testify v1.9.0
1213
github.com/swaggo/http-swagger/v2 v2.0.2
1314
github.com/swaggo/swag v1.16.4
1415
k8s.io/api v0.31.0
@@ -60,6 +61,7 @@ require (
6061
github.com/modern-go/reflect2 v1.0.2 // indirect
6162
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
6263
github.com/pkg/errors v0.9.1 // indirect
64+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
6365
github.com/prometheus/client_golang v1.19.1 // indirect
6466
github.com/prometheus/client_model v0.6.1 // indirect
6567
github.com/prometheus/common v0.55.0 // indirect
@@ -93,6 +95,7 @@ require (
9395
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect
9496
google.golang.org/grpc v1.65.0 // indirect
9597
google.golang.org/protobuf v1.34.2 // indirect
98+
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
9699
gopkg.in/inf.v0 v0.9.1 // indirect
97100
gopkg.in/yaml.v2 v2.4.0 // indirect
98101
gopkg.in/yaml.v3 v3.0.1 // indirect
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
Copyright 2024.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package auth
18+
19+
import (
20+
"net/http"
21+
22+
. "github.com/onsi/ginkgo/v2"
23+
. "github.com/onsi/gomega"
24+
)
25+
26+
var _ = Describe("NewRequestAuthenticator", func() {
27+
const (
28+
userHeader = "X-User"
29+
groupsHeader = "X-Groups"
30+
userPrefix = "service-account:"
31+
)
32+
33+
It("authenticates user without prefix", func() {
34+
authn, err := NewRequestAuthenticator(userHeader, "", groupsHeader)
35+
Expect(err).NotTo(HaveOccurred())
36+
37+
req, _ := http.NewRequest("GET", "/", http.NoBody)
38+
req.Header.Set(userHeader, "test-user")
39+
req.Header.Set(groupsHeader, "group-a,group-b")
40+
41+
resp, ok, err := authn.AuthenticateRequest(req)
42+
Expect(err).NotTo(HaveOccurred())
43+
Expect(ok).To(BeTrue())
44+
Expect(resp).NotTo(BeNil())
45+
Expect(resp.User.GetName()).To(Equal("test-user"))
46+
Expect(resp.User.GetGroups()).To(ConsistOf("group-a,group-b"))
47+
})
48+
49+
It("authenticates user and trims prefix", func() {
50+
authn, err := NewRequestAuthenticator(userHeader, userPrefix, groupsHeader)
51+
Expect(err).NotTo(HaveOccurred())
52+
53+
req, _ := http.NewRequest("GET", "/", http.NoBody)
54+
req.Header.Set(userHeader, userPrefix+"test-user")
55+
req.Header.Set(groupsHeader, "group-c")
56+
57+
resp, ok, err := authn.AuthenticateRequest(req)
58+
Expect(err).NotTo(HaveOccurred())
59+
Expect(ok).To(BeTrue())
60+
Expect(resp).NotTo(BeNil())
61+
Expect(resp.User.GetName()).To(Equal("test-user"))
62+
Expect(resp.User.GetGroups()).To(Equal([]string{"group-c"}))
63+
})
64+
65+
It("authenticates user when prefix is configured but not present", func() {
66+
authn, err := NewRequestAuthenticator(userHeader, userPrefix, groupsHeader)
67+
Expect(err).NotTo(HaveOccurred())
68+
69+
req, _ := http.NewRequest("GET", "/", http.NoBody)
70+
req.Header.Set(userHeader, "another-user")
71+
72+
resp, ok, err := authn.AuthenticateRequest(req)
73+
Expect(err).NotTo(HaveOccurred())
74+
Expect(ok).To(BeTrue())
75+
Expect(resp).NotTo(BeNil())
76+
Expect(resp.User.GetName()).To(Equal("another-user"))
77+
})
78+
79+
It("handles unauthenticated request", func() {
80+
authn, err := NewRequestAuthenticator(userHeader, userPrefix, groupsHeader)
81+
Expect(err).NotTo(HaveOccurred())
82+
83+
req, _ := http.NewRequest("GET", "/", http.NoBody)
84+
req.Header.Set(groupsHeader, "some-group")
85+
86+
resp, ok, err := authn.AuthenticateRequest(req)
87+
Expect(err).NotTo(HaveOccurred())
88+
Expect(ok).To(BeFalse())
89+
Expect(resp).To(BeNil())
90+
})
91+
})
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
Copyright 2024.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package auth
18+
19+
import (
20+
. "github.com/onsi/ginkgo/v2"
21+
. "github.com/onsi/gomega"
22+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
23+
"k8s.io/apimachinery/pkg/runtime"
24+
"k8s.io/apimachinery/pkg/runtime/schema"
25+
"k8s.io/apiserver/pkg/authentication/user"
26+
)
27+
28+
type mockObject struct {
29+
metav1.ObjectMeta
30+
metav1.TypeMeta
31+
}
32+
33+
func (m *mockObject) GetObjectKind() schema.ObjectKind { return &m.TypeMeta }
34+
35+
func (m *mockObject) DeepCopyObject() runtime.Object {
36+
return &mockObject{
37+
ObjectMeta: *m.ObjectMeta.DeepCopy(),
38+
TypeMeta: m.TypeMeta,
39+
}
40+
}
41+
42+
var _ runtime.Object = &mockObject{}
43+
var _ = Describe("NewResourcePolicy", func() {
44+
It("creates policy for a namespaced resource", func() {
45+
mock := &mockObject{}
46+
mock.SetName("my-deployment")
47+
mock.SetNamespace("my-namespace")
48+
mock.SetGroupVersionKind(schema.GroupVersionKind{
49+
Group: "apps",
50+
Version: "v1",
51+
Kind: "Deployment",
52+
})
53+
54+
policy := NewResourcePolicy(ResourceVerbGet, mock)
55+
56+
Expect(policy).NotTo(BeNil())
57+
Expect(policy.Verb).To(Equal(ResourceVerbGet))
58+
Expect(policy.Group).To(Equal("apps"))
59+
Expect(policy.Version).To(Equal("v1"))
60+
Expect(policy.Kind).To(Equal("Deployment"))
61+
Expect(policy.Namespace).To(Equal("my-namespace"))
62+
Expect(policy.Name).To(Equal("my-deployment"))
63+
})
64+
65+
It("creates policy for a cluster-scoped resource", func() {
66+
mock := &mockObject{}
67+
mock.SetName("my-cluster-role")
68+
mock.SetGroupVersionKind(schema.GroupVersionKind{
69+
Group: "rbac.authorization.k8s.io",
70+
Version: "v1",
71+
Kind: "ClusterRole",
72+
})
73+
74+
policy := NewResourcePolicy(ResourceVerbDelete, mock)
75+
76+
Expect(policy).NotTo(BeNil())
77+
Expect(policy.Verb).To(Equal(ResourceVerbDelete))
78+
Expect(policy.Group).To(Equal("rbac.authorization.k8s.io"))
79+
Expect(policy.Kind).To(Equal("ClusterRole"))
80+
Expect(policy.Name).To(Equal("my-cluster-role"))
81+
Expect(policy.Namespace).To(BeEmpty())
82+
})
83+
})
84+
85+
var _ = Describe("AttributesFor", func() {
86+
userInfo := &user.DefaultInfo{
87+
Name: "test-user",
88+
Groups: []string{"group-a", "system:authenticated"},
89+
}
90+
91+
It("creates attributes for a specific resource", func() {
92+
policy := &ResourcePolicy{
93+
Verb: ResourceVerbUpdate,
94+
Group: "kubeflow.org",
95+
Version: "v1beta1",
96+
Kind: "Workspace",
97+
Namespace: "user-namespace",
98+
Name: "my-workspace",
99+
}
100+
101+
attrs := policy.AttributesFor(userInfo)
102+
Expect(attrs).NotTo(BeNil())
103+
Expect(attrs.GetUser()).To(Equal(userInfo))
104+
Expect(attrs.GetVerb()).To(Equal("update"))
105+
Expect(attrs.GetNamespace()).To(Equal("user-namespace"))
106+
Expect(attrs.GetAPIGroup()).To(Equal("kubeflow.org"))
107+
Expect(attrs.GetAPIVersion()).To(Equal("v1beta1"))
108+
Expect(attrs.GetResource()).To(Equal("Workspace"))
109+
Expect(attrs.GetName()).To(Equal("my-workspace"))
110+
Expect(attrs.IsResourceRequest()).To(BeTrue())
111+
})
112+
113+
It("creates attributes for a collection of resources", func() {
114+
policy := &ResourcePolicy{
115+
Verb: ResourceVerbList,
116+
Group: "kubeflow.org",
117+
Version: "v1beta1",
118+
Kind: "Workspace",
119+
Namespace: "user-namespace",
120+
Name: "",
121+
}
122+
123+
attrs := policy.AttributesFor(userInfo)
124+
Expect(attrs).NotTo(BeNil())
125+
Expect(attrs.GetUser()).To(Equal(userInfo))
126+
Expect(attrs.GetVerb()).To(Equal("list"))
127+
Expect(attrs.GetNamespace()).To(Equal("user-namespace"))
128+
Expect(attrs.GetName()).To(BeEmpty())
129+
Expect(attrs.IsResourceRequest()).To(BeTrue())
130+
})
131+
})
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
Copyright 2024.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package auth
18+
19+
import (
20+
"testing"
21+
22+
. "github.com/onsi/ginkgo/v2"
23+
. "github.com/onsi/gomega"
24+
)
25+
26+
func TestAuth(t *testing.T) {
27+
RegisterFailHandler(Fail)
28+
RunSpecs(t, "Auth Suite")
29+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
Copyright 2024.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package helper
18+
19+
import (
20+
. "github.com/onsi/ginkgo/v2"
21+
. "github.com/onsi/gomega"
22+
corev1 "k8s.io/api/core/v1"
23+
"k8s.io/apimachinery/pkg/runtime/schema"
24+
)
25+
26+
var _ = Describe("Helper functions", func() {
27+
Describe("BuildScheme", func() {
28+
It("should return a scheme that recognizes Pod and Workspace types", func() {
29+
scheme, err := BuildScheme()
30+
Expect(err).NotTo(HaveOccurred())
31+
Expect(scheme).NotTo(BeNil())
32+
33+
podGVK := corev1.SchemeGroupVersion.WithKind("Pod")
34+
Expect(scheme.Recognizes(podGVK)).To(BeTrue())
35+
36+
workspaceGVK := schema.GroupVersionKind{
37+
Group: "kubeflow.org",
38+
Version: "v1beta1",
39+
Kind: "Workspace",
40+
}
41+
Expect(scheme.Recognizes(workspaceGVK)).To(BeTrue())
42+
})
43+
})
44+
})
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
Copyright 2024.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package helper
18+
19+
import (
20+
"testing"
21+
22+
. "github.com/onsi/ginkgo/v2"
23+
. "github.com/onsi/gomega"
24+
)
25+
26+
func TestHelper(t *testing.T) {
27+
RegisterFailHandler(Fail)
28+
RunSpecs(t, "Helper Suite")
29+
}

0 commit comments

Comments
 (0)