@alchemy.run/kubernetes 0.0.0 → 2.0.0-beta.85

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 (94) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +41 -4
  3. package/lib/BuiltinAdapters.d.ts +43 -0
  4. package/lib/BuiltinAdapters.d.ts.map +1 -0
  5. package/lib/BuiltinAdapters.js +129 -0
  6. package/lib/BuiltinAdapters.js.map +1 -0
  7. package/lib/Client.d.ts +97 -0
  8. package/lib/Client.d.ts.map +1 -0
  9. package/lib/Client.js +312 -0
  10. package/lib/Client.js.map +1 -0
  11. package/lib/ClusterAdapter.d.ts +324 -0
  12. package/lib/ClusterAdapter.d.ts.map +1 -0
  13. package/lib/ClusterAdapter.js +65 -0
  14. package/lib/ClusterAdapter.js.map +1 -0
  15. package/lib/Connection.d.ts +210 -0
  16. package/lib/Connection.d.ts.map +1 -0
  17. package/lib/Connection.js +58 -0
  18. package/lib/Connection.js.map +1 -0
  19. package/lib/Deployment.d.ts +401 -0
  20. package/lib/Deployment.d.ts.map +1 -0
  21. package/lib/Deployment.js +550 -0
  22. package/lib/Deployment.js.map +1 -0
  23. package/lib/HelmChart.d.ts +147 -0
  24. package/lib/HelmChart.d.ts.map +1 -0
  25. package/lib/HelmChart.js +248 -0
  26. package/lib/HelmChart.js.map +1 -0
  27. package/lib/Job.d.ts +333 -0
  28. package/lib/Job.d.ts.map +1 -0
  29. package/lib/Job.js +443 -0
  30. package/lib/Job.js.map +1 -0
  31. package/lib/LocalCluster.d.ts +243 -0
  32. package/lib/LocalCluster.d.ts.map +1 -0
  33. package/lib/LocalCluster.js +359 -0
  34. package/lib/LocalCluster.js.map +1 -0
  35. package/lib/Manifest.d.ts +157 -0
  36. package/lib/Manifest.d.ts.map +1 -0
  37. package/lib/Manifest.js +205 -0
  38. package/lib/Manifest.js.map +1 -0
  39. package/lib/Objects.d.ts +60 -0
  40. package/lib/Objects.d.ts.map +1 -0
  41. package/lib/Objects.js +132 -0
  42. package/lib/Objects.js.map +1 -0
  43. package/lib/Providers.d.ts +24 -0
  44. package/lib/Providers.d.ts.map +1 -0
  45. package/lib/Providers.js +36 -0
  46. package/lib/Providers.js.map +1 -0
  47. package/lib/index.d.ts +10 -0
  48. package/lib/index.d.ts.map +1 -0
  49. package/lib/index.js +10 -0
  50. package/lib/index.js.map +1 -0
  51. package/lib/internal/declared.d.ts +19 -0
  52. package/lib/internal/declared.d.ts.map +1 -0
  53. package/lib/internal/declared.js +435 -0
  54. package/lib/internal/declared.js.map +1 -0
  55. package/lib/internal/helm.d.ts +65 -0
  56. package/lib/internal/helm.d.ts.map +1 -0
  57. package/lib/internal/helm.js +173 -0
  58. package/lib/internal/helm.js.map +1 -0
  59. package/lib/internal/kind.d.ts +17 -0
  60. package/lib/internal/kind.d.ts.map +1 -0
  61. package/lib/internal/kind.js +31 -0
  62. package/lib/internal/kind.js.map +1 -0
  63. package/lib/internal/kubeconfig.d.ts +79 -0
  64. package/lib/internal/kubeconfig.d.ts.map +1 -0
  65. package/lib/internal/kubeconfig.js +222 -0
  66. package/lib/internal/kubeconfig.js.map +1 -0
  67. package/lib/internal/registry.d.ts +44 -0
  68. package/lib/internal/registry.d.ts.map +1 -0
  69. package/lib/internal/registry.js +72 -0
  70. package/lib/internal/registry.js.map +1 -0
  71. package/lib/internal/workload.d.ts +127 -0
  72. package/lib/internal/workload.d.ts.map +1 -0
  73. package/lib/internal/workload.js +411 -0
  74. package/lib/internal/workload.js.map +1 -0
  75. package/package.json +55 -3
  76. package/src/BuiltinAdapters.ts +202 -0
  77. package/src/Client.ts +496 -0
  78. package/src/ClusterAdapter.ts +373 -0
  79. package/src/Connection.ts +234 -0
  80. package/src/Deployment.ts +872 -0
  81. package/src/HelmChart.ts +388 -0
  82. package/src/Job.ts +709 -0
  83. package/src/LocalCluster.ts +631 -0
  84. package/src/Manifest.ts +301 -0
  85. package/src/Objects.ts +213 -0
  86. package/src/Providers.ts +52 -0
  87. package/src/globals.d.ts +2 -0
  88. package/src/index.ts +9 -0
  89. package/src/internal/declared.ts +471 -0
  90. package/src/internal/helm.ts +245 -0
  91. package/src/internal/kind.ts +43 -0
  92. package/src/internal/kubeconfig.ts +364 -0
  93. package/src/internal/registry.ts +108 -0
  94. package/src/internal/workload.ts +504 -0
