@intentius/chant-lexicon-gcp 0.46.0 → 0.50.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/dist/composites/gpu-node-pool.d.ts +83 -0
- package/dist/composites/gpu-node-pool.d.ts.map +1 -0
- package/dist/composites/index.d.ts +2 -0
- package/dist/composites/index.d.ts.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/integrity.json +3 -3
- package/dist/manifest.json +1 -1
- package/dist/op/builders.d.ts +45 -0
- package/dist/op/builders.d.ts.map +1 -0
- package/dist/skills/chant-gcp.md +1 -0
- package/package.json +3 -3
- package/src/composites/composites.test.ts +148 -0
- package/src/composites/gpu-node-pool.ts +150 -0
- package/src/composites/index.ts +2 -0
- package/src/index.ts +10 -1
- package/src/op/builders.test.ts +58 -0
- package/src/op/builders.ts +70 -0
- package/src/skills/chant-gcp.md +1 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GpuNodePool composite — ContainerNodePool with GPU accelerators.
|
|
3
|
+
*
|
|
4
|
+
* Promoted from the hand-wired `gpuNodePool` in the ray-kuberay-gke example
|
|
5
|
+
* (examples/ray-kuberay-gke/src/infra/cluster.ts). Attaches to an existing
|
|
6
|
+
* GKE cluster (e.g. one created by `GkeCluster`) and adds a separate,
|
|
7
|
+
* scale-to-zero pool for GPU-tainted workloads.
|
|
8
|
+
*
|
|
9
|
+
* NOTE: GKE auto-installs the nvidia-device-plugin DaemonSet when a node
|
|
10
|
+
* pool has accelerators. Do NOT emit it as a K8s manifest — it will
|
|
11
|
+
* conflict with the GKE-managed version.
|
|
12
|
+
*/
|
|
13
|
+
import { NodePool } from "../generated/index.js";
|
|
14
|
+
export interface GpuNodePoolTaint {
|
|
15
|
+
key: string;
|
|
16
|
+
value: string;
|
|
17
|
+
effect: string;
|
|
18
|
+
}
|
|
19
|
+
export interface GpuNodePoolProps {
|
|
20
|
+
/** Node pool name. */
|
|
21
|
+
name: string;
|
|
22
|
+
/** Reference to the GKE cluster this pool attaches to, e.g. `{ name: "my-cluster" }`. */
|
|
23
|
+
clusterRef: Record<string, unknown>;
|
|
24
|
+
/** GCP region or zone of the cluster. */
|
|
25
|
+
location: string;
|
|
26
|
+
/** Machine type for GPU nodes (default: "n1-standard-8"). */
|
|
27
|
+
machineType?: string;
|
|
28
|
+
/** Accelerator type, e.g. "nvidia-tesla-t4", "nvidia-l4", "nvidia-tesla-a100" (default: "nvidia-tesla-t4"). */
|
|
29
|
+
acceleratorType?: string;
|
|
30
|
+
/** Number of accelerators per node (default: 1). */
|
|
31
|
+
acceleratorCount?: number;
|
|
32
|
+
/** Minimum nodes for autoscaling — 0 enables scale-to-zero (default: 0). */
|
|
33
|
+
minNodeCount?: number;
|
|
34
|
+
/** Maximum nodes for autoscaling (default: 4). */
|
|
35
|
+
maxNodeCount?: number;
|
|
36
|
+
/** Boot disk size in GB (default: 200). */
|
|
37
|
+
diskSizeGb?: number;
|
|
38
|
+
/** Boot disk type (default: "pd-ssd"). */
|
|
39
|
+
diskType?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Node taints — only pods with a matching toleration are scheduled here.
|
|
42
|
+
* Default: `nvidia.com/gpu=present:NO_SCHEDULE`. Pass an empty array to omit tainting.
|
|
43
|
+
*/
|
|
44
|
+
taint?: GpuNodePoolTaint[];
|
|
45
|
+
/** Enable GKE metadata server workload identity mode on nodes (default: true). */
|
|
46
|
+
workloadMetadata?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* GPU time-sharing configuration, e.g.
|
|
49
|
+
* `{ maxSharedClientsPerGpu: 2, gpuSharingStrategy: "TIME_SHARING" }`.
|
|
50
|
+
*/
|
|
51
|
+
gpuSharingConfig?: Record<string, unknown>;
|
|
52
|
+
/** Multi-instance GPU (MIG) partition size, e.g. "1g.5gb". */
|
|
53
|
+
gpuPartitionSize?: string;
|
|
54
|
+
/** Additional labels. */
|
|
55
|
+
labels?: Record<string, string>;
|
|
56
|
+
/** Namespace for the node pool resource. */
|
|
57
|
+
namespace?: string;
|
|
58
|
+
/** Per-member defaults for customizing the underlying resource. */
|
|
59
|
+
defaults?: {
|
|
60
|
+
nodePool?: Partial<ConstructorParameters<typeof NodePool>[0]>;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Create a GpuNodePool composite — a scale-to-zero ContainerNodePool with
|
|
65
|
+
* GPU accelerators, tainted so only pods with a matching toleration land there.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* import { GpuNodePool } from "@intentius/chant-lexicon-gcp";
|
|
70
|
+
*
|
|
71
|
+
* const { nodePool } = GpuNodePool({
|
|
72
|
+
* name: "ray-gke-gpu",
|
|
73
|
+
* clusterRef: { name: "ray-gke" },
|
|
74
|
+
* location: "us-central1",
|
|
75
|
+
* acceleratorType: "nvidia-tesla-t4",
|
|
76
|
+
* maxNodeCount: 4,
|
|
77
|
+
* });
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export declare const GpuNodePool: import("@intentius/chant").CompositeDefinition<GpuNodePoolProps, {
|
|
81
|
+
nodePool: import("@intentius/chant").Declarable & Record<string, string>;
|
|
82
|
+
}>;
|
|
83
|
+
//# sourceMappingURL=gpu-node-pool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gpu-node-pool.d.ts","sourceRoot":"","sources":["../../src/composites/gpu-node-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,yFAAyF;IACzF,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+GAA+G;IAC/G,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oDAAoD;IACpD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,KAAK,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC3B,kFAAkF;IAClF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yBAAyB;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,QAAQ,CAAC,EAAE;QACT,QAAQ,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KAC/D,CAAC;CACH;AAMD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,WAAW;;EA6DP,CAAC"}
|
|
@@ -26,4 +26,6 @@ export { MultiRegionVpc } from "./multi-region-vpc.js";
|
|
|
26
26
|
export type { MultiRegionVpcConfig, MultiRegionVpcRegion } from "./multi-region-vpc.js";
|
|
27
27
|
export { GkeCrdbRegion } from "./gke-crdb-region.js";
|
|
28
28
|
export type { GkeCrdbRegionConfig, GkeCrdbRegionNodeConfig } from "./gke-crdb-region.js";
|
|
29
|
+
export { GpuNodePool } from "./gpu-node-pool.js";
|
|
30
|
+
export type { GpuNodePoolProps, GpuNodePoolTaint } from "./gpu-node-pool.js";
|
|
29
31
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/composites/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACpG,YAAY,EACV,yBAAyB,EACzB,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,YAAY,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,YAAY,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,YAAY,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,YAAY,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,YAAY,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/composites/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACpG,YAAY,EACV,yBAAyB,EACzB,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,YAAY,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,YAAY,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,YAAY,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,YAAY,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,YAAY,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AACtF,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { gcpApply, gcpDelete, flociGcpUp, flociGcpDown } from "./op/builders.js";
|
|
1
2
|
export { gcpSerializer } from "./serializer.js";
|
|
2
3
|
export { gcpPlugin } from "./plugin.js";
|
|
3
4
|
export { defaultLabels, defaultAnnotations, isDefaultLabels, isDefaultAnnotations } from "./default-labels.js";
|
|
@@ -5,8 +6,8 @@ export { DEFAULT_LABELS_MARKER, DEFAULT_ANNOTATIONS_MARKER } from "./default-lab
|
|
|
5
6
|
export { GCP, ProjectId, Region, Zone } from "./pseudo.js";
|
|
6
7
|
export { GcpAnnotations } from "./variables.js";
|
|
7
8
|
export * from "./generated/index.js";
|
|
8
|
-
export { GkeCluster, CloudRunServiceComposite, CloudSqlInstance, GcsBucket, VpcNetwork, PubSubPipeline, CloudFunctionWithTrigger, PrivateService, ManagedCertificate, SecureProject, MemorystoreRedis, MultiRegionVpc, GkeCrdbRegion, GovernanceFoundation, LocationRestriction, OrganizationAuditConfig, } from "./composites/index.js";
|
|
9
|
-
export type { GkeClusterProps, CloudRunServiceProps, CloudSqlInstanceProps, GcsBucketProps, VpcNetworkProps, VpcSubnet, PubSubPipelineProps, CloudFunctionWithTriggerProps, PrivateServiceProps, ManagedCertificateProps, SecureProjectProps, MemorystoreRedisProps, MultiRegionVpcConfig, MultiRegionVpcRegion, GkeCrdbRegionConfig, GkeCrdbRegionNodeConfig, GovernanceFoundationProps, LocationRestrictionProps, OrganizationAuditConfigProps, } from "./composites/index.js";
|
|
9
|
+
export { GkeCluster, CloudRunServiceComposite, CloudSqlInstance, GcsBucket, VpcNetwork, PubSubPipeline, CloudFunctionWithTrigger, PrivateService, ManagedCertificate, SecureProject, MemorystoreRedis, MultiRegionVpc, GkeCrdbRegion, GpuNodePool, GovernanceFoundation, LocationRestriction, OrganizationAuditConfig, } from "./composites/index.js";
|
|
10
|
+
export type { GkeClusterProps, CloudRunServiceProps, CloudSqlInstanceProps, GcsBucketProps, VpcNetworkProps, VpcSubnet, PubSubPipelineProps, CloudFunctionWithTriggerProps, PrivateServiceProps, ManagedCertificateProps, SecureProjectProps, MemorystoreRedisProps, MultiRegionVpcConfig, MultiRegionVpcRegion, GkeCrdbRegionConfig, GkeCrdbRegionNodeConfig, GpuNodePoolProps, GpuNodePoolTaint, GovernanceFoundationProps, LocationRestrictionProps, OrganizationAuditConfigProps, } from "./composites/index.js";
|
|
10
11
|
export { landingZoneConfig, resourceLocationRestriction, DISABLE_SA_KEY_CREATION, SKIP_DEFAULT_NETWORK, AUDIT_ALL_SERVICES, FOUNDATION_FOLDERS, } from "./governance.js";
|
|
11
12
|
export type { GcpGovernanceConfig, LandingZoneConfigProps, FolderConfig, OrgPolicyConfig, ProjectConfig } from "./governance.js";
|
|
12
13
|
export { StorageRoles, ComputeRoles, ContainerRoles, IAMRoles, SQLRoles, RunRoles, PubSubRoles } from "./actions/index.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAG9E,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG7C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGrC,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC5G,OAAO,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAGrF,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAGxD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAI7C,cAAc,mBAAmB,CAAC;AAGlC,OAAO,EACL,UAAU,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,SAAS,EAAE,UAAU,EAC7E,cAAc,EAAE,wBAAwB,EAAE,cAAc,EAAE,kBAAkB,EAAE,aAAa,EAC3F,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAC5D,oBAAoB,EAAE,mBAAmB,EAAE,uBAAuB,GACnE,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,eAAe,EACf,oBAAoB,EACpB,qBAAqB,EACrB,cAAc,EACd,eAAe,EAAE,SAAS,EAC1B,mBAAmB,EACnB,6BAA6B,EAC7B,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,EAClB,qBAAqB,EACrB,oBAAoB,EAAE,oBAAoB,EAC1C,mBAAmB,EAAE,uBAAuB,EAC5C,gBAAgB,EAAE,gBAAgB,EAClC,yBAAyB,EAAE,wBAAwB,EAAE,4BAA4B,GAClF,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EACL,iBAAiB,EAAE,2BAA2B,EAC9C,uBAAuB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,kBAAkB,GACtF,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG9H,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGxH,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACrF,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAC1G,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,kBAAkB,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGrI,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGvE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/integrity.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"algorithm": "sha256",
|
|
3
3
|
"artifacts": {
|
|
4
|
-
"manifest.json": "
|
|
4
|
+
"manifest.json": "ed246ac3b74e491648ab0fe551472acafbae7f5ec4dcd09f4cfca817effe4eea",
|
|
5
5
|
"meta.json": "475f10909854d059a2e2d4fb541c058803422e38b9c64bd4d6858c0623eedb8c",
|
|
6
6
|
"types/index.d.ts": "5433b54c04b57d6fda8f3d81ef92ed0aca87f7e8e5dd3ea92d8de6e62a3ccfab",
|
|
7
7
|
"rules/hardcoded-project.ts": "228631d3159e1ffcce2359c66073d4ae59bb0285f378e46e446f416aec50481c",
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
"rules/wgc501.ts": "bf99d8dc97537687fdfe9a8d5eb420172bf3279a4147311037f9c1d1f5fd4c85",
|
|
36
36
|
"rules/wgc502.ts": "6460a028f73ef31a66653954e67142079130112b70fa01a79f80464968a1b9f6",
|
|
37
37
|
"rules/wgc503.ts": "44dc51efbf9f9384b61a4e19b173b4c182557143cb59fbaf4da087e70a38f916",
|
|
38
|
-
"skills/chant-gcp.md": "
|
|
38
|
+
"skills/chant-gcp.md": "46a5e711ac59086d9f59ef645085aa54e8b1953afb76a0d93158b7288edf362e",
|
|
39
39
|
"skills/chant-gcp-security.md": "39a1c97b7425ed43b081257132449d11ce9d12f2d4755fc30d8b14bbc38f60bd",
|
|
40
40
|
"skills/chant-gcp-patterns.md": "4c6809fc7c37fa1879379ad4c0e2d114dec9497bc6eb9d1bca4e79fddea4f509",
|
|
41
41
|
"skills/chant-gcp-gke.md": "be277019da9a722c851e47cd2dfb9c9536668948c3535fb20db7697e934c4e2b"
|
|
42
42
|
},
|
|
43
|
-
"composite": "
|
|
43
|
+
"composite": "d82d01c89efe07eb6159d280987dae5435443c5f5696f5d1044d8812f87a0f31"
|
|
44
44
|
}
|
package/dist/manifest.json
CHANGED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed step-builder wrappers for this lexicon's activities (chant #1288
|
|
3
|
+
* Stage 2). See `lexicons/k8s/src/op/builders.ts`'s module doc for why these
|
|
4
|
+
* live beside their `*Args` interfaces rather than in core or the temporal
|
|
5
|
+
* barrel. `opts`'s type in each wrapper below IS the activity's own `*Args`
|
|
6
|
+
* interface (via `Omit`/`WithStepRefs`) — never restated. `core`'s own
|
|
7
|
+
* `gcpApply`/`gcpDelete`/`flociGcpUp`/`flociGcpDown` are unchanged and
|
|
8
|
+
* produce byte-identical `ActivityStep` output; these are purely additive.
|
|
9
|
+
*/
|
|
10
|
+
import { type ActivityStep, type NamedActivityStep, type WithStepRefs } from "@intentius/chant/op";
|
|
11
|
+
import type { GcpApplyArgs } from "./activities/gcp-apply.js";
|
|
12
|
+
import type { FlociGcpUpArgs, FlociGcpDownArgs } from "./activities/floci-gcp.js";
|
|
13
|
+
/** Extra opts every wrapper below accepts alongside its activity's own fields. */
|
|
14
|
+
type StepOpts = {
|
|
15
|
+
profile?: ActivityStep["profile"];
|
|
16
|
+
id?: string;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Apply built GCP (CNRM) resources directly to their GCP REST APIs — the
|
|
20
|
+
* fully typed twin of core's `gcpApply`. `opts` is {@link GcpApplyArgs}
|
|
21
|
+
* itself, minus the positional `manifestPath`. Defaults to the `longInfra`
|
|
22
|
+
* profile.
|
|
23
|
+
*/
|
|
24
|
+
export declare const gcpApply: (manifestPath: string, opts?: WithStepRefs<Omit<GcpApplyArgs, "manifestPath">> & StepOpts) => NamedActivityStep;
|
|
25
|
+
/**
|
|
26
|
+
* Delete the GCP (CNRM) resources in a built manifest — the inverse of
|
|
27
|
+
* {@link gcpApply}, fully typed twin of core's `gcpDelete`. `opts` is
|
|
28
|
+
* {@link GcpApplyArgs} itself (the activity reuses it), minus the positional
|
|
29
|
+
* `manifestPath`. Defaults to the `longInfra` profile.
|
|
30
|
+
*/
|
|
31
|
+
export declare const gcpDelete: (manifestPath: string, opts?: WithStepRefs<Omit<GcpApplyArgs, "manifestPath">> & StepOpts) => NamedActivityStep;
|
|
32
|
+
/**
|
|
33
|
+
* Boot a local floci-gcp (GCP emulator) — the fully typed twin of core's
|
|
34
|
+
* `flociGcpUp`. `opts` is {@link FlociGcpUpArgs} itself. Defaults to the
|
|
35
|
+
* `longInfra` profile.
|
|
36
|
+
*/
|
|
37
|
+
export declare const flociGcpUp: (opts?: WithStepRefs<FlociGcpUpArgs> & StepOpts) => NamedActivityStep;
|
|
38
|
+
/**
|
|
39
|
+
* Stop and remove the local floci-gcp container — the fully typed twin of
|
|
40
|
+
* core's `flociGcpDown`. `opts` is {@link FlociGcpDownArgs} itself. Defaults
|
|
41
|
+
* to the `fastIdempotent` profile.
|
|
42
|
+
*/
|
|
43
|
+
export declare const flociGcpDown: (opts?: WithStepRefs<FlociGcpDownArgs> & StepOpts) => NamedActivityStep;
|
|
44
|
+
export {};
|
|
45
|
+
//# sourceMappingURL=builders.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../../src/op/builders.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/E,kFAAkF;AAClF,KAAK,QAAQ,GAAG;IAAE,OAAO,CAAC,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,GACnB,cAAc,MAAM,EACpB,OAAO,YAAY,CAAC,IAAI,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC,GAAG,QAAQ,KACjE,iBAGF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,SAAS,GACpB,cAAc,MAAM,EACpB,OAAO,YAAY,CAAC,IAAI,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC,GAAG,QAAQ,KACjE,iBAGF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,YAAY,CAAC,cAAc,CAAC,GAAG,QAAQ,KAAG,iBAG3E,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,YAAY,CAAC,gBAAgB,CAAC,GAAG,QAAQ,KAAG,iBAG/E,CAAC"}
|
package/dist/skills/chant-gcp.md
CHANGED
|
@@ -201,6 +201,7 @@ Composites group related Config Connector resources with secure defaults. Each r
|
|
|
201
201
|
| `PrivateService` | ComputeGlobalAddress + ServiceNetworkingConnection | RFC 1918 range, automatic peering |
|
|
202
202
|
| `ManagedCertificate` | ComputeManagedSslCertificate | Auto-renewal via Google-managed cert |
|
|
203
203
|
| `SecureProject` | Project + IAMAuditConfig + essential Service resources | Audit logging, required APIs enabled, org policy constraints |
|
|
204
|
+
| `GpuNodePool` | ContainerNodePool with GPU accelerators | Scale-to-zero, nvidia.com/gpu taint, GKE metadata workload identity |
|
|
204
205
|
|
|
205
206
|
### Example: GKE cluster with secure defaults
|
|
206
207
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant-lexicon-gcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.50.0",
|
|
4
4
|
"description": "Google Cloud lexicon for chant — declarative IaC in TypeScript",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://intentius.io/chant",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
70
|
"fflate": "^0.8.2",
|
|
71
|
-
"js-yaml": "^4.1
|
|
71
|
+
"js-yaml": "^4.3.1",
|
|
72
72
|
"@types/js-yaml": "^4.0.9"
|
|
73
73
|
},
|
|
74
74
|
"devDependencies": {
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"typescript": "^5.9.3"
|
|
77
77
|
},
|
|
78
78
|
"peerDependencies": {
|
|
79
|
-
"@intentius/chant": "^0.
|
|
79
|
+
"@intentius/chant": "^0.50.0",
|
|
80
80
|
"typescript": "^5.9.3"
|
|
81
81
|
}
|
|
82
82
|
}
|
|
@@ -9,6 +9,7 @@ import { CloudFunctionWithTrigger } from "./cloud-function";
|
|
|
9
9
|
import { PrivateService } from "./private-service";
|
|
10
10
|
import { ManagedCertificate } from "./managed-certificate";
|
|
11
11
|
import { SecureProject } from "./secure-project";
|
|
12
|
+
import { GpuNodePool } from "./gpu-node-pool";
|
|
12
13
|
|
|
13
14
|
/** Helper to extract props from a Declarable member. */
|
|
14
15
|
function p(member: unknown): Record<string, any> {
|
|
@@ -462,3 +463,150 @@ describe("SecureProject", () => {
|
|
|
462
463
|
expect(result.loggingSink).toBeUndefined();
|
|
463
464
|
});
|
|
464
465
|
});
|
|
466
|
+
|
|
467
|
+
// ── GpuNodePool ────────────────────────────────────────────────────
|
|
468
|
+
|
|
469
|
+
describe("GpuNodePool", () => {
|
|
470
|
+
test("returns a node pool", () => {
|
|
471
|
+
const result = GpuNodePool({
|
|
472
|
+
name: "ray-gke-gpu",
|
|
473
|
+
clusterRef: { name: "ray-gke" },
|
|
474
|
+
location: "us-central1",
|
|
475
|
+
});
|
|
476
|
+
expect(result.nodePool).toBeDefined();
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
test("scales to zero by default", () => {
|
|
480
|
+
const result = GpuNodePool({
|
|
481
|
+
name: "gpu-pool",
|
|
482
|
+
clusterRef: { name: "c" },
|
|
483
|
+
location: "us-central1",
|
|
484
|
+
});
|
|
485
|
+
expect(p(result.nodePool).initialNodeCount).toBe(0);
|
|
486
|
+
expect(p(result.nodePool).autoscaling.minNodeCount).toBe(0);
|
|
487
|
+
expect(p(result.nodePool).autoscaling.maxNodeCount).toBe(4);
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
test("defaults to a single nvidia-tesla-t4 accelerator", () => {
|
|
491
|
+
const result = GpuNodePool({
|
|
492
|
+
name: "gpu-pool",
|
|
493
|
+
clusterRef: { name: "c" },
|
|
494
|
+
location: "us-central1",
|
|
495
|
+
});
|
|
496
|
+
expect(p(result.nodePool).nodeConfig.guestAccelerator).toEqual([
|
|
497
|
+
{ count: 1, type: "nvidia-tesla-t4" },
|
|
498
|
+
]);
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
test("respects acceleratorType and acceleratorCount", () => {
|
|
502
|
+
const result = GpuNodePool({
|
|
503
|
+
name: "gpu-pool",
|
|
504
|
+
clusterRef: { name: "c" },
|
|
505
|
+
location: "us-central1",
|
|
506
|
+
acceleratorType: "nvidia-l4",
|
|
507
|
+
acceleratorCount: 2,
|
|
508
|
+
});
|
|
509
|
+
expect(p(result.nodePool).nodeConfig.guestAccelerator).toEqual([
|
|
510
|
+
{ count: 2, type: "nvidia-l4" },
|
|
511
|
+
]);
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
test("defaults to the nvidia.com/gpu NoSchedule taint", () => {
|
|
515
|
+
const result = GpuNodePool({
|
|
516
|
+
name: "gpu-pool",
|
|
517
|
+
clusterRef: { name: "c" },
|
|
518
|
+
location: "us-central1",
|
|
519
|
+
});
|
|
520
|
+
expect(p(result.nodePool).nodeConfig.taint).toEqual([
|
|
521
|
+
{ key: "nvidia.com/gpu", value: "present", effect: "NO_SCHEDULE" },
|
|
522
|
+
]);
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
test("omits taint when an empty array is passed", () => {
|
|
526
|
+
const result = GpuNodePool({
|
|
527
|
+
name: "gpu-pool",
|
|
528
|
+
clusterRef: { name: "c" },
|
|
529
|
+
location: "us-central1",
|
|
530
|
+
taint: [],
|
|
531
|
+
});
|
|
532
|
+
expect(p(result.nodePool).nodeConfig.taint).toBeUndefined();
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
test("does not emit a device-plugin manifest — GKE auto-installs it", () => {
|
|
536
|
+
const result = GpuNodePool({
|
|
537
|
+
name: "gpu-pool",
|
|
538
|
+
clusterRef: { name: "c" },
|
|
539
|
+
location: "us-central1",
|
|
540
|
+
});
|
|
541
|
+
expect(Object.keys(result)).toEqual(["nodePool"]);
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
test("enables GKE_METADATA workload identity mode by default", () => {
|
|
545
|
+
const result = GpuNodePool({
|
|
546
|
+
name: "gpu-pool",
|
|
547
|
+
clusterRef: { name: "c" },
|
|
548
|
+
location: "us-central1",
|
|
549
|
+
});
|
|
550
|
+
expect(p(result.nodePool).nodeConfig.workloadMetadataConfig).toEqual({ mode: "GKE_METADATA" });
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
test("supports GPU time-sharing config", () => {
|
|
554
|
+
const result = GpuNodePool({
|
|
555
|
+
name: "gpu-pool",
|
|
556
|
+
clusterRef: { name: "c" },
|
|
557
|
+
location: "us-central1",
|
|
558
|
+
gpuSharingConfig: { maxSharedClientsPerGpu: 2, gpuSharingStrategy: "TIME_SHARING" },
|
|
559
|
+
});
|
|
560
|
+
expect(p(result.nodePool).nodeConfig.guestAccelerator[0].gpuSharingConfig).toEqual({
|
|
561
|
+
maxSharedClientsPerGpu: 2,
|
|
562
|
+
gpuSharingStrategy: "TIME_SHARING",
|
|
563
|
+
});
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
test("supports MIG partition size", () => {
|
|
567
|
+
const result = GpuNodePool({
|
|
568
|
+
name: "gpu-pool",
|
|
569
|
+
clusterRef: { name: "c" },
|
|
570
|
+
location: "us-central1",
|
|
571
|
+
gpuPartitionSize: "1g.5gb",
|
|
572
|
+
});
|
|
573
|
+
expect(p(result.nodePool).nodeConfig.guestAccelerator[0].gpuPartitionSize).toBe("1g.5gb");
|
|
574
|
+
});
|
|
575
|
+
|
|
576
|
+
test("references the target cluster", () => {
|
|
577
|
+
const result = GpuNodePool({
|
|
578
|
+
name: "gpu-pool",
|
|
579
|
+
clusterRef: { name: "ray-gke" },
|
|
580
|
+
location: "us-central1",
|
|
581
|
+
});
|
|
582
|
+
expect(p(result.nodePool).clusterRef).toEqual({ name: "ray-gke" });
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
test("matches the hand-wired ray-kuberay-gke example config", () => {
|
|
586
|
+
const result = GpuNodePool({
|
|
587
|
+
name: "ray-gke-gpu",
|
|
588
|
+
clusterRef: { name: "ray-gke" },
|
|
589
|
+
location: "us-central1",
|
|
590
|
+
machineType: "n1-standard-8",
|
|
591
|
+
acceleratorType: "nvidia-tesla-t4",
|
|
592
|
+
acceleratorCount: 1,
|
|
593
|
+
minNodeCount: 0,
|
|
594
|
+
maxNodeCount: 4,
|
|
595
|
+
diskSizeGb: 200,
|
|
596
|
+
diskType: "pd-ssd",
|
|
597
|
+
});
|
|
598
|
+
const spec = p(result.nodePool);
|
|
599
|
+
expect(spec.initialNodeCount).toBe(0);
|
|
600
|
+
expect(spec.autoscaling).toEqual({ minNodeCount: 0, maxNodeCount: 4, locationPolicy: "ANY" });
|
|
601
|
+
expect(spec.nodeConfig).toEqual({
|
|
602
|
+
machineType: "n1-standard-8",
|
|
603
|
+
diskSizeGb: 200,
|
|
604
|
+
diskType: "pd-ssd",
|
|
605
|
+
guestAccelerator: [{ count: 1, type: "nvidia-tesla-t4" }],
|
|
606
|
+
taint: [{ key: "nvidia.com/gpu", value: "present", effect: "NO_SCHEDULE" }],
|
|
607
|
+
workloadMetadataConfig: { mode: "GKE_METADATA" },
|
|
608
|
+
oauthScopes: ["https://www.googleapis.com/auth/cloud-platform"],
|
|
609
|
+
});
|
|
610
|
+
expect(spec.management).toEqual({ autoRepair: true, autoUpgrade: true });
|
|
611
|
+
});
|
|
612
|
+
});
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GpuNodePool composite — ContainerNodePool with GPU accelerators.
|
|
3
|
+
*
|
|
4
|
+
* Promoted from the hand-wired `gpuNodePool` in the ray-kuberay-gke example
|
|
5
|
+
* (examples/ray-kuberay-gke/src/infra/cluster.ts). Attaches to an existing
|
|
6
|
+
* GKE cluster (e.g. one created by `GkeCluster`) and adds a separate,
|
|
7
|
+
* scale-to-zero pool for GPU-tainted workloads.
|
|
8
|
+
*
|
|
9
|
+
* NOTE: GKE auto-installs the nvidia-device-plugin DaemonSet when a node
|
|
10
|
+
* pool has accelerators. Do NOT emit it as a K8s manifest — it will
|
|
11
|
+
* conflict with the GKE-managed version.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { Composite, mergeDefaults } from "@intentius/chant";
|
|
15
|
+
import { NodePool } from "../generated";
|
|
16
|
+
|
|
17
|
+
export interface GpuNodePoolTaint {
|
|
18
|
+
key: string;
|
|
19
|
+
value: string;
|
|
20
|
+
effect: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface GpuNodePoolProps {
|
|
24
|
+
/** Node pool name. */
|
|
25
|
+
name: string;
|
|
26
|
+
/** Reference to the GKE cluster this pool attaches to, e.g. `{ name: "my-cluster" }`. */
|
|
27
|
+
clusterRef: Record<string, unknown>;
|
|
28
|
+
/** GCP region or zone of the cluster. */
|
|
29
|
+
location: string;
|
|
30
|
+
/** Machine type for GPU nodes (default: "n1-standard-8"). */
|
|
31
|
+
machineType?: string;
|
|
32
|
+
/** Accelerator type, e.g. "nvidia-tesla-t4", "nvidia-l4", "nvidia-tesla-a100" (default: "nvidia-tesla-t4"). */
|
|
33
|
+
acceleratorType?: string;
|
|
34
|
+
/** Number of accelerators per node (default: 1). */
|
|
35
|
+
acceleratorCount?: number;
|
|
36
|
+
/** Minimum nodes for autoscaling — 0 enables scale-to-zero (default: 0). */
|
|
37
|
+
minNodeCount?: number;
|
|
38
|
+
/** Maximum nodes for autoscaling (default: 4). */
|
|
39
|
+
maxNodeCount?: number;
|
|
40
|
+
/** Boot disk size in GB (default: 200). */
|
|
41
|
+
diskSizeGb?: number;
|
|
42
|
+
/** Boot disk type (default: "pd-ssd"). */
|
|
43
|
+
diskType?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Node taints — only pods with a matching toleration are scheduled here.
|
|
46
|
+
* Default: `nvidia.com/gpu=present:NO_SCHEDULE`. Pass an empty array to omit tainting.
|
|
47
|
+
*/
|
|
48
|
+
taint?: GpuNodePoolTaint[];
|
|
49
|
+
/** Enable GKE metadata server workload identity mode on nodes (default: true). */
|
|
50
|
+
workloadMetadata?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* GPU time-sharing configuration, e.g.
|
|
53
|
+
* `{ maxSharedClientsPerGpu: 2, gpuSharingStrategy: "TIME_SHARING" }`.
|
|
54
|
+
*/
|
|
55
|
+
gpuSharingConfig?: Record<string, unknown>;
|
|
56
|
+
/** Multi-instance GPU (MIG) partition size, e.g. "1g.5gb". */
|
|
57
|
+
gpuPartitionSize?: string;
|
|
58
|
+
/** Additional labels. */
|
|
59
|
+
labels?: Record<string, string>;
|
|
60
|
+
/** Namespace for the node pool resource. */
|
|
61
|
+
namespace?: string;
|
|
62
|
+
/** Per-member defaults for customizing the underlying resource. */
|
|
63
|
+
defaults?: {
|
|
64
|
+
nodePool?: Partial<ConstructorParameters<typeof NodePool>[0]>;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const DEFAULT_TAINT: GpuNodePoolTaint[] = [
|
|
69
|
+
{ key: "nvidia.com/gpu", value: "present", effect: "NO_SCHEDULE" },
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Create a GpuNodePool composite — a scale-to-zero ContainerNodePool with
|
|
74
|
+
* GPU accelerators, tainted so only pods with a matching toleration land there.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```ts
|
|
78
|
+
* import { GpuNodePool } from "@intentius/chant-lexicon-gcp";
|
|
79
|
+
*
|
|
80
|
+
* const { nodePool } = GpuNodePool({
|
|
81
|
+
* name: "ray-gke-gpu",
|
|
82
|
+
* clusterRef: { name: "ray-gke" },
|
|
83
|
+
* location: "us-central1",
|
|
84
|
+
* acceleratorType: "nvidia-tesla-t4",
|
|
85
|
+
* maxNodeCount: 4,
|
|
86
|
+
* });
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export const GpuNodePool = Composite((props: GpuNodePoolProps) => {
|
|
90
|
+
const {
|
|
91
|
+
name,
|
|
92
|
+
clusterRef,
|
|
93
|
+
location,
|
|
94
|
+
machineType = "n1-standard-8",
|
|
95
|
+
acceleratorType = "nvidia-tesla-t4",
|
|
96
|
+
acceleratorCount = 1,
|
|
97
|
+
minNodeCount = 0,
|
|
98
|
+
maxNodeCount = 4,
|
|
99
|
+
diskSizeGb = 200,
|
|
100
|
+
diskType = "pd-ssd",
|
|
101
|
+
taint = DEFAULT_TAINT,
|
|
102
|
+
workloadMetadata = true,
|
|
103
|
+
gpuSharingConfig,
|
|
104
|
+
gpuPartitionSize,
|
|
105
|
+
labels: extraLabels = {},
|
|
106
|
+
namespace,
|
|
107
|
+
defaults: defs,
|
|
108
|
+
} = props;
|
|
109
|
+
|
|
110
|
+
const commonLabels: Record<string, string> = {
|
|
111
|
+
"app.kubernetes.io/name": name,
|
|
112
|
+
"app.kubernetes.io/managed-by": "chant",
|
|
113
|
+
...extraLabels,
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const guestAccelerator: Record<string, unknown> = {
|
|
117
|
+
count: acceleratorCount,
|
|
118
|
+
type: acceleratorType,
|
|
119
|
+
...(gpuSharingConfig && { gpuSharingConfig }),
|
|
120
|
+
...(gpuPartitionSize && { gpuPartitionSize }),
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const nodePool = new NodePool(mergeDefaults({
|
|
124
|
+
metadata: {
|
|
125
|
+
name,
|
|
126
|
+
...(namespace && { namespace }),
|
|
127
|
+
labels: { ...commonLabels, "app.kubernetes.io/component": "gpu-node-pool" },
|
|
128
|
+
},
|
|
129
|
+
clusterRef,
|
|
130
|
+
location,
|
|
131
|
+
initialNodeCount: 0,
|
|
132
|
+
autoscaling: {
|
|
133
|
+
minNodeCount,
|
|
134
|
+
maxNodeCount,
|
|
135
|
+
locationPolicy: "ANY",
|
|
136
|
+
},
|
|
137
|
+
nodeConfig: {
|
|
138
|
+
machineType,
|
|
139
|
+
diskSizeGb,
|
|
140
|
+
diskType,
|
|
141
|
+
guestAccelerator: [guestAccelerator],
|
|
142
|
+
...(taint.length > 0 && { taint }),
|
|
143
|
+
...(workloadMetadata && { workloadMetadataConfig: { mode: "GKE_METADATA" } }),
|
|
144
|
+
oauthScopes: ["https://www.googleapis.com/auth/cloud-platform"],
|
|
145
|
+
},
|
|
146
|
+
management: { autoRepair: true, autoUpgrade: true },
|
|
147
|
+
} as Record<string, unknown>, defs?.nodePool));
|
|
148
|
+
|
|
149
|
+
return { nodePool };
|
|
150
|
+
}, "GpuNodePool");
|
package/src/composites/index.ts
CHANGED
|
@@ -30,3 +30,5 @@ export { MultiRegionVpc } from "./multi-region-vpc";
|
|
|
30
30
|
export type { MultiRegionVpcConfig, MultiRegionVpcRegion } from "./multi-region-vpc";
|
|
31
31
|
export { GkeCrdbRegion } from "./gke-crdb-region";
|
|
32
32
|
export type { GkeCrdbRegionConfig, GkeCrdbRegionNodeConfig } from "./gke-crdb-region";
|
|
33
|
+
export { GpuNodePool } from "./gpu-node-pool";
|
|
34
|
+
export type { GpuNodePoolProps, GpuNodePoolTaint } from "./gpu-node-pool";
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
// Typed Op step-builder wrappers (chant #1288 Stage 2) — gcpApply/gcpDelete/
|
|
2
|
+
// flociGcpUp/flociGcpDown with authoring-time types derived from this
|
|
3
|
+
// lexicon's own *Args interfaces (see ./op/builders.ts's module doc for why
|
|
4
|
+
// these live here rather than in core or the temporal barrel). Opt-in:
|
|
5
|
+
// `@intentius/chant-lexicon-temporal`'s same-named exports are core's
|
|
6
|
+
// original untyped builders, unchanged.
|
|
7
|
+
export { gcpApply, gcpDelete, flociGcpUp, flociGcpDown } from "./op/builders";
|
|
8
|
+
|
|
1
9
|
// Serializer
|
|
2
10
|
export { gcpSerializer } from "./serializer";
|
|
3
11
|
|
|
@@ -22,7 +30,7 @@ export * from "./generated/index";
|
|
|
22
30
|
export {
|
|
23
31
|
GkeCluster, CloudRunServiceComposite, CloudSqlInstance, GcsBucket, VpcNetwork,
|
|
24
32
|
PubSubPipeline, CloudFunctionWithTrigger, PrivateService, ManagedCertificate, SecureProject,
|
|
25
|
-
MemorystoreRedis, MultiRegionVpc, GkeCrdbRegion,
|
|
33
|
+
MemorystoreRedis, MultiRegionVpc, GkeCrdbRegion, GpuNodePool,
|
|
26
34
|
GovernanceFoundation, LocationRestriction, OrganizationAuditConfig,
|
|
27
35
|
} from "./composites/index";
|
|
28
36
|
export type {
|
|
@@ -39,6 +47,7 @@ export type {
|
|
|
39
47
|
MemorystoreRedisProps,
|
|
40
48
|
MultiRegionVpcConfig, MultiRegionVpcRegion,
|
|
41
49
|
GkeCrdbRegionConfig, GkeCrdbRegionNodeConfig,
|
|
50
|
+
GpuNodePoolProps, GpuNodePoolTaint,
|
|
42
51
|
GovernanceFoundationProps, LocationRestrictionProps, OrganizationAuditConfigProps,
|
|
43
52
|
} from "./composites/index";
|
|
44
53
|
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed step-builder wrappers (chant #1288 Stage 2) — see
|
|
3
|
+
* `lexicons/k8s/src/op/builders.test.ts`'s module doc for what's asserted
|
|
4
|
+
* and why.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { describe, test, expect } from "vitest";
|
|
8
|
+
import {
|
|
9
|
+
gcpApply as gcpApplyOld,
|
|
10
|
+
gcpDelete as gcpDeleteOld,
|
|
11
|
+
flociGcpUp as flociGcpUpOld,
|
|
12
|
+
flociGcpDown as flociGcpDownOld,
|
|
13
|
+
stepOutput,
|
|
14
|
+
type StepOutputRef,
|
|
15
|
+
} from "@intentius/chant/op";
|
|
16
|
+
import { gcpApply, gcpDelete, flociGcpUp, flociGcpDown } from "./builders";
|
|
17
|
+
|
|
18
|
+
describe("gcp typed step builders (#1288 Stage 2)", () => {
|
|
19
|
+
test("gcpApply: identical ActivityStep to core's original for a minimal call", () => {
|
|
20
|
+
expect(gcpApply("dist/manifest.yaml")).toEqual(gcpApplyOld("dist/manifest.yaml"));
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("gcpApply: identical ActivityStep with opts", () => {
|
|
24
|
+
const opts = { project: "my-project", prune: true };
|
|
25
|
+
expect(gcpApply("dist/manifest.yaml", opts)).toEqual(gcpApplyOld("dist/manifest.yaml", opts));
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("gcpDelete: identical ActivityStep to core's original", () => {
|
|
29
|
+
expect(gcpDelete("dist/manifest.yaml")).toEqual(gcpDeleteOld("dist/manifest.yaml"));
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("flociGcpUp/flociGcpDown: identical ActivityStep to core's original", () => {
|
|
33
|
+
expect(flociGcpUp()).toEqual(flociGcpUpOld());
|
|
34
|
+
expect(flociGcpDown()).toEqual(flociGcpDownOld());
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("gcpApply: accepts a StepOutputRef in a typed slot", () => {
|
|
38
|
+
const ref = stepOutput("resolve-project", "project");
|
|
39
|
+
const step = gcpApply("dist/manifest.yaml", { project: ref });
|
|
40
|
+
expect(step.args?.project).toBe(ref);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("gcpApply: .out is reachable when an id is given", () => {
|
|
44
|
+
const step = gcpApply("dist/manifest.yaml", { id: "apply" });
|
|
45
|
+
const ref: StepOutputRef = step.out.applied;
|
|
46
|
+
expect(ref.step).toBe("apply");
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// ── Compile-time-only: authoring-time type errors (never executed) ──────────
|
|
51
|
+
function _typeChecksOnly(): void {
|
|
52
|
+
// @ts-expect-error — "projectId" is not a key of GcpApplyArgs (the field is `project`).
|
|
53
|
+
gcpApply("dist/manifest.yaml", { projectId: "my-project" });
|
|
54
|
+
|
|
55
|
+
// @ts-expect-error — prune must be a boolean.
|
|
56
|
+
gcpApply("dist/manifest.yaml", { prune: "true" });
|
|
57
|
+
}
|
|
58
|
+
void _typeChecksOnly;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed step-builder wrappers for this lexicon's activities (chant #1288
|
|
3
|
+
* Stage 2). See `lexicons/k8s/src/op/builders.ts`'s module doc for why these
|
|
4
|
+
* live beside their `*Args` interfaces rather than in core or the temporal
|
|
5
|
+
* barrel. `opts`'s type in each wrapper below IS the activity's own `*Args`
|
|
6
|
+
* interface (via `Omit`/`WithStepRefs`) — never restated. `core`'s own
|
|
7
|
+
* `gcpApply`/`gcpDelete`/`flociGcpUp`/`flociGcpDown` are unchanged and
|
|
8
|
+
* produce byte-identical `ActivityStep` output; these are purely additive.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
activity,
|
|
13
|
+
takeProfileAndId,
|
|
14
|
+
type ActivityStep,
|
|
15
|
+
type NamedActivityStep,
|
|
16
|
+
type WithStepRefs,
|
|
17
|
+
} from "@intentius/chant/op";
|
|
18
|
+
import type { GcpApplyArgs } from "./activities/gcp-apply";
|
|
19
|
+
import type { FlociGcpUpArgs, FlociGcpDownArgs } from "./activities/floci-gcp";
|
|
20
|
+
|
|
21
|
+
/** Extra opts every wrapper below accepts alongside its activity's own fields. */
|
|
22
|
+
type StepOpts = { profile?: ActivityStep["profile"]; id?: string };
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Apply built GCP (CNRM) resources directly to their GCP REST APIs — the
|
|
26
|
+
* fully typed twin of core's `gcpApply`. `opts` is {@link GcpApplyArgs}
|
|
27
|
+
* itself, minus the positional `manifestPath`. Defaults to the `longInfra`
|
|
28
|
+
* profile.
|
|
29
|
+
*/
|
|
30
|
+
export const gcpApply = (
|
|
31
|
+
manifestPath: string,
|
|
32
|
+
opts?: WithStepRefs<Omit<GcpApplyArgs, "manifestPath">> & StepOpts,
|
|
33
|
+
): NamedActivityStep => {
|
|
34
|
+
const { args, profile, id } = takeProfileAndId(opts as Record<string, unknown> | undefined);
|
|
35
|
+
return activity("gcpApply", { manifestPath, ...args }, { profile: profile ?? "longInfra", ...(id ? { id } : {}) });
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Delete the GCP (CNRM) resources in a built manifest — the inverse of
|
|
40
|
+
* {@link gcpApply}, fully typed twin of core's `gcpDelete`. `opts` is
|
|
41
|
+
* {@link GcpApplyArgs} itself (the activity reuses it), minus the positional
|
|
42
|
+
* `manifestPath`. Defaults to the `longInfra` profile.
|
|
43
|
+
*/
|
|
44
|
+
export const gcpDelete = (
|
|
45
|
+
manifestPath: string,
|
|
46
|
+
opts?: WithStepRefs<Omit<GcpApplyArgs, "manifestPath">> & StepOpts,
|
|
47
|
+
): NamedActivityStep => {
|
|
48
|
+
const { args, profile, id } = takeProfileAndId(opts as Record<string, unknown> | undefined);
|
|
49
|
+
return activity("gcpDelete", { manifestPath, ...args }, { profile: profile ?? "longInfra", ...(id ? { id } : {}) });
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Boot a local floci-gcp (GCP emulator) — the fully typed twin of core's
|
|
54
|
+
* `flociGcpUp`. `opts` is {@link FlociGcpUpArgs} itself. Defaults to the
|
|
55
|
+
* `longInfra` profile.
|
|
56
|
+
*/
|
|
57
|
+
export const flociGcpUp = (opts?: WithStepRefs<FlociGcpUpArgs> & StepOpts): NamedActivityStep => {
|
|
58
|
+
const { args, profile, id } = takeProfileAndId(opts as Record<string, unknown> | undefined);
|
|
59
|
+
return activity("flociGcpUp", args, { profile: profile ?? "longInfra", ...(id ? { id } : {}) });
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Stop and remove the local floci-gcp container — the fully typed twin of
|
|
64
|
+
* core's `flociGcpDown`. `opts` is {@link FlociGcpDownArgs} itself. Defaults
|
|
65
|
+
* to the `fastIdempotent` profile.
|
|
66
|
+
*/
|
|
67
|
+
export const flociGcpDown = (opts?: WithStepRefs<FlociGcpDownArgs> & StepOpts): NamedActivityStep => {
|
|
68
|
+
const { args, profile, id } = takeProfileAndId(opts as Record<string, unknown> | undefined);
|
|
69
|
+
return activity("flociGcpDown", args, { profile: profile ?? "fastIdempotent", ...(id ? { id } : {}) });
|
|
70
|
+
};
|
package/src/skills/chant-gcp.md
CHANGED
|
@@ -201,6 +201,7 @@ Composites group related Config Connector resources with secure defaults. Each r
|
|
|
201
201
|
| `PrivateService` | ComputeGlobalAddress + ServiceNetworkingConnection | RFC 1918 range, automatic peering |
|
|
202
202
|
| `ManagedCertificate` | ComputeManagedSslCertificate | Auto-renewal via Google-managed cert |
|
|
203
203
|
| `SecureProject` | Project + IAMAuditConfig + essential Service resources | Audit logging, required APIs enabled, org policy constraints |
|
|
204
|
+
| `GpuNodePool` | ContainerNodePool with GPU accelerators | Scale-to-zero, nvidia.com/gpu taint, GKE metadata workload identity |
|
|
204
205
|
|
|
205
206
|
### Example: GKE cluster with secure defaults
|
|
206
207
|
|