@@ -31,134 +31,57 @@ import (
31
31
)
32
32
33
33
const (
34
- timeout = time .Second * 20
34
+ timeout = time .Second * 10
35
35
duration = time .Second * 2
36
36
interval = time .Millisecond * 250
37
37
workspaceNamespace = "default"
38
38
)
39
39
40
40
var _ = Describe ("WorkspaceCountController" , func () {
41
- It ("should set scale-down-disabled when workspace is assigned to node" , func () {
42
- // Create a workspace
43
- name := uuid .NewString ()
44
- ws := newWorkspace (name , workspaceNamespace , workspacev1 .WorkspacePhaseRunning )
45
- createWorkspace (ws )
46
-
47
- // Update its runtime status with a node
48
- updateObjWithRetries (k8sClient , ws , true , func (ws * workspacev1.Workspace ) {
49
- ws .Status .Runtime = & workspacev1.WorkspaceRuntimeStatus {
50
- NodeName : NodeName ,
51
- }
52
- })
53
-
54
- // Verify node gets annotated
55
- Eventually (func (g Gomega ) {
56
- var node corev1.Node
57
- g .Expect (k8sClient .Get (ctx , types.NamespacedName {Name : NodeName }, & node )).To (Succeed ())
58
- g .Expect (node .Annotations ).To (HaveKeyWithValue ("cluster-autoscaler.kubernetes.io/scale-down-disabled" , "true" ))
59
- }, timeout , interval ).Should (Succeed ())
60
- })
61
-
62
41
It ("should remove scale-down-disabled when last workspace is removed" , func () {
63
- // Create two workspaces on the same node
64
- ws1 := newWorkspace (uuid .NewString (), workspaceNamespace , workspacev1 .WorkspacePhaseRunning )
65
- ws2 := newWorkspace (uuid .NewString (), workspaceNamespace , workspacev1 .WorkspacePhaseRunning )
42
+ ws1 := newWorkspace (uuid .NewString (), workspaceNamespace , NodeName , workspacev1 .WorkspacePhaseRunning )
43
+ ws2 := newWorkspace (uuid .NewString (), workspaceNamespace , NodeName , workspacev1 .WorkspacePhaseRunning )
44
+ ws1 .Status .Runtime = nil
45
+ ws2 .Status .Runtime = nil
66
46
createWorkspace (ws1 )
67
47
createWorkspace (ws2 )
68
48
69
- // Assign them to the node
49
+ By ( "Assigning nodes to workspaces" )
70
50
updateObjWithRetries (k8sClient , ws1 , true , func (ws * workspacev1.Workspace ) {
51
+ ws .Status .Conditions = []metav1.Condition {}
71
52
ws .Status .Runtime = & workspacev1.WorkspaceRuntimeStatus {
72
53
NodeName : NodeName ,
73
54
}
74
55
})
56
+
75
57
updateObjWithRetries (k8sClient , ws2 , true , func (ws * workspacev1.Workspace ) {
58
+ ws .Status .Conditions = []metav1.Condition {}
76
59
ws .Status .Runtime = & workspacev1.WorkspaceRuntimeStatus {
77
60
NodeName : NodeName ,
78
61
}
79
62
})
80
63
81
- // Verify node has annotation
64
+ By ( "Verifying node annotation" )
82
65
Eventually (func (g Gomega ) {
83
66
var node corev1.Node
84
67
g .Expect (k8sClient .Get (ctx , types.NamespacedName {Name : NodeName }, & node )).To (Succeed ())
85
68
g .Expect (node .Annotations ).To (HaveKeyWithValue ("cluster-autoscaler.kubernetes.io/scale-down-disabled" , "true" ))
86
69
}, timeout , interval ).Should (Succeed ())
87
70
88
- // Delete first workspace
71
+ By ( "Deleting workspaces" )
89
72
Expect (k8sClient .Delete (ctx , ws1 )).To (Succeed ())
90
-
91
- // Verify annotation still exists (second workspace still there)
92
- Consistently (func (g Gomega ) {
93
- var node corev1.Node
94
- g .Expect (k8sClient .Get (ctx , types.NamespacedName {Name : NodeName }, & node )).To (Succeed ())
95
- g .Expect (node .Annotations ).To (HaveKeyWithValue ("cluster-autoscaler.kubernetes.io/scale-down-disabled" , "true" ))
96
- }, "2s" , "100ms" ).Should (Succeed ())
97
-
98
- // Delete second workspace
99
73
Expect (k8sClient .Delete (ctx , ws2 )).To (Succeed ())
100
74
101
- // Verify annotation is removed
75
+ By ( "Verifying final state" )
102
76
Eventually (func (g Gomega ) {
103
77
var node corev1.Node
104
78
g .Expect (k8sClient .Get (ctx , types.NamespacedName {Name : NodeName }, & node )).To (Succeed ())
105
79
g .Expect (node .Annotations ).ToNot (HaveKey ("cluster-autoscaler.kubernetes.io/scale-down-disabled" ))
106
80
}, timeout , interval ).Should (Succeed ())
107
81
})
108
-
109
- It ("should handle workspaces across multiple nodes" , func () {
110
- const SecondNode = "second-node"
111
-
112
- // Create nodes
113
- node2 := & corev1.Node {
114
- ObjectMeta : metav1.ObjectMeta {
115
- Name : SecondNode ,
116
- },
117
- }
118
- Expect (k8sClient .Create (ctx , node2 )).To (Succeed ())
119
-
120
- // Create workspaces
121
- ws1 := newWorkspace (uuid .NewString (), workspaceNamespace , workspacev1 .WorkspacePhaseRunning )
122
- ws2 := newWorkspace (uuid .NewString (), workspaceNamespace , workspacev1 .WorkspacePhaseRunning )
123
- createWorkspace (ws1 )
124
- createWorkspace (ws2 )
125
-
126
- // Assign to different nodes
127
- updateObjWithRetries (k8sClient , ws1 , true , func (ws * workspacev1.Workspace ) {
128
- ws .Status .Runtime = & workspacev1.WorkspaceRuntimeStatus {
129
- NodeName : NodeName ,
130
- }
131
- })
132
- updateObjWithRetries (k8sClient , ws2 , true , func (ws * workspacev1.Workspace ) {
133
- ws .Status .Runtime = & workspacev1.WorkspaceRuntimeStatus {
134
- NodeName : SecondNode ,
135
- }
136
- })
137
-
138
- // Verify both nodes get annotated
139
- Eventually (func (g Gomega ) {
140
- var node1 , node2 corev1.Node
141
- g .Expect (k8sClient .Get (ctx , types.NamespacedName {Name : NodeName }, & node1 )).To (Succeed ())
142
- g .Expect (k8sClient .Get (ctx , types.NamespacedName {Name : SecondNode }, & node2 )).To (Succeed ())
143
- g .Expect (node1 .Annotations ).To (HaveKeyWithValue ("cluster-autoscaler.kubernetes.io/scale-down-disabled" , "true" ))
144
- g .Expect (node2 .Annotations ).To (HaveKeyWithValue ("cluster-autoscaler.kubernetes.io/scale-down-disabled" , "true" ))
145
- }, timeout , interval ).Should (Succeed ())
146
-
147
- // Delete workspace on first node
148
- Expect (k8sClient .Delete (ctx , ws1 )).To (Succeed ())
149
-
150
- // Verify first node's annotation is removed but second remains
151
- Eventually (func (g Gomega ) {
152
- var node1 , node2 corev1.Node
153
- g .Expect (k8sClient .Get (ctx , types.NamespacedName {Name : NodeName }, & node1 )).To (Succeed ())
154
- g .Expect (k8sClient .Get (ctx , types.NamespacedName {Name : SecondNode }, & node2 )).To (Succeed ())
155
- g .Expect (node1 .Annotations ).ToNot (HaveKey ("cluster-autoscaler.kubernetes.io/scale-down-disabled" ))
156
- g .Expect (node2 .Annotations ).To (HaveKeyWithValue ("cluster-autoscaler.kubernetes.io/scale-down-disabled" , "true" ))
157
- }, timeout , interval ).Should (Succeed ())
158
- })
159
82
})
160
83
161
- func newWorkspace (name , namespace string , phase workspacev1.WorkspacePhase ) * workspacev1.Workspace {
84
+ func newWorkspace (name , namespace , nodeName string , phase workspacev1.WorkspacePhase ) * workspacev1.Workspace {
162
85
GinkgoHelper ()
163
86
initializer := & csapi.WorkspaceInitializer {
164
87
Spec : & csapi.WorkspaceInitializer_Empty {Empty : & csapi.EmptyInitializer {}},
@@ -168,17 +91,19 @@ func newWorkspace(name, namespace string, phase workspacev1.WorkspacePhase) *wor
168
91
169
92
return & workspacev1.Workspace {
170
93
Status : workspacev1.WorkspaceStatus {
171
- Phase : phase ,
94
+ Phase : phase ,
95
+ Runtime : & workspacev1.WorkspaceRuntimeStatus {
96
+ NodeName : nodeName ,
97
+ },
172
98
Conditions : []metav1.Condition {},
173
99
},
174
100
TypeMeta : metav1.TypeMeta {
175
101
APIVersion : "workspace.gitpod.io/v1" ,
176
102
Kind : "Workspace" ,
177
103
},
178
104
ObjectMeta : metav1.ObjectMeta {
179
- Name : name ,
180
- Namespace : namespace ,
181
- Finalizers : []string {workspacev1 .GitpodFinalizerName },
105
+ Name : name ,
106
+ Namespace : namespace ,
182
107
},
183
108
Spec : workspacev1.WorkspaceSpec {
184
109
Ownership : workspacev1.Ownership {
@@ -237,7 +162,7 @@ var (
237
162
ctx context.Context
238
163
cancel context.CancelFunc
239
164
workspaceCtrl * WorkspaceCountController
240
- NodeName = "ws-daemon -node"
165
+ NodeName = "cool-ws -node"
241
166
)
242
167
243
168
func TestAPIs (t * testing.T ) {
@@ -253,7 +178,7 @@ var _ = BeforeSuite(func() {
253
178
testEnv = & envtest.Environment {
254
179
ControlPlaneStartTimeout : 1 * time .Minute ,
255
180
ControlPlaneStopTimeout : 1 * time .Minute ,
256
- CRDDirectoryPaths : []string {filepath .Join (".." , ".." , " crd" )},
181
+ CRDDirectoryPaths : []string {filepath .Join (".." , "crd" )},
257
182
ErrorIfCRDPathMissing : true ,
258
183
}
259
184
@@ -276,6 +201,14 @@ var _ = BeforeSuite(func() {
276
201
Expect (err ).ToNot (HaveOccurred ())
277
202
ctx , cancel = context .WithCancel (context .Background ())
278
203
204
+ By ("Creating default ws node" )
205
+ node := & corev1.Node {
206
+ ObjectMeta : metav1.ObjectMeta {
207
+ Name : NodeName ,
208
+ },
209
+ }
210
+ Expect (k8sClient .Create (ctx , node )).To (Succeed ())
211
+
279
212
By ("Setting up workspace controller" )
280
213
workspaceCtrl , err = NewWorkspaceCountController (k8sClient )
281
214
Expect (err ).NotTo (HaveOccurred ())
0 commit comments