@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.
Files changed (63) hide show
  1. package/LICENSE +17 -0
  2. package/README.md +206 -0
  3. package/dist/bundle-store.d.ts +32 -0
  4. package/dist/bundle-store.d.ts.map +1 -0
  5. package/dist/bundle-store.js +86 -0
  6. package/dist/bundle-store.js.map +1 -0
  7. package/dist/capabilities.d.ts +15 -0
  8. package/dist/capabilities.d.ts.map +1 -0
  9. package/dist/capabilities.js +30 -0
  10. package/dist/capabilities.js.map +1 -0
  11. package/dist/config.d.ts +95 -0
  12. package/dist/config.d.ts.map +1 -0
  13. package/dist/config.js +76 -0
  14. package/dist/config.js.map +1 -0
  15. package/dist/k8s/backend.d.ts +19 -0
  16. package/dist/k8s/backend.d.ts.map +1 -0
  17. package/dist/k8s/backend.js +488 -0
  18. package/dist/k8s/backend.js.map +1 -0
  19. package/dist/k8s/client.d.ts +16 -0
  20. package/dist/k8s/client.d.ts.map +1 -0
  21. package/dist/k8s/client.js +24 -0
  22. package/dist/k8s/client.js.map +1 -0
  23. package/dist/k8s/image-build.d.ts +105 -0
  24. package/dist/k8s/image-build.d.ts.map +1 -0
  25. package/dist/k8s/image-build.js +432 -0
  26. package/dist/k8s/image-build.js.map +1 -0
  27. package/dist/k8s/ingress.d.ts +15 -0
  28. package/dist/k8s/ingress.d.ts.map +1 -0
  29. package/dist/k8s/ingress.js +102 -0
  30. package/dist/k8s/ingress.js.map +1 -0
  31. package/dist/k8s/pod-spec.d.ts +41 -0
  32. package/dist/k8s/pod-spec.d.ts.map +1 -0
  33. package/dist/k8s/pod-spec.js +146 -0
  34. package/dist/k8s/pod-spec.js.map +1 -0
  35. package/dist/limits.d.ts +25 -0
  36. package/dist/limits.d.ts.map +1 -0
  37. package/dist/limits.js +58 -0
  38. package/dist/limits.js.map +1 -0
  39. package/dist/server.d.ts +13 -0
  40. package/dist/server.d.ts.map +1 -0
  41. package/dist/server.js +93 -0
  42. package/dist/server.js.map +1 -0
  43. package/dist/tar.d.ts +10 -0
  44. package/dist/tar.d.ts.map +1 -0
  45. package/dist/tar.js +63 -0
  46. package/dist/tar.js.map +1 -0
  47. package/package.json +41 -0
  48. package/src/bundle-store.ts +101 -0
  49. package/src/capabilities.ts +40 -0
  50. package/src/config.ts +201 -0
  51. package/src/k8s/backend-failure.test.ts +148 -0
  52. package/src/k8s/backend.ts +535 -0
  53. package/src/k8s/client.ts +39 -0
  54. package/src/k8s/image-build.test.ts +244 -0
  55. package/src/k8s/image-build.ts +547 -0
  56. package/src/k8s/ingress.test.ts +146 -0
  57. package/src/k8s/ingress.ts +127 -0
  58. package/src/k8s/pod-spec.ts +180 -0
  59. package/src/limits.test.ts +59 -0
  60. package/src/limits.ts +90 -0
  61. package/src/server.ts +124 -0
  62. package/src/tar.test.ts +55 -0
  63. 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
+ }