diff --git a/src/datadog-lambda.ts b/src/datadog-lambda.ts index dda57f36..c25809b0 100644 --- a/src/datadog-lambda.ts +++ b/src/datadog-lambda.ts @@ -84,19 +84,19 @@ export class DatadogLambda extends Construct { log.debug("Granting read access to the provided Secret ARN for all your lambda functions."); grantReadLambdaFromSecretArn(construct, this.props.apiKeySecretArn, lambdaFunction); } - } - if (baseProps.addLayers) { - applyLayers( - this.scope, - region, - extractedLambdaFunctions, - this.props.pythonLayerVersion, - this.props.nodeLayerVersion, - this.props.javaLayerVersion, - this.props.dotnetLayerVersion, - this.props.useLayersFromAccount, - ); + if (baseProps.addLayers) { + applyLayers( + this.scope, + region, + lambdaFunction, + this.props.pythonLayerVersion, + this.props.nodeLayerVersion, + this.props.javaLayerVersion, + this.props.dotnetLayerVersion, + this.props.useLayersFromAccount, + ); + } } if (baseProps.extensionLayerVersion !== undefined) { diff --git a/src/layer.ts b/src/layer.ts index b50668b0..ba47b1de 100644 --- a/src/layer.ts +++ b/src/layer.ts @@ -27,7 +27,7 @@ const layers: Map = new Map(); export function applyLayers( scope: Construct, region: string, - lambdas: lambda.Function[], + lam: lambda.Function, pythonLayerVersion?: number, nodeLayerVersion?: number, javaLayerVersion?: number, @@ -37,59 +37,61 @@ export function applyLayers( // TODO: check region availability const errors: string[] = []; log.debug("Applying layers to Lambda functions..."); - lambdas.forEach((lam) => { - const runtime: string = lam.runtime.name; - const lambdaRuntimeType: RuntimeType = runtimeLookup[runtime]; - const isARM = lam.architecture?.dockerPlatform === Architecture.ARM_64.dockerPlatform; + const runtime: string = lam.runtime.name; + const lambdaRuntimeType: RuntimeType = runtimeLookup[runtime]; + const isARM = lam.architecture?.dockerPlatform === Architecture.ARM_64.dockerPlatform; - if (lambdaRuntimeType === undefined || lambdaRuntimeType === RuntimeType.UNSUPPORTED) { - log.debug(`Unsupported runtime: ${runtime}`); - return; - } + if (lambdaRuntimeType === undefined || lambdaRuntimeType === RuntimeType.UNSUPPORTED) { + log.debug(`Unsupported runtime: ${runtime}`); + return errors; + } - const accountId = useLayersFromAccount; - let lambdaLayerArn; - switch (lambdaRuntimeType) { - case RuntimeType.PYTHON: - if (pythonLayerVersion === undefined) { - return handleLayerError(errors, lam.node.id, "Python", "python"); - } - lambdaLayerArn = getLambdaLayerArn(region, pythonLayerVersion, runtime, isARM, accountId); - log.debug(`Using Python Lambda layer: ${lambdaLayerArn}`); - addLayer(lambdaLayerArn, false, scope, lam, runtime); - break; - - case RuntimeType.NODE: - if (nodeLayerVersion === undefined) { - return handleLayerError(errors, lam.node.id, "Node.js", "node"); - } - lambdaLayerArn = getLambdaLayerArn(region, nodeLayerVersion, runtime, false, accountId); // Node has no ARM layer - log.debug(`Using Node Lambda layer: ${lambdaLayerArn}`); - addLayer(lambdaLayerArn, false, scope, lam, runtime); - break; - - case RuntimeType.JAVA: - if (javaLayerVersion === undefined) { - return handleLayerError(errors, lam.node.id, "Java", "java"); - } - lambdaLayerArn = getLambdaLayerArn(region, javaLayerVersion, runtime, false, accountId); //Java has no ARM layer - log.debug(`Using dd-trace-java layer: ${lambdaLayerArn}`); - addLayer(lambdaLayerArn, false, scope, lam, runtime); - break; - - case RuntimeType.DOTNET: - if (dotnetLayerVersion === undefined) { - return handleLayerError(errors, lam.node.id, ".NET", "dotnet"); - } - lambdaLayerArn = getLambdaLayerArn(region, dotnetLayerVersion, runtime, isARM, accountId); - log.debug(`Using dd-trace-dotnet layer: ${lambdaLayerArn}`); - addLayer(lambdaLayerArn, false, scope, lam, runtime); - break; - - case RuntimeType.CUSTOM: - break; - } - }); + const accountId = useLayersFromAccount; + let lambdaLayerArn; + switch (lambdaRuntimeType) { + case RuntimeType.PYTHON: + if (pythonLayerVersion === undefined) { + handleLayerError(errors, lam.node.id, "Python", "python"); + return errors; + } + lambdaLayerArn = getLambdaLayerArn(region, pythonLayerVersion, runtime, isARM, accountId); + log.debug(`Using Python Lambda layer: ${lambdaLayerArn}`); + addLayer(lambdaLayerArn, false, scope, lam, runtime); + break; + + case RuntimeType.NODE: + if (nodeLayerVersion === undefined) { + handleLayerError(errors, lam.node.id, "Node.js", "node"); + return errors; + } + lambdaLayerArn = getLambdaLayerArn(region, nodeLayerVersion, runtime, false, accountId); // Node has no ARM layer + log.debug(`Using Node Lambda layer: ${lambdaLayerArn}`); + addLayer(lambdaLayerArn, false, scope, lam, runtime); + break; + + case RuntimeType.JAVA: + if (javaLayerVersion === undefined) { + handleLayerError(errors, lam.node.id, "Java", "java"); + return errors; + } + lambdaLayerArn = getLambdaLayerArn(region, javaLayerVersion, runtime, false, accountId); //Java has no ARM layer + log.debug(`Using dd-trace-java layer: ${lambdaLayerArn}`); + addLayer(lambdaLayerArn, false, scope, lam, runtime); + break; + + case RuntimeType.DOTNET: + if (dotnetLayerVersion === undefined) { + handleLayerError(errors, lam.node.id, ".NET", "dotnet"); + return errors; + } + lambdaLayerArn = getLambdaLayerArn(region, dotnetLayerVersion, runtime, isARM, accountId); + log.debug(`Using dd-trace-dotnet layer: ${lambdaLayerArn}`); + addLayer(lambdaLayerArn, false, scope, lam, runtime); + break; + + case RuntimeType.CUSTOM: + break; + } return errors; } diff --git a/test/layer.spec.ts b/test/layer.spec.ts index 0458592d..49f56d95 100644 --- a/test/layer.spec.ts +++ b/test/layer.spec.ts @@ -31,7 +31,7 @@ describe("applyLayers", () => { code: lambda.Code.fromAsset("test/lambda"), handler: "example-lambda.handler", }); - const errors = applyLayers(stack, stack.region, [hello], PYTHON_LAYER_VERSION, NODE_LAYER_VERSION); + const errors = applyLayers(stack, stack.region, hello, PYTHON_LAYER_VERSION, NODE_LAYER_VERSION); Template.fromStack(stack).hasResourceProperties("AWS::Lambda::Function", { Layers: [`arn:aws:lambda:${stack.region}:${DD_ACCOUNT_ID}:layer:Datadog-Node16-x:${NODE_LAYER_VERSION}`], }); @@ -200,7 +200,7 @@ describe("applyLayers", () => { handler: "example-lambda.handler", }); (hello as any).architecture = undefined; - const errors = applyLayers(stack, stack.region, [hello], PYTHON_LAYER_VERSION, NODE_LAYER_VERSION); + const errors = applyLayers(stack, stack.region, hello, PYTHON_LAYER_VERSION, NODE_LAYER_VERSION); Template.fromStack(stack).hasResourceProperties("AWS::Lambda::Function", { Layers: [`arn:aws:lambda:${stack.region}:${DD_ACCOUNT_ID}:layer:Datadog-Node16-x:${NODE_LAYER_VERSION}`], }); @@ -230,9 +230,13 @@ describe("applyLayers", () => { handler: "example-lambda.handler", }); - const errors = applyLayers(stack, stack.region, [hello1, hello2, hello3], PYTHON_LAYER_VERSION, NODE_LAYER_VERSION); + const errors1 = applyLayers(stack, stack.region, hello1, PYTHON_LAYER_VERSION, NODE_LAYER_VERSION); + const errors2 = applyLayers(stack, stack.region, hello2, PYTHON_LAYER_VERSION, NODE_LAYER_VERSION); + const errors3 = applyLayers(stack, stack.region, hello3, PYTHON_LAYER_VERSION, NODE_LAYER_VERSION); - expect(errors.length).toEqual(0); + expect(errors1.length).toEqual(0); + expect(errors2.length).toEqual(0); + expect(errors3.length).toEqual(0); Template.fromStack(stack).hasResourceProperties("AWS::Lambda::Function", { Layers: [`arn:aws:lambda:${stack.region}:${DD_ACCOUNT_ID}:layer:Datadog-Node16-x:${NODE_LAYER_VERSION}`], }); @@ -256,7 +260,7 @@ describe("applyLayers", () => { code: lambda.Code.fromAsset("test"), handler: "hello.handler", }); - const errors = applyLayers(stack, stack.region, [hello], PYTHON_LAYER_VERSION, NODE_LAYER_VERSION); + const errors = applyLayers(stack, stack.region, hello, PYTHON_LAYER_VERSION, NODE_LAYER_VERSION); Template.fromStack(stack).hasResourceProperties("AWS::Lambda::Function", { Layers: Match.absent(), }); @@ -394,14 +398,13 @@ describe("applyLayers", () => { code: lambda.Code.fromAsset("test/lambda"), handler: "example-lambda.handler", }); - const errors = applyLayers(stack, stack.region, [hello1, hello2]); + const errors1 = applyLayers(stack, stack.region, hello1); + const errors2 = applyLayers(stack, stack.region, hello2); Template.fromStack(stack).hasResourceProperties("AWS::Lambda::Function", { Layers: Match.absent(), }); - expect(errors).toEqual([ - getMissingLayerVersionErrorMsg("NodeHandler", "Node.js", "node"), - getMissingLayerVersionErrorMsg("PythonHandler", "Python", "python"), - ]); + expect(errors1).toEqual([getMissingLayerVersionErrorMsg("NodeHandler", "Node.js", "node")]); + expect(errors2).toEqual([getMissingLayerVersionErrorMsg("PythonHandler", "Python", "python")]); expect(logSpy).toHaveBeenCalledTimes(2); logSpy.mockRestore(); }); @@ -426,15 +429,11 @@ describe("isGovCloud", () => { code: lambda.Code.fromAsset("test/lambda"), handler: "example-lambda.handler", }); - const errors = applyLayers( - stack, - stack.region, - [pythonLambda, nodeLambda], - PYTHON_LAYER_VERSION, - NODE_LAYER_VERSION, - ); + const errorsPython = applyLayers(stack, stack.region, pythonLambda, PYTHON_LAYER_VERSION, NODE_LAYER_VERSION); + const errorsNode = applyLayers(stack, stack.region, nodeLambda, PYTHON_LAYER_VERSION, NODE_LAYER_VERSION); - expect(errors.length).toEqual(0); + expect(errorsPython.length).toEqual(0); + expect(errorsNode.length).toEqual(0); Template.fromStack(stack).hasResourceProperties("AWS::Lambda::Function", { Layers: [ `arn:aws-us-gov:lambda:us-gov-east-1:${DD_GOV_ACCOUNT_ID}:layer:Datadog-Python39:${PYTHON_LAYER_VERSION}`,