Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adds layers to function #1835

Merged
merged 21 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/serious-dragons-attack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@aws-amplify/backend-function': minor
---

adds support to reference existing layers in defineFunction
5 changes: 5 additions & 0 deletions .changeset/strong-flowers-warn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@aws-amplify/backend': minor
---

adds support to reference existing layers in defineFunction
42 changes: 21 additions & 21 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/backend-function/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export type FunctionProps = {
environment?: Record<string, string | BackendSecret>;
runtime?: NodeVersion;
schedule?: FunctionSchedule | FunctionSchedule[];
layers?: Record<string, string>;
};

// @public (undocumented)
Expand Down
75 changes: 54 additions & 21 deletions packages/backend-function/src/factory.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
import {
FunctionOutput,
functionOutputKey,
} from '@aws-amplify/backend-output-schemas';
import { AttributionMetadataStorage } from '@aws-amplify/backend-output-storage';
import {
AmplifyUserError,
CallerDirectoryExtractor,
TagName,
} from '@aws-amplify/platform-core';
import {
BackendOutputStorageStrategy,
BackendSecret,
Expand All @@ -13,31 +23,27 @@ import {
SsmEnvironmentEntry,
StackProvider,
} from '@aws-amplify/plugin-types';
import { Construct } from 'constructs';
import { NodejsFunction, OutputFormat } from 'aws-cdk-lib/aws-lambda-nodejs';
import * as path from 'path';
import { Duration, Stack, Tags } from 'aws-cdk-lib';
import { CfnFunction, Runtime } from 'aws-cdk-lib/aws-lambda';
import { createRequire } from 'module';
import { FunctionEnvironmentTranslator } from './function_env_translator.js';
import { Rule } from 'aws-cdk-lib/aws-events';
import * as targets from 'aws-cdk-lib/aws-events-targets';
import { Policy } from 'aws-cdk-lib/aws-iam';
import {
CfnFunction,
ILayerVersion,
LayerVersion,
Runtime,
} from 'aws-cdk-lib/aws-lambda';
import { NodejsFunction, OutputFormat } from 'aws-cdk-lib/aws-lambda-nodejs';
import { Construct } from 'constructs';
import { readFileSync } from 'fs';
import { createRequire } from 'module';
import { fileURLToPath } from 'node:url';
import { EOL } from 'os';
import {
FunctionOutput,
functionOutputKey,
} from '@aws-amplify/backend-output-schemas';
import * as path from 'path';
import { FunctionEnvironmentTranslator } from './function_env_translator.js';
import { FunctionEnvironmentTypeGenerator } from './function_env_type_generator.js';
import { AttributionMetadataStorage } from '@aws-amplify/backend-output-storage';
import { fileURLToPath } from 'node:url';
import {
AmplifyUserError,
CallerDirectoryExtractor,
TagName,
} from '@aws-amplify/platform-core';
import { FunctionLayerArnParser } from './layer_parser.js';
import { convertFunctionSchedulesToRuleSchedules } from './schedule_parser.js';
import * as targets from 'aws-cdk-lib/aws-events-targets';
import { Rule } from 'aws-cdk-lib/aws-events';

const functionStackType = 'function-Lambda';

Expand Down Expand Up @@ -126,6 +132,19 @@ export type FunctionProps = {
* schedule: "0 9 ? * 2 *" // every Monday at 9am
*/
schedule?: FunctionSchedule | FunctionSchedule[];

/**
* Attach Lambda layers to a function
ykethan marked this conversation as resolved.
Show resolved Hide resolved
* - A Lambda layer is represented by an object of key/value pair where the key is the module name that is exported from your layer and the value is the ARN of the layer. The key (module name) is used to externalize the module dependency so it doesn't get bundled with your lambda function
* - Maximum of 5 layers can be attached to a function and must be in the same region as the function.
* @example
* layers: {
* "@aws-lambda-powertools/logger": "arn:aws:lambda:<current-region>:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:11"
* },
* @see [Amplify documentation for Lambda layers](https://docs.amplify.aws/react/build-a-backend/functions/add-lambda-layers)
* @see [AWS documentation for Lambda layers](https://docs.aws.amazon.com/lambda/latest/dg/chapter-layers.html)
*/
layers?: Record<string, string>;
};

/**
Expand Down Expand Up @@ -163,6 +182,8 @@ class FunctionFactory implements ConstructFactory<AmplifyFunction> {
): HydratedFunctionProps => {
const name = this.resolveName();
resourceNameValidator?.validate(name);
const parser = new FunctionLayerArnParser();
const layers = parser.parseLayers(this.props.layers ?? {}, name);
return {
name,
entry: this.resolveEntry(),
Expand All @@ -171,6 +192,7 @@ class FunctionFactory implements ConstructFactory<AmplifyFunction> {
environment: this.props.environment ?? {},
runtime: this.resolveRuntime(),
schedule: this.resolveSchedule(),
layers,
};
};

Expand Down Expand Up @@ -292,10 +314,19 @@ class FunctionGenerator implements ConstructContainerEntryGenerator {
scope,
backendSecretResolver,
}: GenerateContainerEntryProps) => {
// resolve layers to LayerVersion objects for the NodejsFunction constructor using the scope.
const resolvedLayers = Object.entries(this.props.layers).map(([key, arn]) =>
LayerVersion.fromLayerVersionArn(
scope,
`${this.props.name}-${key}-layer`,
arn
)
);

return new AmplifyFunction(
scope,
this.props.name,
this.props,
{ ...this.props, resolvedLayers },
backendSecretResolver,
this.outputStorageStrategy
);
Expand All @@ -315,7 +346,7 @@ class AmplifyFunction
constructor(
scope: Construct,
id: string,
props: HydratedFunctionProps,
props: HydratedFunctionProps & { resolvedLayers: ILayerVersion[] },
backendSecretResolver: BackendSecretResolver,
outputStorageStrategy: BackendOutputStorageStrategy<FunctionOutput>
) {
Expand Down Expand Up @@ -365,6 +396,7 @@ class AmplifyFunction
timeout: Duration.seconds(props.timeoutSeconds),
memorySize: props.memoryMB,
runtime: nodeVersionMap[props.runtime],
layers: props.resolvedLayers,
bundling: {
format: OutputFormat.ESM,
banner: bannerCode,
Expand All @@ -375,6 +407,7 @@ class AmplifyFunction
},
minify: true,
sourceMap: true,
externalModules: Object.keys(props.layers),
},
});
} catch (error) {
Expand Down
Loading