Skip to content

Commit f7ae052

Browse files
committed
[ws-manager-mk2] Extract ctrl utils to common-go
1 parent 971c3d6 commit f7ae052

File tree

4 files changed

+45
-72
lines changed

4 files changed

+45
-72
lines changed

components/common-go/kubernetes/kubernetes.go

+24
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,27 @@ func GetCondition(conds []metav1.Condition, tpe string) *metav1.Condition {
171171
}
172172
return nil
173173
}
174+
175+
// ConditionPresentAndTrue returns whether a condition is present and its status set to True.
176+
func ConditionPresentAndTrue(cond []metav1.Condition, tpe string) bool {
177+
for _, c := range cond {
178+
if c.Type == tpe {
179+
return c.Status == metav1.ConditionTrue
180+
}
181+
}
182+
return false
183+
}
184+
185+
// ConditionWithStatusAndReason returns whether a condition is present, and with the given Reason.
186+
func ConditionWithStatusAndReason(cond []metav1.Condition, tpe string, status bool, reason string) bool {
187+
st := metav1.ConditionFalse
188+
if status {
189+
st = metav1.ConditionTrue
190+
}
191+
for _, c := range cond {
192+
if c.Type == tpe {
193+
return c.Type == tpe && c.Status == st && c.Reason == reason
194+
}
195+
}
196+
return false
197+
}

components/ws-manager-mk2/controllers/status.go

+8-7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"encoding/json"
1111
"fmt"
1212

