@intentius/chant-lexicon-k8s 0.1.0 → 0.1.4

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.
@@ -0,0 +1,235 @@
1
+ /**
2
+ * RayJob composite — KubeRay RayJob CR + surrounding K8s infra.
3
+ *
4
+ * RayJob spins up an ephemeral Ray cluster, runs a single entrypoint command,
5
+ * then tears the cluster down. Ideal for batch training pipelines.
6
+ *
7
+ * Encodes the same production defaults as RayCluster (NetworkPolicy,
8
+ * preStop hooks, optional shared PVC, optional autoscaler RBAC).
9
+ */
10
+
11
+ import { Composite, mergeDefaults } from "@intentius/chant";
12
+ import {
13
+ ServiceAccount,
14
+ ClusterRole,
15
+ ClusterRoleBinding,
16
+ NetworkPolicy,
17
+ PersistentVolumeClaim,
18
+ RayJob as RayJobResource,
19
+ } from "../generated";
20
+ import {
21
+ type RayClusterSpec,
22
+ buildRayClusterParts,
23
+ buildRayNetworkPolicy,
24
+ } from "./ray-cluster";
25
+
26
+ export type { RayClusterSpec };
27
+ export type { ResourceSpec, HeadGroupSpec, WorkerGroupSpec } from "./ray-cluster";
28
+
29
+ export interface RayJobProps {
30
+ name: string;
31
+ namespace: string;
32
+ /**
33
+ * Entrypoint command to run on the Ray cluster.
34
+ * E.g. "python train.py --epochs 10"
35
+ */
36
+ entrypoint: string;
37
+ cluster: RayClusterSpec;
38
+ /**
39
+ * Ray runtime environment YAML string.
40
+ * Prefer pre-built images over pip installs here — each pip install adds
41
+ * startup latency per worker on cold start.
42
+ */
43
+ runtimeEnvYAML?: string;
44
+ /**
45
+ * Tear down the cluster after the job finishes (default: true).
46
+ * Set false to keep the cluster alive for debugging.
47
+ */
48
+ shutdownAfterJobFinishes?: boolean;
49
+ /**
50
+ * TTL in seconds before a finished RayJob is garbage-collected (default: 300).
51
+ */
52
+ ttlSecondsAfterFinished?: number;
53
+ sharedStorage?: {
54
+ storageClass: string;
55
+ size: string;
56
+ mountPath?: string;
57
+ };
58
+ enableAutoscaler?: boolean;
59
+ spilloverBucket?: string;
60
+ labels?: Record<string, string>;
61
+ defaults?: {
62
+ serviceAccount?: Partial<Record<string, unknown>>;
63
+ clusterRole?: Partial<Record<string, unknown>>;
64
+ clusterRoleBinding?: Partial<Record<string, unknown>>;
65
+ networkPolicy?: Partial<Record<string, unknown>>;
66
+ pvc?: Partial<Record<string, unknown>>;
67
+ rayJob?: Partial<Record<string, unknown>>;
68
+ };
69
+ }
70
+
71
+ export interface RayJobResult {
72
+ serviceAccount: InstanceType<typeof ServiceAccount>;
73
+ clusterRole?: InstanceType<typeof ClusterRole>;
74
+ clusterRoleBinding?: InstanceType<typeof ClusterRoleBinding>;
75
+ networkPolicy: InstanceType<typeof NetworkPolicy>;
76
+ pvc?: InstanceType<typeof PersistentVolumeClaim>;
77
+ rayJob: InstanceType<typeof RayJobResource>;
78
+ }
79
+
80
+ /**
81
+ * Create a RayJob composite — ephemeral Ray cluster for a single batch job.
82
+ *
83
+ * @example
84
+ * ```ts
85
+ * import { RayJob } from "@intentius/chant-lexicon-k8s";
86
+ *
87
+ * const job = RayJob({
88
+ * name: "train-resnet",
89
+ * namespace: "ray-system",
90
+ * entrypoint: "python train.py --epochs 50",
91
+ * cluster: {
92
+ * image: "us-docker.pkg.dev/my-project/ray-images/ray:2.40.0",
93
+ * head: { resources: { cpu: "2", memory: "8Gi" } },
94
+ * workerGroups: [
95
+ * { groupName: "gpu", replicas: 4,
96
+ * resources: { cpu: "8", memory: "32Gi", gpu: 1 },
97
+ * gpuTolerations: true },
98
+ * ],
99
+ * },
100
+ * spilloverBucket: "my-ray-spill",
101
+ * });
102
+ * ```
103
+ */
104
+ export const RayJob = Composite<RayJobProps>((props) => {
105
+ const {
106
+ name,
107
+ namespace,
108
+ entrypoint,
109
+ cluster,
110
+ runtimeEnvYAML,
111
+ shutdownAfterJobFinishes = true,
112
+ ttlSecondsAfterFinished = 300,
113
+ sharedStorage,
114
+ enableAutoscaler = false,
115
+ spilloverBucket,
116
+ labels: extraLabels = {},
117
+ defaults: defs,
118
+ } = props;
119
+
120
+ const saName = `${name}-head`;
121
+ const pvcName = sharedStorage ? `${name}-shared` : undefined;
122
+ const mountPath = sharedStorage?.mountPath;
123
+
124
+ const commonLabels: Record<string, string> = {
125
+ "app.kubernetes.io/name": name,
126
+ "app.kubernetes.io/managed-by": "chant",
127
+ "app.kubernetes.io/component": "ray",
128
+ ...extraLabels,
129
+ };
130
+
131
+ // -- ServiceAccount --
132
+
133
+ const serviceAccount = new ServiceAccount(mergeDefaults({
134
+ metadata: {
135
+ name: saName,
136
+ namespace,
137
+ labels: { ...commonLabels, "app.kubernetes.io/component": "service-account" },
138
+ },
139
+ }, defs?.serviceAccount));
140
+
141
+ // -- Autoscaler RBAC (optional) --
142
+
143
+ const clusterRole = enableAutoscaler ? new ClusterRole(mergeDefaults({
144
+ metadata: {
145
+ name: `${name}-autoscaler`,
146
+ labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
147
+ },
148
+ rules: [
149
+ {
150
+ apiGroups: [""],
151
+ resources: ["pods"],
152
+ verbs: ["get", "list", "watch", "create", "delete", "patch"],
153
+ },
154
+ {
155
+ apiGroups: [""],
156
+ resources: ["pods/status"],
157
+ verbs: ["get"],
158
+ },
159
+ {
160
+ apiGroups: ["ray.io"],
161
+ resources: ["rayjobs"],
162
+ verbs: ["get", "list", "patch"],
163
+ },
164
+ ],
165
+ }, defs?.clusterRole)) : undefined;
166
+
167
+ const clusterRoleBinding = enableAutoscaler ? new ClusterRoleBinding(mergeDefaults({
168
+ metadata: {
169
+ name: `${name}-autoscaler`,
170
+ labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
171
+ },
172
+ roleRef: {
173
+ apiGroup: "rbac.authorization.k8s.io",
174
+ kind: "ClusterRole",
175
+ name: `${name}-autoscaler`,
176
+ },
177
+ subjects: [{ kind: "ServiceAccount", name: saName, namespace }],
178
+ }, defs?.clusterRoleBinding)) : undefined;
179
+
180
+ // -- NetworkPolicy --
181
+
182
+ const networkPolicy = buildRayNetworkPolicy(
183
+ name, namespace, commonLabels, false, defs?.networkPolicy,
184
+ );
185
+
186
+ // -- Shared PVC (optional) --
187
+
188
+ const pvc = sharedStorage ? new PersistentVolumeClaim(mergeDefaults({
189
+ metadata: {
190
+ name: pvcName!,
191
+ namespace,
192
+ labels: { ...commonLabels, "app.kubernetes.io/component": "storage" },
193
+ },
194
+ spec: {
195
+ accessModes: ["ReadWriteMany"],
196
+ storageClassName: sharedStorage.storageClass,
197
+ resources: { requests: { storage: sharedStorage.size } },
198
+ },
199
+ }, defs?.pvc)) : undefined;
200
+
201
+ // -- RayJob CR --
202
+
203
+ const { headGroupSpec, workerGroupSpecs, rayVersion } = buildRayClusterParts(
204
+ cluster, saName, spilloverBucket, pvcName, mountPath,
205
+ );
206
+
207
+ const rayJob = new RayJobResource(mergeDefaults({
208
+ metadata: {
209
+ name,
210
+ namespace,
211
+ labels: commonLabels,
212
+ },
213
+ spec: {
214
+ entrypoint,
215
+ ...(runtimeEnvYAML && { runtimeEnvYAML }),
216
+ shutdownAfterJobFinishes,
217
+ ttlSecondsAfterFinished,
218
+ rayClusterSpec: {
219
+ ...(rayVersion && { rayVersion }),
220
+ ...(enableAutoscaler && { enableInTreeAutoscaling: true }),
221
+ headGroupSpec,
222
+ workerGroupSpecs,
223
+ },
224
+ },
225
+ }, defs?.rayJob));
226
+
227
+ return {
228
+ serviceAccount,
229
+ ...(clusterRole && { clusterRole }),
230
+ ...(clusterRoleBinding && { clusterRoleBinding }),
231
+ networkPolicy,
232
+ ...(pvc && { pvc }),
233
+ rayJob,
234
+ };
235
+ }, "RayJob");
@@ -0,0 +1,271 @@
1
+ /**
2
+ * RayService composite — KubeRay RayService CR + surrounding K8s infra.
3
+ *
4
+ * RayService manages a persistent Ray Serve HTTP endpoint with zero-downtime
5
+ * blue-green upgrades. Ideal for online inference and serving workloads.
6
+ *
7
+ * Encodes the same production defaults as RayCluster (NetworkPolicy, preStop
8
+ * hooks, PDB, optional shared PVC, optional autoscaler RBAC) plus a
9
+ * LoadBalancer Service exposing the Serve HTTP endpoint on port 8000.
10
+ */
11
+
12
+ import { Composite, mergeDefaults } from "@intentius/chant";
13
+ import {
14
+ ServiceAccount,
15
+ ClusterRole,
16
+ ClusterRoleBinding,
17
+ NetworkPolicy,
18
+ PodDisruptionBudget,
19
+ PersistentVolumeClaim,
20
+ Service,
21
+ RayService as RayServiceResource,
22
+ } from "../generated";
23
+ import {
24
+ type RayClusterSpec,
25
+ buildRayClusterParts,
26
+ buildRayNetworkPolicy,
27
+ } from "./ray-cluster";
28
+
29
+ export type { RayClusterSpec };
30
+ export type { ResourceSpec, HeadGroupSpec, WorkerGroupSpec } from "./ray-cluster";
31
+
32
+ export interface RayServiceProps {
33
+ name: string;
34
+ namespace: string;
35
+ /**
36
+ * Ray Serve application config in YAML format.
37
+ * Passed verbatim to spec.serveConfigV2.
38
+ * See https://docs.ray.io/en/latest/serve/production-guide/config.html
39
+ */
40
+ serveConfigV2: string;
41
+ cluster: RayClusterSpec;
42
+ sharedStorage?: {
43
+ storageClass: string;
44
+ size: string;
45
+ mountPath?: string;
46
+ };
47
+ enableAutoscaler?: boolean;
48
+ spilloverBucket?: string;
49
+ labels?: Record<string, string>;
50
+ defaults?: {
51
+ serviceAccount?: Partial<Record<string, unknown>>;
52
+ clusterRole?: Partial<Record<string, unknown>>;
53
+ clusterRoleBinding?: Partial<Record<string, unknown>>;
54
+ networkPolicy?: Partial<Record<string, unknown>>;
55
+ pdb?: Partial<Record<string, unknown>>;
56
+ pvc?: Partial<Record<string, unknown>>;
57
+ serveService?: Partial<Record<string, unknown>>;
58
+ rayService?: Partial<Record<string, unknown>>;
59
+ };
60
+ }
61
+
62
+ export interface RayServiceResult {
63
+ serviceAccount: InstanceType<typeof ServiceAccount>;
64
+ clusterRole?: InstanceType<typeof ClusterRole>;
65
+ clusterRoleBinding?: InstanceType<typeof ClusterRoleBinding>;
66
+ networkPolicy: InstanceType<typeof NetworkPolicy>;
67
+ pdb: InstanceType<typeof PodDisruptionBudget>;
68
+ pvc?: InstanceType<typeof PersistentVolumeClaim>;
69
+ /** LoadBalancer Service exposing Ray Serve on port 8000. */
70
+ serveService: InstanceType<typeof Service>;
71
+ rayService: InstanceType<typeof RayServiceResource>;
72
+ }
73
+
74
+ /**
75
+ * Create a RayService composite — persistent Ray Serve endpoint with
76
+ * zero-downtime blue-green upgrades.
77
+ *
78
+ * @example
79
+ * ```ts
80
+ * import { RayService } from "@intentius/chant-lexicon-k8s";
81
+ *
82
+ * const svc = RayService({
83
+ * name: "inference",
84
+ * namespace: "ray-system",
85
+ * serveConfigV2: `
86
+ * applications:
87
+ * - name: classifier
88
+ * import_path: app:deployment
89
+ * deployments:
90
+ * - name: Classifier
91
+ * num_replicas: 2
92
+ * `,
93
+ * cluster: {
94
+ * image: "us-docker.pkg.dev/my-project/ray-images/ray:2.40.0",
95
+ * head: { resources: { cpu: "2", memory: "8Gi" } },
96
+ * workerGroups: [
97
+ * { groupName: "gpu", replicas: 2,
98
+ * resources: { cpu: "4", memory: "16Gi", gpu: 1 },
99
+ * gpuTolerations: true },
100
+ * ],
101
+ * },
102
+ * });
103
+ * ```
104
+ */
105
+ export const RayService = Composite<RayServiceProps>((props) => {
106
+ const {
107
+ name,
108
+ namespace,
109
+ serveConfigV2,
110
+ cluster,
111
+ sharedStorage,
112
+ enableAutoscaler = false,
113
+ spilloverBucket,
114
+ labels: extraLabels = {},
115
+ defaults: defs,
116
+ } = props;
117
+
118
+ const saName = `${name}-head`;
119
+ const pvcName = sharedStorage ? `${name}-shared` : undefined;
120
+ const mountPath = sharedStorage?.mountPath;
121
+
122
+ const commonLabels: Record<string, string> = {
123
+ "app.kubernetes.io/name": name,
124
+ "app.kubernetes.io/managed-by": "chant",
125
+ "app.kubernetes.io/component": "ray",
126
+ ...extraLabels,
127
+ };
128
+
129
+ // -- ServiceAccount --
130
+
131
+ const serviceAccount = new ServiceAccount(mergeDefaults({
132
+ metadata: {
133
+ name: saName,
134
+ namespace,
135
+ labels: { ...commonLabels, "app.kubernetes.io/component": "service-account" },
136
+ },
137
+ }, defs?.serviceAccount));
138
+
139
+ // -- Autoscaler RBAC (optional) --
140
+
141
+ const clusterRole = enableAutoscaler ? new ClusterRole(mergeDefaults({
142
+ metadata: {
143
+ name: `${name}-autoscaler`,
144
+ labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
145
+ },
146
+ rules: [
147
+ {
148
+ apiGroups: [""],
149
+ resources: ["pods"],
150
+ verbs: ["get", "list", "watch", "create", "delete", "patch"],
151
+ },
152
+ {
153
+ apiGroups: [""],
154
+ resources: ["pods/status"],
155
+ verbs: ["get"],
156
+ },
157
+ {
158
+ apiGroups: ["ray.io"],
159
+ resources: ["rayservices"],
160
+ verbs: ["get", "list", "patch"],
161
+ },
162
+ ],
163
+ }, defs?.clusterRole)) : undefined;
164
+
165
+ const clusterRoleBinding = enableAutoscaler ? new ClusterRoleBinding(mergeDefaults({
166
+ metadata: {
167
+ name: `${name}-autoscaler`,
168
+ labels: { ...commonLabels, "app.kubernetes.io/component": "rbac" },
169
+ },
170
+ roleRef: {
171
+ apiGroup: "rbac.authorization.k8s.io",
172
+ kind: "ClusterRole",
173
+ name: `${name}-autoscaler`,
174
+ },
175
+ subjects: [{ kind: "ServiceAccount", name: saName, namespace }],
176
+ }, defs?.clusterRoleBinding)) : undefined;
177
+
178
+ // -- NetworkPolicy --
179
+ // RayService exposes port 8000 (Serve HTTP) externally via LoadBalancer,
180
+ // so we allow ingress from outside the cluster on that port.
181
+
182
+ const networkPolicy = buildRayNetworkPolicy(
183
+ name, namespace, commonLabels, false, defs?.networkPolicy,
184
+ );
185
+
186
+ // -- PodDisruptionBudget (head) --
187
+
188
+ const pdb = new PodDisruptionBudget(mergeDefaults({
189
+ metadata: {
190
+ name: `${name}-head`,
191
+ namespace,
192
+ labels: { ...commonLabels, "app.kubernetes.io/component": "disruption-budget" },
193
+ },
194
+ spec: {
195
+ minAvailable: 1,
196
+ selector: {
197
+ matchLabels: {
198
+ "ray.io/cluster-name": name,
199
+ "ray.io/node-type": "head",
200
+ },
201
+ },
202
+ },
203
+ }, defs?.pdb));
204
+
205
+ // -- Shared PVC (optional) --
206
+
207
+ const pvc = sharedStorage ? new PersistentVolumeClaim(mergeDefaults({
208
+ metadata: {
209
+ name: pvcName!,
210
+ namespace,
211
+ labels: { ...commonLabels, "app.kubernetes.io/component": "storage" },
212
+ },
213
+ spec: {
214
+ accessModes: ["ReadWriteMany"],
215
+ storageClassName: sharedStorage.storageClass,
216
+ resources: { requests: { storage: sharedStorage.size } },
217
+ },
218
+ }, defs?.pvc)) : undefined;
219
+
220
+ // -- Ray Serve LoadBalancer Service --
221
+
222
+ const serveService = new Service(mergeDefaults({
223
+ metadata: {
224
+ name: `${name}-serve`,
225
+ namespace,
226
+ labels: { ...commonLabels, "app.kubernetes.io/component": "serve" },
227
+ },
228
+ spec: {
229
+ type: "LoadBalancer",
230
+ selector: {
231
+ "ray.io/cluster-name": name,
232
+ "ray.io/node-type": "head",
233
+ },
234
+ ports: [{ port: 8000, targetPort: 8000, protocol: "TCP", name: "serve" }],
235
+ },
236
+ }, defs?.serveService));
237
+
238
+ // -- RayService CR --
239
+
240
+ const { headGroupSpec, workerGroupSpecs, rayVersion } = buildRayClusterParts(
241
+ cluster, saName, spilloverBucket, pvcName, mountPath,
242
+ );
243
+
244
+ const rayService = new RayServiceResource(mergeDefaults({
245
+ metadata: {
246
+ name,
247
+ namespace,
248
+ labels: commonLabels,
249
+ },
250
+ spec: {
251
+ serveConfigV2,
252
+ rayClusterConfig: {
253
+ ...(rayVersion && { rayVersion }),
254
+ ...(enableAutoscaler && { enableInTreeAutoscaling: true }),
255
+ headGroupSpec,
256
+ workerGroupSpecs,
257
+ },
258
+ },
259
+ }, defs?.rayService));
260
+
261
+ return {
262
+ serviceAccount,
263
+ ...(clusterRole && { clusterRole }),
264
+ ...(clusterRoleBinding && { clusterRoleBinding }),
265
+ networkPolicy,
266
+ pdb,
267
+ ...(pvc && { pvc }),
268
+ serveService,
269
+ rayService,
270
+ };
271
+ }, "RayService");
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Third-party CRD sources included in k8s lexicon generation.
3
+ *
4
+ * Add entries here to have CRDs fetched and code-generated alongside
5
+ * the core Kubernetes OpenAPI types. The CRD YAML is fetched at
6
+ * generation time (npm run generate) and baked into the output.
7
+ */
8
+
9
+ import type { CRDSource } from "./types";
10
+
11
+ /**
12
+ * KubeRay operator CRDs — ray.io/v1
13
+ *
14
+ * Produces:
15
+ * K8s::Ray::RayCluster → apiVersion: ray.io/v1, kind: RayCluster
16
+ * K8s::Ray::RayJob → apiVersion: ray.io/v1, kind: RayJob
17
+ * K8s::Ray::RayService → apiVersion: ray.io/v1, kind: RayService
18
+ *
19
+ * Operator install: kubectl apply -f
20
+ * https://github.com/ray-project/kuberay/releases/download/v1.3.0/kuberay-operator.yaml
21
+ */
22
+ const KUBERAY_VERSION = "v1.3.0";
23
+ const KUBERAY_CRD_BASE = `https://raw.githubusercontent.com/ray-project/kuberay/${KUBERAY_VERSION}/helm-chart/kuberay-operator/crds`;
24
+
25
+ export const CRD_SOURCES: CRDSource[] = [
26
+ { type: "url", url: `${KUBERAY_CRD_BASE}/ray.io_rayclusters.yaml` },
27
+ { type: "url", url: `${KUBERAY_CRD_BASE}/ray.io_rayjobs.yaml` },
28
+ { type: "url", url: `${KUBERAY_CRD_BASE}/ray.io_rayservices.yaml` },
29
+ ];
package/src/crd/parser.ts CHANGED
@@ -10,7 +10,7 @@
10
10
  import type { K8sParseResult, ParsedProperty, ParsedPropertyType, GroupVersionKind } from "../spec/parse";
