Skip to content

Commit a81ce66

Browse files
committed
[ws-manager-mk2] Extract ctrl utils to common-go
1 parent 463ee02 commit a81ce66

File tree

4 files changed

+45
-72
lines changed

4 files changed

+45
-72
lines changed

components/common-go/kubernetes/kubernetes.go

Lines changed: 24 additions & 0 deletions
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

Lines changed: 8 additions & 7 deletions
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

Lines changed: 9 additions & 41 deletions
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

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -341,10 +341,10 @@ func (wsm *WorkspaceManagerServer) MarkActive(ctx context.Context, req *wsmanapi
341341

342342
// We do however maintain the the "closed" flag as annotation on the workspace. This flag should not change
343343
// very often and provides a better UX if it persists across ws-manager restarts.
344-
isMarkedClosed := conditionPresentAndTrue(ws.Status.Conditions, string(workspacev1.WorkspaceConditionClosed))
344+
isMarkedClosed := wsk8s.ConditionPresentAndTrue(ws.Status.Conditions, string(workspacev1.WorkspaceConditionClosed))
345345
if req.Closed && !isMarkedClosed {
346346
err = wsm.modifyWorkspace(ctx, req.Id, true, func(ws *workspacev1.Workspace) error {
347-
ws.Status.Conditions = addUniqueCondition(ws.Status.Conditions, metav1.Condition{
347+
ws.Status.Conditions = wsk8s.AddUniqueCondition(ws.Status.Conditions, metav1.Condition{
348348
Type: string(workspacev1.WorkspaceConditionClosed),
349349
Status: metav1.ConditionTrue,
350350
LastTransitionTime: metav1.NewTime(now),
@@ -354,7 +354,7 @@ func (wsm *WorkspaceManagerServer) MarkActive(ctx context.Context, req *wsmanapi
354354
})
355355
} else if !req.Closed && isMarkedClosed {
356356
err = wsm.modifyWorkspace(ctx, req.Id, true, func(ws *workspacev1.Workspace) error {
357-
ws.Status.Conditions = addUniqueCondition(ws.Status.Conditions, metav1.Condition{
357+
ws.Status.Conditions = wsk8s.AddUniqueCondition(ws.Status.Conditions, metav1.Condition{
358358
Type: string(workspacev1.WorkspaceConditionClosed),
359359
Status: metav1.ConditionFalse,
360360
LastTransitionTime: metav1.NewTime(now),
@@ -370,7 +370,7 @@ func (wsm *WorkspaceManagerServer) MarkActive(ctx context.Context, req *wsmanapi
370370
// If it's the first call: Mark the pod with FirstUserActivity condition.
371371
if firstUserActivity == nil {
372372
err := wsm.modifyWorkspace(ctx, req.Id, true, func(ws *workspacev1.Workspace) error {
373-
ws.Status.Conditions = addUniqueCondition(ws.Status.Conditions, metav1.Condition{
373+
ws.Status.Conditions = wsk8s.AddUniqueCondition(ws.Status.Conditions, metav1.Condition{
374374
Type: string(workspacev1.WorkspaceConditionFirstUserActivity),
375375
Status: metav1.ConditionTrue,
376376
LastTransitionTime: metav1.NewTime(now),
@@ -965,23 +965,3 @@ func (m *workspaceMetrics) Describe(ch chan<- *prometheus.Desc) {
965965
func (m *workspaceMetrics) Collect(ch chan<- prometheus.Metric) {
966966
m.totalStartsCounterVec.Collect(ch)
967967
}
968-
969-
func addUniqueCondition(conds []metav1.Condition, cond metav1.Condition) []metav1.Condition {
970-
for i, c := range conds {
971-
if c.Type == cond.Type {
972-
conds[i] = cond
973-
return conds
974-
}
975-
}
976-
977-
return append(conds, cond)
978-
}
979-
980-
func conditionPresentAndTrue(cond []metav1.Condition, tpe string) bool {
981-
for _, c := range cond {
982-
if c.Type == tpe {
983-
return c.Status == metav1.ConditionTrue
984-
}
985-
}
986-
return false
987-
}

0 commit comments

Comments
 (0)