alasio 8.0.0 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/src/api-server.js +18 -0
- package/dist/cli/src/api-server.js.map +1 -0
- package/dist/cli/src/branches.js +61 -20
- package/dist/cli/src/branches.js.map +1 -1
- package/dist/cli/src/cluster/docker.js +25 -10
- package/dist/cli/src/cluster/docker.js.map +1 -1
- package/dist/cli/src/cluster/host.js +33 -7
- package/dist/cli/src/cluster/host.js.map +1 -1
- package/dist/cli/src/cluster/k3s.js +43 -11
- package/dist/cli/src/cluster/k3s.js.map +1 -1
- package/dist/cli/src/cluster/node.js +107 -32
- package/dist/cli/src/cluster/node.js.map +1 -1
- package/dist/cli/src/cluster/stargz.js +55 -0
- package/dist/cli/src/cluster/stargz.js.map +1 -0
- package/dist/cli/src/commands/branch.js +5 -4
- package/dist/cli/src/commands/branch.js.map +1 -1
- package/dist/cli/src/commands/common.js +9 -3
- package/dist/cli/src/commands/common.js.map +1 -1
- package/dist/cli/src/commands/folder.js +14 -0
- package/dist/cli/src/commands/folder.js.map +1 -0
- package/dist/cli/src/commands/status.js +64 -12
- package/dist/cli/src/commands/status.js.map +1 -1
- package/dist/cli/src/commands/uninstall.js +8 -9
- package/dist/cli/src/commands/uninstall.js.map +1 -1
- package/dist/cli/src/commands/up.js +11 -3
- package/dist/cli/src/commands/up.js.map +1 -1
- package/dist/cli/src/commands/upgrade.js +1 -1
- package/dist/cli/src/commands/upgrade.js.map +1 -1
- package/dist/cli/src/commands.js +2 -1
- package/dist/cli/src/commands.js.map +1 -1
- package/dist/cli/src/config.js +4 -1
- package/dist/cli/src/config.js.map +1 -1
- package/dist/cli/src/cpu-baseline.js +8 -4
- package/dist/cli/src/cpu-baseline.js.map +1 -1
- package/dist/cli/src/folders.js +67 -0
- package/dist/cli/src/folders.js.map +1 -0
- package/dist/cli/src/gateway-calls.js +58 -0
- package/dist/cli/src/gateway-calls.js.map +1 -0
- package/dist/cli/src/install.js +77 -29
- package/dist/cli/src/install.js.map +1 -1
- package/dist/cli/src/kept-releases.js +27 -20
- package/dist/cli/src/kept-releases.js.map +1 -1
- package/dist/cli/src/kube/api.js +2 -3
- package/dist/cli/src/kube/api.js.map +1 -1
- package/dist/cli/src/kube/apply.js +15 -72
- package/dist/cli/src/kube/apply.js.map +1 -1
- package/dist/cli/src/kube/rollout.js +28 -16
- package/dist/cli/src/kube/rollout.js.map +1 -1
- package/dist/cli/src/manifests/admission.js +342 -223
- package/dist/cli/src/manifests/admission.js.map +1 -1
- package/dist/cli/src/manifests/alasio.js +58 -394
- package/dist/cli/src/manifests/alasio.js.map +1 -1
- package/dist/cli/src/manifests/branch.js +10 -26
- package/dist/cli/src/manifests/branch.js.map +1 -1
- package/dist/cli/src/manifests/collector.js +60 -44
- package/dist/cli/src/manifests/collector.js.map +1 -1
- package/dist/cli/src/manifests/common.js +32 -2
- package/dist/cli/src/manifests/common.js.map +1 -1
- package/dist/cli/src/manifests/config.js +64 -81
- package/dist/cli/src/manifests/config.js.map +1 -1
- package/dist/cli/src/manifests/disruption.js +10 -0
- package/dist/cli/src/manifests/disruption.js.map +1 -1
- package/dist/cli/src/manifests/folders.js +128 -0
- package/dist/cli/src/manifests/folders.js.map +1 -0
- package/dist/cli/src/manifests/grafana.js +4 -2
- package/dist/cli/src/manifests/grafana.js.map +1 -1
- package/dist/cli/src/manifests/index.js +10 -7
- package/dist/cli/src/manifests/index.js.map +1 -1
- package/dist/cli/src/manifests/lake.js +18 -4
- package/dist/cli/src/manifests/lake.js.map +1 -1
- package/dist/cli/src/manifests/log.js +32 -14
- package/dist/cli/src/manifests/log.js.map +1 -1
- package/dist/cli/src/manifests/neon.js +3 -3
- package/dist/cli/src/manifests/neon.js.map +1 -1
- package/dist/cli/src/manifests/network-policies.js +140 -74
- package/dist/cli/src/manifests/network-policies.js.map +1 -1
- package/dist/cli/src/manifests/node-agent.js +11 -4
- package/dist/cli/src/manifests/node-agent.js.map +1 -1
- package/dist/cli/src/manifests/object-store.js +4 -2
- package/dist/cli/src/manifests/object-store.js.map +1 -1
- package/dist/cli/src/manifests/sandbox-gateway.js +663 -0
- package/dist/cli/src/manifests/sandbox-gateway.js.map +1 -0
- package/dist/cli/src/manifests/scalers.js +16 -5
- package/dist/cli/src/manifests/scalers.js.map +1 -1
- package/dist/cli/src/manifests/sizing.js +16 -8
- package/dist/cli/src/manifests/sizing.js.map +1 -1
- package/dist/cli/src/manifests/valkey.js +11 -5
- package/dist/cli/src/manifests/valkey.js.map +1 -1
- package/dist/cli/src/manifests/vpa.js +3 -1
- package/dist/cli/src/manifests/vpa.js.map +1 -1
- package/dist/cli/src/manifests/workspace-storage.js +174 -89
- package/dist/cli/src/manifests/workspace-storage.js.map +1 -1
- package/dist/cli/src/neon-storage.js +54 -14
- package/dist/cli/src/neon-storage.js.map +1 -1
- package/dist/cli/src/release.js +9 -9
- package/dist/cluster/node/pins.json +9 -4
- package/dist/neon/control/branches.js +6 -6
- package/dist/neon/control/branches.js.map +1 -1
- package/dist/neon/control/secrets.js +14 -3
- package/dist/neon/control/secrets.js.map +1 -1
- package/dist/src/binder/names.js +33 -0
- package/dist/src/binder/names.js.map +1 -0
- package/dist/src/binder/tokens.js +58 -0
- package/dist/src/binder/tokens.js.map +1 -0
- package/dist/src/branch/names.js +12 -2
- package/dist/src/branch/names.js.map +1 -1
- package/dist/src/events/names.js +7 -0
- package/dist/src/events/names.js.map +1 -0
- package/dist/src/gateway/names.js +201 -0
- package/dist/src/gateway/names.js.map +1 -0
- package/dist/src/harness/names.js +49 -0
- package/dist/src/harness/names.js.map +1 -0
- package/dist/src/kube/sandbox-shape.js +8 -68
- package/dist/src/kube/sandbox-shape.js.map +1 -1
- package/dist/src/node-agent/names.js +52 -2
- package/dist/src/node-agent/names.js.map +1 -1
- package/dist/src/sandbox/names.js +12 -20
- package/dist/src/sandbox/names.js.map +1 -1
- package/dist/src/sandbox/otlp-resource.js +173 -0
- package/dist/src/sandbox/otlp-resource.js.map +1 -0
- package/dist/src/sandbox/telemetry.js +43 -0
- package/dist/src/sandbox/telemetry.js.map +1 -0
- package/dist/src/telemetry/config.js +131 -0
- package/dist/src/telemetry/config.js.map +1 -0
- package/dist/src/telemetry/forward.js +154 -0
- package/dist/src/telemetry/forward.js.map +1 -0
- package/package.json +1 -1
- package/dist/cli/src/manifests/agent-sandbox.js +0 -92
- package/dist/cli/src/manifests/agent-sandbox.js.map +0 -1
- package/dist/cli/src/manifests/juicefs-csi.js +0 -320
- package/dist/cli/src/manifests/juicefs-csi.js.map +0 -1
- package/dist/cli/src/manifests/sandboxes.agents.x-k8s.io.json +0 -6295
- package/dist/src/kube/config.js +0 -145
- package/dist/src/kube/config.js.map +0 -1
|
@@ -1,283 +1,37 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* namespaces its workspaces run in, its identity in them, and the templates it makes
|
|
4
|
-
* its workspaces' Sandboxes from (src/kube/config.ts); main's, or a branch environment's
|
|
5
|
-
* in its own namespaces (./branch.ts), and main's Service of the forks it makes for them.
|
|
6
|
-
*/
|
|
7
|
-
import { isDeepStrictEqual } from "node:util";
|
|
8
|
-
import { Result } from "effect";
|
|
9
|
-
import { BRANCH_FORK_PORT, branchSessionsNamespace } from "../../../src/branch/names.js";
|
|
10
|
-
import { decodeKubeTemplates } from "../../../src/kube/config.js";
|
|
11
|
-
import { BAYMA_STOP_SECONDS, CPU_FEATURES_ANNOTATION, STOP_WAIT_ARG } from "../../../src/kube/sandbox-shape.js";
|
|
12
|
-
import { gvisorRuntimeClass, NODE_AGENT_PORT, NODE_AGENT_TOKEN_VARIABLE } from "../../../src/node-agent/names.js";
|
|
1
|
+
import { BRANCH_FORK_PORT, BRANCH_PARENT_LABEL, branchSessionsNamespace, MAIN_ENVIRONMENT_NAME } from "../../../src/branch/names.js";
|
|
2
|
+
import { ALASIO_GATEWAY_CALLER_KEY_VARIABLE, ALASIO_GATEWAY_ENVIRONMENT_VARIABLE, ALASIO_GATEWAY_FOLDERS_VARIABLE, ALASIO_GATEWAY_URL_VARIABLE } from "../../../src/gateway/names.js";
|
|
13
3
|
import { gvisorReleases, NODE_PINS } from "../cluster/node.js";
|
|
14
4
|
import { imageReference } from "../images.js";
|
|
15
|
-
import {
|
|
5
|
+
import { busyLabelPolicy } from "./admission.js";
|
|
6
|
+
import { foldersRun } from "./folders.js";
|
|
7
|
+
import { carriedPools, GATEWAY, GATEWAY_PORT, sandboxServiceRuns } from "./sandbox-gateway.js";
|
|
16
8
|
import { alasioGroup, environmentLogSecret, environmentName, lakeWakeTopic, LOG_BROKERS, telegramTopic } from "./log.js";
|
|
17
|
-
import { BRANCH_FORK_SECRET, BRANCH_LABEL, componentName, databaseSecret, envOf, given,
|
|
9
|
+
import { BRANCH_FORK_SECRET, BRANCH_LABEL, componentName, databaseSecret, envOf, given, hostVolumeMounts, hostVolumes, imagePullSecrets, labels, lakeRuns, MAIN_ENVIRONMENT, NAMESPACE, ONE, otelEnv, RELEASE, replicasOf, restrictedContainer, restrictedPod, roleVerifiers, selectorLabels, SESSIONS_CALLER_SECRET, } from "./common.js";
|
|
18
10
|
import { durationSeconds } from "./config.js";
|
|
19
11
|
import { busyBudget } from "./disruption.js";
|
|
20
12
|
import { priority } from "./priorities.js";
|
|
21
13
|
import { verticalPodAutoscaler } from "./sizing.js";
|
|
22
|
-
import { cloneJob } from "./workspace-storage.js";
|
|
23
|
-
/** The port every workspace's bayma serves MCP on. */
|
|
24
|
-
const BAYMA_PORT = 7290;
|
|
25
14
|
/** The namespace of the sessions of the alasio of `environment`: the configured one, or a branch environment's own. */
|
|
26
15
|
export function sessionsNamespace(config, { branch }) {
|
|
27
16
|
return branch ? branchSessionsNamespace(branch) : config.sessions.namespace;
|
|
28
17
|
}
|
|
29
|
-
/** The namespaces whose Sandboxes alasio drives: the sessions', and the host profile's. */
|
|
30
|
-
function workspaceNamespaces(config, environment) {
|
|
31
|
-
return [...(config.sessions.enabled ? [sessionsNamespace(config, environment)] : []), ...(config.host.enabled ? [config.host.namespace] : [])];
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* The template of session filesystems' Sandboxes: an empty, isolated workspace under
|
|
35
|
-
* the sessions' runtime, restricted, on a volume of workspace storage's class when it is
|
|
36
|
-
* on. alasio adds what is per Sandbox: its name and labels, bayma's token, and its
|
|
37
|
-
* network mode. A branch environment's are in its own namespace, and neither clones a
|
|
38
|
-
* session (its parent does, src/branch/fork.ts) nor removes JuiceFS's mount pods, which
|
|
39
|
-
* are main's to drive.
|
|
40
|
-
*/
|
|
41
|
-
function sessionsProfile(config, environment, { cpuBaseline, gvisorReleases }) {
|
|
42
|
-
const { sessions, workspaceStorage } = config;
|
|
43
|
-
const main = environment.branch === null;
|
|
44
|
-
// Snapshotted once every node's CPU features are known, its sandboxes held to those all have.
|
|
45
|
-
const snapshotted = main && nodeAgentRuns(config) && cpuBaseline !== null;
|
|
46
|
-
const agent = imageReference(config.images.agent);
|
|
47
|
-
const storageClassName = sessions.storage.storageClassName || (workspaceStorage.enabled ? workspaceStorage.storageClassName : "");
|
|
48
|
-
// On workspace storage, the volume's mounts follow its mount pod's, as upstream's
|
|
49
|
-
// template has them (gVisor does not, and alasio restarts a session whose mount is
|
|
50
|
-
// gone), and its files are given the pod's group only when its root is not the group's,
|
|
51
|
-
// as walking a JuiceFS volume is slow.
|
|
52
|
-
const propagation = workspaceStorage.enabled ? { mountPropagation: "HostToContainer" } : {};
|
|
53
|
-
const ownership = workspaceStorage.enabled ? { fsGroupChangePolicy: "OnRootMismatch" } : {};
|
|
54
|
-
return {
|
|
55
|
-
namespace: sessionsNamespace(config, environment),
|
|
56
|
-
port: BAYMA_PORT,
|
|
57
|
-
workspaceDir: "/workspace",
|
|
58
|
-
egressGate: sessions.egressGate,
|
|
59
|
-
fullModeNameservers: [...sessions.fullModeNameservers],
|
|
60
|
-
...(main && mountPodsRemoved(config) ? { mountPodNamespace: workspaceStorage.csi.namespace } : {}),
|
|
61
|
-
podTemplate: {
|
|
62
|
-
metadata: {
|
|
63
|
-
labels: { "app.kubernetes.io/part-of": "alasio", "app.kubernetes.io/instance": RELEASE, "app.kubernetes.io/component": "session" },
|
|
64
|
-
// Under gVisor, /tmp is a tmpfs of the sandbox's own, by gVisor's mount hints, rather
|
|
65
|
-
// than the emptyDir's directory on the node: a snapshot of the sandbox holds it, as it
|
|
66
|
-
// holds the files that bayma's runtimes keep open there.
|
|
67
|
-
annotations: {
|
|
68
|
-
"dev.gvisor.spec.mount.tmp.share": "container",
|
|
69
|
-
"dev.gvisor.spec.mount.tmp.type": "tmpfs",
|
|
70
|
-
"dev.gvisor.spec.mount.tmp.options": "rw",
|
|
71
|
-
...(snapshotted ? { [CPU_FEATURES_ANNOTATION]: cpuBaseline.join(",") } : {}),
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
spec: {
|
|
75
|
-
...(sessions.runtimeClassName ? { runtimeClassName: sessions.runtimeClassName } : {}),
|
|
76
|
-
...priority("turn"),
|
|
77
|
-
// A pod that ends is ended: alasio brings the session up in a new one, and nothing
|
|
78
|
-
// starts bayma again in a sandbox that a snapshot has just ended.
|
|
79
|
-
restartPolicy: "Never",
|
|
80
|
-
// Ended by other than alasio, bayma holds its stop for alasio's snapshot, then stops.
|
|
81
|
-
...(snapshotted ? { terminationGracePeriodSeconds: stopWaitSeconds(config) + BAYMA_STOP_SECONDS } : {}),
|
|
82
|
-
securityContext: { ...restrictedPod(1000, 1000), ...ownership },
|
|
83
|
-
...imagePullSecrets(config),
|
|
84
|
-
...given("nodeSelector", { ...sessions.nodeSelector }),
|
|
85
|
-
...given("tolerations", [...sessions.tolerations]),
|
|
86
|
-
initContainers: [
|
|
87
|
-
// The workspace and home on the session's volume, and bayma's toolbelt, which the
|
|
88
|
-
// image installs, linked into the home.
|
|
89
|
-
{
|
|
90
|
-
name: "prepare",
|
|
91
|
-
image: agent,
|
|
92
|
-
imagePullPolicy: config.images.pullPolicy,
|
|
93
|
-
command: [
|
|
94
|
-
"/bin/sh",
|
|
95
|
-
"-c",
|
|
96
|
-
"mkdir -p /data/workspace /data/home/.local/share/bayma && ln -sfn /opt/bayma-data/bayma/toolbelt /data/home/.local/share/bayma/toolbelt",
|
|
97
|
-
],
|
|
98
|
-
securityContext: restrictedContainer(),
|
|
99
|
-
...helperResources(),
|
|
100
|
-
volumeMounts: [{ name: "data", mountPath: "/data" }],
|
|
101
|
-
},
|
|
102
|
-
],
|
|
103
|
-
containers: [{
|
|
104
|
-
name: "bayma",
|
|
105
|
-
image: agent,
|
|
106
|
-
imagePullPolicy: config.images.pullPolicy,
|
|
107
|
-
command: ["/usr/bin/tini", "-s", "--", "node", "/opt/bayma/bayma.js"],
|
|
108
|
-
args: [
|
|
109
|
-
"mcp-http",
|
|
110
|
-
"--host",
|
|
111
|
-
"0.0.0.0",
|
|
112
|
-
"--port",
|
|
113
|
-
String(BAYMA_PORT),
|
|
114
|
-
"--state-dir",
|
|
115
|
-
"/home/agent/.bayma",
|
|
116
|
-
...(snapshotted ? [STOP_WAIT_ARG, String(stopWaitSeconds(config) * 1000)] : []),
|
|
117
|
-
],
|
|
118
|
-
workingDir: "/workspace",
|
|
119
|
-
env: [
|
|
120
|
-
{ name: "HOME", value: "/home/agent" },
|
|
121
|
-
{ name: "USER", value: "agent" },
|
|
122
|
-
{ name: "BAYMA_PAYLOAD_DIR", value: "/opt/bayma/payload" },
|
|
123
|
-
],
|
|
124
|
-
ports: [{ name: "mcp", containerPort: BAYMA_PORT }],
|
|
125
|
-
securityContext: restrictedContainer(),
|
|
126
|
-
resources: sessions.resources,
|
|
127
|
-
volumeMounts: [
|
|
128
|
-
{ name: "data", mountPath: "/workspace", subPath: "workspace", ...propagation },
|
|
129
|
-
{ name: "data", mountPath: "/home/agent", subPath: "home", ...propagation },
|
|
130
|
-
{ name: "tmp", mountPath: "/tmp" },
|
|
131
|
-
],
|
|
132
|
-
}],
|
|
133
|
-
volumes: [{ name: "tmp", emptyDir: { sizeLimit: "2Gi" } }],
|
|
134
|
-
},
|
|
135
|
-
},
|
|
136
|
-
volumeClaimTemplates: [{
|
|
137
|
-
metadata: { name: "data" },
|
|
138
|
-
spec: {
|
|
139
|
-
accessModes: ["ReadWriteOnce"],
|
|
140
|
-
...(storageClassName ? { storageClassName } : {}),
|
|
141
|
-
resources: { requests: { storage: sessions.storage.size } },
|
|
142
|
-
},
|
|
143
|
-
}],
|
|
144
|
-
...(main && sessionsForked(config) ? { clone: { claimTemplate: "data", job: cloneJob(config) } } : {}),
|
|
145
|
-
...(snapshotted ? { snapshots: sessionSnapshots(config, gvisorReleases) } : {}),
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
18
|
/** How long a session's bayma holds a stop alasio did not make (sessions.snapshots.stopWait). */
|
|
149
|
-
function stopWaitSeconds(config) {
|
|
19
|
+
export function stopWaitSeconds(config) {
|
|
150
20
|
// A duration, as the configuration checks it.
|
|
151
21
|
return durationSeconds(config.sessions.snapshots.stopWait) ?? 0;
|
|
152
22
|
}
|
|
153
|
-
/**
|
|
154
|
-
|
|
155
|
-
* where the node agents run: once sessions.snapshots.releaseAfter has passed without an
|
|
156
|
-
* exec or a turn, live every sessions.snapshots.liveEvery while execs run, and as their
|
|
157
|
-
* pods are ended by other than alasio, within sessions.snapshots.stopWait, under the
|
|
158
|
-
* gVisor `releases` alasio keeps (../kept-releases.ts), the
|
|
159
|
-
* current one first, each restored with a RuntimeClass of its own, by the agents in
|
|
160
|
-
* alasio's namespace.
|
|
161
|
-
*/
|
|
162
|
-
function sessionSnapshots(config, releases) {
|
|
163
|
-
return {
|
|
164
|
-
// A duration, as the configuration checks it.
|
|
165
|
-
releaseAfterSeconds: durationSeconds(config.sessions.snapshots.releaseAfter) ?? 0,
|
|
166
|
-
liveEverySeconds: durationSeconds(config.sessions.snapshots.liveEvery) ?? 0,
|
|
167
|
-
releases: releases.map((release) => ({ release, runtimeClassName: gvisorRuntimeClass(release) })),
|
|
168
|
-
agents: {
|
|
169
|
-
namespace: NAMESPACE,
|
|
170
|
-
selector: Object.entries(selectorLabels("node-agent")).map(([label, value]) => `${label}=${value}`).join(","),
|
|
171
|
-
port: NODE_AGENT_PORT,
|
|
172
|
-
},
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
/** Whether alasio forks sessions: where their volumes are workspace storage's, which JuiceFS clones. */
|
|
176
|
-
export function sessionsForked({ sessions, workspaceStorage }) {
|
|
177
|
-
return workspaceStorage.enabled && [workspaceStorage.storageClassName, ""].includes(sessions.storage.storageClassName);
|
|
178
|
-
}
|
|
179
|
-
/** The template of folder workspaces' bayma: bayma itself, as the operator, with the machine's mounts. */
|
|
180
|
-
function hostProfile(config) {
|
|
181
|
-
const { host } = config;
|
|
182
|
-
return {
|
|
183
|
-
namespace: host.namespace,
|
|
184
|
-
port: BAYMA_PORT,
|
|
185
|
-
stateRoot: host.stateRoot,
|
|
186
|
-
podTemplate: {
|
|
187
|
-
metadata: { labels: { "app.kubernetes.io/part-of": "alasio", "app.kubernetes.io/instance": RELEASE, "app.kubernetes.io/component": "folder-bayma" } },
|
|
188
|
-
spec: {
|
|
189
|
-
// May restart alasio, by rolling out its Deployment, as an agent restarts it.
|
|
190
|
-
serviceAccountName: componentName("host-agent"),
|
|
191
|
-
...priority("turn"),
|
|
192
|
-
securityContext: {
|
|
193
|
-
runAsUser: host.uid,
|
|
194
|
-
runAsGroup: host.gid,
|
|
195
|
-
// The group the bayma token's Secret volume is given, which the operator's user
|
|
196
|
-
// reads it as; the node's own paths the mounts give are left as they are.
|
|
197
|
-
fsGroup: host.gid,
|
|
198
|
-
...given("supplementalGroups", [...host.supplementalGroups]),
|
|
199
|
-
},
|
|
200
|
-
...imagePullSecrets(config),
|
|
201
|
-
containers: [{
|
|
202
|
-
name: "bayma",
|
|
203
|
-
image: imageReference(host.baymaImage),
|
|
204
|
-
imagePullPolicy: "IfNotPresent",
|
|
205
|
-
args: ["mcp-http", "--host", "0.0.0.0", "--port", String(BAYMA_PORT), "--default-durability", "checkpointed"],
|
|
206
|
-
workingDir: host.home,
|
|
207
|
-
env: [{ name: "HOME", value: host.home }, ...envOf(host.env)],
|
|
208
|
-
ports: [{ name: "mcp", containerPort: BAYMA_PORT }],
|
|
209
|
-
securityContext: {
|
|
210
|
-
// What bayma needs to snapshot its REPL sessions' processes as it stops and
|
|
211
|
-
// restore them whole as it starts again.
|
|
212
|
-
capabilities: { add: ["CHECKPOINT_RESTORE", "SYS_PTRACE"] },
|
|
213
|
-
seccompProfile: { type: "Unconfined" },
|
|
214
|
-
appArmorProfile: { type: "Unconfined" },
|
|
215
|
-
},
|
|
216
|
-
resources: host.resources,
|
|
217
|
-
...given("volumeMounts", hostVolumeMounts(config)),
|
|
218
|
-
}],
|
|
219
|
-
...given("volumes", hostVolumes(config)),
|
|
220
|
-
},
|
|
221
|
-
},
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
/** What a cluster keeps where up has found nothing of it yet: no baseline, the releases pinned, and no bot. */
|
|
225
|
-
export const NOTHING_KEPT = { cpuBaseline: null, gvisorReleases: gvisorReleases(NODE_PINS), botChecksum: null };
|
|
23
|
+
/** What a cluster keeps where up has found nothing of it yet: no baseline, the releases pinned, no bot, no API server known, and none of the mount's Services. */
|
|
24
|
+
export const NOTHING_KEPT = { cpuBaseline: null, gvisorReleases: gvisorReleases(NODE_PINS), botChecksum: null, apiServer: null, mountServices: {} };
|
|
226
25
|
/** Nothing carried forward: a first installation's, and a branch environment's. */
|
|
227
|
-
export const NOTHING_CARRIED = {
|
|
228
|
-
/** The ConfigMap of the templates, by its name. */
|
|
229
|
-
export const SANDBOX_TEMPLATES = componentName("sandbox-templates");
|
|
26
|
+
export const NOTHING_CARRIED = { previousPools: { none: null, full: null }, ...NOTHING_KEPT };
|
|
230
27
|
/**
|
|
231
28
|
* What the installation `config` describes, with what the cluster keeps, `kept`, carries
|
|
232
|
-
* forward from `
|
|
233
|
-
* `
|
|
234
|
-
*
|
|
235
|
-
* template, and no more. Pure, for tests.
|
|
236
|
-
*
|
|
237
|
-
* What it carries is pinned whole into the Sandbox policy (./admission.ts) as a template
|
|
238
|
-
* alasio may make a Sandbox from, read back from the cluster rather than rendered from the
|
|
239
|
-
* config: the ConfigMap is the anchor of that trust. It is one as long as only the
|
|
240
|
-
* operator, by `alasio up`, writes it: alasio's ServiceAccount may write no ConfigMap
|
|
241
|
-
* (./alasio.ts identity). Were alasio given that, it could write any pod template into
|
|
242
|
-
* the ConfigMap, and the next `up` would let it make Sandboxes of it.
|
|
243
|
-
*/
|
|
244
|
-
export function carriedFrom(config, live, kept) {
|
|
245
|
-
const nothing = { ...NOTHING_CARRIED, ...kept };
|
|
246
|
-
if (!config.sessions.enabled || live === undefined)
|
|
247
|
-
return nothing;
|
|
248
|
-
// Carried as the ConfigMap held them, which alasio read as they are: the profile a snapshot recorded the hash of.
|
|
249
|
-
if (Result.isFailure(decodeKubeTemplates(SANDBOX_TEMPLATES, live)))
|
|
250
|
-
return nothing;
|
|
251
|
-
const held = JSON.parse(live);
|
|
252
|
-
if (!held.sessions)
|
|
253
|
-
return nothing;
|
|
254
|
-
// The current profile as the ConfigMap holds it, to compare with what it held.
|
|
255
|
-
const current = JSON.parse(goJson(sessionsProfile(config, MAIN_ENVIRONMENT, kept), ""));
|
|
256
|
-
return { previousSessions: isDeepStrictEqual(held.sessions.podTemplate, current.podTemplate) ? (held.previousSessions ?? null) : held.sessions, ...kept };
|
|
257
|
-
}
|
|
258
|
-
/**
|
|
259
|
-
* The CPU baseline the installation whose templates are `live` (as carriedFrom takes
|
|
260
|
-
* them) holds sessions to: what its sessions' template sets, if anything.
|
|
29
|
+
* forward from `liveGateway`, the sandbox gateway's configuration of the installation it
|
|
30
|
+
* replaces (its ConfigMap's `config.json`, if it has one): its pools' templates before the
|
|
31
|
+
* current ones (./sandbox-gateway.ts carriedPools). Pure, for tests.
|
|
261
32
|
*/
|
|
262
|
-
export function
|
|
263
|
-
|
|
264
|
-
return null;
|
|
265
|
-
const held = JSON.parse(live);
|
|
266
|
-
const recorded = held.sessions?.podTemplate.metadata?.annotations?.[CPU_FEATURES_ANNOTATION];
|
|
267
|
-
return recorded ? recorded.split(",") : null;
|
|
268
|
-
}
|
|
269
|
-
/** The ConfigMap of the templates, and their checksum, which alasio's pod carries so it is replaced when they change. */
|
|
270
|
-
function sandboxTemplates(config, environment, carried) {
|
|
271
|
-
const name = SANDBOX_TEMPLATES;
|
|
272
|
-
const templates = goJson({
|
|
273
|
-
...(config.sessions.enabled ? { sessions: sessionsProfile(config, environment, carried) } : {}),
|
|
274
|
-
...(config.sessions.enabled && carried.previousSessions ? { previousSessions: carried.previousSessions } : {}),
|
|
275
|
-
...(config.host.enabled ? { host: hostProfile(config) } : {}),
|
|
276
|
-
}, " ");
|
|
277
|
-
return {
|
|
278
|
-
configMap: { apiVersion: "v1", kind: "ConfigMap", metadata: { name, namespace: environment.namespace, labels: labels("alasio") }, data: { "templates.json": templates } },
|
|
279
|
-
checksum: sha256(templates),
|
|
280
|
-
};
|
|
33
|
+
export function carriedFrom(config, kept, liveGateway) {
|
|
34
|
+
return { ...kept, previousPools: carriedPools(config, liveGateway, kept) };
|
|
281
35
|
}
|
|
282
36
|
/** Where alasio's Secrets of branch environments are mounted: main's key, or a branch's token. */
|
|
283
37
|
const BRANCH_SECRETS = "/run/alasio/branch";
|
|
@@ -303,9 +57,9 @@ function branchSecretVolume(config, { branch }) {
|
|
|
303
57
|
return [{ name: "branch", secret: { secretName: BRANCH_FORK_SECRET, items: [{ key: "token", path: "token" }] } }];
|
|
304
58
|
return forksForBranches(config) ? [{ name: "branch", secret: { secretName: componentName("branches"), items: [{ key: "fork-key", path: "fork-key" }], optional: true } }] : [];
|
|
305
59
|
}
|
|
306
|
-
/** Whether main forks its sessions for branch environments: where it has Neon to branch, and
|
|
60
|
+
/** Whether main forks its sessions for branch environments: where it has Neon to branch, and the sandbox service, whose node agents clone them. */
|
|
307
61
|
export function forksForBranches(config) {
|
|
308
|
-
return config.neon.enabled &&
|
|
62
|
+
return config.neon.enabled && sandboxServiceRuns(config);
|
|
309
63
|
}
|
|
310
64
|
/**
|
|
311
65
|
* The roles main's alasio makes for what reads its Neon beside it (common.ts
|
|
@@ -319,7 +73,6 @@ function readerRoles(config, { branch }) {
|
|
|
319
73
|
function alasioEnv(config, home, operatorHome, environment) {
|
|
320
74
|
const { alasio, host } = config;
|
|
321
75
|
return [
|
|
322
|
-
{ name: "ALASIO_KUBE_TEMPLATES", value: "/etc/alasio/templates.json" },
|
|
323
76
|
{ name: "ALASIO_STATE_DIR", value: "/var/lib/alasio/state" },
|
|
324
77
|
{ name: "HOME", value: home },
|
|
325
78
|
// A home of alasio's own does not outlast its pod; the operator's keeps their login.
|
|
@@ -331,6 +84,7 @@ function alasioEnv(config, home, operatorHome, environment) {
|
|
|
331
84
|
{ name: "TELEGRAM_ALLOWED_USER_IDS", valueFrom: { secretKeyRef: { name: alasio.telegram.existingSecret, key: "allowedUserIds" } } },
|
|
332
85
|
{ name: "ALASIO_DATABASE_URL_FILE", value: "/run/alasio/database/url" },
|
|
333
86
|
{ name: "ALASIO_LAKE_VERIFIER_FILE", value: "/run/alasio/database/lake-verifier" },
|
|
87
|
+
{ name: "ALASIO_HARNESS_VERIFIER_FILE", value: "/run/alasio/database/harness-verifier" },
|
|
334
88
|
...readerRoles(config, environment).map(({ key, variable }) => ({ name: variable, value: `/run/alasio/database/${key}` })),
|
|
335
89
|
{ name: "ALASIO_LAKE_ENABLED", value: config.lake.enabled && config.neon.enabled ? "1" : "0" },
|
|
336
90
|
// Its Telegram updates: its environment's topic, read in its group as its principal.
|
|
@@ -341,17 +95,21 @@ function alasioEnv(config, home, operatorHome, environment) {
|
|
|
341
95
|
{ name: "ALASIO_TELEGRAM_GROUP", value: alasioGroup(environmentName(environment)) },
|
|
342
96
|
// Its environment's wake topic, which it tells the lake's loader of each transcript it writes on, as that principal.
|
|
343
97
|
...(lakeRuns(config) ? [{ name: "ALASIO_LAKE_WAKE_TOPIC", value: lakeWakeTopic(environmentName(environment)) }] : []),
|
|
344
|
-
{ name: "ALASIO_TELEMETRY_RECEIVER_SERVICE", value: `${componentName("telemetry")}.${environment.namespace}.svc` },
|
|
345
|
-
{ name: "ALASIO_TELEMETRY_RECEIVER_PORT", value: String(config.telemetry.receiverPort) },
|
|
346
98
|
...(alasio.defaultHarness ? [{ name: "ALASIO_DEFAULT_HARNESS", value: alasio.defaultHarness }] : []),
|
|
347
99
|
...(host.enabled && host.workspaceRoot ? [{ name: "ALASIO_WORKSPACE_ROOT", value: host.workspaceRoot }] : []),
|
|
348
100
|
...(alasio.claude.existingSecret
|
|
349
101
|
? [{ name: "CLAUDE_CODE_OAUTH_TOKEN", valueFrom: { secretKeyRef: { name: alasio.claude.existingSecret, key: alasio.claude.key } } }]
|
|
350
102
|
: []),
|
|
351
|
-
//
|
|
352
|
-
...(
|
|
353
|
-
? [
|
|
103
|
+
// Its environment's sessions, through the sandbox gateway, by its environment's own key of the gateway's.
|
|
104
|
+
...(sandboxServiceRuns(config)
|
|
105
|
+
? [
|
|
106
|
+
{ name: ALASIO_GATEWAY_URL_VARIABLE, value: `http://${GATEWAY}.${NAMESPACE}.svc.cluster.local:${GATEWAY_PORT}` },
|
|
107
|
+
{ name: ALASIO_GATEWAY_ENVIRONMENT_VARIABLE, value: environmentName(environment) },
|
|
108
|
+
{ name: ALASIO_GATEWAY_CALLER_KEY_VARIABLE, valueFrom: { secretKeyRef: { name: SESSIONS_CALLER_SECRET, key: "caller-key" } } },
|
|
109
|
+
]
|
|
354
110
|
: []),
|
|
111
|
+
// Main's folder workspaces, the gateway's folder instances, where the host profile renders them.
|
|
112
|
+
...(environment.branch === null && foldersRun(config) ? [{ name: ALASIO_GATEWAY_FOLDERS_VARIABLE, value: "1" }] : []),
|
|
355
113
|
...branchEnv(config, environment),
|
|
356
114
|
...otelEnv(config, environment),
|
|
357
115
|
...envOf(alasio.env),
|
|
@@ -367,10 +125,10 @@ function alasioEnv(config, home, operatorHome, environment) {
|
|
|
367
125
|
* branch environment's runs in its namespace on the branch's database, told it is the
|
|
368
126
|
* branch, with its token to ask main to fork the sessions it inherited; main's is given
|
|
369
127
|
* the key branch environments' tokens are signed with, where it forks sessions. Its pod
|
|
370
|
-
* carries
|
|
371
|
-
*
|
|
128
|
+
* carries, where up read it, the checksum of its bot's Secret, so it is replaced when it
|
|
129
|
+
* changes.
|
|
372
130
|
*/
|
|
373
|
-
function deployment(config,
|
|
131
|
+
function deployment(config, botChecksum, environment) {
|
|
374
132
|
const { alasio, host } = config;
|
|
375
133
|
const operatorHome = host.enabled && host.alasioHome;
|
|
376
134
|
const home = operatorHome ? host.home : "/var/lib/alasio/home";
|
|
@@ -390,7 +148,7 @@ function deployment(config, templatesChecksum, botChecksum, environment) {
|
|
|
390
148
|
template: {
|
|
391
149
|
metadata: {
|
|
392
150
|
labels: labels("alasio"),
|
|
393
|
-
|
|
151
|
+
...(botChecksum === null ? {} : { annotations: { "checksum/telegram": botChecksum } }),
|
|
394
152
|
},
|
|
395
153
|
spec: {
|
|
396
154
|
serviceAccountName: RELEASE,
|
|
@@ -406,16 +164,12 @@ function deployment(config, templatesChecksum, botChecksum, environment) {
|
|
|
406
164
|
workingDir: home,
|
|
407
165
|
env: alasioEnv(config, home, operatorHome, environment),
|
|
408
166
|
...given("envFrom", [...alasio.envFrom]),
|
|
409
|
-
ports: [
|
|
410
|
-
{ name: "telemetry", containerPort: config.telemetry.receiverPort },
|
|
411
|
-
...(environment.branch === null && forksForBranches(config) ? [{ name: "branch-forks", containerPort: BRANCH_FORK_PORT }] : []),
|
|
412
|
-
],
|
|
167
|
+
...(environment.branch === null && forksForBranches(config) ? { ports: [{ name: "branch-forks", containerPort: BRANCH_FORK_PORT }] } : {}),
|
|
413
168
|
securityContext: restrictedContainer(),
|
|
414
169
|
resources: alasio.resources,
|
|
415
170
|
volumeMounts: [
|
|
416
171
|
{ name: "state", mountPath: "/var/lib/alasio/state" },
|
|
417
172
|
...(operatorHome ? [] : [{ name: "alasio-home", mountPath: home }]),
|
|
418
|
-
{ name: "templates", mountPath: "/etc/alasio", readOnly: true },
|
|
419
173
|
{ name: "database", mountPath: "/run/alasio/database", readOnly: true },
|
|
420
174
|
{ name: "log", mountPath: "/run/alasio/log", readOnly: true },
|
|
421
175
|
...branchSecret.map(({ name }) => ({ name, mountPath: BRANCH_SECRETS, readOnly: true })),
|
|
@@ -425,12 +179,11 @@ function deployment(config, templatesChecksum, botChecksum, environment) {
|
|
|
425
179
|
volumes: [
|
|
426
180
|
{ name: "state", emptyDir: {} },
|
|
427
181
|
...(operatorHome ? [] : [{ name: "alasio-home", emptyDir: {} }]),
|
|
428
|
-
{ name: "templates", configMap: { name: componentName("sandbox-templates") } },
|
|
429
182
|
{
|
|
430
183
|
name: "database",
|
|
431
184
|
secret: {
|
|
432
185
|
secretName: databaseSecret(config),
|
|
433
|
-
items: ["url", "lake-verifier", ...readerRoles(config, environment).map(({ key }) => key)].map((key) => ({ key, path: key })),
|
|
186
|
+
items: ["url", "lake-verifier", "harness-verifier", ...readerRoles(config, environment).map(({ key }) => key)].map((key) => ({ key, path: key })),
|
|
434
187
|
},
|
|
435
188
|
},
|
|
436
189
|
{ name: "log", secret: { secretName: environmentLogSecret(environment), items: [{ key: "password", path: "password" }] } },
|
|
@@ -445,15 +198,6 @@ function deployment(config, templatesChecksum, botChecksum, environment) {
|
|
|
445
198
|
},
|
|
446
199
|
};
|
|
447
200
|
}
|
|
448
|
-
/** Where session sandboxes export their telemetry: alasio's receiver. */
|
|
449
|
-
function telemetryService(config, environment) {
|
|
450
|
-
return {
|
|
451
|
-
apiVersion: "v1",
|
|
452
|
-
kind: "Service",
|
|
453
|
-
metadata: { name: componentName("telemetry"), namespace: environment.namespace, labels: labels("alasio") },
|
|
454
|
-
spec: { selector: selectorLabels("alasio"), ports: [{ name: "otlp-http", port: config.telemetry.receiverPort, targetPort: "telemetry" }] },
|
|
455
|
-
};
|
|
456
|
-
}
|
|
457
201
|
/** Where branch environments ask main to fork the sessions they inherited (src/branch/fork.ts). */
|
|
458
202
|
function branchForksService() {
|
|
459
203
|
return {
|
|
@@ -466,8 +210,13 @@ function branchForksService() {
|
|
|
466
210
|
/**
|
|
467
211
|
* The namespaces workspaces run in, which alasio makes unless told not to. Sessions'
|
|
468
212
|
* enforces Pod Security "restricted": nothing privileged, no host paths, no added
|
|
469
|
-
* capabilities
|
|
470
|
-
*
|
|
213
|
+
* capabilities; but where the sandbox service runs, whose pools' pods mount their own
|
|
214
|
+
* directories on their nodes, a host path no level but "privileged" allows, it enforces that
|
|
215
|
+
* and warns and audits of "restricted", the sandbox pods' policy holding every pod of it to the
|
|
216
|
+
* pools' templates instead (./admission.ts sandboxPodPolicy). The host profile's is
|
|
217
|
+
* "privileged", as its pods mount the machine. A branch environment always has its own,
|
|
218
|
+
* beside its own namespace, which records the environment it was branched from, main's
|
|
219
|
+
* (BRANCH_PARENT_LABEL), as the sandbox gateway forks main's sessions into it for that alone.
|
|
471
220
|
*/
|
|
472
221
|
function namespaces(config, environment) {
|
|
473
222
|
const { sessions, host } = config;
|
|
@@ -484,9 +233,12 @@ function namespaces(config, environment) {
|
|
|
484
233
|
labels: {
|
|
485
234
|
...labels("session"),
|
|
486
235
|
...branched,
|
|
487
|
-
|
|
488
|
-
|
|
236
|
+
...(branch ? { [BRANCH_PARENT_LABEL]: MAIN_ENVIRONMENT_NAME } : {}),
|
|
237
|
+
...(sandboxServiceRuns(config)
|
|
238
|
+
? { "pod-security.kubernetes.io/enforce": "privileged", "pod-security.kubernetes.io/audit": "restricted", "pod-security.kubernetes.io/audit-version": "latest" }
|
|
239
|
+
: { "pod-security.kubernetes.io/enforce": "restricted", "pod-security.kubernetes.io/enforce-version": "latest" }),
|
|
489
240
|
"pod-security.kubernetes.io/warn": "restricted",
|
|
241
|
+
"pod-security.kubernetes.io/warn-version": "latest",
|
|
490
242
|
},
|
|
491
243
|
},
|
|
492
244
|
}]
|
|
@@ -501,97 +253,22 @@ function namespaces(config, environment) {
|
|
|
501
253
|
];
|
|
502
254
|
}
|
|
503
255
|
/**
|
|
504
|
-
*
|
|
505
|
-
*
|
|
506
|
-
*
|
|
507
|
-
*/
|
|
508
|
-
function mountPodsRemoved({ workspaceStorage }) {
|
|
509
|
-
return workspaceStorage.enabled && workspaceStorage.csi.enabled;
|
|
510
|
-
}
|
|
511
|
-
/**
|
|
512
|
-
* alasio's identity: it drives its workspaces' Sandboxes, their token Secrets, and reads
|
|
513
|
-
* files from sessions through exec, in the namespaces it owns, labelling their pods busy
|
|
514
|
-
* while turns run in them, as it does its own in its namespace (src/kube/busy.ts); where
|
|
515
|
-
* it snapshots sessions, sets a restored session's readiness; where it forks
|
|
516
|
-
* sessions, reads sessions' volume claims and runs the Jobs that clone them in its own;
|
|
517
|
-
* where the node agents run, watches pods in its own, theirs among them, and reads the
|
|
518
|
-
* cluster's nodes, for a restore to go to one that takes its pod; and, where it installs
|
|
519
|
-
* JuiceFS's driver, lists and deletes pods in the driver's namespace, its mount pods; and
|
|
520
|
-
* nothing else.
|
|
256
|
+
* alasio's identity: it labels its own pod busy while turns run in it (src/kube/busy.ts), and
|
|
257
|
+
* nothing else. Its sessions and its folder workspaces are the sandbox gateway's, which it
|
|
258
|
+
* reaches by its key alone.
|
|
521
259
|
*/
|
|
522
260
|
function identity(config, environment) {
|
|
523
|
-
const
|
|
524
|
-
const
|
|
261
|
+
const inOwnNamespace = { name: RELEASE, namespace: environment.namespace, labels: labels("alasio") };
|
|
262
|
+
const own = { apiVersion: "rbac.authorization.k8s.io/v1", kind: "Role", metadata: inOwnNamespace, rules: [{ apiGroups: [""], resources: ["pods"], verbs: ["list", "patch"] }] };
|
|
263
|
+
const binding = {
|
|
525
264
|
apiVersion: "rbac.authorization.k8s.io/v1",
|
|
526
265
|
kind: "RoleBinding",
|
|
527
|
-
metadata,
|
|
266
|
+
metadata: inOwnNamespace,
|
|
528
267
|
subjects: [{ kind: "ServiceAccount", name: RELEASE, namespace: environment.namespace }],
|
|
529
268
|
roleRef: { apiGroup: "rbac.authorization.k8s.io", kind: "Role", name: RELEASE },
|
|
530
|
-
});
|
|
531
|
-
const inDriverNamespace = { name: RELEASE, namespace: config.workspaceStorage.csi.namespace, labels: labels("alasio") };
|
|
532
|
-
const mountPods = {
|
|
533
|
-
apiVersion: "rbac.authorization.k8s.io/v1",
|
|
534
|
-
kind: "Role",
|
|
535
|
-
metadata: inDriverNamespace,
|
|
536
|
-
rules: [{ apiGroups: [""], resources: ["pods"], verbs: ["list", "delete"] }],
|
|
537
|
-
};
|
|
538
|
-
const inOwnNamespace = { name: RELEASE, namespace: environment.namespace, labels: labels("alasio") };
|
|
539
|
-
const own = {
|
|
540
|
-
apiVersion: "rbac.authorization.k8s.io/v1",
|
|
541
|
-
kind: "Role",
|
|
542
|
-
metadata: inOwnNamespace,
|
|
543
|
-
rules: [
|
|
544
|
-
// Its own pod's busy label; and each node's agent, found by its pod on the node.
|
|
545
|
-
{ apiGroups: [""], resources: ["pods"], verbs: main && nodeAgentRuns(config) ? ["list", "watch", "patch"] : ["list", "patch"] },
|
|
546
|
-
...(main && sessionsForked(config) ? [{ apiGroups: ["batch"], resources: ["jobs"], verbs: ["create", "get", "delete"] }] : []),
|
|
547
|
-
],
|
|
548
269
|
};
|
|
549
270
|
const serviceAccount = { apiVersion: "v1", kind: "ServiceAccount", metadata: { name: RELEASE, namespace: environment.namespace, labels: labels("alasio") } };
|
|
550
|
-
|
|
551
|
-
const nodes = { name: componentName("nodes"), labels: labels("alasio") };
|
|
552
|
-
const nodesRole = {
|
|
553
|
-
apiVersion: "rbac.authorization.k8s.io/v1",
|
|
554
|
-
kind: "ClusterRole",
|
|
555
|
-
metadata: nodes,
|
|
556
|
-
rules: [{ apiGroups: [""], resources: ["nodes"], verbs: ["get"] }],
|
|
557
|
-
};
|
|
558
|
-
const nodesBinding = {
|
|
559
|
-
apiVersion: "rbac.authorization.k8s.io/v1",
|
|
560
|
-
kind: "ClusterRoleBinding",
|
|
561
|
-
metadata: nodes,
|
|
562
|
-
subjects: [{ kind: "ServiceAccount", name: RELEASE, namespace: environment.namespace }],
|
|
563
|
-
roleRef: { apiGroup: "rbac.authorization.k8s.io", kind: "ClusterRole", name: nodes.name },
|
|
564
|
-
};
|
|
565
|
-
return [
|
|
566
|
-
serviceAccount,
|
|
567
|
-
...workspaceNamespaces(config, environment).flatMap((namespace) => {
|
|
568
|
-
const metadata = { name: RELEASE, namespace, labels: labels("alasio") };
|
|
569
|
-
const forked = main && sessionsForked(config) && namespace === config.sessions.namespace;
|
|
570
|
-
const snapshotted = main && nodeAgentRuns(config) && namespace === config.sessions.namespace;
|
|
571
|
-
const role = {
|
|
572
|
-
apiVersion: "rbac.authorization.k8s.io/v1",
|
|
573
|
-
kind: "Role",
|
|
574
|
-
metadata,
|
|
575
|
-
rules: [
|
|
576
|
-
{ apiGroups: ["agents.x-k8s.io"], resources: ["sandboxes"], verbs: ["get", "list", "watch", "create", "patch", "delete"] },
|
|
577
|
-
{ apiGroups: [""], resources: ["secrets"], verbs: ["get", "create"] },
|
|
578
|
-
{ apiGroups: [""], resources: ["pods"], verbs: ["get", "list", "patch"] },
|
|
579
|
-
{ apiGroups: [""], resources: ["pods/exec"], verbs: ["create", "get"] },
|
|
580
|
-
...(forked ? [{ apiGroups: [""], resources: ["persistentvolumeclaims"], verbs: ["get"] }] : []),
|
|
581
|
-
// A restored session's readiness, once its sandbox is let run, and the network policies that must hold it first (src/sandbox/snapshots.ts).
|
|
582
|
-
...(snapshotted
|
|
583
|
-
? [{ apiGroups: [""], resources: ["pods/status"], verbs: ["patch"] }, { apiGroups: ["networking.k8s.io"], resources: ["networkpolicies"], verbs: ["list"] }]
|
|
584
|
-
: []),
|
|
585
|
-
],
|
|
586
|
-
};
|
|
587
|
-
return [role, binding(metadata)];
|
|
588
|
-
}),
|
|
589
|
-
own,
|
|
590
|
-
binding(inOwnNamespace),
|
|
591
|
-
...(main && mountPodsRemoved(config) ? [mountPods, binding(inDriverNamespace)] : []),
|
|
592
|
-
...(main && nodeAgentRuns(config) ? [nodesRole, nodesBinding] : []),
|
|
593
|
-
...(config.host.enabled ? hostAgentIdentity(config) : []),
|
|
594
|
-
];
|
|
271
|
+
return [serviceAccount, own, binding, ...(environment.branch === null && foldersRun(config) ? hostAgentIdentity(config) : [])];
|
|
595
272
|
}
|
|
596
273
|
/**
|
|
597
274
|
* Folder workspaces' bayma: the operator's agents, which may restart alasio as they
|
|
@@ -626,31 +303,18 @@ function hostAgentIdentity(config) {
|
|
|
626
303
|
}
|
|
627
304
|
/** The objects of the alasio of `environment`, main's unless a branch environment's, with what main's carries forward. */
|
|
628
305
|
export function alasioObjects(config, environment = MAIN_ENVIRONMENT, carried = NOTHING_CARRIED) {
|
|
629
|
-
const
|
|
630
|
-
const alasio = deployment(config, templates.checksum, carried.botChecksum, environment);
|
|
306
|
+
const alasio = deployment(config, carried.botChecksum, environment);
|
|
631
307
|
return [
|
|
632
308
|
...namespaces(config, environment),
|
|
633
309
|
...identity(config, environment),
|
|
634
|
-
templates.configMap,
|
|
635
310
|
alasio,
|
|
636
311
|
// It runs turns, in its harnesses, which a recreation would end.
|
|
637
312
|
verticalPodAutoscaler(alasio, "Recommended"),
|
|
638
|
-
// A drain waits for the turns running in its pod
|
|
639
|
-
|
|
640
|
-
telemetryService(config, environment),
|
|
313
|
+
// A drain waits for the turns running in its pod to end.
|
|
314
|
+
busyBudget(environment.namespace),
|
|
641
315
|
...(environment.branch === null && forksForBranches(config) ? [branchForksService()] : []),
|
|
642
|
-
// What alasio may do beyond what RBAC can say
|
|
643
|
-
...(environment.branch === null ?
|
|
644
|
-
// Where sessions are snapshotted, what alasio may set of a restored session's pod's status.
|
|
645
|
-
...(environment.branch === null && config.sessions.enabled && nodeAgentRuns(config)
|
|
646
|
-
? resumedConditionPolicy(componentName("resumed-condition"), alasioAccount(environment.namespace), config.sessions.namespace)
|
|
647
|
-
: []),
|
|
648
|
-
...(environment.branch === null && sessionsForked(config) ? cloneJobPolicy(cloneJob(config)) : []),
|
|
649
|
-
...sandboxPolicy(sandboxPolicyName(environment.namespace), alasioAccount(environment.namespace), {
|
|
650
|
-
sessions: config.sessions.enabled ? sessionsProfile(config, environment, carried) : null,
|
|
651
|
-
previousSessions: config.sessions.enabled ? carried.previousSessions : null,
|
|
652
|
-
host: config.host.enabled ? hostProfile(config) : null,
|
|
653
|
-
}),
|
|
316
|
+
// What alasio may do beyond what RBAC can say: the cluster's, made with main's.
|
|
317
|
+
...(environment.branch === null ? busyLabelPolicy() : []),
|
|
654
318
|
];
|
|
655
319
|
}
|
|
656
320
|
//# sourceMappingURL=alasio.js.map
|