package/lib/Job.js ADDED
@@ -0,0 +1,443 @@
1
+ import { isResolved } from "alchemy/Diff";
2
+ import * as Output from "alchemy/Output";
3
+ import { createPhysicalName } from "alchemy/PhysicalName";
4
+ import { Platform } from "alchemy/Platform";
5
+ import * as Provider from "alchemy/Provider";
6
+ import { Resource } from "alchemy/Resource";
7
+ import { packEnvValue, unpackEnvValue, RuntimeContext } from "alchemy/RuntimeContext";
8
+ import { Stack } from "alchemy/Stack";
9
+ import { createInternalTags } from "alchemy/Tags";
10
+ import { unwrapRedacted } from "alchemy/Util/data";
11
+ import { sha256Object } from "alchemy/Util/sha256";
12
+ import * as Effect from "effect/Effect";
13
+ import { connectCluster, deleteObjects, ifClusterExists, readObject, reconcileObjects, } from "./Client.js";
14
+ import { findClusterAdapter, } from "./ClusterAdapter.js";
15
+ import { toConnection } from "./Connection.js";
16
+ import { makeConnectionRegistry } from "./internal/registry.js";
17
+ import { collectBindingEnv, containerEnvValue, connectionIdentity, connectionOfOutput, deepMerge, imagePlatformOf, makeJobBootstrap, resolveWorkloadImage, tryConnectionOf, workloadImageHash, } from "./internal/workload.js";
18
+ export const isJob = (value) => typeof value === "object" && value !== null && "Type" in value && value.Type === "Kubernetes.Job";
19
+ /**
20
+ * Run-to-completion work on any Kubernetes cluster, as a container image
21
+ * or an Effect program.
22
+ *
23
+ * `Job` provisions a Kubernetes `Job` (or `CronJob` when `schedule` is
24
+ * set) via server-side apply and a ServiceAccount, plus — through the
25
+ * target cluster's platform adapter — workload identity and a container
26
+ * image from exactly one of three sources flat on props: `main` (bundle an
27
+ * inline Effect program whose impl returns `{ run }`), `context` (build
28
+ * your own Dockerfile), or `image` (a pre-built registry reference).
29
+ * `main` and `context` images are built on the deploying machine and
30
+ * pushed to the connection's registry (`Kubernetes.LocalCluster` includes
31
+ * one; EKS uses ECR; GKE uses Artifact Registry). On `AWS.EKS.Cluster`
32
+ * targets, bindings attach IAM policy statements to a generated
33
+ * pod-identity role; on `GCP.Container.Cluster` targets, GCP bindings grant
34
+ * their IAM roles to the Kubernetes ServiceAccount's Workload Identity
35
+ * Federation principal — exactly like `Kubernetes.Deployment`.
36
+ * ### Creating a Job
37
+ * **Example:** Remote image (external — no Effect runtime in the container)
38
+ * ```typescript
39
+ * const migrate = yield* Kubernetes.Job("DbMigrate", {
40
+ * cluster,
41
+ * image: "ghcr.io/acme/migrator:v3",
42
+ * backoffLimit: 2,
43
+ * });
44
+ * ```
45
+ *
46
+ * **Example:** Your own Dockerfile with build args and secrets
47
+ * ```typescript
48
+ * // Dockerfile:
49
+ * // ARG NODE_ENV
50
+ * // RUN --mount=type=secret,id=NPM_TOKEN,env=NPM_TOKEN npm ci
51
+ * const migrate = yield* Kubernetes.Job("DbMigrate", {
52
+ * cluster,
53
+ * context: "./migrator",
54
+ * build: {
55
+ * args: { NODE_ENV: "production" },
56
+ * // Mounted only into the RUN step that asks for it; never in the image.
57
+ * secrets: { NPM_TOKEN: Config.Redacted("NPM_TOKEN") },
58
+ * },
59
+ * backoffLimit: 2,
60
+ * });
61
+ * ```
62
+ *
63
+ * **Example:** Inline Effect program
64
+ * ```typescript
65
+ * const cluster = yield* Kubernetes.LocalCluster("Cluster", {
66
+ * name: "alchemy",
67
+ * });
68
+ *
69
+ * const hello = yield* Kubernetes.Job(
70
+ * "Hello",
71
+ * { cluster, main: import.meta.url, backoffLimit: 2 },
72
+ * Effect.gen(function* () {
73
+ * return {
74
+ * run: Effect.log("hello from a Job"),
75
+ * };
76
+ * }),
77
+ * );
78
+ * ```
79
+ *
80
+ * **Example:** Inline Effect program with a DynamoDB binding (EKS)
81
+ * ```typescript
82
+ * const seed = yield* Kubernetes.Job(
83
+ * "SeedData",
84
+ * { cluster, main: import.meta.url },
85
+ * Effect.gen(function* () {
86
+ * const putItem = yield* AWS.DynamoDB.PutItem(table);
87
+ * return {
88
+ * run: Effect.gen(function* () {
89
+ * yield* putItem({ Item: { id: { S: "seed" } } });
90
+ * }),
91
+ * };
92
+ * }).pipe(Effect.provide(AWS.DynamoDB.PutItemHttp)),
93
+ * );
94
+ * ```
95
+ *
96
+ * **Example:** Tagged Effect program
97
+ * ```typescript
98
+ * export class Backfill extends Kubernetes.Job<Backfill, {
99
+ * progress: () => Effect.Effect<number>;
100
+ * }>()("Backfill") {}
101
+ *
102
+ * export default Backfill.make(
103
+ * { cluster, main: import.meta.url, backoffLimit: 1 },
104
+ * Effect.gen(function* () {
105
+ * return {
106
+ * run: Effect.gen(function* () { }),
107
+ * progress: () => Effect.succeed(0),
108
+ * };
109
+ * }),
110
+ * );
111
+ * ```
112
+ *
113
+ * ### Bundling & Tree-shaking
114
+ * `main` is bundled with rolldown at deploy time. Unused code is
115
+ * tree-shaken. `effect`, alchemy, and `@distilled.cloud` are marked
116
+ * pure so unused parts prune more aggressively. Your app is not
117
+ * marked pure.
118
+ *
119
+ * **Example:** Mark additional packages as pure
120
+ * Only list packages with no top-level side effects.
121
+ * ```typescript
122
+ * {
123
+ * main: import.meta.url,
124
+ * build: {
125
+ * pure: { packages: ["my-lib", "@my-scope/*"] },
126
+ * },
127
+ * }
128
+ * ```
129
+ *
130
+ * **Example:** Turn it off
131
+ * ```typescript
132
+ * {
133
+ * main: import.meta.url,
134
+ * build: { pure: false },
135
+ * }
136
+ * ```
137
+ *
138
+ * ### Scheduling
139
+ * **Example:** Nightly CronJob
140
+ * ```typescript
141
+ * const nightly = yield* Kubernetes.Job("NightlyBackfill", {
142
+ * cluster,
143
+ * main: import.meta.url,
144
+ * schedule: "0 3 * * *",
145
+ * });
146
+ * ```
147
+ *
148
+ * @resource
149
+ * @product Workloads
150
+ */
151
+ export const Job = Platform("Kubernetes.Job", {
152
+ aliases: ["AWS.EKS.Job"],
153
+ createRuntimeContext: (id) => {
154
+ // A one-shot host context: `serve` (invoked by the Platform machinery
155
+ // with the impl shape) registers the shape's `run` effect as the
156
+ // program instead of an HTTP server, so the generated entry executes
157
+ // it to completion and exits.
158
+ const runners = [];
159
+ const env = {};
160
+ const context = {
161
+ Type: "Kubernetes.Job",
162
+ id,
163
+ env,
164
+ set: (bindingId, output) => Effect.sync(() => {
165
+ const key = bindingId.replaceAll(/[^a-zA-Z0-9]/g, "_");
166
+ env[key] = output.pipe(Output.map(packEnvValue));
167
+ return key;
168
+ }),
169
+ get: (key) => Effect.sync(() => unpackEnvValue(process.env[key])),
170
+ run: (effect) => Effect.sync(() => {
171
+ runners.push(effect);
172
+ }),
173
+ serve: ((_handler, options) => Effect.sync(() => {
174
+ const run = options?.shape?.run;
175
+ if (Effect.isEffect(run)) {
176
+ // oxlint-disable-next-line effecttsgo/unsafe-effect-type-assertion -- `run` is a user program; the host runner surfaces its failures
177
+ runners.push(run);
178
+ }
179
+ })),
180
+ exports: Effect.sync(() => ({
181
+ program: Effect.all(runners, { concurrency: "unbounded" }).pipe(Effect.asVoid),
182
+ })),
183
+ };
184
+ return context;
185
+ },
186
+ });
187
+ export const JobProvider = () => Provider.effect(Job, Effect.gen(function* () {
188
+ const stack = yield* Stack;
189
+ const connectionRegistry = yield* makeConnectionRegistry;
190
+ const alchemyEnv = {
191
+ ALCHEMY_STACK_NAME: stack.name,
192
+ ALCHEMY_STAGE: stack.stage,
193
+ ALCHEMY_PHASE: "runtime",
194
+ };
195
+ // The base name doubles as the `app.kubernetes.io/name` label value
196
+ // (and the Service name), both capped at 63 characters.
197
+ const toBaseName = (id, props = {}) => props.name
198
+ ? Effect.succeed(props.name)
199
+ : createPhysicalName({ id, maxLength: 63, lowercase: true }).pipe(Effect.map((name) => name.replaceAll(/[^a-z0-9-]/g, "-")));
200
+ return {
201
+ stables: ["connection", "namespace", "serviceAccountName", "identity", "registry"],
202
+ // A Job's identity spans in-cluster Kubernetes objects plus
203
+ // adapter-owned cloud resources — no single enumeration
204
+ // reconstructs the composite, so enumeration is empty; `read`
205
+ // refreshes known instances.
206
+ list: () => Effect.succeed([]),
207
+ diff: Effect.fn(function* ({ olds = {}, news: input, output }) {
208
+ // `exports` carries the program's runtime Effects (never plain
209
+ // data); everything else must be resolved to diff.
210
+ const { exports: _exports, ...declared } = input;
211
+ if (!isResolved(declared))
212
+ return;
213
+ const news = input;
214
+ const oldCluster = connectionIdentity(tryConnectionOf(olds.cluster));
215
+ const newCluster = connectionIdentity(tryConnectionOf(news.cluster));
216
+ if (oldCluster !== undefined && newCluster !== undefined && oldCluster !== newCluster) {
217
+ return { action: "replace" };
218
+ }
219
+ if (oldCluster !== undefined &&
220
+ (olds.namespace ?? "default") !== (news.namespace ?? "default")) {
221
+ return { action: "replace" };
222
+ }
223
+ // Content drift (see Deployment).
224
+ const connection = tryConnectionOf(news.cluster);
225
+ if (output && connection) {
226
+ const adapter = yield* findClusterAdapter(connection.auth.kind);
227
+ const source = news;
228
+ const hash = yield* workloadImageHash({
229
+ adapter,
230
+ connection,
231
+ connectionRegistry,
232
+ source,
233
+ platform: imagePlatformOf(news.architecture, connection),
234
+ isExternal: news.isExternal,
235
+ bootstrap: (adapter.bootstrap?.job ?? makeJobBootstrap)(source.handler ?? "default"),
236
+ });
237
+ if (hash !== undefined && hash !== output.code.hash) {
238
+ return { action: "update" };
239
+ }
240
+ }
241
+ }),
242
+ read: Effect.fn(function* ({ output }) {
243
+ if (!output)
244
+ return undefined;
245
+ const connection = connectionOfOutput(output);
246
+ if (!connection)
247
+ return undefined;
248
+ const transport = yield* connectCluster(connection);
249
+ // The ServiceAccount is the stable existence anchor: one-shot Job
250
+ // objects are content-addressed and may have been TTL-collected.
251
+ const anchor = (output.kubernetesObjects ?? [])[0];
252
+ if (!anchor)
253
+ return output;
254
+ const observed = yield* readObject({
255
+ transport,
256
+ object: anchor,
257
+ }).pipe(Effect.catchTag("KubernetesNotFound", () => Effect.undefined));
258
+ if (observed === undefined)
259
+ return undefined;
260
+ return output;
261
+ }),
262
+ reconcile: Effect.fn(function* ({ id, news, bindings, output, session }) {
263
+ const connection = toConnection(news.cluster);
264
+ const adapter = yield* findClusterAdapter(connection.auth.kind);
265
+ const transport = yield* adapter.connect(connection);
266
+ const namespace = news.namespace ?? "default";
267
+ const baseName = yield* toBaseName(id, news);
268
+ const serviceAccountName = output?.serviceAccountName ?? baseName;
269
+ const tags = {
270
+ ...(yield* createInternalTags(id)),
271
+ ...news.tags,
272
+ };
273
+ const { env: bindingEnv, grantKeys } = collectBindingEnv(bindings);
274
+ if (grantKeys.length > 0 && adapter.identity === undefined) {
275
+ return yield* Effect.die(new Error(`'${id}': bindings carry cloud credential grants ` +
276
+ `(${grantKeys.join(", ")}) but this cluster's platform ` +
277
+ "has no workload-identity adapter. Target a managed " +
278
+ "cluster (e.g. AWS.EKS.Cluster) or bind through " +
279
+ "environment variables instead."));
280
+ }
281
+ const identity = adapter.identity
282
+ ? yield* adapter.identity.reconcile({
283
+ id,
284
+ connection,
285
+ namespace,
286
+ serviceAccount: serviceAccountName,
287
+ bindings,
288
+ options: news.identity,
289
+ state: output?.identity ??
290
+ output,
291
+ tags,
292
+ })
293
+ : undefined;
294
+ // Resolve the container image (`main` | `context` | `image`).
295
+ const source = news;
296
+ const resolved = yield* resolveWorkloadImage({
297
+ adapter,
298
+ connection,
299
+ connectionRegistry,
300
+ id,
301
+ source,
302
+ platform: imagePlatformOf(news.architecture, connection),
303
+ isExternal: news.isExternal,
304
+ bootstrap: (adapter.bootstrap?.job ?? makeJobBootstrap)(source.handler ?? "default"),
305
+ tags,
306
+ state: output?.registry ??
307
+ output,
308
+ session,
309
+ });
310
+ // Synthesize the Kubernetes objects. The generated name label is
311
+ // always present so selectors and Kueue-style extra labels
312
+ // compose without erasing the workload's identity label.
313
+ const labels = {
314
+ "app.kubernetes.io/name": baseName,
315
+ ...news.labels,
316
+ };
317
+ const containerEnv = {
318
+ ...bindingEnv,
319
+ ...identity?.env,
320
+ ...alchemyEnv,
321
+ ...news.env,
322
+ };
323
+ const serviceAccountObject = {
324
+ apiVersion: "v1",
325
+ kind: "ServiceAccount",
326
+ metadata: {
327
+ name: serviceAccountName,
328
+ namespace,
329
+ labels,
330
+ ...(identity?.serviceAccountAnnotations
331
+ ? { annotations: identity.serviceAccountAnnotations }
332
+ : {}),
333
+ },
334
+ };
335
+ const podTemplate = deepMerge({
336
+ metadata: { labels },
337
+ spec: {
338
+ serviceAccountName,
339
+ restartPolicy: news.restartPolicy ?? "Never",
340
+ containers: [
341
+ {
342
+ name: baseName,
343
+ image: resolved.imageUri,
344
+ command: news.command,
345
+ args: news.args,
346
+ env: Object.entries(containerEnv).map(([name, value]) => ({
347
+ name,
348
+ value: containerEnvValue(value),
349
+ })),
350
+ resources: news.resources,
351
+ },
352
+ ],
353
+ },
354
+ }, news.podTemplate);
355
+ const jobSpec = {
356
+ backoffLimit: news.backoffLimit,
357
+ ttlSecondsAfterFinished: news.ttlSecondsAfterFinished,
358
+ template: podTemplate,
359
+ };
360
+ const kind = news.schedule ? "CronJob" : "Job";
361
+ // A Kubernetes Job's pod template is immutable after creation, so
362
+ // one-shot Jobs are content-addressed: the object name embeds a
363
+ // hash of the spec, and a spec change applies a NEW Job (which
364
+ // runs) while `reconcileObjects` deletes the previous one.
365
+ // CronJobs are mutable and keep the stable base name.
366
+ // Kubernetes rejects Job names over 63 characters (the API
367
+ // stamps the name into the batch.kubernetes.io/job-name pod
368
+ // label, and label values cap at 63) — truncate the base so the
369
+ // content-address suffix always fits.
370
+ const jobName = news.schedule
371
+ ? baseName.slice(0, 52).replace(/-+$/, "")
372
+ : `${baseName.slice(0, 54).replace(/-+$/, "")}-${(yield* sha256Object(unwrapRedacted(jobSpec))).slice(0, 8)}`;
373
+ const workloadObject = news.schedule
374
+ ? {
375
+ apiVersion: "batch/v1",
376
+ kind: "CronJob",
377
+ metadata: { name: jobName, namespace, labels },
378
+ spec: {
379
+ schedule: news.schedule,
380
+ jobTemplate: {
381
+ metadata: { labels },
382
+ spec: jobSpec,
383
+ },
384
+ },
385
+ }
386
+ : {
387
+ apiVersion: "batch/v1",
388
+ kind: "Job",
389
+ metadata: { name: jobName, namespace, labels },
390
+ spec: jobSpec,
391
+ };
392
+ const desiredObjects = [serviceAccountObject, workloadObject];
393
+ const kubernetesObjects = yield* reconcileObjects({
394
+ transport,
395
+ previousObjects: output?.kubernetesObjects ?? [],
396
+ desiredObjects,
397
+ });
398
+ yield* session.note(`Applied Kubernetes ${kind} ${namespace}/${jobName}`);
399
+ return {
400
+ connection,
401
+ namespace,
402
+ kind,
403
+ jobName,
404
+ schedule: news.schedule,
405
+ serviceAccountName,
406
+ imageUri: resolved.imageUri,
407
+ identity: identity?.state,
408
+ registry: resolved.state,
409
+ kubernetesObjects,
410
+ code: { hash: resolved.codeHash },
411
+ };
412
+ }),
413
+ delete: Effect.fn(function* ({ output }) {
414
+ const connection = connectionOfOutput(output);
415
+ if (!connection)
416
+ return;
417
+ const adapter = yield* findClusterAdapter(connection.auth.kind);
418
+ // Skip only a missing cluster, then still clean up adapter-owned
419
+ // cloud resources (image repository, identity role).
420
+ const transport = yield* ifClusterExists(adapter.connect(connection));
421
+ if (transport && (output.kubernetesObjects ?? []).length > 0) {
422
+ yield* deleteObjects({
423
+ transport,
424
+ objects: output.kubernetesObjects ?? [],
425
+ });
426
+ }
427
+ if (adapter.identity) {
428
+ yield* adapter.identity.delete({
429
+ connection,
430
+ state: output.identity ??
431
+ output,
432
+ });
433
+ }
434
+ if (adapter.registry) {
435
+ yield* adapter.registry.delete({
436
+ state: output.registry ??
437
+ output,
438
+ });
439
+ }
440
+ }),
441
+ };
442
+ }));
443
+ //# sourceMappingURL=Job.js.map
package/lib/Job.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Job.js","sourceRoot":"","sources":["../src/Job.ts"],"names":[],"mappings":"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"}