@telorun/k8s-runner 0.6.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/LICENSE +17 -0
- package/README.md +206 -0
- package/dist/bundle-store.d.ts +32 -0
- package/dist/bundle-store.d.ts.map +1 -0
- package/dist/bundle-store.js +86 -0
- package/dist/bundle-store.js.map +1 -0
- package/dist/capabilities.d.ts +15 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +30 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/config.d.ts +95 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +76 -0
- package/dist/config.js.map +1 -0
- package/dist/k8s/backend.d.ts +19 -0
- package/dist/k8s/backend.d.ts.map +1 -0
- package/dist/k8s/backend.js +488 -0
- package/dist/k8s/backend.js.map +1 -0
- package/dist/k8s/client.d.ts +16 -0
- package/dist/k8s/client.d.ts.map +1 -0
- package/dist/k8s/client.js +24 -0
- package/dist/k8s/client.js.map +1 -0
- package/dist/k8s/image-build.d.ts +105 -0
- package/dist/k8s/image-build.d.ts.map +1 -0
- package/dist/k8s/image-build.js +432 -0
- package/dist/k8s/image-build.js.map +1 -0
- package/dist/k8s/ingress.d.ts +15 -0
- package/dist/k8s/ingress.d.ts.map +1 -0
- package/dist/k8s/ingress.js +102 -0
- package/dist/k8s/ingress.js.map +1 -0
- package/dist/k8s/pod-spec.d.ts +41 -0
- package/dist/k8s/pod-spec.d.ts.map +1 -0
- package/dist/k8s/pod-spec.js +146 -0
- package/dist/k8s/pod-spec.js.map +1 -0
- package/dist/limits.d.ts +25 -0
- package/dist/limits.d.ts.map +1 -0
- package/dist/limits.js +58 -0
- package/dist/limits.js.map +1 -0
- package/dist/server.d.ts +13 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +93 -0
- package/dist/server.js.map +1 -0
- package/dist/tar.d.ts +10 -0
- package/dist/tar.d.ts.map +1 -0
- package/dist/tar.js +63 -0
- package/dist/tar.js.map +1 -0
- package/package.json +41 -0
- package/src/bundle-store.ts +101 -0
- package/src/capabilities.ts +40 -0
- package/src/config.ts +201 -0
- package/src/k8s/backend-failure.test.ts +148 -0
- package/src/k8s/backend.ts +535 -0
- package/src/k8s/client.ts +39 -0
- package/src/k8s/image-build.test.ts +244 -0
- package/src/k8s/image-build.ts +547 -0
- package/src/k8s/ingress.test.ts +146 -0
- package/src/k8s/ingress.ts +127 -0
- package/src/k8s/pod-spec.ts +180 -0
- package/src/limits.test.ts +59 -0
- package/src/limits.ts +90 -0
- package/src/server.ts +124 -0
- package/src/tar.test.ts +55 -0
- package/src/tar.ts +68 -0
package/src/tar.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { gzip } from "node:zlib";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
|
|
4
|
+
import { normalizeBundlePath, type RunBundle } from "@telorun/runner-core";
|
|
5
|
+
|
|
6
|
+
const BLOCK = 512;
|
|
7
|
+
const gzipAsync = promisify(gzip);
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Minimal ustar + gzip writer — enough to ship a Telo bundle to a busybox
|
|
11
|
+
* `tar xzf` initContainer without pulling a tar dependency. Bundle paths are
|
|
12
|
+
* re-normalized (traversal-guarded) before they enter the archive. Gzip runs
|
|
13
|
+
* async so a large, user-controlled bundle doesn't block the event loop (and
|
|
14
|
+
* the runner's HTTP handling) during session creation.
|
|
15
|
+
*/
|
|
16
|
+
export async function makeBundleTarGz(bundle: RunBundle): Promise<Buffer> {
|
|
17
|
+
const blocks: Buffer[] = [];
|
|
18
|
+
for (const file of bundle.files) {
|
|
19
|
+
const name = normalizeBundlePath(file.relativePath);
|
|
20
|
+
// ustar names are capped at 100 bytes; truncating would risk path
|
|
21
|
+
// collisions, so reject instead of silently shortening.
|
|
22
|
+
if (Buffer.byteLength(name, "utf8") > 100) {
|
|
23
|
+
throw new Error(`bundle path too long for tar (max 100 bytes): '${name}'`);
|
|
24
|
+
}
|
|
25
|
+
const content = Buffer.from(file.contents, "utf8");
|
|
26
|
+
blocks.push(makeHeader(name, content.byteLength));
|
|
27
|
+
blocks.push(padToBlock(content));
|
|
28
|
+
}
|
|
29
|
+
// Two zero blocks terminate the archive.
|
|
30
|
+
blocks.push(Buffer.alloc(BLOCK * 2));
|
|
31
|
+
return gzipAsync(Buffer.concat(blocks));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function makeHeader(name: string, size: number): Buffer {
|
|
35
|
+
const header = Buffer.alloc(BLOCK);
|
|
36
|
+
writeString(header, name, 0, 100);
|
|
37
|
+
writeOctal(header, 0o644, 100, 8); // mode
|
|
38
|
+
writeOctal(header, 0, 108, 8); // uid
|
|
39
|
+
writeOctal(header, 0, 116, 8); // gid
|
|
40
|
+
writeOctal(header, size, 124, 12); // size
|
|
41
|
+
writeOctal(header, 0, 136, 12); // mtime (0 — reproducible)
|
|
42
|
+
header.write(" ", 148, 8, "ascii"); // checksum placeholder (spaces)
|
|
43
|
+
header.write("0", 156, 1, "ascii"); // typeflag: regular file
|
|
44
|
+
header.write("ustar\0", 257, 6, "ascii"); // magic
|
|
45
|
+
header.write("00", 263, 2, "ascii"); // version
|
|
46
|
+
|
|
47
|
+
let sum = 0;
|
|
48
|
+
for (let i = 0; i < BLOCK; i++) sum += header[i]!;
|
|
49
|
+
writeOctal(header, sum, 148, 8);
|
|
50
|
+
return header;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function padToBlock(content: Buffer): Buffer {
|
|
54
|
+
const remainder = content.byteLength % BLOCK;
|
|
55
|
+
if (remainder === 0) return content;
|
|
56
|
+
return Buffer.concat([content, Buffer.alloc(BLOCK - remainder)]);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function writeString(buf: Buffer, value: string, offset: number, length: number): void {
|
|
60
|
+
buf.write(value, offset, length, "utf8");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** ustar numeric fields are zero-padded octal, NUL-terminated. */
|
|
64
|
+
function writeOctal(buf: Buffer, value: number, offset: number, length: number): void {
|
|
65
|
+
const octal = value.toString(8);
|
|
66
|
+
const padded = octal.padStart(length - 1, "0").slice(-(length - 1));
|
|
67
|
+
buf.write(padded + "\0", offset, length, "ascii");
|
|
68
|
+
}
|