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
|
@@ -1,1115 +0,0 @@
|
|
|
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: this.normalizeReplicas(spec.replicas),
|
|
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
|
-
// Validate and encode base64 data if needed
|
|
177
|
-
const processedData = spec.data ? this.validateAndEncodeSecretData(spec.data) : undefined;
|
|
178
|
-
return new ApiObject(this.chart, spec.name, {
|
|
179
|
-
apiVersion: CoreResources.CORE_API_VERSION,
|
|
180
|
-
kind: 'Secret',
|
|
181
|
-
metadata: {
|
|
182
|
-
name: spec.name,
|
|
183
|
-
...(spec.labels ? { labels: spec.labels } : {}),
|
|
184
|
-
...(spec.annotations ? { annotations: spec.annotations } : {}),
|
|
185
|
-
},
|
|
186
|
-
type: spec.type ?? 'Opaque',
|
|
187
|
-
...(processedData ? { data: processedData } : {}),
|
|
188
|
-
...(spec.stringData ? { stringData: spec.stringData } : {}),
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Validates and encodes Secret data as base64
|
|
193
|
-
* @param data - Raw secret data
|
|
194
|
-
* @returns Base64 encoded data
|
|
195
|
-
* @private
|
|
196
|
-
* @since 2.5.0
|
|
197
|
-
*/
|
|
198
|
-
validateAndEncodeSecretData(data) {
|
|
199
|
-
const encodedData = {};
|
|
200
|
-
for (const [key, value] of Object.entries(data)) {
|
|
201
|
-
// Check if value is already base64 encoded (basic validation)
|
|
202
|
-
if (this.isBase64Encoded(value)) {
|
|
203
|
-
// eslint-disable-next-line security/detect-object-injection -- Safe: key is from Object.entries iteration
|
|
204
|
-
encodedData[key] = value;
|
|
205
|
-
}
|
|
206
|
-
else {
|
|
207
|
-
// Encode as base64
|
|
208
|
-
// eslint-disable-next-line security/detect-object-injection -- Safe: key is from Object.entries iteration
|
|
209
|
-
encodedData[key] = Buffer.from(value, 'utf8').toString('base64');
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
return encodedData;
|
|
213
|
-
}
|
|
214
|
-
/**
|
|
215
|
-
* Checks if a string is base64 encoded
|
|
216
|
-
* @param str - String to check
|
|
217
|
-
* @returns True if string appears to be base64 encoded
|
|
218
|
-
* @private
|
|
219
|
-
* @since 2.5.0
|
|
220
|
-
*/
|
|
221
|
-
isBase64Encoded(str) {
|
|
222
|
-
// Basic base64 validation - checks for valid base64 characters and padding
|
|
223
|
-
const base64Regex = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
224
|
-
if (!base64Regex.test(str)) {
|
|
225
|
-
return false;
|
|
226
|
-
}
|
|
227
|
-
try {
|
|
228
|
-
// Attempt decode without exposing the decoded content
|
|
229
|
-
Buffer.from(str, 'base64');
|
|
230
|
-
return true;
|
|
231
|
-
}
|
|
232
|
-
catch {
|
|
233
|
-
return false;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Creates a ServiceAccount resource
|
|
238
|
-
* @param spec - ServiceAccount specification
|
|
239
|
-
* @returns Created ServiceAccount ApiObject
|
|
240
|
-
*
|
|
241
|
-
* @example
|
|
242
|
-
* ```typescript
|
|
243
|
-
* coreResources.addServiceAccount({
|
|
244
|
-
* name: 'app-service-account',
|
|
245
|
-
* automountServiceAccountToken: false
|
|
246
|
-
* });
|
|
247
|
-
* ```
|
|
248
|
-
*
|
|
249
|
-
* @since 2.4.0
|
|
250
|
-
*/
|
|
251
|
-
addServiceAccount(spec) {
|
|
252
|
-
return new ApiObject(this.chart, spec.name, {
|
|
253
|
-
apiVersion: CoreResources.CORE_API_VERSION,
|
|
254
|
-
kind: 'ServiceAccount',
|
|
255
|
-
metadata: {
|
|
256
|
-
name: spec.name,
|
|
257
|
-
...(spec.labels ? { labels: spec.labels } : {}),
|
|
258
|
-
...(spec.annotations ? { annotations: spec.annotations } : {}),
|
|
259
|
-
},
|
|
260
|
-
...(spec.automountServiceAccountToken !== undefined
|
|
261
|
-
? { automountServiceAccountToken: spec.automountServiceAccountToken }
|
|
262
|
-
: {}),
|
|
263
|
-
...(spec.imagePullSecrets ? { imagePullSecrets: spec.imagePullSecrets } : {}),
|
|
264
|
-
...(spec.secrets ? { secrets: spec.secrets } : {}),
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
/**
|
|
268
|
-
* Creates a DaemonSet resource
|
|
269
|
-
* @param spec - DaemonSet specification
|
|
270
|
-
* @returns Created DaemonSet ApiObject
|
|
271
|
-
*
|
|
272
|
-
* @example
|
|
273
|
-
* ```typescript
|
|
274
|
-
* coreResources.addDaemonSet({
|
|
275
|
-
* name: 'log-collector',
|
|
276
|
-
* image: 'fluentd:v1.14',
|
|
277
|
-
* containerPort: 24224,
|
|
278
|
-
* hostNetwork: true
|
|
279
|
-
* });
|
|
280
|
-
* ```
|
|
281
|
-
*
|
|
282
|
-
* @since 2.4.0
|
|
283
|
-
*/
|
|
284
|
-
addDaemonSet(spec) {
|
|
285
|
-
const matchLabels = spec.matchLabels ?? {
|
|
286
|
-
[CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
|
|
287
|
-
};
|
|
288
|
-
const daemonSetSpec = this.buildDaemonSetSpec(spec, matchLabels);
|
|
289
|
-
const labels = {
|
|
290
|
-
[CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
|
|
291
|
-
...(spec.labels || {}),
|
|
292
|
-
};
|
|
293
|
-
return new ApiObject(this.chart, spec.name, {
|
|
294
|
-
apiVersion: CoreResources.APPS_API_VERSION,
|
|
295
|
-
kind: 'DaemonSet',
|
|
296
|
-
metadata: {
|
|
297
|
-
name: spec.name,
|
|
298
|
-
...(labels && Object.keys(labels).length > 0 ? { labels } : {}),
|
|
299
|
-
...(spec.annotations && Object.keys(spec.annotations).length > 0
|
|
300
|
-
? { annotations: spec.annotations }
|
|
301
|
-
: {}),
|
|
302
|
-
},
|
|
303
|
-
spec: daemonSetSpec,
|
|
304
|
-
});
|
|
305
|
-
}
|
|
306
|
-
/**
|
|
307
|
-
* Builds DaemonSet specification object
|
|
308
|
-
* @private
|
|
309
|
-
*/
|
|
310
|
-
buildDaemonSetSpec(spec, matchLabels) {
|
|
311
|
-
const containers = this.buildDaemonSetContainers(spec);
|
|
312
|
-
const podSpec = this.buildDaemonSetPodSpec(spec, containers);
|
|
313
|
-
return {
|
|
314
|
-
selector: { matchLabels },
|
|
315
|
-
template: {
|
|
316
|
-
metadata: {
|
|
317
|
-
labels: { ...matchLabels, ...(spec.labels || {}) },
|
|
318
|
-
...(spec.annotations && Object.keys(spec.annotations).length > 0
|
|
319
|
-
? { annotations: spec.annotations }
|
|
320
|
-
: {}),
|
|
321
|
-
},
|
|
322
|
-
spec: podSpec,
|
|
323
|
-
},
|
|
324
|
-
...(spec.updateStrategy && { updateStrategy: spec.updateStrategy }),
|
|
325
|
-
};
|
|
326
|
-
}
|
|
327
|
-
/**
|
|
328
|
-
* Builds container specification for DaemonSet
|
|
329
|
-
* @private
|
|
330
|
-
*/
|
|
331
|
-
buildDaemonSetContainers(spec) {
|
|
332
|
-
const container = {
|
|
333
|
-
name: spec.name,
|
|
334
|
-
image: spec.image,
|
|
335
|
-
};
|
|
336
|
-
if (spec.containerPort) {
|
|
337
|
-
container['ports'] = [{ containerPort: spec.containerPort }];
|
|
338
|
-
}
|
|
339
|
-
if (spec.env) {
|
|
340
|
-
container['env'] = spec.env;
|
|
341
|
-
}
|
|
342
|
-
if (spec.resources) {
|
|
343
|
-
container['resources'] = spec.resources;
|
|
344
|
-
}
|
|
345
|
-
if (spec.volumeMounts) {
|
|
346
|
-
container['volumeMounts'] = spec.volumeMounts;
|
|
347
|
-
}
|
|
348
|
-
if (spec.securityContext) {
|
|
349
|
-
container['securityContext'] = spec.securityContext;
|
|
350
|
-
}
|
|
351
|
-
return [container];
|
|
352
|
-
}
|
|
353
|
-
/**
|
|
354
|
-
* Builds pod specification for DaemonSet
|
|
355
|
-
* @private
|
|
356
|
-
*/
|
|
357
|
-
buildDaemonSetPodSpec(spec, containers) {
|
|
358
|
-
const podSpec = {
|
|
359
|
-
containers,
|
|
360
|
-
};
|
|
361
|
-
if (spec.serviceAccountName) {
|
|
362
|
-
podSpec['serviceAccountName'] = spec.serviceAccountName;
|
|
363
|
-
}
|
|
364
|
-
if (spec.nodeSelector) {
|
|
365
|
-
podSpec['nodeSelector'] = spec.nodeSelector;
|
|
366
|
-
}
|
|
367
|
-
if (spec.tolerations) {
|
|
368
|
-
podSpec['tolerations'] = spec.tolerations;
|
|
369
|
-
}
|
|
370
|
-
if (spec.affinity) {
|
|
371
|
-
podSpec['affinity'] = spec.affinity;
|
|
372
|
-
}
|
|
373
|
-
if (spec.volumes) {
|
|
374
|
-
podSpec['volumes'] = spec.volumes;
|
|
375
|
-
}
|
|
376
|
-
if (spec.hostNetwork) {
|
|
377
|
-
podSpec['hostNetwork'] = spec.hostNetwork;
|
|
378
|
-
}
|
|
379
|
-
if (spec.hostPID) {
|
|
380
|
-
podSpec['hostPID'] = spec.hostPID;
|
|
381
|
-
}
|
|
382
|
-
if (spec.dnsPolicy) {
|
|
383
|
-
podSpec['dnsPolicy'] = spec.dnsPolicy;
|
|
384
|
-
}
|
|
385
|
-
if (spec.priorityClassName) {
|
|
386
|
-
podSpec['priorityClassName'] = spec.priorityClassName;
|
|
387
|
-
}
|
|
388
|
-
return podSpec;
|
|
389
|
-
}
|
|
390
|
-
/**
|
|
391
|
-
* Creates a StatefulSet resource
|
|
392
|
-
* @param spec - StatefulSet specification
|
|
393
|
-
* @returns Created StatefulSet ApiObject
|
|
394
|
-
*
|
|
395
|
-
* @example
|
|
396
|
-
* ```typescript
|
|
397
|
-
* coreResources.addStatefulSet({
|
|
398
|
-
* name: 'database',
|
|
399
|
-
* image: 'postgres:13',
|
|
400
|
-
* replicas: 3,
|
|
401
|
-
* containerPort: 5432,
|
|
402
|
-
* serviceName: 'database-headless'
|
|
403
|
-
* });
|
|
404
|
-
* ```
|
|
405
|
-
*
|
|
406
|
-
* @since 2.4.0
|
|
407
|
-
*/
|
|
408
|
-
addStatefulSet(spec) {
|
|
409
|
-
const matchLabels = spec.matchLabels ?? {
|
|
410
|
-
[CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
|
|
411
|
-
};
|
|
412
|
-
const statefulSetSpec = this.buildStatefulSetSpec(spec, matchLabels);
|
|
413
|
-
const labels = {
|
|
414
|
-
[CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
|
|
415
|
-
...(spec.labels || {}),
|
|
416
|
-
};
|
|
417
|
-
return new ApiObject(this.chart, spec.name, {
|
|
418
|
-
apiVersion: CoreResources.APPS_API_VERSION,
|
|
419
|
-
kind: 'StatefulSet',
|
|
420
|
-
metadata: {
|
|
421
|
-
name: spec.name,
|
|
422
|
-
...(labels && Object.keys(labels).length > 0 ? { labels } : {}),
|
|
423
|
-
...(spec.annotations && Object.keys(spec.annotations).length > 0
|
|
424
|
-
? { annotations: spec.annotations }
|
|
425
|
-
: {}),
|
|
426
|
-
},
|
|
427
|
-
spec: statefulSetSpec,
|
|
428
|
-
});
|
|
429
|
-
}
|
|
430
|
-
/**
|
|
431
|
-
* Builds StatefulSet specification object
|
|
432
|
-
* @private
|
|
433
|
-
*/
|
|
434
|
-
buildStatefulSetSpec(spec, matchLabels) {
|
|
435
|
-
const containers = this.buildStatefulSetContainers(spec);
|
|
436
|
-
const podSpec = this.buildStatefulSetPodSpec(spec, containers);
|
|
437
|
-
const statefulSetSpec = {
|
|
438
|
-
replicas: this.normalizeReplicas(spec.replicas),
|
|
439
|
-
selector: { matchLabels },
|
|
440
|
-
serviceName: spec.serviceName,
|
|
441
|
-
template: {
|
|
442
|
-
metadata: {
|
|
443
|
-
labels: { ...matchLabels, ...(spec.labels || {}) },
|
|
444
|
-
...(spec.annotations && Object.keys(spec.annotations).length > 0
|
|
445
|
-
? { annotations: spec.annotations }
|
|
446
|
-
: {}),
|
|
447
|
-
},
|
|
448
|
-
spec: podSpec,
|
|
449
|
-
},
|
|
450
|
-
};
|
|
451
|
-
if (spec.volumeClaimTemplates) {
|
|
452
|
-
statefulSetSpec['volumeClaimTemplates'] = spec.volumeClaimTemplates;
|
|
453
|
-
}
|
|
454
|
-
if (spec.updateStrategy) {
|
|
455
|
-
statefulSetSpec['updateStrategy'] = spec.updateStrategy;
|
|
456
|
-
}
|
|
457
|
-
if (spec.podManagementPolicy) {
|
|
458
|
-
statefulSetSpec['podManagementPolicy'] = spec.podManagementPolicy;
|
|
459
|
-
}
|
|
460
|
-
if (spec.revisionHistoryLimit !== undefined) {
|
|
461
|
-
statefulSetSpec['revisionHistoryLimit'] = spec.revisionHistoryLimit;
|
|
462
|
-
}
|
|
463
|
-
return statefulSetSpec;
|
|
464
|
-
}
|
|
465
|
-
/**
|
|
466
|
-
* Builds container specification for StatefulSet
|
|
467
|
-
* @private
|
|
468
|
-
*/
|
|
469
|
-
buildStatefulSetContainers(spec) {
|
|
470
|
-
const container = {
|
|
471
|
-
name: spec.name,
|
|
472
|
-
image: spec.image,
|
|
473
|
-
};
|
|
474
|
-
if (spec.containerPort) {
|
|
475
|
-
container['ports'] = [{ containerPort: spec.containerPort }];
|
|
476
|
-
}
|
|
477
|
-
if (spec.env) {
|
|
478
|
-
container['env'] = spec.env;
|
|
479
|
-
}
|
|
480
|
-
if (spec.resources) {
|
|
481
|
-
container['resources'] = spec.resources;
|
|
482
|
-
}
|
|
483
|
-
if (spec.volumeMounts) {
|
|
484
|
-
container['volumeMounts'] = spec.volumeMounts;
|
|
485
|
-
}
|
|
486
|
-
if (spec.securityContext) {
|
|
487
|
-
container['securityContext'] = spec.securityContext;
|
|
488
|
-
}
|
|
489
|
-
if (spec.livenessProbe) {
|
|
490
|
-
container['livenessProbe'] = spec.livenessProbe;
|
|
491
|
-
}
|
|
492
|
-
if (spec.readinessProbe) {
|
|
493
|
-
container['readinessProbe'] = spec.readinessProbe;
|
|
494
|
-
}
|
|
495
|
-
return [container];
|
|
496
|
-
}
|
|
497
|
-
/**
|
|
498
|
-
* Builds pod specification for StatefulSet
|
|
499
|
-
* @private
|
|
500
|
-
*/
|
|
501
|
-
buildStatefulSetPodSpec(spec, containers) {
|
|
502
|
-
const podSpec = {
|
|
503
|
-
containers,
|
|
504
|
-
};
|
|
505
|
-
if (spec.serviceAccountName) {
|
|
506
|
-
podSpec['serviceAccountName'] = spec.serviceAccountName;
|
|
507
|
-
}
|
|
508
|
-
if (spec.nodeSelector) {
|
|
509
|
-
podSpec['nodeSelector'] = spec.nodeSelector;
|
|
510
|
-
}
|
|
511
|
-
if (spec.tolerations) {
|
|
512
|
-
podSpec['tolerations'] = spec.tolerations;
|
|
513
|
-
}
|
|
514
|
-
if (spec.affinity) {
|
|
515
|
-
podSpec['affinity'] = spec.affinity;
|
|
516
|
-
}
|
|
517
|
-
if (spec.volumes) {
|
|
518
|
-
podSpec['volumes'] = spec.volumes;
|
|
519
|
-
}
|
|
520
|
-
if (spec.initContainers) {
|
|
521
|
-
podSpec['initContainers'] = spec.initContainers;
|
|
522
|
-
}
|
|
523
|
-
if (spec.terminationGracePeriodSeconds !== undefined) {
|
|
524
|
-
podSpec['terminationGracePeriodSeconds'] = spec.terminationGracePeriodSeconds;
|
|
525
|
-
}
|
|
526
|
-
return podSpec;
|
|
527
|
-
}
|
|
528
|
-
/**
|
|
529
|
-
* Creates a Role resource for RBAC
|
|
530
|
-
* @param spec - Role specification
|
|
531
|
-
* @returns Created Role ApiObject
|
|
532
|
-
*
|
|
533
|
-
* @example
|
|
534
|
-
* ```typescript
|
|
535
|
-
* coreResources.addRole({
|
|
536
|
-
* name: 'pod-reader',
|
|
537
|
-
* rules: [
|
|
538
|
-
* {
|
|
539
|
-
* apiGroups: [''],
|
|
540
|
-
* resources: ['pods'],
|
|
541
|
-
* verbs: ['get', 'list', 'watch']
|
|
542
|
-
* }
|
|
543
|
-
* ]
|
|
544
|
-
* });
|
|
545
|
-
* ```
|
|
546
|
-
*
|
|
547
|
-
* @since 2.4.0
|
|
548
|
-
*/
|
|
549
|
-
addRole(spec) {
|
|
550
|
-
const labels = {
|
|
551
|
-
[CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
|
|
552
|
-
...(spec.labels || {}),
|
|
553
|
-
};
|
|
554
|
-
return new ApiObject(this.chart, spec.name, {
|
|
555
|
-
apiVersion: CoreResources.RBAC_API_VERSION,
|
|
556
|
-
kind: 'Role',
|
|
557
|
-
metadata: {
|
|
558
|
-
name: spec.name,
|
|
559
|
-
...(spec.namespace && { namespace: spec.namespace }),
|
|
560
|
-
...(labels && Object.keys(labels).length > 0 ? { labels } : {}),
|
|
561
|
-
...(spec.annotations && Object.keys(spec.annotations).length > 0
|
|
562
|
-
? { annotations: spec.annotations }
|
|
563
|
-
: {}),
|
|
564
|
-
},
|
|
565
|
-
rules: spec.rules,
|
|
566
|
-
});
|
|
567
|
-
}
|
|
568
|
-
/**
|
|
569
|
-
* Creates a ClusterRole resource for cluster-wide RBAC
|
|
570
|
-
* @param spec - ClusterRole specification
|
|
571
|
-
* @returns Created ClusterRole ApiObject
|
|
572
|
-
*
|
|
573
|
-
* @example
|
|
574
|
-
* ```typescript
|
|
575
|
-
* coreResources.addClusterRole({
|
|
576
|
-
* name: 'cluster-admin',
|
|
577
|
-
* rules: [
|
|
578
|
-
* {
|
|
579
|
-
* apiGroups: ['*'],
|
|
580
|
-
* resources: ['*'],
|
|
581
|
-
* verbs: ['*']
|
|
582
|
-
* }
|
|
583
|
-
* ]
|
|
584
|
-
* });
|
|
585
|
-
* ```
|
|
586
|
-
*
|
|
587
|
-
* @since 2.4.0
|
|
588
|
-
*/
|
|
589
|
-
addClusterRole(spec) {
|
|
590
|
-
const labels = {
|
|
591
|
-
[CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
|
|
592
|
-
...(spec.labels || {}),
|
|
593
|
-
};
|
|
594
|
-
return new ApiObject(this.chart, spec.name, {
|
|
595
|
-
apiVersion: CoreResources.RBAC_API_VERSION,
|
|
596
|
-
kind: 'ClusterRole',
|
|
597
|
-
metadata: {
|
|
598
|
-
name: spec.name,
|
|
599
|
-
...(labels && Object.keys(labels).length > 0 ? { labels } : {}),
|
|
600
|
-
...(spec.annotations && Object.keys(spec.annotations).length > 0
|
|
601
|
-
? { annotations: spec.annotations }
|
|
602
|
-
: {}),
|
|
603
|
-
},
|
|
604
|
-
rules: spec.rules,
|
|
605
|
-
});
|
|
606
|
-
}
|
|
607
|
-
/**
|
|
608
|
-
* Creates a RoleBinding resource for RBAC
|
|
609
|
-
* @param spec - RoleBinding specification
|
|
610
|
-
* @returns Created RoleBinding ApiObject
|
|
611
|
-
*
|
|
612
|
-
* @example
|
|
613
|
-
* ```typescript
|
|
614
|
-
* coreResources.addRoleBinding({
|
|
615
|
-
* name: 'pod-reader-binding',
|
|
616
|
-
* roleRef: {
|
|
617
|
-
* kind: 'Role',
|
|
618
|
-
* name: 'pod-reader',
|
|
619
|
-
* apiGroup: 'rbac.authorization.k8s.io'
|
|
620
|
-
* },
|
|
621
|
-
* subjects: [
|
|
622
|
-
* {
|
|
623
|
-
* kind: 'ServiceAccount',
|
|
624
|
-
* name: 'my-service-account',
|
|
625
|
-
* namespace: 'default'
|
|
626
|
-
* }
|
|
627
|
-
* ]
|
|
628
|
-
* });
|
|
629
|
-
* ```
|
|
630
|
-
*
|
|
631
|
-
* @since 2.4.0
|
|
632
|
-
*/
|
|
633
|
-
addRoleBinding(spec) {
|
|
634
|
-
const labels = {
|
|
635
|
-
[CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
|
|
636
|
-
...(spec.labels || {}),
|
|
637
|
-
};
|
|
638
|
-
return new ApiObject(this.chart, spec.name, {
|
|
639
|
-
apiVersion: CoreResources.RBAC_API_VERSION,
|
|
640
|
-
kind: 'RoleBinding',
|
|
641
|
-
metadata: {
|
|
642
|
-
name: spec.name,
|
|
643
|
-
...(spec.namespace && { namespace: spec.namespace }),
|
|
644
|
-
...(labels && Object.keys(labels).length > 0 ? { labels } : {}),
|
|
645
|
-
...(spec.annotations && Object.keys(spec.annotations).length > 0
|
|
646
|
-
? { annotations: spec.annotations }
|
|
647
|
-
: {}),
|
|
648
|
-
},
|
|
649
|
-
roleRef: spec.roleRef,
|
|
650
|
-
subjects: spec.subjects,
|
|
651
|
-
});
|
|
652
|
-
}
|
|
653
|
-
/**
|
|
654
|
-
* Creates a ClusterRoleBinding resource for cluster-wide RBAC
|
|
655
|
-
* @param spec - ClusterRoleBinding specification
|
|
656
|
-
* @returns Created ClusterRoleBinding ApiObject
|
|
657
|
-
*
|
|
658
|
-
* @example
|
|
659
|
-
* ```typescript
|
|
660
|
-
* coreResources.addClusterRoleBinding({
|
|
661
|
-
* name: 'cluster-admin-binding',
|
|
662
|
-
* roleRef: {
|
|
663
|
-
* kind: 'ClusterRole',
|
|
664
|
-
* name: 'cluster-admin',
|
|
665
|
-
* apiGroup: 'rbac.authorization.k8s.io'
|
|
666
|
-
* },
|
|
667
|
-
* subjects: [
|
|
668
|
-
* {
|
|
669
|
-
* kind: 'ServiceAccount',
|
|
670
|
-
* name: 'admin-user',
|
|
671
|
-
* namespace: 'kube-system'
|
|
672
|
-
* }
|
|
673
|
-
* ]
|
|
674
|
-
* });
|
|
675
|
-
* ```
|
|
676
|
-
*
|
|
677
|
-
* @since 2.4.0
|
|
678
|
-
*/
|
|
679
|
-
addClusterRoleBinding(spec) {
|
|
680
|
-
const labels = {
|
|
681
|
-
[CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
|
|
682
|
-
...(spec.labels || {}),
|
|
683
|
-
};
|
|
684
|
-
return new ApiObject(this.chart, spec.name, {
|
|
685
|
-
apiVersion: CoreResources.RBAC_API_VERSION,
|
|
686
|
-
kind: 'ClusterRoleBinding',
|
|
687
|
-
metadata: {
|
|
688
|
-
name: spec.name,
|
|
689
|
-
...(labels && Object.keys(labels).length > 0 ? { labels } : {}),
|
|
690
|
-
...(spec.annotations && Object.keys(spec.annotations).length > 0
|
|
691
|
-
? { annotations: spec.annotations }
|
|
692
|
-
: {}),
|
|
693
|
-
},
|
|
694
|
-
roleRef: spec.roleRef,
|
|
695
|
-
subjects: spec.subjects,
|
|
696
|
-
});
|
|
697
|
-
}
|
|
698
|
-
/**
|
|
699
|
-
* Creates a Job resource for batch workloads
|
|
700
|
-
* @param spec - Job specification
|
|
701
|
-
* @returns Created Job ApiObject
|
|
702
|
-
*
|
|
703
|
-
* @example
|
|
704
|
-
* ```typescript
|
|
705
|
-
* coreResources.addJob({
|
|
706
|
-
* name: 'data-processor',
|
|
707
|
-
* image: 'busybox:1.35',
|
|
708
|
-
* command: ['sh', '-c', 'echo "Processing data..." && sleep 30'],
|
|
709
|
-
* completions: 1,
|
|
710
|
-
* parallelism: 1
|
|
711
|
-
* });
|
|
712
|
-
* ```
|
|
713
|
-
*
|
|
714
|
-
* @since 2.4.0
|
|
715
|
-
*/
|
|
716
|
-
addJob(spec) {
|
|
717
|
-
const matchLabels = spec.matchLabels ?? {
|
|
718
|
-
[CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
|
|
719
|
-
};
|
|
720
|
-
const jobSpec = this.buildJobSpec(spec, matchLabels);
|
|
721
|
-
const labels = {
|
|
722
|
-
[CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
|
|
723
|
-
...(spec.labels || {}),
|
|
724
|
-
};
|
|
725
|
-
return new ApiObject(this.chart, spec.name, {
|
|
726
|
-
apiVersion: 'batch/v1',
|
|
727
|
-
kind: 'Job',
|
|
728
|
-
metadata: {
|
|
729
|
-
name: spec.name,
|
|
730
|
-
...(labels && Object.keys(labels).length > 0 ? { labels } : {}),
|
|
731
|
-
...(spec.annotations && Object.keys(spec.annotations).length > 0
|
|
732
|
-
? { annotations: spec.annotations }
|
|
733
|
-
: {}),
|
|
734
|
-
},
|
|
735
|
-
spec: jobSpec,
|
|
736
|
-
});
|
|
737
|
-
}
|
|
738
|
-
/**
|
|
739
|
-
* Builds Job specification object
|
|
740
|
-
* @private
|
|
741
|
-
*/
|
|
742
|
-
buildJobSpec(spec, matchLabels) {
|
|
743
|
-
const containers = this.buildJobContainers(spec);
|
|
744
|
-
const podSpec = this.buildJobPodSpec(spec, containers);
|
|
745
|
-
const jobSpec = {
|
|
746
|
-
template: {
|
|
747
|
-
metadata: {
|
|
748
|
-
labels: { ...matchLabels, ...(spec.labels || {}) },
|
|
749
|
-
...(spec.annotations && Object.keys(spec.annotations).length > 0
|
|
750
|
-
? { annotations: spec.annotations }
|
|
751
|
-
: {}),
|
|
752
|
-
},
|
|
753
|
-
spec: podSpec,
|
|
754
|
-
},
|
|
755
|
-
};
|
|
756
|
-
if (spec.completions !== undefined) {
|
|
757
|
-
jobSpec['completions'] = spec.completions;
|
|
758
|
-
}
|
|
759
|
-
if (spec.parallelism !== undefined) {
|
|
760
|
-
jobSpec['parallelism'] = spec.parallelism;
|
|
761
|
-
}
|
|
762
|
-
if (spec.backoffLimit !== undefined) {
|
|
763
|
-
jobSpec['backoffLimit'] = spec.backoffLimit;
|
|
764
|
-
}
|
|
765
|
-
if (spec.activeDeadlineSeconds !== undefined) {
|
|
766
|
-
jobSpec['activeDeadlineSeconds'] = spec.activeDeadlineSeconds;
|
|
767
|
-
}
|
|
768
|
-
if (spec.ttlSecondsAfterFinished !== undefined) {
|
|
769
|
-
jobSpec['ttlSecondsAfterFinished'] = spec.ttlSecondsAfterFinished;
|
|
770
|
-
}
|
|
771
|
-
if (spec.completionMode) {
|
|
772
|
-
jobSpec['completionMode'] = spec.completionMode;
|
|
773
|
-
}
|
|
774
|
-
if (spec.suspend !== undefined) {
|
|
775
|
-
jobSpec['suspend'] = spec.suspend;
|
|
776
|
-
}
|
|
777
|
-
return jobSpec;
|
|
778
|
-
}
|
|
779
|
-
/**
|
|
780
|
-
* Builds container specification for Job
|
|
781
|
-
* @private
|
|
782
|
-
*/
|
|
783
|
-
buildJobContainers(spec) {
|
|
784
|
-
const containerSpec = {
|
|
785
|
-
name: spec.name,
|
|
786
|
-
image: spec.image,
|
|
787
|
-
};
|
|
788
|
-
if (spec.command)
|
|
789
|
-
containerSpec['command'] = spec.command;
|
|
790
|
-
if (spec.args)
|
|
791
|
-
containerSpec['args'] = spec.args;
|
|
792
|
-
if (spec.env)
|
|
793
|
-
containerSpec['env'] = spec.env;
|
|
794
|
-
if (spec.resources)
|
|
795
|
-
containerSpec['resources'] = spec.resources;
|
|
796
|
-
if (spec.volumeMounts)
|
|
797
|
-
containerSpec['volumeMounts'] = spec.volumeMounts;
|
|
798
|
-
if (spec.securityContext)
|
|
799
|
-
containerSpec['securityContext'] = spec.securityContext;
|
|
800
|
-
return this.buildGenericContainers(containerSpec);
|
|
801
|
-
}
|
|
802
|
-
/**
|
|
803
|
-
* Builds pod specification for Job
|
|
804
|
-
* @private
|
|
805
|
-
*/
|
|
806
|
-
buildJobPodSpec(spec, containers) {
|
|
807
|
-
const podSpec = {
|
|
808
|
-
containers,
|
|
809
|
-
restartPolicy: spec.restartPolicy ?? 'Never',
|
|
810
|
-
};
|
|
811
|
-
if (spec.serviceAccountName) {
|
|
812
|
-
podSpec['serviceAccountName'] = spec.serviceAccountName;
|
|
813
|
-
}
|
|
814
|
-
if (spec.nodeSelector) {
|
|
815
|
-
podSpec['nodeSelector'] = spec.nodeSelector;
|
|
816
|
-
}
|
|
817
|
-
if (spec.tolerations) {
|
|
818
|
-
podSpec['tolerations'] = spec.tolerations;
|
|
819
|
-
}
|
|
820
|
-
if (spec.affinity) {
|
|
821
|
-
podSpec['affinity'] = spec.affinity;
|
|
822
|
-
}
|
|
823
|
-
if (spec.volumes) {
|
|
824
|
-
podSpec['volumes'] = spec.volumes;
|
|
825
|
-
}
|
|
826
|
-
if (spec.initContainers) {
|
|
827
|
-
podSpec['initContainers'] = spec.initContainers;
|
|
828
|
-
}
|
|
829
|
-
return podSpec;
|
|
830
|
-
}
|
|
831
|
-
/**
|
|
832
|
-
* Creates a ReplicaSet resource
|
|
833
|
-
* @param spec - ReplicaSet specification
|
|
834
|
-
* @returns Created ReplicaSet ApiObject
|
|
835
|
-
*
|
|
836
|
-
* @example
|
|
837
|
-
* ```typescript
|
|
838
|
-
* coreResources.addReplicaSet({
|
|
839
|
-
* name: 'web-replica',
|
|
840
|
-
* image: 'nginx:1.21',
|
|
841
|
-
* replicas: 3,
|
|
842
|
-
* containerPort: 80
|
|
843
|
-
* });
|
|
844
|
-
* ```
|
|
845
|
-
*
|
|
846
|
-
* @since 2.4.0
|
|
847
|
-
*/
|
|
848
|
-
addReplicaSet(spec) {
|
|
849
|
-
const matchLabels = spec.matchLabels ?? {
|
|
850
|
-
[CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
|
|
851
|
-
};
|
|
852
|
-
const containers = [
|
|
853
|
-
{
|
|
854
|
-
name: spec.name,
|
|
855
|
-
image: spec.image,
|
|
856
|
-
...(spec.containerPort ? { ports: [{ containerPort: spec.containerPort }] } : {}),
|
|
857
|
-
...(spec.env ? { env: spec.env } : {}),
|
|
858
|
-
...(spec.resources ? { resources: spec.resources } : {}),
|
|
859
|
-
...(spec.volumeMounts ? { volumeMounts: spec.volumeMounts } : {}),
|
|
860
|
-
...(spec.securityContext ? { securityContext: spec.securityContext } : {}),
|
|
861
|
-
},
|
|
862
|
-
];
|
|
863
|
-
const replicaSetSpec = {
|
|
864
|
-
replicas: this.normalizeReplicas(spec.replicas),
|
|
865
|
-
selector: { matchLabels },
|
|
866
|
-
template: {
|
|
867
|
-
metadata: { labels: { ...matchLabels, ...spec.labels } },
|
|
868
|
-
spec: {
|
|
869
|
-
containers,
|
|
870
|
-
...(spec.volumes ? { volumes: spec.volumes } : {}),
|
|
871
|
-
...(spec.serviceAccountName ? { serviceAccountName: spec.serviceAccountName } : {}),
|
|
872
|
-
...(spec.nodeSelector ? { nodeSelector: spec.nodeSelector } : {}),
|
|
873
|
-
...(spec.tolerations ? { tolerations: spec.tolerations } : {}),
|
|
874
|
-
...(spec.affinity ? { affinity: spec.affinity } : {}),
|
|
875
|
-
},
|
|
876
|
-
},
|
|
877
|
-
};
|
|
878
|
-
return new ApiObject(this.chart, spec.name, {
|
|
879
|
-
apiVersion: CoreResources.APPS_API_VERSION,
|
|
880
|
-
kind: 'ReplicaSet',
|
|
881
|
-
metadata: {
|
|
882
|
-
name: spec.name,
|
|
883
|
-
...(spec.labels ? { labels: spec.labels } : {}),
|
|
884
|
-
...(spec.annotations ? { annotations: spec.annotations } : {}),
|
|
885
|
-
},
|
|
886
|
-
spec: replicaSetSpec,
|
|
887
|
-
});
|
|
888
|
-
}
|
|
889
|
-
/**
|
|
890
|
-
* Creates a Pod resource
|
|
891
|
-
* @param spec - Pod specification
|
|
892
|
-
* @returns Created Pod ApiObject
|
|
893
|
-
*
|
|
894
|
-
* @example
|
|
895
|
-
* ```typescript
|
|
896
|
-
* coreResources.addPod({
|
|
897
|
-
* name: 'web-pod',
|
|
898
|
-
* image: 'nginx:1.21',
|
|
899
|
-
* containerPort: 80
|
|
900
|
-
* });
|
|
901
|
-
* ```
|
|
902
|
-
*
|
|
903
|
-
* @since 2.4.0
|
|
904
|
-
*/
|
|
905
|
-
addPod(spec) {
|
|
906
|
-
const containers = [
|
|
907
|
-
{
|
|
908
|
-
name: spec.name,
|
|
909
|
-
image: spec.image,
|
|
910
|
-
...(spec.containerPort ? { ports: [{ containerPort: spec.containerPort }] } : {}),
|
|
911
|
-
...(spec.env ? { env: spec.env } : {}),
|
|
912
|
-
...(spec.resources ? { resources: spec.resources } : {}),
|
|
913
|
-
...(spec.volumeMounts ? { volumeMounts: spec.volumeMounts } : {}),
|
|
914
|
-
...(spec.securityContext ? { securityContext: spec.securityContext } : {}),
|
|
915
|
-
},
|
|
916
|
-
];
|
|
917
|
-
const podSpec = {
|
|
918
|
-
containers,
|
|
919
|
-
restartPolicy: spec.restartPolicy ?? 'Always',
|
|
920
|
-
...(spec.volumes ? { volumes: spec.volumes } : {}),
|
|
921
|
-
...(spec.serviceAccountName ? { serviceAccountName: spec.serviceAccountName } : {}),
|
|
922
|
-
...(spec.nodeSelector ? { nodeSelector: spec.nodeSelector } : {}),
|
|
923
|
-
...(spec.tolerations ? { tolerations: spec.tolerations } : {}),
|
|
924
|
-
...(spec.affinity ? { affinity: spec.affinity } : {}),
|
|
925
|
-
...(spec.initContainers ? { initContainers: spec.initContainers } : {}),
|
|
926
|
-
};
|
|
927
|
-
return new ApiObject(this.chart, spec.name, {
|
|
928
|
-
apiVersion: CoreResources.CORE_API_VERSION,
|
|
929
|
-
kind: 'Pod',
|
|
930
|
-
metadata: {
|
|
931
|
-
name: spec.name,
|
|
932
|
-
...(spec.labels ? { labels: spec.labels } : {}),
|
|
933
|
-
...(spec.annotations ? { annotations: spec.annotations } : {}),
|
|
934
|
-
},
|
|
935
|
-
spec: podSpec,
|
|
936
|
-
});
|
|
937
|
-
}
|
|
938
|
-
/**
|
|
939
|
-
* Creates a CronJob resource
|
|
940
|
-
* @param spec - CronJob specification
|
|
941
|
-
* @returns Created CronJob ApiObject
|
|
942
|
-
*
|
|
943
|
-
* @example
|
|
944
|
-
* ```typescript
|
|
945
|
-
* coreResources.addCronJob({
|
|
946
|
-
* name: 'backup-job',
|
|
947
|
-
* schedule: '0 2 * * *',
|
|
948
|
-
* image: 'backup:latest',
|
|
949
|
-
* command: ['sh', '-c', 'backup-script.sh']
|
|
950
|
-
* });
|
|
951
|
-
* ```
|
|
952
|
-
*
|
|
953
|
-
* @since 2.4.0
|
|
954
|
-
*/
|
|
955
|
-
addCronJob(spec) {
|
|
956
|
-
const matchLabels = spec.matchLabels ?? {
|
|
957
|
-
[CoreResources.LABEL_NAME]: include(CoreResources.HELPER_NAME),
|
|
958
|
-
};
|
|
959
|
-
const cronJobSpec = this.buildCronJobSpec(spec, matchLabels);
|
|
960
|
-
return new ApiObject(this.chart, spec.name, {
|
|
961
|
-
apiVersion: 'batch/v1',
|
|
962
|
-
kind: 'CronJob',
|
|
963
|
-
metadata: {
|
|
964
|
-
name: spec.name,
|
|
965
|
-
...(spec.labels ? { labels: spec.labels } : {}),
|
|
966
|
-
...(spec.annotations ? { annotations: spec.annotations } : {}),
|
|
967
|
-
},
|
|
968
|
-
spec: cronJobSpec,
|
|
969
|
-
});
|
|
970
|
-
}
|
|
971
|
-
/**
|
|
972
|
-
* Builds CronJob specification object
|
|
973
|
-
* @private
|
|
974
|
-
*/
|
|
975
|
-
buildCronJobSpec(spec, matchLabels) {
|
|
976
|
-
const containerSpec = {
|
|
977
|
-
name: spec.name,
|
|
978
|
-
image: spec.image,
|
|
979
|
-
};
|
|
980
|
-
if (spec.command)
|
|
981
|
-
containerSpec['command'] = spec.command;
|
|
982
|
-
if (spec.args)
|
|
983
|
-
containerSpec['args'] = spec.args;
|
|
984
|
-
if (spec.env)
|
|
985
|
-
containerSpec['env'] = spec.env;
|
|
986
|
-
if (spec.resources)
|
|
987
|
-
containerSpec['resources'] = spec.resources;
|
|
988
|
-
if (spec.volumeMounts)
|
|
989
|
-
containerSpec['volumeMounts'] = spec.volumeMounts;
|
|
990
|
-
if (spec.securityContext)
|
|
991
|
-
containerSpec['securityContext'] = spec.securityContext;
|
|
992
|
-
const containers = this.buildGenericContainers(containerSpec);
|
|
993
|
-
const podSpec = this.buildCronJobPodSpec(spec, containers);
|
|
994
|
-
const cronJobSpec = {
|
|
995
|
-
schedule: spec.schedule,
|
|
996
|
-
jobTemplate: {
|
|
997
|
-
spec: {
|
|
998
|
-
template: {
|
|
999
|
-
metadata: { labels: { ...matchLabels, ...spec.labels } },
|
|
1000
|
-
spec: podSpec,
|
|
1001
|
-
},
|
|
1002
|
-
...(spec.backoffLimit !== undefined ? { backoffLimit: spec.backoffLimit } : {}),
|
|
1003
|
-
...(spec.activeDeadlineSeconds !== undefined
|
|
1004
|
-
? { activeDeadlineSeconds: spec.activeDeadlineSeconds }
|
|
1005
|
-
: {}),
|
|
1006
|
-
},
|
|
1007
|
-
},
|
|
1008
|
-
};
|
|
1009
|
-
if (spec.concurrencyPolicy) {
|
|
1010
|
-
cronJobSpec['concurrencyPolicy'] = spec.concurrencyPolicy;
|
|
1011
|
-
}
|
|
1012
|
-
if (spec.suspend !== undefined) {
|
|
1013
|
-
cronJobSpec['suspend'] = spec.suspend;
|
|
1014
|
-
}
|
|
1015
|
-
if (spec.successfulJobsHistoryLimit !== undefined) {
|
|
1016
|
-
cronJobSpec['successfulJobsHistoryLimit'] = spec.successfulJobsHistoryLimit;
|
|
1017
|
-
}
|
|
1018
|
-
if (spec.failedJobsHistoryLimit !== undefined) {
|
|
1019
|
-
cronJobSpec['failedJobsHistoryLimit'] = spec.failedJobsHistoryLimit;
|
|
1020
|
-
}
|
|
1021
|
-
if (spec.startingDeadlineSeconds !== undefined) {
|
|
1022
|
-
cronJobSpec['startingDeadlineSeconds'] = spec.startingDeadlineSeconds;
|
|
1023
|
-
}
|
|
1024
|
-
return cronJobSpec;
|
|
1025
|
-
}
|
|
1026
|
-
/**
|
|
1027
|
-
* Builds generic container specification
|
|
1028
|
-
* @private
|
|
1029
|
-
*/
|
|
1030
|
-
buildGenericContainers(spec) {
|
|
1031
|
-
const container = {
|
|
1032
|
-
name: spec['name'],
|
|
1033
|
-
image: spec['image'],
|
|
1034
|
-
};
|
|
1035
|
-
if (spec['containerPort']) {
|
|
1036
|
-
container['ports'] = [{ containerPort: spec['containerPort'] }];
|
|
1037
|
-
}
|
|
1038
|
-
if (spec['command']) {
|
|
1039
|
-
container['command'] = spec['command'];
|
|
1040
|
-
}
|
|
1041
|
-
if (spec['args']) {
|
|
1042
|
-
container['args'] = spec['args'];
|
|
1043
|
-
}
|
|
1044
|
-
if (spec['env']) {
|
|
1045
|
-
container['env'] = spec['env'];
|
|
1046
|
-
}
|
|
1047
|
-
if (spec['resources']) {
|
|
1048
|
-
container['resources'] = spec['resources'];
|
|
1049
|
-
}
|
|
1050
|
-
if (spec['volumeMounts']) {
|
|
1051
|
-
container['volumeMounts'] = spec['volumeMounts'];
|
|
1052
|
-
}
|
|
1053
|
-
if (spec['securityContext']) {
|
|
1054
|
-
container['securityContext'] = spec['securityContext'];
|
|
1055
|
-
}
|
|
1056
|
-
return [container];
|
|
1057
|
-
}
|
|
1058
|
-
/**
|
|
1059
|
-
* Builds pod specification for CronJob
|
|
1060
|
-
* @private
|
|
1061
|
-
*/
|
|
1062
|
-
buildCronJobPodSpec(spec, containers) {
|
|
1063
|
-
const podSpec = {
|
|
1064
|
-
containers,
|
|
1065
|
-
restartPolicy: spec.restartPolicy ?? 'OnFailure',
|
|
1066
|
-
};
|
|
1067
|
-
if (spec.volumes) {
|
|
1068
|
-
podSpec['volumes'] = spec.volumes;
|
|
1069
|
-
}
|
|
1070
|
-
if (spec.serviceAccountName) {
|
|
1071
|
-
podSpec['serviceAccountName'] = spec.serviceAccountName;
|
|
1072
|
-
}
|
|
1073
|
-
if (spec.nodeSelector) {
|
|
1074
|
-
podSpec['nodeSelector'] = spec.nodeSelector;
|
|
1075
|
-
}
|
|
1076
|
-
if (spec.tolerations) {
|
|
1077
|
-
podSpec['tolerations'] = spec.tolerations;
|
|
1078
|
-
}
|
|
1079
|
-
if (spec.affinity) {
|
|
1080
|
-
podSpec['affinity'] = spec.affinity;
|
|
1081
|
-
}
|
|
1082
|
-
return podSpec;
|
|
1083
|
-
}
|
|
1084
|
-
/**
|
|
1085
|
-
* Normalizes replicas value to ensure it's always a number
|
|
1086
|
-
* @param replicas - Replicas value (number, string, or undefined)
|
|
1087
|
-
* @returns Normalized number value or Helm template string
|
|
1088
|
-
* @private
|
|
1089
|
-
* @since 2.5.0
|
|
1090
|
-
*/
|
|
1091
|
-
normalizeReplicas(replicas) {
|
|
1092
|
-
if (replicas === undefined || replicas === null) {
|
|
1093
|
-
return 1;
|
|
1094
|
-
}
|
|
1095
|
-
// Validate Helm template value with safe regex (no ReDoS vulnerability)
|
|
1096
|
-
if (typeof replicas === 'string') {
|
|
1097
|
-
// Simple check for Helm template pattern without catastrophic backtracking
|
|
1098
|
-
if (replicas.trim().startsWith('{{') && replicas.trim().endsWith('}}')) {
|
|
1099
|
-
return replicas.trim();
|
|
1100
|
-
}
|
|
1101
|
-
const parsed = parseInt(replicas, 10);
|
|
1102
|
-
return isNaN(parsed) ? 1 : Math.max(0, parsed);
|
|
1103
|
-
}
|
|
1104
|
-
if (typeof replicas === 'number') {
|
|
1105
|
-
return Math.max(0, Math.floor(replicas));
|
|
1106
|
-
}
|
|
1107
|
-
return 1;
|
|
1108
|
-
}
|
|
1109
|
-
}
|
|
1110
|
-
CoreResources.APPS_API_VERSION = 'apps/v1';
|
|
1111
|
-
CoreResources.CORE_API_VERSION = 'v1';
|
|
1112
|
-
CoreResources.RBAC_API_VERSION = 'rbac.authorization.k8s.io/v1';
|
|
1113
|
-
CoreResources.LABEL_NAME = 'app.kubernetes.io/name';
|
|
1114
|
-
CoreResources.HELPER_NAME = 'chart.name';
|
|
1115
|
-
//# sourceMappingURL=coreResources.js.map
|