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,5 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Loader
|
|
3
|
+
*
|
|
4
|
+
* This module provides configuration loading and validation for policy plugins.
|
|
5
|
+
* It supports environment-specific configuration, schema validation, and
|
|
6
|
+
* configuration inheritance.
|
|
7
|
+
*
|
|
8
|
+
* @since 3.0.0
|
|
9
|
+
*/
|
|
1
10
|
import { createLogger } from '../utils/logger.js';
|
|
2
11
|
import { PluginConfigurationError } from './errors.js';
|
|
12
|
+
/**
|
|
13
|
+
* Default configuration loader options
|
|
14
|
+
*/
|
|
3
15
|
const DEFAULT_LOADER_OPTIONS = {
|
|
4
16
|
defaultEnvironment: 'development',
|
|
5
17
|
validateSchemas: true,
|
|
@@ -7,12 +19,18 @@ const DEFAULT_LOADER_OPTIONS = {
|
|
|
7
19
|
configurationFiles: [],
|
|
8
20
|
environmentPrefix: 'TIMONEL_POLICY',
|
|
9
21
|
};
|
|
22
|
+
/**
|
|
23
|
+
* Configuration priority levels
|
|
24
|
+
*/
|
|
10
25
|
const CONFIGURATION_PRIORITIES = {
|
|
11
26
|
default: 0,
|
|
12
27
|
file: 10,
|
|
13
28
|
environment: 20,
|
|
14
29
|
inline: 30,
|
|
15
30
|
};
|
|
31
|
+
/**
|
|
32
|
+
* Configuration loader for policy plugins
|
|
33
|
+
*/
|
|
16
34
|
export class ConfigurationLoader {
|
|
17
35
|
constructor(options = {}) {
|
|
18
36
|
this.configurations = new Map();
|
|
@@ -24,6 +42,13 @@ export class ConfigurationLoader {
|
|
|
24
42
|
operation: 'config_loader_init',
|
|
25
43
|
});
|
|
26
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Loads configuration for a plugin
|
|
47
|
+
* @param plugin - Plugin to load configuration for
|
|
48
|
+
* @param environment - Target environment
|
|
49
|
+
* @param inlineConfig - Inline configuration to merge
|
|
50
|
+
* @returns Plugin configuration
|
|
51
|
+
*/
|
|
27
52
|
async loadPluginConfiguration(plugin, environment, inlineConfig) {
|
|
28
53
|
const targetEnvironment = environment || this.options.defaultEnvironment;
|
|
29
54
|
this.logger.debug('Loading plugin configuration', {
|
|
@@ -32,8 +57,11 @@ export class ConfigurationLoader {
|
|
|
32
57
|
hasInlineConfig: inlineConfig !== undefined,
|
|
33
58
|
operation: 'load_plugin_config',
|
|
34
59
|
});
|
|
60
|
+
// Collect configuration entries from all sources
|
|
35
61
|
const entries = await this.collectConfigurationEntries(plugin, targetEnvironment, inlineConfig);
|
|
62
|
+
// Merge configurations by priority
|
|
36
63
|
const mergedConfig = this.mergeConfigurations(entries);
|
|
64
|
+
// Validate configuration if schema is provided
|
|
37
65
|
const validationResult = this.validatePluginConfiguration(plugin, mergedConfig);
|
|
38
66
|
const result = {
|
|
39
67
|
pluginName: plugin.name,
|
|
@@ -54,8 +82,13 @@ export class ConfigurationLoader {
|
|
|
54
82
|
});
|
|
55
83
|
return result;
|
|
56
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Collects configuration entries from all sources
|
|
87
|
+
* @private
|
|
88
|
+
*/
|
|
57
89
|
async collectConfigurationEntries(plugin, targetEnvironment, inlineConfig) {
|
|
58
90
|
const entries = [];
|
|
91
|
+
// 1. Default configuration (if plugin provides it)
|
|
59
92
|
if (plugin.metadata?.defaultConfig) {
|
|
60
93
|
entries.push({
|
|
61
94
|
value: plugin.metadata.defaultConfig,
|
|
@@ -64,6 +97,7 @@ export class ConfigurationLoader {
|
|
|
64
97
|
...(plugin.configSchema && { schema: plugin.configSchema }),
|
|
65
98
|
});
|
|
66
99
|
}
|
|
100
|
+
// 2. File-based configuration
|
|
67
101
|
const fileConfig = await this.loadFileConfiguration(plugin.name, targetEnvironment);
|
|
68
102
|
if (fileConfig) {
|
|
69
103
|
entries.push({
|
|
@@ -74,6 +108,7 @@ export class ConfigurationLoader {
|
|
|
74
108
|
...(plugin.configSchema && { schema: plugin.configSchema }),
|
|
75
109
|
});
|
|
76
110
|
}
|
|
111
|
+
// 3. Environment variable configuration
|
|
77
112
|
const envConfig = this.loadEnvironmentVariableConfiguration(plugin.name);
|
|
78
113
|
if (envConfig) {
|
|
79
114
|
entries.push({
|
|
@@ -83,6 +118,7 @@ export class ConfigurationLoader {
|
|
|
83
118
|
...(plugin.configSchema && { schema: plugin.configSchema }),
|
|
84
119
|
});
|
|
85
120
|
}
|
|
121
|
+
// 4. Inline configuration (highest priority)
|
|
86
122
|
if (inlineConfig) {
|
|
87
123
|
entries.push({
|
|
88
124
|
value: inlineConfig,
|
|
@@ -93,6 +129,10 @@ export class ConfigurationLoader {
|
|
|
93
129
|
}
|
|
94
130
|
return entries;
|
|
95
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Validates plugin configuration
|
|
134
|
+
* @private
|
|
135
|
+
*/
|
|
96
136
|
validatePluginConfiguration(plugin, mergedConfig) {
|
|
97
137
|
let validated = false;
|
|
98
138
|
let validationErrors;
|
|
@@ -112,6 +152,11 @@ export class ConfigurationLoader {
|
|
|
112
152
|
}
|
|
113
153
|
return { validated, ...(validationErrors && { validationErrors }) };
|
|
114
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* Loads environment-specific configuration
|
|
157
|
+
* @param environment - Environment name
|
|
158
|
+
* @returns Environment configuration
|
|
159
|
+
*/
|
|
115
160
|
async loadEnvironmentConfiguration(environment) {
|
|
116
161
|
if (this.environmentConfigs.has(environment)) {
|
|
117
162
|
return this.environmentConfigs.get(environment);
|
|
@@ -120,6 +165,7 @@ export class ConfigurationLoader {
|
|
|
120
165
|
environment,
|
|
121
166
|
operation: 'load_env_config',
|
|
122
167
|
});
|
|
168
|
+
// Load from configuration files
|
|
123
169
|
const envConfig = await this.loadEnvironmentFromFiles(environment);
|
|
124
170
|
if (envConfig) {
|
|
125
171
|
this.environmentConfigs.set(environment, envConfig);
|
|
@@ -132,6 +178,13 @@ export class ConfigurationLoader {
|
|
|
132
178
|
}
|
|
133
179
|
return envConfig;
|
|
134
180
|
}
|
|
181
|
+
/**
|
|
182
|
+
* Validates configuration against a JSON schema
|
|
183
|
+
* @param config - Configuration to validate
|
|
184
|
+
* @param schema - JSON schema to validate against
|
|
185
|
+
* @param pluginName - Plugin name for error reporting
|
|
186
|
+
* @throws {PluginConfigurationError} When validation fails
|
|
187
|
+
*/
|
|
135
188
|
validateConfiguration(config, schema, pluginName) {
|
|
136
189
|
try {
|
|
137
190
|
this.validateAgainstSchema(config, schema, []);
|
|
@@ -140,12 +193,18 @@ export class ConfigurationLoader {
|
|
|
140
193
|
throw new PluginConfigurationError(`Configuration validation failed for plugin '${pluginName}': ${error instanceof Error ? error.message : String(error)}`, pluginName, undefined, { config, schema, validationError: error });
|
|
141
194
|
}
|
|
142
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* Adds a configuration entry for a plugin
|
|
198
|
+
* @param pluginName - Plugin name
|
|
199
|
+
* @param entry - Configuration entry to add
|
|
200
|
+
*/
|
|
143
201
|
addConfigurationEntry(pluginName, entry) {
|
|
144
202
|
if (!this.configurations.has(pluginName)) {
|
|
145
203
|
this.configurations.set(pluginName, []);
|
|
146
204
|
}
|
|
147
205
|
const entries = this.configurations.get(pluginName);
|
|
148
206
|
entries.push(entry);
|
|
207
|
+
// Sort by priority (highest first)
|
|
149
208
|
entries.sort((a, b) => b.priority - a.priority);
|
|
150
209
|
this.logger.debug('Configuration entry added', {
|
|
151
210
|
pluginName,
|
|
@@ -154,9 +213,17 @@ export class ConfigurationLoader {
|
|
|
154
213
|
operation: 'config_entry_added',
|
|
155
214
|
});
|
|
156
215
|
}
|
|
216
|
+
/**
|
|
217
|
+
* Gets all configuration entries for a plugin
|
|
218
|
+
* @param pluginName - Plugin name
|
|
219
|
+
* @returns Array of configuration entries
|
|
220
|
+
*/
|
|
157
221
|
getConfigurationEntries(pluginName) {
|
|
158
222
|
return this.configurations.get(pluginName) || [];
|
|
159
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* Clears all cached configurations
|
|
226
|
+
*/
|
|
160
227
|
clearCache() {
|
|
161
228
|
this.configurations.clear();
|
|
162
229
|
this.environmentConfigs.clear();
|
|
@@ -164,9 +231,24 @@ export class ConfigurationLoader {
|
|
|
164
231
|
operation: 'config_cache_cleared',
|
|
165
232
|
});
|
|
166
233
|
}
|
|
234
|
+
/**
|
|
235
|
+
* Loads file-based configuration for a plugin
|
|
236
|
+
* @param _pluginName - Plugin name (unused)
|
|
237
|
+
* @param _environment - Target environment (unused)
|
|
238
|
+
* @returns Configuration object or undefined
|
|
239
|
+
* @private
|
|
240
|
+
*/
|
|
167
241
|
async loadFileConfiguration(_pluginName, _environment) {
|
|
242
|
+
// For now, return undefined as file loading is not implemented
|
|
243
|
+
// This would typically load from JSON/YAML files
|
|
168
244
|
return undefined;
|
|
169
245
|
}
|
|
246
|
+
/**
|
|
247
|
+
* Loads environment variable configuration for a plugin
|
|
248
|
+
* @param pluginName - Plugin name
|
|
249
|
+
* @returns Configuration object or undefined
|
|
250
|
+
* @private
|
|
251
|
+
*/
|
|
170
252
|
loadEnvironmentVariableConfiguration(pluginName) {
|
|
171
253
|
if (!pluginName) {
|
|
172
254
|
return undefined;
|
|
@@ -174,19 +256,36 @@ export class ConfigurationLoader {
|
|
|
174
256
|
const prefix = `${this.options.environmentPrefix}_${pluginName.toUpperCase().replace(/[^A-Z0-9]/g, '_')}`;
|
|
175
257
|
const config = Object.create(null);
|
|
176
258
|
let hasConfig = false;
|
|
259
|
+
// Scan environment variables with the plugin prefix
|
|
177
260
|
for (const [key, value] of Object.entries(process.env)) {
|
|
178
261
|
if (key.startsWith(prefix + '_')) {
|
|
179
262
|
const configKey = key.substring(prefix.length + 1).toLowerCase();
|
|
263
|
+
// eslint-disable-next-line security/detect-object-injection
|
|
180
264
|
config[configKey] = this.parseEnvironmentValue(value);
|
|
181
265
|
hasConfig = true;
|
|
182
266
|
}
|
|
183
267
|
}
|
|
184
268
|
return hasConfig ? config : undefined;
|
|
185
269
|
}
|
|
270
|
+
/**
|
|
271
|
+
* Loads environment configuration from files
|
|
272
|
+
* @param _environment - Environment name (unused)
|
|
273
|
+
* @returns Environment configuration or undefined
|
|
274
|
+
* @private
|
|
275
|
+
*/
|
|
186
276
|
async loadEnvironmentFromFiles(_environment) {
|
|
277
|
+
// For now, return undefined as file loading is not implemented
|
|
278
|
+
// This would typically load from configuration files
|
|
187
279
|
return undefined;
|
|
188
280
|
}
|
|
281
|
+
/**
|
|
282
|
+
* Merges configuration entries by priority
|
|
283
|
+
* @param entries - Configuration entries to merge
|
|
284
|
+
* @returns Merged configuration
|
|
285
|
+
* @private
|
|
286
|
+
*/
|
|
189
287
|
mergeConfigurations(entries) {
|
|
288
|
+
// Sort by priority (lowest first for proper merging)
|
|
190
289
|
const sortedEntries = [...entries].sort((a, b) => a.priority - b.priority);
|
|
191
290
|
let merged = {};
|
|
192
291
|
for (const entry of sortedEntries) {
|
|
@@ -196,20 +295,40 @@ export class ConfigurationLoader {
|
|
|
196
295
|
}
|
|
197
296
|
return merged;
|
|
198
297
|
}
|
|
298
|
+
/**
|
|
299
|
+
* Parses environment variable value to appropriate type
|
|
300
|
+
* @param value - Environment variable value
|
|
301
|
+
* @returns Parsed value
|
|
302
|
+
* @private
|
|
303
|
+
*/
|
|
199
304
|
parseEnvironmentValue(value) {
|
|
200
305
|
if (!value)
|
|
201
306
|
return undefined;
|
|
307
|
+
// Try to parse as JSON first
|
|
202
308
|
try {
|
|
203
309
|
return JSON.parse(value);
|
|
204
310
|
}
|
|
205
311
|
catch {
|
|
312
|
+
// Return as string if not valid JSON
|
|
206
313
|
return value;
|
|
207
314
|
}
|
|
208
315
|
}
|
|
316
|
+
/**
|
|
317
|
+
* Validates a configuration object against a JSON schema
|
|
318
|
+
* @param config - Configuration to validate
|
|
319
|
+
* @param schema - JSON schema
|
|
320
|
+
* @param path - Current path for error reporting
|
|
321
|
+
* @throws {Error} When validation fails
|
|
322
|
+
* @private
|
|
323
|
+
*/
|
|
209
324
|
validateAgainstSchema(config, schema, path) {
|
|
210
325
|
this.validateBasicType(config, schema, path);
|
|
211
326
|
this.validateObjectProperties(config, schema, path);
|
|
212
327
|
}
|
|
328
|
+
/**
|
|
329
|
+
* Validates basic type constraints
|
|
330
|
+
* @private
|
|
331
|
+
*/
|
|
213
332
|
validateBasicType(config, schema, path) {
|
|
214
333
|
if (schema.type) {
|
|
215
334
|
const actualType = Array.isArray(config) ? 'array' : typeof config;
|
|
@@ -218,6 +337,10 @@ export class ConfigurationLoader {
|
|
|
218
337
|
}
|
|
219
338
|
}
|
|
220
339
|
}
|
|
340
|
+
/**
|
|
341
|
+
* Validates object properties
|
|
342
|
+
* @private
|
|
343
|
+
*/
|
|
221
344
|
validateObjectProperties(config, schema, path) {
|
|
222
345
|
if (schema.type === 'object' &&
|
|
223
346
|
schema.properties &&
|
|
@@ -228,6 +351,10 @@ export class ConfigurationLoader {
|
|
|
228
351
|
this.validateEachProperty(configObj, schema, path);
|
|
229
352
|
}
|
|
230
353
|
}
|
|
354
|
+
/**
|
|
355
|
+
* Validates required properties
|
|
356
|
+
* @private
|
|
357
|
+
*/
|
|
231
358
|
validateRequiredProperties(configObj, schema, path) {
|
|
232
359
|
if (schema.required) {
|
|
233
360
|
for (const requiredProp of schema.required) {
|
|
@@ -237,8 +364,13 @@ export class ConfigurationLoader {
|
|
|
237
364
|
}
|
|
238
365
|
}
|
|
239
366
|
}
|
|
367
|
+
/**
|
|
368
|
+
* Validates each property in the object
|
|
369
|
+
* @private
|
|
370
|
+
*/
|
|
240
371
|
validateEachProperty(configObj, schema, path) {
|
|
241
372
|
for (const [propName, propValue] of Object.entries(configObj)) {
|
|
373
|
+
// eslint-disable-next-line security/detect-object-injection
|
|
242
374
|
const propSchema = schema.properties?.[propName];
|
|
243
375
|
if (propSchema) {
|
|
244
376
|
this.validateAgainstSchema(propValue, propSchema, [...path, propName]);
|
|
@@ -1,23 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Context Generator
|
|
3
|
+
*
|
|
4
|
+
* This module provides utilities for generating detailed error context
|
|
5
|
+
* for policy violations, including stack traces, environment information,
|
|
6
|
+
* and debugging hints.
|
|
7
|
+
*
|
|
8
|
+
* @since 3.0.0
|
|
9
|
+
*/
|
|
1
10
|
import type { PolicyViolation, PolicyWarning, ValidationContext } from './types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Enhanced error context information
|
|
13
|
+
*/
|
|
2
14
|
export interface ErrorContext {
|
|
15
|
+
/** Error timestamp */
|
|
3
16
|
readonly timestamp: string;
|
|
17
|
+
/** Environment information */
|
|
4
18
|
readonly environment: {
|
|
5
19
|
readonly nodeVersion: string;
|
|
6
20
|
readonly platform: string;
|
|
7
21
|
readonly arch: string;
|
|
8
22
|
readonly timonelVersion?: string;
|
|
9
23
|
};
|
|
24
|
+
/** Validation context */
|
|
10
25
|
readonly validationContext: {
|
|
11
26
|
readonly chartName?: string;
|
|
12
27
|
readonly chartVersion?: string;
|
|
13
28
|
readonly kubernetesVersion?: string;
|
|
14
29
|
readonly environment?: string;
|
|
15
30
|
};
|
|
31
|
+
/** Plugin information */
|
|
16
32
|
readonly plugin: {
|
|
17
33
|
readonly name: string;
|
|
18
34
|
readonly version?: string;
|
|
19
35
|
readonly executionTime?: number;
|
|
20
36
|
};
|
|
37
|
+
/** Error details */
|
|
21
38
|
readonly error: {
|
|
22
39
|
readonly message: string;
|
|
23
40
|
readonly severity: 'error' | 'warning' | 'info';
|
|
@@ -27,15 +44,36 @@ export interface ErrorContext {
|
|
|
27
44
|
readonly stackTrace?: string;
|
|
28
45
|
readonly originalContext?: Record<string, unknown>;
|
|
29
46
|
};
|
|
47
|
+
/** Debugging hints */
|
|
30
48
|
readonly debuggingHints: string[];
|
|
49
|
+
/** Related violations */
|
|
31
50
|
readonly relatedViolations?: Array<{
|
|
32
51
|
readonly plugin: string;
|
|
33
52
|
readonly message: string;
|
|
34
53
|
readonly similarity: number;
|
|
35
54
|
}>;
|
|
36
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* Error context generator for policy violations
|
|
58
|
+
*/
|
|
37
59
|
export declare class ErrorContextGenerator {
|
|
60
|
+
/**
|
|
61
|
+
* Generates detailed error context for a policy violation
|
|
62
|
+
* @param violation - Policy violation to generate context for
|
|
63
|
+
* @param validationContext - Validation context
|
|
64
|
+
* @param allViolations - All violations for finding related issues
|
|
65
|
+
* @param executionTime - Plugin execution time
|
|
66
|
+
* @returns Enhanced error context
|
|
67
|
+
*/
|
|
38
68
|
generateContext(violation: PolicyViolation | PolicyWarning, validationContext?: ValidationContext, allViolations?: (PolicyViolation | PolicyWarning)[], executionTime?: number): ErrorContext;
|
|
69
|
+
/**
|
|
70
|
+
* Generates a formatted error report
|
|
71
|
+
* @param violation - Policy violation
|
|
72
|
+
* @param validationContext - Validation context
|
|
73
|
+
* @param allViolations - All violations
|
|
74
|
+
* @param executionTime - Plugin execution time
|
|
75
|
+
* @returns Formatted error report string
|
|
76
|
+
*/
|
|
39
77
|
generateErrorReport(violation: PolicyViolation | PolicyWarning, validationContext?: ValidationContext, allViolations?: (PolicyViolation | PolicyWarning)[], executionTime?: number): string;
|
|
40
78
|
private addReportHeader;
|
|
41
79
|
private addBasicInformation;
|
|
@@ -46,9 +84,32 @@ export declare class ErrorContextGenerator {
|
|
|
46
84
|
private addDebuggingHints;
|
|
47
85
|
private addRelatedViolations;
|
|
48
86
|
private addOriginalContext;
|
|
87
|
+
/**
|
|
88
|
+
* Gets environment information
|
|
89
|
+
* @returns Environment information object
|
|
90
|
+
* @private
|
|
91
|
+
*/
|
|
49
92
|
private getEnvironmentInfo;
|
|
93
|
+
/**
|
|
94
|
+
* Gets Timonel version from package.json
|
|
95
|
+
* @returns Timonel version or undefined
|
|
96
|
+
* @private
|
|
97
|
+
*/
|
|
50
98
|
private getTimonelVersion;
|
|
99
|
+
/**
|
|
100
|
+
* Extracts validation context information
|
|
101
|
+
* @param validationContext - Validation context
|
|
102
|
+
* @returns Validation context information
|
|
103
|
+
* @private
|
|
104
|
+
*/
|
|
51
105
|
private getValidationContextInfo;
|
|
106
|
+
/**
|
|
107
|
+
* Generates debugging hints based on the violation
|
|
108
|
+
* @param violation - Policy violation
|
|
109
|
+
* @param validationContext - Validation context
|
|
110
|
+
* @returns Array of debugging hints
|
|
111
|
+
* @private
|
|
112
|
+
*/
|
|
52
113
|
private generateDebuggingHints;
|
|
53
114
|
private addSeverityHints;
|
|
54
115
|
private addResourcePathHints;
|
|
@@ -56,8 +117,36 @@ export declare class ErrorContextGenerator {
|
|
|
56
117
|
private addPluginHints;
|
|
57
118
|
private addEnvironmentHints;
|
|
58
119
|
private addKubernetesVersionHints;
|
|
120
|
+
/**
|
|
121
|
+
* Finds violations related to the current one
|
|
122
|
+
* @param violation - Current violation
|
|
123
|
+
* @param allViolations - All violations to search through
|
|
124
|
+
* @returns Array of related violations with similarity scores
|
|
125
|
+
* @private
|
|
126
|
+
*/
|
|
59
127
|
private findRelatedViolations;
|
|
128
|
+
/**
|
|
129
|
+
* Calculates similarity between two violations
|
|
130
|
+
* @param violation1 - First violation
|
|
131
|
+
* @param violation2 - Second violation
|
|
132
|
+
* @returns Similarity score between 0 and 1
|
|
133
|
+
* @private
|
|
134
|
+
*/
|
|
60
135
|
private calculateSimilarity;
|
|
136
|
+
/**
|
|
137
|
+
* Calculates string similarity using a simple algorithm
|
|
138
|
+
* @param str1 - First string
|
|
139
|
+
* @param str2 - Second string
|
|
140
|
+
* @returns Similarity score between 0 and 1
|
|
141
|
+
* @private
|
|
142
|
+
*/
|
|
61
143
|
private calculateStringSimilarity;
|
|
144
|
+
/**
|
|
145
|
+
* Calculates Levenshtein distance between two strings
|
|
146
|
+
* @param str1 - First string
|
|
147
|
+
* @param str2 - Second string
|
|
148
|
+
* @returns Edit distance
|
|
149
|
+
* @private
|
|
150
|
+
*/
|
|
62
151
|
private calculateLevenshteinDistance;
|
|
63
152
|
}
|
|
@@ -1,4 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Context Generator
|
|
3
|
+
*
|
|
4
|
+
* This module provides utilities for generating detailed error context
|
|
5
|
+
* for policy violations, including stack traces, environment information,
|
|
6
|
+
* and debugging hints.
|
|
7
|
+
*
|
|
8
|
+
* @since 3.0.0
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Error context generator for policy violations
|
|
12
|
+
*/
|
|
1
13
|
export class ErrorContextGenerator {
|
|
14
|
+
/**
|
|
15
|
+
* Generates detailed error context for a policy violation
|
|
16
|
+
* @param violation - Policy violation to generate context for
|
|
17
|
+
* @param validationContext - Validation context
|
|
18
|
+
* @param allViolations - All violations for finding related issues
|
|
19
|
+
* @param executionTime - Plugin execution time
|
|
20
|
+
* @returns Enhanced error context
|
|
21
|
+
*/
|
|
2
22
|
generateContext(violation, validationContext, allViolations, executionTime) {
|
|
3
23
|
return {
|
|
4
24
|
timestamp: new Date().toISOString(),
|
|
@@ -20,6 +40,14 @@ export class ErrorContextGenerator {
|
|
|
20
40
|
relatedViolations: this.findRelatedViolations(violation, allViolations),
|
|
21
41
|
};
|
|
22
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Generates a formatted error report
|
|
45
|
+
* @param violation - Policy violation
|
|
46
|
+
* @param validationContext - Validation context
|
|
47
|
+
* @param allViolations - All violations
|
|
48
|
+
* @param executionTime - Plugin execution time
|
|
49
|
+
* @returns Formatted error report string
|
|
50
|
+
*/
|
|
23
51
|
generateErrorReport(violation, validationContext, allViolations, executionTime) {
|
|
24
52
|
const context = this.generateContext(violation, validationContext, allViolations, executionTime);
|
|
25
53
|
const lines = [];
|
|
@@ -126,6 +154,11 @@ export class ErrorContextGenerator {
|
|
|
126
154
|
lines.push('');
|
|
127
155
|
}
|
|
128
156
|
}
|
|
157
|
+
/**
|
|
158
|
+
* Gets environment information
|
|
159
|
+
* @returns Environment information object
|
|
160
|
+
* @private
|
|
161
|
+
*/
|
|
129
162
|
getEnvironmentInfo() {
|
|
130
163
|
const timonelVersion = this.getTimonelVersion();
|
|
131
164
|
return {
|
|
@@ -135,9 +168,23 @@ export class ErrorContextGenerator {
|
|
|
135
168
|
...(timonelVersion && { timonelVersion }),
|
|
136
169
|
};
|
|
137
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Gets Timonel version from package.json
|
|
173
|
+
* @returns Timonel version or undefined
|
|
174
|
+
* @private
|
|
175
|
+
*/
|
|
138
176
|
getTimonelVersion() {
|
|
139
|
-
|
|
177
|
+
// Try to read package.json to get version
|
|
178
|
+
// This is a simplified approach - in a real implementation,
|
|
179
|
+
// you might want to read from a constants file or build-time injection
|
|
180
|
+
return '3.0.0'; // Placeholder
|
|
140
181
|
}
|
|
182
|
+
/**
|
|
183
|
+
* Extracts validation context information
|
|
184
|
+
* @param validationContext - Validation context
|
|
185
|
+
* @returns Validation context information
|
|
186
|
+
* @private
|
|
187
|
+
*/
|
|
141
188
|
getValidationContextInfo(validationContext) {
|
|
142
189
|
return {
|
|
143
190
|
...(validationContext?.chart?.name && { chartName: validationContext.chart.name }),
|
|
@@ -148,6 +195,13 @@ export class ErrorContextGenerator {
|
|
|
148
195
|
...(validationContext?.environment && { environment: validationContext.environment }),
|
|
149
196
|
};
|
|
150
197
|
}
|
|
198
|
+
/**
|
|
199
|
+
* Generates debugging hints based on the violation
|
|
200
|
+
* @param violation - Policy violation
|
|
201
|
+
* @param validationContext - Validation context
|
|
202
|
+
* @returns Array of debugging hints
|
|
203
|
+
* @private
|
|
204
|
+
*/
|
|
151
205
|
generateDebuggingHints(violation, validationContext) {
|
|
152
206
|
const hints = [];
|
|
153
207
|
this.addSeverityHints(hints, violation);
|
|
@@ -220,6 +274,13 @@ export class ErrorContextGenerator {
|
|
|
220
274
|
}
|
|
221
275
|
}
|
|
222
276
|
}
|
|
277
|
+
/**
|
|
278
|
+
* Finds violations related to the current one
|
|
279
|
+
* @param violation - Current violation
|
|
280
|
+
* @param allViolations - All violations to search through
|
|
281
|
+
* @returns Array of related violations with similarity scores
|
|
282
|
+
* @private
|
|
283
|
+
*/
|
|
223
284
|
findRelatedViolations(violation, allViolations) {
|
|
224
285
|
if (!allViolations || allViolations.length <= 1) {
|
|
225
286
|
return [];
|
|
@@ -230,6 +291,7 @@ export class ErrorContextGenerator {
|
|
|
230
291
|
continue;
|
|
231
292
|
const similarity = this.calculateSimilarity(violation, other);
|
|
232
293
|
if (similarity > 0.3) {
|
|
294
|
+
// 30% similarity threshold
|
|
233
295
|
related.push({
|
|
234
296
|
plugin: other.plugin,
|
|
235
297
|
message: other.message,
|
|
@@ -237,34 +299,54 @@ export class ErrorContextGenerator {
|
|
|
237
299
|
});
|
|
238
300
|
}
|
|
239
301
|
}
|
|
302
|
+
// Sort by similarity and return top 3
|
|
240
303
|
return related.sort((a, b) => b.similarity - a.similarity).slice(0, 3);
|
|
241
304
|
}
|
|
305
|
+
/**
|
|
306
|
+
* Calculates similarity between two violations
|
|
307
|
+
* @param violation1 - First violation
|
|
308
|
+
* @param violation2 - Second violation
|
|
309
|
+
* @returns Similarity score between 0 and 1
|
|
310
|
+
* @private
|
|
311
|
+
*/
|
|
242
312
|
calculateSimilarity(violation1, violation2) {
|
|
243
313
|
let score = 0;
|
|
244
314
|
let factors = 0;
|
|
315
|
+
// Same plugin
|
|
245
316
|
if (violation1.plugin === violation2.plugin) {
|
|
246
317
|
score += 0.4;
|
|
247
318
|
}
|
|
248
319
|
factors += 0.4;
|
|
320
|
+
// Same severity
|
|
249
321
|
if (violation1.severity === violation2.severity) {
|
|
250
322
|
score += 0.2;
|
|
251
323
|
}
|
|
252
324
|
factors += 0.2;
|
|
325
|
+
// Similar resource path
|
|
253
326
|
if (violation1.resourcePath && violation2.resourcePath) {
|
|
254
327
|
const pathSimilarity = this.calculateStringSimilarity(violation1.resourcePath, violation2.resourcePath);
|
|
255
328
|
score += pathSimilarity * 0.2;
|
|
256
329
|
}
|
|
257
330
|
factors += 0.2;
|
|
331
|
+
// Similar field
|
|
258
332
|
if (violation1.field && violation2.field) {
|
|
259
333
|
const fieldSimilarity = this.calculateStringSimilarity(violation1.field, violation2.field);
|
|
260
334
|
score += fieldSimilarity * 0.1;
|
|
261
335
|
}
|
|
262
336
|
factors += 0.1;
|
|
337
|
+
// Similar message
|
|
263
338
|
const messageSimilarity = this.calculateStringSimilarity(violation1.message, violation2.message);
|
|
264
339
|
score += messageSimilarity * 0.1;
|
|
265
340
|
factors += 0.1;
|
|
266
341
|
return factors > 0 ? score / factors : 0;
|
|
267
342
|
}
|
|
343
|
+
/**
|
|
344
|
+
* Calculates string similarity using a simple algorithm
|
|
345
|
+
* @param str1 - First string
|
|
346
|
+
* @param str2 - Second string
|
|
347
|
+
* @returns Similarity score between 0 and 1
|
|
348
|
+
* @private
|
|
349
|
+
*/
|
|
268
350
|
calculateStringSimilarity(str1, str2) {
|
|
269
351
|
if (str1 === str2)
|
|
270
352
|
return 1;
|
|
@@ -277,23 +359,38 @@ export class ErrorContextGenerator {
|
|
|
277
359
|
const editDistance = this.calculateLevenshteinDistance(longer, shorter);
|
|
278
360
|
return (longer.length - editDistance) / longer.length;
|
|
279
361
|
}
|
|
362
|
+
/**
|
|
363
|
+
* Calculates Levenshtein distance between two strings
|
|
364
|
+
* @param str1 - First string
|
|
365
|
+
* @param str2 - Second string
|
|
366
|
+
* @returns Edit distance
|
|
367
|
+
* @private
|
|
368
|
+
*/
|
|
280
369
|
calculateLevenshteinDistance(str1, str2) {
|
|
281
370
|
const matrix = Array(str2.length + 1)
|
|
282
371
|
.fill(null)
|
|
283
372
|
.map(() => Array(str1.length + 1).fill(0));
|
|
284
373
|
for (let i = 0; i <= str2.length; i++) {
|
|
374
|
+
// eslint-disable-next-line security/detect-object-injection
|
|
285
375
|
matrix[i][0] = i;
|
|
286
376
|
}
|
|
287
377
|
for (let j = 0; j <= str1.length; j++) {
|
|
378
|
+
// eslint-disable-next-line security/detect-object-injection
|
|
288
379
|
matrix[0][j] = j;
|
|
289
380
|
}
|
|
290
381
|
for (let i = 1; i <= str2.length; i++) {
|
|
291
382
|
for (let j = 1; j <= str1.length; j++) {
|
|
292
383
|
if (str2.charAt(i - 1) === str1.charAt(j - 1)) {
|
|
384
|
+
// eslint-disable-next-line security/detect-object-injection
|
|
293
385
|
matrix[i][j] = matrix[i - 1][j - 1];
|
|
294
386
|
}
|
|
295
387
|
else {
|
|
296
|
-
|
|
388
|
+
// eslint-disable-next-line security/detect-object-injection
|
|
389
|
+
matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // substitution
|
|
390
|
+
// eslint-disable-next-line security/detect-object-injection
|
|
391
|
+
matrix[i][j - 1] + 1, // insertion
|
|
392
|
+
// eslint-disable-next-line security/detect-object-injection
|
|
393
|
+
matrix[i - 1][j] + 1);
|
|
297
394
|
}
|
|
298
395
|
}
|
|
299
396
|
}
|