Skip to content

Commit

Permalink
Allow the extension layer to be applied separately from the runtime l…
Browse files Browse the repository at this point in the history
…ayers (#131)

* Allowing the extension to be installed standalone from the runtime layers

* Updating test spec for layers

* extra line

* removing the optional flag for the new parameter, updating tests

* fixing style issues

* Adding error messaging for when extensionLayerVersion is missing and bumping major version
  • Loading branch information
TophrC-dd authored Sep 17, 2024
1 parent fd54eab commit bb5797e
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 93 deletions.
9 changes: 9 additions & 0 deletions serverless/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import log from "loglevel";
export interface Configuration {
// Whether to add the Datadog Lambda Library layers, or expect the users to bring their own
addLayers: boolean;
// Whether to add the Datadog Extension Library layer
addExtension: boolean;
// Python Lambda layer version
pythonLayerVersion?: number;
// Node.js Lambda layer version
Expand Down Expand Up @@ -109,6 +111,7 @@ const ddApmFlushDeadlineMillisecondsEnvVar = "DD_APM_FLUSH_DEADLINE_MILLISECONDS

export const defaultConfiguration: Configuration = {
addLayers: true,
addExtension: true,
flushMetricsToLogs: true,
logLevel: undefined,
site: "datadoghq.com",
Expand Down Expand Up @@ -252,6 +255,11 @@ export function validateParameters(config: Configuration) {
"Warning: Invalid site URL. Must be either datadoghq.com, datadoghq.eu, us3.datadoghq.com, us5.datadoghq.com, ap1.datadoghq.com, or ddog-gov.com.",
);
}
if (config.addExtension === true) {
if (config.extensionLayerVersion === undefined) {
errors.push("Please add the 'extensionLayerVersion' parameter for the Datadog serverless macro");
}
}
if (config.extensionLayerVersion !== undefined) {
if (config.forwarderArn !== undefined) {
errors.push("`extensionLayerVersion` and `forwarderArn` cannot be set at the same time.");
Expand All @@ -260,6 +268,7 @@ export function validateParameters(config: Configuration) {
errors.push("When `extensionLayerVersion` is set, `apiKey`, `apiKeySecretArn`, or `apiKmsKey` must also be set.");
}
}

return errors;
}

Expand Down
15 changes: 13 additions & 2 deletions serverless/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getConfigFromCfnMappings, getConfigFromCfnParams, setEnvConfiguration, validateParameters } from "./env";
import { findLambdas, applyLayers, LambdaFunction } from "./layer";
import { findLambdas, applyLayers, applyExtensionLayer, LambdaFunction } from "./layer";
import { getTracingMode, enableTracing, MissingIamRoleError, TracingMode } from "./tracing";
import { addDDTags, addMacroTag, addCDKTag, addSAMTag } from "./tags";
import { redirectHandlers } from "./redirect";
Expand Down Expand Up @@ -106,7 +106,6 @@ export const handler = async (event: InputEvent, _: any) => {
config.nodeLayerVersion,
config.dotnetLayerVersion,
config.javaLayerVersion,
config.extensionLayerVersion,
);
if (errors.length > 0) {
return {
Expand All @@ -118,6 +117,18 @@ export const handler = async (event: InputEvent, _: any) => {
}
}

if (config.addExtension) {
errors = applyExtensionLayer(region, lambdas, config.extensionLayerVersion);
if (errors.length > 0) {
return {
requestId: event.requestId,
status: FAILURE,
fragment,
errorMessage: errors.join("\n"),
};
}
}

// Enable tracing
const tracingMode = getTracingMode(config);
try {
Expand Down
28 changes: 22 additions & 6 deletions serverless/src/layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,6 @@ export function applyLayers(
nodeLayerVersion?: number,
dotnetLayerVersion?: number,
javaLayerVersion?: number,
extensionLayerVersion?: number,
) {
const errors: string[] = [];
lambdas.forEach((lambda) => {
Expand All @@ -183,7 +182,6 @@ export function applyLayers(
}

let lambdaLibraryLayerArn;
let lambdaExtensionLayerArn;

if (lambda.runtimeType === RuntimeType.PYTHON) {
if (pythonLayerVersion === undefined) {
Expand Down Expand Up @@ -228,12 +226,23 @@ export function applyLayers(
lambdaLibraryLayerArn = getLambdaLibraryLayerArn(region, javaLayerVersion, lambda.runtime, lambda.architecture);
addLayer(lambdaLibraryLayerArn, lambda);
}
});
return errors;
}

export function applyExtensionLayer(region: string, lambdas: LambdaFunction[], extensionLayerVersion?: number) {
const errors: string[] = [];
lambdas.forEach((lambda) => {
let lambdaExtensionLayerArn;

if (extensionLayerVersion !== undefined) {
log.debug(`Setting Lambda Extension layer for ${lambda.key}`);
lambdaExtensionLayerArn = getExtensionLayerArn(region, extensionLayerVersion, lambda.architecture);
addLayer(lambdaExtensionLayerArn, lambda);
if (extensionLayerVersion === undefined) {
errors.push(getMissingExtensionLayerVersionErrorMsg(lambda.key));
return;
}

log.debug(`Setting Lambda Extension layer for ${lambda.key}`);
lambdaExtensionLayerArn = getExtensionLayerArn(region, extensionLayerVersion, lambda.architecture);
addLayer(lambdaExtensionLayerArn, lambda);
});
return errors;
}
Expand Down Expand Up @@ -311,3 +320,10 @@ export function getMissingLayerVersionErrorMsg(functionKey: string, formalRuntim
`Please add the '${paramRuntime}LayerVersion' parameter for the Datadog serverless macro.`
);
}

export function getMissingExtensionLayerVersionErrorMsg(functionKey: string) {
return (
`Resource ${functionKey} has been configured to apply the extension laybe but no extension version was provided. ` +
`Please add the 'extensionLayerVersion' parameter for the Datadog serverless macro`
);
}
2 changes: 1 addition & 1 deletion serverless/template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Transform: AWS::Serverless-2016-10-31
Mappings:
Constants:
DatadogServerlessMacro:
Version: 0.13.0
Version: 0.15.0

Parameters:
FunctionName:
Expand Down
40 changes: 40 additions & 0 deletions serverless/test/env.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ describe("getConfig", () => {
const config = getConfigFromCfnParams(params);
expect(config).toEqual({
addLayers: true,
addExtension: true,
flushMetricsToLogs: true,
site: "my-site",
enableXrayTracing: false,
Expand Down Expand Up @@ -62,6 +63,7 @@ describe("getConfig", () => {
const config = getConfigFromEnvVars();
expect(config).toEqual({
addLayers: true,
addExtension: true,
flushMetricsToLogs: false,
logLevel: undefined,
site: "datadoghq.com",
Expand Down Expand Up @@ -89,6 +91,7 @@ describe("getConfig", () => {
const config = getConfigFromCfnParams(params);
expect(config).toEqual({
addLayers: true,
addExtension: true,
flushMetricsToLogs: false,
site: "my-site",
enableXrayTracing: false,
Expand Down Expand Up @@ -199,6 +202,7 @@ describe("setEnvConfiguration", () => {
};
const config = {
addLayers: false,
addExtension: false,
apiKey: "1234",
apiKMSKey: "5678",
site: "datadoghq.eu",
Expand Down Expand Up @@ -265,6 +269,7 @@ describe("setEnvConfiguration", () => {
};
const config = {
addLayers: false,
addExtension: false,
apiKey: "1234",
apiKMSKey: "5678",
site: "datadoghq.eu",
Expand Down Expand Up @@ -350,6 +355,7 @@ describe("setEnvConfiguration", () => {
};
const config = {
addLayers: false,
addExtension: false,
apiKey: "abcd",
apiKMSKey: "efgh",
site: "datadoghq.com",
Expand Down Expand Up @@ -396,6 +402,7 @@ describe("setEnvConfiguration", () => {
};
const config = {
addLayers: false,
addExtension: false,
apiKey: "1234",
apiKMSKey: "5678",
site: "datadoghq.eu",
Expand Down Expand Up @@ -438,6 +445,7 @@ describe("setEnvConfiguration", () => {
};
const config = {
addLayers: false,
addExtension: false,
apiKey: "1234",
apiKMSKey: "5678",
site: "datadoghq.eu",
Expand Down Expand Up @@ -482,6 +490,7 @@ describe("setEnvConfiguration", () => {
};
const config = {
addLayers: false,
addExtension: false,
apiKeySecretArn: "some-resource:from:aws:secrets-manager:arn",
site: "datadoghq.eu",
logLevel: "info",
Expand Down Expand Up @@ -525,6 +534,7 @@ describe("setEnvConfiguration", () => {
};
const config = {
addLayers: false,
addExtension: false,
apiKeySecretArn: "some-resource:from:aws:secrets-manager:arn",
site: "datadoghq.eu",
logLevel: "info",
Expand All @@ -548,6 +558,7 @@ describe("validateParameters", () => {
it("returns an error when given an invalid site url", () => {
const params = {
addLayers: true,
addExtension: false,
flushMetricsToLogs: true,
logLevel: "info",
site: "datacathq.com",
Expand All @@ -569,6 +580,7 @@ describe("validateParameters", () => {
it("returns an error when extensionLayerVersion and forwarderArn are set", () => {
const params = {
addLayers: true,
addExtension: false,
flushMetricsToLogs: true,
logLevel: "info",
site: "datadoghq.com",
Expand All @@ -585,9 +597,31 @@ describe("validateParameters", () => {
expect(errors.includes("`extensionLayerVersion` and `forwarderArn` cannot be set at the same time.")).toBe(true);
});

it("returns an error when extensionLayer is true without setting extensionLayerVersion", () => {
const params = {
addLayers: true,
addExtension: true,
flushMetricsToLogs: true,
logLevel: "info",
site: "datadoghq.com",
enableXrayTracing: false,
enableDDTracing: true,
enableDDLogs: true,
enableEnhancedMetrics: true,
forwarderArn: "test-forwarder",
captureLambdaPayload: false,
};

const errors = validateParameters(params);
expect(errors.includes("Please add the 'extensionLayerVersion' parameter for the Datadog serverless macro")).toBe(
true,
);
});

it("returns an error when extensionLayerVersion is set but neither apiKey nor apiKMSKey is set", () => {
const params = {
addLayers: true,
addExtension: true,
flushMetricsToLogs: true,
logLevel: "info",
site: "datadoghq.com",
Expand All @@ -610,6 +644,7 @@ describe("validateParameters", () => {
it("returns an error when multiple api keys are set", () => {
const params = {
addLayers: true,
addExtension: false,
apiKey: "1234",
apiKMSKey: "5678",
flushMetricsToLogs: true,
Expand All @@ -629,6 +664,7 @@ describe("validateParameters", () => {
it("works with ap1", () => {
const params = {
addLayers: true,
addExtension: false,
apiKey: "1234",
flushMetricsToLogs: true,
logLevel: "info",
Expand All @@ -651,6 +687,7 @@ describe("checkForMultipleApiKeys", () => {
expect(
checkForMultipleApiKeys({
addLayers: false,
addExtension: false,
apiKey: "1234",
apiKMSKey: "5678",
logLevel: "debug",
Expand All @@ -669,6 +706,7 @@ describe("checkForMultipleApiKeys", () => {
expect(
checkForMultipleApiKeys({
addLayers: false,
addExtension: false,
apiKey: "5678",
apiKeySecretArn: "some-resource:from:aws:secrets-manager:arn",
logLevel: "debug",
Expand All @@ -687,6 +725,7 @@ describe("checkForMultipleApiKeys", () => {
expect(
checkForMultipleApiKeys({
addLayers: false,
addExtension: false,
apiKeySecretArn: "some-resource:from:aws:secrets-manager:arn",
apiKMSKey: "5678",
logLevel: "debug",
Expand All @@ -705,6 +744,7 @@ describe("checkForMultipleApiKeys", () => {
expect(
checkForMultipleApiKeys({
addLayers: false,
addExtension: false,
apiKey: "1234",
apiKeySecretArn: "some-resource:from:aws:secrets-manager:arn",
apiKMSKey: "5678",
Expand Down
Loading

0 comments on commit bb5797e

Please sign in to comment.