timonel 2.8.0-beta.4 → 2.8.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/CHANGELOG.md +9 -19
- package/README.md +12 -55
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +7 -15
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -7
- package/dist/index.js.map +1 -1
- package/dist/lib/helm.d.ts +234 -4
- package/dist/lib/helm.d.ts.map +1 -1
- package/dist/lib/helm.js +309 -20
- package/dist/lib/helm.js.map +1 -1
- package/dist/lib/helmChartWriter.js +5 -19
- package/dist/lib/helmChartWriter.js.map +1 -1
- package/dist/lib/resources/baseResourceProvider.d.ts +1 -1
- package/dist/lib/resources/baseResourceProvider.d.ts.map +1 -1
- package/dist/lib/resources/baseResourceProvider.js.map +1 -1
- package/dist/lib/resources/cloud/aws/awsResources.d.ts +5 -6
- package/dist/lib/resources/cloud/aws/awsResources.d.ts.map +1 -1
- package/dist/lib/resources/cloud/aws/awsResources.js +59 -30
- package/dist/lib/resources/cloud/aws/awsResources.js.map +1 -1
- package/dist/lib/rutter.d.ts +73 -708
- package/dist/lib/rutter.d.ts.map +1 -1
- package/dist/lib/rutter.js +157 -837
- package/dist/lib/rutter.js.map +1 -1
- package/dist/lib/security.d.ts +2 -1
- package/dist/lib/security.d.ts.map +1 -1
- package/dist/lib/security.js +33 -4
- package/dist/lib/security.js.map +1 -1
- package/dist/lib/umbrellaRutter.d.ts +1 -1
- package/dist/lib/umbrellaRutter.d.ts.map +1 -1
- package/dist/lib/utils/helmHelpers.d.ts +2 -12
- package/dist/lib/utils/helmHelpers.d.ts.map +1 -1
- package/dist/lib/utils/helmHelpers.js +2 -46
- package/dist/lib/utils/helmHelpers.js.map +1 -1
- package/package.json +2 -2
- package/dist/lib/resources/autoscaling/autoscalingResources.d.ts +0 -248
- package/dist/lib/resources/autoscaling/autoscalingResources.d.ts.map +0 -1
- package/dist/lib/resources/autoscaling/autoscalingResources.js +0 -81
- package/dist/lib/resources/autoscaling/autoscalingResources.js.map +0 -1
- package/dist/lib/resources/cloud/azure/azureResources.d.ts +0 -169
- package/dist/lib/resources/cloud/azure/azureResources.d.ts.map +0 -1
- package/dist/lib/resources/cloud/azure/azureResources.js +0 -218
- package/dist/lib/resources/cloud/azure/azureResources.js.map +0 -1
- package/dist/lib/resources/cloud/gcp/gcpResources.d.ts +0 -164
- package/dist/lib/resources/cloud/gcp/gcpResources.d.ts.map +0 -1
- package/dist/lib/resources/cloud/gcp/gcpResources.js +0 -192
- package/dist/lib/resources/cloud/gcp/gcpResources.js.map +0 -1
- package/dist/lib/resources/core/coreResources.d.ts +0 -790
- package/dist/lib/resources/core/coreResources.d.ts.map +0 -1
- package/dist/lib/resources/core/coreResources.js +0 -1115
- package/dist/lib/resources/core/coreResources.js.map +0 -1
- package/dist/lib/resources/core/storageResources.d.ts +0 -133
- package/dist/lib/resources/core/storageResources.d.ts.map +0 -1
- package/dist/lib/resources/core/storageResources.js +0 -120
- package/dist/lib/resources/core/storageResources.js.map +0 -1
- package/dist/lib/resources/network/networkResources.d.ts +0 -229
- package/dist/lib/resources/network/networkResources.d.ts.map +0 -1
- package/dist/lib/resources/network/networkResources.js +0 -310
- package/dist/lib/resources/network/networkResources.js.map +0 -1
- package/dist/lib/resources/validation/validationResources.d.ts +0 -26
- package/dist/lib/resources/validation/validationResources.d.ts.map +0 -1
- package/dist/lib/resources/validation/validationResources.js +0 -33
- package/dist/lib/resources/validation/validationResources.js.map +0 -1
- package/dist/lib/utils/podTemplates.d.ts +0 -192
- package/dist/lib/utils/podTemplates.d.ts.map +0 -1
- package/dist/lib/utils/podTemplates.js +0 -331
- package/dist/lib/utils/podTemplates.js.map +0 -1
- package/dist/lib/utils/resourceNaming.d.ts +0 -57
- package/dist/lib/utils/resourceNaming.d.ts.map +0 -1
- package/dist/lib/utils/resourceNaming.js +0 -82
- package/dist/lib/utils/resourceNaming.js.map +0 -1
package/dist/lib/rutter.js
CHANGED
|
@@ -1,19 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ApiObject, App, Chart, Testing } from 'cdk8s';
|
|
2
2
|
import YAML from 'yaml';
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import { StorageResources } from './resources/core/storageResources.js';
|
|
3
|
+
import { helm, include } from './helm.js';
|
|
4
|
+
import { HelmChartWriter } from './helmChartWriter.js';
|
|
6
5
|
import { AWSResources } from './resources/cloud/aws/awsResources.js';
|
|
7
|
-
import { AzureResources } from './resources/cloud/azure/azureResources.js';
|
|
8
|
-
import { GCPResources } from './resources/cloud/gcp/gcpResources.js';
|
|
9
|
-
import { AutoscalingResources } from './resources/autoscaling/autoscalingResources.js';
|
|
10
|
-
import { NetworkResources } from './resources/network/networkResources.js';
|
|
11
6
|
import { KarpenterResources } from './resources/cloud/aws/karpenterResources.js';
|
|
12
|
-
// Import HelmChartWriter for write functionality
|
|
13
|
-
import { HelmChartWriter } from './helmChartWriter.js';
|
|
14
|
-
import { include, helm } from './helm.js';
|
|
15
7
|
import { generateHelpersTemplate } from './utils/helmHelpers.js';
|
|
16
|
-
import { generateManifestName } from './utils/resourceNaming.js';
|
|
17
8
|
/**
|
|
18
9
|
* Rutter class with modular architecture
|
|
19
10
|
* Provides a clean API while delegating to specialized resource providers
|
|
@@ -35,346 +26,9 @@ export class Rutter {
|
|
|
35
26
|
...(props.namespace ? { namespace: props.namespace } : {}),
|
|
36
27
|
});
|
|
37
28
|
// Initialize resource providers
|
|
38
|
-
this.coreResources = new CoreResources(this.chart);
|
|
39
|
-
this.storageResources = new StorageResources(this.chart);
|
|
40
29
|
this.awsResources = new AWSResources(this.chart);
|
|
41
|
-
this.azureResources = new AzureResources(this.chart);
|
|
42
|
-
this.gcpResources = new GCPResources(this.chart);
|
|
43
|
-
this.autoscalingResources = new AutoscalingResources(this.chart);
|
|
44
|
-
this.networkResources = new NetworkResources(this.chart);
|
|
45
30
|
this.karpenterResources = new KarpenterResources(this.chart);
|
|
46
31
|
}
|
|
47
|
-
// Core Kubernetes Resources
|
|
48
|
-
/**
|
|
49
|
-
* Creates a Deployment resource
|
|
50
|
-
* @param spec - Deployment specification
|
|
51
|
-
* @returns Created Deployment ApiObject
|
|
52
|
-
*
|
|
53
|
-
* @example
|
|
54
|
-
* ```typescript
|
|
55
|
-
* rutter.addDeployment({
|
|
56
|
-
* name: 'web-app',
|
|
57
|
-
* image: 'nginx:1.21',
|
|
58
|
-
* replicas: 3,
|
|
59
|
-
* containerPort: 80
|
|
60
|
-
* });
|
|
61
|
-
* ```
|
|
62
|
-
*
|
|
63
|
-
* @since 1.0.0
|
|
64
|
-
*/
|
|
65
|
-
addDeployment(spec) {
|
|
66
|
-
return this.coreResources.addDeployment(spec);
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Creates a DaemonSet resource
|
|
70
|
-
* @param spec - DaemonSet specification
|
|
71
|
-
* @returns Created DaemonSet ApiObject
|
|
72
|
-
*
|
|
73
|
-
* @example
|
|
74
|
-
* ```typescript
|
|
75
|
-
* rutter.addDaemonSet({
|
|
76
|
-
* name: 'log-collector',
|
|
77
|
-
* image: 'fluentd:v1.14',
|
|
78
|
-
* containerPort: 24224,
|
|
79
|
-
* hostNetwork: true
|
|
80
|
-
* });
|
|
81
|
-
* ```
|
|
82
|
-
*
|
|
83
|
-
* @since 2.4.0
|
|
84
|
-
*/
|
|
85
|
-
addDaemonSet(spec) {
|
|
86
|
-
return this.coreResources.addDaemonSet(spec);
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Creates a StatefulSet resource
|
|
90
|
-
* @param spec - StatefulSet specification
|
|
91
|
-
* @returns Created StatefulSet ApiObject
|
|
92
|
-
*
|
|
93
|
-
* @example
|
|
94
|
-
* ```typescript
|
|
95
|
-
* rutter.addStatefulSet({
|
|
96
|
-
* name: 'database',
|
|
97
|
-
* image: 'postgres:13',
|
|
98
|
-
* replicas: 3,
|
|
99
|
-
* serviceName: 'database-headless',
|
|
100
|
-
* containerPort: 5432
|
|
101
|
-
* });
|
|
102
|
-
* ```
|
|
103
|
-
*
|
|
104
|
-
* @since 2.4.0
|
|
105
|
-
*/
|
|
106
|
-
addStatefulSet(spec) {
|
|
107
|
-
return this.coreResources.addStatefulSet(spec);
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Creates a Role resource for RBAC
|
|
111
|
-
* @param spec - Role specification
|
|
112
|
-
* @returns Created Role ApiObject
|
|
113
|
-
*
|
|
114
|
-
* @example
|
|
115
|
-
* ```typescript
|
|
116
|
-
* rutter.addRole({
|
|
117
|
-
* name: 'pod-reader',
|
|
118
|
-
* rules: [
|
|
119
|
-
* {
|
|
120
|
-
* apiGroups: [''],
|
|
121
|
-
* resources: ['pods'],
|
|
122
|
-
* verbs: ['get', 'list', 'watch']
|
|
123
|
-
* }
|
|
124
|
-
* ]
|
|
125
|
-
* });
|
|
126
|
-
* ```
|
|
127
|
-
*
|
|
128
|
-
* @since 2.4.0
|
|
129
|
-
*/
|
|
130
|
-
addRole(spec) {
|
|
131
|
-
return this.coreResources.addRole(spec);
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Creates a ClusterRole resource for cluster-wide RBAC
|
|
135
|
-
* @param spec - ClusterRole specification
|
|
136
|
-
* @returns Created ClusterRole ApiObject
|
|
137
|
-
*
|
|
138
|
-
* @example
|
|
139
|
-
* ```typescript
|
|
140
|
-
* rutter.addClusterRole({
|
|
141
|
-
* name: 'cluster-reader',
|
|
142
|
-
* rules: [
|
|
143
|
-
* {
|
|
144
|
-
* apiGroups: [''],
|
|
145
|
-
* resources: ['nodes', 'namespaces'],
|
|
146
|
-
* verbs: ['get', 'list', 'watch']
|
|
147
|
-
* }
|
|
148
|
-
* ]
|
|
149
|
-
* });
|
|
150
|
-
* ```
|
|
151
|
-
*
|
|
152
|
-
* @since 2.4.0
|
|
153
|
-
*/
|
|
154
|
-
addClusterRole(spec) {
|
|
155
|
-
return this.coreResources.addClusterRole(spec);
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Creates a RoleBinding resource for RBAC
|
|
159
|
-
* @param spec - RoleBinding specification
|
|
160
|
-
* @returns Created RoleBinding ApiObject
|
|
161
|
-
*
|
|
162
|
-
* @example
|
|
163
|
-
* ```typescript
|
|
164
|
-
* rutter.addRoleBinding({
|
|
165
|
-
* name: 'pod-reader-binding',
|
|
166
|
-
* roleRef: {
|
|
167
|
-
* kind: 'Role',
|
|
168
|
-
* name: 'pod-reader',
|
|
169
|
-
* apiGroup: 'rbac.authorization.k8s.io'
|
|
170
|
-
* },
|
|
171
|
-
* subjects: [
|
|
172
|
-
* {
|
|
173
|
-
* kind: 'ServiceAccount',
|
|
174
|
-
* name: 'my-service-account'
|
|
175
|
-
* }
|
|
176
|
-
* ]
|
|
177
|
-
* });
|
|
178
|
-
* ```
|
|
179
|
-
*
|
|
180
|
-
* @since 2.4.0
|
|
181
|
-
*/
|
|
182
|
-
addRoleBinding(spec) {
|
|
183
|
-
return this.coreResources.addRoleBinding(spec);
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* Creates a ClusterRoleBinding resource for cluster-wide RBAC
|
|
187
|
-
* @param spec - ClusterRoleBinding specification
|
|
188
|
-
* @returns Created ClusterRoleBinding ApiObject
|
|
189
|
-
*
|
|
190
|
-
* @example
|
|
191
|
-
* ```typescript
|
|
192
|
-
* rutter.addClusterRoleBinding({
|
|
193
|
-
* name: 'cluster-reader-binding',
|
|
194
|
-
* roleRef: {
|
|
195
|
-
* kind: 'ClusterRole',
|
|
196
|
-
* name: 'cluster-reader',
|
|
197
|
-
* apiGroup: 'rbac.authorization.k8s.io'
|
|
198
|
-
* },
|
|
199
|
-
* subjects: [
|
|
200
|
-
* {
|
|
201
|
-
* kind: 'ServiceAccount',
|
|
202
|
-
* name: 'monitoring-agent',
|
|
203
|
-
* namespace: 'monitoring'
|
|
204
|
-
* }
|
|
205
|
-
* ]
|
|
206
|
-
* });
|
|
207
|
-
* ```
|
|
208
|
-
*
|
|
209
|
-
* @since 2.4.0
|
|
210
|
-
*/
|
|
211
|
-
addClusterRoleBinding(spec) {
|
|
212
|
-
return this.coreResources.addClusterRoleBinding(spec);
|
|
213
|
-
}
|
|
214
|
-
/**
|
|
215
|
-
* Creates a Job resource for batch workloads
|
|
216
|
-
* @param spec - Job specification
|
|
217
|
-
* @returns Created Job ApiObject
|
|
218
|
-
*
|
|
219
|
-
* @example
|
|
220
|
-
* ```typescript
|
|
221
|
-
* rutter.addJob({
|
|
222
|
-
* name: 'data-processor',
|
|
223
|
-
* image: 'busybox:1.35',
|
|
224
|
-
* command: ['sh', '-c', 'echo "Processing..." && sleep 30'],
|
|
225
|
-
* completions: 1
|
|
226
|
-
* });
|
|
227
|
-
* ```
|
|
228
|
-
*
|
|
229
|
-
* @since 2.4.0
|
|
230
|
-
*/
|
|
231
|
-
addJob(spec) {
|
|
232
|
-
return this.coreResources.addJob(spec);
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Creates a Service resource
|
|
236
|
-
* @param spec - Service specification
|
|
237
|
-
* @returns Created Service ApiObject
|
|
238
|
-
*
|
|
239
|
-
* @example
|
|
240
|
-
* ```typescript
|
|
241
|
-
* rutter.addService({
|
|
242
|
-
* name: 'web-service',
|
|
243
|
-
* port: 80,
|
|
244
|
-
* targetPort: 8080,
|
|
245
|
-
* type: 'ClusterIP'
|
|
246
|
-
* });
|
|
247
|
-
* ```
|
|
248
|
-
*
|
|
249
|
-
* @since 1.0.0
|
|
250
|
-
*/
|
|
251
|
-
addService(spec) {
|
|
252
|
-
return this.coreResources.addService(spec);
|
|
253
|
-
}
|
|
254
|
-
/**
|
|
255
|
-
* Creates a ConfigMap resource
|
|
256
|
-
* @param spec - ConfigMap specification
|
|
257
|
-
* @returns Created ConfigMap ApiObject
|
|
258
|
-
*
|
|
259
|
-
* @example
|
|
260
|
-
* ```typescript
|
|
261
|
-
* rutter.addConfigMap({
|
|
262
|
-
* name: 'app-config',
|
|
263
|
-
* data: {
|
|
264
|
-
* 'config.yaml': 'key: value',
|
|
265
|
-
* 'app.properties': 'debug=true'
|
|
266
|
-
* }
|
|
267
|
-
* });
|
|
268
|
-
* ```
|
|
269
|
-
*
|
|
270
|
-
* @since 1.0.0
|
|
271
|
-
*/
|
|
272
|
-
addConfigMap(spec) {
|
|
273
|
-
return this.coreResources.addConfigMap(spec);
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* Creates a Secret resource
|
|
277
|
-
* @param spec - Secret specification
|
|
278
|
-
* @returns Created Secret ApiObject
|
|
279
|
-
*
|
|
280
|
-
* @example
|
|
281
|
-
* ```typescript
|
|
282
|
-
* rutter.addSecret({
|
|
283
|
-
* name: 'app-secrets',
|
|
284
|
-
* type: 'Opaque',
|
|
285
|
-
* data: {
|
|
286
|
-
* username: 'YWRtaW4=',
|
|
287
|
-
* password: 'MWYyZDFlMmU2N2Rm'
|
|
288
|
-
* }
|
|
289
|
-
* });
|
|
290
|
-
* ```
|
|
291
|
-
*
|
|
292
|
-
* @since 1.0.0
|
|
293
|
-
*/
|
|
294
|
-
addSecret(spec) {
|
|
295
|
-
return this.coreResources.addSecret(spec);
|
|
296
|
-
}
|
|
297
|
-
/**
|
|
298
|
-
* Creates a ServiceAccount resource
|
|
299
|
-
* @param spec - ServiceAccount specification
|
|
300
|
-
* @returns Created ServiceAccount ApiObject
|
|
301
|
-
*
|
|
302
|
-
* @example
|
|
303
|
-
* ```typescript
|
|
304
|
-
* rutter.addServiceAccount({
|
|
305
|
-
* name: 'app-service-account',
|
|
306
|
-
* automountServiceAccountToken: false
|
|
307
|
-
* });
|
|
308
|
-
* ```
|
|
309
|
-
*
|
|
310
|
-
* @since 1.0.0
|
|
311
|
-
*/
|
|
312
|
-
addServiceAccount(spec) {
|
|
313
|
-
return this.coreResources.addServiceAccount(spec);
|
|
314
|
-
}
|
|
315
|
-
// Storage Resources
|
|
316
|
-
/**
|
|
317
|
-
* Creates a PersistentVolume resource
|
|
318
|
-
* @param spec - PersistentVolume specification
|
|
319
|
-
* @returns Created PersistentVolume ApiObject
|
|
320
|
-
*
|
|
321
|
-
* @example
|
|
322
|
-
* ```typescript
|
|
323
|
-
* rutter.addPersistentVolume({
|
|
324
|
-
* name: 'data-pv',
|
|
325
|
-
* capacity: '10Gi',
|
|
326
|
-
* accessModes: ['ReadWriteOnce'],
|
|
327
|
-
* storageClassName: 'fast-ssd'
|
|
328
|
-
* });
|
|
329
|
-
* ```
|
|
330
|
-
*
|
|
331
|
-
* @since 1.0.0
|
|
332
|
-
*/
|
|
333
|
-
addPersistentVolume(spec) {
|
|
334
|
-
return this.storageResources.addPersistentVolume(spec);
|
|
335
|
-
}
|
|
336
|
-
/**
|
|
337
|
-
* Creates a PersistentVolumeClaim resource
|
|
338
|
-
* @param spec - PersistentVolumeClaim specification
|
|
339
|
-
* @returns Created PersistentVolumeClaim ApiObject
|
|
340
|
-
*
|
|
341
|
-
* @example
|
|
342
|
-
* ```typescript
|
|
343
|
-
* rutter.addPersistentVolumeClaim({
|
|
344
|
-
* name: 'data-pvc',
|
|
345
|
-
* size: '10Gi',
|
|
346
|
-
* accessModes: ['ReadWriteOnce'],
|
|
347
|
-
* storageClassName: 'fast-ssd'
|
|
348
|
-
* });
|
|
349
|
-
* ```
|
|
350
|
-
*
|
|
351
|
-
* @since 1.0.0
|
|
352
|
-
*/
|
|
353
|
-
addPersistentVolumeClaim(spec) {
|
|
354
|
-
return this.storageResources.addPersistentVolumeClaim(spec);
|
|
355
|
-
}
|
|
356
|
-
/**
|
|
357
|
-
* Creates a StorageClass resource
|
|
358
|
-
* @param spec - StorageClass specification
|
|
359
|
-
* @returns Created StorageClass ApiObject
|
|
360
|
-
*
|
|
361
|
-
* @example
|
|
362
|
-
* ```typescript
|
|
363
|
-
* rutter.addStorageClass({
|
|
364
|
-
* name: 'fast-ssd',
|
|
365
|
-
* provisioner: 'kubernetes.io/aws-ebs',
|
|
366
|
-
* parameters: {
|
|
367
|
-
* type: 'gp3',
|
|
368
|
-
* encrypted: 'true'
|
|
369
|
-
* }
|
|
370
|
-
* });
|
|
371
|
-
* ```
|
|
372
|
-
*
|
|
373
|
-
* @since 1.0.0
|
|
374
|
-
*/
|
|
375
|
-
addStorageClass(spec) {
|
|
376
|
-
return this.storageResources.addStorageClass(spec);
|
|
377
|
-
}
|
|
378
32
|
// AWS Resources
|
|
379
33
|
/**
|
|
380
34
|
* Creates an AWS EBS StorageClass
|
|
@@ -423,8 +77,8 @@ export class Rutter {
|
|
|
423
77
|
* @example
|
|
424
78
|
* ```typescript
|
|
425
79
|
* rutter.addAWSIRSAServiceAccount({
|
|
426
|
-
* name: '
|
|
427
|
-
* roleArn: 'arn:aws:iam::
|
|
80
|
+
* name: 'my-service-account',
|
|
81
|
+
* roleArn: 'arn:aws:iam::ACCOUNT_ID:role/MyRole'
|
|
428
82
|
* });
|
|
429
83
|
* ```
|
|
430
84
|
*
|
|
@@ -458,116 +112,6 @@ export class Rutter {
|
|
|
458
112
|
addAWSALBIngress(spec) {
|
|
459
113
|
return this.awsResources.addALBIngress(spec);
|
|
460
114
|
}
|
|
461
|
-
// Azure Cloud Resources
|
|
462
|
-
/**
|
|
463
|
-
* Creates an Azure Disk StorageClass
|
|
464
|
-
* @param spec - Azure Disk StorageClass specification
|
|
465
|
-
* @returns Created StorageClass ApiObject
|
|
466
|
-
*
|
|
467
|
-
* @since 2.4.0
|
|
468
|
-
*/
|
|
469
|
-
addAzureDiskStorageClass(spec) {
|
|
470
|
-
return this.azureResources.addAzureDiskStorageClass(spec);
|
|
471
|
-
}
|
|
472
|
-
/**
|
|
473
|
-
* Creates an Azure File StorageClass
|
|
474
|
-
* @param spec - Azure File StorageClass specification
|
|
475
|
-
* @returns Created StorageClass ApiObject
|
|
476
|
-
*
|
|
477
|
-
* @since 2.4.0
|
|
478
|
-
*/
|
|
479
|
-
addAzureFileStorageClass(spec) {
|
|
480
|
-
return this.azureResources.addAzureFileStorageClass(spec);
|
|
481
|
-
}
|
|
482
|
-
/**
|
|
483
|
-
* Creates an Azure Application Gateway Ingress
|
|
484
|
-
* @param spec - AGIC Ingress specification
|
|
485
|
-
* @returns Created Ingress ApiObject
|
|
486
|
-
*
|
|
487
|
-
* @since 2.4.0
|
|
488
|
-
*/
|
|
489
|
-
addAzureApplicationGatewayIngress(spec) {
|
|
490
|
-
return this.azureResources.addApplicationGatewayIngress(spec);
|
|
491
|
-
}
|
|
492
|
-
/**
|
|
493
|
-
* Creates an Azure Key Vault SecretProviderClass
|
|
494
|
-
* @param spec - Azure Key Vault SecretProviderClass specification
|
|
495
|
-
* @returns Created SecretProviderClass ApiObject
|
|
496
|
-
*
|
|
497
|
-
* @since 2.4.0
|
|
498
|
-
*/
|
|
499
|
-
addAzureKeyVaultSecretProviderClass(spec) {
|
|
500
|
-
return this.azureResources.addAzureKeyVaultSecretProviderClass(spec);
|
|
501
|
-
}
|
|
502
|
-
/**
|
|
503
|
-
* Creates an Azure Container Registry ServiceAccount
|
|
504
|
-
* @param spec - Azure ACR ServiceAccount specification
|
|
505
|
-
* @returns Created ServiceAccount ApiObject
|
|
506
|
-
*
|
|
507
|
-
* @since 2.4.0
|
|
508
|
-
*/
|
|
509
|
-
addAzureACRServiceAccount(spec) {
|
|
510
|
-
return this.azureResources.addAzureACRServiceAccount(spec);
|
|
511
|
-
}
|
|
512
|
-
// GCP Cloud Resources
|
|
513
|
-
/**
|
|
514
|
-
* Creates a GCP Persistent Disk StorageClass
|
|
515
|
-
* @param spec - GCP PD StorageClass specification
|
|
516
|
-
* @returns Created StorageClass ApiObject
|
|
517
|
-
*
|
|
518
|
-
* @since 2.4.0
|
|
519
|
-
*/
|
|
520
|
-
addGCPPersistentDiskStorageClass(spec) {
|
|
521
|
-
return this.gcpResources.addPersistentDiskStorageClass(spec);
|
|
522
|
-
}
|
|
523
|
-
/**
|
|
524
|
-
* Creates a GCP Filestore StorageClass
|
|
525
|
-
* @param spec - GCP Filestore StorageClass specification
|
|
526
|
-
* @returns Created StorageClass ApiObject
|
|
527
|
-
*
|
|
528
|
-
* @since 2.4.0
|
|
529
|
-
*/
|
|
530
|
-
addGCPFilestoreStorageClass(spec) {
|
|
531
|
-
return this.gcpResources.addFilestoreStorageClass(spec);
|
|
532
|
-
}
|
|
533
|
-
/**
|
|
534
|
-
* Creates a GCE Ingress with Google Cloud Load Balancer
|
|
535
|
-
* @param spec - GCE Ingress specification
|
|
536
|
-
* @returns Created Ingress ApiObject
|
|
537
|
-
*
|
|
538
|
-
* @since 2.4.0
|
|
539
|
-
*/
|
|
540
|
-
addGCPGCEIngress(spec) {
|
|
541
|
-
return this.gcpResources.addGCEIngress(spec);
|
|
542
|
-
}
|
|
543
|
-
/**
|
|
544
|
-
* Creates a ServiceAccount with Workload Identity annotations
|
|
545
|
-
* @param spec - Workload Identity ServiceAccount specification
|
|
546
|
-
* @returns Created ServiceAccount ApiObject
|
|
547
|
-
*
|
|
548
|
-
* @since 2.4.0
|
|
549
|
-
*/
|
|
550
|
-
addGCPWorkloadIdentityServiceAccount(spec) {
|
|
551
|
-
return this.gcpResources.addWorkloadIdentityServiceAccount(spec);
|
|
552
|
-
}
|
|
553
|
-
/**
|
|
554
|
-
* Creates a ServiceAccount with GCP Artifact Registry access
|
|
555
|
-
* @param spec - Artifact Registry ServiceAccount specification
|
|
556
|
-
* @returns Created ServiceAccount ApiObject
|
|
557
|
-
*
|
|
558
|
-
* @example
|
|
559
|
-
* ```typescript
|
|
560
|
-
* rutter.addGCPArtifactRegistryServiceAccount({
|
|
561
|
-
* name: 'artifact-registry-sa',
|
|
562
|
-
* googleServiceAccount: 'my-gsa@project.iam.gserviceaccount.com'
|
|
563
|
-
* });
|
|
564
|
-
* ```
|
|
565
|
-
*
|
|
566
|
-
* @since 2.7.0
|
|
567
|
-
*/
|
|
568
|
-
addGCPArtifactRegistryServiceAccount(spec) {
|
|
569
|
-
return this.gcpResources.addArtifactRegistryServiceAccount(spec);
|
|
570
|
-
}
|
|
571
115
|
// AWS Karpenter Resources
|
|
572
116
|
/**
|
|
573
117
|
* Creates a Karpenter NodePool resource
|
|
@@ -696,235 +240,6 @@ export class Rutter {
|
|
|
696
240
|
addKarpenterNodePoolWithScheduling(spec) {
|
|
697
241
|
return this.karpenterResources.addKarpenterNodePoolWithScheduling(spec);
|
|
698
242
|
}
|
|
699
|
-
// Network Resources
|
|
700
|
-
/**
|
|
701
|
-
* Creates a NetworkPolicy resource
|
|
702
|
-
* @param spec - NetworkPolicy specification
|
|
703
|
-
* @returns Created NetworkPolicy ApiObject
|
|
704
|
-
*
|
|
705
|
-
* @example
|
|
706
|
-
* ```typescript
|
|
707
|
-
* rutter.addNetworkPolicy({
|
|
708
|
-
* name: 'deny-all',
|
|
709
|
-
* podSelector: {},
|
|
710
|
-
* policyTypes: ['Ingress', 'Egress']
|
|
711
|
-
* });
|
|
712
|
-
* ```
|
|
713
|
-
*
|
|
714
|
-
* @since 2.7.0
|
|
715
|
-
*/
|
|
716
|
-
addNetworkPolicy(spec) {
|
|
717
|
-
return this.networkResources.addNetworkPolicy(spec);
|
|
718
|
-
}
|
|
719
|
-
/**
|
|
720
|
-
* Creates a deny-all NetworkPolicy that blocks all traffic
|
|
721
|
-
* @param name - Policy name
|
|
722
|
-
* @param podSelector - Pod selector to apply policy to
|
|
723
|
-
* @param labels - Optional labels
|
|
724
|
-
* @param annotations - Optional annotations
|
|
725
|
-
* @returns Created NetworkPolicy ApiObject
|
|
726
|
-
*
|
|
727
|
-
* @example
|
|
728
|
-
* ```typescript
|
|
729
|
-
* rutter.addDenyAllNetworkPolicy('deny-all', { matchLabels: { app: 'web' } });
|
|
730
|
-
* ```
|
|
731
|
-
*
|
|
732
|
-
* @since 2.7.0
|
|
733
|
-
*/
|
|
734
|
-
addDenyAllNetworkPolicy(name, podSelector = {}, labels, annotations) {
|
|
735
|
-
return this.networkResources.addDenyAllNetworkPolicy(name, podSelector, labels, annotations);
|
|
736
|
-
}
|
|
737
|
-
/**
|
|
738
|
-
* Creates a NetworkPolicy that allows traffic from specific pods
|
|
739
|
-
* @param name - Policy name
|
|
740
|
-
* @param podSelector - Pod selector to apply policy to
|
|
741
|
-
* @param fromPodSelector - Pod selector for allowed source pods
|
|
742
|
-
* @param ports - Optional ports to allow
|
|
743
|
-
* @param labels - Optional labels
|
|
744
|
-
* @param annotations - Optional annotations
|
|
745
|
-
* @returns Created NetworkPolicy ApiObject
|
|
746
|
-
*
|
|
747
|
-
* @example
|
|
748
|
-
* ```typescript
|
|
749
|
-
* rutter.addAllowFromPodsNetworkPolicy(
|
|
750
|
-
* 'allow-from-frontend',
|
|
751
|
-
* { matchLabels: { app: 'backend' } },
|
|
752
|
-
* { matchLabels: { app: 'frontend' } },
|
|
753
|
-
* [{ port: 8080, protocol: 'TCP' }]
|
|
754
|
-
* );
|
|
755
|
-
* ```
|
|
756
|
-
*
|
|
757
|
-
* @since 2.7.0
|
|
758
|
-
*/
|
|
759
|
-
addAllowFromPodsNetworkPolicy(name, podSelector, fromPodSelector, ports, labels, annotations) {
|
|
760
|
-
return this.networkResources.addAllowFromPodsNetworkPolicy(name, podSelector, fromPodSelector, ports, labels, annotations);
|
|
761
|
-
}
|
|
762
|
-
/**
|
|
763
|
-
* Creates a NetworkPolicy that allows traffic from specific namespaces
|
|
764
|
-
* @param name - Policy name
|
|
765
|
-
* @param podSelector - Pod selector to apply policy to
|
|
766
|
-
* @param fromNamespaceSelector - Namespace selector for allowed source namespaces
|
|
767
|
-
* @param ports - Optional ports to allow
|
|
768
|
-
* @param labels - Optional labels
|
|
769
|
-
* @param annotations - Optional annotations
|
|
770
|
-
* @returns Created NetworkPolicy ApiObject
|
|
771
|
-
*
|
|
772
|
-
* @example
|
|
773
|
-
* ```typescript
|
|
774
|
-
* rutter.addAllowFromNamespaceNetworkPolicy(
|
|
775
|
-
* 'allow-from-monitoring',
|
|
776
|
-
* { matchLabels: { app: 'web' } },
|
|
777
|
-
* { matchLabels: { name: 'monitoring' } },
|
|
778
|
-
* [{ port: 9090, protocol: 'TCP' }]
|
|
779
|
-
* );
|
|
780
|
-
* ```
|
|
781
|
-
*
|
|
782
|
-
* @since 2.7.0
|
|
783
|
-
*/
|
|
784
|
-
addAllowFromNamespaceNetworkPolicy(name, podSelector, fromNamespaceSelector, ports, labels, annotations) {
|
|
785
|
-
return this.networkResources.addAllowFromNamespaceNetworkPolicy(name, podSelector, fromNamespaceSelector, ports, labels, annotations);
|
|
786
|
-
}
|
|
787
|
-
addIngress(specOrName, host, serviceName, servicePort, options) {
|
|
788
|
-
if (typeof specOrName === 'string') {
|
|
789
|
-
return this.createSimpleIngress(specOrName, host, serviceName, servicePort, options);
|
|
790
|
-
}
|
|
791
|
-
// Original spec-based overload
|
|
792
|
-
return this.networkResources.addIngress(specOrName);
|
|
793
|
-
}
|
|
794
|
-
/**
|
|
795
|
-
* Creates a simple Ingress with enhanced options
|
|
796
|
-
* @private
|
|
797
|
-
*/
|
|
798
|
-
createSimpleIngress(name, host, serviceName, servicePort, options) {
|
|
799
|
-
const tlsSecretName = typeof options?.tls === 'string' ? options.tls : `${name}-tls`;
|
|
800
|
-
const annotations = this.buildIngressAnnotations(options);
|
|
801
|
-
const spec = {
|
|
802
|
-
name,
|
|
803
|
-
rules: [
|
|
804
|
-
{
|
|
805
|
-
host,
|
|
806
|
-
http: {
|
|
807
|
-
paths: [
|
|
808
|
-
{
|
|
809
|
-
path: options?.path || '/',
|
|
810
|
-
pathType: options?.pathType || 'Prefix',
|
|
811
|
-
backend: {
|
|
812
|
-
service: {
|
|
813
|
-
name: serviceName,
|
|
814
|
-
port: { number: servicePort },
|
|
815
|
-
},
|
|
816
|
-
},
|
|
817
|
-
},
|
|
818
|
-
],
|
|
819
|
-
},
|
|
820
|
-
},
|
|
821
|
-
],
|
|
822
|
-
...(options?.className && { ingressClassName: options.className }),
|
|
823
|
-
...(Object.keys(annotations).length > 0 && { annotations }),
|
|
824
|
-
...(options?.tls && {
|
|
825
|
-
tls: [
|
|
826
|
-
{
|
|
827
|
-
hosts: [host],
|
|
828
|
-
secretName: tlsSecretName,
|
|
829
|
-
},
|
|
830
|
-
],
|
|
831
|
-
}),
|
|
832
|
-
};
|
|
833
|
-
return this.networkResources.addIngress(spec);
|
|
834
|
-
}
|
|
835
|
-
/**
|
|
836
|
-
* Builds annotations for Ingress based on options
|
|
837
|
-
* @private
|
|
838
|
-
*/
|
|
839
|
-
buildIngressAnnotations(options) {
|
|
840
|
-
const annotations = { ...options?.annotations };
|
|
841
|
-
this.addSSLRedirectAnnotation(annotations, options);
|
|
842
|
-
this.addCertManagerAnnotation(annotations, options);
|
|
843
|
-
this.addNginxAnnotations(annotations, options);
|
|
844
|
-
return annotations;
|
|
845
|
-
}
|
|
846
|
-
/**
|
|
847
|
-
* Adds SSL redirect annotation based on class and options
|
|
848
|
-
* @private
|
|
849
|
-
*/
|
|
850
|
-
addSSLRedirectAnnotation(annotations, options) {
|
|
851
|
-
if (!options?.tls || options.sslRedirect === false)
|
|
852
|
-
return;
|
|
853
|
-
if (options.className === 'nginx' || !options.className) {
|
|
854
|
-
annotations['nginx.ingress.kubernetes.io/ssl-redirect'] = 'true';
|
|
855
|
-
}
|
|
856
|
-
else if (options.className === 'alb') {
|
|
857
|
-
annotations['alb.ingress.kubernetes.io/ssl-redirect'] = '443';
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
/**
|
|
861
|
-
* Adds cert-manager annotation if specified
|
|
862
|
-
* @private
|
|
863
|
-
*/
|
|
864
|
-
addCertManagerAnnotation(annotations, options) {
|
|
865
|
-
if (options?.certManager) {
|
|
866
|
-
annotations['cert-manager.io/cluster-issuer'] = options.certManager;
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
/**
|
|
870
|
-
* Adds NGINX-specific annotations
|
|
871
|
-
* @private
|
|
872
|
-
*/
|
|
873
|
-
addNginxAnnotations(annotations, options) {
|
|
874
|
-
if (options?.className !== 'nginx' && options?.className)
|
|
875
|
-
return;
|
|
876
|
-
if (options?.cors) {
|
|
877
|
-
annotations['nginx.ingress.kubernetes.io/enable-cors'] = 'true';
|
|
878
|
-
}
|
|
879
|
-
if (options?.bodySize) {
|
|
880
|
-
annotations['nginx.ingress.kubernetes.io/proxy-body-size'] = options.bodySize;
|
|
881
|
-
}
|
|
882
|
-
if (options?.timeout) {
|
|
883
|
-
annotations['nginx.ingress.kubernetes.io/proxy-read-timeout'] = options.timeout.toString();
|
|
884
|
-
}
|
|
885
|
-
if (options?.backendProtocol && options.backendProtocol !== 'HTTP') {
|
|
886
|
-
annotations['nginx.ingress.kubernetes.io/backend-protocol'] = options.backendProtocol;
|
|
887
|
-
}
|
|
888
|
-
if (options?.rewriteTarget) {
|
|
889
|
-
annotations['nginx.ingress.kubernetes.io/rewrite-target'] = options.rewriteTarget;
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
/**
|
|
893
|
-
* Creates a secure Ingress resource with TLS validation and environment-aware security defaults
|
|
894
|
-
* @param spec - Enhanced Ingress specification with security options
|
|
895
|
-
* @returns Created Ingress ApiObject
|
|
896
|
-
*
|
|
897
|
-
* @example
|
|
898
|
-
* ```typescript
|
|
899
|
-
* // Production Ingress with mandatory TLS
|
|
900
|
-
* rutter.addSecureIngress({
|
|
901
|
-
* name: 'secure-web-ingress',
|
|
902
|
-
* environment: 'production',
|
|
903
|
-
* tls: [{
|
|
904
|
-
* hosts: ['secure.example.com'],
|
|
905
|
-
* secretName: 'secure-example-tls'
|
|
906
|
-
* }],
|
|
907
|
-
* forceSSLRedirect: true,
|
|
908
|
-
* rules: [{
|
|
909
|
-
* host: 'secure.example.com',
|
|
910
|
-
* http: {
|
|
911
|
-
* paths: [{
|
|
912
|
-
* path: '/',
|
|
913
|
-
* pathType: 'Prefix',
|
|
914
|
-
* backend: {
|
|
915
|
-
* service: { name: 'web-service', port: { number: 80 } }
|
|
916
|
-
* }
|
|
917
|
-
* }]
|
|
918
|
-
* }
|
|
919
|
-
* }]
|
|
920
|
-
* });
|
|
921
|
-
* ```
|
|
922
|
-
*
|
|
923
|
-
* @since 2.8.0
|
|
924
|
-
*/
|
|
925
|
-
addSecureIngress(spec) {
|
|
926
|
-
return this.networkResources.addSecureIngress(spec);
|
|
927
|
-
}
|
|
928
243
|
// AWS ECR ServiceAccount
|
|
929
244
|
/**
|
|
930
245
|
* Creates a ServiceAccount with ECR access annotations
|
|
@@ -935,7 +250,7 @@ export class Rutter {
|
|
|
935
250
|
* ```typescript
|
|
936
251
|
* rutter.addAWSECRServiceAccount({
|
|
937
252
|
* name: 'ecr-service-account',
|
|
938
|
-
* roleArn: 'arn:aws:iam::
|
|
253
|
+
* roleArn: 'arn:aws:iam::ACCOUNT_ID:role/ECRAccessRole'
|
|
939
254
|
* });
|
|
940
255
|
* ```
|
|
941
256
|
*
|
|
@@ -944,103 +259,21 @@ export class Rutter {
|
|
|
944
259
|
addAWSECRServiceAccount(spec) {
|
|
945
260
|
return this.awsResources.addECRServiceAccount(spec);
|
|
946
261
|
}
|
|
947
|
-
//
|
|
948
|
-
/**
|
|
949
|
-
* Creates a Horizontal Pod Autoscaler (HPA) resource
|
|
950
|
-
* @param spec - HPA specification
|
|
951
|
-
* @returns Created HPA ApiObject
|
|
952
|
-
*
|
|
953
|
-
* @example
|
|
954
|
-
* ```typescript
|
|
955
|
-
* rutter.addHorizontalPodAutoscaler({
|
|
956
|
-
* name: 'web-hpa',
|
|
957
|
-
* scaleTargetRef: {
|
|
958
|
-
* apiVersion: 'apps/v1',
|
|
959
|
-
* kind: 'Deployment',
|
|
960
|
-
* name: 'web-app'
|
|
961
|
-
* },
|
|
962
|
-
* minReplicas: 2,
|
|
963
|
-
* maxReplicas: 10,
|
|
964
|
-
* metrics: [{
|
|
965
|
-
* type: 'Resource',
|
|
966
|
-
* resource: {
|
|
967
|
-
* name: 'cpu',
|
|
968
|
-
* target: { type: 'Utilization', averageUtilization: 70 }
|
|
969
|
-
* }
|
|
970
|
-
* }]
|
|
971
|
-
* });
|
|
972
|
-
* ```
|
|
973
|
-
*
|
|
974
|
-
* @since 2.7.0
|
|
975
|
-
*/
|
|
976
|
-
addHorizontalPodAutoscaler(spec) {
|
|
977
|
-
return this.autoscalingResources.addHorizontalPodAutoscaler(spec);
|
|
978
|
-
}
|
|
979
|
-
/**
|
|
980
|
-
* Creates a Vertical Pod Autoscaler (VPA) resource
|
|
981
|
-
* @param spec - VPA specification
|
|
982
|
-
* @returns Created VPA ApiObject
|
|
983
|
-
*
|
|
984
|
-
* @example
|
|
985
|
-
* ```typescript
|
|
986
|
-
* rutter.addVerticalPodAutoscaler({
|
|
987
|
-
* name: 'web-vpa',
|
|
988
|
-
* targetRef: {
|
|
989
|
-
* apiVersion: 'apps/v1',
|
|
990
|
-
* kind: 'Deployment',
|
|
991
|
-
* name: 'web-app'
|
|
992
|
-
* },
|
|
993
|
-
* updatePolicy: { updateMode: 'Auto' }
|
|
994
|
-
* });
|
|
995
|
-
* ```
|
|
996
|
-
*
|
|
997
|
-
* @since 2.7.0
|
|
998
|
-
*/
|
|
999
|
-
addVerticalPodAutoscaler(spec) {
|
|
1000
|
-
return this.autoscalingResources.addVerticalPodAutoscaler(spec);
|
|
1001
|
-
}
|
|
262
|
+
// Utility methods
|
|
1002
263
|
/**
|
|
1003
|
-
*
|
|
1004
|
-
* @param spec - CronJob specification
|
|
1005
|
-
* @returns Created CronJob ApiObject
|
|
264
|
+
* Adds a Kubernetes manifest to the chart using CDK8S
|
|
1006
265
|
*
|
|
1007
|
-
*
|
|
1008
|
-
*
|
|
1009
|
-
*
|
|
1010
|
-
* name: 'backup-job',
|
|
1011
|
-
* schedule: '0 2 * * *',
|
|
1012
|
-
* jobTemplate: {
|
|
1013
|
-
* spec: {
|
|
1014
|
-
* template: {
|
|
1015
|
-
* spec: {
|
|
1016
|
-
* containers: [{
|
|
1017
|
-
* name: 'backup',
|
|
1018
|
-
* image: 'backup:latest',
|
|
1019
|
-
* command: ['backup.sh']
|
|
1020
|
-
* }],
|
|
1021
|
-
* restartPolicy: 'OnFailure'
|
|
1022
|
-
* }
|
|
1023
|
-
* }
|
|
1024
|
-
* }
|
|
1025
|
-
* }
|
|
1026
|
-
* });
|
|
1027
|
-
* ```
|
|
266
|
+
* This method allows you to add any Kubernetes manifest (CRDs, custom resources, etc.)
|
|
267
|
+
* either as YAML strings or as objects. The manifest will be processed using CDK8S
|
|
268
|
+
* for better type safety and validation.
|
|
1028
269
|
*
|
|
1029
|
-
* @
|
|
1030
|
-
|
|
1031
|
-
addCronJob(spec) {
|
|
1032
|
-
return this.autoscalingResources.addCronJob(spec);
|
|
1033
|
-
}
|
|
1034
|
-
// Utility methods
|
|
1035
|
-
/**
|
|
1036
|
-
* Adds a custom resource definition (CRD) YAML or object
|
|
1037
|
-
* @param yamlOrObject - CRD YAML content string or object
|
|
1038
|
-
* @param id - Unique identifier for the CRD
|
|
270
|
+
* @param yamlOrObject - Kubernetes manifest as YAML string or object
|
|
271
|
+
* @param id - Unique identifier for the manifest (required for multiple manifests)
|
|
1039
272
|
*
|
|
1040
273
|
* @example
|
|
1041
274
|
* ```typescript
|
|
1042
|
-
* // Using YAML string
|
|
1043
|
-
* rutter.
|
|
275
|
+
* // Using YAML string for CRD
|
|
276
|
+
* rutter.addManifest(`
|
|
1044
277
|
* apiVersion: apiextensions.k8s.io/v1
|
|
1045
278
|
* kind: CustomResourceDefinition
|
|
1046
279
|
* metadata:
|
|
@@ -1048,82 +281,144 @@ export class Rutter {
|
|
|
1048
281
|
* spec:
|
|
1049
282
|
* group: example.com
|
|
1050
283
|
* versions: []
|
|
1051
|
-
*
|
|
284
|
+
* `, 'my-crd');
|
|
1052
285
|
*
|
|
1053
|
-
* // Using object
|
|
1054
|
-
* rutter.
|
|
1055
|
-
* apiVersion: '
|
|
1056
|
-
* kind: '
|
|
1057
|
-
* metadata: { name: '
|
|
1058
|
-
*
|
|
1059
|
-
* });
|
|
286
|
+
* // Using object for any Kubernetes resource
|
|
287
|
+
* rutter.addManifest({
|
|
288
|
+
* apiVersion: 'v1',
|
|
289
|
+
* kind: 'ConfigMap',
|
|
290
|
+
* metadata: { name: 'my-config' },
|
|
291
|
+
* data: { key: 'value' }
|
|
292
|
+
* }, 'my-configmap');
|
|
1060
293
|
* ```
|
|
1061
294
|
*
|
|
1062
|
-
* @since
|
|
295
|
+
* @since 3.0.0
|
|
296
|
+
* @note Consider using cdk8s-plus constructs for better type safety when available
|
|
1063
297
|
*/
|
|
1064
|
-
|
|
1065
|
-
let
|
|
1066
|
-
let crdObject;
|
|
298
|
+
addManifest(yamlOrObject, id) {
|
|
299
|
+
let manifestObject;
|
|
1067
300
|
if (typeof yamlOrObject === 'string') {
|
|
1068
|
-
//
|
|
301
|
+
// Parse YAML string to object
|
|
1069
302
|
try {
|
|
1070
|
-
|
|
1071
|
-
yaml = yamlOrObject.trim();
|
|
303
|
+
manifestObject = YAML.parse(yamlOrObject);
|
|
1072
304
|
}
|
|
1073
305
|
catch (error) {
|
|
1074
|
-
throw new Error(`Invalid YAML provided to
|
|
306
|
+
throw new Error(`Invalid YAML provided to addManifest(): ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
1075
307
|
}
|
|
1076
308
|
}
|
|
1077
309
|
else if (typeof yamlOrObject === 'object' && yamlOrObject !== null) {
|
|
1078
|
-
// Use object directly
|
|
1079
|
-
|
|
1080
|
-
try {
|
|
1081
|
-
yaml = YAML.stringify(yamlOrObject).trim();
|
|
1082
|
-
}
|
|
1083
|
-
catch (error) {
|
|
1084
|
-
throw new Error(`Failed to convert object to YAML in addCrd(): ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
1085
|
-
}
|
|
310
|
+
// Use object directly
|
|
311
|
+
manifestObject = yamlOrObject;
|
|
1086
312
|
}
|
|
1087
313
|
else {
|
|
1088
|
-
throw new Error('
|
|
314
|
+
throw new Error('addManifest() requires either a YAML string or an object');
|
|
1089
315
|
}
|
|
1090
|
-
//
|
|
1091
|
-
|
|
1092
|
-
|
|
316
|
+
// Validate basic Kubernetes manifest structure
|
|
317
|
+
this.validateManifestStructure(manifestObject);
|
|
318
|
+
// Create CDK8S ApiObject from the manifest
|
|
319
|
+
return new ApiObject(this.chart, id, {
|
|
320
|
+
apiVersion: manifestObject['apiVersion'],
|
|
321
|
+
kind: manifestObject['kind'],
|
|
322
|
+
metadata: manifestObject['metadata'],
|
|
323
|
+
spec: manifestObject['spec'],
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Adds a Kubernetes manifest wrapped in a Helm conditional
|
|
328
|
+
*
|
|
329
|
+
* This method creates a manifest that will only be rendered if the specified
|
|
330
|
+
* condition evaluates to true. The condition is checked against .Values in Helm.
|
|
331
|
+
*
|
|
332
|
+
* @param manifestObject - JavaScript object representing the Kubernetes manifest
|
|
333
|
+
* @param condition - Path to the condition value in .Values (e.g., 'createNamespace')
|
|
334
|
+
* @param id - Unique identifier for this manifest within the chart
|
|
335
|
+
* @returns The created ApiObject instance
|
|
336
|
+
* @throws {Error} If the manifest structure is incorrect or condition path is invalid
|
|
337
|
+
*
|
|
338
|
+
* @example
|
|
339
|
+
* ```typescript
|
|
340
|
+
* // Add a namespace that's only created if .Values.createNamespace is true
|
|
341
|
+
* rutter.addConditionalManifest(
|
|
342
|
+
* {
|
|
343
|
+
* apiVersion: 'v1',
|
|
344
|
+
* kind: 'Namespace',
|
|
345
|
+
* metadata: {
|
|
346
|
+
* name: valuesRef('namespace'),
|
|
347
|
+
* labels: {
|
|
348
|
+
* environment: conditionalRef('environment', 'environment')
|
|
349
|
+
* }
|
|
350
|
+
* }
|
|
351
|
+
* },
|
|
352
|
+
* 'createNamespace',
|
|
353
|
+
* 'namespace'
|
|
354
|
+
* );
|
|
355
|
+
* ```
|
|
356
|
+
*
|
|
357
|
+
* @since 2.7.4
|
|
358
|
+
*/
|
|
359
|
+
addConditionalManifest(manifestObject, condition, id) {
|
|
360
|
+
// Validate condition path
|
|
361
|
+
if (!condition || typeof condition !== 'string') {
|
|
362
|
+
throw new Error('Condition must be a non-empty string');
|
|
1093
363
|
}
|
|
1094
|
-
// Validate
|
|
1095
|
-
this.
|
|
1096
|
-
|
|
364
|
+
// Validate basic Kubernetes manifest structure
|
|
365
|
+
this.validateManifestStructure(manifestObject);
|
|
366
|
+
// Store the manifest as a conditional asset that will be processed during write
|
|
367
|
+
const conditionalAsset = {
|
|
368
|
+
id,
|
|
369
|
+
yaml: `{{- if .Values.${condition} }}\n${YAML.stringify(manifestObject)}{{- end }}`,
|
|
370
|
+
target: 'templates',
|
|
371
|
+
};
|
|
372
|
+
this.assets.push(conditionalAsset);
|
|
373
|
+
// Create a placeholder CDK8S ApiObject for consistency
|
|
374
|
+
return new ApiObject(this.chart, id, {
|
|
375
|
+
apiVersion: manifestObject['apiVersion'],
|
|
376
|
+
kind: manifestObject['kind'],
|
|
377
|
+
metadata: {
|
|
378
|
+
...(manifestObject['metadata'] || {}),
|
|
379
|
+
annotations: {
|
|
380
|
+
...(manifestObject['metadata']?.['annotations'] || {}),
|
|
381
|
+
'timonel.sh/conditional': condition,
|
|
382
|
+
},
|
|
383
|
+
},
|
|
384
|
+
spec: manifestObject['spec'],
|
|
385
|
+
});
|
|
1097
386
|
}
|
|
1098
387
|
/**
|
|
1099
|
-
* Validates
|
|
1100
|
-
* @param
|
|
388
|
+
* Validates the structure of a Kubernetes manifest object
|
|
389
|
+
* @param manifest - The manifest object to validate
|
|
1101
390
|
* @private
|
|
1102
|
-
* @since
|
|
391
|
+
* @since 3.0.0
|
|
1103
392
|
*/
|
|
1104
|
-
|
|
1105
|
-
if (
|
|
1106
|
-
throw new Error('
|
|
393
|
+
validateManifestStructure(manifest) {
|
|
394
|
+
if (!manifest['apiVersion'] || typeof manifest['apiVersion'] !== 'string') {
|
|
395
|
+
throw new Error('Kubernetes manifest must have a valid apiVersion');
|
|
1107
396
|
}
|
|
1108
|
-
if (
|
|
1109
|
-
throw new Error('
|
|
397
|
+
if (!manifest['kind'] || typeof manifest['kind'] !== 'string') {
|
|
398
|
+
throw new Error('Kubernetes manifest must have a valid kind');
|
|
1110
399
|
}
|
|
1111
|
-
if (!
|
|
1112
|
-
|
|
400
|
+
if (!manifest['metadata'] ||
|
|
401
|
+
typeof manifest['metadata'] !== 'object' ||
|
|
402
|
+
manifest['metadata'] === null) {
|
|
403
|
+
throw new Error('Kubernetes manifest must have valid metadata');
|
|
1113
404
|
}
|
|
1114
|
-
const metadata =
|
|
405
|
+
const metadata = manifest['metadata'];
|
|
1115
406
|
if (!metadata['name'] || typeof metadata['name'] !== 'string') {
|
|
1116
|
-
throw new Error('
|
|
1117
|
-
}
|
|
1118
|
-
if (!crd['spec'] || typeof crd['spec'] !== 'object' || crd['spec'] === null) {
|
|
1119
|
-
throw new Error('CRD must have a spec object');
|
|
407
|
+
throw new Error('Kubernetes manifest metadata must have a valid name');
|
|
1120
408
|
}
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
409
|
+
// Additional validation for specific resource types
|
|
410
|
+
const kind = manifest['kind'];
|
|
411
|
+
if (kind === 'CustomResourceDefinition') {
|
|
412
|
+
if (!manifest['spec'] || typeof manifest['spec'] !== 'object' || manifest['spec'] === null) {
|
|
413
|
+
throw new Error('CustomResourceDefinition must have a valid spec');
|
|
414
|
+
}
|
|
415
|
+
const spec = manifest['spec'];
|
|
416
|
+
if (!spec['group'] || typeof spec['group'] !== 'string') {
|
|
417
|
+
throw new Error('CustomResourceDefinition spec must have a valid group');
|
|
418
|
+
}
|
|
419
|
+
if (!Array.isArray(spec['versions']) || spec['versions'].length === 0) {
|
|
420
|
+
throw new Error('CustomResourceDefinition must have at least one version in spec.versions');
|
|
421
|
+
}
|
|
1127
422
|
}
|
|
1128
423
|
}
|
|
1129
424
|
/**
|
|
@@ -1169,6 +464,13 @@ export class Rutter {
|
|
|
1169
464
|
* @since 2.4.0
|
|
1170
465
|
*/
|
|
1171
466
|
toSynthArray() {
|
|
467
|
+
// Get ApiObject IDs before synthesis
|
|
468
|
+
const apiObjectIds = [];
|
|
469
|
+
for (const child of this.chart.node.children) {
|
|
470
|
+
if (child instanceof ApiObject) {
|
|
471
|
+
apiObjectIds.push(child.node.id);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
1172
474
|
// Use cdk8s Testing.synth to obtain manifest objects
|
|
1173
475
|
const manifestObjs = Testing.synth(this.chart);
|
|
1174
476
|
// Enforce common labels best-practice on all rendered objects
|
|
@@ -1200,7 +502,7 @@ export class Rutter {
|
|
|
1200
502
|
if (this.props.singleManifestFile) {
|
|
1201
503
|
// Combine all resources into single manifest
|
|
1202
504
|
const combinedYaml = enriched
|
|
1203
|
-
.map((obj) => YAML.stringify(obj).trim())
|
|
505
|
+
.map((obj) => this.processHelmTemplates(YAML.stringify(obj).trim()))
|
|
1204
506
|
.filter(Boolean)
|
|
1205
507
|
.join('\n---\n');
|
|
1206
508
|
const manifestId = this.props.manifestPrefix ?? 'manifests';
|
|
@@ -1209,9 +511,12 @@ export class Rutter {
|
|
|
1209
511
|
else {
|
|
1210
512
|
// Create separate files for each resource (default behavior)
|
|
1211
513
|
enriched.forEach((obj, index) => {
|
|
1212
|
-
const yaml = YAML.stringify(obj).trim();
|
|
514
|
+
const yaml = this.processHelmTemplates(YAML.stringify(obj).trim());
|
|
1213
515
|
if (yaml) {
|
|
1214
|
-
|
|
516
|
+
// Use descriptive name from ApiObject ID if available, otherwise fallback to generic name
|
|
517
|
+
// eslint-disable-next-line security/detect-object-injection
|
|
518
|
+
const apiObjectId = apiObjectIds[index];
|
|
519
|
+
const manifestId = apiObjectId || `manifest-${index + 1}`;
|
|
1215
520
|
synthAssets.push({ id: manifestId, yaml });
|
|
1216
521
|
}
|
|
1217
522
|
});
|
|
@@ -1222,6 +527,21 @@ export class Rutter {
|
|
|
1222
527
|
});
|
|
1223
528
|
return synthAssets;
|
|
1224
529
|
}
|
|
530
|
+
/**
|
|
531
|
+
* Process YAML content to remove quotes from Helm templates
|
|
532
|
+
* This fixes the issue where YAML.stringify adds quotes around Helm template expressions
|
|
533
|
+
* Removes quotes from all Helm template expressions
|
|
534
|
+
*/
|
|
535
|
+
processHelmTemplates(yaml) {
|
|
536
|
+
// Remove quotes from Helm template expressions
|
|
537
|
+
// Match patterns like "{{ .Values.replicas | int }}", "{{ .Release.Name }}", etc.
|
|
538
|
+
// Handle both key-value pairs and standalone values
|
|
539
|
+
return yaml
|
|
540
|
+
.replace(/": "\{\{([^}]+)\}\}"/g, ': {{ $1 }}')
|
|
541
|
+
.replace(/: "\{\{([^}]+)\}\}"/g, ': {{ $1 }}')
|
|
542
|
+
.replace(/"\{\{([^}]+)\}\}"/g, '{{ $1 }}')
|
|
543
|
+
.replace(/": "\.nan"/g, ': .nan');
|
|
544
|
+
}
|
|
1225
545
|
/**
|
|
1226
546
|
* Writes the Helm chart to the specified output directory
|
|
1227
547
|
* @param outDir - Output directory path
|