13+
wsk8s "github.com/gitpod-io/gitpod/common-go/kubernetes"
1314
workspacev1 "github.com/gitpod-io/gitpod/ws-manager/api/crd/v1"
1415
corev1 "k8s.io/api/core/v1"
1516
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -44,7 +45,7 @@ func updateWorkspaceStatus(ctx context.Context, workspace *workspacev1.Workspace
4445
// continue below
4546
default:
4647
// This is exceptional - not sure what to do here. Probably fail the pod
47-
workspace.Status.Conditions = AddUniqueCondition(workspace.Status.Conditions, metav1.Condition{
48+
workspace.Status.Conditions = wsk8s.AddUniqueCondition(workspace.Status.Conditions, metav1.Condition{
4849
Type: string(workspacev1.WorkspaceConditionFailed),
4950
Status: metav1.ConditionTrue,
5051
LastTransitionTime: metav1.Now(),
@@ -54,7 +55,7 @@ func updateWorkspaceStatus(ctx context.Context, workspace *workspacev1.Workspace
5455
return nil
5556
}
5657

57-
workspace.Status.Conditions = AddUniqueCondition(workspace.Status.Conditions, metav1.Condition{
58+
workspace.Status.Conditions = wsk8s.AddUniqueCondition(workspace.Status.Conditions, metav1.Condition{
5859
Type: string(workspacev1.WorkspaceConditionDeployed),
5960
Status: metav1.ConditionTrue,
6061
LastTransitionTime: metav1.Now(),
@@ -83,9 +84,9 @@ func updateWorkspaceStatus(ctx context.Context, workspace *workspacev1.Workspace
8384
workspace.Status.Phase = *phase
8485
}
8586

86-
if failure != "" && !conditionPresentAndTrue(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionFailed)) {
87+
if failure != "" && !wsk8s.ConditionPresentAndTrue(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionFailed)) {
8788
// workspaces can fail only once - once there is a failed condition set, stick with it
88-
workspace.Status.Conditions = AddUniqueCondition(workspace.Status.Conditions, metav1.Condition{
89+
workspace.Status.Conditions = wsk8s.AddUniqueCondition(workspace.Status.Conditions, metav1.Condition{
8990
Type: string(workspacev1.WorkspaceConditionFailed),
9091
Status: metav1.ConditionTrue,
9192
LastTransitionTime: metav1.Now(),
@@ -105,9 +106,9 @@ func updateWorkspaceStatus(ctx context.Context, workspace *workspacev1.Workspace
105106
}
106107
}
107108
if hasFinalizer {
108-
if conditionPresentAndTrue(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionBackupComplete)) ||
109-
conditionPresentAndTrue(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionBackupFailure)) ||
110-
conditionWithStatusAndReson(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionContentReady), false, "InitializationFailure") {
109+
if wsk8s.ConditionPresentAndTrue(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionBackupComplete)) ||
110+
wsk8s.ConditionPresentAndTrue(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionBackupFailure)) ||
111+
wsk8s.ConditionWithStatusAndReason(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionContentReady), false, "InitializationFailure") {
111112

112113
workspace.Status.Phase = workspacev1.WorkspacePhaseStopped
113114
}

components/ws-manager-mk2/controllers/workspace_controller.go

+9-41
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"sigs.k8s.io/controller-runtime/pkg/client"
1717
"sigs.k8s.io/controller-runtime/pkg/log"
1818

19+
wsk8s "github.com/gitpod-io/gitpod/common-go/kubernetes"
1920
config "github.com/gitpod-io/gitpod/ws-manager/api/config"
2021
workspacev1 "github.com/gitpod-io/gitpod/ws-manager/api/crd/v1"
2122
"github.com/prometheus/client_golang/prometheus"
@@ -176,7 +177,7 @@ func (r *WorkspaceReconciler) actOnStatus(ctx context.Context, workspace *worksp
176177

177178
switch {
178179
// if there is a pod, and it's failed, delete it
179-
case conditionPresentAndTrue(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionFailed)) && !isPodBeingDeleted(pod):
180+
case wsk8s.ConditionPresentAndTrue(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionFailed)) && !isPodBeingDeleted(pod):
180181
err := r.Client.Delete(ctx, pod)
181182
if errors.IsNotFound(err) {
182183
// pod is gone - nothing to do here
@@ -185,7 +186,7 @@ func (r *WorkspaceReconciler) actOnStatus(ctx context.Context, workspace *worksp
185186
}
186187

187188
// if the pod was stopped by request, delete it
188-
case conditionPresentAndTrue(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionStoppedByRequest)) && !isPodBeingDeleted(pod):
189+
case wsk8s.ConditionPresentAndTrue(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionStoppedByRequest)) && !isPodBeingDeleted(pod):
189190
err := r.Client.Delete(ctx, pod)
190191
if errors.IsNotFound(err) {
191192
// pod is gone - nothing to do here
@@ -194,7 +195,7 @@ func (r *WorkspaceReconciler) actOnStatus(ctx context.Context, workspace *worksp
194195
}
195196

196197
// if the content initialization failed, delete the pod
197-
case conditionWithStatusAndReson(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionContentReady), false, "InitializationFailure") && !isPodBeingDeleted(pod):
198+
case wsk8s.ConditionWithStatusAndReason(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionContentReady), false, "InitializationFailure") && !isPodBeingDeleted(pod):
198199
err := r.Client.Delete(ctx, pod)
199200
if errors.IsNotFound(err) {
200201
// pod is gone - nothing to do here
@@ -243,28 +244,28 @@ func (r *WorkspaceReconciler) updateMetrics(ctx context.Context, workspace *work
243244
phase == workspacev1.WorkspacePhaseCreating ||
244245
phase == workspacev1.WorkspacePhaseInitializing:
245246

246-
if conditionWithStatusAndReson(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionContentReady), false, "InitializationFailure") {
247+
if wsk8s.ConditionWithStatusAndReason(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionContentReady), false, "InitializationFailure") {
247248
r.metrics.countTotalRestoreFailures(&log, workspace)
248249
r.metrics.countWorkspaceStartFailures(&log, workspace)
249250
}
250251

251-
if conditionPresentAndTrue(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionFailed)) {
252+
if wsk8s.ConditionPresentAndTrue(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionFailed)) {
252253
r.metrics.countWorkspaceStartFailures(&log, workspace)
253254
}
254255

255256
case phase == workspacev1.WorkspacePhaseRunning:
256257
r.metrics.recordWorkspaceStartupTime(&log, workspace)
257-
if conditionPresentAndTrue(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionContentReady)) {
258+
if wsk8s.ConditionPresentAndTrue(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionContentReady)) {
258259
r.metrics.countTotalRestores(&log, workspace)
259260
}
260261

261262
case phase == workspacev1.WorkspacePhaseStopped:
262-
if conditionPresentAndTrue(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionBackupFailure)) {
263+
if wsk8s.ConditionPresentAndTrue(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionBackupFailure)) {
263264
r.metrics.countTotalBackups(&log, workspace)
264265
r.metrics.countTotalBackupFailures(&log, workspace)
265266
}
266267

267-
if conditionPresentAndTrue(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionBackupComplete)) {
268+
if wsk8s.ConditionPresentAndTrue(workspace.Status.Conditions, string(workspacev1.WorkspaceConditionBackupComplete)) {
268269
r.metrics.countTotalBackups(&log, workspace)
269270
}
270271

@@ -276,24 +277,6 @@ func (r *WorkspaceReconciler) updateMetrics(ctx context.Context, workspace *work
276277
r.metrics.rememberWorkspace(workspace)
277278
}
278279

279-
func conditionPresentAndTrue(cond []metav1.Condition, tpe string) bool {
280-
for _, c := range cond {
281-
if c.Type == tpe {
282-
return c.Status == metav1.ConditionTrue
283-
}
284-
}
285-
return false
286-
}
287-
288-
func conditionWithStatusAndReson(cond []metav1.Condition, tpe string, status bool, reason string) bool {
289-
for _, c := range cond {
290-
if c.Type == tpe {
291-
return c.Type == tpe && c.Reason == reason
292-
}
293-
}
294-
return false
295-
}
296-
297280
var (
298281
wsOwnerKey = ".metadata.controller"
299282
apiGVStr = workspacev1.GroupVersion.String()
@@ -326,18 +309,3 @@ func (r *WorkspaceReconciler) SetupWithManager(mgr ctrl.Manager) error {
326309
Owns(&corev1.Pod{}).
327310
Complete(r)
328311
}
329-
330-
func AddUniqueCondition(conds []metav1.Condition, cond metav1.Condition) []metav1.Condition {
331-
if cond.Reason == "" {
332-
cond.Reason = "unknown"
333-
}
334-
335-
for i, c := range conds {
336-
if c.Type == cond.Type {
337-
conds[i] = cond
338-
return conds
339-
}
340-
}
341-
342-
return append(conds, cond)
343-
}

components/ws-manager-mk2/service/manager.go

+4-24
Original file line numberDiff line numberDiff line change
@@ -342,10 +342,10 @@ func (wsm *WorkspaceManagerServer) MarkActive(ctx context.Context, req *wsmanapi
342342

343343
// We do however maintain the the "closed" flag as annotation on the workspace. This flag should not change
344344
// very often and provides a better UX if it persists across ws-manager restarts.
345-
isMarkedClosed := conditionPresentAndTrue(ws.Status.Conditions, string(workspacev1.WorkspaceConditionClosed))
345+
isMarkedClosed := wsk8s.ConditionPresentAndTrue(ws.Status.Conditions, string(workspacev1.WorkspaceConditionClosed))
346346
if req.Closed && !isMarkedClosed {
347347
err = wsm.modifyWorkspace(ctx, req.Id, true, func(ws *workspacev1.Workspace) error {
348-
ws.Status.Conditions = addUniqueCondition(ws.Status.Conditions, metav1.Condition{
348+
ws.Status.Conditions = wsk8s.AddUniqueCondition(ws.Status.Conditions, metav1.Condition{
349349
Type: string(workspacev1.WorkspaceConditionClosed),
350350
Status: metav1.ConditionTrue,
351351
LastTransitionTime: metav1.NewTime(now),
@@ -355,7 +355,7 @@ func (wsm *WorkspaceManagerServer) MarkActive(ctx context.Context, req *wsmanapi
355355
})
356356
} else if !req.Closed && isMarkedClosed {
357357
err = wsm.modifyWorkspace(ctx, req.Id, true, func(ws *workspacev1.Workspace) error {
358-
ws.Status.Conditions = addUniqueCondition(ws.Status.Conditions, metav1.Condition{
358+
ws.Status.Conditions = wsk8s.AddUniqueCondition(ws.Status.Conditions, metav1.Condition{
359359
Type: string(workspacev1.WorkspaceConditionClosed),
360360
Status: metav1.ConditionFalse,
361361
LastTransitionTime: metav1.NewTime(now),
@@ -375,7 +375,7 @@ func (wsm *WorkspaceManagerServer) MarkActive(ctx context.Context, req *wsmanapi
375375
// If it's the first call: Mark the pod with FirstUserActivity condition.
376376
if firstUserActivity == nil {
377377
err := wsm.modifyWorkspace(ctx, req.Id, true, func(ws *workspacev1.Workspace) error {
378-
ws.Status.Conditions = addUniqueCondition(ws.Status.Conditions, metav1.Condition{
378+
ws.Status.Conditions = wsk8s.AddUniqueCondition(ws.Status.Conditions, metav1.Condition{
379379
Type: string(workspacev1.WorkspaceConditionFirstUserActivity),
380380
Status: metav1.ConditionTrue,
381381
LastTransitionTime: metav1.NewTime(now),
@@ -970,23 +970,3 @@ func (m *workspaceMetrics) Describe(ch chan<- *prometheus.Desc) {
970970
func (m *workspaceMetrics) Collect(ch chan<- prometheus.Metric) {
971971
m.totalStartsCounterVec.Collect(ch)
972972
}
973-
974-
func addUniqueCondition(conds []metav1.Condition, cond metav1.Condition) []metav1.Condition {
975-
for i, c := range conds {
976-
if c.Type == cond.Type {
977-
conds[i] = cond
978-
return conds
979-
}
980-
}
981-
982-
return append(conds, cond)
983-
}
984-
985-
func conditionPresentAndTrue(cond []metav1.Condition, tpe string) bool {
986-
for _, c := range cond {
987-
if c.Type == tpe {
988-
return c.Status == metav1.ConditionTrue
989-
}
990-
}
991-
return false
992-
}

0 commit comments

Comments
 (0)