Skip to content

Commit e442c3d

Browse files
authored
chore(ci): move e2e utils into testing (#1661)
* chore: move e2e utils into testing * chore: move test to correct folder * chore: reduced duplication * chore: add sonarcloud properties temp * chore: add sonarcloud properties temp * chore: remove sonarcloud properties * improv: refactor tests to remove duplication * improv: refactor tests to remove duplication * improv: refactor tests to remove duplication * fix: typo * fix: typo * chore: fix parameters test * fix: layer arn retrieval * chore: make ssm parameter name unique * docs: explain layers tests * chore: make layer id unique * chore: added removal policy * chore: make parameter name unique
1 parent 50b6ace commit e442c3d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+2799
-2937
lines changed

Diff for: layers/src/canary-stack.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { CustomResource, Duration, Stack, StackProps } from 'aws-cdk-lib';
22
import { Construct } from 'constructs';
33
import { LayerVersion, Runtime } from 'aws-cdk-lib/aws-lambda';
44
import { RetentionDays } from 'aws-cdk-lib/aws-logs';
5-
import { v4 } from 'uuid';
5+
import { randomUUID } from 'node:crypto';
66
import { Effect, PolicyStatement } from 'aws-cdk-lib/aws-iam';
77
import { Provider } from 'aws-cdk-lib/custom-resources';
88
import { StringParameter } from 'aws-cdk-lib/aws-ssm';
@@ -20,7 +20,7 @@ export class CanaryStack extends Stack {
2020
super(scope, id, props);
2121
const { layerName, powertoolsPackageVersion } = props;
2222

23-
const suffix = v4().substring(0, 5);
23+
const suffix = randomUUID().substring(0, 5);
2424

2525
const layerArn = StringParameter.fromStringParameterAttributes(
2626
this,

Diff for: layers/src/layer-publisher-stack.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ import {
77
CfnLayerVersionPermission,
88
} from 'aws-cdk-lib/aws-lambda';
99
import { StringParameter } from 'aws-cdk-lib/aws-ssm';
10+
import { resolve } from 'node:path';
1011

1112
export interface LayerPublisherStackProps extends StackProps {
1213
readonly layerName?: string;
1314
readonly powertoolsPackageVersion?: string;
1415
readonly ssmParameterLayerArn: string;
16+
readonly removeLayerVersion?: boolean;
1517
}
1618

1719
export class LayerPublisherStack extends Stack {
@@ -23,7 +25,7 @@ export class LayerPublisherStack extends Stack {
2325
) {
2426
super(scope, id, props);
2527

26-
const { layerName, powertoolsPackageVersion } = props;
28+
const { layerName, powertoolsPackageVersion, removeLayerVersion } = props;
2729

2830
console.log(
2931
`publishing layer ${layerName} version : ${powertoolsPackageVersion}`
@@ -40,7 +42,11 @@ export class LayerPublisherStack extends Stack {
4042
license: 'MIT-0',
4143
// This is needed because the following regions do not support the compatibleArchitectures property #1400
4244
// ...(![ 'eu-south-2', 'eu-central-2', 'ap-southeast-4' ].includes(Stack.of(this).region) ? { compatibleArchitectures: [Architecture.X86_64] } : {}),
43-
code: Code.fromAsset('../tmp'),
45+
code: Code.fromAsset(resolve(__dirname, '..', '..', 'tmp')),
46+
removalPolicy:
47+
removeLayerVersion === true
48+
? RemovalPolicy.DESTROY
49+
: RemovalPolicy.RETAIN,
4450
});
4551

4652
const layerPermission = new CfnLayerVersionPermission(
@@ -60,6 +66,7 @@ export class LayerPublisherStack extends Stack {
6066
parameterName: props.ssmParameterLayerArn,
6167
stringValue: this.lambdaLayerVersion.layerVersionArn,
6268
});
69+
6370
new CfnOutput(this, 'LatestLayerArn', {
6471
value: this.lambdaLayerVersion.layerVersionArn,
6572
exportName: props?.layerName ?? `LambdaPowerToolsForTypeScriptLayerARN`,

Diff for: layers/tests/e2e/layerPublisher.class.test.functionCode.ts

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export const handler = (): void => {
3535

3636
// Check that the tracer is working
3737
const segment = tracer.getSegment();
38+
if (!segment) throw new Error('Segment not found');
3839
const handlerSegment = segment.addNewSubsegment('### index.handler');
3940
tracer.setSegment(handlerSegment);
4041
tracer.annotateColdStart();

Diff for: layers/tests/e2e/layerPublisher.test.ts

+76-86
Original file line numberDiff line numberDiff line change
@@ -4,129 +4,119 @@
44
* @group e2e/layers/all
55
*/
66
import { App } from 'aws-cdk-lib';
7-
import { LayerVersion, Tracing } from 'aws-cdk-lib/aws-lambda';
7+
import { LayerVersion } from 'aws-cdk-lib/aws-lambda';
88
import { LayerPublisherStack } from '../../src/layer-publisher-stack';
99
import {
10+
TestNodejsFunction,
1011
TestStack,
11-
defaultRuntime,
12+
TestInvocationLogs,
13+
invokeFunctionOnce,
14+
generateTestUniqueName,
1215
} from '@aws-lambda-powertools/testing-utils';
13-
import {
14-
generateUniqueName,
15-
invokeFunction,
16-
isValidRuntimeKey,
17-
createStackWithLambdaFunction,
18-
} from '../../../packages/commons/tests/utils/e2eUtils';
1916
import {
2017
RESOURCE_NAME_PREFIX,
2118
SETUP_TIMEOUT,
2219
TEARDOWN_TIMEOUT,
2320
TEST_CASE_TIMEOUT,
2421
} from './constants';
25-
import {
26-
LEVEL,
27-
InvocationLogs,
28-
} from '../../../packages/commons/tests/utils/InvocationLogs';
29-
import { v4 } from 'uuid';
30-
import path from 'path';
22+
import { join } from 'node:path';
3123
import packageJson from '../../package.json';
3224

33-
const runtime: string = process.env.RUNTIME || defaultRuntime;
25+
/**
26+
* This test has two stacks:
27+
* 1. LayerPublisherStack - publishes a layer version using the LayerPublisher construct and containing the Powertools utilities from the repo
28+
* 2. TestStack - uses the layer published in the first stack and contains a lambda function that uses the Powertools utilities from the layer
29+
*
30+
* The lambda function is invoked once and the logs are collected. The goal of the test is to verify that the layer creation and usage works as expected.
31+
*/
32+
describe(`Layers E2E tests, publisher stack`, () => {
33+
const testStack = new TestStack({
34+
stackNameProps: {
35+
stackNamePrefix: RESOURCE_NAME_PREFIX,
36+
testName: 'functionStack',
37+
},
38+
});
3439

35-
if (!isValidRuntimeKey(runtime)) {
36-
throw new Error(`Invalid runtime key: ${runtime}`);
37-
}
40+
let invocationLogs: TestInvocationLogs;
3841

39-
describe(`layers E2E tests (LayerPublisherStack) for runtime: ${runtime}`, () => {
40-
const uuid = v4();
41-
let invocationLogs: InvocationLogs[];
42-
const stackNameLayers = generateUniqueName(
43-
RESOURCE_NAME_PREFIX,
44-
uuid,
45-
runtime,
46-
'layerStack'
47-
);
48-
const stackNameFunction = generateUniqueName(
49-
RESOURCE_NAME_PREFIX,
50-
uuid,
51-
runtime,
52-
'functionStack'
53-
);
54-
const functionName = generateUniqueName(
55-
RESOURCE_NAME_PREFIX,
56-
uuid,
57-
runtime,
58-
'function'
59-
);
60-
const ssmParameterLayerName = generateUniqueName(
61-
RESOURCE_NAME_PREFIX,
62-
uuid,
63-
runtime,
64-
'parameter'
42+
const ssmParameterLayerName = generateTestUniqueName({
43+
testPrefix: `${RESOURCE_NAME_PREFIX}`,
44+
testName: 'parameter',
45+
});
46+
47+
// Location of the lambda function code
48+
const lambdaFunctionCodeFilePath = join(
49+
__dirname,
50+
'layerPublisher.class.test.functionCode.ts'
6551
);
66-
const lambdaFunctionCodeFile = 'layerPublisher.class.test.functionCode.ts';
6752

68-
const invocationCount = 1;
6953
const powerToolsPackageVersion = packageJson.version;
70-
const layerName = generateUniqueName(
71-
RESOURCE_NAME_PREFIX,
72-
uuid,
73-
runtime,
74-
'layer'
75-
);
7654

77-
const testStack = new TestStack(stackNameFunction);
7855
const layerApp = new App();
79-
const layerStack = new LayerPublisherStack(layerApp, stackNameLayers, {
80-
layerName,
56+
const layerId = generateTestUniqueName({
57+
testPrefix: RESOURCE_NAME_PREFIX,
58+
testName: 'layerStack',
59+
});
60+
const layerStack = new LayerPublisherStack(layerApp, layerId, {
61+
layerName: layerId,
8162
powertoolsPackageVersion: powerToolsPackageVersion,
8263
ssmParameterLayerArn: ssmParameterLayerName,
64+
removeLayerVersion: true,
65+
});
66+
const testLayerStack = new TestStack({
67+
stackNameProps: {
68+
stackNamePrefix: RESOURCE_NAME_PREFIX,
69+
testName: 'layerStack',
70+
},
71+
app: layerApp,
72+
stack: layerStack,
8373
});
84-
const testLayerStack = new TestStack(stackNameLayers, layerApp, layerStack);
8574

8675
beforeAll(async () => {
87-
const outputs = await testLayerStack.deploy();
76+
await testLayerStack.deploy();
8877

8978
const layerVersion = LayerVersion.fromLayerVersionArn(
9079
testStack.stack,
9180
'LayerVersionArnReference',
92-
outputs['LatestLayerArn']
81+
testLayerStack.findAndGetStackOutputValue('LatestLayerArn')
9382
);
94-
createStackWithLambdaFunction({
95-
stack: testStack.stack,
96-
functionName: functionName,
97-
functionEntry: path.join(__dirname, lambdaFunctionCodeFile),
98-
tracing: Tracing.ACTIVE,
99-
environment: {
100-
UUID: uuid,
101-
POWERTOOLS_PACKAGE_VERSION: powerToolsPackageVersion,
102-
POWERTOOLS_SERVICE_NAME: 'LayerPublisherStack',
103-
},
104-
runtime: runtime,
105-
bundling: {
106-
externalModules: [
107-
'@aws-lambda-powertools/commons',
108-
'@aws-lambda-powertools/logger',
109-
'@aws-lambda-powertools/metrics',
110-
'@aws-lambda-powertools/tracer',
111-
],
83+
new TestNodejsFunction(
84+
testStack,
85+
{
86+
entry: lambdaFunctionCodeFilePath,
87+
environment: {
88+
POWERTOOLS_PACKAGE_VERSION: powerToolsPackageVersion,
89+
POWERTOOLS_SERVICE_NAME: 'LayerPublisherStack',
90+
},
91+
bundling: {
92+
externalModules: [
93+
'@aws-lambda-powertools/commons',
94+
'@aws-lambda-powertools/logger',
95+
'@aws-lambda-powertools/metrics',
96+
'@aws-lambda-powertools/tracer',
97+
],
98+
},
99+
layers: [layerVersion],
112100
},
113-
layers: [layerVersion],
114-
});
101+
{
102+
nameSuffix: 'testFn',
103+
}
104+
);
115105

116106
await testStack.deploy();
117107

118-
invocationLogs = await invokeFunction(
108+
const functionName = testStack.findAndGetStackOutputValue('testFn');
109+
110+
invocationLogs = await invokeFunctionOnce({
119111
functionName,
120-
invocationCount,
121-
'SEQUENTIAL'
122-
);
112+
});
123113
}, SETUP_TIMEOUT);
124114

125115
describe('LayerPublisherStack usage', () => {
126116
it(
127117
'should have no errors in the logs, which indicates the pacakges version matches the expected one',
128118
() => {
129-
const logs = invocationLogs[0].getFunctionLogs(LEVEL.ERROR);
119+
const logs = invocationLogs.getFunctionLogs('ERROR');
130120

131121
expect(logs.length).toBe(0);
132122
},
@@ -136,7 +126,7 @@ describe(`layers E2E tests (LayerPublisherStack) for runtime: ${runtime}`, () =>
136126
it(
137127
'should have one warning related to missing Metrics namespace',
138128
() => {
139-
const logs = invocationLogs[0].getFunctionLogs(LEVEL.WARN);
129+
const logs = invocationLogs.getFunctionLogs('WARN');
140130

141131
expect(logs.length).toBe(1);
142132
expect(logs[0]).toContain('Namespace should be defined, default used');
@@ -147,7 +137,7 @@ describe(`layers E2E tests (LayerPublisherStack) for runtime: ${runtime}`, () =>
147137
it(
148138
'should have one info log related to coldstart metric',
149139
() => {
150-
const logs = invocationLogs[0].getFunctionLogs(LEVEL.INFO);
140+
const logs = invocationLogs.getFunctionLogs('INFO');
151141

152142
expect(logs.length).toBe(1);
153143
expect(logs[0]).toContain('ColdStart');
@@ -158,7 +148,7 @@ describe(`layers E2E tests (LayerPublisherStack) for runtime: ${runtime}`, () =>
158148
it(
159149
'should have one debug log that says Hello World!',
160150
() => {
161-
const logs = invocationLogs[0].getFunctionLogs(LEVEL.DEBUG);
151+
const logs = invocationLogs.getFunctionLogs('DEBUG');
162152

163153
expect(logs.length).toBe(1);
164154
expect(logs[0]).toContain('Hello World!');

Diff for: package-lock.json

+1-11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: package.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,7 @@
7070
"ts-node": "^10.9.1",
7171
"typedoc": "^0.24.7",
7272
"typedoc-plugin-missing-exports": "^2.0.0",
73-
"typescript": "^4.9.4",
74-
"uuid": "^9.0.0"
73+
"typescript": "^4.9.4"
7574
},
7675
"engines": {
7776
"node": ">=14"

0 commit comments

Comments
 (0)