Skip to content

Commit

Permalink
chore(cli): add SAM CDK integration test cases (#18875)
Browse files Browse the repository at this point in the history
----
Add Integration test cases to cover the integration with SAM CLI tool.

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
moelasmar authored Mar 24, 2022
1 parent 604207c commit 8c60d4d
Show file tree
Hide file tree
Showing 29 changed files with 805 additions and 7 deletions.
1 change: 1 addition & 0 deletions packages/aws-cdk/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const baseConfig = require('@aws-cdk/cdk-build-tools/config/eslintrc');
baseConfig.ignorePatterns.push('lib/init-templates/**/typescript/**/*.ts');
baseConfig.ignorePatterns.push('test/integ/cli/sam_cdk_integ_app/**/*.ts');
baseConfig.parserOptions.project = __dirname + '/tsconfig.json';
module.exports = baseConfig;
1 change: 1 addition & 0 deletions packages/aws-cdk/.npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ tsconfig.json
!test/integ/cli/jest.config.js
!test/integ/uberpackage/jest.config.js
!test/integ/cli-regression-patches/**/*
!test/integ/cli/sam_cdk_integ_app/**/*.ts

.DS_Store

Expand Down
3 changes: 2 additions & 1 deletion packages/aws-cdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@
"sinon": "^9.2.4",
"ts-jest": "^27.1.3",
"ts-mock-imports": "^1.3.8",
"xml-js": "^1.6.11"
"xml-js": "^1.6.11",
"axios": "^0.25.0"
},
"dependencies": {
"@aws-cdk/cloud-assembly-schema": "0.0.0",
Expand Down
219 changes: 218 additions & 1 deletion packages/aws-cdk/test/integ/cli/cli.integtest.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { promises as fs } from 'fs';
import { promises as fs, existsSync } from 'fs';
import * as os from 'os';
import * as path from 'path';
import { retry, sleep } from '../helpers/aws';
import { cloneDirectory, MAJOR_VERSION, shell, withDefaultFixture } from '../helpers/cdk';
import { randomInteger, withSamIntegrationFixture } from '../helpers/sam';
import { integTest } from '../helpers/test-helpers';

jest.setTimeout(600_000);
Expand Down Expand Up @@ -757,6 +758,222 @@ integTest('templates on disk contain metadata resource, also in nested assemblie
expect(JSON.parse(nestedTemplateContents).Resources.CDKMetadata).toBeTruthy();
}));

integTest('CDK synth add the metadata properties expected by sam', withSamIntegrationFixture(async (fixture) => {
// Synth first
await fixture.cdkSynth();

const template = fixture.template('TestStack');

const expectedResources = [
{
// Python Layer Version
id: 'PythonLayerVersion39495CEF',
cdkId: 'PythonLayerVersion',
isBundled: true,
property: 'Content',
},
{
// Layer Version
id: 'LayerVersion3878DA3A',
cdkId: 'LayerVersion',
isBundled: false,
property: 'Content',
},
{
// Bundled layer version
id: 'BundledLayerVersionPythonRuntime6BADBD6E',
cdkId: 'BundledLayerVersionPythonRuntime',
isBundled: true,
property: 'Content',
},
{
// Python Function
id: 'PythonFunction0BCF77FD',
cdkId: 'PythonFunction',
isBundled: true,
property: 'Code',
},
{
// Log Retention Function
id: 'LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A',
cdkId: 'LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a',
isBundled: false,
property: 'Code',
},
{
// Function
id: 'FunctionPythonRuntime28CBDA05',
cdkId: 'FunctionPythonRuntime',
isBundled: false,
property: 'Code',
},
{
// Bundled Function
id: 'BundledFunctionPythonRuntime4D9A0918',
cdkId: 'BundledFunctionPythonRuntime',
isBundled: true,
property: 'Code',
},
{
// NodeJs Function
id: 'NodejsFunction09C1F20F',
cdkId: 'NodejsFunction',
isBundled: true,
property: 'Code',
},
{
// Go Function
id: 'GoFunctionCA95FBAA',
cdkId: 'GoFunction',
isBundled: true,
property: 'Code',
},
{
// Docker Image Function
id: 'DockerImageFunction28B773E6',
cdkId: 'DockerImageFunction',
dockerFilePath: 'Dockerfile',
property: 'Code.ImageUri',
},
{
// Spec Rest Api
id: 'SpecRestAPI7D4B3A34',
cdkId: 'SpecRestAPI',
property: 'BodyS3Location',
},
];

for (const resource of expectedResources) {
fixture.output.write(`validate assets metadata for resource ${resource}`);
expect(resource.id in template.Resources).toBeTruthy();
expect(template.Resources[resource.id]).toEqual(expect.objectContaining({
Metadata: {
'aws:cdk:path': `${fixture.fullStackName('TestStack')}/${resource.cdkId}/Resource`,
'aws:asset:path': expect.stringMatching(/asset\.[0-9a-zA-Z]{64}/),
'aws:asset:is-bundled': resource.isBundled,
'aws:asset:dockerfile-path': resource.dockerFilePath,
'aws:asset:property': resource.property,
},
}));
}

// Nested Stack
fixture.output.write('validate assets metadata for nested stack resource');
expect('NestedStackNestedStackNestedStackNestedStackResourceB70834FD' in template.Resources).toBeTruthy();
expect(template.Resources.NestedStackNestedStackNestedStackNestedStackResourceB70834FD).toEqual(expect.objectContaining({
Metadata: {
'aws:cdk:path': `${fixture.fullStackName('TestStack')}/NestedStack.NestedStack/NestedStack.NestedStackResource`,
'aws:asset:path': expect.stringMatching(`${fixture.stackNamePrefix.replace(/-/, '')}TestStackNestedStack[0-9A-Z]{8}\.nested\.template\.json`),
'aws:asset:property': 'TemplateURL',
},
}));
}));

