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

fix(apigateway): SAM CLI asset metadata missing from SpecRestApi #17293

Merged
merged 12 commits into from
Nov 11, 2021
27 changes: 27 additions & 0 deletions packages/@aws-cdk/aws-apigateway/lib/api-definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import * as s3_assets from '@aws-cdk/aws-s3-assets';

// keep this import separate from other imports to reduce chance for merge conflicts with v2-main
// eslint-disable-next-line no-duplicate-imports, import/order
import * as cxapi from '@aws-cdk/cx-api';
import { Node } from 'constructs';
import { CfnRestApi } from './apigateway.generated';
import { IRestApi } from './restapi';
import { Construct } from '@aws-cdk/core';

/**
Expand Down Expand Up @@ -82,6 +86,15 @@ export abstract class ApiDefinition {
* assume it's initialized. You may just use it as a construct scope.
*/
public abstract bind(scope: Construct): ApiDefinitionConfig;

/**
* Called after the CFN RestApi resource has been created to allow the Api
* Definition to bind to it. Specifically it's required to allow assets to add
* metadata for tooling like SAM CLI to be able to find their origins.
*/
public bindAfterCreate(_scope: Construct, _restApi: IRestApi) {
return;
}
}

/**
Expand Down Expand Up @@ -198,4 +211,18 @@ export class AssetApiDefinition extends ApiDefinition {
},
};
}

public bindAfterCreate(scope: Construct, restApi: IRestApi) {
if (!scope.node.tryGetContext(cxapi.ASSET_RESOURCE_METADATA_ENABLED_CONTEXT)) {
return; // not enabled
}

if (!this.asset) {
throw new Error('bindToResource() must be called after bind()');
}

const child = Node.of(restApi).defaultChild as CfnRestApi;
child.addMetadata(cxapi.ASSET_RESOURCE_METADATA_PATH_KEY, this.asset.assetPath);
child.addMetadata(cxapi.ASSET_RESOURCE_METADATA_PROPERTY_KEY, 'BodyS3Location');
}
}
3 changes: 3 additions & 0 deletions packages/@aws-cdk/aws-apigateway/lib/restapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,9 @@ export class SpecRestApi extends RestApiBase {
endpointConfiguration: this._configureEndpoints(props),
parameters: props.parameters,
});

props.apiDefinition.bindAfterCreate(this, this);

this.node.defaultChild = resource;
this.restApiId = resource.ref;
this.restApiRootResourceId = resource.attrRootResourceId;
Expand Down
19 changes: 19 additions & 0 deletions packages/@aws-cdk/aws-apigateway/test/api-definition.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import '@aws-cdk/assert-internal/jest';
import * as path from 'path';
import { ResourcePart } from '@aws-cdk/assert-internal';
import * as s3 from '@aws-cdk/aws-s3';
import * as cdk from '@aws-cdk/core';
import * as cxapi from '@aws-cdk/cx-api';
import * as apigw from '../lib';

describe('api definition', () => {
Expand Down Expand Up @@ -73,6 +75,23 @@ describe('api definition', () => {
expect(synthesized.assets.length).toEqual(1);

});

test('asset metadata added to RestApi resource that contains Asset Api Definition', () => {
const stack = new cdk.Stack();
stack.node.setContext(cxapi.ASSET_RESOURCE_METADATA_ENABLED_CONTEXT, true);
const assetApiDefinition = apigw.ApiDefinition.fromAsset(path.join(__dirname, 'sample-definition.yaml'));
new apigw.SpecRestApi(stack, 'API', {
apiDefinition: assetApiDefinition,
});

expect(stack).toHaveResource('AWS::ApiGateway::RestApi', {
Metadata: {
'aws:asset:path': 'asset.68497ac876de4e963fc8f7b5f1b28844c18ecc95e3f7c6e9e0bf250e03c037fb.yaml',
'aws:asset:property': 'BodyS3Location',
},
}, ResourcePart.CompleteDefinition);

});
});

describe('apigateway.ApiDefinition.fromBucket', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,14 @@
]
}
},
"Handler": "index.handler",
"Role": {
"Fn::GetAtt": [
"MyAuthorizerFunctionServiceRole8A34C19E",
"Arn"
]
},
"Runtime": "nodejs10.x"
"Handler": "index.handler",
"Runtime": "nodejs14.x"
},
"DependsOn": [
"MyAuthorizerFunctionServiceRole8A34C19E"
Expand Down Expand Up @@ -313,4 +313,4 @@
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const app = new App();
const stack = new Stack(app, 'RequestAuthorizerInteg');

const authorizerFn = new lambda.Function(stack, 'MyAuthorizerFunction', {
runtime: lambda.Runtime.NODEJS_10_X,
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'index.handler',
code: lambda.AssetCode.fromAsset(path.join(__dirname, 'integ.request-authorizer.handler')),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,14 @@
]
}
},
"Handler": "index.handler",
"Role": {
"Fn::GetAtt": [
"MyAuthorizerFunctionServiceRole8A34C19E",
"Arn"
]
},
"Runtime": "nodejs10.x"
"Handler": "index.handler",
"Runtime": "nodejs14.x"
},
"DependsOn": [
"MyAuthorizerFunctionServiceRole8A34C19E"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const app = new App();
const stack = new Stack(app, 'TokenAuthorizerIAMRoleInteg');

const authorizerFn = new lambda.Function(stack, 'MyAuthorizerFunction', {
runtime: lambda.Runtime.NODEJS_10_X,
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'index.handler',
code: lambda.AssetCode.fromAsset(path.join(__dirname, 'integ.token-authorizer.handler')),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,14 @@
]
}
},
"Handler": "index.handler",
"Role": {
"Fn::GetAtt": [
"MyAuthorizerFunctionServiceRole8A34C19E",
"Arn"
]
},
"Runtime": "nodejs10.x"
"Handler": "index.handler",
"Runtime": "nodejs14.x"
},
"DependsOn": [
"MyAuthorizerFunctionServiceRole8A34C19E"
Expand Down Expand Up @@ -313,4 +313,4 @@
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const app = new App();
const stack = new Stack(app, 'TokenAuthorizerInteg');

const authorizerFn = new lambda.Function(stack, 'MyAuthorizerFunction', {
runtime: lambda.Runtime.NODEJS_10_X,
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'index.handler',
code: lambda.AssetCode.fromAsset(path.join(__dirname, 'integ.token-authorizer.handler')),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -564,14 +564,14 @@
]
}
},
"Handler": "index.handler",
"Role": {
"Fn::GetAtt": [
"handlerServiceRole187D5A5A",
"Arn"
]
},
"Runtime": "nodejs10.x"
"Handler": "index.handler",
"Runtime": "nodejs14.x"
},
"DependsOn": [
"handlerServiceRole187D5A5A"
Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-apigateway/test/integ.cors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class TestStack extends Stack {
const api = new apigw.RestApi(this, 'cors-api-test');

const handler = new lambda.Function(this, 'handler', {
runtime: lambda.Runtime.NODEJS_10_X,
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'index.handler',
code: lambda.Code.fromAsset(path.join(__dirname, 'integ.cors.handler')),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@
"Code": {
"ZipFile": "foo"
},
"Handler": "index.handler",
"Role": {
"Fn::GetAtt": [
"myfnServiceRole7822DC24",
"Arn"
]
},
"Runtime": "nodejs10.x"
"Handler": "index.handler",
"Runtime": "nodejs14.x"
},
"DependsOn": [
"myfnServiceRole7822DC24"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class LateBoundDeploymentStageStack extends Stack {

const fn = new Function(this, 'myfn', {
code: Code.fromInline('foo'),
runtime: Runtime.NODEJS_10_X,
runtime: Runtime.NODEJS_14_X,
handler: 'index.handler',
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@
"Code": {
"ZipFile": "exports.handler = function echoHandlerCode(event, _, callback) {\n return callback(undefined, {\n isBase64Encoded: false,\n statusCode: 200,\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(event),\n });\n}"
},
"Handler": "index.handler",
"Role": {
"Fn::GetAtt": [
"BooksHandlerServiceRole5B6A8847",
"Arn"
]
},
"Runtime": "nodejs10.x"
"Handler": "index.handler",
"Runtime": "nodejs14.x"
},
"DependsOn": [
"BooksHandlerServiceRole5B6A8847"
Expand Down Expand Up @@ -87,14 +87,14 @@
"Code": {
"ZipFile": "exports.handler = function echoHandlerCode(event, _, callback) {\n return callback(undefined, {\n isBase64Encoded: false,\n statusCode: 200,\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(event),\n });\n}"
},
"Handler": "index.handler",
"Role": {
"Fn::GetAtt": [
"BookHandlerServiceRole894768AD",
"Arn"
]
},
"Runtime": "nodejs10.x"
"Handler": "index.handler",
"Runtime": "nodejs14.x"
},
"DependsOn": [
"BookHandlerServiceRole894768AD"
Expand Down Expand Up @@ -137,14 +137,14 @@
"Code": {
"ZipFile": "exports.handler = function helloCode(_event, _context, callback) {\n return callback(undefined, {\n statusCode: 200,\n body: 'hello, world!',\n });\n}"
},
"Handler": "index.handler",
"Role": {
"Fn::GetAtt": [
"HelloServiceRole1E55EA16",
"Arn"
]
},
"Runtime": "nodejs10.x"
"Handler": "index.handler",
"Runtime": "nodejs14.x"
},
"DependsOn": [
"HelloServiceRole1E55EA16"
Expand Down
6 changes: 3 additions & 3 deletions packages/@aws-cdk/aws-apigateway/test/integ.restapi.books.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@ class BookStack extends cdk.Stack {
super(scope, id);

const booksHandler = new apigw.LambdaIntegration(new lambda.Function(this, 'BooksHandler', {
runtime: lambda.Runtime.NODEJS_10_X,
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'index.handler',
code: lambda.Code.fromInline(`exports.handler = ${echoHandlerCode}`),
}));

const bookHandler = new apigw.LambdaIntegration(new lambda.Function(this, 'BookHandler', {
runtime: lambda.Runtime.NODEJS_10_X,
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'index.handler',
code: lambda.Code.fromInline(`exports.handler = ${echoHandlerCode}`),
}));

const hello = new apigw.LambdaIntegration(new lambda.Function(this, 'Hello', {
runtime: lambda.Runtime.NODEJS_10_X,
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'index.handler',
code: lambda.Code.fromInline(`exports.handler = ${helloCode}`),
}));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -651,14 +651,14 @@
"Code": {
"ZipFile": "exports.handler = function handlerCode(event, _, callback) {\n return callback(undefined, {\n isBase64Encoded: false,\n statusCode: 200,\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(event),\n });\n }"
},
"Handler": "index.handler",
"Role": {
"Fn::GetAtt": [
"MyHandlerServiceRoleFFA06653",
"Arn"
]
},
"Runtime": "nodejs10.x"
"Handler": "index.handler",
"Runtime": "nodejs14.x"
},
"DependsOn": [
"MyHandlerServiceRoleFFA06653"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@
"Code": {
"ZipFile": "exports.handler = async function(event) {\n return {\n 'headers': { 'Content-Type': 'text/plain' },\n 'statusCode': 200\n }\n }"
},
"Handler": "index.handler",
"Role": {
"Fn::GetAtt": [
"firstLambdaServiceRoleB6408C31",
"Arn"
]
},
"Runtime": "nodejs10.x",
"FunctionName": "FirstLambda"
"FunctionName": "FirstLambda",
"Handler": "index.handler",
"Runtime": "nodejs14.x"
},
"DependsOn": [
"firstLambdaServiceRoleB6408C31"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class FirstStack extends cdk.Stack {
}
}`),
handler: 'index.handler',
runtime: lambda.Runtime.NODEJS_10_X,
runtime: lambda.Runtime.NODEJS_14_X,
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@
"Code": {
"ZipFile": "exports.handler = function helloCode(_event, _context, callback) {\n return callback(undefined, {\n statusCode: 200,\n body: 'hello, world!',\n });\n}"
},
"Handler": "index.handler",
"Role": {
"Fn::GetAtt": [
"HelloServiceRole1E55EA16",
"Arn"
]
},
"Runtime": "nodejs10.x"
"Handler": "index.handler",
"Runtime": "nodejs14.x"
},
"DependsOn": [
"HelloServiceRole1E55EA16"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class MultiStack extends cdk.Stack {
super(scope, id);

const hello = new apigw.LambdaIntegration(new lambda.Function(this, 'Hello', {
runtime: lambda.Runtime.NODEJS_10_X,
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'index.handler',
code: lambda.Code.fromInline(`exports.handler = ${helloCode}`),
}));
Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-apigateway/test/integ.restapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class Test extends cdk.Stack {
});

const handler = new lambda.Function(this, 'MyHandler', {
runtime: lambda.Runtime.NODEJS_10_X,
runtime: lambda.Runtime.NODEJS_14_X,
code: lambda.Code.fromInline(`exports.handler = ${handlerCode}`),
handler: 'index.handler',
});
Expand Down
Loading