Skip to content

Commit 4684b1e

Browse files
authored
Merge branch 'master' into master
2 parents e58dcce + 64086ea commit 4684b1e

File tree

126 files changed

+2857
-2632
lines changed

Some content is hidden

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

126 files changed

+2857
-2632
lines changed

.github/PULL_REQUEST_TEMPLATE.md

+1-28
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,10 @@
1-
## Description
21

3-
<!--
4-
The description should describe _motivation_. Think about your code reviewers and what information they need in order to understand what you did. If it's a big commit (hopefully not), try to provide some good entry points so it will be easier to follow.
5-
If not obvious (i.e. from unit tests), describe how you verified that your change works.
6-
-->
7-
8-
## Commit Message
9-
<!--Simply copy paste from the PR title and replace the necessary parts-->
10-
{*replace-with-pr-title*} (#{*replace-with-pr-number*})
11-
12-
<!--Use this to give a more detailed message that describes the change-->
13-
{replace-with-extended-commit-message}
14-
15-
<!--For every issue your PR resolves, add `fixes #<issue>` or `closes #<issue>`-->
16-
17-
<!--Shout out to collaborators.-->
18-
19-
<!--If your PR includes breaking changes, uncomment and fill in the following (notice how multiple breaking changes should be formatted):-->
20-
<!--
21-
BREAKING CHANGE: Description of what broke and how to achieve this behavior now<br>
22-
\* **module-name:** Another breaking change<br>
23-
\* **module-name:** Yet another breaking change
24-
-->
25-
26-
<!--IMPORTANT: This section cannot contain any additional markdown headers (#)-->
27-
28-
## End Commit Message
292

303
----
314

325
*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
336

34-
<!--
7+
<!--
358
Please read the contribution guidelines and follow the pull-request checklist:
369
https://github.com/aws/aws-cdk/blob/master/CONTRIBUTING.md
3710
-->

.github/actions/prlinter/index.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ const github = require('@actions/github');
33
const linter = require('prlint')
44

55
const checks = {
6-
"MANDATORY_CHANGES": linter.mandatoryChanges,
7-
"COMMIT_MESSAGE": linter.commitMessage
6+
"MANDATORY_CHANGES": linter.mandatoryChanges
87
}
98

109
async function run() {
@@ -21,7 +20,7 @@ async function run() {
2120
}
2221

2322
await check(number);
24-
23+
2524
} catch (error) {
2625

2726
core.setFailed(error.message);

CONTRIBUTING.md

+32-20
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ and let us know if it's not up-to-date (even better, submit a PR with your corr
1111
- [Step 1: Open Issue](#step-1-open-issue)
1212
- [Step 2: Design (optional)](#step-2-design-optional)
1313
- [Step 3: Work your Magic](#step-3-work-your-magic)
14-
- [Step 4: Pull Request](#step-4-pull-request)
15-
- [Step 5: Merge](#step-5-merge)
14+
- [Step 4: Commit](#step-4-commit)
15+
- [Step 5: Pull Request](#step-5-pull-request)
16+
- [Step 6: Merge](#step-6-merge)
1617
- [Tools](#tools)
1718
- [Main build scripts](#main-build-scripts)
1819
- [Partial build tools](#partial-build-tools)
@@ -52,7 +53,7 @@ For day-to-day development and normal contributions, the following SDKs and tool
5253
- [.NET Core SDK 3.0](https://www.microsoft.com/net/download)
5354
- [Python 3.6.5](https://www.python.org/downloads/release/python-365/)
5455
- [Ruby 2.5.1](https://www.ruby-lang.org/en/news/2018/03/28/ruby-2-5-1-released/)
55-
56+
5657
The basic commands to get the repository cloned and built locally follow:
5758

5859
```console
@@ -141,7 +142,7 @@ Integration tests perform a few functions in the CDK code base -
141142
3. (Optionally) Acts as a way to validate that constructs set up the CloudFormation resources as expected. A successful
142143
CloudFormation deployment does not mean that the resources are set up correctly.
143144

144-
If you are working on a new feature that is using previously unused CloudFormation resource types, or involves
145+
If you are working on a new feature that is using previously unused CloudFormation resource types, or involves
145146
configuring resource types across services, you need to write integration tests that use these resource types or
146147
features.
147148

@@ -161,37 +162,48 @@ Examples:
161162
* [integ.destinations.ts](https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/aws-lambda-destinations/test/integ.destinations.ts#L7)
162163
* [integ.token-authorizer.ts](https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/aws-apigateway/test/authorizers/integ.token-authorizer.ts#L6)
163164

164-
### Step 4: Pull Request
165+
### Step 4: Commit
165166

166-
* Push to a GitHub fork or to a branch (naming convention: `<user>/<feature-bug-name>`)
167-
* Submit a Pull Request on GitHub and assign the PR for a review to the "aws/aws-cdk-team" team. The title and description will be used to format the commit message when its merged to master. This in turn, will translate to CHANGELOG entries. It is therefore important we be consistent and informative. Here is an example PR you should use as a reference: https://github.com/aws/aws-cdk/pull/6553.
167+
Create a commit with the proposed change changes:
168168

169-
### Title
169+
* Commit title and message (and PR title and description) must adhere to [conventionalcommits](https://www.conventionalcommits.org).
170+
* The title must begin with `feat(module): title`, `fix(module): title`, `refactor(module): title` or
171+
`chore(module): title`.
172+
* Title should be lowercase.
173+
* No period at the end of the title.
170174

171-
* Must adhere to [conventionalcommits](https://www.conventionalcommits.org).
172-
* The title must begin with one of:
173-
- `feat(module): title`
174-
- `fix(module): title`
175-
- `refactor(module): title`
176-
- `chore(module): title`
177-
* Should be lowercase.
178-
* No period at the end.
175+
* Commit message should describe _motivation_. Think about your code reviewers and what information they need in
176+
order to understand what you did. If it's a big commit (hopefully not), try to provide some good entry points so
177+
it will be easier to follow.
179178

179+
* Commit message should indicate which issues are fixed: `fixes #<issue>` or `closes #<issue>`.
180180

181-
### Description
181+
* Shout out to collaborators.
182182

183-
* Simply follow the PR template carefully.
183+
* If not obvious (i.e. from unit tests), describe how you verified that your change works.
184184

185+
* If this commit includes breaking changes, they must be listed at the end in the following format (notice how multiple breaking changes should be formatted):
185186

187+
```
188+
BREAKING CHANGE: Description of what broke and how to achieve this behavior now
189+
* **module-name:** Another breaking change
190+
* **module-name:** Yet another breaking change
191+
```
192+
193+
### Step 5: Pull Request
194+
195+
* Push to a GitHub fork or to a branch (naming convention: `<user>/<feature-bug-name>`)
196+
* Submit a Pull Requests on GitHub and assign the PR for a review to the "awslabs/aws-cdk" team.
186197
* Please follow the PR checklist written below. We trust our contributors to self-check, and this helps that process!
187198
* Discuss review comments and iterate until you get at least one “Approve”. When iterating, push new commits to the
188199
same branch. Usually all these are going to be squashed when you merge to master. The commit messages should be hints
189200
for you when you finalize your merge commit message.
190-
* Make sure to update the PR title/description if things change.
201+
* Make sure to update the PR title/description if things change. The PR title/description are going to be used as the
202+
commit title/message and will appear in the CHANGELOG, so maintain them all the way throughout the process.
191203

192204

193205

194-
### Step 5: Merge
206+
### Step 6: Merge
195207

196208
* Make sure your PR builds successfully (we have CodeBuild setup to automatically build all PRs)
197209
* Once approved and tested, a maintainer will squash-merge to master and will use your PR title/description as the

allowed-breaking-changes.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@ change-return-type:@aws-cdk/aws-lambda-destinations.EventBridgeDestination.bind
4040
change-return-type:@aws-cdk/aws-lambda-destinations.LambdaDestination.bind
4141
change-return-type:@aws-cdk/aws-lambda-destinations.SnsDestination.bind
4242
change-return-type:@aws-cdk/aws-lambda-destinations.SqsDestination.bind
43-
43+
removed:@aws-cdk/cdk-assets-schema.DockerImageDestination.imageUri

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"devDependencies": {
1717
"conventional-changelog-cli": "^2.0.31",
1818
"fs-extra": "^8.1.0",
19-
"jsii-diff": "^1.0.0",
19+
"jsii-diff": "^1.1.0",
2020
"jsii-pacmak": "^0.22.0",
2121
"jsii-rosetta": "^0.22.0",
2222
"lerna": "^3.20.2",

packages/@aws-cdk/aws-apigateway/README.md

+31-1
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,36 @@ plan.addApiStage({
153153
});
154154
```
155155

156+
In scenarios where you need to create a single api key and configure rate limiting for it, you can use `RateLimitedApiKey`.
157+
This construct lets you specify rate limiting properties which should be applied only to the api key being created.
158+
The API key created has the specified rate limits, such as quota and throttles, applied.
159+
160+
The following example shows how to use a rate limited api key :
161+
```ts
162+
const hello = new lambda.Function(this, 'hello', {
163+
runtime: lambda.Runtime.NODEJS_10_X,
164+
handler: 'hello.handler',
165+
code: lambda.Code.fromAsset('lambda')
166+
});
167+
168+
const api = new apigateway.RestApi(this, 'hello-api', { });
169+
const integration = new apigateway.LambdaIntegration(hello);
170+
171+
const v1 = api.root.addResource('v1');
172+
const echo = v1.addResource('echo');
173+
const echoMethod = echo.addMethod('GET', integration, { apiKeyRequired: true });
174+
175+
const key = new apigateway.RateLimitedApiKey(this, 'rate-limited-api-key', {
176+
customerId: 'hello-customer',
177+
resources: [api],
178+
quota: {
179+
limit: 10000,
180+
period: apigateway.Period.MONTH
181+
}
182+
});
183+
184+
```
185+
156186
### Working with models
157187

158188
When you work with Lambda integrations that are not Proxy integrations, you
@@ -343,7 +373,7 @@ that can be used for controlling access to your REST APIs.
343373

344374
#### IAM-based authorizer
345375

346-
The following CDK code provides 'excecute-api' permission to an IAM user, via IAM policies, for the 'GET' method on the `books` resource:
376+
The following CDK code provides 'execute-api' permission to an IAM user, via IAM policies, for the 'GET' method on the `books` resource:
347377

348378
```ts
349379
const getBooks = books.addMethod('GET', new apigateway.HttpIntegration('http://amazon.com'), {

packages/@aws-cdk/aws-apigateway/lib/api-key.ts

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export interface IApiKey extends IResourceBase {
2020
*/
2121
export interface ApiKeyProps extends ResourceOptions {
2222
/**
23+
* [disable-awslint:ref-via-interface]
2324
* A list of resources this api key is associated with.
2425
* @default none
2526
*/

packages/@aws-cdk/aws-apigateway/lib/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export * from './stage';
77
export * from './integrations';
88
export * from './lambda-api';
99
export * from './api-key';
10+
export * from './rate-limited-api-key';
1011
export * from './usage-plan';
1112
export * from './vpc-link';
1213
export * from './methodresponse';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { Construct, Resource } from '@aws-cdk/core';
2+
import { ApiKey, ApiKeyProps, IApiKey } from './api-key';
3+
import { QuotaSettings, ThrottleSettings, UsagePlan, UsagePlanPerApiStage } from './usage-plan';
4+
5+
/**
6+
* RateLimitedApiKey properties.
7+
*/
8+
export interface RateLimitedApiKeyProps extends ApiKeyProps {
9+
/**
10+
* API Stages to be associated with the RateLimitedApiKey.
11+
* @default none
12+
*/
13+
readonly apiStages?: UsagePlanPerApiStage[];
14+
15+
/**
16+
* Number of requests clients can make in a given time period.
17+
* @default none
18+
*/
19+
readonly quota?: QuotaSettings;
20+
21+
/**
22+
* Overall throttle settings for the API.
23+
* @default none
24+
*/
25+
readonly throttle?: ThrottleSettings;
26+
}
27+
28+
/**
29+
* An API Gateway ApiKey, for which a rate limiting configuration can be specified.
30+
*
31+
* @resource AWS::ApiGateway::ApiKey
32+
*/
33+
export class RateLimitedApiKey extends Resource implements IApiKey {
34+
public readonly keyId: string;
35+
36+
constructor(scope: Construct, id: string, props: RateLimitedApiKeyProps = { }) {
37+
super(scope, id, {
38+
physicalName: props.apiKeyName,
39+
});
40+
41+
const resource = new ApiKey(this, 'Resource', props);
42+
43+
if (props.apiStages || props.quota || props.throttle) {
44+
new UsagePlan(this, 'UsagePlanResource', {
45+
apiKey: resource,
46+
apiStages: props.apiStages,
47+
quota: props.quota,
48+
throttle: props.throttle
49+
});
50+
}
51+
52+
this.keyId = resource.keyId;
53+
}
54+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import { expect, haveResource, ResourcePart } from '@aws-cdk/assert';
2+
import * as cdk from '@aws-cdk/core';
3+
import { Test } from "nodeunit";
4+
import * as apigateway from '../lib';
5+
6+
const API_KEY_RESOURCE_TYPE = 'AWS::ApiGateway::ApiKey';
7+
const USAGE_PLAN_RESOURCE_TYPE = 'AWS::ApiGateway::UsagePlan';
8+
const USAGE_PLAN_KEY_RESOURCE_TYPE = 'AWS::ApiGateway::UsagePlanKey';
9+
10+
export = {
11+
'default setup'(test: Test) {
12+
// GIVEN
13+
const stack = new cdk.Stack();
14+
const api = new apigateway.RestApi(stack, 'my-api', { cloudWatchRole: false, deploy: false });
15+
api.root.addMethod('GET'); // Need at least one method on the api
16+
17+
// WHEN
18+
new apigateway.RateLimitedApiKey(stack, 'my-api-key');
19+
20+
// THEN
21+
// should have an api key with no props defined.
22+
expect(stack).to(haveResource(API_KEY_RESOURCE_TYPE, undefined, ResourcePart.CompleteDefinition));
23+
// should not have a usage plan.
24+
expect(stack).notTo(haveResource(USAGE_PLAN_RESOURCE_TYPE));
25+
// should not have a usage plan key.
26+
expect(stack).notTo(haveResource(USAGE_PLAN_KEY_RESOURCE_TYPE));
27+
28+
test.done();
29+
},
30+
31+
'only api key is created when rate limiting properties are not provided'(test: Test) {
32+
// GIVEN
33+
const stack = new cdk.Stack();
34+
const api = new apigateway.RestApi(stack, 'test-api', { cloudWatchRole: false, deploy: true, deployOptions: { stageName: 'test' } });
35+
api.root.addMethod('GET'); // api must have atleast one method.
36+
37+
// WHEN
38+
new apigateway.RateLimitedApiKey(stack, 'test-api-key', {
39+
customerId: 'test-customer',
40+
resources: [api]
41+
});
42+
43+
// THEN
44+
expect(stack).to(haveResource('AWS::ApiGateway::ApiKey', {
45+
CustomerId: 'test-customer',
46+
StageKeys: [
47+
{
48+
RestApiId: { Ref: "testapiD6451F70" },
49+
StageName: { Ref: "testapiDeploymentStagetest5869DF71" }
50+
}
51+
]
52+
}));
53+
// should not have a usage plan.
54+
expect(stack).notTo(haveResource(USAGE_PLAN_RESOURCE_TYPE));
55+
// should not have a usage plan key.
56+
expect(stack).notTo(haveResource(USAGE_PLAN_KEY_RESOURCE_TYPE));
57+
58+
test.done();
59+
},
60+
61+
'api key and usage plan are created and linked when rate limiting properties are provided'(test: Test) {
62+
// GIVEN
63+
const stack = new cdk.Stack();
64+
const api = new apigateway.RestApi(stack, 'test-api', { cloudWatchRole: false, deploy: true, deployOptions: { stageName: 'test' } });
65+
api.root.addMethod('GET'); // api must have atleast one method.
66+
67+
// WHEN
68+
new apigateway.RateLimitedApiKey(stack, 'test-api-key', {
69+
customerId: 'test-customer',
70+
resources: [api],
71+
quota: {
72+
limit: 10000,
73+
period: apigateway.Period.MONTH
74+
}
75+
});
76+
77+
// THEN
78+
// should have an api key
79+
expect(stack).to(haveResource('AWS::ApiGateway::ApiKey', {
80+
CustomerId: 'test-customer',
81+
StageKeys: [
82+
{
83+
RestApiId: { Ref: "testapiD6451F70" },
84+
StageName: { Ref: "testapiDeploymentStagetest5869DF71" }
85+
}
86+
]
87+
}));
88+
// should have a usage plan with specified quota.
89+
expect(stack).to(haveResource(USAGE_PLAN_RESOURCE_TYPE, {
90+
Quota: {
91+
Limit: 10000,
92+
Period: 'MONTH'
93+
}
94+
}, ResourcePart.Properties));
95+
// should have a usage plan key linking the api key and usage plan
96+
expect(stack).to(haveResource(USAGE_PLAN_KEY_RESOURCE_TYPE, {
97+
KeyId: {
98+
Ref: 'testapikey998028B6'
99+
},
100+
KeyType: 'API_KEY',
101+
UsagePlanId: {
102+
Ref: 'testapikeyUsagePlanResource66DB63D6'
103+
}
104+
}, ResourcePart.Properties));
105+
106+
test.done();
107+
}
108+
};

0 commit comments

Comments
 (0)