@lambda-kata/cdk 0.1.3-rc.2 → 0.1.3-rc.21
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 +203 -57
- package/out/tsc/src/aws-layer-manager.d.ts +640 -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 -14
- package/out/tsc/src/logger.d.ts +88 -0
- package/out/tsc/src/nodejs-layer-manager.d.ts +547 -0
- package/package.json +8 -6
|
@@ -0,0 +1,640 @@
|
|
|
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 { S3ClientConfig } from '@aws-sdk/client-s3';
|
|
19
|
+
import { LayerCreationOptions, LayerInfo, LayerManager, LayerRequirements, LayerSearchOptions, Logger, MultiArchitectureDeploymentResult, NodejsLayerDeploymentOptions, NodejsLayerDeploymentResult } from './nodejs-layer-manager';
|
|
20
|
+
/**
|
|
21
|
+
* Configuration options for AWSLayerManager.
|
|
22
|
+
*/
|
|
23
|
+
export interface AWSLayerManagerOptions {
|
|
24
|
+
/**
|
|
25
|
+
* AWS SDK configuration for Lambda client.
|
|
26
|
+
* If not provided, uses default AWS SDK configuration.
|
|
27
|
+
*/
|
|
28
|
+
awsSdkConfig?: LambdaClientConfig;
|
|
29
|
+
/**
|
|
30
|
+
* AWS SDK configuration for S3 client.
|
|
31
|
+
* If not provided, uses the same configuration as Lambda client.
|
|
32
|
+
*/
|
|
33
|
+
s3SdkConfig?: S3ClientConfig;
|
|
34
|
+
/**
|
|
35
|
+
* Logger for debugging and monitoring.
|
|
36
|
+
* If not provided, uses createDefaultLogger().
|
|
37
|
+
*/
|
|
38
|
+
logger?: Logger;
|
|
39
|
+
/**
|
|
40
|
+
* Maximum age in milliseconds for layers to be considered fresh.
|
|
41
|
+
* Layers older than this may be recreated.
|
|
42
|
+
* Default: 7 days (604800000ms)
|
|
43
|
+
*/
|
|
44
|
+
maxLayerAge?: number;
|
|
45
|
+
/**
|
|
46
|
+
* Maximum number of retries for AWS API operations.
|
|
47
|
+
* Default: 3
|
|
48
|
+
*/
|
|
49
|
+
maxRetries?: number;
|
|
50
|
+
/**
|
|
51
|
+
* Base delay in milliseconds for exponential backoff.
|
|
52
|
+
* Default: 1000ms (1 second)
|
|
53
|
+
*/
|
|
54
|
+
retryBaseDelay?: number;
|
|
55
|
+
/**
|
|
56
|
+
* Circuit breaker failure threshold.
|
|
57
|
+
* Number of consecutive failures before opening the circuit.
|
|
58
|
+
* Default: 5
|
|
59
|
+
*/
|
|
60
|
+
circuitBreakerFailureThreshold?: number;
|
|
61
|
+
/**
|
|
62
|
+
* Circuit breaker timeout in milliseconds.
|
|
63
|
+
* How long to wait before transitioning from OPEN to HALF_OPEN.
|
|
64
|
+
* Default: 60000ms (1 minute)
|
|
65
|
+
*/
|
|
66
|
+
circuitBreakerTimeout?: number;
|
|
67
|
+
/**
|
|
68
|
+
* Circuit breaker success threshold for HALF_OPEN state.
|
|
69
|
+
* Number of consecutive successes needed to close the circuit.
|
|
70
|
+
* Default: 2
|
|
71
|
+
*/
|
|
72
|
+
circuitBreakerSuccessThreshold?: number;
|
|
73
|
+
/**
|
|
74
|
+
* Enable S3 support for large layer uploads.
|
|
75
|
+
* If true, creates S3Client for handling layers >50MB.
|
|
76
|
+
* Default: true
|
|
77
|
+
*/
|
|
78
|
+
enableS3Support?: boolean;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* AWS Lambda Layer Manager implementation using AWS SDK v3.
|
|
82
|
+
*
|
|
83
|
+
* Provides comprehensive layer management functionality including:
|
|
84
|
+
* - Layer searching with pagination support
|
|
85
|
+
* - Layer compatibility validation
|
|
86
|
+
* - Layer creation with proper metadata
|
|
87
|
+
* - Error handling with exponential backoff retry logic
|
|
88
|
+
* - Circuit breaker pattern for AWS API resilience
|
|
89
|
+
* - Concurrent operation coordination to prevent duplicate layer creation
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* const manager = new AWSLayerManager({
|
|
94
|
+
* awsSdkConfig: { region: 'us-east-1' },
|
|
95
|
+
* logger: new ConsoleLogger()
|
|
96
|
+
* });
|
|
97
|
+
*
|
|
98
|
+
* const layer = await manager.findExistingLayer({
|
|
99
|
+
* layerName: 'lambda-kata-nodejs-nodejs20.x-x86_64',
|
|
100
|
+
* requirements: {
|
|
101
|
+
* nodeVersion: '20.10.0',
|
|
102
|
+
* architecture: 'x86_64'
|
|
103
|
+
* }
|
|
104
|
+
* });
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
export declare class AWSLayerManager implements LayerManager {
|
|
108
|
+
private readonly lambdaClient;
|
|
109
|
+
private readonly s3Client;
|
|
110
|
+
private readonly logger;
|
|
111
|
+
private readonly maxLayerAge;
|
|
112
|
+
private readonly maxRetries;
|
|
113
|
+
private readonly retryBaseDelay;
|
|
114
|
+
private readonly circuitBreaker;
|
|
115
|
+
/**
|
|
116
|
+
* Map of layer names to in-progress creation operations.
|
|
117
|
+
* Used to coordinate concurrent calls and prevent duplicate layer creation.
|
|
118
|
+
*/
|
|
119
|
+
private readonly layerCreationLocks;
|
|
120
|
+
/**
|
|
121
|
+
* AWS Lambda Layer size limits (in bytes).
|
|
122
|
+
* These are AWS service limits that cannot be exceeded.
|
|
123
|
+
*/
|
|
124
|
+
private static readonly MAX_LAYER_SIZE_UNZIPPED;
|
|
125
|
+
private static readonly MAX_LAYER_SIZE_ZIPPED;
|
|
126
|
+
/**
|
|
127
|
+
* Docker operation timeout in milliseconds.
|
|
128
|
+
*/
|
|
129
|
+
private static readonly DOCKER_TIMEOUT;
|
|
130
|
+
constructor(options?: AWSLayerManagerOptions);
|
|
131
|
+
/**
|
|
132
|
+
* Searches for an existing compatible Node.js layer.
|
|
133
|
+
*
|
|
134
|
+
* Uses AWS SDK v3 pagination to efficiently search through all layers
|
|
135
|
+
* in the account and region. Validates compatibility based on layer
|
|
136
|
+
* metadata and requirements.
|
|
137
|
+
*
|
|
138
|
+
* @param options - Search criteria and requirements
|
|
139
|
+
* @returns Promise resolving to layer info if found, null otherwise
|
|
140
|
+
* @throws NodeRuntimeLayerError if search fails
|
|
141
|
+
*/
|
|
142
|
+
findExistingLayer(options: LayerSearchOptions): Promise<LayerInfo | null>;
|
|
143
|
+
/**
|
|
144
|
+
* Creates a new Node.js Lambda Layer with concurrent operation coordination.
|
|
145
|
+
*
|
|
146
|
+
* This method extracts the Node.js binary from the corresponding AWS Lambda
|
|
147
|
+
* Docker image, packages it in the proper Lambda Layer directory structure,
|
|
148
|
+
* and publishes it to AWS Lambda with appropriate metadata.
|
|
149
|
+
*
|
|
150
|
+
* Enhanced with concurrent operation coordination to prevent duplicate layer
|
|
151
|
+
* creation when multiple calls are made with identical parameters. If a layer
|
|
152
|
+
* creation is already in progress for the same layer name, subsequent calls
|
|
153
|
+
* will wait for the existing operation to complete rather than starting a
|
|
154
|
+
* duplicate operation.
|
|
155
|
+
*
|
|
156
|
+
* Process:
|
|
157
|
+
* 1. Check for existing in-progress layer creation operation
|
|
158
|
+
* 2. If operation exists, wait for its completion
|
|
159
|
+
* 3. If no operation exists, start new layer creation with lock
|
|
160
|
+
* 4. Create temporary directory for layer contents
|
|
161
|
+
* 5. Extract Node.js binary from Docker container
|
|
162
|
+
* 6. Create proper Lambda Layer directory structure (/opt/nodejs/bin/)
|
|
163
|
+
* 7. Create ZIP archive with correct permissions
|
|
164
|
+
* 8. Validate size limits
|
|
165
|
+
* 9. Publish to AWS Lambda
|
|
166
|
+
* 10. Clean up temporary files and release lock
|
|
167
|
+
*
|
|
168
|
+
* Enhanced with comprehensive resource cleanup on failure to prevent orphaned resources.
|
|
169
|
+
*
|
|
170
|
+
* @param options - Layer creation configuration
|
|
171
|
+
* @returns Promise resolving to information about the created layer
|
|
172
|
+
* @throws NodeRuntimeLayerError if creation fails
|
|
173
|
+
*/
|
|
174
|
+
createNodeLayer(options: LayerCreationOptions): Promise<LayerInfo>;
|
|
175
|
+
/**
|
|
176
|
+
* Performs the actual layer creation operation without concurrent coordination.
|
|
177
|
+
*
|
|
178
|
+
* This is the core layer creation logic extracted from the original createNodeLayer
|
|
179
|
+
* method to separate concerns between concurrent coordination and actual creation.
|
|
180
|
+
*
|
|
181
|
+
* @param options - Layer creation configuration
|
|
182
|
+
* @returns Promise resolving to information about the created layer
|
|
183
|
+
* @throws NodeRuntimeLayerError if creation fails
|
|
184
|
+
*/
|
|
185
|
+
private performLayerCreation;
|
|
186
|
+
/**
|
|
187
|
+
* Deploys a pre-built Node.js Lambda Layer from ZIP file.
|
|
188
|
+
*
|
|
189
|
+
* This method bypasses Docker binary extraction and deploys existing
|
|
190
|
+
* layer ZIP files directly to AWS Lambda. Handles large layers via S3
|
|
191
|
+
* temporary bucket upload with automatic cleanup.
|
|
192
|
+
*
|
|
193
|
+
* Process:
|
|
194
|
+
* 1. Validate input parameters and architecture
|
|
195
|
+
* 2. Search for existing layer ZIP files with fallback naming patterns
|
|
196
|
+
* 3. Read and validate layer ZIP file size
|
|
197
|
+
* 4. Deploy via direct upload (<50MB) or S3 upload (≥50MB)
|
|
198
|
+
* 5. Clean up temporary S3 resources if used
|
|
199
|
+
* 6. Return deployment result with layer ARN and metadata
|
|
200
|
+
*
|
|
201
|
+
* @param options - Deployment configuration
|
|
202
|
+
* @returns Promise resolving to deployment result
|
|
203
|
+
* @throws NodeRuntimeLayerError if deployment fails
|
|
204
|
+
*/
|
|
205
|
+
deployNodejsLayer(options: NodejsLayerDeploymentOptions): Promise<NodejsLayerDeploymentResult>;
|
|
206
|
+
/**
|
|
207
|
+
* Deploys Node.js layers for all supported architectures.
|
|
208
|
+
*
|
|
209
|
+
* Attempts to deploy layers for both arm64 and x86_64 architectures,
|
|
210
|
+
* continuing on individual failures to maximize successful deployments.
|
|
211
|
+
* This matches the behavior of the Python deployment script.
|
|
212
|
+
*
|
|
213
|
+
* @param options - Base deployment configuration (architecture will be overridden)
|
|
214
|
+
* @returns Promise resolving to multi-architecture deployment results
|
|
215
|
+
*/
|
|
216
|
+
deployAllArchitectures(options: Omit<NodejsLayerDeploymentOptions, 'architecture'>): Promise<MultiArchitectureDeploymentResult>;
|
|
217
|
+
/**
|
|
218
|
+
* Generates a standard layer name for the given architecture.
|
|
219
|
+
*
|
|
220
|
+
* @param architecture - Target architecture
|
|
221
|
+
* @returns Standard layer name following the pattern: nodejs-18-{architecture}
|
|
222
|
+
*/
|
|
223
|
+
private generateLayerName;
|
|
224
|
+
/**
|
|
225
|
+
* Searches for layer ZIP files with fallback naming patterns.
|
|
226
|
+
*
|
|
227
|
+
* Implements the same search logic as the Python script with multiple
|
|
228
|
+
* naming conventions for maximum compatibility.
|
|
229
|
+
*
|
|
230
|
+
* @param architecture - Target architecture
|
|
231
|
+
* @param baseDirectory - Directory to search in
|
|
232
|
+
* @returns Promise resolving to ZIP file path or null if not found
|
|
233
|
+
*/
|
|
234
|
+
private findLayerZipFile;
|
|
235
|
+
/**
|
|
236
|
+
* Deploys a large layer (>50MB) via S3 temporary bucket.
|
|
237
|
+
*
|
|
238
|
+
* Creates a temporary S3 bucket, uploads the layer, publishes from S3,
|
|
239
|
+
* and cleans up the bucket. Implements the same logic as the Python script.
|
|
240
|
+
*
|
|
241
|
+
* @param layerName - Name of the layer
|
|
242
|
+
* @param layerContent - ZIP file content
|
|
243
|
+
* @param architecture - Target architecture
|
|
244
|
+
* @param region - AWS region
|
|
245
|
+
* @param description - Optional layer description
|
|
246
|
+
* @param zipFilePath - Original ZIP file path for metadata
|
|
247
|
+
* @returns Promise resolving to deployment result
|
|
248
|
+
*/
|
|
249
|
+
private deployLargeLayerViaS3;
|
|
250
|
+
/**
|
|
251
|
+
* Deploys a layer directly to Lambda (for layers <50MB).
|
|
252
|
+
*
|
|
253
|
+
* @param layerName - Name of the layer
|
|
254
|
+
* @param layerContent - ZIP file content
|
|
255
|
+
* @param architecture - Target architecture
|
|
256
|
+
* @param description - Optional layer description
|
|
257
|
+
* @param zipFilePath - Original ZIP file path for metadata
|
|
258
|
+
* @returns Promise resolving to deployment result
|
|
259
|
+
*/
|
|
260
|
+
private deployLayerDirect;
|
|
261
|
+
/**
|
|
262
|
+
* Creates an S3 bucket for temporary layer storage.
|
|
263
|
+
*
|
|
264
|
+
* @param bucketName - Name of the bucket to create
|
|
265
|
+
* @param region - AWS region
|
|
266
|
+
*/
|
|
267
|
+
private createS3Bucket;
|
|
268
|
+
/**
|
|
269
|
+
* Uploads layer content to S3.
|
|
270
|
+
*
|
|
271
|
+
* @param bucketName - S3 bucket name
|
|
272
|
+
* @param keyName - S3 object key
|
|
273
|
+
* @param layerContent - Layer ZIP content
|
|
274
|
+
*/
|
|
275
|
+
private uploadLayerToS3;
|
|
276
|
+
/**
|
|
277
|
+
* Cleans up S3 resources (bucket and objects).
|
|
278
|
+
*
|
|
279
|
+
* @param bucketName - S3 bucket name
|
|
280
|
+
* @param keyName - S3 object key
|
|
281
|
+
*/
|
|
282
|
+
private cleanupS3Resources;
|
|
283
|
+
/**
|
|
284
|
+
* Validates whether a layer meets the specified requirements.
|
|
285
|
+
*
|
|
286
|
+
* Checks layer compatibility based on:
|
|
287
|
+
* - Node.js version exact match
|
|
288
|
+
* - Architecture compatibility
|
|
289
|
+
* - Layer age (if maxAge is specified in requirements)
|
|
290
|
+
*
|
|
291
|
+
* @param layer - The layer to validate
|
|
292
|
+
* @param requirements - The requirements to check against
|
|
293
|
+
* @returns true if the layer is compatible, false otherwise
|
|
294
|
+
*/
|
|
295
|
+
validateLayerCompatibility(layer: LayerInfo, requirements: LayerRequirements): boolean;
|
|
296
|
+
/**
|
|
297
|
+
* Lists layers by name using AWS SDK v3 pagination with retry logic.
|
|
298
|
+
*
|
|
299
|
+
* Efficiently searches through all layers in the account and region
|
|
300
|
+
* to find layers matching the specified name pattern. Uses retry logic
|
|
301
|
+
* to handle transient pagination failures.
|
|
302
|
+
*
|
|
303
|
+
* @param layerName - The layer name to search for
|
|
304
|
+
* @returns Promise resolving to array of matching layers
|
|
305
|
+
* @throws Error if AWS API operations fail
|
|
306
|
+
*/
|
|
307
|
+
private listLayersByName;
|
|
308
|
+
/**
|
|
309
|
+
* Gets detailed information about a specific layer version.
|
|
310
|
+
*
|
|
311
|
+
* Retrieves layer metadata and extracts Node.js version and architecture
|
|
312
|
+
* information from the layer description or other metadata.
|
|
313
|
+
*
|
|
314
|
+
* @param layerName - The name of the layer
|
|
315
|
+
* @param version - The version number of the layer
|
|
316
|
+
* @returns Promise resolving to LayerInfo
|
|
317
|
+
* @throws Error if layer information cannot be retrieved
|
|
318
|
+
*/
|
|
319
|
+
private getLayerInfo;
|
|
320
|
+
/**
|
|
321
|
+
* Parses layer metadata to extract Node.js version and architecture.
|
|
322
|
+
*
|
|
323
|
+
* Attempts to extract information from layer description or falls back
|
|
324
|
+
* to parsing the layer name if description doesn't contain the required data.
|
|
325
|
+
*
|
|
326
|
+
* @param description - The layer description
|
|
327
|
+
* @param layerName - The layer name as fallback
|
|
328
|
+
* @returns Object containing nodeVersion and architecture
|
|
329
|
+
*/
|
|
330
|
+
private parseLayerMetadata;
|
|
331
|
+
/**
|
|
332
|
+
* Executes an AWS API operation with exponential backoff retry logic and circuit breaker protection.
|
|
333
|
+
*
|
|
334
|
+
* Implements retry logic for transient AWS API failures with exponential
|
|
335
|
+
* backoff and jitter to avoid thundering herd problems. Uses circuit breaker
|
|
336
|
+
* pattern to prevent cascading failures during AWS service outages.
|
|
337
|
+
*
|
|
338
|
+
* @param operation - The async operation to execute
|
|
339
|
+
* @returns Promise resolving to the operation result
|
|
340
|
+
* @throws Error if all retries are exhausted or circuit breaker is open
|
|
341
|
+
*/
|
|
342
|
+
private executeWithRetry;
|
|
343
|
+
/**
|
|
344
|
+
* Determines if an error is retryable.
|
|
345
|
+
*
|
|
346
|
+
* @param error - The error to check
|
|
347
|
+
* @returns true if the error is retryable, false otherwise
|
|
348
|
+
*/
|
|
349
|
+
private isRetryableError;
|
|
350
|
+
/**
|
|
351
|
+
* Checks if an error is a network-related error that should be retried.
|
|
352
|
+
*
|
|
353
|
+
* @param error - The error to check
|
|
354
|
+
* @returns true if it's a retryable network error
|
|
355
|
+
*/
|
|
356
|
+
private isNetworkError;
|
|
357
|
+
/**
|
|
358
|
+
* Calculates retry delay with exponential backoff and jitter.
|
|
359
|
+
*
|
|
360
|
+
* @param attempt - The current attempt number (0-based)
|
|
361
|
+
* @returns Delay in milliseconds
|
|
362
|
+
*/
|
|
363
|
+
private calculateRetryDelay;
|
|
364
|
+
/**
|
|
365
|
+
* Sleeps for the specified number of milliseconds.
|
|
366
|
+
*
|
|
367
|
+
* @param ms - Milliseconds to sleep
|
|
368
|
+
* @returns Promise that resolves after the delay
|
|
369
|
+
*/
|
|
370
|
+
private sleep;
|
|
371
|
+
/**
|
|
372
|
+
* Gets the current circuit breaker state for monitoring and debugging.
|
|
373
|
+
*
|
|
374
|
+
* @returns Object containing circuit breaker state information
|
|
375
|
+
*/
|
|
376
|
+
getCircuitBreakerState(): {
|
|
377
|
+
state: string;
|
|
378
|
+
failureCount: number;
|
|
379
|
+
successCount: number;
|
|
380
|
+
};
|
|
381
|
+
/**
|
|
382
|
+
* Gets the current concurrent operation state for monitoring and debugging.
|
|
383
|
+
*
|
|
384
|
+
* @returns Object containing information about in-progress layer creation operations
|
|
385
|
+
*/
|
|
386
|
+
getConcurrentOperationState(): {
|
|
387
|
+
activeOperations: number;
|
|
388
|
+
operations: Array<{
|
|
389
|
+
layerName: string;
|
|
390
|
+
startTime: number;
|
|
391
|
+
duration: number;
|
|
392
|
+
waiters: number;
|
|
393
|
+
nodeVersion: string;
|
|
394
|
+
architecture: string;
|
|
395
|
+
}>;
|
|
396
|
+
};
|
|
397
|
+
/**
|
|
398
|
+
* Destroys the AWS Lambda client and cleans up resources.
|
|
399
|
+
*
|
|
400
|
+
* Should be called when the manager is no longer needed to prevent
|
|
401
|
+
* resource leaks. Also cleans up any remaining concurrent operation locks.
|
|
402
|
+
*/
|
|
403
|
+
destroy(): void;
|
|
404
|
+
/**
|
|
405
|
+
* Creates a temporary directory for layer creation operations.
|
|
406
|
+
*
|
|
407
|
+
* @returns Promise resolving to the temporary directory path
|
|
408
|
+
* @throws Error if directory creation fails
|
|
409
|
+
*/
|
|
410
|
+
private createTempDirectory;
|
|
411
|
+
/**
|
|
412
|
+
* Extracts Node.js binary from AWS Lambda Docker image with resource tracking.
|
|
413
|
+
*
|
|
414
|
+
* Uses ONLY AWS Lambda Docker images to extract the Node.js binary from the
|
|
415
|
+
* official Lambda runtime environment. This ensures compatibility with the
|
|
416
|
+
* Lambda execution environment while extracting only the minimal binary needed.
|
|
417
|
+
*
|
|
418
|
+
* CRITICAL: Uses ONLY AWS Lambda Docker images as required by user specifications.
|
|
419
|
+
* Docker image format: public.ecr.aws/lambda/nodejs:{version}-{arch}
|
|
420
|
+
* Extracts ONLY: /var/lang/bin/node
|
|
421
|
+
*
|
|
422
|
+
* @param nodeVersion - The Node.js version (e.g., "20.10.0")
|
|
423
|
+
* @param architecture - The target architecture
|
|
424
|
+
* @param tempDir - Temporary directory for extraction
|
|
425
|
+
* @param resourceTracker - Resource tracker for cleanup
|
|
426
|
+
* @returns Promise resolving to the path of the extracted binary
|
|
427
|
+
* @throws NodeRuntimeLayerError if extraction fails
|
|
428
|
+
*/
|
|
429
|
+
private extractNodeBinaryFromDockerWithTracking;
|
|
430
|
+
/**
|
|
431
|
+
* Optimizes Node.js binary to reduce size while preserving functionality.
|
|
432
|
+
*
|
|
433
|
+
* Multi-stage optimization approach:
|
|
434
|
+
* 1. Strip debug symbols using 'strip' command (30-50% reduction)
|
|
435
|
+
* 2. UPX compression if still >50MB (50-70% additional reduction)
|
|
436
|
+
* 3. System Node.js replacement if still >60MB
|
|
437
|
+
* 4. Verify binary functionality after each stage
|
|
438
|
+
* 5. Fallback to original if within 250MB limit
|
|
439
|
+
*
|
|
440
|
+
* @param originalBinaryPath - Path to the original Node.js binary
|
|
441
|
+
* @param tempDir - Temporary directory for optimization work
|
|
442
|
+
* @returns Promise resolving to path of optimized binary
|
|
443
|
+
* @throws Error if optimization fails and original exceeds 250MB limit
|
|
444
|
+
*/
|
|
445
|
+
private optimizeNodeBinary;
|
|
446
|
+
/**
|
|
447
|
+
* Attempts strip-based optimization with progressive aggressiveness.
|
|
448
|
+
*
|
|
449
|
+
* @param originalBinaryPath - Path to original binary
|
|
450
|
+
* @param tempDir - Working directory
|
|
451
|
+
* @returns Path to stripped binary or original if stripping fails
|
|
452
|
+
*/
|
|
453
|
+
private tryStripOptimization;
|
|
454
|
+
/**
|
|
455
|
+
* Attempts UPX compression optimization.
|
|
456
|
+
*
|
|
457
|
+
* @param binaryPath - Path to binary to compress
|
|
458
|
+
* @param tempDir - Working directory
|
|
459
|
+
* @returns Path to compressed binary or null if UPX unavailable/fails
|
|
460
|
+
*/
|
|
461
|
+
private tryUPXOptimization;
|
|
462
|
+
/**
|
|
463
|
+
* Attempts to use system Node.js binary as replacement.
|
|
464
|
+
*
|
|
465
|
+
* @param tempDir - Working directory
|
|
466
|
+
* @returns Path to system Node.js copy or null if unavailable/unsuitable
|
|
467
|
+
*/
|
|
468
|
+
private trySystemNodeReplacement;
|
|
469
|
+
/**
|
|
470
|
+
* Verifies that a Node.js binary is functional after optimization.
|
|
471
|
+
*
|
|
472
|
+
* Runs basic Node.js commands to ensure the binary works correctly.
|
|
473
|
+
* This prevents shipping broken binaries after optimization.
|
|
474
|
+
*
|
|
475
|
+
* @param binaryPath - Path to the Node.js binary to verify
|
|
476
|
+
* @throws Error if verification fails
|
|
477
|
+
*/
|
|
478
|
+
private verifyNodeBinary;
|
|
479
|
+
/**
|
|
480
|
+
* Verifies Node.js binary with graceful fallback for spawn errors.
|
|
481
|
+
*
|
|
482
|
+
* This method attempts full verification but falls back to basic checks
|
|
483
|
+
* if spawn fails (e.g., error -8). This prevents blocking deployment for
|
|
484
|
+
* binaries that are valid but fail verification due to system issues.
|
|
485
|
+
*
|
|
486
|
+
* @param binaryPath - Path to the Node.js binary to verify
|
|
487
|
+
* @returns Promise resolving to verification result with success flag and optional error
|
|
488
|
+
*/
|
|
489
|
+
private verifyNodeBinaryWithFallback;
|
|
490
|
+
/**
|
|
491
|
+
* Creates the proper Lambda Layer directory structure.
|
|
492
|
+
*
|
|
493
|
+
* Lambda Layers for Node.js binary should use minimal structure:
|
|
494
|
+
* - bin/node (uncompressed binary)
|
|
495
|
+
* - bin/node.gz (compressed binary with decompression script)
|
|
496
|
+
*
|
|
497
|
+
* @param tempDir - Base temporary directory
|
|
498
|
+
* @param nodeBinaryPath - Path to the Node.js binary (may be compressed)
|
|
499
|
+
* @returns Promise resolving to the layer directory path
|
|
500
|
+
* @throws Error if directory creation fails
|
|
501
|
+
*/
|
|
502
|
+
private createLayerDirectoryStructure;
|
|
503
|
+
/**
|
|
504
|
+
* Creates a ZIP archive of the layer contents with compression optimization.
|
|
505
|
+
*
|
|
506
|
+
* Uses Python's zipfile module to create a properly compressed ZIP file with
|
|
507
|
+
* file permissions preserved for the Node.js binary. Implements compression
|
|
508
|
+
* optimization to minimize storage and transfer costs.
|
|
509
|
+
*
|
|
510
|
+
* @param layerDir - Directory containing the layer contents
|
|
511
|
+
* @param layerName - Name of the layer (used for ZIP filename)
|
|
512
|
+
* @returns Promise resolving to the ZIP file path
|
|
513
|
+
* @throws Error if ZIP creation fails
|
|
514
|
+
*/
|
|
515
|
+
private createLayerZipArchive;
|
|
516
|
+
/**
|
|
517
|
+
* Calculates the total size of all files in a directory.
|
|
518
|
+
*
|
|
519
|
+
* @param dirPath - Directory path to analyze
|
|
520
|
+
* @returns Promise resolving to total size in bytes
|
|
521
|
+
*/
|
|
522
|
+
private calculateDirectorySize;
|
|
523
|
+
/**
|
|
524
|
+
* Fallback ZIP creation using system zip command.
|
|
525
|
+
*
|
|
526
|
+
* @param layerDir - Directory containing the layer contents
|
|
527
|
+
* @param zipFilePath - Target ZIP file path
|
|
528
|
+
* @returns Promise resolving to the ZIP file path
|
|
529
|
+
* @throws Error if ZIP creation fails
|
|
530
|
+
*/
|
|
531
|
+
private createZipFallback;
|
|
532
|
+
/**
|
|
533
|
+
* Validates that the layer ZIP file meets AWS size limits.
|
|
534
|
+
*
|
|
535
|
+
* AWS Lambda has strict size limits for layers:
|
|
536
|
+
* - 50MB for zipped layer
|
|
537
|
+
* - 250MB for unzipped layer
|
|
538
|
+
*
|
|
539
|
+
* Enhanced to check both zipped and unzipped sizes with comprehensive
|
|
540
|
+
* error reporting and optimization suggestions.
|
|
541
|
+
*
|
|
542
|
+
* @param zipFilePath - Path to the ZIP file
|
|
543
|
+
* @throws NodeRuntimeLayerError if size limits are exceeded
|
|
544
|
+
*/
|
|
545
|
+
private preValidateLayerContent;
|
|
546
|
+
/**
|
|
547
|
+
* Validates layer size limits after ZIP creation.
|
|
548
|
+
*
|
|
549
|
+
* @param zipFilePath - Path to the ZIP file
|
|
550
|
+
* @throws NodeRuntimeLayerError if size limits are exceeded
|
|
551
|
+
*/
|
|
552
|
+
private validateLayerSize;
|
|
553
|
+
/**
|
|
554
|
+
* Calculates the unzipped size of a ZIP file by examining its contents.
|
|
555
|
+
*
|
|
556
|
+
* Uses Python's zipfile module to read ZIP metadata and calculate
|
|
557
|
+
* the total uncompressed size without extracting files.
|
|
558
|
+
*
|
|
559
|
+
* @param zipFilePath - Path to the ZIP file
|
|
560
|
+
* @returns Promise resolving to unzipped size in bytes
|
|
561
|
+
* @throws Error if size calculation fails
|
|
562
|
+
*/
|
|
563
|
+
private calculateUnzippedSize;
|
|
564
|
+
/**
|
|
565
|
+
* Publishes the layer to AWS Lambda.
|
|
566
|
+
*
|
|
567
|
+
* Uses the AWS SDK v3 Lambda client to publish the layer with proper
|
|
568
|
+
* metadata including compatible runtimes and architectures.
|
|
569
|
+
*
|
|
570
|
+
* @param options - Layer creation options
|
|
571
|
+
* @param zipFilePath - Path to the ZIP file
|
|
572
|
+
* @returns Promise resolving to LayerInfo
|
|
573
|
+
* @throws NodeRuntimeLayerError if publishing fails
|
|
574
|
+
*/
|
|
575
|
+
private publishLayerToAWS;
|
|
576
|
+
/**
|
|
577
|
+
* Executes a Docker command with timeout and error handling.
|
|
578
|
+
*
|
|
579
|
+
* @param args - Docker command arguments
|
|
580
|
+
* @returns Promise that resolves when command completes successfully
|
|
581
|
+
* @throws Error if command fails
|
|
582
|
+
*/
|
|
583
|
+
private executeDockerCommand;
|
|
584
|
+
/**
|
|
585
|
+
* Executes a system command with timeout and error handling, capturing output.
|
|
586
|
+
*
|
|
587
|
+
* @param command - Command to execute
|
|
588
|
+
* @param args - Command arguments
|
|
589
|
+
* @param options - Execution options including working directory
|
|
590
|
+
* @returns Promise resolving to command output (stdout and stderr)
|
|
591
|
+
* @throws Error if command fails
|
|
592
|
+
*/
|
|
593
|
+
private executeCommandWithOutput;
|
|
594
|
+
/**
|
|
595
|
+
* Executes a system command with timeout and error handling.
|
|
596
|
+
*
|
|
597
|
+
* @param command - Command to execute
|
|
598
|
+
* @param args - Command arguments
|
|
599
|
+
* @param options - Execution options including working directory
|
|
600
|
+
* @returns Promise that resolves when command completes successfully
|
|
601
|
+
* @throws Error if command fails
|
|
602
|
+
*/
|
|
603
|
+
private executeCommand;
|
|
604
|
+
/**
|
|
605
|
+
* Legacy cleanup method for backward compatibility.
|
|
606
|
+
*
|
|
607
|
+
* @deprecated Use performComprehensiveCleanup with ResourceTracker instead
|
|
608
|
+
* @param tempDir - Temporary directory to remove (if exists)
|
|
609
|
+
* @param zipFilePath - ZIP file to remove (if exists)
|
|
610
|
+
*/
|
|
611
|
+
private cleanupTempResources;
|
|
612
|
+
/**
|
|
613
|
+
* Legacy Docker extraction method for backward compatibility.
|
|
614
|
+
*
|
|
615
|
+
* @deprecated Use extractNodeBinaryFromDockerWithTracking instead
|
|
616
|
+
*/
|
|
617
|
+
private extractNodeBinaryFromDocker;
|
|
618
|
+
/**
|
|
619
|
+
* Creates an enhanced error with cleanup context preservation.
|
|
620
|
+
*
|
|
621
|
+
* Preserves the original error while adding context about the layer creation
|
|
622
|
+
* operation that failed. This maintains debugging capability while providing
|
|
623
|
+
* additional context for troubleshooting.
|
|
624
|
+
*
|
|
625
|
+
* @param originalError - The original error that occurred
|
|
626
|
+
* @param options - Layer creation options for context
|
|
627
|
+
* @returns Enhanced NodeRuntimeLayerError with preserved context
|
|
628
|
+
*/
|
|
629
|
+
private createEnhancedError;
|
|
630
|
+
/**
|
|
631
|
+
* Performs comprehensive cleanup of all tracked resources.
|
|
632
|
+
*
|
|
633
|
+
* Cleans up Docker containers, temporary directories, and ZIP files.
|
|
634
|
+
* Cleanup failures are logged as warnings but do not prevent the cleanup
|
|
635
|
+
* of other resources or mask the original error.
|
|
636
|
+
*
|
|
637
|
+
* @param resourceTracker - Tracker containing all resources to clean up
|
|
638
|
+
*/
|
|
639
|
+
private performComprehensiveCleanup;
|
|
640
|
+
}
|