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,41 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin Loader
|
|
3
|
+
*
|
|
4
|
+
* This module provides plugin discovery and loading capabilities for the policy engine.
|
|
5
|
+
* It supports loading plugins from npm packages, version compatibility checks, and
|
|
6
|
+
* conditional loading based on environment.
|
|
7
|
+
*
|
|
8
|
+
* @since 3.0.0
|
|
9
|
+
*/
|
|
1
10
|
import type { PolicyPlugin, PluginMetadata } from './types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Plugin loading options
|
|
13
|
+
*/
|
|
2
14
|
export interface PluginLoaderOptions {
|
|
15
|
+
/** Base directory for plugin discovery */
|
|
3
16
|
baseDirectory?: string;
|
|
17
|
+
/** Environment for conditional loading */
|
|
4
18
|
environment?: string;
|
|
19
|
+
/** Whether to validate plugin compatibility */
|
|
5
20
|
validateCompatibility?: boolean;
|
|
21
|
+
/** Supported Kubernetes versions for compatibility checks */
|
|
6
22
|
supportedKubernetesVersions?: string[];
|
|
23
|
+
/** Plugin registry URL for discovery */
|
|
7
24
|
registryUrl?: string;
|
|
25
|
+
/** Timeout for plugin loading operations */
|
|
8
26
|
loadTimeout?: number;
|
|
9
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Plugin discovery result
|
|
30
|
+
*/
|
|
10
31
|
export interface PluginDiscoveryResult {
|
|
32
|
+
/** Plugin package name */
|
|
11
33
|
packageName: string;
|
|
34
|
+
/** Plugin version */
|
|
12
35
|
version: string;
|
|
36
|
+
/** Plugin metadata */
|
|
13
37
|
metadata?: PluginMetadata;
|
|
38
|
+
/** Whether plugin is compatible */
|
|
14
39
|
compatible: boolean;
|
|
40
|
+
/** Compatibility issues if any */
|
|
15
41
|
compatibilityIssues?: string[];
|
|
42
|
+
/** Plugin source (npm, local, etc.) */
|
|
16
43
|
source: 'npm' | 'local' | 'registry';
|
|
17
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Plugin loading result
|
|
47
|
+
*/
|
|
18
48
|
export interface PluginLoadingResult {
|
|
49
|
+
/** Loaded plugin instance */
|
|
19
50
|
plugin: PolicyPlugin;
|
|
51
|
+
/** Plugin package name */
|
|
20
52
|
packageName: string;
|
|
53
|
+
/** Loading source */
|
|
21
54
|
source: 'npm' | 'local' | 'registry';
|
|
55
|
+
/** Loading time in milliseconds */
|
|
22
56
|
loadTime: number;
|
|
57
|
+
/** Whether plugin passed validation */
|
|
23
58
|
validated: boolean;
|
|
59
|
+
/** Validation warnings if any */
|
|
24
60
|
warnings?: string[];
|
|
25
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Plugin loader for policy engine
|
|
64
|
+
*/
|
|
26
65
|
export declare class PluginLoader {
|
|
27
66
|
private readonly options;
|
|
28
67
|
private readonly logger;
|
|
29
68
|
private readonly loadedPlugins;
|
|
30
69
|
constructor(options?: PluginLoaderOptions);
|
|
70
|
+
/**
|
|
71
|
+
* Loads a plugin from an npm package
|
|
72
|
+
* @param packageName - NPM package name
|
|
73
|
+
* @param version - Optional version constraint
|
|
74
|
+
* @returns Plugin loading result
|
|
75
|
+
*/
|
|
31
76
|
loadFromPackage(packageName: string, version?: string): Promise<PluginLoadingResult>;
|
|
77
|
+
/**
|
|
78
|
+
* Discovers available plugins in the environment
|
|
79
|
+
* @param searchPattern - Optional search pattern for plugin names
|
|
80
|
+
* @returns Array of discovered plugins
|
|
81
|
+
*/
|
|
32
82
|
discoverPlugins(searchPattern?: string): Promise<PluginDiscoveryResult[]>;
|
|
83
|
+
/**
|
|
84
|
+
* Loads multiple plugins from a list of package names
|
|
85
|
+
* @param packages - Array of package names or package@version strings
|
|
86
|
+
* @returns Array of loading results
|
|
87
|
+
*/
|
|
33
88
|
loadMultiplePlugins(packages: string[]): Promise<PluginLoadingResult[]>;
|
|
89
|
+
/**
|
|
90
|
+
* Validates that a plugin implements the required interface
|
|
91
|
+
* @param plugin - Plugin to validate
|
|
92
|
+
* @param packageName - Package name for error reporting
|
|
93
|
+
* @throws {PluginRegistrationError} When plugin is invalid
|
|
94
|
+
*/
|
|
34
95
|
static validatePluginInterface(plugin: unknown, packageName: string): asserts plugin is PolicyPlugin;
|
|
96
|
+
/**
|
|
97
|
+
* Gets all loaded plugins
|
|
98
|
+
* @returns Array of loaded plugin results
|
|
99
|
+
*/
|
|
35
100
|
getLoadedPlugins(): PluginLoadingResult[];
|
|
101
|
+
/**
|
|
102
|
+
* Clears the plugin cache
|
|
103
|
+
*/
|
|
36
104
|
clearCache(): void;
|
|
105
|
+
/**
|
|
106
|
+
* Loads a module with timeout protection
|
|
107
|
+
* @param modulePath - Module path to load
|
|
108
|
+
* @returns Loaded plugin
|
|
109
|
+
* @private
|
|
110
|
+
*/
|
|
37
111
|
private loadModuleWithTimeout;
|
|
112
|
+
/**
|
|
113
|
+
* Validates plugin interface (instance method)
|
|
114
|
+
* @param plugin - Plugin to validate
|
|
115
|
+
* @param packageName - Package name for error reporting
|
|
116
|
+
* @private
|
|
117
|
+
*/
|
|
38
118
|
private validatePluginInterface;
|
|
119
|
+
/**
|
|
120
|
+
* Checks plugin compatibility with current environment
|
|
121
|
+
* @param plugin - Plugin to check
|
|
122
|
+
* @returns Array of compatibility issues
|
|
123
|
+
* @private
|
|
124
|
+
*/
|
|
39
125
|
private checkCompatibility;
|
|
126
|
+
/**
|
|
127
|
+
* Determines if plugin should be loaded in current environment
|
|
128
|
+
* @param _plugin - Plugin to check (unused for now)
|
|
129
|
+
* @returns True if plugin should be loaded
|
|
130
|
+
* @private
|
|
131
|
+
*/
|
|
40
132
|
private shouldLoadInEnvironment;
|
|
41
133
|
}
|
|
@@ -1,14 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin Loader
|
|
3
|
+
*
|
|
4
|
+
* This module provides plugin discovery and loading capabilities for the policy engine.
|
|
5
|
+
* It supports loading plugins from npm packages, version compatibility checks, and
|
|
6
|
+
* conditional loading based on environment.
|
|
7
|
+
*
|
|
8
|
+
* @since 3.0.0
|
|
9
|
+
*/
|
|
1
10
|
import { createLogger } from '../utils/logger.js';
|
|
2
11
|
import { PluginError, PluginRegistrationError } from './errors.js';
|
|
12
|
+
/**
|
|
13
|
+
* Constants for error messages
|
|
14
|
+
*/
|
|
3
15
|
const UNKNOWN_ERROR_MESSAGE = 'Unknown error';
|
|
16
|
+
/**
|
|
17
|
+
* Default plugin loader options
|
|
18
|
+
*/
|
|
4
19
|
const DEFAULT_LOADER_OPTIONS = {
|
|
5
20
|
baseDirectory: process.cwd(),
|
|
6
21
|
environment: 'development',
|
|
7
22
|
validateCompatibility: true,
|
|
8
23
|
supportedKubernetesVersions: ['1.25', '1.26', '1.27', '1.28', '1.29'],
|
|
9
24
|
registryUrl: 'https://registry.npmjs.org',
|
|
10
|
-
loadTimeout: 30000,
|
|
25
|
+
loadTimeout: 30000, // 30 seconds
|
|
11
26
|
};
|
|
27
|
+
/**
|
|
28
|
+
* Plugin loader for policy engine
|
|
29
|
+
*/
|
|
12
30
|
export class PluginLoader {
|
|
13
31
|
constructor(options = {}) {
|
|
14
32
|
this.loadedPlugins = new Map();
|
|
@@ -19,6 +37,12 @@ export class PluginLoader {
|
|
|
19
37
|
operation: 'plugin_loader_init',
|
|
20
38
|
});
|
|
21
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Loads a plugin from an npm package
|
|
42
|
+
* @param packageName - NPM package name
|
|
43
|
+
* @param version - Optional version constraint
|
|
44
|
+
* @returns Plugin loading result
|
|
45
|
+
*/
|
|
22
46
|
async loadFromPackage(packageName, version) {
|
|
23
47
|
const startTime = Date.now();
|
|
24
48
|
this.logger.info('Loading plugin from package', {
|
|
@@ -27,6 +51,7 @@ export class PluginLoader {
|
|
|
27
51
|
operation: 'load_from_package',
|
|
28
52
|
});
|
|
29
53
|
try {
|
|
54
|
+
// Check if already loaded
|
|
30
55
|
const cacheKey = `${packageName}@${version || 'latest'}`;
|
|
31
56
|
if (this.loadedPlugins.has(cacheKey)) {
|
|
32
57
|
const cached = this.loadedPlugins.get(cacheKey);
|
|
@@ -37,14 +62,19 @@ export class PluginLoader {
|
|
|
37
62
|
});
|
|
38
63
|
return cached;
|
|
39
64
|
}
|
|
65
|
+
// Construct module path
|
|
40
66
|
const modulePath = version ? `${packageName}@${version}` : packageName;
|
|
67
|
+
// Load the module with timeout
|
|
41
68
|
const plugin = await this.loadModuleWithTimeout(modulePath);
|
|
69
|
+
// Validate plugin interface
|
|
42
70
|
this.validatePluginInterface(plugin, packageName);
|
|
71
|
+
// Check compatibility if enabled
|
|
43
72
|
const warnings = [];
|
|
44
73
|
if (this.options.validateCompatibility) {
|
|
45
74
|
const compatibilityIssues = this.checkCompatibility(plugin);
|
|
46
75
|
warnings.push(...compatibilityIssues);
|
|
47
76
|
}
|
|
77
|
+
// Check environment conditions
|
|
48
78
|
if (!this.shouldLoadInEnvironment(plugin)) {
|
|
49
79
|
throw new PluginError(`Plugin '${packageName}' is not enabled for environment '${this.options.environment}'`, packageName);
|
|
50
80
|
}
|
|
@@ -57,6 +87,7 @@ export class PluginLoader {
|
|
|
57
87
|
validated: true,
|
|
58
88
|
...(warnings.length > 0 && { warnings }),
|
|
59
89
|
};
|
|
90
|
+
// Cache the result
|
|
60
91
|
this.loadedPlugins.set(cacheKey, result);
|
|
61
92
|
this.logger.info('Plugin loaded successfully', {
|
|
62
93
|
packageName,
|
|
@@ -80,6 +111,11 @@ export class PluginLoader {
|
|
|
80
111
|
throw new PluginError(`Failed to load plugin from package '${packageName}': ${error instanceof Error ? error.message : UNKNOWN_ERROR_MESSAGE}`, packageName, { originalError: error, loadTime });
|
|
81
112
|
}
|
|
82
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Discovers available plugins in the environment
|
|
116
|
+
* @param searchPattern - Optional search pattern for plugin names
|
|
117
|
+
* @returns Array of discovered plugins
|
|
118
|
+
*/
|
|
83
119
|
async discoverPlugins(searchPattern) {
|
|
84
120
|
this.logger.info('Discovering plugins', {
|
|
85
121
|
searchPattern,
|
|
@@ -88,6 +124,9 @@ export class PluginLoader {
|
|
|
88
124
|
});
|
|
89
125
|
const discovered = [];
|
|
90
126
|
try {
|
|
127
|
+
// For now, return empty array as actual discovery would require
|
|
128
|
+
// scanning node_modules, package.json, or registry API calls
|
|
129
|
+
// This is a placeholder for future implementation
|
|
91
130
|
this.logger.info('Plugin discovery completed', {
|
|
92
131
|
discoveredCount: discovered.length,
|
|
93
132
|
operation: 'discovery_complete',
|
|
@@ -102,6 +141,11 @@ export class PluginLoader {
|
|
|
102
141
|
throw new PluginError(`Plugin discovery failed: ${error instanceof Error ? error.message : UNKNOWN_ERROR_MESSAGE}`, 'discovery');
|
|
103
142
|
}
|
|
104
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Loads multiple plugins from a list of package names
|
|
146
|
+
* @param packages - Array of package names or package@version strings
|
|
147
|
+
* @returns Array of loading results
|
|
148
|
+
*/
|
|
105
149
|
async loadMultiplePlugins(packages) {
|
|
106
150
|
this.logger.info('Loading multiple plugins', {
|
|
107
151
|
packageCount: packages.length,
|
|
@@ -110,6 +154,7 @@ export class PluginLoader {
|
|
|
110
154
|
});
|
|
111
155
|
const results = [];
|
|
112
156
|
const errors = [];
|
|
157
|
+
// Load plugins in parallel
|
|
113
158
|
const loadPromises = packages.map(async (pkg) => {
|
|
114
159
|
try {
|
|
115
160
|
const [packageName, version] = pkg.includes('@') && !pkg.startsWith('@') ? pkg.split('@') : [pkg, undefined];
|
|
@@ -124,11 +169,13 @@ export class PluginLoader {
|
|
|
124
169
|
}
|
|
125
170
|
});
|
|
126
171
|
const loadResults = await Promise.all(loadPromises);
|
|
172
|
+
// Collect successful results
|
|
127
173
|
for (const result of loadResults) {
|
|
128
174
|
if (result) {
|
|
129
175
|
results.push(result);
|
|
130
176
|
}
|
|
131
177
|
}
|
|
178
|
+
// Log errors but don't throw (graceful degradation)
|
|
132
179
|
if (errors.length > 0) {
|
|
133
180
|
this.logger.warn('Some plugins failed to load', {
|
|
134
181
|
successCount: results.length,
|
|
@@ -145,6 +192,12 @@ export class PluginLoader {
|
|
|
145
192
|
});
|
|
146
193
|
return results;
|
|
147
194
|
}
|
|
195
|
+
/**
|
|
196
|
+
* Validates that a plugin implements the required interface
|
|
197
|
+
* @param plugin - Plugin to validate
|
|
198
|
+
* @param packageName - Package name for error reporting
|
|
199
|
+
* @throws {PluginRegistrationError} When plugin is invalid
|
|
200
|
+
*/
|
|
148
201
|
static validatePluginInterface(plugin, packageName) {
|
|
149
202
|
if (!plugin || typeof plugin !== 'object') {
|
|
150
203
|
throw new PluginRegistrationError(`Plugin from package '${packageName}' must be an object`, packageName);
|
|
@@ -159,6 +212,7 @@ export class PluginLoader {
|
|
|
159
212
|
if (typeof p.validate !== 'function') {
|
|
160
213
|
throw new PluginRegistrationError(`Plugin from package '${packageName}' must implement validate method`, packageName);
|
|
161
214
|
}
|
|
215
|
+
// Validate optional fields if present
|
|
162
216
|
if (p.description !== undefined && typeof p.description !== 'string') {
|
|
163
217
|
throw new PluginRegistrationError(`Plugin from package '${packageName}' description must be a string`, packageName);
|
|
164
218
|
}
|
|
@@ -169,23 +223,38 @@ export class PluginLoader {
|
|
|
169
223
|
throw new PluginRegistrationError(`Plugin from package '${packageName}' metadata must be an object`, packageName);
|
|
170
224
|
}
|
|
171
225
|
}
|
|
226
|
+
/**
|
|
227
|
+
* Gets all loaded plugins
|
|
228
|
+
* @returns Array of loaded plugin results
|
|
229
|
+
*/
|
|
172
230
|
getLoadedPlugins() {
|
|
173
231
|
return Array.from(this.loadedPlugins.values());
|
|
174
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* Clears the plugin cache
|
|
235
|
+
*/
|
|
175
236
|
clearCache() {
|
|
176
237
|
this.loadedPlugins.clear();
|
|
177
238
|
this.logger.debug('Plugin cache cleared', {
|
|
178
239
|
operation: 'cache_cleared',
|
|
179
240
|
});
|
|
180
241
|
}
|
|
242
|
+
/**
|
|
243
|
+
* Loads a module with timeout protection
|
|
244
|
+
* @param modulePath - Module path to load
|
|
245
|
+
* @returns Loaded plugin
|
|
246
|
+
* @private
|
|
247
|
+
*/
|
|
181
248
|
async loadModuleWithTimeout(modulePath) {
|
|
182
249
|
return new Promise((resolve, reject) => {
|
|
183
250
|
const timeout = globalThis.setTimeout(() => {
|
|
184
251
|
reject(new Error(`Plugin loading timed out after ${this.options.loadTimeout}ms`));
|
|
185
252
|
}, this.options.loadTimeout);
|
|
253
|
+
// Use dynamic import to load the module
|
|
186
254
|
import(modulePath)
|
|
187
255
|
.then((module) => {
|
|
188
256
|
globalThis.clearTimeout(timeout);
|
|
257
|
+
// Handle different export patterns
|
|
189
258
|
const plugin = module.default || module;
|
|
190
259
|
if (!plugin) {
|
|
191
260
|
reject(new Error('Plugin module does not export a plugin'));
|
|
@@ -199,11 +268,24 @@ export class PluginLoader {
|
|
|
199
268
|
});
|
|
200
269
|
});
|
|
201
270
|
}
|
|
271
|
+
/**
|
|
272
|
+
* Validates plugin interface (instance method)
|
|
273
|
+
* @param plugin - Plugin to validate
|
|
274
|
+
* @param packageName - Package name for error reporting
|
|
275
|
+
* @private
|
|
276
|
+
*/
|
|
202
277
|
validatePluginInterface(plugin, packageName) {
|
|
203
278
|
PluginLoader.validatePluginInterface(plugin, packageName);
|
|
204
279
|
}
|
|
280
|
+
/**
|
|
281
|
+
* Checks plugin compatibility with current environment
|
|
282
|
+
* @param plugin - Plugin to check
|
|
283
|
+
* @returns Array of compatibility issues
|
|
284
|
+
* @private
|
|
285
|
+
*/
|
|
205
286
|
checkCompatibility(plugin) {
|
|
206
287
|
const issues = [];
|
|
288
|
+
// Check Kubernetes version compatibility
|
|
207
289
|
if (plugin.metadata?.kubernetesVersions) {
|
|
208
290
|
const supportedVersions = new Set(this.options.supportedKubernetesVersions);
|
|
209
291
|
const pluginVersions = plugin.metadata.kubernetesVersions;
|
|
@@ -212,9 +294,18 @@ export class PluginLoader {
|
|
|
212
294
|
issues.push(`Plugin requires Kubernetes versions [${pluginVersions.join(', ')}] but only [${this.options.supportedKubernetesVersions.join(', ')}] are supported`);
|
|
213
295
|
}
|
|
214
296
|
}
|
|
297
|
+
// Add more compatibility checks as needed
|
|
215
298
|
return issues;
|
|
216
299
|
}
|
|
300
|
+
/**
|
|
301
|
+
* Determines if plugin should be loaded in current environment
|
|
302
|
+
* @param _plugin - Plugin to check (unused for now)
|
|
303
|
+
* @returns True if plugin should be loaded
|
|
304
|
+
* @private
|
|
305
|
+
*/
|
|
217
306
|
shouldLoadInEnvironment(_plugin) {
|
|
307
|
+
// For now, always return true
|
|
308
|
+
// This could be extended to check plugin metadata for environment restrictions
|
|
218
309
|
return true;
|
|
219
310
|
}
|
|
220
311
|
}
|
|
@@ -1,14 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin Registry
|
|
3
|
+
*
|
|
4
|
+
* This module manages the lifecycle of policy plugins including registration,
|
|
5
|
+
* validation, and configuration management.
|
|
6
|
+
*
|
|
7
|
+
* @since 3.0.0
|
|
8
|
+
*/
|
|
1
9
|
import type { PolicyPlugin } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Registry for managing policy plugins
|
|
12
|
+
*/
|
|
2
13
|
export declare class PluginRegistry {
|
|
3
14
|
private plugins;
|
|
4
15
|
private pluginConfigs;
|
|
16
|
+
/**
|
|
17
|
+
* Registers a policy plugin with optional configuration
|
|
18
|
+
* @param plugin - The policy plugin to register
|
|
19
|
+
* @param config - Optional plugin-specific configuration
|
|
20
|
+
* @throws {PluginRegistrationError} When plugin validation fails
|
|
21
|
+
*/
|
|
5
22
|
register(plugin: PolicyPlugin, config?: unknown): void;
|
|
23
|
+
/**
|
|
24
|
+
* Gets a plugin by name
|
|
25
|
+
* @param name - Plugin name
|
|
26
|
+
* @returns Plugin instance or undefined if not found
|
|
27
|
+
*/
|
|
6
28
|
getPlugin(name: string): PolicyPlugin | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Gets all registered plugins
|
|
31
|
+
* @returns Array of all registered plugins
|
|
32
|
+
*/
|
|
7
33
|
getAllPlugins(): PolicyPlugin[];
|
|
34
|
+
/**
|
|
35
|
+
* Gets plugin configuration
|
|
36
|
+
* @param pluginName - Name of the plugin
|
|
37
|
+
* @returns Plugin configuration or undefined if not set
|
|
38
|
+
*/
|
|
8
39
|
getPluginConfig(pluginName: string): unknown;
|
|
40
|
+
/**
|
|
41
|
+
* Checks if a plugin is registered
|
|
42
|
+
* @param name - Plugin name
|
|
43
|
+
* @returns True if plugin is registered
|
|
44
|
+
*/
|
|
9
45
|
hasPlugin(name: string): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Gets the number of registered plugins
|
|
48
|
+
* @returns Number of registered plugins
|
|
49
|
+
*/
|
|
10
50
|
getPluginCount(): number;
|
|
51
|
+
/**
|
|
52
|
+
* Unregisters a plugin
|
|
53
|
+
* @param name - Plugin name to unregister
|
|
54
|
+
* @returns True if plugin was removed, false if not found
|
|
55
|
+
*/
|
|
11
56
|
unregister(name: string): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Clears all registered plugins
|
|
59
|
+
*/
|
|
12
60
|
clear(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Validates that a plugin implements the required interface
|
|
63
|
+
* @param plugin - Plugin to validate
|
|
64
|
+
* @throws {PluginRegistrationError} When plugin is invalid
|
|
65
|
+
* @private
|
|
66
|
+
*/
|
|
13
67
|
private validatePlugin;
|
|
14
68
|
}
|
|
@@ -1,11 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin Registry
|
|
3
|
+
*
|
|
4
|
+
* This module manages the lifecycle of policy plugins including registration,
|
|
5
|
+
* validation, and configuration management.
|
|
6
|
+
*
|
|
7
|
+
* @since 3.0.0
|
|
8
|
+
*/
|
|
1
9
|
import { PluginRegistrationError } from './errors.js';
|
|
10
|
+
/**
|
|
11
|
+
* Registry for managing policy plugins
|
|
12
|
+
*/
|
|
2
13
|
export class PluginRegistry {
|
|
3
14
|
constructor() {
|
|
4
15
|
this.plugins = new Map();
|
|
5
16
|
this.pluginConfigs = new Map();
|
|
6
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Registers a policy plugin with optional configuration
|
|
20
|
+
* @param plugin - The policy plugin to register
|
|
21
|
+
* @param config - Optional plugin-specific configuration
|
|
22
|
+
* @throws {PluginRegistrationError} When plugin validation fails
|
|
23
|
+
*/
|
|
7
24
|
register(plugin, config) {
|
|
8
25
|
this.validatePlugin(plugin);
|
|
26
|
+
// Check for duplicate plugin names
|
|
9
27
|
if (this.plugins.has(plugin.name)) {
|
|
10
28
|
throw new PluginRegistrationError(`Plugin with name '${plugin.name}' is already registered`, plugin.name);
|
|
11
29
|
}
|
|
@@ -14,21 +32,49 @@ export class PluginRegistry {
|
|
|
14
32
|
this.pluginConfigs.set(plugin.name, config);
|
|
15
33
|
}
|
|
16
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Gets a plugin by name
|
|
37
|
+
* @param name - Plugin name
|
|
38
|
+
* @returns Plugin instance or undefined if not found
|
|
39
|
+
*/
|
|
17
40
|
getPlugin(name) {
|
|
18
41
|
return this.plugins.get(name);
|
|
19
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Gets all registered plugins
|
|
45
|
+
* @returns Array of all registered plugins
|
|
46
|
+
*/
|
|
20
47
|
getAllPlugins() {
|
|
21
48
|
return Array.from(this.plugins.values());
|
|
22
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Gets plugin configuration
|
|
52
|
+
* @param pluginName - Name of the plugin
|
|
53
|
+
* @returns Plugin configuration or undefined if not set
|
|
54
|
+
*/
|
|
23
55
|
getPluginConfig(pluginName) {
|
|
24
56
|
return this.pluginConfigs.get(pluginName);
|
|
25
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Checks if a plugin is registered
|
|
60
|
+
* @param name - Plugin name
|
|
61
|
+
* @returns True if plugin is registered
|
|
62
|
+
*/
|
|
26
63
|
hasPlugin(name) {
|
|
27
64
|
return this.plugins.has(name);
|
|
28
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Gets the number of registered plugins
|
|
68
|
+
* @returns Number of registered plugins
|
|
69
|
+
*/
|
|
29
70
|
getPluginCount() {
|
|
30
71
|
return this.plugins.size;
|
|
31
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* Unregisters a plugin
|
|
75
|
+
* @param name - Plugin name to unregister
|
|
76
|
+
* @returns True if plugin was removed, false if not found
|
|
77
|
+
*/
|
|
32
78
|
unregister(name) {
|
|
33
79
|
const removed = this.plugins.delete(name);
|
|
34
80
|
if (removed) {
|
|
@@ -36,10 +82,19 @@ export class PluginRegistry {
|
|
|
36
82
|
}
|
|
37
83
|
return removed;
|
|
38
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Clears all registered plugins
|
|
87
|
+
*/
|
|
39
88
|
clear() {
|
|
40
89
|
this.plugins.clear();
|
|
41
90
|
this.pluginConfigs.clear();
|
|
42
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Validates that a plugin implements the required interface
|
|
94
|
+
* @param plugin - Plugin to validate
|
|
95
|
+
* @throws {PluginRegistrationError} When plugin is invalid
|
|
96
|
+
* @private
|
|
97
|
+
*/
|
|
43
98
|
validatePlugin(plugin) {
|
|
44
99
|
if (!plugin) {
|
|
45
100
|
throw new PluginRegistrationError('Plugin cannot be null or undefined');
|
|
@@ -56,6 +111,7 @@ export class PluginRegistry {
|
|
|
56
111
|
if (typeof plugin.validate !== 'function') {
|
|
57
112
|
throw new PluginRegistrationError('Plugin must implement validate method', plugin.name);
|
|
58
113
|
}
|
|
114
|
+
// Validate optional fields if present
|
|
59
115
|
if (plugin.description !== undefined && typeof plugin.description !== 'string') {
|
|
60
116
|
throw new PluginRegistrationError('Plugin description must be a string', plugin.name);
|
|
61
117
|
}
|