timonel 2.10.2 → 2.12.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 +17 -0
- package/README.md +8 -54
- package/dist/cli.js +65 -52
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -2
- package/dist/lib/helmChartWriter.js +17 -2
- package/dist/lib/rutter.d.ts +1 -0
- package/dist/lib/rutter.js +64 -11
- package/dist/lib/templates/flexible-subchart.d.ts +1 -0
- package/dist/lib/templates/flexible-subchart.js +101 -0
- package/dist/lib/templates/umbrella-chart.d.ts +13 -2
- package/dist/lib/templates/umbrella-chart.js +128 -42
- package/dist/lib/utils/helmHelpers/envHelpers.d.ts +2 -0
- package/dist/lib/utils/helmHelpers/envHelpers.js +97 -0
- package/dist/lib/utils/helmHelpers/gitopsHelpers.d.ts +2 -0
- package/dist/lib/utils/helmHelpers/gitopsHelpers.js +132 -0
- package/dist/lib/utils/helmHelpers/index.d.ts +23 -0
- package/dist/lib/utils/helmHelpers/index.js +132 -0
- package/dist/lib/utils/helmHelpers/observabilityHelpers.d.ts +2 -0
- package/dist/lib/utils/helmHelpers/observabilityHelpers.js +221 -0
- package/dist/lib/utils/helmHelpers/types.d.ts +16 -0
- package/dist/lib/utils/helmHelpers/types.js +1 -0
- package/dist/lib/utils/helmHelpers/validationHelpers.d.ts +2 -0
- package/dist/lib/utils/helmHelpers/validationHelpers.js +201 -0
- package/dist/lib/utils/helmHelpers.d.ts +11 -1
- package/dist/lib/utils/helmHelpers.js +20 -7
- package/dist/lib/utils/helmYamlSerializer.d.ts +53 -1
- package/dist/lib/utils/helmYamlSerializer.js +325 -29
- package/dist/lib/utils/logger.d.ts +49 -0
- package/dist/lib/utils/logger.js +418 -0
- package/package.json +21 -11
- package/dist/lib/templates/basic-chart.d.ts +0 -19
- package/dist/lib/templates/basic-chart.js +0 -210
- package/dist/lib/templates/subchart.d.ts +0 -27
- package/dist/lib/templates/subchart.js +0 -219
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { Chart } from 'cdk8s';
|
|
1
|
+
import { App, Chart } from 'cdk8s';
|
|
3
2
|
import type { ChartProps } from '../types.js';
|
|
4
3
|
export declare function generateUmbrellaChart(name: string): string;
|
|
5
4
|
export declare class UmbrellaChartTemplate extends Chart {
|
|
@@ -9,6 +8,18 @@ export declare class UmbrellaChartTemplate extends Chart {
|
|
|
9
8
|
private configure;
|
|
10
9
|
private _addService;
|
|
11
10
|
private _addSubchart;
|
|
11
|
+
private _createFlexibleSubchart;
|
|
12
|
+
private _createFallbackSubchart;
|
|
13
|
+
private _handleFunctionChart;
|
|
14
|
+
private _handleObjectChart;
|
|
15
|
+
private _isRutterInstance;
|
|
16
|
+
private _isChartInstance;
|
|
17
|
+
private _processRutterInstance;
|
|
18
|
+
private _processChartInstance;
|
|
19
|
+
private _copyTemplates;
|
|
20
|
+
private _ensureDirectoryExists;
|
|
21
|
+
private _processAssets;
|
|
22
|
+
private _cleanupTempDir;
|
|
12
23
|
private _createBasicSubchart;
|
|
13
24
|
writeHelmChart(outputDir: string): void;
|
|
14
25
|
}
|
|
@@ -1,13 +1,20 @@
|
|
|
1
|
-
import { writeFileSync, mkdirSync, existsSync } from 'fs';
|
|
1
|
+
import { writeFileSync, mkdirSync, existsSync, copyFileSync, readdirSync, rmSync } from 'fs';
|
|
2
2
|
import { join } from 'path';
|
|
3
|
-
import
|
|
3
|
+
import * as jsYaml from 'js-yaml';
|
|
4
|
+
import { App, Chart, ApiObject } from 'cdk8s';
|
|
4
5
|
import { dumpHelmAwareYaml } from '../utils/helmYamlSerializer.js';
|
|
5
6
|
import { generateHelpersTemplate } from '../utils/helmHelpers.js';
|
|
6
7
|
import { createFlexibleSubchart } from './flexible-subchart.js';
|
|
7
8
|
export function generateUmbrellaChart(name) {
|
|
8
9
|
return `import { App } from 'cdk8s';
|
|
9
10
|
import { UmbrellaChart } from 'timonel';
|
|
11
|
+
// Import subcharts - add your subchart imports here
|
|
10
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Synthesizes the umbrella chart with all subcharts
|
|
15
|
+
* @param outDir Output directory for generated charts
|
|
16
|
+
* @since 2.11.0
|
|
17
|
+
*/
|
|
11
18
|
export function synth(outDir: string) {
|
|
12
19
|
const app = new App({
|
|
13
20
|
outdir: outDir,
|
|
@@ -20,7 +27,9 @@ export function synth(outDir: string) {
|
|
|
20
27
|
version: '0.1.0',
|
|
21
28
|
description: '${name} umbrella chart',
|
|
22
29
|
services: [],
|
|
23
|
-
subcharts: [
|
|
30
|
+
subcharts: [
|
|
31
|
+
// Add your subcharts here:
|
|
32
|
+
]
|
|
24
33
|
});
|
|
25
34
|
|
|
26
35
|
// Generate Helm chart files
|
|
@@ -95,54 +104,131 @@ export class UmbrellaChartTemplate extends Chart {
|
|
|
95
104
|
}
|
|
96
105
|
_addSubchart(subchart, index) {
|
|
97
106
|
try {
|
|
98
|
-
|
|
99
|
-
const { name: _name, version: _version, description: _description, ...subchartProps } = subchart;
|
|
100
|
-
const flexibleSubchart = createFlexibleSubchart(this, `${subchart.name}-${index}`, {
|
|
101
|
-
name: subchart.name,
|
|
102
|
-
version: subchart.version || '1.0.0',
|
|
103
|
-
description: subchart.description || `${subchart.name} subchart`,
|
|
104
|
-
...subchartProps,
|
|
105
|
-
});
|
|
107
|
+
const flexibleSubchart = this._createFlexibleSubchart(subchart, index);
|
|
106
108
|
if (typeof subchart.chart === 'function') {
|
|
107
|
-
|
|
108
|
-
const subchartInstance = subchart.chart(this, `${subchart.name}-${index}`);
|
|
109
|
-
if (subchartInstance.node.children) {
|
|
110
|
-
subchartInstance.node.children.forEach((child) => {
|
|
111
|
-
if (child instanceof Chart) {
|
|
112
|
-
flexibleSubchart.addConstruct(child);
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
catch {
|
|
118
|
-
const subchartInstance = subchart.chart();
|
|
119
|
-
if (subchartInstance.node.children) {
|
|
120
|
-
subchartInstance.node.children.forEach((child) => {
|
|
121
|
-
if (child instanceof Chart) {
|
|
122
|
-
flexibleSubchart.addConstruct(child);
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
}
|
|
109
|
+
this._handleFunctionChart(subchart, index, flexibleSubchart);
|
|
127
110
|
}
|
|
128
111
|
else if (subchart.chart && typeof subchart.chart === 'object') {
|
|
129
|
-
|
|
130
|
-
flexibleSubchart.addConstruct(subchart.chart);
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
flexibleSubchart.addManifest(subchart.chart);
|
|
134
|
-
}
|
|
112
|
+
this._handleObjectChart(subchart, flexibleSubchart);
|
|
135
113
|
}
|
|
136
114
|
console.log(`Added flexible subchart: ${subchart.name}`);
|
|
137
115
|
}
|
|
138
116
|
catch (_error) {
|
|
139
117
|
console.warn(`Failed to add subchart ${subchart.name}:`, _error);
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
118
|
+
this._createFallbackSubchart(subchart, index);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
_createFlexibleSubchart(subchart, index) {
|
|
122
|
+
const { name: _name, version: _version, description: _description, ...subchartProps } = subchart;
|
|
123
|
+
return createFlexibleSubchart(this, `${subchart.name}-${index}`, {
|
|
124
|
+
name: subchart.name,
|
|
125
|
+
version: subchart.version || '1.0.0',
|
|
126
|
+
description: subchart.description || `${subchart.name} subchart`,
|
|
127
|
+
...subchartProps,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
_createFallbackSubchart(subchart, index) {
|
|
131
|
+
const _fallbackSubchart = createFlexibleSubchart(this, `${subchart.name}-fallback-${index}`, {
|
|
132
|
+
name: subchart.name,
|
|
133
|
+
version: subchart.version || '1.0.0',
|
|
134
|
+
description: `${subchart.name} subchart (fallback)`,
|
|
135
|
+
});
|
|
136
|
+
console.log(`Created fallback subchart: ${subchart.name}`);
|
|
137
|
+
}
|
|
138
|
+
_handleFunctionChart(subchart, index, flexibleSubchart) {
|
|
139
|
+
try {
|
|
140
|
+
const tempApp = new App({ outdir: 'temp' });
|
|
141
|
+
const rutterInstance = subchart.chart(tempApp);
|
|
142
|
+
if (this._isRutterInstance(rutterInstance)) {
|
|
143
|
+
this._processRutterInstance(subchart, index, rutterInstance, flexibleSubchart);
|
|
144
|
+
}
|
|
145
|
+
else if (this._isChartInstance(rutterInstance)) {
|
|
146
|
+
this._processChartInstance(rutterInstance, flexibleSubchart);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
console.log(`Failed to process subchart ${subchart.name}:`, error);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
_handleObjectChart(subchart, flexibleSubchart) {
|
|
154
|
+
const chartObj = subchart.chart;
|
|
155
|
+
if (chartObj.constructor && chartObj.constructor.name !== 'Object') {
|
|
156
|
+
flexibleSubchart.addConstruct(subchart.chart);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
flexibleSubchart.addManifest(subchart.chart);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
_isRutterInstance(instance) {
|
|
163
|
+
return !!(instance && typeof instance.addManifest === 'function');
|
|
164
|
+
}
|
|
165
|
+
_isChartInstance(instance) {
|
|
166
|
+
const obj = instance;
|
|
167
|
+
const node = obj?.node;
|
|
168
|
+
return !!(node && node.children);
|
|
169
|
+
}
|
|
170
|
+
_processRutterInstance(subchart, index, rutterInstance, flexibleSubchart) {
|
|
171
|
+
const tempDir = `temp-${subchart.name}-${index}`;
|
|
172
|
+
const write = rutterInstance.write;
|
|
173
|
+
write?.(tempDir);
|
|
174
|
+
this._copyTemplates(subchart.name, tempDir);
|
|
175
|
+
this._processAssets(rutterInstance, flexibleSubchart);
|
|
176
|
+
this._cleanupTempDir(tempDir);
|
|
177
|
+
}
|
|
178
|
+
_processChartInstance(rutterInstance, flexibleSubchart) {
|
|
179
|
+
const obj = rutterInstance;
|
|
180
|
+
const node = obj?.node;
|
|
181
|
+
const children = node?.children;
|
|
182
|
+
children?.forEach((child) => {
|
|
183
|
+
if (child instanceof Chart) {
|
|
184
|
+
flexibleSubchart.addConstruct(child);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
_copyTemplates(subchartName, tempDir) {
|
|
189
|
+
const tempTemplatesDir = join(tempDir, 'templates');
|
|
190
|
+
const subchartTemplatesDir = join('dist', 'charts', subchartName, 'templates');
|
|
191
|
+
if (existsSync(tempTemplatesDir)) {
|
|
192
|
+
this._ensureDirectoryExists(join('dist', 'charts', subchartName));
|
|
193
|
+
this._ensureDirectoryExists(subchartTemplatesDir);
|
|
194
|
+
const templateFiles = readdirSync(tempTemplatesDir);
|
|
195
|
+
templateFiles.forEach((file) => {
|
|
196
|
+
if (file.endsWith('.yaml') || file.endsWith('.yml') || file.endsWith('.tpl')) {
|
|
197
|
+
const sourceFile = join(tempTemplatesDir, file);
|
|
198
|
+
const targetFile = join(subchartTemplatesDir, file);
|
|
199
|
+
copyFileSync(sourceFile, targetFile);
|
|
200
|
+
}
|
|
144
201
|
});
|
|
145
|
-
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
_ensureDirectoryExists(dirPath) {
|
|
205
|
+
if (!existsSync(dirPath)) {
|
|
206
|
+
mkdirSync(dirPath, { recursive: true });
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
_processAssets(rutterInstance, flexibleSubchart) {
|
|
210
|
+
const getAssets = rutterInstance.getAssets;
|
|
211
|
+
const assets = getAssets?.() || [];
|
|
212
|
+
assets.forEach((asset, assetIndex) => {
|
|
213
|
+
try {
|
|
214
|
+
const manifest = jsYaml.load(asset.yaml);
|
|
215
|
+
if (manifest?.apiVersion && manifest?.kind) {
|
|
216
|
+
new ApiObject(flexibleSubchart, `${String(manifest.kind).toLowerCase()}-${assetIndex}`, {
|
|
217
|
+
apiVersion: String(manifest.apiVersion),
|
|
218
|
+
kind: String(manifest.kind),
|
|
219
|
+
metadata: manifest.metadata || {},
|
|
220
|
+
spec: manifest.spec || {},
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
catch (error) {
|
|
225
|
+
console.log(`Failed to parse asset ${asset.id}:`, error);
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
_cleanupTempDir(tempDir) {
|
|
230
|
+
if (existsSync(tempDir)) {
|
|
231
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
146
232
|
}
|
|
147
233
|
}
|
|
148
234
|
_createBasicSubchart(subchartName, subchartDir) {
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
export const ENV_HELPERS = [
|
|
2
|
+
{
|
|
3
|
+
name: 'env.required',
|
|
4
|
+
template: `{{- $key := . -}}
|
|
5
|
+
{{- $value := index .Values.env $key -}}
|
|
6
|
+
{{- required (printf "Environment variable %s is required" $key) $value }}`,
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
name: 'env.isDev',
|
|
10
|
+
template: `{{- $env := .Values.environment | default "production" -}}
|
|
11
|
+
{{- or (eq $env "dev") (eq $env "development") }}`,
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: 'env.isProd',
|
|
15
|
+
template: `{{- $env := .Values.environment | default "production" -}}
|
|
16
|
+
{{- or (eq $env "prod") (eq $env "production") }}`,
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: 'env.isStaging',
|
|
20
|
+
template: `{{- $env := .Values.environment | default "production" -}}
|
|
21
|
+
{{- or (eq $env "staging") (eq $env "stage") }}`,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'env.isTest',
|
|
25
|
+
template: `{{- $env := .Values.environment | default "production" -}}
|
|
26
|
+
{{- or (eq $env "test") (eq $env "testing") }}`,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'config.merge',
|
|
30
|
+
template: `{{- $base := .base | default dict -}}
|
|
31
|
+
{{- $env := .env | default dict -}}
|
|
32
|
+
{{- $override := .override | default dict -}}
|
|
33
|
+
{{- merge $override $env $base | toJson }}`,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: 'config.secretRef',
|
|
37
|
+
template: `{{- if .fromSecret -}}
|
|
38
|
+
valueFrom:
|
|
39
|
+
secretKeyRef:
|
|
40
|
+
name: {{ .fromSecret.name }}
|
|
41
|
+
key: {{ .fromSecret.key }}
|
|
42
|
+
{{- if .fromSecret.optional }}
|
|
43
|
+
optional: true
|
|
44
|
+
{{- end }}
|
|
45
|
+
{{- else if .fromConfigMap -}}
|
|
46
|
+
valueFrom:
|
|
47
|
+
configMapKeyRef:
|
|
48
|
+
name: {{ .fromConfigMap.name }}
|
|
49
|
+
key: {{ .fromConfigMap.key }}
|
|
50
|
+
{{- if .fromConfigMap.optional }}
|
|
51
|
+
optional: true
|
|
52
|
+
{{- end }}
|
|
53
|
+
{{- else -}}
|
|
54
|
+
value: {{ .value | quote }}
|
|
55
|
+
{{- end }}`,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: 'config.envFromSource',
|
|
59
|
+
template: `{{- if .configMapRef -}}
|
|
60
|
+
configMapRef:
|
|
61
|
+
name: {{ .configMapRef.name }}
|
|
62
|
+
{{- if .configMapRef.optional }}
|
|
63
|
+
optional: true
|
|
64
|
+
{{- end }}
|
|
65
|
+
{{- else if .secretRef -}}
|
|
66
|
+
secretRef:
|
|
67
|
+
name: {{ .secretRef.name }}
|
|
68
|
+
{{- if .secretRef.optional }}
|
|
69
|
+
optional: true
|
|
70
|
+
{{- end }}
|
|
71
|
+
{{- end }}`,
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: 'config.featureFlag',
|
|
75
|
+
template: `{{- $flag := .flag -}}
|
|
76
|
+
{{- $default := .default | default false -}}
|
|
77
|
+
{{- $envKey := printf "FEATURE_%s" ($flag | upper) -}}
|
|
78
|
+
{{- $envFlag := index .Values.env $envKey | default "" -}}
|
|
79
|
+
{{- $valueFlag := index .Values.features $flag | default "" -}}
|
|
80
|
+
{{- if $valueFlag }}
|
|
81
|
+
{{- $valueFlag }}
|
|
82
|
+
{{- else if $envFlag }}
|
|
83
|
+
{{- $envFlag }}
|
|
84
|
+
{{- else }}
|
|
85
|
+
{{- $default }}
|
|
86
|
+
{{- end }}`,
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: 'config.debugMode',
|
|
90
|
+
template: `{{- $debug := .Values.debug | default (index .Values.env "DEBUG") | default false -}}
|
|
91
|
+
{{- if or $debug (include "env.isDev" .) -}}
|
|
92
|
+
true
|
|
93
|
+
{{- else -}}
|
|
94
|
+
false
|
|
95
|
+
{{- end }}`,
|
|
96
|
+
},
|
|
97
|
+
];
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
export const GITOPS_HELPERS = [
|
|
2
|
+
{
|
|
3
|
+
name: 'git.commitSha',
|
|
4
|
+
template: `{{- .Values.git.commitSha | default "unknown" }}`,
|
|
5
|
+
},
|
|
6
|
+
{
|
|
7
|
+
name: 'git.shortSha',
|
|
8
|
+
template: `{{- $sha := include "git.commitSha" . -}}
|
|
9
|
+
{{- if ne $sha "unknown" -}}
|
|
10
|
+
{{- $sha | trunc 8 -}}
|
|
11
|
+
{{- else -}}
|
|
12
|
+
unknown
|
|
13
|
+
{{- end }}`,
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
name: 'git.branch',
|
|
17
|
+
template: `{{- .Values.git.branch | default "main" }}`,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'git.tag',
|
|
21
|
+
template: `{{- .Values.git.tag | default "" }}`,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'git.repository',
|
|
25
|
+
template: `{{- .Values.git.repository | default "unknown/repository" }}`,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: 'image.tagWithSha',
|
|
29
|
+
template: `{{- $repo := .Values.image.repository -}}
|
|
30
|
+
{{- $sha := include "git.shortSha" . -}}
|
|
31
|
+
{{- printf "%s:%s" $repo $sha }}`,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: 'image.tagWithVersion',
|
|
35
|
+
template: `{{- $repo := .Values.image.repository -}}
|
|
36
|
+
{{- $tag := .Values.image.tag | default .Chart.AppVersion | default "latest" -}}
|
|
37
|
+
{{- printf "%s:%s" $repo $tag }}`,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: 'image.tagWithBranch',
|
|
41
|
+
template: `{{- $repo := .Values.image.repository -}}
|
|
42
|
+
{{- $branch := include "git.branch" . | replace "/" "-" | lower -}}
|
|
43
|
+
{{- printf "%s:%s" $repo $branch }}`,
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: 'ci.buildId',
|
|
47
|
+
template: `{{- .Values.ci.buildId | default "unknown" }}`,
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: 'ci.buildUrl',
|
|
51
|
+
template: `{{- .Values.ci.buildUrl | default "" }}`,
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: 'ci.jobUrl',
|
|
55
|
+
template: `{{- .Values.ci.jobUrl | default "" }}`,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: 'ci.runner',
|
|
59
|
+
template: `{{- .Values.ci.runner | default "unknown" }}`,
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: 'deploy.timestamp',
|
|
63
|
+
template: `{{- now | date "2006-01-02T15:04:05Z07:00" }}`,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: 'deploy.user',
|
|
67
|
+
template: `{{- .Values.deploy.user | default "automated" }}`,
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: 'deploy.annotations',
|
|
71
|
+
template: `deployment.kubernetes.io/revision: "{{ .Release.Revision }}"
|
|
72
|
+
app.kubernetes.io/version: "{{ .Chart.AppVersion }}"
|
|
73
|
+
app.kubernetes.io/part-of: "{{ .Values.application.name | default .Chart.Name }}"
|
|
74
|
+
git.commit: "{{ include "git.commitSha" . }}"
|
|
75
|
+
git.branch: "{{ include "git.branch" . }}"
|
|
76
|
+
git.repository: "{{ include "git.repository" . }}"
|
|
77
|
+
ci.build-id: "{{ include "ci.buildId" . }}"
|
|
78
|
+
ci.build-url: "{{ include "ci.buildUrl" . }}"
|
|
79
|
+
deploy.timestamp: "{{ include "deploy.timestamp" . }}"
|
|
80
|
+
deploy.user: "{{ include "deploy.user" . }}"`,
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: 'deploy.labels',
|
|
84
|
+
template: `app.kubernetes.io/version: "{{ .Chart.AppVersion }}"
|
|
85
|
+
app.kubernetes.io/component: "{{ .Values.component | default "application" }}"
|
|
86
|
+
app.kubernetes.io/part-of: "{{ .Values.application.name | default .Chart.Name }}"
|
|
87
|
+
git.branch: "{{ include "git.branch" . | replace "/" "-" | lower }}"
|
|
88
|
+
environment: "{{ .Values.environment | default "development" }}"`,
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: 'semver.parse',
|
|
92
|
+
template: `{{- $version := . -}}
|
|
93
|
+
{{- $parts := regexSplit "\\\\." $version -1 -}}
|
|
94
|
+
{{- if eq (len $parts) 3 -}}
|
|
95
|
+
{{- printf "{\\"major\\": %s, \\"minor\\": %s, \\"patch\\": %s}" (index $parts 0) (index $parts 1) (index $parts 2) -}}
|
|
96
|
+
{{- else -}}
|
|
97
|
+
{{- printf "{\\"major\\": 0, \\"minor\\": 0, \\"patch\\": 0}" -}}
|
|
98
|
+
{{- end }}`,
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: 'semver.bump',
|
|
102
|
+
template: `{{- $version := .version -}}
|
|
103
|
+
{{- $type := .type | default "patch" -}}
|
|
104
|
+
{{- $parts := regexSplit "\\\\." $version -1 -}}
|
|
105
|
+
{{- if eq (len $parts) 3 -}}
|
|
106
|
+
{{- $major := index $parts 0 | int -}}
|
|
107
|
+
{{- $minor := index $parts 1 | int -}}
|
|
108
|
+
{{- $patch := index $parts 2 | int -}}
|
|
109
|
+
{{- if eq $type "major" -}}
|
|
110
|
+
{{- printf "%d.0.0" (add $major 1) -}}
|
|
111
|
+
{{- else if eq $type "minor" -}}
|
|
112
|
+
{{- printf "%d.%d.0" $major (add $minor 1) -}}
|
|
113
|
+
{{- else -}}
|
|
114
|
+
{{- printf "%d.%d.%d" $major $minor (add $patch 1) -}}
|
|
115
|
+
{{- end -}}
|
|
116
|
+
{{- else -}}
|
|
117
|
+
{{- fail (printf "Invalid semantic version: %s" $version) -}}
|
|
118
|
+
{{- end }}`,
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: 'rollout.canaryWeight',
|
|
122
|
+
template: `{{- $weight := .Values.rollout.canary.weight | default 10 -}}
|
|
123
|
+
{{- $env := .Values.environment | default "development" -}}
|
|
124
|
+
{{- if eq $env "production" -}}
|
|
125
|
+
{{- min $weight 5 -}}
|
|
126
|
+
{{- else if eq $env "staging" -}}
|
|
127
|
+
{{- min $weight 50 -}}
|
|
128
|
+
{{- else -}}
|
|
129
|
+
{{- $weight -}}
|
|
130
|
+
{{- end }}`,
|
|
131
|
+
},
|
|
132
|
+
];
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type { HelperDefinition, HelperCategory, CloudProvider, HelperOptions } from './types.js';
|
|
2
|
+
export { ENV_HELPERS } from './envHelpers.js';
|
|
3
|
+
export { GITOPS_HELPERS } from './gitopsHelpers.js';
|
|
4
|
+
export { OBSERVABILITY_HELPERS } from './observabilityHelpers.js';
|
|
5
|
+
export { VALIDATION_HELPERS } from './validationHelpers.js';
|
|
6
|
+
import type { HelperDefinition, HelperCategory, HelperOptions } from './types.js';
|
|
7
|
+
export declare function getNewHelpersByCategory(category: HelperCategory): HelperDefinition[];
|
|
8
|
+
export declare function getAvailableHelperCategories(): HelperCategory[];
|
|
9
|
+
export declare function getHelpersByCategories(categories: HelperCategory[]): HelperDefinition[];
|
|
10
|
+
export declare function getHelpersByOptions(options: HelperOptions): HelperDefinition[];
|
|
11
|
+
export declare function formatNewHelpers(helpers: HelperDefinition[]): string;
|
|
12
|
+
export declare function generateNewHelpersTemplate(options?: HelperOptions, customHelpers?: HelperDefinition[]): string;
|
|
13
|
+
export declare function getCachedNewHelpersTemplate(options?: HelperOptions, customHelpers?: HelperDefinition[]): string;
|
|
14
|
+
export declare function createNewHelper(name: string, template: string): HelperDefinition;
|
|
15
|
+
export declare function validateHelperNames(helpers: HelperDefinition[]): void;
|
|
16
|
+
export declare function filterHelpersByPattern(helpers: HelperDefinition[], pattern: RegExp): HelperDefinition[];
|
|
17
|
+
export declare function getHelperStatistics(helpers: HelperDefinition[]): {
|
|
18
|
+
totalHelpers: number;
|
|
19
|
+
categoryCounts: Record<string, number>;
|
|
20
|
+
averageTemplateLength: number;
|
|
21
|
+
longestHelper: string;
|
|
22
|
+
shortestHelper: string;
|
|
23
|
+
};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
export { ENV_HELPERS } from './envHelpers.js';
|
|
2
|
+
export { GITOPS_HELPERS } from './gitopsHelpers.js';
|
|
3
|
+
export { OBSERVABILITY_HELPERS } from './observabilityHelpers.js';
|
|
4
|
+
export { VALIDATION_HELPERS } from './validationHelpers.js';
|
|
5
|
+
import { ENV_HELPERS } from './envHelpers.js';
|
|
6
|
+
import { GITOPS_HELPERS } from './gitopsHelpers.js';
|
|
7
|
+
import { OBSERVABILITY_HELPERS } from './observabilityHelpers.js';
|
|
8
|
+
import { VALIDATION_HELPERS } from './validationHelpers.js';
|
|
9
|
+
const HELPER_CATEGORIES = new Map([
|
|
10
|
+
['env', ENV_HELPERS],
|
|
11
|
+
['gitops', GITOPS_HELPERS],
|
|
12
|
+
['observability', OBSERVABILITY_HELPERS],
|
|
13
|
+
['validation', VALIDATION_HELPERS],
|
|
14
|
+
]);
|
|
15
|
+
const COMPILED_HELPERS_CACHE = new Map();
|
|
16
|
+
export function getNewHelpersByCategory(category) {
|
|
17
|
+
const helpers = HELPER_CATEGORIES.get(category);
|
|
18
|
+
if (!helpers) {
|
|
19
|
+
throw new Error(`Unknown helper category: ${category}`);
|
|
20
|
+
}
|
|
21
|
+
return [...helpers];
|
|
22
|
+
}
|
|
23
|
+
export function getAvailableHelperCategories() {
|
|
24
|
+
return Array.from(HELPER_CATEGORIES.keys());
|
|
25
|
+
}
|
|
26
|
+
export function getHelpersByCategories(categories) {
|
|
27
|
+
const helpers = [];
|
|
28
|
+
for (const category of categories) {
|
|
29
|
+
helpers.push(...getNewHelpersByCategory(category));
|
|
30
|
+
}
|
|
31
|
+
return helpers;
|
|
32
|
+
}
|
|
33
|
+
export function getHelpersByOptions(options) {
|
|
34
|
+
const helpers = [];
|
|
35
|
+
if (options.includeEnv) {
|
|
36
|
+
helpers.push(...ENV_HELPERS);
|
|
37
|
+
}
|
|
38
|
+
if (options.includeGitops) {
|
|
39
|
+
helpers.push(...GITOPS_HELPERS);
|
|
40
|
+
}
|
|
41
|
+
if (options.includeObservability) {
|
|
42
|
+
helpers.push(...OBSERVABILITY_HELPERS);
|
|
43
|
+
}
|
|
44
|
+
if (options.includeValidation) {
|
|
45
|
+
helpers.push(...VALIDATION_HELPERS);
|
|
46
|
+
}
|
|
47
|
+
return helpers;
|
|
48
|
+
}
|
|
49
|
+
export function formatNewHelpers(helpers) {
|
|
50
|
+
return helpers
|
|
51
|
+
.map((helper) => `{{/*
|
|
52
|
+
${helper.name}
|
|
53
|
+
*/}}
|
|
54
|
+
{{- define "${helper.name}" -}}
|
|
55
|
+
${helper.template}
|
|
56
|
+
{{- end }}`)
|
|
57
|
+
.join('\n\n');
|
|
58
|
+
}
|
|
59
|
+
export function generateNewHelpersTemplate(options, customHelpers) {
|
|
60
|
+
const helpers = [];
|
|
61
|
+
if (options) {
|
|
62
|
+
helpers.push(...getHelpersByOptions(options));
|
|
63
|
+
}
|
|
64
|
+
if (customHelpers) {
|
|
65
|
+
helpers.push(...customHelpers);
|
|
66
|
+
}
|
|
67
|
+
return formatNewHelpers(helpers);
|
|
68
|
+
}
|
|
69
|
+
export function getCachedNewHelpersTemplate(options, customHelpers) {
|
|
70
|
+
const cacheKey = JSON.stringify({ options, customHelpers });
|
|
71
|
+
if (COMPILED_HELPERS_CACHE.has(cacheKey)) {
|
|
72
|
+
return COMPILED_HELPERS_CACHE.get(cacheKey);
|
|
73
|
+
}
|
|
74
|
+
const template = generateNewHelpersTemplate(options, customHelpers);
|
|
75
|
+
COMPILED_HELPERS_CACHE.set(cacheKey, template);
|
|
76
|
+
return template;
|
|
77
|
+
}
|
|
78
|
+
export function createNewHelper(name, template) {
|
|
79
|
+
return { name, template };
|
|
80
|
+
}
|
|
81
|
+
export function validateHelperNames(helpers) {
|
|
82
|
+
const namePattern = /^[a-zA-Z][a-zA-Z0-9._-]*$/;
|
|
83
|
+
const duplicates = new Set();
|
|
84
|
+
const seen = new Set();
|
|
85
|
+
for (const helper of helpers) {
|
|
86
|
+
if (!namePattern.test(helper.name)) {
|
|
87
|
+
throw new Error(`Invalid helper name: "${helper.name}". Names must start with a letter and contain only letters, numbers, dots, underscores, and hyphens.`);
|
|
88
|
+
}
|
|
89
|
+
if (seen.has(helper.name)) {
|
|
90
|
+
duplicates.add(helper.name);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
seen.add(helper.name);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (duplicates.size > 0) {
|
|
97
|
+
throw new Error(`Duplicate helper names found: ${Array.from(duplicates).join(', ')}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
export function filterHelpersByPattern(helpers, pattern) {
|
|
101
|
+
return helpers.filter((helper) => pattern.test(helper.name));
|
|
102
|
+
}
|
|
103
|
+
export function getHelperStatistics(helpers) {
|
|
104
|
+
const categoryMap = new Map();
|
|
105
|
+
let totalTemplateLength = 0;
|
|
106
|
+
let longestHelper = '';
|
|
107
|
+
let shortestHelper = '';
|
|
108
|
+
let longestLength = 0;
|
|
109
|
+
let shortestLength = Infinity;
|
|
110
|
+
for (const helper of helpers) {
|
|
111
|
+
const category = helper.name.split('.')[0] || 'unknown';
|
|
112
|
+
const currentCount = categoryMap.get(category) || 0;
|
|
113
|
+
categoryMap.set(category, currentCount + 1);
|
|
114
|
+
const templateLength = helper.template.length;
|
|
115
|
+
totalTemplateLength += templateLength;
|
|
116
|
+
if (templateLength > longestLength) {
|
|
117
|
+
longestLength = templateLength;
|
|
118
|
+
longestHelper = helper.name;
|
|
119
|
+
}
|
|
120
|
+
if (templateLength < shortestLength) {
|
|
121
|
+
shortestLength = templateLength;
|
|
122
|
+
shortestHelper = helper.name;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
totalHelpers: helpers.length,
|
|
127
|
+
categoryCounts: Object.fromEntries(categoryMap),
|
|
128
|
+
averageTemplateLength: helpers.length > 0 ? Math.round(totalTemplateLength / helpers.length) : 0,
|
|
129
|
+
longestHelper,
|
|
130
|
+
shortestHelper,
|
|
131
|
+
};
|
|
132
|
+
}
|