alchemy 2.0.0-beta.64 → 2.0.0-beta.65

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 (165) hide show
  1. package/lib/AWS/EC2/InternetGateway.d.ts.map +1 -1
  2. package/lib/AWS/EC2/InternetGateway.js +8 -3
  3. package/lib/AWS/EC2/InternetGateway.js.map +1 -1
  4. package/lib/AWS/EC2/LingeringEnis.d.ts +26 -0
  5. package/lib/AWS/EC2/LingeringEnis.d.ts.map +1 -0
  6. package/lib/AWS/EC2/LingeringEnis.js +128 -0
  7. package/lib/AWS/EC2/LingeringEnis.js.map +1 -0
  8. package/lib/AWS/EC2/SecurityGroup.d.ts.map +1 -1
  9. package/lib/AWS/EC2/SecurityGroup.js +14 -14
  10. package/lib/AWS/EC2/SecurityGroup.js.map +1 -1
  11. package/lib/AWS/EC2/Subnet.d.ts.map +1 -1
  12. package/lib/AWS/EC2/Subnet.js +13 -21
  13. package/lib/AWS/EC2/Subnet.js.map +1 -1
  14. package/lib/AWS/ECR/Image.d.ts +1 -0
  15. package/lib/AWS/ECR/Image.d.ts.map +1 -1
  16. package/lib/AWS/EKS/Addon.d.ts.map +1 -1
  17. package/lib/AWS/EKS/Addon.js +15 -3
  18. package/lib/AWS/EKS/Addon.js.map +1 -1
  19. package/lib/AWS/EKS/Deployment.d.ts +10 -1
  20. package/lib/AWS/EKS/Deployment.d.ts.map +1 -1
  21. package/lib/AWS/EKS/Deployment.js +10 -4
  22. package/lib/AWS/EKS/Deployment.js.map +1 -1
  23. package/lib/AWS/EKS/HyperPod.d.ts +57 -0
  24. package/lib/AWS/EKS/HyperPod.d.ts.map +1 -0
  25. package/lib/AWS/EKS/HyperPod.js +46 -0
  26. package/lib/AWS/EKS/HyperPod.js.map +1 -0
  27. package/lib/AWS/EKS/Job.d.ts +10 -1
  28. package/lib/AWS/EKS/Job.d.ts.map +1 -1
  29. package/lib/AWS/EKS/Job.js +16 -6
  30. package/lib/AWS/EKS/Job.js.map +1 -1
  31. package/lib/AWS/EKS/internal/client.d.ts +4 -3
  32. package/lib/AWS/EKS/internal/client.d.ts.map +1 -1
  33. package/lib/AWS/EKS/internal/client.js +33 -2
  34. package/lib/AWS/EKS/internal/client.js.map +1 -1
  35. package/lib/AWS/Lambda/Function.d.ts.map +1 -1
  36. package/lib/AWS/Lambda/Function.js +1 -1
  37. package/lib/AWS/Lambda/Function.js.map +1 -1
  38. package/lib/AWS/Providers.d.ts.map +1 -1
  39. package/lib/AWS/Providers.js +4 -1
  40. package/lib/AWS/Providers.js.map +1 -1
  41. package/lib/AWS/SageMaker/Cluster.d.ts +327 -0
  42. package/lib/AWS/SageMaker/Cluster.d.ts.map +1 -0
  43. package/lib/AWS/SageMaker/Cluster.js +469 -0
  44. package/lib/AWS/SageMaker/Cluster.js.map +1 -0
  45. package/lib/AWS/SageMaker/ClusterSchedulerConfig.d.ts +96 -0
  46. package/lib/AWS/SageMaker/ClusterSchedulerConfig.d.ts.map +1 -0
  47. package/lib/AWS/SageMaker/ClusterSchedulerConfig.js +270 -0
  48. package/lib/AWS/SageMaker/ClusterSchedulerConfig.js.map +1 -0
  49. package/lib/AWS/SageMaker/ComputeQuota.d.ts +106 -0
  50. package/lib/AWS/SageMaker/ComputeQuota.d.ts.map +1 -0
  51. package/lib/AWS/SageMaker/ComputeQuota.js +268 -0
  52. package/lib/AWS/SageMaker/ComputeQuota.js.map +1 -0
  53. package/lib/AWS/SageMaker/index.d.ts +3 -0
  54. package/lib/AWS/SageMaker/index.d.ts.map +1 -1
  55. package/lib/AWS/SageMaker/index.js +3 -0
  56. package/lib/AWS/SageMaker/index.js.map +1 -1
  57. package/lib/Bundle/PurePlugin.d.ts +29 -7
  58. package/lib/Bundle/PurePlugin.d.ts.map +1 -1
  59. package/lib/Bundle/PurePlugin.js +56 -33
  60. package/lib/Bundle/PurePlugin.js.map +1 -1
  61. package/lib/Cli/commands/nuke.d.ts.map +1 -1
  62. package/lib/Cli/commands/nuke.js +231 -37
  63. package/lib/Cli/commands/nuke.js.map +1 -1
  64. package/lib/Cloudflare/StateStore/Api.d.ts +1 -1
  65. package/lib/Cloudflare/Workers/Assets.d.ts +26 -8
  66. package/lib/Cloudflare/Workers/Assets.d.ts.map +1 -1
  67. package/lib/Cloudflare/Workers/Assets.js +46 -1
  68. package/lib/Cloudflare/Workers/Assets.js.map +1 -1
  69. package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts +2 -2
  70. package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts.map +1 -1
  71. package/lib/Cloudflare/Workers/LocalWorkerProvider.js +39 -6
  72. package/lib/Cloudflare/Workers/LocalWorkerProvider.js.map +1 -1
  73. package/lib/Cloudflare/Workers/Worker.d.ts +7 -5
  74. package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
  75. package/lib/Cloudflare/Workers/Worker.js +0 -1
  76. package/lib/Cloudflare/Workers/Worker.js.map +1 -1
  77. package/lib/Cloudflare/Workers/WorkerBinding.d.ts +2 -2
  78. package/lib/Cloudflare/Workers/WorkerBundle.d.ts +20 -1
  79. package/lib/Cloudflare/Workers/WorkerBundle.d.ts.map +1 -1
  80. package/lib/Cloudflare/Workers/WorkerBundle.js +11 -0
  81. package/lib/Cloudflare/Workers/WorkerBundle.js.map +1 -1
  82. package/lib/Cloudflare/Workers/WorkerProvider.d.ts.map +1 -1
  83. package/lib/Cloudflare/Workers/WorkerProvider.js +10 -4
  84. package/lib/Cloudflare/Workers/WorkerProvider.js.map +1 -1
  85. package/lib/Cloudflare/Workflows/WorkflowBridge.d.ts +2 -1
  86. package/lib/Cloudflare/Workflows/WorkflowBridge.d.ts.map +1 -1
  87. package/lib/Cloudflare/Workflows/WorkflowBridge.js +5 -5
  88. package/lib/Cloudflare/Workflows/WorkflowBridge.js.map +1 -1
  89. package/lib/Cloudflare/Workflows/index.d.ts +1 -1
  90. package/lib/Cloudflare/Workflows/index.d.ts.map +1 -1
  91. package/lib/Cloudflare/Workflows/index.js +1 -1
  92. package/lib/Cloudflare/Workflows/index.js.map +1 -1
  93. package/lib/Docker/Container.d.ts +26 -0
  94. package/lib/Docker/Container.d.ts.map +1 -1
  95. package/lib/Docker/Container.js +20 -1
  96. package/lib/Docker/Container.js.map +1 -1
  97. package/lib/Docker/Docker.d.ts +2 -0
  98. package/lib/Docker/Docker.d.ts.map +1 -1
  99. package/lib/Docker/Docker.js.map +1 -1
  100. package/lib/Output.d.ts +4 -1
  101. package/lib/Output.d.ts.map +1 -1
  102. package/lib/Output.js.map +1 -1
  103. package/lib/Provider.d.ts +20 -0
  104. package/lib/Provider.d.ts.map +1 -1
  105. package/lib/Provider.js.map +1 -1
  106. package/lib/Random.d.ts +1 -1
  107. package/lib/Random.d.ts.map +1 -1
  108. package/lib/Resource.d.ts +14 -1
  109. package/lib/Resource.d.ts.map +1 -1
  110. package/lib/Resource.js.map +1 -1
  111. package/lib/SQL/D1.d.ts +1 -1
  112. package/lib/SQL/D1.js +1 -1
  113. package/lib/SQL/Postgres.d.ts +1 -1
  114. package/lib/SQL/Postgres.js +1 -1
  115. package/lib/State/HttpStateApi.d.ts +11 -11
  116. package/lib/Test/Alchemy.d.ts +1 -1
  117. package/lib/Test/Alchemy.js +1 -1
  118. package/lib/Test/Vitest.d.ts +58 -0
  119. package/lib/Test/Vitest.d.ts.map +1 -0
  120. package/lib/Test/Vitest.js +114 -0
  121. package/lib/Test/Vitest.js.map +1 -0
  122. package/lib/Util/proxy-chain.d.ts +5 -0
  123. package/lib/Util/proxy-chain.d.ts.map +1 -1
  124. package/lib/Util/proxy-chain.js +52 -4
  125. package/lib/Util/proxy-chain.js.map +1 -1
  126. package/package.json +23 -15
  127. package/src/AWS/EC2/InternetGateway.ts +8 -3
  128. package/src/AWS/EC2/LingeringEnis.ts +169 -0
  129. package/src/AWS/EC2/SecurityGroup.ts +24 -28
  130. package/src/AWS/EC2/Subnet.ts +23 -34
  131. package/src/AWS/EKS/Addon.ts +17 -4
  132. package/src/AWS/EKS/Deployment.ts +26 -5
  133. package/src/AWS/EKS/HyperPod.ts +97 -0
  134. package/src/AWS/EKS/Job.ts +32 -7
  135. package/src/AWS/EKS/internal/client.ts +40 -3
  136. package/src/AWS/Lambda/Function.ts +5 -3
  137. package/src/AWS/Providers.ts +6 -0
  138. package/src/AWS/SageMaker/Cluster.ts +775 -0
  139. package/src/AWS/SageMaker/ClusterSchedulerConfig.ts +430 -0
  140. package/src/AWS/SageMaker/ComputeQuota.ts +426 -0
  141. package/src/AWS/SageMaker/index.ts +3 -0
  142. package/src/Bundle/PurePlugin.ts +92 -39
  143. package/src/Cli/commands/nuke.ts +295 -56
  144. package/src/Cloudflare/Workers/Assets.ts +53 -1
  145. package/src/Cloudflare/Workers/LocalWorkerProvider.ts +46 -7
  146. package/src/Cloudflare/Workers/Worker.ts +7 -5
  147. package/src/Cloudflare/Workers/WorkerBundle.ts +31 -1
  148. package/src/Cloudflare/Workers/WorkerProvider.ts +18 -4
  149. package/src/Cloudflare/Workflows/WorkflowBridge.ts +5 -5
  150. package/src/Cloudflare/Workflows/index.ts +1 -1
  151. package/src/Docker/Container.ts +30 -1
  152. package/src/Docker/Docker.ts +2 -0
  153. package/src/Output.ts +19 -11
  154. package/src/Provider.ts +20 -0
  155. package/src/Resource.ts +18 -1
  156. package/src/SQL/D1.ts +1 -1
  157. package/src/SQL/Postgres.ts +1 -1
  158. package/src/Test/Alchemy.ts +1 -1
  159. package/src/Test/Vitest.ts +244 -0
  160. package/src/Util/proxy-chain.ts +73 -4
  161. package/lib/SQL/index.d.ts +0 -4
  162. package/lib/SQL/index.d.ts.map +0 -1
  163. package/lib/SQL/index.js +0 -4
  164. package/lib/SQL/index.js.map +0 -1
  165. package/src/SQL/index.ts +0 -3
