timonel 3.1.1 → 3.1.2
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 +7 -0
- package/README.md +323 -695
- package/dist/cli.js +275 -15
- package/dist/index.d.ts +5 -1
- package/dist/index.js +12 -0
- package/dist/lib/helm.d.ts +471 -0
- package/dist/lib/helm.js +483 -0
- package/dist/lib/helmChartWriter.d.ts +157 -0
- package/dist/lib/helmChartWriter.js +171 -1
- package/dist/lib/policy/configurationLoader.d.ts +132 -0
- package/dist/lib/policy/configurationLoader.js +132 -0
- package/dist/lib/policy/errorContextGenerator.d.ts +89 -0
- package/dist/lib/policy/errorContextGenerator.js +99 -2
- package/dist/lib/policy/errors.d.ts +35 -0
- package/dist/lib/policy/errors.js +36 -0
- package/dist/lib/policy/index.d.ts +9 -0
- package/dist/lib/policy/index.js +16 -0
- package/dist/lib/policy/parallelExecutor.d.ts +90 -0
- package/dist/lib/policy/parallelExecutor.js +86 -3
- package/dist/lib/policy/pluginLoader.d.ts +92 -0
- package/dist/lib/policy/pluginLoader.js +92 -1
- package/dist/lib/policy/pluginRegistry.d.ts +54 -0
- package/dist/lib/policy/pluginRegistry.js +56 -0
- package/dist/lib/policy/policyEngine.d.ts +137 -0
- package/dist/lib/policy/policyEngine.js +191 -5
- package/dist/lib/policy/resultAggregator.d.ts +46 -0
- package/dist/lib/policy/resultAggregator.js +69 -1
- package/dist/lib/policy/resultFormatter.d.ts +88 -0
- package/dist/lib/policy/resultFormatter.js +101 -0
- package/dist/lib/policy/types.d.ts +136 -0
- package/dist/lib/policy/types.js +8 -0
- package/dist/lib/policy/validationCache.d.ts +146 -0
- package/dist/lib/policy/validationCache.js +142 -6
- package/dist/lib/resources/baseResourceProvider.d.ts +45 -0
- package/dist/lib/resources/baseResourceProvider.js +48 -1
- package/dist/lib/resources/cloud/aws/awsResources.d.ts +192 -0
- package/dist/lib/resources/cloud/aws/awsResources.js +163 -1
- package/dist/lib/resources/cloud/aws/karpenterResources.d.ts +131 -0
- package/dist/lib/resources/cloud/aws/karpenterResources.js +77 -0
- package/dist/lib/rutter.d.ts +381 -3
- package/dist/lib/rutter.js +439 -28
- package/dist/lib/security.d.ts +123 -0
- package/dist/lib/security.js +162 -4
- package/dist/lib/templates/flexible-subchart.d.ts +52 -0
- package/dist/lib/templates/flexible-subchart.js +70 -0
- package/dist/lib/templates/umbrella-chart.d.ts +27 -0
- package/dist/lib/templates/umbrella-chart.js +89 -0
- package/dist/lib/types.d.ts +26 -0
- package/dist/lib/umbrella.d.ts +23 -0
- package/dist/lib/umbrella.js +23 -0
- package/dist/lib/umbrellaRutter.d.ts +75 -0
- package/dist/lib/umbrellaRutter.js +82 -2
- package/dist/lib/utils/envVarsLoader.d.ts +49 -0
- package/dist/lib/utils/envVarsLoader.js +53 -0
- package/dist/lib/utils/helmConstructSerializer.d.ts +17 -0
- package/dist/lib/utils/helmConstructSerializer.js +22 -0
- package/dist/lib/utils/helmControlStructures.d.ts +194 -0
- package/dist/lib/utils/helmControlStructures.js +180 -0
- package/dist/lib/utils/helmHelpers/envHelpers.d.ts +13 -0
- package/dist/lib/utils/helmHelpers/envHelpers.js +13 -0
- package/dist/lib/utils/helmHelpers/gitopsHelpers.d.ts +13 -0
- package/dist/lib/utils/helmHelpers/gitopsHelpers.js +13 -0
- package/dist/lib/utils/helmHelpers/index.d.ts +74 -0
- package/dist/lib/utils/helmHelpers/index.js +85 -1
- package/dist/lib/utils/helmHelpers/observabilityHelpers.d.ts +13 -0
- package/dist/lib/utils/helmHelpers/observabilityHelpers.js +13 -0
- package/dist/lib/utils/helmHelpers/types.d.ts +23 -0
- package/dist/lib/utils/helmHelpers/types.js +4 -0
- package/dist/lib/utils/helmHelpers/validationHelpers.d.ts +13 -0
- package/dist/lib/utils/helmHelpers/validationHelpers.js +13 -0
- package/dist/lib/utils/helmHelpers.d.ts +62 -0
- package/dist/lib/utils/helmHelpers.js +77 -0
- package/dist/lib/utils/helmYamlSerializer.d.ts +77 -0
- package/dist/lib/utils/helmYamlSerializer.js +398 -21
- package/dist/lib/utils/logger.d.ts +153 -0
- package/dist/lib/utils/logger.js +170 -2
- package/dist/lib/utils/valuesRef.d.ts +181 -50
- package/dist/lib/utils/valuesRef.js +168 -170
- package/dist/lib/validation/inputValidator.d.ts +45 -0
- package/dist/lib/validation/inputValidator.js +67 -2
- package/dist/types/index.d.ts +34 -0
- package/dist/types/index.js +3 -0
- package/package.json +31 -38
|
@@ -1,26 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview UmbrellaRutter class for managing Helm umbrella charts with multiple subcharts
|
|
3
|
+
* @since 2.8.0+
|
|
4
|
+
*/
|
|
1
5
|
import type { HelmChartMeta } from './helmChartWriter.js';
|
|
2
6
|
import type { Rutter } from './rutter.js';
|
|
3
7
|
import { type TimonelLogger } from './utils/logger.js';
|
|
8
|
+
/**
|
|
9
|
+
* Configuration for a subchart within an umbrella chart
|
|
10
|
+
*
|
|
11
|
+
* @since 2.8.0+
|
|
12
|
+
*/
|
|
4
13
|
export interface SubchartSpec {
|
|
14
|
+
/** Name of the subchart */
|
|
5
15
|
name: string;
|
|
16
|
+
/** Rutter instance that generates the subchart */
|
|
6
17
|
rutter: Rutter;
|
|
18
|
+
/** Version of the subchart (optional) */
|
|
7
19
|
version?: string;
|
|
20
|
+
/** Helm condition for enabling/disabling the subchart */
|
|
8
21
|
condition?: string;
|
|
22
|
+
/** Tags for grouping subcharts */
|
|
9
23
|
tags?: string[];
|
|
24
|
+
/** Repository URL for the subchart */
|
|
10
25
|
repository?: string;
|
|
11
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Configuration properties for UmbrellaRutter
|
|
29
|
+
*
|
|
30
|
+
* @since 2.8.0+
|
|
31
|
+
*/
|
|
12
32
|
export interface UmbrellaRutterProps {
|
|
33
|
+
/** Metadata for the umbrella chart */
|
|
13
34
|
meta: HelmChartMeta;
|
|
35
|
+
/** Array of subchart specifications */
|
|
14
36
|
subcharts: SubchartSpec[];
|
|
37
|
+
/** Default values for the umbrella chart */
|
|
15
38
|
defaultValues?: Record<string, unknown>;
|
|
39
|
+
/**
|
|
40
|
+
* Custom logger instance
|
|
41
|
+
* @since 2.13.0
|
|
42
|
+
*/
|
|
16
43
|
logger?: TimonelLogger;
|
|
44
|
+
/** Environment-specific values */
|
|
17
45
|
envValues?: Record<string, Record<string, unknown>>;
|
|
18
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* UmbrellaRutter manages multiple Rutter instances as subcharts
|
|
49
|
+
* to create Helm umbrella charts with dependencies.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```typescript
|
|
53
|
+
* const umbrella = new UmbrellaRutter({
|
|
54
|
+
* meta: { name: 'my-app', version: '1.0.0' },
|
|
55
|
+
* subcharts: [
|
|
56
|
+
* { name: 'frontend', rutter: frontendChart },
|
|
57
|
+
* { name: 'backend', rutter: backendChart }
|
|
58
|
+
* ]
|
|
59
|
+
* });
|
|
60
|
+
*
|
|
61
|
+
* umbrella.write('./my-app');
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @since 2.8.0+
|
|
65
|
+
*/
|
|
19
66
|
export declare class UmbrellaRutter {
|
|
20
67
|
private readonly props;
|
|
21
68
|
private readonly logger;
|
|
69
|
+
/**
|
|
70
|
+
* Creates a new UmbrellaRutter instance
|
|
71
|
+
*
|
|
72
|
+
* @param props - Configuration properties for the umbrella chart
|
|
73
|
+
* @throws {Error} If chart metadata is invalid
|
|
74
|
+
*
|
|
75
|
+
* @since 2.8.0+
|
|
76
|
+
*/
|
|
22
77
|
constructor(props: UmbrellaRutterProps);
|
|
23
78
|
private validateMetadata;
|
|
79
|
+
/**
|
|
80
|
+
* Write the umbrella chart with all subcharts to the output directory
|
|
81
|
+
*
|
|
82
|
+
* Creates the complete umbrella chart structure including:
|
|
83
|
+
* - Parent Chart.yaml with dependencies
|
|
84
|
+
* - Parent values.yaml with global and subchart values
|
|
85
|
+
* - Individual subchart directories under charts/
|
|
86
|
+
* - NOTES.txt template
|
|
87
|
+
*
|
|
88
|
+
* @param outDir - Output directory path for the umbrella chart
|
|
89
|
+
* @returns Promise that resolves when the chart is written
|
|
90
|
+
* @throws {Error} If output directory path is invalid
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* await umbrella.write('./dist/my-umbrella-chart');
|
|
95
|
+
* ```
|
|
96
|
+
*
|
|
97
|
+
* @since 2.8.0+
|
|
98
|
+
*/
|
|
24
99
|
write(outDir: string): Promise<void>;
|
|
25
100
|
private writeParentChart;
|
|
26
101
|
private writeParentValues;
|
|
@@ -1,9 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview UmbrellaRutter class for managing Helm umbrella charts with multiple subcharts
|
|
3
|
+
* @since 2.8.0+
|
|
4
|
+
*/
|
|
1
5
|
import { writeFileSync, mkdirSync } from 'fs';
|
|
2
6
|
import { join } from 'path';
|
|
3
7
|
import { createLogger } from './utils/logger.js';
|
|
4
8
|
import { SecurityUtils } from './security.js';
|
|
5
9
|
import { dumpHelmAwareYaml } from './utils/helmYamlSerializer.js';
|
|
10
|
+
/**
|
|
11
|
+
* UmbrellaRutter manages multiple Rutter instances as subcharts
|
|
12
|
+
* to create Helm umbrella charts with dependencies.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const umbrella = new UmbrellaRutter({
|
|
17
|
+
* meta: { name: 'my-app', version: '1.0.0' },
|
|
18
|
+
* subcharts: [
|
|
19
|
+
* { name: 'frontend', rutter: frontendChart },
|
|
20
|
+
* { name: 'backend', rutter: backendChart }
|
|
21
|
+
* ]
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* umbrella.write('./my-app');
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @since 2.8.0+
|
|
28
|
+
*/
|
|
6
29
|
export class UmbrellaRutter {
|
|
30
|
+
/**
|
|
31
|
+
* Creates a new UmbrellaRutter instance
|
|
32
|
+
*
|
|
33
|
+
* @param props - Configuration properties for the umbrella chart
|
|
34
|
+
* @throws {Error} If chart metadata is invalid
|
|
35
|
+
*
|
|
36
|
+
* @since 2.8.0+
|
|
37
|
+
*/
|
|
7
38
|
constructor(props) {
|
|
8
39
|
this.logger = props.logger ?? createLogger('umbrella-rutter');
|
|
9
40
|
this.logger.info('Initializing umbrella chart', {
|
|
@@ -11,39 +42,75 @@ export class UmbrellaRutter {
|
|
|
11
42
|
version: props.meta.version,
|
|
12
43
|
subchartsCount: props.subcharts.length,
|
|
13
44
|
});
|
|
45
|
+
// Validate chart metadata
|
|
14
46
|
this.validateMetadata(props.meta);
|
|
15
47
|
this.props = props;
|
|
16
48
|
}
|
|
17
49
|
validateMetadata(meta) {
|
|
50
|
+
// Validate chart name follows Helm conventions
|
|
51
|
+
// eslint-disable-next-line security/detect-unsafe-regex -- Safe regex for chart name validation
|
|
18
52
|
if (!/^[a-z0-9]([-a-z0-9]*[a-z0-9])?$/.test(meta.name)) {
|
|
19
53
|
throw new Error('Chart name must contain only lowercase letters, numbers, and dashes');
|
|
20
54
|
}
|
|
55
|
+
// Validate semantic versioning
|
|
56
|
+
// eslint-disable-next-line security/detect-unsafe-regex -- Safe regex for semver validation
|
|
21
57
|
if (!/^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/.test(meta.version)) {
|
|
22
58
|
throw new Error('Chart version must follow semantic versioning (e.g., 1.0.0)');
|
|
23
59
|
}
|
|
24
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Write the umbrella chart with all subcharts to the output directory
|
|
63
|
+
*
|
|
64
|
+
* Creates the complete umbrella chart structure including:
|
|
65
|
+
* - Parent Chart.yaml with dependencies
|
|
66
|
+
* - Parent values.yaml with global and subchart values
|
|
67
|
+
* - Individual subchart directories under charts/
|
|
68
|
+
* - NOTES.txt template
|
|
69
|
+
*
|
|
70
|
+
* @param outDir - Output directory path for the umbrella chart
|
|
71
|
+
* @returns Promise that resolves when the chart is written
|
|
72
|
+
* @throws {Error} If output directory path is invalid
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* await umbrella.write('./dist/my-umbrella-chart');
|
|
77
|
+
* ```
|
|
78
|
+
*
|
|
79
|
+
* @since 2.8.0+
|
|
80
|
+
*/
|
|
25
81
|
async write(outDir) {
|
|
82
|
+
// Validate output directory path
|
|
26
83
|
const validatedOutDir = SecurityUtils.validatePath(outDir, process.cwd(), {
|
|
27
84
|
allowAbsolute: true,
|
|
28
85
|
});
|
|
86
|
+
// Create output directory structure
|
|
87
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- validated path
|
|
29
88
|
mkdirSync(validatedOutDir, { recursive: true });
|
|
30
89
|
const chartsDir = SecurityUtils.validatePath(join(validatedOutDir, 'charts'), process.cwd(), {
|
|
31
90
|
allowAbsolute: true,
|
|
32
91
|
});
|
|
92
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- validated path
|
|
33
93
|
mkdirSync(chartsDir, { recursive: true });
|
|
94
|
+
// Write each subchart to charts/ directory
|
|
34
95
|
for (const subchart of this.props.subcharts) {
|
|
96
|
+
// Validate subchart name using centralized validation
|
|
35
97
|
if (!SecurityUtils.isValidSubchartName(subchart.name)) {
|
|
36
98
|
throw new Error(`Invalid subchart name: ${SecurityUtils.sanitizeLogMessage(subchart.name)}`);
|
|
37
99
|
}
|
|
38
|
-
const sanitizedName = subchart.name;
|
|
100
|
+
const sanitizedName = subchart.name; // Already validated by SecurityUtils
|
|
39
101
|
const subchartDir = SecurityUtils.validatePath(join(validatedOutDir, 'charts', sanitizedName), process.cwd(), { allowAbsolute: true });
|
|
40
102
|
await subchart.rutter.write(subchartDir);
|
|
41
103
|
}
|
|
104
|
+
// Generate parent Chart.yaml with dependencies
|
|
42
105
|
this.writeParentChart(validatedOutDir);
|
|
106
|
+
// Generate parent values.yaml
|
|
43
107
|
this.writeParentValues(validatedOutDir);
|
|
108
|
+
// Generate empty templates directory (umbrella charts typically don't have templates)
|
|
44
109
|
const templatesDir = SecurityUtils.validatePath(join(validatedOutDir, 'templates'), process.cwd(), { allowAbsolute: true });
|
|
110
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- validated path
|
|
45
111
|
mkdirSync(templatesDir, { recursive: true });
|
|
46
112
|
const notesPath = SecurityUtils.validatePath(join(validatedOutDir, 'templates', 'NOTES.txt'), process.cwd(), { allowAbsolute: true });
|
|
113
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- validated path
|
|
47
114
|
writeFileSync(notesPath, this.generateNotesTemplate());
|
|
48
115
|
}
|
|
49
116
|
writeParentChart(outDir) {
|
|
@@ -59,6 +126,7 @@ export class UmbrellaRutter {
|
|
|
59
126
|
sources: this.props.meta.sources,
|
|
60
127
|
maintainers: this.props.meta.maintainers,
|
|
61
128
|
dependencies: this.props.subcharts.map((subchart) => {
|
|
129
|
+
// Subchart name already validated in write() method
|
|
62
130
|
return {
|
|
63
131
|
name: subchart.name,
|
|
64
132
|
version: subchart.version || '0.1.0',
|
|
@@ -71,13 +139,17 @@ export class UmbrellaRutter {
|
|
|
71
139
|
const chartYamlPath = SecurityUtils.validatePath(join(outDir, 'Chart.yaml'), process.cwd(), {
|
|
72
140
|
allowAbsolute: true,
|
|
73
141
|
});
|
|
142
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- validated path
|
|
74
143
|
writeFileSync(chartYamlPath, dumpHelmAwareYaml(chartYaml));
|
|
75
144
|
}
|
|
76
145
|
writeParentValues(outDir) {
|
|
77
146
|
const values = {
|
|
147
|
+
// Global values that can be shared across subcharts
|
|
78
148
|
global: {},
|
|
149
|
+
// Individual subchart values
|
|
79
150
|
...this.props.defaultValues,
|
|
80
151
|
};
|
|
152
|
+
// Add subchart-specific value sections
|
|
81
153
|
for (const subchart of this.props.subcharts) {
|
|
82
154
|
if (!(subchart.name in values)) {
|
|
83
155
|
values[subchart.name] = {
|
|
@@ -88,12 +160,16 @@ export class UmbrellaRutter {
|
|
|
88
160
|
const valuesYamlPath = SecurityUtils.validatePath(join(outDir, 'values.yaml'), process.cwd(), {
|
|
89
161
|
allowAbsolute: true,
|
|
90
162
|
});
|
|
163
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- validated path
|
|
91
164
|
writeFileSync(valuesYamlPath, dumpHelmAwareYaml(values));
|
|
165
|
+
// Write environment-specific values files
|
|
92
166
|
if (this.props.envValues) {
|
|
93
167
|
for (const [env, envVals] of Object.entries(this.props.envValues)) {
|
|
168
|
+
// Use centralized environment name sanitization
|
|
94
169
|
const sanitizedEnv = SecurityUtils.sanitizeEnvironmentName(env);
|
|
95
170
|
const envValues = this.deepMerge(values, envVals);
|
|
96
171
|
const envValuesPath = SecurityUtils.validatePath(join(outDir, `values-${sanitizedEnv}.yaml`), process.cwd(), { allowAbsolute: true });
|
|
172
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- validated path
|
|
97
173
|
writeFileSync(envValuesPath, dumpHelmAwareYaml(envValues));
|
|
98
174
|
}
|
|
99
175
|
}
|
|
@@ -102,9 +178,13 @@ export class UmbrellaRutter {
|
|
|
102
178
|
const result = { ...target };
|
|
103
179
|
for (const [key, value] of Object.entries(source)) {
|
|
104
180
|
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
105
|
-
|
|
181
|
+
// eslint-disable-next-line security/detect-object-injection -- Safe object property access in deep merge
|
|
182
|
+
result[key] = this.deepMerge(
|
|
183
|
+
// eslint-disable-next-line security/detect-object-injection -- Safe object property access in deep merge
|
|
184
|
+
result[key] || {}, value);
|
|
106
185
|
}
|
|
107
186
|
else {
|
|
187
|
+
// eslint-disable-next-line security/detect-object-injection -- Safe object property access in deep merge
|
|
108
188
|
result[key] = value;
|
|
109
189
|
}
|
|
110
190
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment variable configuration
|
|
3
|
+
*/
|
|
1
4
|
export interface EnvVarConfig {
|
|
2
5
|
name: string;
|
|
3
6
|
type: 'value' | 'secret';
|
|
@@ -5,15 +8,61 @@ export interface EnvVarConfig {
|
|
|
5
8
|
defaultValue?: string;
|
|
6
9
|
secretName?: string;
|
|
7
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Options for loading environment variables
|
|
13
|
+
*/
|
|
8
14
|
export interface LoadEnvVarsOptions {
|
|
9
15
|
configPath?: string;
|
|
10
16
|
defaultScope?: string;
|
|
11
17
|
fallbackConfig?: EnvVarConfig[];
|
|
12
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Load environment variables from YAML or JSON file
|
|
21
|
+
*
|
|
22
|
+
* @param options - Configuration options
|
|
23
|
+
* @returns Array of environment variable configurations
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* const envVars = loadEnvVarsConfig({
|
|
28
|
+
* configPath: './env-config.yaml',
|
|
29
|
+
* defaultScope: 'global.env'
|
|
30
|
+
* });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
13
33
|
export declare function loadEnvVarsConfig(options?: LoadEnvVarsOptions): EnvVarConfig[];
|
|
34
|
+
/**
|
|
35
|
+
* Generate Kubernetes environment variables from configuration
|
|
36
|
+
*
|
|
37
|
+
* @param config - Array of environment variable configurations
|
|
38
|
+
* @param options - Generation options
|
|
39
|
+
* @returns Array of Kubernetes env var objects
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* const envVars = generateEnvVars(config, { defaultScope: 'global.env' });
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
14
46
|
export declare function generateEnvVars(config: EnvVarConfig[], options?: {
|
|
15
47
|
defaultScope?: string;
|
|
16
48
|
}): Array<Record<string, unknown>>;
|
|
49
|
+
/**
|
|
50
|
+
* Convenience function to load and generate env vars in one step
|
|
51
|
+
*
|
|
52
|
+
* @param options - Combined load and generate options
|
|
53
|
+
* @returns Array of Kubernetes env var objects
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const envVars = loadAndGenerateEnvVars({
|
|
58
|
+
* configPath: './env-config.yaml',
|
|
59
|
+
* defaultScope: 'global.env',
|
|
60
|
+
* fallbackConfig: [
|
|
61
|
+
* { name: 'VERSION', type: 'value', defaultValue: '1.0.0' }
|
|
62
|
+
* ]
|
|
63
|
+
* });
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
17
66
|
export declare function loadAndGenerateEnvVars(options?: LoadEnvVarsOptions & {
|
|
18
67
|
defaultScope?: string;
|
|
19
68
|
}): Array<Record<string, unknown>>;
|
|
@@ -3,35 +3,70 @@ import { join } from 'path';
|
|
|
3
3
|
import { parse as parseYaml } from 'yaml';
|
|
4
4
|
import { SecurityUtils } from '../security.js';
|
|
5
5
|
import { createHelmExpression } from './helmControlStructures.js';
|
|
6
|
+
/**
|
|
7
|
+
* Load environment variables from YAML or JSON file
|
|
8
|
+
*
|
|
9
|
+
* @param options - Configuration options
|
|
10
|
+
* @returns Array of environment variable configurations
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const envVars = loadEnvVarsConfig({
|
|
15
|
+
* configPath: './env-config.yaml',
|
|
16
|
+
* defaultScope: 'global.env'
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
6
20
|
export function loadEnvVarsConfig(options = {}) {
|
|
7
21
|
const { configPath, fallbackConfig = [] } = options;
|
|
8
22
|
try {
|
|
23
|
+
// If specific path provided, use it
|
|
9
24
|
if (configPath) {
|
|
10
25
|
const validatedConfigPath = SecurityUtils.validatePath(configPath, process.cwd(), {
|
|
11
26
|
allowAbsolute: true,
|
|
12
27
|
});
|
|
28
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- validated path
|
|
13
29
|
if (existsSync(validatedConfigPath)) {
|
|
30
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- validated path
|
|
14
31
|
const data = readFileSync(validatedConfigPath, 'utf-8');
|
|
15
32
|
return validatedConfigPath.endsWith('.yaml') || validatedConfigPath.endsWith('.yml')
|
|
16
33
|
? parseYaml(data)
|
|
17
34
|
: JSON.parse(data);
|
|
18
35
|
}
|
|
19
36
|
}
|
|
37
|
+
// Try default locations
|
|
20
38
|
const yamlPath = SecurityUtils.validatePath(join(process.cwd(), 'env-config.yaml'), process.cwd(), { allowAbsolute: true });
|
|
39
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- validated path
|
|
21
40
|
if (existsSync(yamlPath)) {
|
|
41
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- validated path
|
|
22
42
|
const data = readFileSync(yamlPath, 'utf-8');
|
|
23
43
|
return parseYaml(data);
|
|
24
44
|
}
|
|
25
45
|
const jsonPath = SecurityUtils.validatePath(join(process.cwd(), 'env-config.json'), process.cwd(), { allowAbsolute: true });
|
|
46
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- validated path
|
|
26
47
|
if (existsSync(jsonPath)) {
|
|
48
|
+
// eslint-disable-next-line security/detect-non-literal-fs-filename -- validated path
|
|
27
49
|
const data = readFileSync(jsonPath, 'utf-8');
|
|
28
50
|
return JSON.parse(data);
|
|
29
51
|
}
|
|
30
52
|
}
|
|
31
53
|
catch {
|
|
54
|
+
// Fall through to fallback
|
|
32
55
|
}
|
|
33
56
|
return fallbackConfig;
|
|
34
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Generate Kubernetes environment variables from configuration
|
|
60
|
+
*
|
|
61
|
+
* @param config - Array of environment variable configurations
|
|
62
|
+
* @param options - Generation options
|
|
63
|
+
* @returns Array of Kubernetes env var objects
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* const envVars = generateEnvVars(config, { defaultScope: 'global.env' });
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
35
70
|
export function generateEnvVars(config, options = {}) {
|
|
36
71
|
const { defaultScope = 'global.env' } = options;
|
|
37
72
|
return config.map((item) => {
|
|
@@ -43,6 +78,7 @@ export function generateEnvVars(config, options = {}) {
|
|
|
43
78
|
};
|
|
44
79
|
}
|
|
45
80
|
else {
|
|
81
|
+
// Secret reference
|
|
46
82
|
return {
|
|
47
83
|
name: item.name,
|
|
48
84
|
valueFrom: {
|
|
@@ -56,6 +92,23 @@ export function generateEnvVars(config, options = {}) {
|
|
|
56
92
|
}
|
|
57
93
|
});
|
|
58
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Convenience function to load and generate env vars in one step
|
|
97
|
+
*
|
|
98
|
+
* @param options - Combined load and generate options
|
|
99
|
+
* @returns Array of Kubernetes env var objects
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* const envVars = loadAndGenerateEnvVars({
|
|
104
|
+
* configPath: './env-config.yaml',
|
|
105
|
+
* defaultScope: 'global.env',
|
|
106
|
+
* fallbackConfig: [
|
|
107
|
+
* { name: 'VERSION', type: 'value', defaultValue: '1.0.0' }
|
|
108
|
+
* ]
|
|
109
|
+
* });
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
59
112
|
export function loadAndGenerateEnvVars(options = {}) {
|
|
60
113
|
const config = loadEnvVarsConfig(options);
|
|
61
114
|
const genOptions = options.defaultScope ? { defaultScope: options.defaultScope } : {};
|
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Helm construct serialization utilities
|
|
3
|
+
* Converts HelmConstruct objects into Helm template syntax
|
|
4
|
+
* @since 2.14.0
|
|
5
|
+
*/
|
|
1
6
|
import type { HelmConstruct, HelmContent } from './helmControlStructures.js';
|
|
7
|
+
/**
|
|
8
|
+
* Serialize a HelmConstruct object into Helm template syntax
|
|
9
|
+
* @param construct The HelmConstruct to serialize
|
|
10
|
+
* @param indent Current indentation level
|
|
11
|
+
* @returns Helm template string
|
|
12
|
+
*/
|
|
2
13
|
export declare function serializeHelmConstruct(construct: HelmConstruct, indent?: number): string;
|
|
14
|
+
/**
|
|
15
|
+
* Serialize HelmContent (which can be primitives, objects, arrays, or HelmConstructs)
|
|
16
|
+
* @param content The content to serialize
|
|
17
|
+
* @param indent Current indentation level
|
|
18
|
+
* @returns Serialized string
|
|
19
|
+
*/
|
|
3
20
|
export declare function serializeHelmContent(content: HelmContent, indent?: number): string;
|
|
@@ -1,4 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Helm construct serialization utilities
|
|
3
|
+
* Converts HelmConstruct objects into Helm template syntax
|
|
4
|
+
* @since 2.14.0
|
|
5
|
+
*/
|
|
1
6
|
import { isHelmConstruct } from './helmControlStructures.js';
|
|
7
|
+
/**
|
|
8
|
+
* Serialize a HelmConstruct object into Helm template syntax
|
|
9
|
+
* @param construct The HelmConstruct to serialize
|
|
10
|
+
* @param indent Current indentation level
|
|
11
|
+
* @returns Helm template string
|
|
12
|
+
*/
|
|
2
13
|
export function serializeHelmConstruct(construct, indent = 0) {
|
|
3
14
|
const trimLeft = construct.options?.trimLeft ?? true;
|
|
4
15
|
const trimRight = construct.options?.trimRight ?? true;
|
|
@@ -20,17 +31,26 @@ export function serializeHelmConstruct(construct, indent = 0) {
|
|
|
20
31
|
throw new Error(`Unknown Helm construct type: ${construct.type}`);
|
|
21
32
|
}
|
|
22
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Serialize HelmContent (which can be primitives, objects, arrays, or HelmConstructs)
|
|
36
|
+
* @param content The content to serialize
|
|
37
|
+
* @param indent Current indentation level
|
|
38
|
+
* @returns Serialized string
|
|
39
|
+
*/
|
|
23
40
|
export function serializeHelmContent(content, indent = 0) {
|
|
24
41
|
const indentStr = ' '.repeat(indent);
|
|
42
|
+
// Handle HelmConstruct
|
|
25
43
|
if (isHelmConstruct(content)) {
|
|
26
44
|
return serializeHelmConstruct(content, indent);
|
|
27
45
|
}
|
|
46
|
+
// Handle primitives
|
|
28
47
|
if (content === null || content === undefined) {
|
|
29
48
|
return '';
|
|
30
49
|
}
|
|
31
50
|
if (typeof content === 'string' || typeof content === 'number' || typeof content === 'boolean') {
|
|
32
51
|
return String(content);
|
|
33
52
|
}
|
|
53
|
+
// Handle arrays
|
|
34
54
|
if (Array.isArray(content)) {
|
|
35
55
|
return content
|
|
36
56
|
.map((item) => {
|
|
@@ -41,6 +61,7 @@ export function serializeHelmContent(content, indent = 0) {
|
|
|
41
61
|
})
|
|
42
62
|
.join('\n');
|
|
43
63
|
}
|
|
64
|
+
// Handle objects (convert to YAML)
|
|
44
65
|
if (typeof content === 'object') {
|
|
45
66
|
const lines = [];
|
|
46
67
|
for (const [key, value] of Object.entries(content)) {
|
|
@@ -52,6 +73,7 @@ export function serializeHelmContent(content, indent = 0) {
|
|
|
52
73
|
lines.push(serializeHelmContent(value, indent + 1));
|
|
53
74
|
}
|
|
54
75
|
else {
|
|
76
|
+
// Generic Object Injection Sink /* eslint-disable-next-line security/detect-object-injection */
|
|
55
77
|
lines.push(`${indentStr}${key}: ${value}`);
|
|
56
78
|
}
|
|
57
79
|
}
|