hammerkit 1.27.0-next.21 → 1.27.0-next.23
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/build.schema.json +70 -0
- package/dist/executer/docker-task.js +21 -1
- package/dist/kubernetes/job-placement.js +36 -12
- package/dist/kubernetes/sandbox-runner.js +3 -1
- package/dist/planner/utils/append-work-task.js +3 -1
- package/dist/planner/work-runtime-kubernetes.js +4 -2
- package/dist/remote/host-config.js +5 -0
- package/dist/remote/remote-work-commands.js +33 -0
- package/dist/schema/build-file-base-task-schema.js +3 -0
- package/dist/schema/build-file-container-service-schema.js +2 -0
- package/dist/schema/build-file-container-task-schema.js +4 -0
- package/dist/schema/build-file-include-schema.js +12 -4
- package/dist/schema/build-file-kubernetes-service-schema.js +2 -0
- package/dist/schema/capabilities-schema.js +56 -0
- package/dist/schema/reference-parser.js +99 -10
- package/dist/schema/schema-parser.js +56 -37
- package/dist/secrets/command-secret-provider.js +3 -1
- package/dist/secrets/secret-catalog.js +43 -19
- package/dist/server/definitions-api.js +62 -1
- package/dist/server/executor.js +1 -0
- package/dist/server/kubernetes-backend.js +71 -8
- package/dist/server/plan.js +62 -41
- package/dist/server/run-worker.js +9 -1
- package/dist/server/server-config.js +29 -0
- package/dist/server/server.js +6 -0
- package/package.json +1 -1
package/build.schema.json
CHANGED
|
@@ -296,6 +296,9 @@
|
|
|
296
296
|
"type": "string",
|
|
297
297
|
"minLength": 1
|
|
298
298
|
},
|
|
299
|
+
"publish": {
|
|
300
|
+
"type": "boolean"
|
|
301
|
+
},
|
|
299
302
|
"image": {
|
|
300
303
|
"type": "string"
|
|
301
304
|
},
|
|
@@ -308,6 +311,56 @@
|
|
|
308
311
|
"volumeSize": {
|
|
309
312
|
"type": "string",
|
|
310
313
|
"description": "size of its claim on Kubernetes, e.g. 10Gi"
|
|
314
|
+
},
|
|
315
|
+
"capAdd": {
|
|
316
|
+
"type": "array",
|
|
317
|
+
"items": {
|
|
318
|
+
"type": "string",
|
|
319
|
+
"enum": [
|
|
320
|
+
"AUDIT_CONTROL",
|
|
321
|
+
"AUDIT_READ",
|
|
322
|
+
"AUDIT_WRITE",
|
|
323
|
+
"BLOCK_SUSPEND",
|
|
324
|
+
"BPF",
|
|
325
|
+
"CHECKPOINT_RESTORE",
|
|
326
|
+
"CHOWN",
|
|
327
|
+
"DAC_OVERRIDE",
|
|
328
|
+
"DAC_READ_SEARCH",
|
|
329
|
+
"FOWNER",
|
|
330
|
+
"FSETID",
|
|
331
|
+
"IPC_LOCK",
|
|
332
|
+
"IPC_OWNER",
|
|
333
|
+
"KILL",
|
|
334
|
+
"LEASE",
|
|
335
|
+
"LINUX_IMMUTABLE",
|
|
336
|
+
"MAC_ADMIN",
|
|
337
|
+
"MAC_OVERRIDE",
|
|
338
|
+
"MKNOD",
|
|
339
|
+
"NET_ADMIN",
|
|
340
|
+
"NET_BIND_SERVICE",
|
|
341
|
+
"NET_BROADCAST",
|
|
342
|
+
"NET_RAW",
|
|
343
|
+
"PERFMON",
|
|
344
|
+
"SETFCAP",
|
|
345
|
+
"SETGID",
|
|
346
|
+
"SETPCAP",
|
|
347
|
+
"SETUID",
|
|
348
|
+
"SYS_ADMIN",
|
|
349
|
+
"SYS_BOOT",
|
|
350
|
+
"SYS_CHROOT",
|
|
351
|
+
"SYS_MODULE",
|
|
352
|
+
"SYS_NICE",
|
|
353
|
+
"SYS_PACCT",
|
|
354
|
+
"SYS_PTRACE",
|
|
355
|
+
"SYS_RAWIO",
|
|
356
|
+
"SYS_RESOURCE",
|
|
357
|
+
"SYS_TIME",
|
|
358
|
+
"SYS_TTY_CONFIG",
|
|
359
|
+
"SYSLOG",
|
|
360
|
+
"WAKE_ALARM"
|
|
361
|
+
]
|
|
362
|
+
},
|
|
363
|
+
"description": "Linux capabilities added to the container, e.g. [SYS_ADMIN]"
|
|
311
364
|
}
|
|
312
365
|
},
|
|
313
366
|
"required": [
|
|
@@ -379,6 +432,9 @@
|
|
|
379
432
|
"runner": {
|
|
380
433
|
"$ref": "#/definitions/hammerkit/properties/tasks/additionalProperties/anyOf/0/properties/runner"
|
|
381
434
|
},
|
|
435
|
+
"publish": {
|
|
436
|
+
"$ref": "#/definitions/hammerkit/properties/tasks/additionalProperties/anyOf/0/properties/publish"
|
|
437
|
+
},
|
|
382
438
|
"platform": {
|
|
383
439
|
"type": "object",
|
|
384
440
|
"properties": {
|
|
@@ -520,6 +576,9 @@
|
|
|
520
576
|
},
|
|
521
577
|
"args": {
|
|
522
578
|
"type": "boolean"
|
|
579
|
+
},
|
|
580
|
+
"publish": {
|
|
581
|
+
"type": "boolean"
|
|
523
582
|
}
|
|
524
583
|
},
|
|
525
584
|
"required": [
|
|
@@ -576,6 +635,9 @@
|
|
|
576
635
|
"number"
|
|
577
636
|
]
|
|
578
637
|
}
|
|
638
|
+
},
|
|
639
|
+
"publish": {
|
|
640
|
+
"type": "boolean"
|
|
579
641
|
}
|
|
580
642
|
},
|
|
581
643
|
"required": [
|
|
@@ -606,6 +668,10 @@
|
|
|
606
668
|
"with": {
|
|
607
669
|
"$ref": "#/definitions/hammerkit/properties/envs",
|
|
608
670
|
"description": "Environment values for the current build task\nhttps://hammerkit.dev/docs/build-file/environment-variables"
|
|
671
|
+
},
|
|
672
|
+
"publish": {
|
|
673
|
+
"type": "boolean",
|
|
674
|
+
"description": "false: a server leaves out what this file declares"
|
|
609
675
|
}
|
|
610
676
|
},
|
|
611
677
|
"required": [
|
|
@@ -633,6 +699,10 @@
|
|
|
633
699
|
"with": {
|
|
634
700
|
"$ref": "#/definitions/hammerkit/properties/envs",
|
|
635
701
|
"description": "Environment values for the current build task\nhttps://hammerkit.dev/docs/build-file/environment-variables"
|
|
702
|
+
},
|
|
703
|
+
"publish": {
|
|
704
|
+
"type": "boolean",
|
|
705
|
+
"description": "false: a server leaves out what this file declares"
|
|
636
706
|
}
|
|
637
707
|
},
|
|
638
708
|
"required": [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.dockerTask = exports.buildCreateOptions = void 0;
|
|
3
|
+
exports.dockerTask = exports.getCapabilityHostConfig = exports.buildCreateOptions = void 0;
|
|
4
4
|
const run_labels_1 = require("../docker/run-labels");
|
|
5
5
|
const execute_docker_1 = require("./execute-docker");
|
|
6
6
|
const abort_1 = require("./abort");
|
|
@@ -47,10 +47,30 @@ function buildCreateOptions(item, stateKey, network, environment, secrets, resou
|
|
|
47
47
|
...(0, item_network_1.getNetworkHostConfig)(network),
|
|
48
48
|
AutoRemove: true,
|
|
49
49
|
...resources,
|
|
50
|
+
...getCapabilityHostConfig(item, environment),
|
|
50
51
|
},
|
|
51
52
|
};
|
|
52
53
|
}
|
|
53
54
|
exports.buildCreateOptions = buildCreateOptions;
|
|
55
|
+
/**
|
|
56
|
+
* The capabilities a task adds (`capAdd`). On a server they are only granted in the
|
|
57
|
+
* sandboxed runtime of `backend.capabilities`, never by the kernel of the docker host.
|
|
58
|
+
*/
|
|
59
|
+
function getCapabilityHostConfig(item, environment) {
|
|
60
|
+
const capAdd = item.data.capAdd;
|
|
61
|
+
if (capAdd.length === 0) {
|
|
62
|
+
return {};
|
|
63
|
+
}
|
|
64
|
+
if (!environment.hosted) {
|
|
65
|
+
return { CapAdd: capAdd };
|
|
66
|
+
}
|
|
67
|
+
const runtime = environment.hosted.capabilityRuntime;
|
|
68
|
+
if (!runtime) {
|
|
69
|
+
throw new Error(`${item.name}: adds the capabilities ${capAdd.join(', ')}, which this server grants in no sandboxed runtime`);
|
|
70
|
+
}
|
|
71
|
+
return { CapAdd: capAdd, Runtime: runtime };
|
|
72
|
+
}
|
|
73
|
+
exports.getCapabilityHostConfig = getCapabilityHostConfig;
|
|
54
74
|
async function dockerTask(docker, item, environment, options) {
|
|
55
75
|
item.status.write('info', `execute ${item.name} in container`);
|
|
56
76
|
let network = null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getContainerSecurity = exports.getRunLabels = exports.getRunLabelValue = exports.RUN_LABEL = exports.getPodPlacement = exports.placeOnPool = exports.getNodeArch = exports.runInToolImage = exports.getLocalTaskPool = void 0;
|
|
3
|
+
exports.getPodRuntimeClass = exports.getContainerSecurity = exports.getRunLabels = exports.getRunLabelValue = exports.RUN_LABEL = exports.getPodPlacement = exports.placeOnPool = exports.getNodeArch = exports.runInToolImage = exports.getLocalTaskPool = void 0;
|
|
4
4
|
const crypto_1 = require("crypto");
|
|
5
5
|
/**
|
|
6
6
|
* The pool a local task runs on: the first that offers its platform. A pool says
|
|
@@ -34,6 +34,7 @@ function runInToolImage(task, server, platform) {
|
|
|
34
34
|
user: null,
|
|
35
35
|
mounts: [],
|
|
36
36
|
volumeSize: null,
|
|
37
|
+
capAdd: [],
|
|
37
38
|
pool: pool.name,
|
|
38
39
|
arch: getNodeArch(pool),
|
|
39
40
|
};
|
|
@@ -82,18 +83,41 @@ exports.getRunLabels = getRunLabels;
|
|
|
82
83
|
/**
|
|
83
84
|
* What a container of a run may do on a server, where it shares nodes with the pods of
|
|
84
85
|
* other callers: no privilege escalation (setuid binaries such as sudo), no raw sockets
|
|
85
|
-
* (spoofing on a bridge network) and the runtime's seccomp profile.
|
|
86
|
+
* (spoofing on a bridge network) and the runtime's seccomp profile. The capabilities a
|
|
87
|
+
* task adds (`capAdd`) come on top, in the sandbox of getPodRuntimeClass on a server.
|
|
86
88
|
*/
|
|
87
|
-
function getContainerSecurity(kubernetes) {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
89
|
+
function getContainerSecurity(kubernetes, capAdd = []) {
|
|
90
|
+
const add = capAdd.length > 0 ? { add: [...capAdd] } : {};
|
|
91
|
+
if (!kubernetes.server) {
|
|
92
|
+
return capAdd.length > 0 ? { securityContext: { capabilities: add } } : {};
|
|
93
|
+
}
|
|
94
|
+
const drop = capAdd.includes('NET_RAW') ? {} : { drop: ['NET_RAW'] };
|
|
95
|
+
return {
|
|
96
|
+
securityContext: {
|
|
97
|
+
allowPrivilegeEscalation: false,
|
|
98
|
+
capabilities: { ...drop, ...add },
|
|
99
|
+
seccompProfile: { type: 'RuntimeDefault' },
|
|
100
|
+
},
|
|
101
|
+
};
|
|
97
102
|
}
|
|
98
103
|
exports.getContainerSecurity = getContainerSecurity;
|
|
104
|
+
/**
|
|
105
|
+
* The RuntimeClass of the pod of a task that adds capabilities on a server: the sandbox the
|
|
106
|
+
* operator named (`backend.capabilities.runtimeClass`), so the capabilities hold in its own
|
|
107
|
+
* kernel and never in the node's. Elsewhere the cluster is the build file's own.
|
|
108
|
+
*/
|
|
109
|
+
function getPodRuntimeClass(task, kubernetes) {
|
|
110
|
+
if (task.capAdd.length === 0 || !kubernetes.server) {
|
|
111
|
+
return {};
|
|
112
|
+
}
|
|
113
|
+
const sandbox = kubernetes.server.capabilities;
|
|
114
|
+
if (!sandbox) {
|
|
115
|
+
throw new Error(`${task.name}: adds the capabilities ${task.capAdd.join(', ')}, which this server grants in no sandboxed runtime`);
|
|
116
|
+
}
|
|
117
|
+
if (sandbox.unavailable) {
|
|
118
|
+
throw new Error(`${task.name}: adds the capabilities ${task.capAdd.join(', ')}, but ${sandbox.unavailable}`);
|
|
119
|
+
}
|
|
120
|
+
return { runtimeClassName: sandbox.runtimeClass };
|
|
121
|
+
}
|
|
122
|
+
exports.getPodRuntimeClass = getPodRuntimeClass;
|
|
99
123
|
//# sourceMappingURL=job-placement.js.map
|
|
@@ -151,7 +151,9 @@ function canUseRunner(task, kubernetes, persistence) {
|
|
|
151
151
|
persistence.mounts.some((mount) => (0, path_1.relative)(workspace.root, mount.mount.mountPath) === '') &&
|
|
152
152
|
task.needs.length === 0 &&
|
|
153
153
|
task.data.secrets.length === 0 &&
|
|
154
|
-
task.data.generates.length === 0
|
|
154
|
+
task.data.generates.length === 0 &&
|
|
155
|
+
// its pod would need the sandboxed runtime of a Job
|
|
156
|
+
task.data.capAdd.length === 0);
|
|
155
157
|
}
|
|
156
158
|
exports.canUseRunner = canUseRunner;
|
|
157
159
|
// What the runner is made of: the same key for the same pod
|
|
@@ -92,10 +92,12 @@ function parseTask(cwd, task, environment, context) {
|
|
|
92
92
|
return {
|
|
93
93
|
...baseWorkNode,
|
|
94
94
|
type: 'container-task',
|
|
95
|
-
|
|
95
|
+
// a capability holds for root only: a task that adds some runs as its image's user
|
|
96
|
+
user: task.schema.capAdd?.length ? null : (0, get_container_user_1.getContainerUser)(),
|
|
96
97
|
image: (0, template_value_1.templateValue)(task.schema.image, envs),
|
|
97
98
|
mounts: (0, parse_work_mounts_1.parseWorkMounts)(cwd, task.schema, envs),
|
|
98
99
|
volumeSize: task.schema.volumeSize ?? null,
|
|
100
|
+
capAdd: task.schema.capAdd ?? [],
|
|
99
101
|
};
|
|
100
102
|
}
|
|
101
103
|
else {
|
|
@@ -130,7 +130,8 @@ exports.describeFailedJob = describeFailedJob;
|
|
|
130
130
|
* The containers of the Job of a command: the network gate first, nothing runs before the
|
|
131
131
|
* item's policy holds, then the init containers that read its secrets, then the command. The
|
|
132
132
|
* proxy's token (`network.secretEnv`) reaches the init containers through `secretSpec` only:
|
|
133
|
-
* the command's container gets the proxy variables of a limited network without it.
|
|
133
|
+
* the command's container gets the proxy variables of a limited network without it. A task that
|
|
134
|
+
* adds capabilities gets them in the sandbox's RuntimeClass only.
|
|
134
135
|
*/
|
|
135
136
|
function getTaskJobContainers(options) {
|
|
136
137
|
const { task, cmd, envs, secrets, network, secretSpec, kubernetes } = options;
|
|
@@ -155,9 +156,10 @@ function getTaskJobContainers(options) {
|
|
|
155
156
|
name: options.container,
|
|
156
157
|
volumeMounts: [...options.mounts, ...secrets.mounts, ...secretSpec.mounts],
|
|
157
158
|
...(0, container_resources_1.getKubernetesResources)(task.data.resources),
|
|
158
|
-
...(0, job_placement_1.getContainerSecurity)(kubernetes),
|
|
159
|
+
...(0, job_placement_1.getContainerSecurity)(kubernetes, task.data.capAdd),
|
|
159
160
|
},
|
|
160
161
|
],
|
|
162
|
+
...(0, job_placement_1.getPodRuntimeClass)({ name: task.name, capAdd: task.data.capAdd }, kubernetes),
|
|
161
163
|
};
|
|
162
164
|
}
|
|
163
165
|
exports.getTaskJobContainers = getTaskJobContainers;
|
|
@@ -5,6 +5,7 @@ const path_1 = require("path");
|
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const yaml_1 = require("yaml");
|
|
7
7
|
const get_cache_directory_1 = require("../optimizer/get-cache-directory");
|
|
8
|
+
const build_file_secret_provider_schema_1 = require("../schema/build-file-secret-provider-schema");
|
|
8
9
|
// Names with a meaning of their own in `run.on` / `--on`
|
|
9
10
|
exports.RESERVED_SERVER_NAMES = ['local', 'auto'];
|
|
10
11
|
const serverNamePattern = /^[a-z0-9][a-z0-9._-]*$/i;
|
|
@@ -43,6 +44,10 @@ exports.hostConfigSchema = zod_1.z
|
|
|
43
44
|
servers: zod_1.z.record(exports.hostServerSchema).default({}),
|
|
44
45
|
tokenCommands: zod_1.z.record(tokenCommandSchema).optional(),
|
|
45
46
|
run: zod_1.z.object({ on: zod_1.z.string().optional() }).passthrough().default({}),
|
|
47
|
+
// how this machine reads secrets, beside what the build files declare (see
|
|
48
|
+
// collectSecretCatalog); a server reads only its own config
|
|
49
|
+
secretProviders: build_file_secret_provider_schema_1.buildFileSecretProvidersSchema.optional(),
|
|
50
|
+
secretAccounts: build_file_secret_provider_schema_1.buildFileSecretAccountsSchema.optional(),
|
|
46
51
|
})
|
|
47
52
|
.passthrough();
|
|
48
53
|
// Names like "constructor" must not find inherited members.
|
|
@@ -17,6 +17,22 @@ const units_1 = require("../utils/units");
|
|
|
17
17
|
const service_tools_1 = require("../harness/service-tools");
|
|
18
18
|
const path_1 = require("path");
|
|
19
19
|
const check_keys_1 = require("../optimizer/check-keys");
|
|
20
|
+
function describeOutcome(planned) {
|
|
21
|
+
switch (planned.outcome) {
|
|
22
|
+
case 'published':
|
|
23
|
+
return 'publishing it would publish it';
|
|
24
|
+
case 'already published':
|
|
25
|
+
return planned.yanked ? 'it is published already, and yanked' : 'it is published already';
|
|
26
|
+
case 'proposed':
|
|
27
|
+
return planned.missing?.length
|
|
28
|
+
? `publishing it would propose it, it names accounts you do not use: ${planned.missing
|
|
29
|
+
.map(server_client_1.printable)
|
|
30
|
+
.join(', ')}`
|
|
31
|
+
: 'publishing it would propose it, somebody who may publish approves it';
|
|
32
|
+
default:
|
|
33
|
+
return 'the server accepts it, publishing it needs builds: propose or publish';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
20
36
|
const RUN_ID = /^run_[A-Za-z0-9_-]{16}$/;
|
|
21
37
|
// how a check passed, one line
|
|
22
38
|
function describePassed(passed) {
|
|
@@ -106,6 +122,7 @@ function describePlan(plan) {
|
|
|
106
122
|
...(entry.mounts.length > 0 ? [` mounts: ${entry.mounts.map(server_client_1.printable).join(', ')}`] : []),
|
|
107
123
|
...(entry.ports.length > 0 ? [` ports: ${entry.ports.map(server_client_1.printable).join(', ')}`] : []),
|
|
108
124
|
...(entry.generates.length > 0 ? [` generates: ${entry.generates.map(server_client_1.printable).join(', ')}`] : []),
|
|
125
|
+
...(entry.capAdd?.length ? [` capAdd: ${entry.capAdd.map(server_client_1.printable).join(', ')}`] : []),
|
|
109
126
|
]);
|
|
110
127
|
}
|
|
111
128
|
exports.describePlan = describePlan;
|
|
@@ -136,8 +153,24 @@ function registerWorkCommands(remote, context) {
|
|
|
136
153
|
.command('publish [server]')
|
|
137
154
|
.description('publish the build file and the files it includes to a server, runs refer to it by its hash')
|
|
138
155
|
.addOption(new commander_1.Option('--annotation <key=value>', 'say more about where it comes from, or leave one out with key=; path, repo, commit, machine and user are filled in').argParser(collectOption))
|
|
156
|
+
.addOption(new commander_1.Option('--dry-run', "check it against the server's policy and say what publishing would do, without publishing; builds: run is enough"))
|
|
139
157
|
.action(guarded('Remote publish was not successful', async (name, options) => {
|
|
140
158
|
const bundle = await (0, collect_bundle_1.collectBundle)(buildFile, environment);
|
|
159
|
+
if (options.dryRun) {
|
|
160
|
+
const { name: serverName, server, token } = await connect(name);
|
|
161
|
+
const answer = await (0, server_client_1.callServer)(server, token, 'POST', '/v1/definitions/plan', bundle).catch((e) => {
|
|
162
|
+
throw e instanceof server_client_1.ServerError && e.status === 404
|
|
163
|
+
? new Error(`${serverName} can't check a build file without publishing it, it needs hammerkit 1.27`)
|
|
164
|
+
: e;
|
|
165
|
+
});
|
|
166
|
+
const planned = answer.body;
|
|
167
|
+
const files = Object.keys(bundle.files).length;
|
|
168
|
+
environment.stdout.write(`checked with the policy of ${serverName}: ${(0, server_client_1.printable)(planned.hash)} (${files} ${files === 1 ? 'file' : 'files'}), nothing was published\n`);
|
|
169
|
+
const names = [...(planned.tasks ?? []), ...(planned.services ?? [])];
|
|
170
|
+
environment.stdout.write(`tasks and services: ${names.map(server_client_1.printable).join(', ') || 'none'}\n`);
|
|
171
|
+
environment.stdout.write(`${describeOutcome(planned)}\n`);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
141
174
|
const annotations = (0, annotations_1.applyAnnotations)(await (0, annotations_1.collectAnnotations)(buildFile, Object.keys(bundle.files)), options.annotation ?? []);
|
|
142
175
|
const { name: serverName, server, token } = await connect(name);
|
|
143
176
|
const answer = await (0, server_client_1.callServer)(server, token, 'POST', '/v1/definitions', {
|
|
@@ -49,5 +49,8 @@ exports.buildFileBaseTaskSchema = (0, zod_1.object)({
|
|
|
49
49
|
// Name of the server (see `hammerkit remote`) the task has to run on; defaults
|
|
50
50
|
// to the build file's `runner`. Never a local fallback when it is unknown.
|
|
51
51
|
runner: runner_schema_1.runnerSchema.optional(),
|
|
52
|
+
// false: a server leaves it out of a published version, for a task only this machine
|
|
53
|
+
// runs (a dev watcher, a task that mounts the docker socket)
|
|
54
|
+
publish: (0, zod_1.boolean)().optional(),
|
|
52
55
|
});
|
|
53
56
|
//# sourceMappingURL=build-file-base-task-schema.js.map
|
|
@@ -47,6 +47,8 @@ exports.buildFileContainerServiceSchema = (0, zod_1.object)({
|
|
|
47
47
|
network: network_schema_1.networkSchema.optional(),
|
|
48
48
|
// whether its `cmd` takes the arguments after `--` of `up`: false refuses them
|
|
49
49
|
args: (0, zod_1.boolean)().optional(),
|
|
50
|
+
// false: a server leaves it out of a published version
|
|
51
|
+
publish: (0, zod_1.boolean)().optional(),
|
|
50
52
|
})
|
|
51
53
|
.strict()
|
|
52
54
|
.describe('container service');
|
|
@@ -4,12 +4,16 @@ exports.buildFileContainerTaskSchema = void 0;
|
|
|
4
4
|
const build_file_base_task_schema_1 = require("./build-file-base-task-schema");
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const size_schema_1 = require("./size-schema");
|
|
7
|
+
const capabilities_schema_1 = require("./capabilities-schema");
|
|
7
8
|
exports.buildFileContainerTaskSchema = build_file_base_task_schema_1.buildFileBaseTaskSchema
|
|
8
9
|
.extend({
|
|
9
10
|
image: (0, zod_1.string)(),
|
|
10
11
|
mounts: (0, zod_1.array)((0, zod_1.string)()).optional(),
|
|
11
12
|
// on Kubernetes, the size of the claim that holds its sources, mounts and outputs
|
|
12
13
|
volumeSize: size_schema_1.sizeSchema.describe('size of its claim on Kubernetes, e.g. 10Gi').optional(),
|
|
14
|
+
// Linux capabilities added to the container, such as SYS_ADMIN for a daemonless image
|
|
15
|
+
// build. A server allows them only in a sandboxed runtime (`backend.capabilities`).
|
|
16
|
+
capAdd: capabilities_schema_1.capabilitiesSchema.describe('Linux capabilities added to the container, e.g. [SYS_ADMIN]').optional(),
|
|
13
17
|
})
|
|
14
18
|
.strict()
|
|
15
19
|
.describe('container task');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isGitSource = exports.buildFileIncludeSchema = exports.buildFileLocalSourceSchema = exports.buildFileGitSourceSchema = void 0;
|
|
3
|
+
exports.isPublished = exports.isGitSource = exports.buildFileIncludeSchema = exports.buildFileLocalSourceSchema = exports.buildFileGitSourceSchema = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const envs_schema_1 = require("./envs-schema");
|
|
6
6
|
// A repo URL or ref starting with `-` would be read by git as an option
|
|
@@ -21,17 +21,25 @@ exports.buildFileGitSourceSchema = (0, zod_1.object)({
|
|
|
21
21
|
path: (0, zod_1.string)().optional().describe('Build file or directory within the repository'),
|
|
22
22
|
// overrides for the top-level `envs` the included file declares as its inputs
|
|
23
23
|
with: envs_schema_1.envsSchema.optional(),
|
|
24
|
+
publish: (0, zod_1.boolean)().optional().describe('false: a server leaves out what this file declares'),
|
|
24
25
|
}).strict();
|
|
25
|
-
// A local path with values for the inputs of the file it names
|
|
26
|
-
// source
|
|
26
|
+
// A local path, with values for the inputs of the file it names like `with` of a git
|
|
27
|
+
// source (a value may pass on an `envs` value of the including file as `${NAME}`), and
|
|
28
|
+
// whether a server publishes what it declares.
|
|
27
29
|
exports.buildFileLocalSourceSchema = (0, zod_1.object)({
|
|
28
30
|
path: (0, zod_1.string)().min(1).describe('Build file or directory, relative to the including file'),
|
|
29
31
|
with: envs_schema_1.envsSchema.optional(),
|
|
32
|
+
publish: (0, zod_1.boolean)().optional().describe('false: a server leaves out what this file declares'),
|
|
30
33
|
}).strict();
|
|
31
|
-
// A string is a local path; an object is a local path with
|
|
34
|
+
// A string is a local path; an object is a local path with options, or a git source (ADR-0004).
|
|
32
35
|
exports.buildFileIncludeSchema = (0, zod_1.union)([(0, zod_1.string)(), exports.buildFileLocalSourceSchema, exports.buildFileGitSourceSchema]);
|
|
33
36
|
function isGitSource(include) {
|
|
34
37
|
return typeof include !== 'string' && 'git' in include;
|
|
35
38
|
}
|
|
36
39
|
exports.isGitSource = isGitSource;
|
|
40
|
+
// `publish: false`: what the file declares is left out of a version a server publishes
|
|
41
|
+
function isPublished(include) {
|
|
42
|
+
return typeof include === 'string' || include.publish !== false;
|
|
43
|
+
}
|
|
44
|
+
exports.isPublished = isPublished;
|
|
37
45
|
//# sourceMappingURL=build-file-include-schema.js.map
|
|
@@ -13,5 +13,7 @@ exports.buildFileKubernetesServiceSchema = (0, zod_1.object)({
|
|
|
13
13
|
selector: build_file_kubernetes_service_selector_schema_1.buildFileKubernetesServiceSelectorSchema,
|
|
14
14
|
labels: labels_schema_1.labelsSchema.optional(),
|
|
15
15
|
ports: (0, zod_1.array)((0, zod_1.union)([(0, zod_1.string)(), (0, zod_1.number)()])),
|
|
16
|
+
// false: a server leaves it out of a published version
|
|
17
|
+
publish: (0, zod_1.boolean)().optional(),
|
|
16
18
|
}).strict();
|
|
17
19
|
//# sourceMappingURL=build-file-kubernetes-service-schema.js.map
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.capabilitiesSchema = exports.LINUX_CAPABILITIES = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
// The Linux capabilities, without the CAP_ prefix (capabilities(7))
|
|
6
|
+
exports.LINUX_CAPABILITIES = [
|
|
7
|
+
'AUDIT_CONTROL',
|
|
8
|
+
'AUDIT_READ',
|
|
9
|
+
'AUDIT_WRITE',
|
|
10
|
+
'BLOCK_SUSPEND',
|
|
11
|
+
'BPF',
|
|
12
|
+
'CHECKPOINT_RESTORE',
|
|
13
|
+
'CHOWN',
|
|
14
|
+
'DAC_OVERRIDE',
|
|
15
|
+
'DAC_READ_SEARCH',
|
|
16
|
+
'FOWNER',
|
|
17
|
+
'FSETID',
|
|
18
|
+
'IPC_LOCK',
|
|
19
|
+
'IPC_OWNER',
|
|
20
|
+
'KILL',
|
|
21
|
+
'LEASE',
|
|
22
|
+
'LINUX_IMMUTABLE',
|
|
23
|
+
'MAC_ADMIN',
|
|
24
|
+
'MAC_OVERRIDE',
|
|
25
|
+
'MKNOD',
|
|
26
|
+
'NET_ADMIN',
|
|
27
|
+
'NET_BIND_SERVICE',
|
|
28
|
+
'NET_BROADCAST',
|
|
29
|
+
'NET_RAW',
|
|
30
|
+
'PERFMON',
|
|
31
|
+
'SETFCAP',
|
|
32
|
+
'SETGID',
|
|
33
|
+
'SETPCAP',
|
|
34
|
+
'SETUID',
|
|
35
|
+
'SYS_ADMIN',
|
|
36
|
+
'SYS_BOOT',
|
|
37
|
+
'SYS_CHROOT',
|
|
38
|
+
'SYS_MODULE',
|
|
39
|
+
'SYS_NICE',
|
|
40
|
+
'SYS_PACCT',
|
|
41
|
+
'SYS_PTRACE',
|
|
42
|
+
'SYS_RAWIO',
|
|
43
|
+
'SYS_RESOURCE',
|
|
44
|
+
'SYS_TIME',
|
|
45
|
+
'SYS_TTY_CONFIG',
|
|
46
|
+
'SYSLOG',
|
|
47
|
+
'WAKE_ALARM',
|
|
48
|
+
];
|
|
49
|
+
// Capabilities a container gets on top of its runtime's default set, by name such as
|
|
50
|
+
// SYS_ADMIN. `ALL` is not one: a task names what it needs.
|
|
51
|
+
exports.capabilitiesSchema = (0, zod_1.array)((0, zod_1.enum)(exports.LINUX_CAPABILITIES, {
|
|
52
|
+
errorMap: (issue, ctx) => issue.code === 'invalid_enum_value'
|
|
53
|
+
? { message: `unknown capability ${JSON.stringify(issue.received)}, expected a name such as SYS_ADMIN` }
|
|
54
|
+
: { message: ctx.defaultError },
|
|
55
|
+
})).refine((names) => new Set(names).size === names.length, 'a capability is listed twice');
|
|
56
|
+
//# sourceMappingURL=capabilities-schema.js.map
|