@@ -0,0 +1,469 @@
1
+ import * as sagemaker from "@distilled.cloud/aws/sagemaker";
2
+ import * as Data from "effect/Data";
3
+ import * as Effect from "effect/Effect";
4
+ import * as Schedule from "effect/Schedule";
5
+ import * as EffectStream from "effect/Stream";
6
+ import { Unowned } from "../../AdoptPolicy.js";
7
+ import { isResolved } from "../../Diff.js";
8
+ import * as Output from "../../Output.js";
9
+ import { createPhysicalName } from "../../PhysicalName.js";
10
+ import * as Provider from "../../Provider.js";
11
+ import { Resource } from "../../Resource.js";
12
+ import { createInternalTags, diffTags, hasAlchemyTags, } from "../../Tags.js";
13
+ const ClusterResource = Resource("AWS.SageMaker.Cluster");
14
+ /**
15
+ * An Amazon SageMaker HyperPod cluster — a resilient, persistent cluster of
16
+ * ML compute for distributed training and inference, orchestrated by Slurm
17
+ * or EKS, with automatic faulty-node recovery and deep health checks.
18
+ *
19
+ * Provisioning a HyperPod cluster takes 10–25 minutes; instance groups are
20
+ * updated in place and removing a group from `instanceGroups` deletes it
21
+ * from the cluster.
22
+ * @resource
23
+ * @section Creating Clusters
24
+ * @example Slurm-Orchestrated Cluster
25
+ * ```typescript
26
+ * import * as AWS from "alchemy/AWS";
27
+ *
28
+ * const cluster = yield* AWS.SageMaker.Cluster("TrainingCluster", {
29
+ * instanceGroups: {
30
+ * controller: {
31
+ * InstanceType: "ml.t3.medium",
32
+ * InstanceCount: 1,
33
+ * ExecutionRole: role.roleArn,
34
+ * LifeCycleConfig: {
35
+ * SourceS3Uri: `s3://${bucket.bucketName}/lifecycle`,
36
+ * OnCreate: "on_create.sh",
37
+ * },
38
+ * },
39
+ * },
40
+ * });
41
+ * ```
42
+ *
43
+ * @example EKS-Orchestrated Cluster
44
+ * ```typescript
45
+ * // The EKS cluster must use the `API` (or `API_AND_CONFIG_MAP`)
46
+ * // authentication mode — pass `accessConfig` explicitly, EKS's own
47
+ * // CONFIG_MAP default is rejected. LifeCycleConfig is required for
48
+ * // EKS-orchestrated instance groups too.
49
+ * const hyperpod = yield* AWS.SageMaker.Cluster("EksHyperPod", {
50
+ * orchestrator: { Eks: { ClusterArn: eksCluster.clusterArn } },
51
+ * vpcConfig: {
52
+ * SecurityGroupIds: [securityGroupId],
53
+ * Subnets: network.privateSubnetIds,
54
+ * },
55
+ * instanceGroups: {
56
+ * workers: {
57
+ * InstanceType: "ml.g5.xlarge",
58
+ * InstanceCount: 2,
59
+ * ExecutionRole: role.roleArn,
60
+ * LifeCycleConfig: {
61
+ * SourceS3Uri: `s3://${bucket.bucketName}/lifecycle`,
62
+ * OnCreate: "on_create.sh",
63
+ * },
64
+ * },
65
+ * },
66
+ * nodeRecovery: "Automatic",
67
+ * });
68
+ *
69
+ * // The keys carry through to the attributes — typed per key:
70
+ * const workers = hyperpod.instanceGroups.workers;
71
+ * ```
72
+ *
73
+ * @section Running Workloads (Slurm)
74
+ * @example Submit jobs from the login node over SSM
75
+ * ```sh
76
+ * # Slurm jobs are submitted on the cluster itself. Each node is an SSM
77
+ * # target named sagemaker-cluster:<cluster-id>_<instance-group>-<instance-id>
78
+ * # (list nodes with `aws sagemaker list-cluster-nodes`).
79
+ * aws ssm start-session \
80
+ * --target sagemaker-cluster:6wl4at0i68c6_controller-i-0123456789abcdef0
81
+ * # then, on the node:
82
+ * sbatch --nodes=4 train.sbatch
83
+ * ```
84
+ *
85
+ * @section Running Workloads (EKS)
86
+ * @example Low level: apply any Kubernetes manifest to the orchestrator
87
+ * ```typescript
88
+ * // HyperPod nodes are ordinary EKS nodes — target them from a raw
89
+ * // manifest (a PyTorchJob CRD, a batch/v1 Job, ...) with the well-known
90
+ * // node labels.
91
+ * const job = yield* AWS.EKS.Manifest("RawTrainJob", {
92
+ * cluster: eksCluster,
93
+ * manifest: {
94
+ * apiVersion: "batch/v1",
95
+ * kind: "Job",
96
+ * metadata: { name: "raw-train", namespace: "default" },
97
+ * spec: {
98
+ * template: {
99
+ * spec: {
100
+ * nodeSelector: {
101
+ * "sagemaker.amazonaws.com/node-health-status": "Schedulable",
102
+ * "sagemaker.amazonaws.com/instance-group-name": "workers",
103
+ * },
104
+ * containers: [{ name: "train", image: "ghcr.io/acme/train:v3" }],
105
+ * restartPolicy: "Never",
106
+ * },
107
+ * },
108
+ * },
109
+ * },
110
+ * });
111
+ * ```
112
+ *
113
+ * @example High level: an effectful Job pinned to HyperPod nodes
114
+ * ```typescript
115
+ * // AWS.EKS.Job / AWS.EKS.Deployment run on HyperPod via the orchestrating
116
+ * // EKS cluster; the `hyperpod` prop derives the node selector, namespace,
117
+ * // and Kueue labels — pass the ComputeQuota resource to submit through
118
+ * // task governance.
119
+ * const evaluate = yield* AWS.EKS.Job(
120
+ * "Evaluate",
121
+ * {
122
+ * cluster: eksCluster,
123
+ * main: import.meta.url,
124
+ * hyperpod: {
125
+ * instanceGroup: "workers",
126
+ * quota,
127
+ * priorityClass: "training",
128
+ * },
129
+ * },
130
+ * Effect.gen(function* () {
131
+ * const putItem = yield* AWS.DynamoDB.PutItem(resultsTable);
132
+ * return {
133
+ * run: Effect.gen(function* () {
134
+ * // evaluation logic; bindings land IAM on the pod-identity role
135
+ * }),
136
+ * };
137
+ * }).pipe(Effect.provide(AWS.DynamoDB.PutItemHttp)),
138
+ * );
139
+ * ```
140
+ *
141
+ * @section Task Governance
142
+ * @example Prioritize workloads with a scheduler policy and team quotas
143
+ * ```typescript
144
+ * // Requires the amazon-sagemaker-hyperpod-taskgovernance EKS add-on.
145
+ * const policy = yield* AWS.SageMaker.ClusterSchedulerConfig("Scheduler", {
146
+ * clusterArn: hyperpod.clusterArn,
147
+ * schedulerConfig: {
148
+ * PriorityClasses: [{ Name: "training", Weight: 90 }],
149
+ * FairShare: "Enabled",
150
+ * },
151
+ * });
152
+ *
153
+ * // Creates the hyperpod-ns-research namespace + Kueue LocalQueue that
154
+ * // `hyperpod: { quota }` on an EKS Job/Deployment submits into.
155
+ * const quota = yield* AWS.SageMaker.ComputeQuota("ResearchQuota", {
156
+ * clusterArn: hyperpod.clusterArn,
157
+ * computeQuotaTarget: { TeamName: "research", FairShareWeight: 10 },
158
+ * computeQuotaConfig: {
159
+ * ComputeQuotaResources: [
160
+ * { InstanceType: "ml.g5.xlarge", Count: 1 },
161
+ * ],
162
+ * },
163
+ * });
164
+ * ```
165
+ */
166
+ export const Cluster = ClusterResource;
167
+ const createClusterName = (id, props) => props.clusterName
168
+ ? Effect.succeed(props.clusterName)
169
+ : createPhysicalName({ id, maxLength: 63 });
170
+ const describeClusterOrUndefined = (name) => sagemaker
171
+ .describeCluster({ ClusterName: name })
172
+ .pipe(Effect.catchTag("ResourceNotFound", () => Effect.succeed(undefined)));
173
+ const fetchClusterTags = Effect.fn(function* (arn) {
174
+ const response = yield* sagemaker
175
+ .listTags({ ResourceArn: arn })
176
+ .pipe(Effect.catchTag("AccessDeniedException", () => Effect.succeed(undefined)));
177
+ return Object.fromEntries((response?.Tags ?? []).flatMap((tag) => tag.Key !== undefined ? [[tag.Key, tag.Value ?? ""]] : []));
178
+ });
179
+ const toAttrs = (described) => ({
180
+ clusterName: described.ClusterName ?? "",
181
+ clusterArn: described.ClusterArn,
182
+ clusterStatus: described.ClusterStatus,
183
+ orchestratorEksClusterArn: described.Orchestrator?.Eks?.ClusterArn,
184
+ instanceGroups: Object.fromEntries((described.InstanceGroups ?? []).flatMap((group) => group.InstanceGroupName !== undefined
185
+ ? [
186
+ [
187
+ group.InstanceGroupName,
188
+ {
189
+ InstanceGroupName: group.InstanceGroupName,
190
+ InstanceType: group.InstanceType,
191
+ CurrentCount: group.CurrentCount,
192
+ TargetCount: group.TargetCount,
193
+ },
194
+ ],
195
+ ]
196
+ : [])),
197
+ });
198
+ /**
199
+ * The cluster is still transitioning toward the awaited state — retried by
200
+ * the bounded wait schedule.
201
+ */
202
+ class ClusterNotReady extends Data.TaggedError("ClusterNotReady") {
203
+ }
204
+ /**
205
+ * The cluster converged to the terminal `Failed` status.
206
+ */
207
+ export class ClusterFailed extends Data.TaggedError("ClusterFailed") {
208
+ }
209
+ /**
210
+ * The cluster is stuck in `Deleting` because SageMaker's internal teardown
211
+ * cannot proceed — e.g. the instance group's execution role (which HyperPod
212
+ * assumes to delete node ENIs) was deleted or lost its
213
+ * `ec2:DeleteNetworkInterface` / `ec2:DeleteNetworkInterfacePermission`
214
+ * permissions mid-teardown. Retrying `deleteCluster` can never fix this;
215
+ * the role and its permissions must be restored out-of-band, after which
216
+ * SageMaker's own retry completes the deletion within a minute.
217
+ */
218
+ export class ClusterTeardownBlocked extends Data.TaggedError("ClusterTeardownBlocked") {
219
+ }
220
+ // Explicitly-typed retry wrapper — an inline `Effect.retry` in provider
221
+ // lifecycle code leaks `Retry.Return`'s conditional type into declaration
222
+ // emit and widens the provider layer to `unknown` for every consumer of
223
+ // `AWS.providers()`.
224
+ const retryWhileNotReady = (self) => Effect.retry(self, {
225
+ while: (e) => e._tag === "ClusterNotReady",
226
+ // HyperPod cluster provisioning routinely takes 10–25 minutes.
227
+ // Poll 15s up to ~35 min.
228
+ schedule: Schedule.max([
229
+ Schedule.spaced("15 seconds"),
230
+ Schedule.recurs(140),
231
+ ]),
232
+ });
233
+ // A freshly created execution role isn't assumable by SageMaker for a few
234
+ // seconds (IAM propagation) — createCluster rejects it with a
235
+ // ValidationException until it is.
236
+ const retryWhileRoleUnassumable = (self) => Effect.retry(self, {
237
+ while: (e) => e._tag === "ValidationException" &&
238
+ (e.message?.includes("cannot assume the execution role") ?? false),
239
+ schedule: Schedule.max([Schedule.spaced("5 seconds"), Schedule.recurs(12)]),
240
+ });
241
+ const waitForCluster = (name, target) => retryWhileNotReady(Effect.gen(function* () {
242
+ const described = yield* describeClusterOrUndefined(name);
243
+ if (target === "Gone") {
244
+ if (described === undefined)
245
+ return;
246
+ // SageMaker's internal teardown deletes node ENIs by assuming the
247
+ // instance group's execution role. If that role (or its EC2
248
+ // permissions) was deleted mid-teardown, every internal retry
249
+ // fails and the cluster stays `Deleting` forever — surface the
250
+ // node's permission failure immediately instead of polling the
251
+ // full wait budget on a delete that can never finish.
252
+ const nodes = yield* sagemaker
253
+ .listClusterNodes({ ClusterName: name })
254
+ .pipe(Effect.catchTag("ResourceNotFound", () => Effect.succeed(undefined)));
255
+ const blocked = (nodes?.ClusterNodeSummaries ?? []).find((node) => node.InstanceStatus?.Message?.includes("does not have permission to perform"));
256
+ if (blocked !== undefined) {
257
+ return yield* Effect.fail(new ClusterTeardownBlocked({
258
+ clusterName: name,
259
+ message: blocked.InstanceStatus?.Message ?? "",
260
+ }));
261
+ }
262
+ return yield* Effect.fail(new ClusterNotReady({
263
+ clusterName: name,
264
+ status: described.ClusterStatus,
265
+ }));
266
+ }
267
+ if (described?.ClusterStatus === "InService")
268
+ return;
269
+ if (described?.ClusterStatus === "Failed") {
270
+ return yield* Effect.fail(new ClusterFailed({
271
+ clusterName: name,
272
+ message: described.FailureMessage,
273
+ }));
274
+ }
275
+ return yield* Effect.fail(new ClusterNotReady({
276
+ clusterName: name,
277
+ status: described?.ClusterStatus,
278
+ }));
279
+ }));
280
+ /**
281
+ * The subset of an instance group's specification that `updateCluster`
282
+ * can change and `describeCluster` reports back — used to diff desired
283
+ * groups against observed groups.
284
+ */
285
+ const observedGroupIdentity = (group) => ({
286
+ count: group.TargetCount ?? group.CurrentCount,
287
+ type: group.InstanceType,
288
+ });
289
+ const desiredGroupIdentity = (group) => ({
290
+ count: group.InstanceCount,
291
+ type: group.InstanceType,
292
+ });
293
+ /** Fold the keyed props form into the API's named-array form. */
294
+ const toGroupSpecs = (groups) => groups === undefined
295
+ ? undefined
296
+ : Object.entries(groups).map(([name, group]) => ({ InstanceGroupName: name, ...group }));
297
+ export const ClusterProvider = () => Provider.effect(Cluster, Effect.gen(function* () {
298
+ return {
299
+ stables: ["clusterName", "clusterArn"],
300
+ // HyperPod's internal teardown deletes node ENIs by assuming the
301
+ // instance group's execution role inside the cluster's VPC —
302
+ // deleting the role or network mid-teardown wedges the cluster in
303
+ // `Deleting` permanently, so nuke must fully delete clusters
304
+ // before touching these types.
305
+ nuke: {
306
+ dependsOn: [
307
+ "AWS.IAM.Role",
308
+ "AWS.IAM.Policy",
309
+ "AWS.IAM.InstanceProfile",
310
+ "AWS.EC2.Vpc",
311
+ "AWS.EC2.Subnet",
312
+ "AWS.EC2.SecurityGroup",
313
+ ],
314
+ },
315
+ list: () => Effect.gen(function* () {
316
+ const summaries = yield* sagemaker.listClusters.pages({}).pipe(EffectStream.runCollect, Effect.map((chunk) => Array.from(chunk).flatMap((page) => page.ClusterSummaries ?? [])));
317
+ return summaries.flatMap((s) => s.ClusterName !== undefined && s.ClusterArn !== undefined
318
+ ? [
319
+ {
320
+ clusterName: s.ClusterName,
321
+ clusterArn: s.ClusterArn,
322
+ clusterStatus: s.ClusterStatus ?? "InService",
323
+ orchestratorEksClusterArn: undefined,
324
+ instanceGroups: {},
325
+ },
326
+ ]
327
+ : []);
328
+ }),
329
+ read: Effect.fn(function* ({ id, olds, output }) {
330
+ const name = output?.clusterName ?? (yield* createClusterName(id, olds ?? {}));
331
+ const described = yield* describeClusterOrUndefined(name);
332
+ if (!described || described.ClusterStatus === "Deleting") {
333
+ return undefined;
334
+ }
335
+ const attrs = toAttrs(described);
336
+ const tags = yield* fetchClusterTags(attrs.clusterArn);
337
+ return (yield* hasAlchemyTags(id, tags))
338
+ ? attrs
339
+ : Unowned(attrs);
340
+ }),
341
+ diff: Effect.fn(function* ({ id, news, olds }) {
342
+ if (!isResolved(news))
343
+ return;
344
+ if (olds === undefined)
345
+ return;
346
+ const oldName = yield* createClusterName(id, olds);
347
+ const newName = yield* createClusterName(id, news);
348
+ // The VPC is fixed at creation — changing it (or the name)
349
+ // replaces the cluster. Everything else updates in place.
350
+ if (oldName !== newName ||
351
+ JSON.stringify(olds.vpcConfig) !== JSON.stringify(news.vpcConfig)) {
352
+ return { action: "replace" };
353
+ }
354
+ }),
355
+ reconcile: Effect.fn(function* ({ id, news, output, session }) {
356
+ if (!news) {
357
+ return yield* Effect.fail(new Error("SageMaker HyperPod Cluster requires props"));
358
+ }
359
+ const name = output?.clusterName ?? (yield* createClusterName(id, news));
360
+ const internalTags = yield* createInternalTags(id);
361
+ const desiredTags = { ...internalTags, ...news.tags };
362
+ // Observe.
363
+ let described = yield* describeClusterOrUndefined(name);
364
+ // Ensure — create if missing; tolerate the already-exists race.
365
+ if (described === undefined) {
366
+ yield* sagemaker
367
+ .createCluster({
368
+ ClusterName: name,
369
+ InstanceGroups: toGroupSpecs(news.instanceGroups),
370
+ RestrictedInstanceGroups: toGroupSpecs(news.restrictedInstanceGroups),
371
+ RestrictedInstanceGroupsConfig: news.restrictedInstanceGroupsConfig,
372
+ VpcConfig: news.vpcConfig,
373
+ Orchestrator: news.orchestrator,
374
+ NodeRecovery: news.nodeRecovery,
375
+ TieredStorageConfig: news.tieredStorageConfig,
376
+ NodeProvisioningMode: news.nodeProvisioningMode,
377
+ ClusterRole: news.clusterRole,
378
+ AutoScaling: news.autoScaling,
379
+ Tags: Object.entries(desiredTags).map(([Key, Value]) => ({
380
+ Key,
381
+ Value,
382
+ })),
383
+ })
384
+ .pipe(retryWhileRoleUnassumable, Effect.catchTag("ResourceInUse", () => Effect.void));
385
+ yield* session.note(`Creating HyperPod cluster ${name} (typically 10-25 minutes)...`);
386
+ }
387
+ else {
388
+ // Sync — diff observed instance groups + mutable settings
389
+ // against desired and apply one update call for the delta.
390
+ const observedGroups = new Map((described.InstanceGroups ?? []).flatMap((g) => g.InstanceGroupName !== undefined
391
+ ? [[g.InstanceGroupName, observedGroupIdentity(g)]]
392
+ : []));
393
+ const desiredGroups = new Map(Object.entries(news.instanceGroups ?? {}).map(([groupName, g]) => [groupName, desiredGroupIdentity(g)]));
394
+ const groupsToDelete = [...observedGroups.keys()].filter((groupName) => !desiredGroups.has(groupName));
395
+ const groupsChanged = groupsToDelete.length > 0 ||
396
+ [...desiredGroups].some(([groupName, identity]) => JSON.stringify(observedGroups.get(groupName)) !==
397
+ JSON.stringify(identity));
398
+ const settingsChanged = (news.nodeRecovery !== undefined &&
399
+ news.nodeRecovery !== described.NodeRecovery) ||
400
+ (news.nodeProvisioningMode !== undefined &&
401
+ news.nodeProvisioningMode !== described.NodeProvisioningMode) ||
402
+ (news.tieredStorageConfig !== undefined &&
403
+ JSON.stringify(news.tieredStorageConfig) !==
404
+ JSON.stringify(described.TieredStorageConfig)) ||
405
+ (news.autoScaling !== undefined &&
406
+ news.autoScaling.Mode !== described.AutoScaling?.Mode);
407
+ if (groupsChanged || settingsChanged) {
408
+ yield* sagemaker
409
+ .updateCluster({
410
+ ClusterName: name,
411
+ InstanceGroups: toGroupSpecs(news.instanceGroups),
412
+ RestrictedInstanceGroups: toGroupSpecs(news.restrictedInstanceGroups),
413
+ RestrictedInstanceGroupsConfig: news.restrictedInstanceGroupsConfig,
414
+ TieredStorageConfig: news.tieredStorageConfig,
415
+ NodeRecovery: news.nodeRecovery,
416
+ InstanceGroupsToDelete: groupsToDelete.length > 0 ? groupsToDelete : undefined,
417
+ NodeProvisioningMode: news.nodeProvisioningMode,
418
+ ClusterRole: news.clusterRole,
419
+ AutoScaling: news.autoScaling,
420
+ })
421
+ .pipe(Effect.catchTag("ResourceNotFound", () => Effect.void));
422
+ yield* session.note(`Updating HyperPod cluster ${name}...`);
423
+ }
424
+ }
425
+ // Converge to InService (provisioning is asynchronous).
426
+ yield* waitForCluster(name, "InService");
427
+ described = yield* describeClusterOrUndefined(name);
428
+ if (described === undefined) {
429
+ return yield* Effect.fail(new Error(`failed to read reconciled HyperPod cluster ${name}`));
430
+ }
431
+ const attrs = toAttrs(described);
432
+ // Sync tags — diff against OBSERVED cloud tags.
433
+ const currentTags = yield* fetchClusterTags(attrs.clusterArn);
434
+ const { removed, upsert } = diffTags(currentTags, desiredTags);
435
+ if (removed.length > 0) {
436
+ yield* sagemaker.deleteTags({
437
+ ResourceArn: attrs.clusterArn,
438
+ TagKeys: removed,
439
+ });
440
+ }
441
+ if (upsert.length > 0) {
442
+ yield* sagemaker.addTags({
443
+ ResourceArn: attrs.clusterArn,
444
+ Tags: upsert.map(({ Key, Value }) => ({ Key, Value })),
445
+ });
446
+ }
447
+ yield* session.note(attrs.clusterArn);
448
+ return attrs;
449
+ }),
450
+ delete: Effect.fn(function* ({ output }) {
451
+ const described = yield* describeClusterOrUndefined(output.clusterName);
452
+ if (described === undefined)
453
+ return;
454
+ // A cluster mid-create/update rejects deletion with a Conflict —
455
+ // wait for it to settle first, then delete. A cluster stuck in
456
+ // `Failed` (or one that never converges) is still deletable. One
457
+ // already `Deleting` (a previous attempt) skips straight to the
458
+ // Gone wait instead of burning the full InService wait budget.
459
+ if (described.ClusterStatus !== "Deleting") {
460
+ yield* waitForCluster(output.clusterName, "InService").pipe(Effect.catchTag(["ClusterFailed", "ClusterNotReady"], () => Effect.void));
461
+ yield* sagemaker
462
+ .deleteCluster({ ClusterName: output.clusterName })
463
+ .pipe(Effect.catchTag("ResourceNotFound", () => Effect.void), Effect.catchTag("ConflictException", () => Effect.void));
464
+ }
465
+ yield* waitForCluster(output.clusterName, "Gone");
466
+ }),
467
+ };
468
+ }));
469
+ //# sourceMappingURL=Cluster.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Cluster.js","sourceRoot":"","sources":["../../../src/AWS/SageMaker/Cluster.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ import * as sagemaker from "@distilled.cloud/aws/sagemaker";
2
+ import * as Provider from "../../Provider.ts";
3
+ import { Resource } from "../../Resource.ts";
4
+ import type { Providers } from "../Providers.ts";
5
+ export type SchedulerResourceStatus = sagemaker.SchedulerResourceStatus;
6
+ export interface ClusterSchedulerConfigProps {
7
+ /**
8
+ * Name of the cluster policy. Maximum 63 characters, alphanumeric and
9
+ * hyphens.
10
+ * @default ${app}-${stage}-${id}
11
+ */
12
+ name?: string;
13
+ /**
14
+ * ARN of the EKS-orchestrated HyperPod cluster the policy applies to.
15
+ * Changing the cluster replaces the policy. AWS allows ONE cluster
16
+ * policy per cluster — creating a second fails with the typed
17
+ * `ClusterSchedulerConfigAlreadyExists` error.
18
+ */
19
+ clusterArn: string;
20
+ /**
21
+ * The policy itself: task priority classes, fair-share allocation, and
22
+ * idle-resource sharing.
23
+ */
24
+ schedulerConfig?: sagemaker.SchedulerConfig;
25
+ /**
26
+ * A description of the cluster policy.
27
+ */
28
+ description?: string;
29
+ /**
30
+ * Tags to associate with the cluster policy. Merged with internal Alchemy
31
+ * tags.
32
+ */
33
+ tags?: Record<string, string>;
34
+ }
35
+ export interface ClusterSchedulerConfig extends Resource<"AWS.SageMaker.ClusterSchedulerConfig", ClusterSchedulerConfigProps, {
36
+ /**
37
+ * The cluster policy's ID.
38
+ */
39
+ clusterSchedulerConfigId: string;
40
+ /**
41
+ * ARN of the cluster policy.
42
+ */
43
+ clusterSchedulerConfigArn: string;
44
+ /**
45
+ * The cluster policy's name.
46
+ */
47
+ name: string;
48
+ /**
49
+ * ARN of the HyperPod cluster the policy applies to.
50
+ */
51
+ clusterArn: string;
52
+ /**
53
+ * The policy's current version (incremented on every update).
54
+ */
55
+ clusterSchedulerConfigVersion: number;
56
+ }, never, Providers> {
57
+ }
58
+ /**
59
+ * A SageMaker HyperPod cluster policy (task governance) — configures how an
60
+ * EKS-orchestrated HyperPod cluster prioritizes tasks and allocates idle
61
+ * compute across teams via priority classes and fair-share weights.
62
+ * @resource
63
+ * @section Creating Cluster Policies
64
+ * @example Priority Classes with Fair-Share
65
+ * ```typescript
66
+ * import * as AWS from "alchemy/AWS";
67
+ *
68
+ * const policy = yield* AWS.SageMaker.ClusterSchedulerConfig("Scheduler", {
69
+ * clusterArn: hyperpod.clusterArn,
70
+ * schedulerConfig: {
71
+ * PriorityClasses: [
72
+ * { Name: "inference", Weight: 100 },
73
+ * { Name: "training", Weight: 75 },
74
+ * ],
75
+ * FairShare: "Enabled",
76
+ * },
77
+ * description: "Prioritize inference over training",
78
+ * });
79
+ * ```
80
+ */
81
+ export declare const ClusterSchedulerConfig: import("../../Resource.ts").ResourceClass<ClusterSchedulerConfig>;
82
+ declare const SchedulerConfigFailed_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
83
+ readonly _tag: "SchedulerConfigFailed";
84
+ } & Readonly<A>;
85
+ /**
86
+ * The cluster policy converged to a terminal failed status.
87
+ */
88
+ export declare class SchedulerConfigFailed extends SchedulerConfigFailed_base<{
89
+ readonly configId: string;
90
+ readonly status: string | undefined;
91
+ readonly message: string | undefined;
92
+ }> {
93
+ }
94
+ export declare const ClusterSchedulerConfigProvider: () => import("effect/Layer").Layer<Provider.Provider<ClusterSchedulerConfig>, never, import("@distilled.cloud/aws/Credentials").Credentials | import("effect/unstable/http/HttpClient").HttpClient | import("@distilled.cloud/aws/Region").Region | import("../../Stack.ts").Stack | import("../../Stage.ts").Stage>;
95
+ export {};
96
+ //# sourceMappingURL=ClusterSchedulerConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClusterSchedulerConfig.d.ts","sourceRoot":"","sources":["../../../src/AWS/SageMaker/ClusterSchedulerConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,gCAAgC,CAAC;AAQ5D,OAAO,KAAK,QAAQ,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAO7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,MAAM,MAAM,uBAAuB,GAAG,SAAS,CAAC,uBAAuB,CAAC;AAExE,MAAM,WAAW,2BAA2B;IAC1C;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,eAAe,CAAC,EAAE,SAAS,CAAC,eAAe,CAAC;IAC5C;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,sBAAuB,SAAQ,QAAQ,CACtD,sCAAsC,EACtC,2BAA2B,EAC3B;IACE;;OAEG;IACH,wBAAwB,EAAE,MAAM,CAAC;IACjC;;OAEG;IACH,yBAAyB,EAAE,MAAM,CAAC;IAClC;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,6BAA6B,EAAE,MAAM,CAAC;CACvC,EACD,KAAK,EACL,SAAS,CACV;CAAG;AAEJ;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,sBAAsB,mEAElC,CAAC;;;;AAgEF;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,2BAEzC;IACA,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;CACtC,CAAC;CAAG;AA+DL,eAAO,MAAM,8BAA8B,sTA6LxC,CAAC"}