Skip to content

Commit 0a67da4

Browse files
authored
Merge branch 'master' into otaviom/s3-orc
2 parents f15bbe2 + 7ac1215 commit 0a67da4

File tree

62 files changed

+1355
-405
lines changed

Some content is hidden

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

62 files changed

+1355
-405
lines changed

Diff for: CHANGELOG.md

+17
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,23 @@
22

33
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
44

5+
## [1.142.0](https://github.com/aws/aws-cdk/compare/v1.141.0...v1.142.0) (2022-01-28)
6+
7+
8+
### Features
9+
10+
* **cfnspec:** cloudformation spec v53.1.0 ([#18680](https://github.com/aws/aws-cdk/issues/18680)) ([f385059](https://github.com/aws/aws-cdk/commit/f38505911a3e140a9cb6b269bdf22abe9803c515))
11+
* **cloudfront-origins:** extend `readTimeout` maximum value for `HttpOriginProps` ([#18697](https://github.com/aws/aws-cdk/issues/18697)) ([e64de67](https://github.com/aws/aws-cdk/commit/e64de677cdfc014f68e92b204f4728e60a8bb111)), closes [#18628](https://github.com/aws/aws-cdk/issues/18628)
12+
* **eks:** cluster logging ([#18112](https://github.com/aws/aws-cdk/issues/18112)) ([872277b](https://github.com/aws/aws-cdk/commit/872277b9e853dbf5f2cac84b5afb6d26e0ed5659)), closes [#4159](https://github.com/aws/aws-cdk/issues/4159)
13+
* **iotevents:** allow setting description, evaluation method and key of DetectorModel ([#18644](https://github.com/aws/aws-cdk/issues/18644)) ([2eeaebc](https://github.com/aws/aws-cdk/commit/2eeaebc3cdc9c5c7ef3fa312b3d1abca265dcbb6))
14+
* **lambda-python:** support setting environment vars for bundling ([#18635](https://github.com/aws/aws-cdk/issues/18635)) ([30e2233](https://github.com/aws/aws-cdk/commit/30e223333fef0b0d7f12287dab170a34e092d7fa))
15+
16+
17+
### Bug Fixes
18+
19+
* **aws-lambda-nodejs:** pre compilation with tsc is not being run ([#18062](https://github.com/aws/aws-cdk/issues/18062)) ([7ac7221](https://github.com/aws/aws-cdk/commit/7ac7221aff3c612ab80e7812c371b11c56e5db0a)), closes [#18002](https://github.com/aws/aws-cdk/issues/18002)
20+
* **pipelines:** undeployable due to dependency cycle ([#18686](https://github.com/aws/aws-cdk/issues/18686)) ([009d689](https://github.com/aws/aws-cdk/commit/009d68912267de9dcf4136a7d80a652a891b7bb9)), closes [#18492](https://github.com/aws/aws-cdk/issues/18492) [#18673](https://github.com/aws/aws-cdk/issues/18673)
21+
522
## [1.141.0](https://github.com/aws/aws-cdk/compare/v1.140.0...v1.141.0) (2022-01-27)
623

724

Diff for: package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@
3232
},
3333
"resolutions": {
3434
"colors": "1.4.0",
35-
"string-width": "^4.2.3"
35+
"string-width": "^4.2.3",
36+
"markdown-it": "^12.3.2"
3637
},
3738
"repository": {
3839
"type": "git",

Diff for: packages/@aws-cdk/assertions/MIGRATING.md

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# Migrating to Assertions
2+
3+
Most of the APIs in the old `assert` module has a corresponding API in `assertions`.
4+
Make the following modifications to your CDK test files to migrate to the
5+
`@aws-cdk/assertions` module.
6+
7+
For a migration script that handles most common use cases for you, see
8+
[Migration Script](migration-script).
9+
10+
## Translation Guide
11+
12+
- Rewrite module imports that use `@aws-cdk/aws-assert` to `@aws-cdk/aws-assertions`.
13+
For example:
14+
15+
```ts
16+
import '@aws-cdk/assert/jest';
17+
import { ABSENT, SynthUtils, ResourcePart } from '@aws-cdk/assert';
18+
```
19+
20+
...becomes...
21+
22+
```ts
23+
import { Template } from '@aws-cdk/assertions';
24+
import { Match, Template } from '@aws-cdk/assertions';
25+
```
26+
27+
- Replace instances of `toHaveResource()` with `hasResourceProperties()` or `hasResource()`.
28+
For example:
29+
30+
```ts
31+
expect(stack).toHaveResource('FOO::BAR', {/*...*/});
32+
expect(stack).toHaveResource('FOO::BAR', {/*...*/}, ResourcePart.CompleteDefinition);
33+
```
34+
35+
...becomes...
36+
37+
```ts
38+
Template.fromStack(stack).hasResourceProperties('FOO::BAR', {/*...*/});
39+
Template.fromStack(stacK).hasResource('FOO::BAR', {/*...*/});
40+
```
41+
42+
- Replace instances of `toCountResources()` with `resourceCountIs`. For example:
43+
44+
```ts
45+
expect(stack).toCountResources('FOO::BAR', 1);
46+
```
47+
48+
...becomes...
49+
50+
```ts
51+
Template.fromStack(stack).resourceCountIs('FOO::BAR', 1);
52+
```
53+
- Replace instances of `toMatchTemplate()` with `templateMatches()`. For example:
54+
55+
```ts
56+
expect(stack).toMatchTemplate({/*...*/});
57+
```
58+
59+
...becomes...
60+
61+
```ts
62+
Template.fromStack(stack).templateMatches({/*...*/});
63+
```
64+
65+
- Replace `arrayWith()` with `Match.arrayWith()`, `objectLike()` with `Match.objectLike()`, and
66+
`ABSENT` with `Match.absent()`.
67+
68+
- `not` can be replaced with `Match.not()` _or_ `resourceCountIs()` depending on the use case.
69+
70+
```ts
71+
// asserting that the stack does not have a particular resource.
72+
expect(stack).not.toHaveResource('FOO::BAR');
73+
```
74+
75+
...becomes...
76+
77+
```ts
78+
Template.fromStack(stack).resourceCountIs('FOO::BAR', 0);
79+
```
80+
81+
```ts
82+
// asserting that the stack does not have a resource with these properties
83+
expect(stack).not.toHaveResource('FOO::BAR', {
84+
prop: 'does not exist',
85+
});
86+
```
87+
88+
...becomes...
89+
90+
```ts
91+
Template.fromStack(stack).hasResourceProperties('FOO::BAR', Match.not({
92+
prop: 'does not exist',
93+
}));
94+
```
95+
96+
- `SynthUtils.synthesize(stack)` can be replaced as well. For example:
97+
98+
```ts
99+
expect(SynthUtils.synthesize(stack).template).toEqual(/*...*/);
100+
SynthUtils.syntesize(stack);
101+
```
102+
103+
...becomes...
104+
105+
```ts
106+
expect(Template.fromStack(stack).toJSON()).toEqual(/*...*/);
107+
App.of(stack).synth();
108+
```
109+
110+
## Migration Script
111+
112+
> NOTE: We have some code rewrite rules that will make it easier to migrate from one library
113+
> to the other. This tool will not do a complete rewrite and is not guaranteed to produce
114+
> compilable code! It will just save you the effort of performing a lot of code substitutions
115+
> you would otherwise have to do by hand.
116+
117+
Comby is a tool used to do structured code rewriting. You can install it
118+
[here](https://comby.dev/). Download the [rewrite.toml](rewrite.toml) file from our GitHub
119+
repository, and run the following command in the root directory of your project:
120+
121+
```bash
122+
comby -config ~/rewrite.toml -f .ts -d test -in-place -timeout 10
123+
```

Diff for: packages/@aws-cdk/assertions/README.md

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99

1010
<!--END STABILITY BANNER-->
1111

12+
If you're migrating from the old `assert` library, the migration guide can be found in
13+
[our GitHub repository](https://github.com/aws/aws-cdk/blob/master/packages/@aws-cdk/assertions/MIGRATING.md).
14+
1215
Functions for writing test asserting against CDK applications, with focus on CloudFormation templates.
1316

1417
The `Template` class includes a set of methods for writing assertions against CloudFormation templates. Use one of the `Template.fromXxx()` static methods to create an instance of this class.

Diff for: packages/@aws-cdk/assertions/lib/private/conditions.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { filterLogicalId, formatFailure, matchSection } from './section';
22
import { Template } from './template';
33

44
export function findConditions(template: Template, logicalId: string, props: any = {}): { [key: string]: { [key: string]: any } } {
5-
const section: { [key: string] : {} } = template.Conditions;
5+
const section: { [key: string] : {} } = template.Conditions ?? {};
66
const result = matchSection(filterLogicalId(section, logicalId), props);
77

88
if (!result.match) {
@@ -13,7 +13,7 @@ export function findConditions(template: Template, logicalId: string, props: any
1313
}
1414

1515
export function hasCondition(template: Template, logicalId: string, props: any): string | void {
16-
const section: { [key: string] : {} } = template.Conditions;
16+
const section: { [key: string] : {} } = template.Conditions ?? {};
1717
const result = matchSection(filterLogicalId(section, logicalId), props);
1818
if (result.match) {
1919
return;

Diff for: packages/@aws-cdk/assertions/lib/private/cyclic.ts

+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
import { Resource, Template } from './template';
2+
3+
/**
4+
* Check a template for cyclic dependencies
5+
*
6+
* This will make sure that we don't happily validate templates
7+
* in unit tests that wouldn't deploy to CloudFormation anyway.
8+
*/
9+
export function checkTemplateForCyclicDependencies(template: Template): void {
10+
const logicalIds = new Set(Object.keys(template.Resources ?? {}));
11+
12+
const dependencies = new Map<string, Set<string>>();
13+
for (const [logicalId, resource] of Object.entries(template.Resources ?? {})) {
14+
dependencies.set(logicalId, intersect(findResourceDependencies(resource), logicalIds));
15+
}
16+
17+
// We will now progressively remove entries from the map of 'dependencies' that have
18+
// 0 elements in them. If we can't do that anymore and the map isn't empty, we
19+
// have a cyclic dependency.
20+
while (dependencies.size > 0) {
21+
const free = Array.from(dependencies.entries()).filter(([_, deps]) => deps.size === 0);
22+
if (free.length === 0) {
23+
// Oops!
24+
const cycle = findCycle(dependencies);
25+
26+
const cycleResources: any = {};
27+
for (const logicalId of cycle) {
28+
cycleResources[logicalId] = template.Resources?.[logicalId];
29+
}
30+
31+
throw new Error(`Template is undeployable, these resources have a dependency cycle: ${cycle.join(' -> ')}:\n\n${JSON.stringify(cycleResources, undefined, 2)}`);
32+
}
33+
34+
for (const [logicalId, _] of free) {
35+
for (const deps of dependencies.values()) {
36+
deps.delete(logicalId);
37+
}
38+
dependencies.delete(logicalId);
39+
}
40+
}
41+
}
42+
43+
function findResourceDependencies(res: Resource): Set<string> {
44+
return new Set([
45+
...toArray(res.DependsOn ?? []),
46+
...findExpressionDependencies(res.Properties),
47+
]);
48+
}
49+
50+
function toArray<A>(x: A | A[]): A[] {
51+
return Array.isArray(x) ? x : [x];
52+
}
53+
54+
function findExpressionDependencies(obj: any): Set<string> {
55+
const ret = new Set<string>();
56+
recurse(obj);
57+
return ret;
58+
59+
function recurse(x: any): void {
60+
if (!x) { return; }
61+
if (Array.isArray(x)) {
62+
x.forEach(recurse);
63+
}
64+
if (typeof x === 'object') {
65+
const keys = Object.keys(x);
66+
if (keys.length === 1 && keys[0] === 'Ref') {
67+
ret.add(x[keys[0]]);
68+
} else if (keys.length === 1 && keys[0] === 'Fn::GetAtt') {
69+
ret.add(x[keys[0]][0]);
70+
} else if (keys.length === 1 && keys[0] === 'Fn::Sub') {
71+
const argument = x[keys[0]];
72+
const pattern = Array.isArray(argument) ? argument[0] : argument;
73+
for (const logId of logicalIdsInSubString(pattern)) {
74+
ret.add(logId);
75+
}
76+
const contextDict = Array.isArray(argument) ? argument[1] : undefined;
77+
if (contextDict) {
78+
Object.values(contextDict).forEach(recurse);
79+
}
80+
} else {
81+
Object.values(x).forEach(recurse);
82+
}
83+
}
84+
}
85+
}
86+
87+
/**
88+
* Return the logical IDs found in a {Fn::Sub} format string
89+
*/
90+
function logicalIdsInSubString(x: string): string[] {
91+
return analyzeSubPattern(x).flatMap((fragment) => {
92+
switch (fragment.type) {
93+
case 'getatt':
94+
case 'ref':
95+
return [fragment.logicalId];
96+
case 'literal':
97+
return [];
98+
}
99+
});
100+
}
101+
102+
103+
function analyzeSubPattern(pattern: string): SubFragment[] {
104+
const ret: SubFragment[] = [];
105+
let start = 0;
106+
107+
let ph0 = pattern.indexOf('${', start);
108+
while (ph0 > -1) {
109+
if (pattern[ph0 + 2] === '!') {
110+
// "${!" means "don't actually substitute"
111+
start = ph0 + 3;
112+
ph0 = pattern.indexOf('${', start);
113+
continue;
114+
}
115+
116+
const ph1 = pattern.indexOf('}', ph0 + 2);
117+
if (ph1 === -1) {
118+
break;
119+
}
120+
const placeholder = pattern.substring(ph0 + 2, ph1);
121+
122+
if (ph0 > start) {
123+
ret.push({ type: 'literal', content: pattern.substring(start, ph0) });
124+
}
125+
if (placeholder.includes('.')) {
126+
const [logicalId, attr] = placeholder.split('.');
127+
ret.push({ type: 'getatt', logicalId: logicalId!, attr: attr! });
128+
} else {
129+
ret.push({ type: 'ref', logicalId: placeholder });
130+
}
131+
132+
start = ph1 + 1;
133+
ph0 = pattern.indexOf('${', start);
134+
}
135+
136+
if (start < pattern.length - 1) {
137+
ret.push({ type: 'literal', content: pattern.substr(start) });
138+
}
139+
140+
return ret;
141+
}
142+
143+
type SubFragment =
144+
| { readonly type: 'literal'; readonly content: string }
145+
| { readonly type: 'ref'; readonly logicalId: string }
146+
| { readonly type: 'getatt'; readonly logicalId: string; readonly attr: string };
147+
148+
149+
function intersect<A>(xs: Set<A>, ys: Set<A>): Set<A> {
150+
return new Set<A>(Array.from(xs).filter(x => ys.has(x)));
151+
}
152+
153+
/**
154+
* Find cycles in a graph
155+
*
156+
* Not the fastest, but effective and should be rare
157+
*/
158+
function findCycle(deps: ReadonlyMap<string, ReadonlySet<string>>): string[] {
159+
for (const node of deps.keys()) {
160+
const cycle = recurse(node, [node]);
161+
if (cycle) { return cycle; }
162+
}
163+
throw new Error('No cycle found. Assertion failure!');
164+
165+
function recurse(node: string, path: string[]): string[] | undefined {
166+
for (const dep of deps.get(node) ?? []) {
167+
if (dep === path[0]) { return [...path, dep]; }
168+
169+
const cycle = recurse(dep, [...path, dep]);
170+
if (cycle) { return cycle; }
171+
}
172+
173+
return undefined;
174+
}
175+
}

Diff for: packages/@aws-cdk/assertions/lib/private/mappings.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { filterLogicalId, formatFailure, matchSection } from './section';
22
import { Template } from './template';
33

44
export function findMappings(template: Template, logicalId: string, props: any = {}): { [key: string]: { [key: string]: any } } {
5-
const section: { [key: string] : {} } = template.Mappings;
5+
const section: { [key: string] : {} } = template.Mappings ?? {};
66
const result = matchSection(filterLogicalId(section, logicalId), props);
77

88
if (!result.match) {
@@ -13,7 +13,7 @@ export function findMappings(template: Template, logicalId: string, props: any =
1313
}
1414

1515
export function hasMapping(template: Template, logicalId: string, props: any): string | void {
16-
const section: { [key: string]: {} } = template.Mappings;
16+
const section: { [key: string]: {} } = template.Mappings ?? {};
1717
const result = matchSection(filterLogicalId(section, logicalId), props);
1818

1919
if (result.match) {

Diff for: packages/@aws-cdk/assertions/lib/private/outputs.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { filterLogicalId, formatFailure, matchSection } from './section';
22
import { Template } from './template';
33

44
export function findOutputs(template: Template, logicalId: string, props: any = {}): { [key: string]: { [key: string]: any } } {
5-
const section = template.Outputs;
5+
const section = template.Outputs ?? {};
66
const result = matchSection(filterLogicalId(section, logicalId), props);
77

88
if (!result.match) {
@@ -13,7 +13,7 @@ export function findOutputs(template: Template, logicalId: string, props: any =
1313
}
1414

1515
export function hasOutput(template: Template, logicalId: string, props: any): string | void {
16-
const section: { [key: string]: {} } = template.Outputs;
16+
const section: { [key: string]: {} } = template.Outputs ?? {};
1717
const result = matchSection(filterLogicalId(section, logicalId), props);
1818
if (result.match) {
1919
return;

0 commit comments

Comments
 (0)