alasio 7.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 +123 -46
- 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 +51 -12
- package/dist/cli/src/cluster/k3s.js.map +1 -1
- package/dist/cli/src/cluster/node.js +115 -33
- 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/init.js +54 -4
- package/dist/cli/src/commands/init.js.map +1 -1
- package/dist/cli/src/commands/lake.js +40 -6
- package/dist/cli/src/commands/lake.js.map +1 -1
- package/dist/cli/src/commands/restore-filer-store.js +40 -8
- package/dist/cli/src/commands/restore-filer-store.js.map +1 -1
- package/dist/cli/src/commands/status.js +216 -20
- 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 +24 -9
- 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 +119 -17
- 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 +11 -5
- package/dist/cli/src/kube/api.js.map +1 -1
- package/dist/cli/src/kube/apply.js +16 -73
- package/dist/cli/src/kube/apply.js.map +1 -1
- package/dist/cli/src/kube/rollout.js +84 -26
- package/dist/cli/src/kube/rollout.js.map +1 -1
- package/dist/cli/src/lake.js +124 -0
- package/dist/cli/src/lake.js.map +1 -0
- package/dist/cli/src/manifests/admission.js +381 -223
- package/dist/cli/src/manifests/admission.js.map +1 -1
- package/dist/cli/src/manifests/alasio.js +79 -362
- 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 +250 -135
- 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 +256 -92
- 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 +15 -8
- package/dist/cli/src/manifests/index.js.map +1 -1
- package/dist/cli/src/manifests/keda.js +2 -1
- package/dist/cli/src/manifests/keda.js.map +1 -1
- package/dist/cli/src/manifests/lake.js +350 -73
- package/dist/cli/src/manifests/lake.js.map +1 -1
- package/dist/cli/src/manifests/log.js +316 -0
- package/dist/cli/src/manifests/log.js.map +1 -0
- package/dist/cli/src/manifests/neon.js +128 -49
- package/dist/cli/src/manifests/neon.js.map +1 -1
- package/dist/cli/src/manifests/network-policies.js +263 -100
- package/dist/cli/src/manifests/network-policies.js.map +1 -1
- package/dist/cli/src/manifests/node-agent.js +24 -8
- 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/webhook.js +102 -0
- package/dist/cli/src/manifests/webhook.js.map +1 -0
- 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 +155 -0
- package/dist/cli/src/neon-storage.js.map +1 -0
- package/dist/cli/src/release.js +9 -6
- package/dist/cli/src/release.js.map +1 -1
- package/dist/cli/src/secrets.js +45 -4
- package/dist/cli/src/secrets.js.map +1 -1
- package/dist/cli/src/target.js +1 -1
- package/dist/cli/src/target.js.map +1 -1
- package/dist/cli/src/telegram.js +56 -10
- package/dist/cli/src/telegram.js.map +1 -1
- package/dist/cli/src/webhook.js +182 -0
- package/dist/cli/src/webhook.js.map +1 -0
- package/dist/cluster/node/pins.json +12 -2
- package/dist/neon/control/branches.js +126 -21
- package/dist/neon/control/branches.js.map +1 -1
- package/dist/neon/control/endpoints.js +9 -0
- package/dist/neon/control/endpoints.js.map +1 -1
- package/dist/neon/control/jwt.js +16 -3
- package/dist/neon/control/jwt.js.map +1 -1
- package/dist/neon/control/secrets.js +51 -7
- 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 +19 -69
- package/dist/src/kube/sandbox-shape.js.map +1 -1
- package/dist/src/node-agent/names.js +118 -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/telegram/deliveries.js +40 -0
- package/dist/src/telegram/deliveries.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 -319
- 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 -143
- package/dist/src/kube/config.js.map +0 -1
|
@@ -1,263 +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 { CPU_FEATURES_ANNOTATION } 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 {
|
|
16
|
-
import {
|
|
5
|
+
import { busyLabelPolicy } from "./admission.js";
|
|
6
|
+
import { foldersRun } from "./folders.js";
|
|
7
|
+
import { carriedPools, GATEWAY, GATEWAY_PORT, sandboxServiceRuns } from "./sandbox-gateway.js";
|
|
8
|
+
import { alasioGroup, environmentLogSecret, environmentName, lakeWakeTopic, LOG_BROKERS, telegramTopic } from "./log.js";
|
|
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";
|
|
17
10
|
import { durationSeconds } from "./config.js";
|
|
18
11
|
import { busyBudget } from "./disruption.js";
|
|
19
12
|
import { priority } from "./priorities.js";
|
|
20
13
|
import { verticalPodAutoscaler } from "./sizing.js";
|
|
21
|
-
import { cloneJob } from "./workspace-storage.js";
|
|
22
|
-
/** The port every workspace's bayma serves MCP on. */
|
|
23
|
-
const BAYMA_PORT = 7290;
|
|
24
14
|
/** The namespace of the sessions of the alasio of `environment`: the configured one, or a branch environment's own. */
|
|
25
15
|
export function sessionsNamespace(config, { branch }) {
|
|
26
16
|
return branch ? branchSessionsNamespace(branch) : config.sessions.namespace;
|
|
27
17
|
}
|
|
28
|
-
/**
|
|
29
|
-
function
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* The template of session filesystems' Sandboxes: an empty, isolated workspace under
|
|
34
|
-
* the sessions' runtime, restricted, on a volume of workspace storage's class when it is
|
|
35
|
-
* on. alasio adds what is per Sandbox: its name and labels, bayma's token, and its
|
|
36
|
-
* network mode. A branch environment's are in its own namespace, and neither clones a
|
|
37
|
-
* session (its parent does, src/branch/fork.ts) nor removes JuiceFS's mount pods, which
|
|
38
|
-
* are main's to drive.
|
|
39
|
-
*/
|
|
40
|
-
function sessionsProfile(config, environment, { cpuBaseline, gvisorReleases }) {
|
|
41
|
-
const { sessions, workspaceStorage } = config;
|
|
42
|
-
const main = environment.branch === null;
|
|
43
|
-
// Snapshotted once every node's CPU features are known, its sandboxes held to those all have.
|
|
44
|
-
const snapshotted = main && nodeAgentRuns(config) && cpuBaseline !== null;
|
|
45
|
-
const agent = imageReference(config.images.agent);
|
|
46
|
-
const storageClassName = sessions.storage.storageClassName || (workspaceStorage.enabled ? workspaceStorage.storageClassName : "");
|
|
47
|
-
// On workspace storage, the volume's mounts follow its mount pod's, as upstream's
|
|
48
|
-
// template has them (gVisor does not, and alasio restarts a session whose mount is
|
|
49
|
-
// gone), and its files are given the pod's group only when its root is not the group's,
|
|
50
|
-
// as walking a JuiceFS volume is slow.
|
|
51
|
-
const propagation = workspaceStorage.enabled ? { mountPropagation: "HostToContainer" } : {};
|
|
52
|
-
const ownership = workspaceStorage.enabled ? { fsGroupChangePolicy: "OnRootMismatch" } : {};
|
|
53
|
-
return {
|
|
54
|
-
namespace: sessionsNamespace(config, environment),
|
|
55
|
-
port: BAYMA_PORT,
|
|
56
|
-
workspaceDir: "/workspace",
|
|
57
|
-
egressGate: sessions.egressGate,
|
|
58
|
-
fullModeNameservers: [...sessions.fullModeNameservers],
|
|
59
|
-
...(main && mountPodsRemoved(config) ? { mountPodNamespace: workspaceStorage.csi.namespace } : {}),
|
|
60
|
-
podTemplate: {
|
|
61
|
-
metadata: {
|
|
62
|
-
labels: { "app.kubernetes.io/part-of": "alasio", "app.kubernetes.io/instance": RELEASE, "app.kubernetes.io/component": "session" },
|
|
63
|
-
// Under gVisor, /tmp is a tmpfs of the sandbox's own, by gVisor's mount hints, rather
|
|
64
|
-
// than the emptyDir's directory on the node: a snapshot of the sandbox holds it, as it
|
|
65
|
-
// holds the files that bayma's runtimes keep open there.
|
|
66
|
-
annotations: {
|
|
67
|
-
"dev.gvisor.spec.mount.tmp.share": "container",
|
|
68
|
-
"dev.gvisor.spec.mount.tmp.type": "tmpfs",
|
|
69
|
-
"dev.gvisor.spec.mount.tmp.options": "rw",
|
|
70
|
-
...(snapshotted ? { [CPU_FEATURES_ANNOTATION]: cpuBaseline.join(",") } : {}),
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
|
-
spec: {
|
|
74
|
-
...(sessions.runtimeClassName ? { runtimeClassName: sessions.runtimeClassName } : {}),
|
|
75
|
-
...priority("turn"),
|
|
76
|
-
// A pod that ends is ended: alasio brings the session up in a new one, and nothing
|
|
77
|
-
// starts bayma again in a sandbox that a snapshot has just ended.
|
|
78
|
-
restartPolicy: "Never",
|
|
79
|
-
securityContext: { ...restrictedPod(1000, 1000), ...ownership },
|
|
80
|
-
...imagePullSecrets(config),
|
|
81
|
-
...given("nodeSelector", { ...sessions.nodeSelector }),
|
|
82
|
-
...given("tolerations", [...sessions.tolerations]),
|
|
83
|
-
initContainers: [
|
|
84
|
-
// The workspace and home on the session's volume, and bayma's toolbelt, which the
|
|
85
|
-
// image installs, linked into the home.
|
|
86
|
-
{
|
|
87
|
-
name: "prepare",
|
|
88
|
-
image: agent,
|
|
89
|
-
imagePullPolicy: config.images.pullPolicy,
|
|
90
|
-
command: [
|
|
91
|
-
"/bin/sh",
|
|
92
|
-
"-c",
|
|
93
|
-
"mkdir -p /data/workspace /data/home/.local/share/bayma && ln -sfn /opt/bayma-data/bayma/toolbelt /data/home/.local/share/bayma/toolbelt",
|
|
94
|
-
],
|
|
95
|
-
securityContext: restrictedContainer(),
|
|
96
|
-
...helperResources(),
|
|
97
|
-
volumeMounts: [{ name: "data", mountPath: "/data" }],
|
|
98
|
-
},
|
|
99
|
-
],
|
|
100
|
-
containers: [{
|
|
101
|
-
name: "bayma",
|
|
102
|
-
image: agent,
|
|
103
|
-
imagePullPolicy: config.images.pullPolicy,
|
|
104
|
-
command: ["/usr/bin/tini", "-s", "--", "node", "/opt/bayma/bayma.js"],
|
|
105
|
-
args: ["mcp-http", "--host", "0.0.0.0", "--port", String(BAYMA_PORT), "--state-dir", "/home/agent/.bayma"],
|
|
106
|
-
workingDir: "/workspace",
|
|
107
|
-
env: [
|
|
108
|
-
{ name: "HOME", value: "/home/agent" },
|
|
109
|
-
{ name: "USER", value: "agent" },
|
|
110
|
-
{ name: "BAYMA_PAYLOAD_DIR", value: "/opt/bayma/payload" },
|
|
111
|
-
],
|
|
112
|
-
ports: [{ name: "mcp", containerPort: BAYMA_PORT }],
|
|
113
|
-
securityContext: restrictedContainer(),
|
|
114
|
-
resources: sessions.resources,
|
|
115
|
-
volumeMounts: [
|
|
116
|
-
{ name: "data", mountPath: "/workspace", subPath: "workspace", ...propagation },
|
|
117
|
-
{ name: "data", mountPath: "/home/agent", subPath: "home", ...propagation },
|
|
118
|
-
{ name: "tmp", mountPath: "/tmp" },
|
|
119
|
-
],
|
|
120
|
-
}],
|
|
121
|
-
volumes: [{ name: "tmp", emptyDir: { sizeLimit: "2Gi" } }],
|
|
122
|
-
},
|
|
123
|
-
},
|
|
124
|
-
volumeClaimTemplates: [{
|
|
125
|
-
metadata: { name: "data" },
|
|
126
|
-
spec: {
|
|
127
|
-
accessModes: ["ReadWriteOnce"],
|
|
128
|
-
...(storageClassName ? { storageClassName } : {}),
|
|
129
|
-
resources: { requests: { storage: sessions.storage.size } },
|
|
130
|
-
},
|
|
131
|
-
}],
|
|
132
|
-
...(main && sessionsForked(config) ? { clone: { claimTemplate: "data", job: cloneJob(config) } } : {}),
|
|
133
|
-
...(snapshotted ? { snapshots: sessionSnapshots(config, gvisorReleases) } : {}),
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* How session sandboxes are snapshotted as they are released (src/sandbox/snapshots.ts),
|
|
138
|
-
* where the node agents run: once sessions.snapshots.releaseAfter has passed without an
|
|
139
|
-
* exec or a turn, under the gVisor `releases` alasio keeps (../kept-releases.ts), the
|
|
140
|
-
* current one first, each restored with a RuntimeClass of its own, by the agents in
|
|
141
|
-
* alasio's namespace.
|
|
142
|
-
*/
|
|
143
|
-
function sessionSnapshots(config, releases) {
|
|
144
|
-
return {
|
|
145
|
-
// A duration, as the configuration checks it.
|
|
146
|
-
releaseAfterSeconds: durationSeconds(config.sessions.snapshots.releaseAfter) ?? 0,
|
|
147
|
-
releases: releases.map((release) => ({ release, runtimeClassName: gvisorRuntimeClass(release) })),
|
|
148
|
-
agents: {
|
|
149
|
-
namespace: NAMESPACE,
|
|
150
|
-
selector: Object.entries(selectorLabels("node-agent")).map(([label, value]) => `${label}=${value}`).join(","),
|
|
151
|
-
port: NODE_AGENT_PORT,
|
|
152
|
-
},
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
/** Whether alasio forks sessions: where their volumes are workspace storage's, which JuiceFS clones. */
|
|
156
|
-
export function sessionsForked({ sessions, workspaceStorage }) {
|
|
157
|
-
return workspaceStorage.enabled && [workspaceStorage.storageClassName, ""].includes(sessions.storage.storageClassName);
|
|
18
|
+
/** How long a session's bayma holds a stop alasio did not make (sessions.snapshots.stopWait). */
|
|
19
|
+
export function stopWaitSeconds(config) {
|
|
20
|
+
// A duration, as the configuration checks it.
|
|
21
|
+
return durationSeconds(config.sessions.snapshots.stopWait) ?? 0;
|
|
158
22
|
}
|
|
159
|
-
/**
|
|
160
|
-
|
|
161
|
-
const { host } = config;
|
|
162
|
-
return {
|
|
163
|
-
namespace: host.namespace,
|
|
164
|
-
port: BAYMA_PORT,
|
|
165
|
-
stateRoot: host.stateRoot,
|
|
166
|
-
podTemplate: {
|
|
167
|
-
metadata: { labels: { "app.kubernetes.io/part-of": "alasio", "app.kubernetes.io/instance": RELEASE, "app.kubernetes.io/component": "folder-bayma" } },
|
|
168
|
-
spec: {
|
|
169
|
-
// May restart alasio, by rolling out its Deployment, as an agent restarts it.
|
|
170
|
-
serviceAccountName: componentName("host-agent"),
|
|
171
|
-
...priority("turn"),
|
|
172
|
-
securityContext: {
|
|
173
|
-
runAsUser: host.uid,
|
|
174
|
-
runAsGroup: host.gid,
|
|
175
|
-
// The group the bayma token's Secret volume is given, which the operator's user
|
|
176
|
-
// reads it as; the node's own paths the mounts give are left as they are.
|
|
177
|
-
fsGroup: host.gid,
|
|
178
|
-
...given("supplementalGroups", [...host.supplementalGroups]),
|
|
179
|
-
},
|
|
180
|
-
...imagePullSecrets(config),
|
|
181
|
-
containers: [{
|
|
182
|
-
name: "bayma",
|
|
183
|
-
image: imageReference(host.baymaImage),
|
|
184
|
-
imagePullPolicy: "IfNotPresent",
|
|
185
|
-
args: ["mcp-http", "--host", "0.0.0.0", "--port", String(BAYMA_PORT), "--default-durability", "checkpointed"],
|
|
186
|
-
workingDir: host.home,
|
|
187
|
-
env: [{ name: "HOME", value: host.home }, ...envOf(host.env)],
|
|
188
|
-
ports: [{ name: "mcp", containerPort: BAYMA_PORT }],
|
|
189
|
-
securityContext: {
|
|
190
|
-
// What bayma needs to snapshot its REPL sessions' processes as it stops and
|
|
191
|
-
// restore them whole as it starts again.
|
|
192
|
-
capabilities: { add: ["CHECKPOINT_RESTORE", "SYS_PTRACE"] },
|
|
193
|
-
seccompProfile: { type: "Unconfined" },
|
|
194
|
-
appArmorProfile: { type: "Unconfined" },
|
|
195
|
-
},
|
|
196
|
-
resources: host.resources,
|
|
197
|
-
...given("volumeMounts", hostVolumeMounts(config)),
|
|
198
|
-
}],
|
|
199
|
-
...given("volumes", hostVolumes(config)),
|
|
200
|
-
},
|
|
201
|
-
},
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
/** What a cluster keeps where up has found nothing of it yet: no baseline, and the releases pinned. */
|
|
205
|
-
export const NOTHING_KEPT = { cpuBaseline: null, gvisorReleases: gvisorReleases(NODE_PINS) };
|
|
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: {} };
|
|
206
25
|
/** Nothing carried forward: a first installation's, and a branch environment's. */
|
|
207
|
-
export const NOTHING_CARRIED = {
|
|
208
|
-
/** The ConfigMap of the templates, by its name. */
|
|
209
|
-
export const SANDBOX_TEMPLATES = componentName("sandbox-templates");
|
|
26
|
+
export const NOTHING_CARRIED = { previousPools: { none: null, full: null }, ...NOTHING_KEPT };
|
|
210
27
|
/**
|
|
211
28
|
* What the installation `config` describes, with what the cluster keeps, `kept`, carries
|
|
212
|
-
* forward from `
|
|
213
|
-
* `
|
|
214
|
-
*
|
|
215
|
-
* template, and no more. Pure, for tests.
|
|
216
|
-
*
|
|
217
|
-
* What it carries is pinned whole into the Sandbox policy (./admission.ts) as a template
|
|
218
|
-
* alasio may make a Sandbox from, read back from the cluster rather than rendered from the
|
|
219
|
-
* config: the ConfigMap is the anchor of that trust. It is one as long as only the
|
|
220
|
-
* operator, by `alasio up`, writes it: alasio's ServiceAccount may write no ConfigMap
|
|
221
|
-
* (./alasio.ts identity). Were alasio given that, it could write any pod template into
|
|
222
|
-
* the ConfigMap, and the next `up` would let it make Sandboxes of it.
|
|
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.
|
|
223
32
|
*/
|
|
224
|
-
export function carriedFrom(config,
|
|
225
|
-
|
|
226
|
-
if (!config.sessions.enabled || live === undefined)
|
|
227
|
-
return nothing;
|
|
228
|
-
// Carried as the ConfigMap held them, which alasio read as they are: the profile a snapshot recorded the hash of.
|
|
229
|
-
if (Result.isFailure(decodeKubeTemplates(SANDBOX_TEMPLATES, live)))
|
|
230
|
-
return nothing;
|
|
231
|
-
const held = JSON.parse(live);
|
|
232
|
-
if (!held.sessions)
|
|
233
|
-
return nothing;
|
|
234
|
-
// The current profile as the ConfigMap holds it, to compare with what it held.
|
|
235
|
-
const current = JSON.parse(goJson(sessionsProfile(config, MAIN_ENVIRONMENT, kept), ""));
|
|
236
|
-
return { previousSessions: isDeepStrictEqual(held.sessions.podTemplate, current.podTemplate) ? (held.previousSessions ?? null) : held.sessions, ...kept };
|
|
237
|
-
}
|
|
238
|
-
/**
|
|
239
|
-
* The CPU baseline the installation whose templates are `live` (as carriedFrom takes
|
|
240
|
-
* them) holds sessions to: what its sessions' template sets, if anything.
|
|
241
|
-
*/
|
|
242
|
-
export function recordedCpuBaseline(live) {
|
|
243
|
-
if (live === undefined || Result.isFailure(decodeKubeTemplates(SANDBOX_TEMPLATES, live)))
|
|
244
|
-
return null;
|
|
245
|
-
const held = JSON.parse(live);
|
|
246
|
-
const recorded = held.sessions?.podTemplate.metadata?.annotations?.[CPU_FEATURES_ANNOTATION];
|
|
247
|
-
return recorded ? recorded.split(",") : null;
|
|
248
|
-
}
|
|
249
|
-
/** The ConfigMap of the templates, and their checksum, which alasio's pod carries so it is replaced when they change. */
|
|
250
|
-
function sandboxTemplates(config, environment, carried) {
|
|
251
|
-
const name = SANDBOX_TEMPLATES;
|
|
252
|
-
const templates = goJson({
|
|
253
|
-
...(config.sessions.enabled ? { sessions: sessionsProfile(config, environment, carried) } : {}),
|
|
254
|
-
...(config.sessions.enabled && carried.previousSessions ? { previousSessions: carried.previousSessions } : {}),
|
|
255
|
-
...(config.host.enabled ? { host: hostProfile(config) } : {}),
|
|
256
|
-
}, " ");
|
|
257
|
-
return {
|
|
258
|
-
configMap: { apiVersion: "v1", kind: "ConfigMap", metadata: { name, namespace: environment.namespace, labels: labels("alasio") }, data: { "templates.json": templates } },
|
|
259
|
-
checksum: sha256(templates),
|
|
260
|
-
};
|
|
33
|
+
export function carriedFrom(config, kept, liveGateway) {
|
|
34
|
+
return { ...kept, previousPools: carriedPools(config, liveGateway, kept) };
|
|
261
35
|
}
|
|
262
36
|
/** Where alasio's Secrets of branch environments are mounted: main's key, or a branch's token. */
|
|
263
37
|
const BRANCH_SECRETS = "/run/alasio/branch";
|
|
@@ -283,9 +57,9 @@ function branchSecretVolume(config, { branch }) {
|
|
|
283
57
|
return [{ name: "branch", secret: { secretName: BRANCH_FORK_SECRET, items: [{ key: "token", path: "token" }] } }];
|
|
284
58
|
return forksForBranches(config) ? [{ name: "branch", secret: { secretName: componentName("branches"), items: [{ key: "fork-key", path: "fork-key" }], optional: true } }] : [];
|
|
285
59
|
}
|
|
286
|
-
/** 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. */
|
|
287
61
|
export function forksForBranches(config) {
|
|
288
|
-
return config.neon.enabled &&
|
|
62
|
+
return config.neon.enabled && sandboxServiceRuns(config);
|
|
289
63
|
}
|
|
290
64
|
/**
|
|
291
65
|
* The roles main's alasio makes for what reads its Neon beside it (common.ts
|
|
@@ -299,7 +73,6 @@ function readerRoles(config, { branch }) {
|
|
|
299
73
|
function alasioEnv(config, home, operatorHome, environment) {
|
|
300
74
|
const { alasio, host } = config;
|
|
301
75
|
return [
|
|
302
|
-
{ name: "ALASIO_KUBE_TEMPLATES", value: "/etc/alasio/templates.json" },
|
|
303
76
|
{ name: "ALASIO_STATE_DIR", value: "/var/lib/alasio/state" },
|
|
304
77
|
{ name: "HOME", value: home },
|
|
305
78
|
// A home of alasio's own does not outlast its pod; the operator's keeps their login.
|
|
@@ -311,35 +84,51 @@ function alasioEnv(config, home, operatorHome, environment) {
|
|
|
311
84
|
{ name: "TELEGRAM_ALLOWED_USER_IDS", valueFrom: { secretKeyRef: { name: alasio.telegram.existingSecret, key: "allowedUserIds" } } },
|
|
312
85
|
{ name: "ALASIO_DATABASE_URL_FILE", value: "/run/alasio/database/url" },
|
|
313
86
|
{ name: "ALASIO_LAKE_VERIFIER_FILE", value: "/run/alasio/database/lake-verifier" },
|
|
87
|
+
{ name: "ALASIO_HARNESS_VERIFIER_FILE", value: "/run/alasio/database/harness-verifier" },
|
|
314
88
|
...readerRoles(config, environment).map(({ key, variable }) => ({ name: variable, value: `/run/alasio/database/${key}` })),
|
|
315
89
|
{ name: "ALASIO_LAKE_ENABLED", value: config.lake.enabled && config.neon.enabled ? "1" : "0" },
|
|
316
|
-
|
|
317
|
-
{ name: "
|
|
90
|
+
// Its Telegram updates: its environment's topic, read in its group as its principal.
|
|
91
|
+
{ name: "ALASIO_LOG_BROKERS", value: LOG_BROKERS },
|
|
92
|
+
{ name: "ALASIO_LOG_USERNAME", valueFrom: { secretKeyRef: { name: environmentLogSecret(environment), key: "username" } } },
|
|
93
|
+
{ name: "ALASIO_LOG_PASSWORD_FILE", value: "/run/alasio/log/password" },
|
|
94
|
+
{ name: "ALASIO_TELEGRAM_TOPIC", value: telegramTopic(environmentName(environment)) },
|
|
95
|
+
{ name: "ALASIO_TELEGRAM_GROUP", value: alasioGroup(environmentName(environment)) },
|
|
96
|
+
// Its environment's wake topic, which it tells the lake's loader of each transcript it writes on, as that principal.
|
|
97
|
+
...(lakeRuns(config) ? [{ name: "ALASIO_LAKE_WAKE_TOPIC", value: lakeWakeTopic(environmentName(environment)) }] : []),
|
|
318
98
|
...(alasio.defaultHarness ? [{ name: "ALASIO_DEFAULT_HARNESS", value: alasio.defaultHarness }] : []),
|
|
319
99
|
...(host.enabled && host.workspaceRoot ? [{ name: "ALASIO_WORKSPACE_ROOT", value: host.workspaceRoot }] : []),
|
|
320
100
|
...(alasio.claude.existingSecret
|
|
321
101
|
? [{ name: "CLAUDE_CODE_OAUTH_TOKEN", valueFrom: { secretKeyRef: { name: alasio.claude.existingSecret, key: alasio.claude.key } } }]
|
|
322
102
|
: []),
|
|
323
|
-
//
|
|
324
|
-
...(
|
|
325
|
-
? [
|
|
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
|
+
]
|
|
326
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" }] : []),
|
|
327
113
|
...branchEnv(config, environment),
|
|
328
114
|
...otelEnv(config, environment),
|
|
329
115
|
...envOf(alasio.env),
|
|
330
116
|
];
|
|
331
117
|
}
|
|
332
118
|
/**
|
|
333
|
-
* alasio's Deployment: one replica,
|
|
334
|
-
*
|
|
119
|
+
* alasio's Deployment: one replica, the one member of its group on its topic's one
|
|
120
|
+
* partition, which its turns run in, so an update stops the old pod before the new one
|
|
121
|
+
* starts. It keeps no volume: its state is in Neon,
|
|
335
122
|
* and what it writes to disk (received files written for the agent, its home unless it
|
|
336
123
|
* is the operator's) is written again as needed, on emptyDirs. Under the
|
|
337
124
|
* host profile it runs as the operator, in their home, with the machine's mounts. A
|
|
338
125
|
* branch environment's runs in its namespace on the branch's database, told it is the
|
|
339
126
|
* branch, with its token to ask main to fork the sessions it inherited; main's is given
|
|
340
|
-
* the key branch environments' tokens are signed with, where it forks sessions.
|
|
127
|
+
* the key branch environments' tokens are signed with, where it forks sessions. Its pod
|
|
128
|
+
* carries, where up read it, the checksum of its bot's Secret, so it is replaced when it
|
|
129
|
+
* changes.
|
|
341
130
|
*/
|
|
342
|
-
function deployment(config,
|
|
131
|
+
function deployment(config, botChecksum, environment) {
|
|
343
132
|
const { alasio, host } = config;
|
|
344
133
|
const operatorHome = host.enabled && host.alasioHome;
|
|
345
134
|
const home = operatorHome ? host.home : "/var/lib/alasio/home";
|
|
@@ -357,7 +146,10 @@ function deployment(config, templatesChecksum, environment) {
|
|
|
357
146
|
strategy: { type: "Recreate" },
|
|
358
147
|
selector: { matchLabels: selectorLabels("alasio") },
|
|
359
148
|
template: {
|
|
360
|
-
metadata: {
|
|
149
|
+
metadata: {
|
|
150
|
+
labels: labels("alasio"),
|
|
151
|
+
...(botChecksum === null ? {} : { annotations: { "checksum/telegram": botChecksum } }),
|
|
152
|
+
},
|
|
361
153
|
spec: {
|
|
362
154
|
serviceAccountName: RELEASE,
|
|
363
155
|
...priority("turn"),
|
|
@@ -372,17 +164,14 @@ function deployment(config, templatesChecksum, environment) {
|
|
|
372
164
|
workingDir: home,
|
|
373
165
|
env: alasioEnv(config, home, operatorHome, environment),
|
|
374
166
|
...given("envFrom", [...alasio.envFrom]),
|
|
375
|
-
ports: [
|
|
376
|
-
{ name: "telemetry", containerPort: config.telemetry.receiverPort },
|
|
377
|
-
...(environment.branch === null && forksForBranches(config) ? [{ name: "branch-forks", containerPort: BRANCH_FORK_PORT }] : []),
|
|
378
|
-
],
|
|
167
|
+
...(environment.branch === null && forksForBranches(config) ? { ports: [{ name: "branch-forks", containerPort: BRANCH_FORK_PORT }] } : {}),
|
|
379
168
|
securityContext: restrictedContainer(),
|
|
380
169
|
resources: alasio.resources,
|
|
381
170
|
volumeMounts: [
|
|
382
171
|
{ name: "state", mountPath: "/var/lib/alasio/state" },
|
|
383
172
|
...(operatorHome ? [] : [{ name: "alasio-home", mountPath: home }]),
|
|
384
|
-
{ name: "templates", mountPath: "/etc/alasio", readOnly: true },
|
|
385
173
|
{ name: "database", mountPath: "/run/alasio/database", readOnly: true },
|
|
174
|
+
{ name: "log", mountPath: "/run/alasio/log", readOnly: true },
|
|
386
175
|
...branchSecret.map(({ name }) => ({ name, mountPath: BRANCH_SECRETS, readOnly: true })),
|
|
387
176
|
...(host.enabled ? hostVolumeMounts(config) : []),
|
|
388
177
|
],
|
|
@@ -390,14 +179,14 @@ function deployment(config, templatesChecksum, environment) {
|
|
|
390
179
|
volumes: [
|
|
391
180
|
{ name: "state", emptyDir: {} },
|
|
392
181
|
...(operatorHome ? [] : [{ name: "alasio-home", emptyDir: {} }]),
|
|
393
|
-
{ name: "templates", configMap: { name: componentName("sandbox-templates") } },
|
|
394
182
|
{
|
|
395
183
|
name: "database",
|
|
396
184
|
secret: {
|
|
397
185
|
secretName: databaseSecret(config),
|
|
398
|
-
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 })),
|
|
399
187
|
},
|
|
400
188
|
},
|
|
189
|
+
{ name: "log", secret: { secretName: environmentLogSecret(environment), items: [{ key: "password", path: "password" }] } },
|
|
401
190
|
...branchSecret,
|
|
402
191
|
...(host.enabled ? hostVolumes(config) : []),
|
|
403
192
|
],
|
|
@@ -409,15 +198,6 @@ function deployment(config, templatesChecksum, environment) {
|
|
|
409
198
|
},
|
|
410
199
|
};
|
|
411
200
|
}
|
|
412
|
-
/** Where session sandboxes export their telemetry: alasio's receiver. */
|
|
413
|
-
function telemetryService(config, environment) {
|
|
414
|
-
return {
|
|
415
|
-
apiVersion: "v1",
|
|
416
|
-
kind: "Service",
|
|
417
|
-
metadata: { name: componentName("telemetry"), namespace: environment.namespace, labels: labels("alasio") },
|
|
418
|
-
spec: { selector: selectorLabels("alasio"), ports: [{ name: "otlp-http", port: config.telemetry.receiverPort, targetPort: "telemetry" }] },
|
|
419
|
-
};
|
|
420
|
-
}
|
|
421
201
|
/** Where branch environments ask main to fork the sessions they inherited (src/branch/fork.ts). */
|
|
422
202
|
function branchForksService() {
|
|
423
203
|
return {
|
|
@@ -430,8 +210,13 @@ function branchForksService() {
|
|
|
430
210
|
/**
|
|
431
211
|
* The namespaces workspaces run in, which alasio makes unless told not to. Sessions'
|
|
432
212
|
* enforces Pod Security "restricted": nothing privileged, no host paths, no added
|
|
433
|
-
* capabilities
|
|
434
|
-
*
|
|
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.
|
|
435
220
|
*/
|
|
436
221
|
function namespaces(config, environment) {
|
|
437
222
|
const { sessions, host } = config;
|
|
@@ -448,9 +233,12 @@ function namespaces(config, environment) {
|
|
|
448
233
|
labels: {
|
|
449
234
|
...labels("session"),
|
|
450
235
|
...branched,
|
|
451
|
-
|
|
452
|
-
|
|
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" }),
|
|
453
240
|
"pod-security.kubernetes.io/warn": "restricted",
|
|
241
|
+
"pod-security.kubernetes.io/warn-version": "latest",
|
|
454
242
|
},
|
|
455
243
|
},
|
|
456
244
|
}]
|
|
@@ -465,80 +253,22 @@ function namespaces(config, environment) {
|
|
|
465
253
|
];
|
|
466
254
|
}
|
|
467
255
|
/**
|
|
468
|
-
*
|
|
469
|
-
*
|
|
470
|
-
*
|
|
471
|
-
*/
|
|
472
|
-
function mountPodsRemoved({ workspaceStorage }) {
|
|
473
|
-
return workspaceStorage.enabled && workspaceStorage.csi.enabled;
|
|
474
|
-
}
|
|
475
|
-
/**
|
|
476
|
-
* alasio's identity: it drives its workspaces' Sandboxes, their token Secrets, and reads
|
|
477
|
-
* files from sessions through exec, in the namespaces it owns, labelling their pods busy
|
|
478
|
-
* while turns run in them, as it does its own in its namespace (src/kube/busy.ts); where
|
|
479
|
-
* it snapshots sessions, sets a restored session's readiness; where it forks
|
|
480
|
-
* sessions, reads sessions' volume claims and runs the Jobs that clone them in its own;
|
|
481
|
-
* where the node agents run, watches pods in its own, theirs among them; and, where it
|
|
482
|
-
* installs JuiceFS's driver, lists and deletes pods in the driver's namespace, its mount
|
|
483
|
-
* pods; and 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.
|
|
484
259
|
*/
|
|
485
260
|
function identity(config, environment) {
|
|
486
|
-
const
|
|
487
|
-
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 = {
|
|
488
264
|
apiVersion: "rbac.authorization.k8s.io/v1",
|
|
489
265
|
kind: "RoleBinding",
|
|
490
|
-
metadata,
|
|
266
|
+
metadata: inOwnNamespace,
|
|
491
267
|
subjects: [{ kind: "ServiceAccount", name: RELEASE, namespace: environment.namespace }],
|
|
492
268
|
roleRef: { apiGroup: "rbac.authorization.k8s.io", kind: "Role", name: RELEASE },
|
|
493
|
-
});
|
|
494
|
-
const inDriverNamespace = { name: RELEASE, namespace: config.workspaceStorage.csi.namespace, labels: labels("alasio") };
|
|
495
|
-
const mountPods = {
|
|
496
|
-
apiVersion: "rbac.authorization.k8s.io/v1",
|
|
497
|
-
kind: "Role",
|
|
498
|
-
metadata: inDriverNamespace,
|
|
499
|
-
rules: [{ apiGroups: [""], resources: ["pods"], verbs: ["list", "delete"] }],
|
|
500
|
-
};
|
|
501
|
-
const inOwnNamespace = { name: RELEASE, namespace: environment.namespace, labels: labels("alasio") };
|
|
502
|
-
const own = {
|
|
503
|
-
apiVersion: "rbac.authorization.k8s.io/v1",
|
|
504
|
-
kind: "Role",
|
|
505
|
-
metadata: inOwnNamespace,
|
|
506
|
-
rules: [
|
|
507
|
-
// Its own pod's busy label; and each node's agent, found by its pod on the node.
|
|
508
|
-
{ apiGroups: [""], resources: ["pods"], verbs: main && nodeAgentRuns(config) ? ["list", "watch", "patch"] : ["list", "patch"] },
|
|
509
|
-
...(main && sessionsForked(config) ? [{ apiGroups: ["batch"], resources: ["jobs"], verbs: ["create", "get", "delete"] }] : []),
|
|
510
|
-
],
|
|
511
269
|
};
|
|
512
270
|
const serviceAccount = { apiVersion: "v1", kind: "ServiceAccount", metadata: { name: RELEASE, namespace: environment.namespace, labels: labels("alasio") } };
|
|
513
|
-
return [
|
|
514
|
-
serviceAccount,
|
|
515
|
-
...workspaceNamespaces(config, environment).flatMap((namespace) => {
|
|
516
|
-
const metadata = { name: RELEASE, namespace, labels: labels("alasio") };
|
|
517
|
-
const forked = main && sessionsForked(config) && namespace === config.sessions.namespace;
|
|
518
|
-
const snapshotted = main && nodeAgentRuns(config) && namespace === config.sessions.namespace;
|
|
519
|
-
const role = {
|
|
520
|
-
apiVersion: "rbac.authorization.k8s.io/v1",
|
|
521
|
-
kind: "Role",
|
|
522
|
-
metadata,
|
|
523
|
-
rules: [
|
|
524
|
-
{ apiGroups: ["agents.x-k8s.io"], resources: ["sandboxes"], verbs: ["get", "list", "watch", "create", "patch", "delete"] },
|
|
525
|
-
{ apiGroups: [""], resources: ["secrets"], verbs: ["get", "create"] },
|
|
526
|
-
{ apiGroups: [""], resources: ["pods"], verbs: ["get", "list", "patch"] },
|
|
527
|
-
{ apiGroups: [""], resources: ["pods/exec"], verbs: ["create", "get"] },
|
|
528
|
-
...(forked ? [{ apiGroups: [""], resources: ["persistentvolumeclaims"], verbs: ["get"] }] : []),
|
|
529
|
-
// A restored session's readiness, once its sandbox is let run, and the network policies that must hold it first (src/sandbox/snapshots.ts).
|
|
530
|
-
...(snapshotted
|
|
531
|
-
? [{ apiGroups: [""], resources: ["pods/status"], verbs: ["patch"] }, { apiGroups: ["networking.k8s.io"], resources: ["networkpolicies"], verbs: ["list"] }]
|
|
532
|
-
: []),
|
|
533
|
-
],
|
|
534
|
-
};
|
|
535
|
-
return [role, binding(metadata)];
|
|
536
|
-
}),
|
|
537
|
-
own,
|
|
538
|
-
binding(inOwnNamespace),
|
|
539
|
-
...(main && mountPodsRemoved(config) ? [mountPods, binding(inDriverNamespace)] : []),
|
|
540
|
-
...(config.host.enabled ? hostAgentIdentity(config) : []),
|
|
541
|
-
];
|
|
271
|
+
return [serviceAccount, own, binding, ...(environment.branch === null && foldersRun(config) ? hostAgentIdentity(config) : [])];
|
|
542
272
|
}
|
|
543
273
|
/**
|
|
544
274
|
* Folder workspaces' bayma: the operator's agents, which may restart alasio as they
|
|
@@ -573,31 +303,18 @@ function hostAgentIdentity(config) {
|
|
|
573
303
|
}
|
|
574
304
|
/** The objects of the alasio of `environment`, main's unless a branch environment's, with what main's carries forward. */
|
|
575
305
|
export function alasioObjects(config, environment = MAIN_ENVIRONMENT, carried = NOTHING_CARRIED) {
|
|
576
|
-
const
|
|
577
|
-
const alasio = deployment(config, templates.checksum, environment);
|
|
306
|
+
const alasio = deployment(config, carried.botChecksum, environment);
|
|
578
307
|
return [
|
|
579
308
|
...namespaces(config, environment),
|
|
580
309
|
...identity(config, environment),
|
|
581
|
-
templates.configMap,
|
|
582
310
|
alasio,
|
|
583
311
|
// It runs turns, in its harnesses, which a recreation would end.
|
|
584
312
|
verticalPodAutoscaler(alasio, "Recommended"),
|
|
585
|
-
// A drain waits for the turns running in its pod
|
|
586
|
-
|
|
587
|
-
telemetryService(config, environment),
|
|
313
|
+
// A drain waits for the turns running in its pod to end.
|
|
314
|
+
busyBudget(environment.namespace),
|
|
588
315
|
...(environment.branch === null && forksForBranches(config) ? [branchForksService()] : []),
|
|
589
|
-
// What alasio may do beyond what RBAC can say
|
|
590
|
-
...(environment.branch === null ?
|
|
591
|
-
// Where sessions are snapshotted, what alasio may set of a restored session's pod's status.
|
|
592
|
-
...(environment.branch === null && config.sessions.enabled && nodeAgentRuns(config)
|
|
593
|
-
? resumedConditionPolicy(componentName("resumed-condition"), alasioAccount(environment.namespace), config.sessions.namespace)
|
|
594
|
-
: []),
|
|
595
|
-
...(environment.branch === null && sessionsForked(config) ? cloneJobPolicy(cloneJob(config)) : []),
|
|
596
|
-
...sandboxPolicy(sandboxPolicyName(environment.namespace), alasioAccount(environment.namespace), {
|
|
597
|
-
sessions: config.sessions.enabled ? sessionsProfile(config, environment, carried) : null,
|
|
598
|
-
previousSessions: config.sessions.enabled ? carried.previousSessions : null,
|
|
599
|
-
host: config.host.enabled ? hostProfile(config) : null,
|
|
600
|
-
}),
|
|
316
|
+
// What alasio may do beyond what RBAC can say: the cluster's, made with main's.
|
|
317
|
+
...(environment.branch === null ? busyLabelPolicy() : []),
|
|
601
318
|
];
|
|
602
319
|
}
|
|
603
320
|
//# sourceMappingURL=alasio.js.map
|