Skip to content

Commit

Permalink
adds architecture prop on defineFunction
Browse files Browse the repository at this point in the history
  • Loading branch information
ykethan committed Aug 29, 2024
1 parent 5d6eef2 commit 11c9f67
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 26 deletions.
5 changes: 5 additions & 0 deletions .changeset/swift-starfishes-relate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@aws-amplify/backend-function': minor
---

adds support for architecture property on defineFunction
4 changes: 4 additions & 0 deletions packages/backend-function/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ export type AddEnvironmentFactory = {
addEnvironment: (key: string, value: string | BackendSecret) => void;
};

// @public (undocumented)
export type ArchitectureType = 'x86_64' | 'arm64';

// @public (undocumented)
export type CronSchedule = `${string} ${string} ${string} ${string} ${string}` | `${string} ${string} ${string} ${string} ${string} ${string}`;

Expand All @@ -29,6 +32,7 @@ export type FunctionProps = {
memoryMB?: number;
environment?: Record<string, string | BackendSecret>;
runtime?: NodeVersion;
architecture?: ArchitectureType;
schedule?: FunctionSchedule | FunctionSchedule[];
};

Expand Down
45 changes: 35 additions & 10 deletions packages/backend-function/src/factory.test.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import { beforeEach, describe, it, mock } from 'node:test';
import { App, Stack } from 'aws-cdk-lib';
import {
ConstructFactoryGetInstanceProps,
ResourceNameValidator,
} from '@aws-amplify/plugin-types';
import assert from 'node:assert';
import { StackMetadataBackendOutputStorageStrategy } from '@aws-amplify/backend-output-storage';
import {
ConstructContainerStub,
ResourceNameValidatorStub,
StackResolverStub,
} from '@aws-amplify/backend-platform-test-stubs';
import { defaultLambda } from './test-assets/default-lambda/resource.js';
import {
ConstructFactoryGetInstanceProps,
ResourceNameValidator,
} from '@aws-amplify/plugin-types';
import { App, Stack } from 'aws-cdk-lib';
import { Template } from 'aws-cdk-lib/assertions';
import { Policy, PolicyStatement } from 'aws-cdk-lib/aws-iam';
import { Runtime } from 'aws-cdk-lib/aws-lambda';
import assert from 'node:assert';
import { beforeEach, describe, it, mock } from 'node:test';
import { NodeVersion, defineFunction } from './factory.js';
import { defaultLambda } from './test-assets/default-lambda/resource.js';
import { lambdaWithDependencies } from './test-assets/lambda-with-dependencies/resource.js';
import { Runtime } from 'aws-cdk-lib/aws-lambda';
import { Policy, PolicyStatement } from 'aws-cdk-lib/aws-iam';

const createStackAndSetContext = (): Stack => {
const app = new App();
Expand Down Expand Up @@ -334,6 +334,31 @@ void describe('AmplifyFunctionFactory', () => {
});
});

void describe('architectures property', () => {
void it('sets valid architectures', () => {
const lambda = defineFunction({
entry: './test-assets/default-lambda/handler.ts',
architecture: 'arm64',
}).getInstance(getInstanceProps);
const template = Template.fromStack(Stack.of(lambda.resources.lambda));

template.hasResourceProperties('AWS::Lambda::Function', {
Architectures: ['arm64'],
});
});

void it('defaults to x86_64 architecture', () => {
const lambda = defineFunction({
entry: './test-assets/default-lambda/handler.ts',
}).getInstance(getInstanceProps);
const template = Template.fromStack(Stack.of(lambda.resources.lambda));

template.hasResourceProperties('AWS::Lambda::Function', {
Architectures: ['x86_64'],
});
});
});

void describe('schedule property', () => {
void it('sets valid schedule - rate', () => {
const lambda = defineFunction({
Expand Down
64 changes: 48 additions & 16 deletions packages/backend-function/src/factory.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import {
FunctionOutput,
functionOutputKey,
} from '@aws-amplify/backend-output-schemas';
import { AttributionMetadataStorage } from '@aws-amplify/backend-output-storage';
import { AmplifyUserError, TagName } from '@aws-amplify/platform-core';
import {
BackendOutputStorageStrategy,
BackendSecret,
Expand All @@ -12,28 +18,22 @@ import {
ResourceProvider,
SsmEnvironmentEntry,
} 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 { getCallerDirectory } from './get_caller_directory.js';
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 { Architecture, CfnFunction, 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, TagName } from '@aws-amplify/platform-core';
import { getCallerDirectory } from './get_caller_directory.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 @@ -109,6 +109,13 @@ export type FunctionProps = {
*/
runtime?: NodeVersion;

/**
* The architecture of the target platform for the function.
* Defaults to x86_64.
* @see [AWS Lambda architectures](https://docs.aws.amazon.com/lambda/latest/dg/foundation-arch.html)
*/
architecture?: ArchitectureType;

/**
* A time interval string to periodically run the function.
* This can be either a string of `"every <positive whole number><m (minute) or h (hour)>"`, `"every day|week|month|year"` or cron expression.
Expand Down Expand Up @@ -165,6 +172,7 @@ class FunctionFactory implements ConstructFactory<AmplifyFunction> {
memoryMB: this.resolveMemory(),
environment: this.props.environment ?? {},
runtime: this.resolveRuntime(),
architecture: this.resolveArchitecture(),
schedule: this.resolveSchedule(),
};
};
Expand Down Expand Up @@ -256,6 +264,23 @@ class FunctionFactory implements ConstructFactory<AmplifyFunction> {
return this.props.runtime;
};

private resolveArchitecture = () => {
// if architecture is not set, default to x86_64
if (!this.props.architecture) {
return 'x86_64';
}

if (!(this.props.architecture in architectureMap)) {
throw new Error(
`architecture must be one of the following: ${Object.keys(
architectureMap
).join(', ')}`
);
}

return this.props.architecture;
};

private resolveSchedule = () => {
if (!this.props.schedule) {
return [];
Expand Down Expand Up @@ -349,6 +374,7 @@ class AmplifyFunction
timeout: Duration.seconds(props.timeoutSeconds),
memorySize: props.memoryMB,
runtime: nodeVersionMap[props.runtime],
architecture: architectureMap[props.architecture],
bundling: {
format: OutputFormat.ESM,
banner: bannerCode,
Expand Down Expand Up @@ -475,3 +501,9 @@ const nodeVersionMap: Record<NodeVersion, Runtime> = {
18: Runtime.NODEJS_18_X,
20: Runtime.NODEJS_20_X,
};

export type ArchitectureType = 'x86_64' | 'arm64';
const architectureMap: Record<ArchitectureType, Architecture> = {
x86_64: Architecture.X86_64,
arm64: Architecture.ARM_64,
};

0 comments on commit 11c9f67

Please sign in to comment.