timonel 2.2.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +5 -1
  3. package/SECURITY.md +15 -8
  4. package/dist/cli.js +29 -31
  5. package/dist/cli.js.map +1 -1
  6. package/dist/index.d.ts +7 -2
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +7 -2
  9. package/dist/index.js.map +1 -1
  10. package/dist/lib/helm.d.ts +200 -12
  11. package/dist/lib/helm.d.ts.map +1 -1
  12. package/dist/lib/helm.js +234 -13
  13. package/dist/lib/helm.js.map +1 -1
  14. package/dist/lib/helmChartWriter.d.ts +238 -0
  15. package/dist/lib/helmChartWriter.d.ts.map +1 -0
  16. package/dist/lib/helmChartWriter.js +318 -0
  17. package/dist/lib/helmChartWriter.js.map +1 -0
  18. package/dist/lib/resources/autoscaling/autoscalingResources.d.ts +26 -0
  19. package/dist/lib/resources/autoscaling/autoscalingResources.d.ts.map +1 -0
  20. package/dist/lib/resources/autoscaling/autoscalingResources.js +35 -0
  21. package/dist/lib/resources/autoscaling/autoscalingResources.js.map +1 -0
  22. package/dist/lib/resources/baseResourceProvider.d.ts +47 -0
  23. package/dist/lib/resources/baseResourceProvider.d.ts.map +1 -0
  24. package/dist/lib/resources/baseResourceProvider.js +83 -0
  25. package/dist/lib/resources/baseResourceProvider.js.map +1 -0
  26. package/dist/lib/resources/cloud/aws/awsResources.d.ts +165 -0
  27. package/dist/lib/resources/cloud/aws/awsResources.d.ts.map +1 -0
  28. package/dist/lib/resources/cloud/aws/awsResources.js +187 -0
  29. package/dist/lib/resources/cloud/aws/awsResources.js.map +1 -0
  30. package/dist/lib/resources/cloud/azure/azureResources.d.ts +169 -0
  31. package/dist/lib/resources/cloud/azure/azureResources.d.ts.map +1 -0
  32. package/dist/lib/resources/cloud/azure/azureResources.js +218 -0
  33. package/dist/lib/resources/cloud/azure/azureResources.js.map +1 -0
  34. package/dist/lib/resources/cloud/gcp/gcpResources.d.ts +133 -0
  35. package/dist/lib/resources/cloud/gcp/gcpResources.d.ts.map +1 -0
  36. package/dist/lib/resources/cloud/gcp/gcpResources.js +162 -0
  37. package/dist/lib/resources/cloud/gcp/gcpResources.js.map +1 -0
  38. package/dist/lib/resources/core/coreResources.d.ts +584 -0
  39. package/dist/lib/resources/core/coreResources.d.ts.map +1 -0
  40. package/dist/lib/resources/core/coreResources.js +796 -0
  41. package/dist/lib/resources/core/coreResources.js.map +1 -0
  42. package/dist/lib/resources/core/storageResources.d.ts +133 -0
  43. package/dist/lib/resources/core/storageResources.d.ts.map +1 -0
  44. package/dist/lib/resources/core/storageResources.js +120 -0
  45. package/dist/lib/resources/core/storageResources.js.map +1 -0
  46. package/dist/lib/resources/validation/validationResources.d.ts +26 -0
  47. package/dist/lib/resources/validation/validationResources.d.ts.map +1 -0
  48. package/dist/lib/resources/validation/validationResources.js +33 -0
  49. package/dist/lib/resources/validation/validationResources.js.map +1 -0
  50. package/dist/lib/rutter.d.ts +554 -0
  51. package/dist/lib/rutter.d.ts.map +1 -0
  52. package/dist/lib/rutter.js +665 -0
  53. package/dist/lib/rutter.js.map +1 -0
  54. package/dist/lib/security.d.ts +73 -0
  55. package/dist/lib/security.d.ts.map +1 -0
  56. package/dist/lib/security.js +138 -0
  57. package/dist/lib/security.js.map +1 -0
  58. package/dist/lib/umbrella.d.ts +22 -2
  59. package/dist/lib/umbrella.d.ts.map +1 -1
  60. package/dist/lib/umbrella.js +21 -1
  61. package/dist/lib/umbrella.js.map +1 -1
  62. package/dist/lib/umbrellaRutter.d.ts +97 -0
  63. package/dist/lib/umbrellaRutter.d.ts.map +1 -0
  64. package/dist/lib/{UmbrellaRutter.js → umbrellaRutter.js} +72 -23
  65. package/dist/lib/umbrellaRutter.js.map +1 -0
  66. package/package.json +2 -1
  67. package/dist/lib/HelmChartWriter.d.ts +0 -69
  68. package/dist/lib/HelmChartWriter.d.ts.map +0 -1
  69. package/dist/lib/HelmChartWriter.js +0 -124
  70. package/dist/lib/HelmChartWriter.js.map +0 -1
  71. package/dist/lib/Rutter.d.ts +0 -1334
  72. package/dist/lib/Rutter.d.ts.map +0 -1
  73. package/dist/lib/Rutter.js +0 -2138
  74. package/dist/lib/Rutter.js.map +0 -1
  75. package/dist/lib/UmbrellaRutter.d.ts +0 -34
  76. package/dist/lib/UmbrellaRutter.d.ts.map +0 -1
  77. package/dist/lib/UmbrellaRutter.js.map +0 -1
