@lambda-kata/cdk 0.1.3-rc.3 → 0.1.3-rc.4
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/out/dist/index.js +105 -46
- package/out/tsc/src/aws-layer-manager.d.ts +465 -0
- package/out/tsc/src/docker-runtime-detector.d.ts +168 -0
- package/out/tsc/src/ensure-node-runtime-layer.d.ts +42 -0
- package/out/tsc/src/index.d.ts +5 -0
- package/out/tsc/src/kata-wrapper.d.ts +27 -0
- package/out/tsc/src/logger.d.ts +88 -0
- package/out/tsc/src/nodejs-layer-manager.d.ts +419 -0
- package/package.json +6 -5
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWS Lambda Layer Manager with SDK v3 Integration
|
|
3
|
+
*
|
|
4
|
+
* This module provides AWS Lambda Layer management functionality using AWS SDK v3.
|
|
5
|
+
* It handles layer creation, searching, and compatibility validation for Node.js
|
|
6
|
+
* runtime layers used by Lambda Kata.
|
|
7
|
+
*
|
|
8
|
+
* Key features:
|
|
9
|
+
* - AWS SDK v3 Lambda client integration with configurable options
|
|
10
|
+
* - Automatic pagination handling for layer listing operations
|
|
11
|
+
* - Layer compatibility validation based on Node.js version and architecture
|
|
12
|
+
* - Comprehensive error handling with retry logic
|
|
13
|
+
* - Idempotent operations to prevent duplicate layer creation
|
|
14
|
+
*
|
|
15
|
+
* @module aws-layer-manager
|
|
16
|
+
*/
|
|
17
|
+
import { LambdaClientConfig } from '@aws-sdk/client-lambda';
|
|
18
|
+
import { LayerManager, LayerInfo, LayerSearchOptions, LayerRequirements, LayerCreationOptions, Logger } from './nodejs-layer-manager';
|
|
19
|
+
/**
|
|
20
|
+
* Configuration options for AWSLayerManager.
|
|
21
|
+
*/
|
|
22
|
+
export interface AWSLayerManagerOptions {
|
|
23
|
+
/**
|
|
24
|
+
* AWS SDK configuration for Lambda client.
|
|
25
|
+
* If not provided, uses default AWS SDK configuration.
|
|
26
|
+
*/
|
|
27
|
+
awsSdkConfig?: LambdaClientConfig;
|
|
28
|
+
/**
|
|
29
|
+
* Logger for debugging and monitoring.
|
|
30
|
+
* If not provided, uses createDefaultLogger().
|
|
31
|
+
*/
|
|
32
|
+
logger?: Logger;
|
|
33
|
+
/**
|
|
34
|
+
* Maximum age in milliseconds for layers to be considered fresh.
|
|
35
|
+
* Layers older than this may be recreated.
|
|
36
|
+
* Default: 7 days (604800000ms)
|
|
37
|
+
*/
|
|
38
|
+
maxLayerAge?: number;
|
|
39
|
+
/**
|
|
40
|
+
* Maximum number of retries for AWS API operations.
|
|
41
|
+
* Default: 3
|
|
42
|
+
*/
|
|
43
|
+
maxRetries?: number;
|
|
44
|
+
/**
|
|
45
|
+
* Base delay in milliseconds for exponential backoff.
|
|
46
|
+
* Default: 1000ms (1 second)
|
|
47
|
+
*/
|
|
48
|
+
retryBaseDelay?: number;
|
|
49
|
+
/**
|
|
50
|
+
* Circuit breaker failure threshold.
|
|
51
|
+
* Number of consecutive failures before opening the circuit.
|
|
52
|
+
* Default: 5
|
|
53
|
+
*/
|
|
54
|
+
circuitBreakerFailureThreshold?: number;
|
|
55
|
+
/**
|
|
56
|
+
* Circuit breaker timeout in milliseconds.
|
|
57
|
+
* How long to wait before transitioning from OPEN to HALF_OPEN.
|
|
58
|
+
* Default: 60000ms (1 minute)
|
|
59
|
+
*/
|
|
60
|
+
circuitBreakerTimeout?: number;
|
|
61
|
+
/**
|
|
62
|
+
* Circuit breaker success threshold for HALF_OPEN state.
|
|
63
|
+
* Number of consecutive successes needed to close the circuit.
|
|
64
|
+
* Default: 2
|
|
65
|
+
*/
|
|
66
|
+
circuitBreakerSuccessThreshold?: number;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* AWS Lambda Layer Manager implementation using AWS SDK v3.
|
|
70
|
+
*
|
|
71
|
+
* Provides comprehensive layer management functionality including:
|
|
72
|
+
* - Layer searching with pagination support
|
|
73
|
+
* - Layer compatibility validation
|
|
74
|
+
* - Layer creation with proper metadata
|
|
75
|
+
* - Error handling with exponential backoff retry logic
|
|
76
|
+
* - Circuit breaker pattern for AWS API resilience
|
|
77
|
+
* - Concurrent operation coordination to prevent duplicate layer creation
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* const manager = new AWSLayerManager({
|
|
82
|
+
* awsSdkConfig: { region: 'us-east-1' },
|
|
83
|
+
* logger: new ConsoleLogger()
|
|
84
|
+
* });
|
|
85
|
+
*
|
|
86
|
+
* const layer = await manager.findExistingLayer({
|
|
87
|
+
* layerName: 'lambda-kata-nodejs-nodejs20.x-x86_64',
|
|
88
|
+
* requirements: {
|
|
89
|
+
* nodeVersion: '20.10.0',
|
|
90
|
+
* architecture: 'x86_64'
|
|
91
|
+
* }
|
|
92
|
+
* });
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export declare class AWSLayerManager implements LayerManager {
|
|
96
|
+
private readonly lambdaClient;
|
|
97
|
+
private readonly logger;
|
|
98
|
+
private readonly maxLayerAge;
|
|
99
|
+
private readonly maxRetries;
|
|
100
|
+
private readonly retryBaseDelay;
|
|
101
|
+
private readonly circuitBreaker;
|
|
102
|
+
/**
|
|
103
|
+
* Map of layer names to in-progress creation operations.
|
|
104
|
+
* Used to coordinate concurrent calls and prevent duplicate layer creation.
|
|
105
|
+
*/
|
|
106
|
+
private readonly layerCreationLocks;
|
|
107
|
+
/**
|
|
108
|
+
* AWS Lambda Layer size limits (in bytes).
|
|
109
|
+
* These are AWS service limits that cannot be exceeded.
|
|
110
|
+
*/
|
|
111
|
+
private static readonly MAX_LAYER_SIZE_UNZIPPED;
|
|
112
|
+
private static readonly MAX_LAYER_SIZE_ZIPPED;
|
|
113
|
+
/**
|
|
114
|
+
* Docker operation timeout in milliseconds.
|
|
115
|
+
*/
|
|
116
|
+
private static readonly DOCKER_TIMEOUT;
|
|
117
|
+
constructor(options?: AWSLayerManagerOptions);
|
|
118
|
+
/**
|
|
119
|
+
* Searches for an existing compatible Node.js layer.
|
|
120
|
+
*
|
|
121
|
+
* Uses AWS SDK v3 pagination to efficiently search through all layers
|
|
122
|
+
* in the account and region. Validates compatibility based on layer
|
|
123
|
+
* metadata and requirements.
|
|
124
|
+
*
|
|
125
|
+
* @param options - Search criteria and requirements
|
|
126
|
+
* @returns Promise resolving to layer info if found, null otherwise
|
|
127
|
+
* @throws NodeRuntimeLayerError if search fails
|
|
128
|
+
*/
|
|
129
|
+
findExistingLayer(options: LayerSearchOptions): Promise<LayerInfo | null>;
|
|
130
|
+
/**
|
|
131
|
+
* Creates a new Node.js Lambda Layer with concurrent operation coordination.
|
|
132
|
+
*
|
|
133
|
+
* This method extracts the Node.js binary from the corresponding AWS Lambda
|
|
134
|
+
* Docker image, packages it in the proper Lambda Layer directory structure,
|
|
135
|
+
* and publishes it to AWS Lambda with appropriate metadata.
|
|
136
|
+
*
|
|
137
|
+
* Enhanced with concurrent operation coordination to prevent duplicate layer
|
|
138
|
+
* creation when multiple calls are made with identical parameters. If a layer
|
|
139
|
+
* creation is already in progress for the same layer name, subsequent calls
|
|
140
|
+
* will wait for the existing operation to complete rather than starting a
|
|
141
|
+
* duplicate operation.
|
|
142
|
+
*
|
|
143
|
+
* Process:
|
|
144
|
+
* 1. Check for existing in-progress layer creation operation
|
|
145
|
+
* 2. If operation exists, wait for its completion
|
|
146
|
+
* 3. If no operation exists, start new layer creation with lock
|
|
147
|
+
* 4. Create temporary directory for layer contents
|
|
148
|
+
* 5. Extract Node.js binary from Docker container
|
|
149
|
+
* 6. Create proper Lambda Layer directory structure (/opt/nodejs/bin/)
|
|
150
|
+
* 7. Create ZIP archive with correct permissions
|
|
151
|
+
* 8. Validate size limits
|
|
152
|
+
* 9. Publish to AWS Lambda
|
|
153
|
+
* 10. Clean up temporary files and release lock
|
|
154
|
+
*
|
|
155
|
+
* Enhanced with comprehensive resource cleanup on failure to prevent orphaned resources.
|
|
156
|
+
*
|
|
157
|
+
* @param options - Layer creation configuration
|
|
158
|
+
* @returns Promise resolving to information about the created layer
|
|
159
|
+
* @throws NodeRuntimeLayerError if creation fails
|
|
160
|
+
*/
|
|
161
|
+
createNodeLayer(options: LayerCreationOptions): Promise<LayerInfo>;
|
|
162
|
+
/**
|
|
163
|
+
* Performs the actual layer creation operation without concurrent coordination.
|
|
164
|
+
*
|
|
165
|
+
* This is the core layer creation logic extracted from the original createNodeLayer
|
|
166
|
+
* method to separate concerns between concurrent coordination and actual creation.
|
|
167
|
+
*
|
|
168
|
+
* @param options - Layer creation configuration
|
|
169
|
+
* @returns Promise resolving to information about the created layer
|
|
170
|
+
* @throws NodeRuntimeLayerError if creation fails
|
|
171
|
+
*/
|
|
172
|
+
private performLayerCreation;
|
|
173
|
+
/**
|
|
174
|
+
* Validates whether a layer meets the specified requirements.
|
|
175
|
+
*
|
|
176
|
+
* Checks layer compatibility based on:
|
|
177
|
+
* - Node.js version exact match
|
|
178
|
+
* - Architecture compatibility
|
|
179
|
+
* - Layer age (if maxAge is specified in requirements)
|
|
180
|
+
*
|
|
181
|
+
* @param layer - The layer to validate
|
|
182
|
+
* @param requirements - The requirements to check against
|
|
183
|
+
* @returns true if the layer is compatible, false otherwise
|
|
184
|
+
*/
|
|
185
|
+
validateLayerCompatibility(layer: LayerInfo, requirements: LayerRequirements): boolean;
|
|
186
|
+
/**
|
|
187
|
+
* Lists layers by name using AWS SDK v3 pagination with retry logic.
|
|
188
|
+
*
|
|
189
|
+
* Efficiently searches through all layers in the account and region
|
|
190
|
+
* to find layers matching the specified name pattern. Uses retry logic
|
|
191
|
+
* to handle transient pagination failures.
|
|
192
|
+
*
|
|
193
|
+
* @param layerName - The layer name to search for
|
|
194
|
+
* @returns Promise resolving to array of matching layers
|
|
195
|
+
* @throws Error if AWS API operations fail
|
|
196
|
+
*/
|
|
197
|
+
private listLayersByName;
|
|
198
|
+
/**
|
|
199
|
+
* Gets detailed information about a specific layer version.
|
|
200
|
+
*
|
|
201
|
+
* Retrieves layer metadata and extracts Node.js version and architecture
|
|
202
|
+
* information from the layer description or other metadata.
|
|
203
|
+
*
|
|
204
|
+
* @param layerName - The name of the layer
|
|
205
|
+
* @param version - The version number of the layer
|
|
206
|
+
* @returns Promise resolving to LayerInfo
|
|
207
|
+
* @throws Error if layer information cannot be retrieved
|
|
208
|
+
*/
|
|
209
|
+
private getLayerInfo;
|
|
210
|
+
/**
|
|
211
|
+
* Parses layer metadata to extract Node.js version and architecture.
|
|
212
|
+
*
|
|
213
|
+
* Attempts to extract information from layer description or falls back
|
|
214
|
+
* to parsing the layer name if description doesn't contain the required data.
|
|
215
|
+
*
|
|
216
|
+
* @param description - The layer description
|
|
217
|
+
* @param layerName - The layer name as fallback
|
|
218
|
+
* @returns Object containing nodeVersion and architecture
|
|
219
|
+
*/
|
|
220
|
+
private parseLayerMetadata;
|
|
221
|
+
/**
|
|
222
|
+
* Executes an AWS API operation with exponential backoff retry logic and circuit breaker protection.
|
|
223
|
+
*
|
|
224
|
+
* Implements retry logic for transient AWS API failures with exponential
|
|
225
|
+
* backoff and jitter to avoid thundering herd problems. Uses circuit breaker
|
|
226
|
+
* pattern to prevent cascading failures during AWS service outages.
|
|
227
|
+
*
|
|
228
|
+
* @param operation - The async operation to execute
|
|
229
|
+
* @returns Promise resolving to the operation result
|
|
230
|
+
* @throws Error if all retries are exhausted or circuit breaker is open
|
|
231
|
+
*/
|
|
232
|
+
private executeWithRetry;
|
|
233
|
+
/**
|
|
234
|
+
* Determines if an error is retryable.
|
|
235
|
+
*
|
|
236
|
+
* @param error - The error to check
|
|
237
|
+
* @returns true if the error is retryable, false otherwise
|
|
238
|
+
*/
|
|
239
|
+
private isRetryableError;
|
|
240
|
+
/**
|
|
241
|
+
* Checks if an error is a network-related error that should be retried.
|
|
242
|
+
*
|
|
243
|
+
* @param error - The error to check
|
|
244
|
+
* @returns true if it's a retryable network error
|
|
245
|
+
*/
|
|
246
|
+
private isNetworkError;
|
|
247
|
+
/**
|
|
248
|
+
* Calculates retry delay with exponential backoff and jitter.
|
|
249
|
+
*
|
|
250
|
+
* @param attempt - The current attempt number (0-based)
|
|
251
|
+
* @returns Delay in milliseconds
|
|
252
|
+
*/
|
|
253
|
+
private calculateRetryDelay;
|
|
254
|
+
/**
|
|
255
|
+
* Sleeps for the specified number of milliseconds.
|
|
256
|
+
*
|
|
257
|
+
* @param ms - Milliseconds to sleep
|
|
258
|
+
* @returns Promise that resolves after the delay
|
|
259
|
+
*/
|
|
260
|
+
private sleep;
|
|
261
|
+
/**
|
|
262
|
+
* Gets the current circuit breaker state for monitoring and debugging.
|
|
263
|
+
*
|
|
264
|
+
* @returns Object containing circuit breaker state information
|
|
265
|
+
*/
|
|
266
|
+
getCircuitBreakerState(): {
|
|
267
|
+
state: string;
|
|
268
|
+
failureCount: number;
|
|
269
|
+
successCount: number;
|
|
270
|
+
};
|
|
271
|
+
/**
|
|
272
|
+
* Gets the current concurrent operation state for monitoring and debugging.
|
|
273
|
+
*
|
|
274
|
+
* @returns Object containing information about in-progress layer creation operations
|
|
275
|
+
*/
|
|
276
|
+
getConcurrentOperationState(): {
|
|
277
|
+
activeOperations: number;
|
|
278
|
+
operations: Array<{
|
|
279
|
+
layerName: string;
|
|
280
|
+
startTime: number;
|
|
281
|
+
duration: number;
|
|
282
|
+
waiters: number;
|
|
283
|
+
nodeVersion: string;
|
|
284
|
+
architecture: string;
|
|
285
|
+
}>;
|
|
286
|
+
};
|
|
287
|
+
/**
|
|
288
|
+
* Destroys the AWS Lambda client and cleans up resources.
|
|
289
|
+
*
|
|
290
|
+
* Should be called when the manager is no longer needed to prevent
|
|
291
|
+
* resource leaks. Also cleans up any remaining concurrent operation locks.
|
|
292
|
+
*/
|
|
293
|
+
destroy(): void;
|
|
294
|
+
/**
|
|
295
|
+
* Creates a temporary directory for layer creation operations.
|
|
296
|
+
*
|
|
297
|
+
* @returns Promise resolving to the temporary directory path
|
|
298
|
+
* @throws Error if directory creation fails
|
|
299
|
+
*/
|
|
300
|
+
private createTempDirectory;
|
|
301
|
+
/**
|
|
302
|
+
* Extracts Node.js binary from AWS Lambda Docker container with resource tracking.
|
|
303
|
+
*
|
|
304
|
+
* Enhanced version that tracks Docker containers for cleanup on failure.
|
|
305
|
+
* Uses Docker to run the AWS Lambda runtime image and copy the Node.js
|
|
306
|
+
* binary to the local filesystem for packaging in the layer.
|
|
307
|
+
*
|
|
308
|
+
* @param nodeVersion - The Node.js version (e.g., "20.10.0")
|
|
309
|
+
* @param architecture - The target architecture
|
|
310
|
+
* @param tempDir - Temporary directory for extraction
|
|
311
|
+
* @param resourceTracker - Resource tracker for cleanup
|
|
312
|
+
* @returns Promise resolving to the path of the extracted binary
|
|
313
|
+
* @throws NodeRuntimeLayerError if extraction fails
|
|
314
|
+
*/
|
|
315
|
+
private extractNodeBinaryFromDockerWithTracking;
|
|
316
|
+
/**
|
|
317
|
+
* Creates the proper Lambda Layer directory structure.
|
|
318
|
+
*
|
|
319
|
+
* Lambda Layers must follow a specific directory structure:
|
|
320
|
+
* - /opt/nodejs/bin/ for Node.js binaries
|
|
321
|
+
*
|
|
322
|
+
* @param tempDir - Base temporary directory
|
|
323
|
+
* @param nodeBinaryPath - Path to the Node.js binary
|
|
324
|
+
* @returns Promise resolving to the layer directory path
|
|
325
|
+
* @throws Error if directory creation fails
|
|
326
|
+
*/
|
|
327
|
+
private createLayerDirectoryStructure;
|
|
328
|
+
/**
|
|
329
|
+
* Creates a ZIP archive of the layer contents with compression optimization.
|
|
330
|
+
*
|
|
331
|
+
* Uses Python's zipfile module to create a properly compressed ZIP file with
|
|
332
|
+
* file permissions preserved for the Node.js binary. Implements compression
|
|
333
|
+
* optimization to minimize storage and transfer costs.
|
|
334
|
+
*
|
|
335
|
+
* @param layerDir - Directory containing the layer contents
|
|
336
|
+
* @param layerName - Name of the layer (used for ZIP filename)
|
|
337
|
+
* @returns Promise resolving to the ZIP file path
|
|
338
|
+
* @throws Error if ZIP creation fails
|
|
339
|
+
*/
|
|
340
|
+
private createLayerZipArchive;
|
|
341
|
+
/**
|
|
342
|
+
* Calculates the total size of all files in a directory.
|
|
343
|
+
*
|
|
344
|
+
* @param dirPath - Directory path to analyze
|
|
345
|
+
* @returns Promise resolving to total size in bytes
|
|
346
|
+
*/
|
|
347
|
+
private calculateDirectorySize;
|
|
348
|
+
/**
|
|
349
|
+
* Fallback ZIP creation using system zip command.
|
|
350
|
+
*
|
|
351
|
+
* @param layerDir - Directory containing the layer contents
|
|
352
|
+
* @param zipFilePath - Target ZIP file path
|
|
353
|
+
* @returns Promise resolving to the ZIP file path
|
|
354
|
+
* @throws Error if ZIP creation fails
|
|
355
|
+
*/
|
|
356
|
+
private createZipFallback;
|
|
357
|
+
/**
|
|
358
|
+
* Validates that the layer ZIP file meets AWS size limits.
|
|
359
|
+
*
|
|
360
|
+
* AWS Lambda has strict size limits for layers:
|
|
361
|
+
* - 50MB for zipped layer
|
|
362
|
+
* - 250MB for unzipped layer
|
|
363
|
+
*
|
|
364
|
+
* Enhanced to check both zipped and unzipped sizes with comprehensive
|
|
365
|
+
* error reporting and optimization suggestions.
|
|
366
|
+
*
|
|
367
|
+
* @param zipFilePath - Path to the ZIP file
|
|
368
|
+
* @throws NodeRuntimeLayerError if size limits are exceeded
|
|
369
|
+
*/
|
|
370
|
+
private preValidateLayerContent;
|
|
371
|
+
/**
|
|
372
|
+
* Validates layer size limits after ZIP creation.
|
|
373
|
+
*
|
|
374
|
+
* @param zipFilePath - Path to the ZIP file
|
|
375
|
+
* @throws NodeRuntimeLayerError if size limits are exceeded
|
|
376
|
+
*/
|
|
377
|
+
private validateLayerSize;
|
|
378
|
+
/**
|
|
379
|
+
* Calculates the unzipped size of a ZIP file by examining its contents.
|
|
380
|
+
*
|
|
381
|
+
* Uses Python's zipfile module to read ZIP metadata and calculate
|
|
382
|
+
* the total uncompressed size without extracting files.
|
|
383
|
+
*
|
|
384
|
+
* @param zipFilePath - Path to the ZIP file
|
|
385
|
+
* @returns Promise resolving to unzipped size in bytes
|
|
386
|
+
* @throws Error if size calculation fails
|
|
387
|
+
*/
|
|
388
|
+
private calculateUnzippedSize;
|
|
389
|
+
/**
|
|
390
|
+
* Publishes the layer to AWS Lambda.
|
|
391
|
+
*
|
|
392
|
+
* Uses the AWS SDK v3 Lambda client to publish the layer with proper
|
|
393
|
+
* metadata including compatible runtimes and architectures.
|
|
394
|
+
*
|
|
395
|
+
* @param options - Layer creation options
|
|
396
|
+
* @param zipFilePath - Path to the ZIP file
|
|
397
|
+
* @returns Promise resolving to LayerInfo
|
|
398
|
+
* @throws NodeRuntimeLayerError if publishing fails
|
|
399
|
+
*/
|
|
400
|
+
private publishLayerToAWS;
|
|
401
|
+
/**
|
|
402
|
+
* Executes a Docker command with timeout and error handling.
|
|
403
|
+
*
|
|
404
|
+
* @param args - Docker command arguments
|
|
405
|
+
* @returns Promise that resolves when command completes successfully
|
|
406
|
+
* @throws Error if command fails
|
|
407
|
+
*/
|
|
408
|
+
private executeDockerCommand;
|
|
409
|
+
/**
|
|
410
|
+
* Executes a system command with timeout and error handling, capturing output.
|
|
411
|
+
*
|
|
412
|
+
* @param command - Command to execute
|
|
413
|
+
* @param args - Command arguments
|
|
414
|
+
* @param options - Execution options including working directory
|
|
415
|
+
* @returns Promise resolving to command output (stdout and stderr)
|
|
416
|
+
* @throws Error if command fails
|
|
417
|
+
*/
|
|
418
|
+
private executeCommandWithOutput;
|
|
419
|
+
/**
|
|
420
|
+
* Executes a system command with timeout and error handling.
|
|
421
|
+
*
|
|
422
|
+
* @param command - Command to execute
|
|
423
|
+
* @param args - Command arguments
|
|
424
|
+
* @param options - Execution options including working directory
|
|
425
|
+
* @returns Promise that resolves when command completes successfully
|
|
426
|
+
* @throws Error if command fails
|
|
427
|
+
*/
|
|
428
|
+
private executeCommand;
|
|
429
|
+
/**
|
|
430
|
+
* Legacy cleanup method for backward compatibility.
|
|
431
|
+
*
|
|
432
|
+
* @deprecated Use performComprehensiveCleanup with ResourceTracker instead
|
|
433
|
+
* @param tempDir - Temporary directory to remove (if exists)
|
|
434
|
+
* @param zipFilePath - ZIP file to remove (if exists)
|
|
435
|
+
*/
|
|
436
|
+
private cleanupTempResources;
|
|
437
|
+
/**
|
|
438
|
+
* Legacy Docker extraction method for backward compatibility.
|
|
439
|
+
*
|
|
440
|
+
* @deprecated Use extractNodeBinaryFromDockerWithTracking instead
|
|
441
|
+
*/
|
|
442
|
+
private extractNodeBinaryFromDocker;
|
|
443
|
+
/**
|
|
444
|
+
* Creates an enhanced error with cleanup context preservation.
|
|
445
|
+
*
|
|
446
|
+
* Preserves the original error while adding context about the layer creation
|
|
447
|
+
* operation that failed. This maintains debugging capability while providing
|
|
448
|
+
* additional context for troubleshooting.
|
|
449
|
+
*
|
|
450
|
+
* @param originalError - The original error that occurred
|
|
451
|
+
* @param options - Layer creation options for context
|
|
452
|
+
* @returns Enhanced NodeRuntimeLayerError with preserved context
|
|
453
|
+
*/
|
|
454
|
+
private createEnhancedError;
|
|
455
|
+
/**
|
|
456
|
+
* Performs comprehensive cleanup of all tracked resources.
|
|
457
|
+
*
|
|
458
|
+
* Cleans up Docker containers, temporary directories, and ZIP files.
|
|
459
|
+
* Cleanup failures are logged as warnings but do not prevent the cleanup
|
|
460
|
+
* of other resources or mask the original error.
|
|
461
|
+
*
|
|
462
|
+
* @param resourceTracker - Tracker containing all resources to clean up
|
|
463
|
+
*/
|
|
464
|
+
private performComprehensiveCleanup;
|
|
465
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { RuntimeDetector, NodeVersionInfo, Logger } from './nodejs-layer-manager';
|
|
2
|
+
/**
|
|
3
|
+
* Configuration options for DockerRuntimeDetector.
|
|
4
|
+
*/
|
|
5
|
+
export interface DockerRuntimeDetectorOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Cache TTL in milliseconds. Default: 1 hour (3600000ms)
|
|
8
|
+
*/
|
|
9
|
+
cacheTtl?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Docker command timeout in milliseconds. Default: 60 seconds (60000ms)
|
|
12
|
+
*/
|
|
13
|
+
dockerTimeout?: number;
|
|
14
|
+
/**
|
|
15
|
+
* Logger for debugging and monitoring. Default: createDefaultLogger()
|
|
16
|
+
*/
|
|
17
|
+
logger?: Logger;
|
|
18
|
+
/**
|
|
19
|
+
* Whether to enable fallback to known version mappings when Docker fails.
|
|
20
|
+
* Default: true
|
|
21
|
+
*/
|
|
22
|
+
enableFallback?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Docker-based implementation of RuntimeDetector.
|
|
26
|
+
*
|
|
27
|
+
* Uses official AWS Lambda runtime Docker images to detect exact Node.js versions.
|
|
28
|
+
* Implements caching to avoid repeated Docker operations and provides fallback
|
|
29
|
+
* version mappings when Docker is unavailable.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* const detector = new DockerRuntimeDetector();
|
|
34
|
+
* const versionInfo = await detector.detectNodeVersion('nodejs20.x', 'x86_64');
|
|
35
|
+
* console.log(`Node.js version: ${versionInfo.version}`);
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare class DockerRuntimeDetector implements RuntimeDetector {
|
|
39
|
+
private readonly versionCache;
|
|
40
|
+
private readonly cacheTtl;
|
|
41
|
+
private readonly dockerTimeout;
|
|
42
|
+
private readonly logger;
|
|
43
|
+
private readonly enableFallback;
|
|
44
|
+
/**
|
|
45
|
+
* Known fallback version mappings for when Docker is unavailable.
|
|
46
|
+
* These are based on AWS Lambda runtime documentation and should be
|
|
47
|
+
* updated when AWS releases new runtime versions.
|
|
48
|
+
*/
|
|
49
|
+
private static readonly FALLBACK_VERSIONS;
|
|
50
|
+
/**
|
|
51
|
+
* Supported AWS Lambda Node.js runtimes.
|
|
52
|
+
*/
|
|
53
|
+
private static readonly SUPPORTED_RUNTIMES;
|
|
54
|
+
/**
|
|
55
|
+
* Supported architectures.
|
|
56
|
+
*/
|
|
57
|
+
private static readonly SUPPORTED_ARCHITECTURES;
|
|
58
|
+
constructor(options?: DockerRuntimeDetectorOptions);
|
|
59
|
+
/**
|
|
60
|
+
* Detects the exact Node.js version for a given runtime and architecture.
|
|
61
|
+
*
|
|
62
|
+
* First checks the cache for existing version information. If not cached or expired,
|
|
63
|
+
* attempts to detect the version using Docker. Falls back to known version mappings
|
|
64
|
+
* if Docker operations fail and fallback is enabled.
|
|
65
|
+
*
|
|
66
|
+
* @param runtimeName - The AWS Lambda runtime (e.g., "nodejs20.x")
|
|
67
|
+
* @param architecture - The target architecture ("x86_64" or "arm64")
|
|
68
|
+
* @returns Promise resolving to Node.js version information
|
|
69
|
+
* @throws NodeRuntimeLayerError if detection fails
|
|
70
|
+
*/
|
|
71
|
+
detectNodeVersion(runtimeName: string, architecture: string): Promise<NodeVersionInfo>;
|
|
72
|
+
/**
|
|
73
|
+
* Validates input parameters for runtime name and architecture.
|
|
74
|
+
*
|
|
75
|
+
* @param runtimeName - The runtime name to validate
|
|
76
|
+
* @param architecture - The architecture to validate
|
|
77
|
+
* @throws NodeRuntimeLayerError if inputs are invalid
|
|
78
|
+
*/
|
|
79
|
+
private validateInputs;
|
|
80
|
+
/**
|
|
81
|
+
* Retrieves cached version information if available and not expired.
|
|
82
|
+
*
|
|
83
|
+
* @param cacheKey - The cache key to look up
|
|
84
|
+
* @returns Cached version entry if valid, null otherwise
|
|
85
|
+
*/
|
|
86
|
+
private getCachedVersion;
|
|
87
|
+
/**
|
|
88
|
+
* Caches version information with TTL.
|
|
89
|
+
*
|
|
90
|
+
* @param cacheKey - The cache key to store under
|
|
91
|
+
* @param versionInfo - The version information to cache
|
|
92
|
+
*/
|
|
93
|
+
private cacheVersion;
|
|
94
|
+
/**
|
|
95
|
+
* Detects Node.js version using Docker by pulling AWS Lambda runtime image
|
|
96
|
+
* and executing `node --version` within a container.
|
|
97
|
+
*
|
|
98
|
+
* @param runtimeName - The AWS Lambda runtime name
|
|
99
|
+
* @param architecture - The target architecture
|
|
100
|
+
* @returns Promise resolving to version information
|
|
101
|
+
* @throws NodeRuntimeLayerError if Docker operations fail
|
|
102
|
+
*/
|
|
103
|
+
private detectVersionFromDocker;
|
|
104
|
+
/**
|
|
105
|
+
* Builds the Docker image name for AWS Lambda runtime.
|
|
106
|
+
*
|
|
107
|
+
* @param runtimeName - The AWS Lambda runtime name (e.g., "nodejs20.x")
|
|
108
|
+
* @param architecture - The target architecture
|
|
109
|
+
* @returns Docker image name (e.g., "public.ecr.aws/lambda/nodejs:20-x86_64")
|
|
110
|
+
*/
|
|
111
|
+
private buildDockerImageName;
|
|
112
|
+
/**
|
|
113
|
+
* Checks if Docker image exists locally before pulling.
|
|
114
|
+
*
|
|
115
|
+
* @param dockerImage - The Docker image to check
|
|
116
|
+
* @returns Promise<boolean> - true if image exists locally
|
|
117
|
+
*/
|
|
118
|
+
private checkDockerImageExists;
|
|
119
|
+
/**
|
|
120
|
+
* Pulls a Docker image using the docker pull command.
|
|
121
|
+
* Optimized to skip pull if image already exists locally.
|
|
122
|
+
*
|
|
123
|
+
* @param dockerImage - The Docker image to pull
|
|
124
|
+
* @returns Promise that resolves when the image is pulled
|
|
125
|
+
* @throws Error if docker pull fails
|
|
126
|
+
*/
|
|
127
|
+
private pullDockerImage;
|
|
128
|
+
/**
|
|
129
|
+
* Extracts Node.js version by running `node --version` in a Docker container.
|
|
130
|
+
*
|
|
131
|
+
* @param dockerImage - The Docker image to run
|
|
132
|
+
* @returns Promise resolving to the Node.js version string
|
|
133
|
+
* @throws Error if container execution fails
|
|
134
|
+
*/
|
|
135
|
+
private extractNodeVersionFromContainer;
|
|
136
|
+
/**
|
|
137
|
+
* Validates that a version string follows semantic versioning format.
|
|
138
|
+
*
|
|
139
|
+
* @param version - The version string to validate
|
|
140
|
+
* @returns true if the version is valid, false otherwise
|
|
141
|
+
*/
|
|
142
|
+
private isValidSemanticVersion;
|
|
143
|
+
/**
|
|
144
|
+
* Provides fallback version information when Docker detection fails.
|
|
145
|
+
*
|
|
146
|
+
* @param runtimeName - The AWS Lambda runtime name
|
|
147
|
+
* @param architecture - The target architecture
|
|
148
|
+
* @returns NodeVersionInfo with fallback version
|
|
149
|
+
* @throws NodeRuntimeLayerError if no fallback is available
|
|
150
|
+
*/
|
|
151
|
+
private getFallbackVersion;
|
|
152
|
+
/**
|
|
153
|
+
* Clears the version cache.
|
|
154
|
+
* Useful for testing or when cache invalidation is needed.
|
|
155
|
+
*/
|
|
156
|
+
clearCache(): void;
|
|
157
|
+
/**
|
|
158
|
+
* Gets the current cache size.
|
|
159
|
+
* Useful for monitoring and debugging.
|
|
160
|
+
*/
|
|
161
|
+
getCacheSize(): number;
|
|
162
|
+
/**
|
|
163
|
+
* Checks if Docker is available on the system.
|
|
164
|
+
*
|
|
165
|
+
* @returns Promise resolving to true if Docker is available, false otherwise
|
|
166
|
+
*/
|
|
167
|
+
isDockerAvailable(): Promise<boolean>;
|
|
168
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main API function for Node.js runtime layer management
|
|
3
|
+
*
|
|
4
|
+
* This module provides the primary entry point for ensuring Node.js runtime layers
|
|
5
|
+
* exist in AWS Lambda. It coordinates between runtime detection and layer management
|
|
6
|
+
* components to provide a seamless experience for CDK integration.
|
|
7
|
+
*
|
|
8
|
+
* @module ensure-node-runtime-layer
|
|
9
|
+
*/
|
|
10
|
+
import { EnsureNodeRuntimeLayerOptions, EnsureNodeRuntimeLayerResult } from './nodejs-layer-manager';
|
|
11
|
+
/**
|
|
12
|
+
* Ensures a Node.js runtime layer exists for the specified configuration.
|
|
13
|
+
*
|
|
14
|
+
* This is the main API function that coordinates runtime detection and layer management
|
|
15
|
+
* to ensure the correct Node.js binaries are available for Lambda Kata execution.
|
|
16
|
+
*
|
|
17
|
+
* The function performs the following operations:
|
|
18
|
+
* 1. Validates all input parameters
|
|
19
|
+
* 2. Detects the exact Node.js version for the runtime
|
|
20
|
+
* 3. Searches for existing compatible layers
|
|
21
|
+
* 4. Creates a new layer if none exists or is compatible
|
|
22
|
+
* 5. Returns comprehensive result information
|
|
23
|
+
*
|
|
24
|
+
* @param options - Configuration options for layer management
|
|
25
|
+
* @returns Promise resolving to layer information and metadata
|
|
26
|
+
* @throws NodeRuntimeLayerError for validation failures or operational errors
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* const result = await ensureNodeRuntimeLayer({
|
|
31
|
+
* runtimeName: 'nodejs20.x',
|
|
32
|
+
* architecture: 'x86_64',
|
|
33
|
+
* region: 'us-east-1',
|
|
34
|
+
* accountId: '123456789012'
|
|
35
|
+
* });
|
|
36
|
+
*
|
|
37
|
+
* console.log(`Layer ARN: ${result.layerArn}`);
|
|
38
|
+
* console.log(`Node.js version: ${result.nodeVersion}`);
|
|
39
|
+
* console.log(`Created new layer: ${result.created}`);
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function ensureNodeRuntimeLayer(options: EnsureNodeRuntimeLayerOptions): Promise<EnsureNodeRuntimeLayerResult>;
|
package/out/tsc/src/index.d.ts
CHANGED
|
@@ -23,3 +23,8 @@ export { MockLicensingService, createMockLicensingService, } from './mock-licens
|
|
|
23
23
|
export { resolveAccountId, resolveAccountIdWithSource, isValidAccountIdFormat, AccountResolutionError, AccountResolutionResult, AccountResolverOptions, } from './account-resolver';
|
|
24
24
|
export { kata, kataWithAccountId, applyTransformation, handleUnlicensed, isKataTransformed, getKataPromise, KataWrapperOptions, KataResult, } from './kata-wrapper';
|
|
25
25
|
export { createKataConfigLayer, generateConfigContent, KataConfigLayerProps, CONFIG_DIR_NAME, CONFIG_FILE_NAME, HANDLER_CONFIG_KEY, } from './config-layer';
|
|
26
|
+
export { EnsureNodeRuntimeLayerOptions, EnsureNodeRuntimeLayerResult, NodeVersionInfo, LayerInfo, LayerSearchOptions, LayerRequirements, LayerCreationOptions, Logger, RuntimeDetector, LayerManager, ErrorCodes, NodeRuntimeLayerError, VersionCacheEntry, LayerMetadata, } from './nodejs-layer-manager';
|
|
27
|
+
export { DockerRuntimeDetector, DockerRuntimeDetectorOptions, } from './docker-runtime-detector';
|
|
28
|
+
export { AWSLayerManager, AWSLayerManagerOptions, } from './aws-layer-manager';
|
|
29
|
+
export { NoOpLogger, ConsoleLogger, createDefaultLogger, OperationTimer, } from './logger';
|
|
30
|
+
export { ensureNodeRuntimeLayer } from './ensure-node-runtime-layer';
|