Skip to content

Commit d32e4cd

Browse files
authored
Add ephemeralStorageSizeMB option to defineFunction (#2283)
* Add ephemeralStorageSize option to defineFunction * fixup * fix: remove unit from default value * re-generate api reports * rename ephemeralStorageSize to ephemeralStorageSizeMB * add `mebibytes` to eslint dictionary * fix: throw AmplifyUserError instead of Error
1 parent 478ea85 commit d32e4cd

File tree

5 files changed

+106
-1
lines changed

5 files changed

+106
-1
lines changed

.changeset/nasty-tables-heal.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@aws-amplify/backend-function': minor
3+
---
4+
5+
Add ephemeralStorageSizeMB option to defineFunction

.eslint_dictionary.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
"lstat",
101101
"macos",
102102
"matchers",
103+
"mebibytes",
103104
"mfas",
104105
"minify",
105106
"mkdtemp",

packages/backend-function/API.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ export type FunctionProps = {
9393
entry?: string;
9494
timeoutSeconds?: number;
9595
memoryMB?: number;
96+
ephemeralStorageSizeMB?: number;
9697
environment?: Record<string, string | BackendSecret>;
9798
runtime?: NodeVersion;
9899
schedule?: FunctionSchedule | FunctionSchedule[];

packages/backend-function/src/factory.test.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,4 +683,71 @@ void describe('AmplifyFunctionFactory', () => {
683683
'function-Lambda'
684684
);
685685
});
686+
687+
void describe('ephemeralStorageSizeMB property', () => {
688+
void it('sets valid ephemeralStorageSize', () => {
689+
const lambda = defineFunction({
690+
entry: './test-assets/default-lambda/handler.ts',
691+
ephemeralStorageSizeMB: 1024,
692+
}).getInstance(getInstanceProps);
693+
const template = Template.fromStack(lambda.stack);
694+
695+
template.hasResourceProperties('AWS::Lambda::Function', {
696+
EphemeralStorage: { Size: 1024 },
697+
});
698+
});
699+
700+
void it('sets default ephemeralStorageSizeMB', () => {
701+
const lambda = defineFunction({
702+
entry: './test-assets/default-lambda/handler.ts',
703+
}).getInstance(getInstanceProps);
704+
const template = Template.fromStack(lambda.stack);
705+
706+
template.hasResourceProperties('AWS::Lambda::Function', {
707+
EphemeralStorage: { Size: 512 },
708+
});
709+
});
710+
711+
void it('throws on ephemeralStorageSizeMB below 512 MB', () => {
712+
assert.throws(
713+
() =>
714+
defineFunction({
715+
entry: './test-assets/default-lambda/handler.ts',
716+
ephemeralStorageSizeMB: 511,
717+
}).getInstance(getInstanceProps),
718+
new AmplifyUserError('InvalidEphemeralStorageSizeMBError', {
719+
message: `Invalid function ephemeralStorageSizeMB of 511`,
720+
resolution: `ephemeralStorageSizeMB must be a whole number between 512 and 10240 inclusive`,
721+
})
722+
);
723+
});
724+
725+
void it('throws on ephemeralStorageSizeMB above 10240 MB', () => {
726+
assert.throws(
727+
() =>
728+
defineFunction({
729+
entry: './test-assets/default-lambda/handler.ts',
730+
ephemeralStorageSizeMB: 10241,
731+
}).getInstance(getInstanceProps),
732+
new AmplifyUserError('InvalidEphemeralStorageSizeMBError', {
733+
message: `Invalid function ephemeralStorageSizeMB of 10241`,
734+
resolution: `ephemeralStorageSizeMB must be a whole number between 512 and 10240 inclusive`,
735+
})
736+
);
737+
});
738+
739+
void it('throws on fractional ephemeralStorageSizeMB', () => {
740+
assert.throws(
741+
() =>
742+
defineFunction({
743+
entry: './test-assets/default-lambda/handler.ts',
744+
ephemeralStorageSizeMB: 512.5,
745+
}).getInstance(getInstanceProps),
746+
new AmplifyUserError('InvalidEphemeralStorageSizeMBError', {
747+
message: `Invalid function ephemeralStorageSizeMB of 512.5`,
748+
resolution: `ephemeralStorageSizeMB must be a whole number between 512 and 10240 inclusive`,
749+
})
750+
);
751+
});
752+
});
686753
});

packages/backend-function/src/factory.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
SsmEnvironmentEntry,
2727
StackProvider,
2828
} from '@aws-amplify/plugin-types';
29-
import { Duration, Stack, Tags } from 'aws-cdk-lib';
29+
import { Duration, Size, Stack, Tags } from 'aws-cdk-lib';
3030
import { Rule } from 'aws-cdk-lib/aws-events';
3131
import * as targets from 'aws-cdk-lib/aws-events-targets';
3232
import { Policy } from 'aws-cdk-lib/aws-iam';
@@ -115,6 +115,13 @@ export type FunctionProps = {
115115
*/
116116
memoryMB?: number;
117117

118+
/**
119+
* The size of the function's /tmp directory in MB.
120+
* Must be a whole number.
121+
* @default 512
122+
*/
123+
ephemeralStorageSizeMB?: number;
124+
118125
/**
119126
* Environment variables that will be available during function execution
120127
*/
@@ -236,6 +243,7 @@ class FunctionFactory implements ConstructFactory<AmplifyFunction> {
236243
entry: this.resolveEntry(),
237244
timeoutSeconds: this.resolveTimeout(),
238245
memoryMB: this.resolveMemory(),
246+
ephemeralStorageSizeMB: this.resolveEphemeralStorageSize(),
239247
environment: this.resolveEnvironment(),
240248
runtime: this.resolveRuntime(),
241249
schedule: this.resolveSchedule(),
@@ -324,6 +332,28 @@ class FunctionFactory implements ConstructFactory<AmplifyFunction> {
324332
return this.props.memoryMB;
325333
};
326334

335+
private resolveEphemeralStorageSize = () => {
336+
const ephemeralStorageSizeMin = 512;
337+
const ephemeralStorageSizeMax = 10240;
338+
const ephemeralStorageSizeDefault = 512;
339+
if (this.props.ephemeralStorageSizeMB === undefined) {
340+
return ephemeralStorageSizeDefault;
341+
}
342+
if (
343+
!isWholeNumberBetweenInclusive(
344+
this.props.ephemeralStorageSizeMB,
345+
ephemeralStorageSizeMin,
346+
ephemeralStorageSizeMax
347+
)
348+
) {
349+
throw new AmplifyUserError('InvalidEphemeralStorageSizeMBError', {
350+
message: `Invalid function ephemeralStorageSizeMB of ${this.props.ephemeralStorageSizeMB}`,
351+
resolution: `ephemeralStorageSizeMB must be a whole number between ${ephemeralStorageSizeMin} and ${ephemeralStorageSizeMax} inclusive`,
352+
});
353+
}
354+
return this.props.ephemeralStorageSizeMB;
355+
};
356+
327357
private resolveEnvironment = () => {
328358
if (this.props.environment === undefined) {
329359
return {};
@@ -509,6 +539,7 @@ class AmplifyFunction
509539
entry: props.entry,
510540
timeout: Duration.seconds(props.timeoutSeconds),
511541
memorySize: props.memoryMB,
542+
ephemeralStorageSize: Size.mebibytes(props.ephemeralStorageSizeMB),
512543
runtime: nodeVersionMap[props.runtime],
513544
layers: props.resolvedLayers,
514545
bundling: {

0 commit comments

Comments
 (0)