@@ -0,0 +1,796 @@
1
+ import { ApiObject } from 'cdk8s';
2
+ import { BaseResourceProvider } from '../baseResourceProvider.js';
3
+ import { include } from '../../helm.js';
4
+ /**
5
+ * Core Kubernetes resources provider
6
+ * Handles fundamental Kubernetes resources like Deployments, Services, ConfigMaps, etc.
7
+ *
8
+ * @since 2.4.0
9
+ */
10
+ export class CoreResources extends BaseResourceProvider {
11
+ /**
12
+ * Creates a Deployment resource
13
+ * @param spec - Deployment specification
14
+ * @returns Created Deployment ApiObject
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * coreResources.addDeployment({
19
+ * name: 'web-app',
20
+ * image: 'nginx:1.21',
21
+ * replicas: 3,
22
+ * containerPort: 80
23
+ * });
24
+ * ```
25
+ *
26
+ * @since 2.4.0
27
+ */
28
+ addDeployment(spec) {
29
+ const matchLabels = spec.matchLabels ?? {
30
+ [CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
31
+ };
32
+ const labels = {
33
+ ...matchLabels,
34
+ ...spec.labels,
35
+ };
36
+ const containers = [
37
+ {
38
+ name: spec.name,
39
+ image: spec.image,
40
+ ...(spec.containerPort ? { ports: [{ containerPort: spec.containerPort }] } : {}),
41
+ ...(spec.env ? { env: spec.env } : {}),
42
+ ...(spec.resources ? { resources: spec.resources } : {}),
43
+ ...(spec.volumeMounts ? { volumeMounts: spec.volumeMounts } : {}),
44
+ ...(spec.securityContext ? { securityContext: spec.securityContext } : {}),
45
+ },
46
+ ];
47
+ const deploymentSpec = {
48
+ replicas: spec.replicas ?? 1,
49
+ selector: { matchLabels },
50
+ template: {
51
+ metadata: { labels },
52
+ spec: {
53
+ containers,
54
+ ...(spec.volumes ? { volumes: spec.volumes } : {}),
55
+ ...(spec.serviceAccountName ? { serviceAccountName: spec.serviceAccountName } : {}),
56
+ ...(spec.securityContext ? { securityContext: spec.securityContext } : {}),
57
+ ...(spec.nodeSelector ? { nodeSelector: spec.nodeSelector } : {}),
58
+ ...(spec.tolerations ? { tolerations: spec.tolerations } : {}),
59
+ ...(spec.affinity ? { affinity: spec.affinity } : {}),
60
+ },
61
+ },
62
+ };
63
+ return new ApiObject(this.chart, spec.name, {
64
+ apiVersion: CoreResources.APPS_API_VERSION,
65
+ kind: 'Deployment',
66
+ metadata: {
67
+ name: spec.name,
68
+ ...(labels && Object.keys(labels).length > 0 ? { labels } : {}),
69
+ ...(spec.annotations && Object.keys(spec.annotations).length > 0
70
+ ? { annotations: spec.annotations }
71
+ : {}),
72
+ },
73
+ spec: deploymentSpec,
74
+ });
75
+ }
76
+ /**
77
+ * Creates a Service resource
78
+ * @param spec - Service specification
79
+ * @returns Created Service ApiObject
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * coreResources.addService({
84
+ * name: 'web-service',
85
+ * port: 80,
86
+ * targetPort: 8080,
87
+ * type: 'ClusterIP'
88
+ * });
89
+ * ```
90
+ *
91
+ * @since 2.4.0
92
+ */
93
+ addService(spec) {
94
+ const selector = spec.selector ?? {
95
+ [CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
96
+ };
97
+ const ports = spec.ports ?? [
98
+ {
99
+ port: spec.port,
100
+ targetPort: spec.targetPort ?? spec.port,
101
+ ...(spec.protocol ? { protocol: spec.protocol } : {}),
102
+ ...(spec.name ? { name: spec.name } : {}),
103
+ },
104
+ ];
105
+ const serviceSpec = {
106
+ selector,
107
+ ports,
108
+ ...(spec.type ? { type: spec.type } : {}),
109
+ ...(spec.clusterIP ? { clusterIP: spec.clusterIP } : {}),
110
+ ...(spec.externalIPs ? { externalIPs: spec.externalIPs } : {}),
111
+ ...(spec.loadBalancerIP ? { loadBalancerIP: spec.loadBalancerIP } : {}),
112
+ ...(spec.sessionAffinity ? { sessionAffinity: spec.sessionAffinity } : {}),
113
+ };
114
+ return new ApiObject(this.chart, spec.name, {
115
+ apiVersion: CoreResources.CORE_API_VERSION,
116
+ kind: 'Service',
117
+ metadata: {
118
+ name: spec.name,
119
+ ...(spec.labels ? { labels: spec.labels } : {}),
120
+ ...(spec.annotations ? { annotations: spec.annotations } : {}),
121
+ },
122
+ spec: serviceSpec,
123
+ });
124
+ }
125
+ /**
126
+ * Creates a ConfigMap resource
127
+ * @param spec - ConfigMap specification
128
+ * @returns Created ConfigMap ApiObject
129
+ *
130
+ * @example
131
+ * ```typescript
132
+ * coreResources.addConfigMap({
133
+ * name: 'app-config',
134
+ * data: {
135
+ * 'config.yaml': 'key: value',
136
+ * 'app.properties': 'debug=true'
137
+ * }
138
+ * });
139
+ * ```
140
+ *
141
+ * @since 2.4.0
142
+ */
143
+ addConfigMap(spec) {
144
+ return new ApiObject(this.chart, spec.name, {
145
+ apiVersion: CoreResources.CORE_API_VERSION,
146
+ kind: 'ConfigMap',
147
+ metadata: {
148
+ name: spec.name,
149
+ ...(spec.labels ? { labels: spec.labels } : {}),
150
+ ...(spec.annotations ? { annotations: spec.annotations } : {}),
151
+ },
152
+ ...(spec.data ? { data: spec.data } : {}),
153
+ ...(spec.binaryData ? { binaryData: spec.binaryData } : {}),
154
+ });
155
+ }
156
+ /**
157
+ * Creates a Secret resource
158
+ * @param spec - Secret specification
159
+ * @returns Created Secret ApiObject
160
+ *
161
+ * @example
162
+ * ```typescript
163
+ * coreResources.addSecret({
164
+ * name: 'app-secrets',
165
+ * type: 'Opaque',
166
+ * data: {
167
+ * username: 'YWRtaW4=',
168
+ * password: 'MWYyZDFlMmU2N2Rm'
169
+ * }
170
+ * });
171
+ * ```
172
+ *
173
+ * @since 2.4.0
174
+ */
175
+ addSecret(spec) {
176
+ return new ApiObject(this.chart, spec.name, {
177
+ apiVersion: CoreResources.CORE_API_VERSION,
178
+ kind: 'Secret',
179
+ metadata: {
180
+ name: spec.name,
181
+ ...(spec.labels ? { labels: spec.labels } : {}),
182
+ ...(spec.annotations ? { annotations: spec.annotations } : {}),
183
+ },
184
+ type: spec.type ?? 'Opaque',
185
+ ...(spec.data ? { data: spec.data } : {}),
186
+ ...(spec.stringData ? { stringData: spec.stringData } : {}),
187
+ });
188
+ }
189
+ /**
190
+ * Creates a ServiceAccount resource
191
+ * @param spec - ServiceAccount specification
192
+ * @returns Created ServiceAccount ApiObject
193
+ *
194
+ * @example
195
+ * ```typescript
196
+ * coreResources.addServiceAccount({
197
+ * name: 'app-service-account',
198
+ * automountServiceAccountToken: false
199
+ * });
200
+ * ```
201
+ *
202
+ * @since 2.4.0
203
+ */
204
+ addServiceAccount(spec) {
205
+ return new ApiObject(this.chart, spec.name, {
206
+ apiVersion: CoreResources.CORE_API_VERSION,
207
+ kind: 'ServiceAccount',
208
+ metadata: {
209
+ name: spec.name,
210
+ ...(spec.labels ? { labels: spec.labels } : {}),
211
+ ...(spec.annotations ? { annotations: spec.annotations } : {}),
212
+ },
213
+ ...(spec.automountServiceAccountToken !== undefined
214
+ ? { automountServiceAccountToken: spec.automountServiceAccountToken }
215
+ : {}),
216
+ ...(spec.imagePullSecrets ? { imagePullSecrets: spec.imagePullSecrets } : {}),
217
+ ...(spec.secrets ? { secrets: spec.secrets } : {}),
218
+ });
219
+ }
220
+ /**
221
+ * Creates a DaemonSet resource
222
+ * @param spec - DaemonSet specification
223
+ * @returns Created DaemonSet ApiObject
224
+ *
225
+ * @example
226
+ * ```typescript
227
+ * coreResources.addDaemonSet({
228
+ * name: 'log-collector',
229
+ * image: 'fluentd:v1.14',
230
+ * containerPort: 24224,
231
+ * hostNetwork: true
232
+ * });
233
+ * ```
234
+ *
235
+ * @since 2.4.0
236
+ */
237
+ addDaemonSet(spec) {
238
+ const matchLabels = spec.matchLabels ?? {
239
+ [CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
240
+ };
241
+ const daemonSetSpec = this.buildDaemonSetSpec(spec, matchLabels);
242
+ const labels = {
243
+ [CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
244
+ ...(spec.labels || {}),
245
+ };
246
+ return new ApiObject(this.chart, spec.name, {
247
+ apiVersion: CoreResources.APPS_API_VERSION,
248
+ kind: 'DaemonSet',
249
+ metadata: {
250
+ name: spec.name,
251
+ ...(labels && Object.keys(labels).length > 0 ? { labels } : {}),
252
+ ...(spec.annotations && Object.keys(spec.annotations).length > 0
253
+ ? { annotations: spec.annotations }
254
+ : {}),
255
+ },
256
+ spec: daemonSetSpec,
257
+ });
258
+ }
259
+ /**
260
+ * Builds DaemonSet specification object
261
+ * @private
262
+ */
263
+ buildDaemonSetSpec(spec, matchLabels) {
264
+ const containers = this.buildDaemonSetContainers(spec);
265
+ const podSpec = this.buildDaemonSetPodSpec(spec, containers);
266
+ return {
267
+ selector: { matchLabels },
268
+ template: {
269
+ metadata: {
270
+ labels: { ...matchLabels, ...(spec.labels || {}) },
271
+ ...(spec.annotations && Object.keys(spec.annotations).length > 0
272
+ ? { annotations: spec.annotations }
273
+ : {}),
274
+ },
275
+ spec: podSpec,
276
+ },
277
+ ...(spec.updateStrategy && { updateStrategy: spec.updateStrategy }),
278
+ };
279
+ }
280
+ /**
281
+ * Builds container specification for DaemonSet
282
+ * @private
283
+ */
284
+ buildDaemonSetContainers(spec) {
285
+ const container = {
286
+ name: spec.name,
287
+ image: spec.image,
288
+ };
289
+ if (spec.containerPort) {
290
+ container['ports'] = [{ containerPort: spec.containerPort }];
291
+ }
292
+ if (spec.env) {
293
+ container['env'] = spec.env;
294
+ }
295
+ if (spec.resources) {
296
+ container['resources'] = spec.resources;
297
+ }
298
+ if (spec.volumeMounts) {
299
+ container['volumeMounts'] = spec.volumeMounts;
300
+ }
301
+ if (spec.securityContext) {
302
+ container['securityContext'] = spec.securityContext;
303
+ }
304
+ return [container];
305
+ }
306
+ /**
307
+ * Builds pod specification for DaemonSet
308
+ * @private
309
+ */
310
+ buildDaemonSetPodSpec(spec, containers) {
311
+ const podSpec = {
312
+ containers,
313
+ };
314
+ if (spec.serviceAccountName) {
315
+ podSpec['serviceAccountName'] = spec.serviceAccountName;
316
+ }
317
+ if (spec.nodeSelector) {
318
+ podSpec['nodeSelector'] = spec.nodeSelector;
319
+ }
320
+ if (spec.tolerations) {
321
+ podSpec['tolerations'] = spec.tolerations;
322
+ }
323
+ if (spec.affinity) {
324
+ podSpec['affinity'] = spec.affinity;
325
+ }
326
+ if (spec.volumes) {
327
+ podSpec['volumes'] = spec.volumes;
328
+ }
329
+ if (spec.hostNetwork) {
330
+ podSpec['hostNetwork'] = spec.hostNetwork;
331
+ }
332
+ if (spec.hostPID) {
333
+ podSpec['hostPID'] = spec.hostPID;
334
+ }
335
+ if (spec.dnsPolicy) {
336
+ podSpec['dnsPolicy'] = spec.dnsPolicy;
337
+ }
338
+ if (spec.priorityClassName) {
339
+ podSpec['priorityClassName'] = spec.priorityClassName;
340
+ }
341
+ return podSpec;
342
+ }
343
+ /**
344
+ * Creates a StatefulSet resource
345
+ * @param spec - StatefulSet specification
346
+ * @returns Created StatefulSet ApiObject
347
+ *
348
+ * @example
349
+ * ```typescript
350
+ * coreResources.addStatefulSet({
351
+ * name: 'database',
352
+ * image: 'postgres:13',
353
+ * replicas: 3,
354
+ * containerPort: 5432,
355
+ * serviceName: 'database-headless'
356
+ * });
357
+ * ```
358
+ *
359
+ * @since 2.4.0
360
+ */
361
+ addStatefulSet(spec) {
362
+ const matchLabels = spec.matchLabels ?? {
363
+ [CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
364
+ };
365
+ const statefulSetSpec = this.buildStatefulSetSpec(spec, matchLabels);
366
+ const labels = {
367
+ [CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
368
+ ...(spec.labels || {}),
369
+ };
370
+ return new ApiObject(this.chart, spec.name, {
371
+ apiVersion: CoreResources.APPS_API_VERSION,
372
+ kind: 'StatefulSet',
373
+ metadata: {
374
+ name: spec.name,
375
+ ...(labels && Object.keys(labels).length > 0 ? { labels } : {}),
376
+ ...(spec.annotations && Object.keys(spec.annotations).length > 0
377
+ ? { annotations: spec.annotations }
378
+ : {}),
379
+ },
380
+ spec: statefulSetSpec,
381
+ });
382
+ }
383
+ /**
384
+ * Builds StatefulSet specification object
385
+ * @private
386
+ */
387
+ buildStatefulSetSpec(spec, matchLabels) {
388
+ const containers = this.buildStatefulSetContainers(spec);
389
+ const podSpec = this.buildStatefulSetPodSpec(spec, containers);
390
+ const statefulSetSpec = {
391
+ replicas: spec.replicas ?? 1,
392
+ selector: { matchLabels },
393
+ serviceName: spec.serviceName,
394
+ template: {
395
+ metadata: {
396
+ labels: { ...matchLabels, ...(spec.labels || {}) },
397
+ ...(spec.annotations && Object.keys(spec.annotations).length > 0
398
+ ? { annotations: spec.annotations }
399
+ : {}),
400
+ },
401
+ spec: podSpec,
402
+ },
403
+ };
404
+ if (spec.volumeClaimTemplates) {
405
+ statefulSetSpec['volumeClaimTemplates'] = spec.volumeClaimTemplates;
406
+ }
407
+ if (spec.updateStrategy) {
408
+ statefulSetSpec['updateStrategy'] = spec.updateStrategy;
409
+ }
410
+ if (spec.podManagementPolicy) {
411
+ statefulSetSpec['podManagementPolicy'] = spec.podManagementPolicy;
412
+ }
413
+ if (spec.revisionHistoryLimit !== undefined) {
414
+ statefulSetSpec['revisionHistoryLimit'] = spec.revisionHistoryLimit;
415
+ }
416
+ return statefulSetSpec;
417
+ }
418
+ /**
419
+ * Builds container specification for StatefulSet
420
+ * @private
421
+ */
422
+ buildStatefulSetContainers(spec) {
423
+ const container = {
424
+ name: spec.name,
425
+ image: spec.image,
426
+ };
427
+ if (spec.containerPort) {
428
+ container['ports'] = [{ containerPort: spec.containerPort }];
429
+ }
430
+ if (spec.env) {
431
+ container['env'] = spec.env;
432
+ }
433
+ if (spec.resources) {
434
+ container['resources'] = spec.resources;
435
+ }
436
+ if (spec.volumeMounts) {
437
+ container['volumeMounts'] = spec.volumeMounts;
438
+ }
439
+ if (spec.securityContext) {
440
+ container['securityContext'] = spec.securityContext;
441
+ }
442
+ if (spec.livenessProbe) {
443
+ container['livenessProbe'] = spec.livenessProbe;
444
+ }
445
+ if (spec.readinessProbe) {
446
+ container['readinessProbe'] = spec.readinessProbe;
447
+ }
448
+ return [container];
449
+ }
450
+ /**
451
+ * Builds pod specification for StatefulSet
452
+ * @private
453
+ */
454
+ buildStatefulSetPodSpec(spec, containers) {
455
+ const podSpec = {
456
+ containers,
457
+ };
458
+ if (spec.serviceAccountName) {
459
+ podSpec['serviceAccountName'] = spec.serviceAccountName;
460
+ }
461
+ if (spec.nodeSelector) {
462
+ podSpec['nodeSelector'] = spec.nodeSelector;
463
+ }
464
+ if (spec.tolerations) {
465
+ podSpec['tolerations'] = spec.tolerations;
466
+ }
467
+ if (spec.affinity) {
468
+ podSpec['affinity'] = spec.affinity;
469
+ }
470
+ if (spec.volumes) {
471
+ podSpec['volumes'] = spec.volumes;
472
+ }
473
+ if (spec.initContainers) {
474
+ podSpec['initContainers'] = spec.initContainers;
475
+ }
476
+ if (spec.terminationGracePeriodSeconds !== undefined) {
477
+ podSpec['terminationGracePeriodSeconds'] = spec.terminationGracePeriodSeconds;
478
+ }
479
+ return podSpec;
480
+ }
481
+ /**
482
+ * Creates a Role resource for RBAC
483
+ * @param spec - Role specification
484
+ * @returns Created Role ApiObject
485
+ *
486
+ * @example
487
+ * ```typescript
488
+ * coreResources.addRole({
489
+ * name: 'pod-reader',
490
+ * rules: [
491
+ * {
492
+ * apiGroups: [''],
493
+ * resources: ['pods'],
494
+ * verbs: ['get', 'list', 'watch']
495
+ * }
496
+ * ]
497
+ * });
498
+ * ```
499
+ *
500
+ * @since 2.4.0
501
+ */
502
+ addRole(spec) {
503
+ const labels = {
504
+ [CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
505
+ ...(spec.labels || {}),
506
+ };
507
+ return new ApiObject(this.chart, spec.name, {
508
+ apiVersion: CoreResources.RBAC_API_VERSION,
509
+ kind: 'Role',
510
+ metadata: {
511
+ name: spec.name,
512
+ ...(spec.namespace && { namespace: spec.namespace }),
513
+ ...(labels && Object.keys(labels).length > 0 ? { labels } : {}),
514
+ ...(spec.annotations && Object.keys(spec.annotations).length > 0
515
+ ? { annotations: spec.annotations }
516
+ : {}),
517
+ },
518
+ rules: spec.rules,
519
+ });
520
+ }
521
+ /**
522
+ * Creates a ClusterRole resource for cluster-wide RBAC
523
+ * @param spec - ClusterRole specification
524
+ * @returns Created ClusterRole ApiObject
525
+ *
526
+ * @example
527
+ * ```typescript
528
+ * coreResources.addClusterRole({
529
+ * name: 'cluster-admin',
530
+ * rules: [
531
+ * {
532
+ * apiGroups: ['*'],
533
+ * resources: ['*'],
534
+ * verbs: ['*']
535
+ * }
536
+ * ]
537
+ * });
538
+ * ```
539
+ *
540
+ * @since 2.4.0
541
+ */
542
+ addClusterRole(spec) {
543
+ const labels = {
544
+ [CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
545
+ ...(spec.labels || {}),
546
+ };
547
+ return new ApiObject(this.chart, spec.name, {
548
+ apiVersion: CoreResources.RBAC_API_VERSION,
549
+ kind: 'ClusterRole',
550
+ metadata: {
551
+ name: spec.name,
552
+ ...(labels && Object.keys(labels).length > 0 ? { labels } : {}),
553
+ ...(spec.annotations && Object.keys(spec.annotations).length > 0
554
+ ? { annotations: spec.annotations }
555
+ : {}),
556
+ },
557
+ rules: spec.rules,
558
+ });
559
+ }
560
+ /**
561
+ * Creates a RoleBinding resource for RBAC
562
+ * @param spec - RoleBinding specification
563
+ * @returns Created RoleBinding ApiObject
564
+ *
565
+ * @example
566
+ * ```typescript
567
+ * coreResources.addRoleBinding({
568
+ * name: 'pod-reader-binding',
569
+ * roleRef: {
570
+ * kind: 'Role',
571
+ * name: 'pod-reader',
572
+ * apiGroup: 'rbac.authorization.k8s.io'
573
+ * },
574
+ * subjects: [
575
+ * {
576
+ * kind: 'ServiceAccount',
577
+ * name: 'my-service-account',
578
+ * namespace: 'default'
579
+ * }
580
+ * ]
581
+ * });
582
+ * ```
583
+ *
584
+ * @since 2.4.0
585
+ */
586
+ addRoleBinding(spec) {
587
+ const labels = {
588
+ [CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
589
+ ...(spec.labels || {}),
590
+ };
591
+ return new ApiObject(this.chart, spec.name, {
592
+ apiVersion: CoreResources.RBAC_API_VERSION,
593
+ kind: 'RoleBinding',
594
+ metadata: {
595
+ name: spec.name,
596
+ ...(spec.namespace && { namespace: spec.namespace }),
597
+ ...(labels && Object.keys(labels).length > 0 ? { labels } : {}),
598
+ ...(spec.annotations && Object.keys(spec.annotations).length > 0
599
+ ? { annotations: spec.annotations }
600
+ : {}),
601
+ },
602
+ roleRef: spec.roleRef,
603
+ subjects: spec.subjects,
604
+ });
605
+ }
606
+ /**
607
+ * Creates a ClusterRoleBinding resource for cluster-wide RBAC
608
+ * @param spec - ClusterRoleBinding specification
609
+ * @returns Created ClusterRoleBinding ApiObject
610
+ *
611
+ * @example
612
+ * ```typescript
613
+ * coreResources.addClusterRoleBinding({
614
+ * name: 'cluster-admin-binding',
615
+ * roleRef: {
616
+ * kind: 'ClusterRole',
617
+ * name: 'cluster-admin',
618
+ * apiGroup: 'rbac.authorization.k8s.io'
619
+ * },
620
+ * subjects: [
621
+ * {
622
+ * kind: 'ServiceAccount',
623
+ * name: 'admin-user',
624
+ * namespace: 'kube-system'
625
+ * }
626
+ * ]
627
+ * });
628
+ * ```
629
+ *
630
+ * @since 2.4.0
631
+ */
632
+ addClusterRoleBinding(spec) {
633
+ const labels = {
634
+ [CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
635
+ ...(spec.labels || {}),
636
+ };
637
+ return new ApiObject(this.chart, spec.name, {
638
+ apiVersion: CoreResources.RBAC_API_VERSION,
639
+ kind: 'ClusterRoleBinding',
640
+ metadata: {
641
+ name: spec.name,
642
+ ...(labels && Object.keys(labels).length > 0 ? { labels } : {}),
643
+ ...(spec.annotations && Object.keys(spec.annotations).length > 0
644
+ ? { annotations: spec.annotations }
645
+ : {}),
646
+ },
647
+ roleRef: spec.roleRef,
648
+ subjects: spec.subjects,
649
+ });
650
+ }
651
+ /**
652
+ * Creates a Job resource for batch workloads
653
+ * @param spec - Job specification
654
+ * @returns Created Job ApiObject
655
+ *
656
+ * @example
657
+ * ```typescript
658
+ * coreResources.addJob({
659
+ * name: 'data-processor',
660
+ * image: 'busybox:1.35',
661
+ * command: ['sh', '-c', 'echo "Processing data..." && sleep 30'],
662
+ * completions: 1,
663
+ * parallelism: 1
664
+ * });
665
+ * ```
666
+ *
667
+ * @since 2.4.0
668
+ */
669
+ addJob(spec) {
670
+ const matchLabels = spec.matchLabels ?? {
671
+ [CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
672
+ };
673
+ const jobSpec = this.buildJobSpec(spec, matchLabels);
674
+ const labels = {
675
+ [CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
676
+ ...(spec.labels || {}),
677
+ };
678
+ return new ApiObject(this.chart, spec.name, {
679
+ apiVersion: 'batch/v1',
680
+ kind: 'Job',
681
+ metadata: {
682
+ name: spec.name,
683
+ ...(labels && Object.keys(labels).length > 0 ? { labels } : {}),
684
+ ...(spec.annotations && Object.keys(spec.annotations).length > 0
685
+ ? { annotations: spec.annotations }
686
+ : {}),
687
+ },
688
+ spec: jobSpec,
689
+ });
690
+ }
691
+ /**
692
+ * Builds Job specification object
693
+ * @private
694
+ */
695
+ buildJobSpec(spec, matchLabels) {
696
+ const containers = this.buildJobContainers(spec);
697
+ const podSpec = this.buildJobPodSpec(spec, containers);
698
+ const jobSpec = {
699
+ template: {
700
+ metadata: {
701
+ labels: { ...matchLabels, ...(spec.labels || {}) },
702
+ ...(spec.annotations && Object.keys(spec.annotations).length > 0
703
+ ? { annotations: spec.annotations }
704
+ : {}),
705
+ },
706
+ spec: podSpec,
707
+ },
708
+ };
709
+ if (spec.completions !== undefined) {
710
+ jobSpec['completions'] = spec.completions;
711
+ }
712
+ if (spec.parallelism !== undefined) {
713
+ jobSpec['parallelism'] = spec.parallelism;
714
+ }
715
+ if (spec.backoffLimit !== undefined) {
716
+ jobSpec['backoffLimit'] = spec.backoffLimit;
717
+ }
718
+ if (spec.activeDeadlineSeconds !== undefined) {
719
+ jobSpec['activeDeadlineSeconds'] = spec.activeDeadlineSeconds;
720
+ }
721
+ if (spec.ttlSecondsAfterFinished !== undefined) {
722
+ jobSpec['ttlSecondsAfterFinished'] = spec.ttlSecondsAfterFinished;
723
+ }
724
+ if (spec.completionMode) {
725
+ jobSpec['completionMode'] = spec.completionMode;
726
+ }
727
+ if (spec.suspend !== undefined) {
728
+ jobSpec['suspend'] = spec.suspend;
729
+ }
730
+ return jobSpec;
731
+ }
732
+ /**
733
+ * Builds container specification for Job
734
+ * @private
735
+ */
736
+ buildJobContainers(spec) {
737
+ const container = {
738
+ name: spec.name,
739
+ image: spec.image,
740
+ };
741
+ if (spec.command) {
742
+ container['command'] = spec.command;
743
+ }
744
+ if (spec.args) {
745
+ container['args'] = spec.args;
746
+ }
747
+ if (spec.env) {
748
+ container['env'] = spec.env;
749
+ }
750
+ if (spec.resources) {
751
+ container['resources'] = spec.resources;
752
+ }
753
+ if (spec.volumeMounts) {
754
+ container['volumeMounts'] = spec.volumeMounts;
755
+ }
756
+ if (spec.securityContext) {
757
+ container['securityContext'] = spec.securityContext;
758
+ }
759
+ return [container];
760
+ }
761
+ /**
762
+ * Builds pod specification for Job
763
+ * @private
764
+ */
765
+ buildJobPodSpec(spec, containers) {
766
+ const podSpec = {
767
+ containers,
768
+ restartPolicy: spec.restartPolicy ?? 'Never',
769
+ };
770
+ if (spec.serviceAccountName) {
771
+ podSpec['serviceAccountName'] = spec.serviceAccountName;
772
+ }
773
+ if (spec.nodeSelector) {
774
+ podSpec['nodeSelector'] = spec.nodeSelector;
775
+ }
776
+ if (spec.tolerations) {
777
+ podSpec['tolerations'] = spec.tolerations;
778
+ }
779
+ if (spec.affinity) {
780
+ podSpec['affinity'] = spec.affinity;
781
+ }
782
+ if (spec.volumes) {
783
+ podSpec['volumes'] = spec.volumes;
784
+ }
785
+ if (spec.initContainers) {
786
+ podSpec['initContainers'] = spec.initContainers;
787
+ }
788
+ return podSpec;
789
+ }
790
+ }
791
+ CoreResources.APPS_API_VERSION = 'apps/v1';
792
+ CoreResources.CORE_API_VERSION = 'v1';
793
+ CoreResources.RBAC_API_VERSION = 'rbac.authorization.k8s.io/v1';
794
+ CoreResources.LABEL_NAME = 'app.kubernetes.io/name';
795
+ CoreResources.HELPER_NAME = 'chart.name';
796
+ //# sourceMappingURL=coreResources.js.map