Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/ee/agent-smith/pkg/agent/actions.go
2501 views
1
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package agent
6
7
import (
8
"context"
9
10
wsk8s "github.com/gitpod-io/gitpod/common-go/kubernetes"
11
"github.com/gitpod-io/gitpod/common-go/log"
12
protocol "github.com/gitpod-io/gitpod/gitpod-protocol"
13
wsmanapi "github.com/gitpod-io/gitpod/ws-manager/api"
14
15
"golang.org/x/sys/unix"
16
"golang.org/x/xerrors"
17
corev1 "k8s.io/apimachinery/pkg/apis/meta/v1"
18
"k8s.io/client-go/util/retry"
19
)
20
21
// all functions in this file deal directly with Kubernetes and make several assumptions
22
// how workspace pods look like. This code should eventually be moved to ws-manager or
23
// call one of ws-manager's libraries.
24
25
// stopWorkspace stops a workspace
26
func (agent *Smith) stopWorkspace(supervisorPID int, instanceID string) error {
27
req := &wsmanapi.StopWorkspaceRequest{
28
Id: instanceID,
29
// Stop workspace without grace period.
30
Policy: wsmanapi.StopWorkspacePolicy_IMMEDIATELY,
31
}
32
_, err := agent.wsman.StopWorkspace(context.Background(), req)
33
if err == nil {
34
return nil
35
}
36
37
log.WithError(err).WithField("instanceID", instanceID).Warn("error stopping workspace through ws-manager, killing supervisor directly")
38
return unix.Kill(supervisorPID, unix.SIGKILL)
39
}
40
41
// stopWorkspaceAndBlockUser stops a workspace and blocks the user (who would have guessed?)
42
func (agent *Smith) stopWorkspaceAndBlockUser(supervisorPID int, ownerID, workspaceID, instanceID string) error {
43
err := agent.stopWorkspace(supervisorPID, instanceID)
44
if err != nil {
45
log.WithError(err).WithField("owner", ownerID).WithField("workspaceID", workspaceID).Warn("error stopping workspace")
46
}
47
err = agent.blockUser(ownerID, workspaceID)
48
return err
49
}
50
51
func (agent *Smith) blockUser(ownerID, workspaceID string) error {
52
if agent.GitpodAPI == nil {
53
return xerrors.Errorf("not connected to Gitpod API")
54
}
55
56
if len(ownerID) == 0 {
57
return xerrors.Errorf("cannot block user as user id is empty")
58
}
59
60
log.Infof("Blocking user %s - workspace %v", ownerID, workspaceID)
61
62
req := protocol.AdminBlockUserRequest{
63
UserID: ownerID,
64
IsBlocked: true,
65
}
66
return agent.GitpodAPI.AdminBlockUser(context.Background(), &req)
67
}
68
69
func (agent *Smith) limitCPUUse(podname string) error {
70
if agent.Kubernetes == nil {
71
return xerrors.Errorf("not connected to Kubernetes - cannot limit CPU usage")
72
}
73
if agent.Config.Enforcement.CPULimitPenalty == "" {
74
return xerrors.Errorf("no CPU limit penalty specified - cannot limit CPU usage")
75
}
76
77
ctx := context.Background()
78
retry.RetryOnConflict(retry.DefaultBackoff, func() error {
79
pods := agent.Kubernetes.CoreV1().Pods(agent.Config.KubernetesNamespace)
80
pod, err := pods.Get(ctx, podname, corev1.GetOptions{})
81
if err != nil {
82
return err
83
}
84
85
pod.Annotations[wsk8s.WorkspaceCpuMinLimitAnnotation] = agent.Config.Enforcement.CPULimitPenalty
86
pod.Annotations[wsk8s.WorkspaceCpuBurstLimitAnnotation] = agent.Config.Enforcement.CPULimitPenalty
87
_, err = pods.Update(ctx, pod, corev1.UpdateOptions{})
88
if err != nil {
89
return err
90
}
91
92
return nil
93
})
94
95
return nil
96
}
97
98