integTest('CDK synth bundled functions as expected', withSamIntegrationFixture(async (fixture) => {
// Synth first
await fixture.cdkSynth();

const template = fixture.template('TestStack');

const expectedBundledAssets = [
{
// Python Layer Version
id: 'PythonLayerVersion39495CEF',
files: [
'python/layer_version_dependency.py',
'python/geonamescache/__init__.py',
'python/geonamescache-1.3.0.dist-info',
],
},
{
// Layer Version
id: 'LayerVersion3878DA3A',
files: [
'layer_version_dependency.py',
'requirements.txt',
],
},
{
// Bundled layer version
id: 'BundledLayerVersionPythonRuntime6BADBD6E',
files: [
'python/layer_version_dependency.py',
'python/geonamescache/__init__.py',
'python/geonamescache-1.3.0.dist-info',
],
},
{
// Python Function
id: 'PythonFunction0BCF77FD',
files: [
'app.py',
'geonamescache/__init__.py',
'geonamescache-1.3.0.dist-info',
],
},
{
// Function
id: 'FunctionPythonRuntime28CBDA05',
files: [
'app.py',
'requirements.txt',
],
},
{
// Bundled Function
id: 'BundledFunctionPythonRuntime4D9A0918',
files: [
'app.py',
'geonamescache/__init__.py',
'geonamescache-1.3.0.dist-info',
],
},
{
// NodeJs Function
id: 'NodejsFunction09C1F20F',
files: [
'index.js',
],
},
{
// Go Function
id: 'GoFunctionCA95FBAA',
files: [
'bootstrap',
],
},
{
// Docker Image Function
id: 'DockerImageFunction28B773E6',
files: [
'app.js',
'Dockerfile',
'package.json',
],
},
];

for (const resource of expectedBundledAssets) {
const assetPath = template.Resources[resource.id].Metadata['aws:asset:path'];
for (const file of resource.files) {
fixture.output.write(`validate Path ${file} for resource ${resource}`);
expect(existsSync(path.join(fixture.integTestDir, 'cdk.out', assetPath, file))).toBeTruthy();
}
}
}));

integTest('sam can locally test the synthesized cdk application', withSamIntegrationFixture(async (fixture) => {
// Synth first
await fixture.cdkSynth();

const result = await fixture.samLocalStartApi(
'TestStack', false, randomInteger(30000, 40000), '/restapis/spec/pythonFunction');
expect(result.actionSucceeded).toBeTruthy();
expect(result.actionOutput).toEqual(expect.objectContaining({
message: 'Hello World',
}));
}));

integTest('skips notice refresh', withDefaultFixture(async (fixture) => {
const output = await fixture.cdkSynth({
options: ['--no-notices'],
Expand Down
11 changes: 11 additions & 0 deletions packages/aws-cdk/test/integ/cli/sam_cdk_integ_app/bin/test-app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env node
if (process.env.PACKAGE_LAYOUT_VERSION === '1') {
var { App } = require('@aws-cdk/core');
} else {
var { App } = require('aws-cdk-lib');
}
var test_stack_1 = require('../lib/test-stack');
var app = new App();
const stackPrefix = process.env.STACK_NAME_PREFIX;
new test_stack_1.CDKSupportDemoRootStack(app, `${stackPrefix}-TestStack`);
app.synth();
6 changes: 6 additions & 0 deletions packages/aws-cdk/test/integ/cli/sam_cdk_integ_app/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"app": "node bin/test-app.js",
"context": {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
if (process.env.PACKAGE_LAYOUT_VERSION === '1') {
var { NestedStack } = require('@aws-cdk/core');
var { Function, Runtime, Code } = require('@aws-cdk/aws-lambda');
} else {
var { NestedStack } = require('aws-cdk-lib');
var { Function, Runtime, Code } = require('aws-cdk-lib/aws-lambda');
}

class NestedStack1 extends NestedStack {
constructor(scope, id, props) {
super(scope, id, props);
new Function(this, 'FunctionPythonRuntime', {
runtime: Runtime.PYTHON_3_7,
code: Code.fromAsset('./src/python/Function'),
handler: 'app.lambda_handler',
});
}
}
exports.NestedStack1 = NestedStack1;
Loading

0 comments on commit 8c60d4d

Please sign in to comment.