11
11
  import type { CRDSpec } from "./types";
12
12
  import type { PropertyConstraints } from "@intentius/chant/codegen/json-schema";
13
- import { parseYAML } from "@intentius/chant/yaml";
13
+ import { loadAll } from "js-yaml";
14
14
 
15
15
  /**
16
16
  * Normalize a CRD group to a PascalCase namespace segment.
@@ -34,17 +34,17 @@ function normalizeGroupName(group: string): string {
34
34
  export function parseCRD(content: string): K8sParseResult[] {
35
35
  const results: K8sParseResult[] = [];
36
36
 
37
- // Support multi-document YAML for CRD bundles
38
- const documents = content
39
- .split(/^---\s*$/m)
40
- .map((d) => d.trim())
41
- .filter((d) => d.length > 0);
37
+ // Use js-yaml to handle full YAML spec (CRD YAMLs use same-indent arrays,
38
+ // nested block scalars, and deep nesting not supported by the lightweight parser).
39
+ const documents: unknown[] = [];
40
+ loadAll(content, (doc) => documents.push(doc));
42
41
 
43
- for (const docStr of documents) {
44
- const doc = parseYAML(docStr) as Record<string, unknown>;
45
- if (!doc || doc.kind !== "CustomResourceDefinition") continue;
42
+ for (const doc of documents) {
43
+ if (!doc || typeof doc !== "object") continue;
44
+ const docObj = doc as Record<string, unknown>;
45
+ if (docObj.kind !== "CustomResourceDefinition") continue;
46
46
 
47
- const spec = doc.spec as CRDSpec | undefined;
47
+ const spec = docObj.spec as CRDSpec | undefined;
48
48
  if (!spec?.group || !spec?.names?.kind || !spec?.versions) continue;
49
49
 
50
50
  const crdResults = parseCRDSpec(spec);
@@ -160,10 +160,15 @@ function extractPropertyTypes(schema: OpenAPISchema, parentTypeName: string): Pa
160
160
  const specSchema = schema.properties?.spec;
161
161
  if (!specSchema?.properties) return results;
162
162
 
163
+ // Use the short name (last :: segment) as prefix so the naming pipeline
164
+ // produces valid TS identifiers: "RayCluster_AutoscalerOptions" not
165
+ // "K8s::Ray::RayCluster::AutoscalerOptions".
166
+ const shortName = parentTypeName.split("::").pop()!;
167
+
163
168
  for (const [name, prop] of Object.entries(specSchema.properties)) {
164
169
  // Extract inline object definitions as property types
165
170
  if (prop.type === "object" && prop.properties) {
166
- const ptName = `${parentTypeName}::${pascalCase(name)}`;
171
+ const ptName = `${shortName}_${pascalCase(name)}`;
167
172
  const requiredSet = new Set<string>(prop.required ?? []);
168
173
 
169
174
  results.push({
@@ -184,7 +189,7 @@ function extractPropertyTypes(schema: OpenAPISchema, parentTypeName: string): Pa
184
189
  if (prop.type === "array" && prop.items?.type === "object" && prop.items.properties) {
185
190
  const itemSchema = prop.items;
186
191
  const itemProps = itemSchema.properties!;
187
- const ptName = `${parentTypeName}::${pascalCase(singularize(name))}`;
192
+ const ptName = `${shortName}_${pascalCase(singularize(name))}`;
188
193
  const requiredSet = new Set<string>(itemSchema.required ?? []);
189
194
 
190
195
  results.push({
@@ -1244,6 +1244,36 @@ export declare class PVC {
1244
1244
  readonly uid: string;
1245
1245
  }
1246
1246
 
1247
+ export declare class RayCluster {
1248
+ constructor(props: {
1249
+ metadata?: Record<string, unknown>;
1250
+ spec?: Record<string, unknown>;
1251
+ });
1252
+ readonly name: string;
1253
+ readonly namespace: string;
1254
+ readonly uid: string;
1255
+ }
1256
+
1257
+ export declare class RayJob {
1258
+ constructor(props: {
1259
+ metadata?: Record<string, unknown>;
1260
+ spec?: Record<string, unknown>;
1261
+ });
1262
+ readonly name: string;
1263
+ readonly namespace: string;
1264
+ readonly uid: string;
1265
+ }
1266
+
1267
+ export declare class RayService {
1268
+ constructor(props: {
1269
+ metadata?: Record<string, unknown>;
1270
+ spec?: Record<string, unknown>;
1271
+ });
1272
+ readonly name: string;
1273
+ readonly namespace: string;
1274
+ readonly uid: string;
1275
+ }
1276
+
1247
1277
  export declare class ReplicaSet {
1248
1278
  constructor(props: {
1249
1279
  /** If the Labels of a ReplicaSet are empty, they are defaulted to be the same as the Pod(s) that the ReplicaSet manages. Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata */
@@ -96,6 +96,9 @@ export const PriorityLevelConfiguration = createResource("K8s::Flowcontrol::Prio
96
96
  export const PriorityLevelConfigurationList = createResource("K8s::Flowcontrol::PriorityLevelConfigurationList", "k8s", {"name":"name","namespace":"namespace","uid":"uid"});
97
97
  export const PV = createResource("K8s::Core::PersistentVolume", "k8s", {"name":"name","namespace":"namespace","uid":"uid"});
98
98
  export const PVC = createResource("K8s::Core::PersistentVolumeClaim", "k8s", {"name":"name","namespace":"namespace","uid":"uid"});
99
+ export const RayCluster = createResource("K8s::Ray::RayCluster", "k8s", {"name":"name","namespace":"namespace","uid":"uid"});
100
+ export const RayJob = createResource("K8s::Ray::RayJob", "k8s", {"name":"name","namespace":"namespace","uid":"uid"});
101
+ export const RayService = createResource("K8s::Ray::RayService", "k8s", {"name":"name","namespace":"namespace","uid":"uid"});
99
102
  export const ReplicaSet = createResource("K8s::Apps::ReplicaSet", "k8s", {"name":"name","namespace":"namespace","uid":"uid"});
100
103
  export const ReplicaSetList = createResource("K8s::Apps::ReplicaSetList", "k8s", {"name":"name","namespace":"namespace","uid":"uid"});
101
104
  export const ReplicationController = createResource("K8s::Core::ReplicationController", "k8s", {"name":"name","namespace":"namespace","uid":"uid"});
@@ -186,6 +189,16 @@ export const PodSpec = createProperty("K8s::Core::PodSpec", "k8s");
186
189
  export const PodTemplateSpec = createProperty("K8s::Core::PodTemplateSpec", "k8s");
187
190
  export const PolicyRule = createProperty("K8s::Rbac::PolicyRule", "k8s");
188
191
  export const Probe = createProperty("K8s::Core::Probe", "k8s");
192
+ export const RayCluster_AutoscalerOptions = createProperty("K8s::Ray::RayCluster.autoscalerOptions", "k8s");
193
+ export const RayCluster_GcsFaultToleranceOptions = createProperty("K8s::Ray::RayCluster.gcsFaultToleranceOptions", "k8s");
194
+ export const RayCluster_HeadGroupSpec = createProperty("K8s::Ray::RayCluster.headGroupSpec", "k8s");
195
+ export const RayCluster_WorkerGroupSpec = createProperty("K8s::Ray::RayCluster.workerGroupSpecs", "k8s");
196
+ export const RayJob_RayClusterSpec = createProperty("K8s::Ray::RayJob.rayClusterSpec", "k8s");
197
+ export const RayJob_SubmitterConfig = createProperty("K8s::Ray::RayJob.submitterConfig", "k8s");
198
+ export const RayJob_SubmitterPodTemplate = createProperty("K8s::Ray::RayJob.submitterPodTemplate", "k8s");
199
+ export const RayService_RayClusterConfig = createProperty("K8s::Ray::RayService.rayClusterConfig", "k8s");
200
+ export const RayService_ServeService = createProperty("K8s::Ray::RayService.serveService", "k8s");
201
+ export const RayService_UpgradeStrategy = createProperty("K8s::Ray::RayService.upgradeStrategy", "k8s");
189
202
  export const ResourceRequirements = createProperty("K8s::Core::ResourceRequirements", "k8s");
190
203
  export const RoleRef = createProperty("K8s::Rbac::RoleRef", "k8s");
191
204
  export const RollingUpdateDeployment = createProperty("K8s::Apps::RollingUpdateDeployment", "k8s");