Skip to content

Commit 70d4ecf

Browse files
authored
Merge branch 'master' into njlynch/ubergenreadme
2 parents 35cba00 + fdd157d commit 70d4ecf

36 files changed

Lines changed: 997 additions & 148 deletions

CONTRIBUTING.md

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,13 @@ $ yarn watch & # runs in the background
319319

320320
## Breaking Changes
321321

322-
_NOTE: Breaking changes will not be allowed in the upcoming v2 release. These instructions apply to v1._
322+
**_NOTE_**: _Starting with version 2.0.0 of the AWS CDK, **all modules and members vended as part of the main CDK library**_
323+
_**(`aws-cdk-lib`) will always be stable**; we are committing to never introduce breaking changes in a non-major bump._
324+
_Breaking changes are only allowed on pre-released (experimental or dev preview) modules_
325+
_(those with a `stability` of `experimental` in their respective `package.json` files)._
326+
_For v1, each module is separately released. For v2, only `stable` modules are released as part of the_
327+
_main `aws-cdk-lib` release, and all `experimental` modules are released independently as `-alpha` versions,_
328+
_and not included in the main CDK library._
323329

324330
Whenever you are making changes, there is a chance for those changes to be
325331
*breaking* existing users of the library. A change is breaking if there are
@@ -455,6 +461,47 @@ If the new behavior is going to be breaking, the user must opt in to it, either
455461
Of these two, the first one is preferred if possible (as feature flags have
456462
non-local effects which can cause unintended effects).
457463

464+
### Adding new experimental ("preview") APIs
465+
466+
To make sure we can keep adding features fast, while keeping our commitment to
467+
not release breaking changes, we are introducing a new model - API Previews.
468+
APIs that we want to get in front of developers early, and are not yet
469+
finalized, will be added to the AWS CDK with a specific suffix: `BetaX`. APIs
470+
with the preview suffix will never be removed, instead they will be deprecated
471+
and replaced by either the stable version (without the suffix), or by a newer
472+
preview version. For example, assume we add the method
473+
`grantAwesomePowerBeta1`:
474+
475+
```ts
476+
/**
477+
* This methods grants awesome powers
478+
*/
479+
grantAwesomePowerBeta1();
480+
```
481+
482+
Times goes by, we get feedback that this method will actually be much better
483+
if it accept a `Principal`. Since adding a required property is a breaking
484+
change, we will add `grantAwesomePowerBeta2()` and deprecate
485+
`grantAwesomePowerBeta1`:
486+
487+
```ts
488+
/**
489+
* This methods grants awesome powers to the given principal
490+
*
491+
* @param grantee The principal to grant powers to
492+
*/
493+
grantAwesomePowerBeta2(grantee: iam.IGrantable)
494+
495+
/**
496+
* This methods grants awesome powers
497+
* @deprecated use grantAwesomePowerBeta2
498+
*/
499+
grantAwesomePowerBeta1()
500+
```
501+
502+
When we decide its time to graduate the API, the latest preview version will
503+
be deprecated and the final version - `grantAwesomePower` will be added.
504+
458505
## Documentation
459506

460507
Every module's README is rendered as the landing page of the official documentation. For example, this is

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

Lines changed: 81 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,20 @@ The `Template` class includes a set of methods for writing assertions against Cl
2121

2222
To create `Template` from CDK stack, start off with:
2323

24-
```ts
24+
```ts nofixture
2525
import { Stack } from '@aws-cdk/core';
2626
import { Template } from '@aws-cdk/assertions';
2727

28-
const stack = new Stack(...)
29-
...
30-
const assert = Template.fromStack(stack);
28+
const stack = new Stack(/* ... */);
29+
// ...
30+
const template = Template.fromStack(stack);
3131
```
3232

3333
Alternatively, assertions can be run on an existing CloudFormation template -
3434

35-
```ts
36-
const template = fs.readFileSync('/path/to/template/file');
37-
const assert = Template.fromString(template);
35+
```ts fixture=init
36+
const templateJson = '{ "Resources": ... }'; /* The CloudFormation template as JSON serialized string. */
37+
const template = Template.fromString(templateJson);
3838
```
3939

4040
## Full Template Match
@@ -43,34 +43,40 @@ The simplest assertion would be to assert that the template matches a given
4343
template.
4444

4545
```ts
46-
assert.templateMatches({
46+
const expected = {
4747
Resources: {
4848
Type: 'Foo::Bar',
4949
Properties: {
5050
Baz: 'Qux',
5151
},
5252
},
53-
});
53+
};
54+
55+
template.templateMatches(expected);
5456
```
5557

56-
The `Template` class also supports [snapshot
57-
testing](https://jestjs.io/docs/snapshot-testing) using jest.
58+
By default, the `templateMatches()` API will use the an 'object-like' comparison,
59+
which means that it will allow for the actual template to be a superset of the
60+
given expectation. See [Special Matchers](#special-matchers) for details on how
61+
to change this.
5862

59-
```ts
60-
// using jest
61-
expect(Template.fromStack(stack)).toMatchSnapshot();
62-
```
63+
Snapshot testing is a common technique to store a snapshot of the output and
64+
compare it during future changes. Since CloudFormation templates are human readable,
65+
they are a good target for åßsnapshot testing.
66+
67+
The `toJSON()` method on the `Template` can be used to produce a well formatted JSON
68+
of the CloudFormation template that can be used as a snapshot.
6369

64-
For non-javascript languages, the `toJSON()` can be called to get an in-memory object
65-
of the template.
70+
See [Snapshot Testing in Jest](https://jestjs.io/docs/snapshot-testing) and [Snapshot
71+
Testing in Java](https://json-snapshot.github.io/).
6672

6773
## Counting Resources
6874

6975
This module allows asserting the number of resources of a specific type found
7076
in a template.
7177

7278
```ts
73-
assert.resourceCountIs('Foo::Bar', 2);
79+
template.resourceCountIs('Foo::Bar', 2);
7480
```
7581

7682
## Resource Matching & Retrieval
@@ -82,21 +88,23 @@ The following code asserts that the `Properties` section of a resource of type
8288
`Foo::Bar` contains the specified properties -
8389

8490
```ts
85-
assert.hasResourceProperties('Foo::Bar', {
91+
const expected = {
8692
Foo: 'Bar',
8793
Baz: 5,
8894
Qux: [ 'Waldo', 'Fred' ],
89-
});
95+
};
96+
template.hasResourceProperties('Foo::Bar', expected);
9097
```
9198

9299
Alternatively, if you would like to assert the entire resource definition, you
93100
can use the `hasResource()` API.
94101

95102
```ts
96-
assert.hasResource('Foo::Bar', {
103+
const expected = {
97104
Properties: { Foo: 'Bar' },
98105
DependsOn: [ 'Waldo', 'Fred' ],
99-
});
106+
};
107+
template.hasResource('Foo::Bar', expected);
100108
```
101109

102110
Beyond assertions, the module provides APIs to retrieve matching resources.
@@ -114,28 +122,31 @@ that matches specific properties. The following code asserts that a template con
114122
an Output with a `logicalId` of `Foo` and the specified properties -
115123

116124
```ts
117-
assert.hasOutput('Foo', {
125+
const expected = {
118126
Value: 'Bar',
119127
Export: { Name: 'ExportBaz' },
120-
});
128+
};
129+
template.hasOutput('Foo', expected);
121130
```
122131

123132
If you want to match against all Outputs in the template, use `*` as the `logicalId`.
124133

125134
```ts
126-
assert.hasOutput('*', {
135+
const expected = {
127136
Value: 'Bar',
128137
Export: { Name: 'ExportBaz' },
129-
});
138+
};
139+
template.hasOutput('*', expected);
130140
```
131141

132142
`findOutputs()` will return a set of outputs that match the `logicalId` and `props`,
133143
and you can use the `'*'` special case as well.
134144

135145
```ts
136-
const result = assert.findOutputs('*', {
146+
const expected = {
137147
Value: 'Fred',
138-
});
148+
};
149+
const result = template.findOutputs('*', expected);
139150
expect(result.Foo).toEqual({ Value: 'Fred', Description: 'FooFred' });
140151
expect(result.Bar).toEqual({ Value: 'Fred', Description: 'BarFred' });
141152
```
@@ -175,18 +186,20 @@ level, the list of keys in the target is a subset of the provided pattern.
175186
// }
176187

177188
// The following will NOT throw an assertion error
178-
assert.hasResourceProperties('Foo::Bar', {
189+
const expected = {
179190
Fred: Match.objectLike({
180191
Wobble: 'Flob',
181192
}),
182-
});
193+
};
194+
template.hasResourceProperties('Foo::Bar', expected);
183195

184196
// The following will throw an assertion error
185-
assert.hasResourceProperties('Foo::Bar', {
197+
const unexpected = {
186198
Fred: Match.objectLike({
187199
Brew: 'Coffee',
188-
})
189-
});
200+
}),
201+
}
202+
template.hasResourceProperties('Foo::Bar', unexpected);
190203
```
191204

192205
The `Match.objectEquals()` API can be used to assert a target as a deep exact
@@ -214,18 +227,20 @@ or outside of any matchers.
214227
// }
215228

216229
// The following will NOT throw an assertion error
217-
assert.hasResourceProperties('Foo::Bar', {
230+
const expected = {
218231
Fred: Match.objectLike({
219232
Bob: Match.absent(),
220233
}),
221-
});
234+
};
235+
template.hasResourceProperties('Foo::Bar', expected);
222236

223237
// The following will throw an assertion error
224-
assert.hasResourceProperties('Foo::Bar', {
238+
const unexpected = {
225239
Fred: Match.objectLike({
226240
Wobble: Match.absent(),
227241
}),
228-
});
242+
};
243+
template.hasResourceProperties('Foo::Bar', unexpected);
229244
```
230245

231246
The `Match.anyValue()` matcher can be used to specify that a specific value should be found
@@ -250,18 +265,20 @@ This matcher can be combined with any of the other matchers.
250265
// }
251266

252267
// The following will NOT throw an assertion error
253-
assert.hasResourceProperties('Foo::Bar', {
268+
const expected = {
254269
Fred: {
255270
Wobble: [Match.anyValue(), "Flip"],
256271
},
257-
});
272+
};
273+
template.hasResourceProperties('Foo::Bar', expected);
258274

259275
// The following will throw an assertion error
260-
assert.hasResourceProperties('Foo::Bar', {
276+
const unexpected = {
261277
Fred: {
262278
Wimble: Match.anyValue(),
263279
},
264-
});
280+
};
281+
template.hasResourceProperties('Foo::Bar', unexpected);
265282
```
266283

267284
### Array Matchers
@@ -284,14 +301,16 @@ This API will perform subset match on the target.
284301
// }
285302

286303
// The following will NOT throw an assertion error
287-
assert.hasResourceProperties('Foo::Bar', {
304+
const expected = {
288305
Fred: Match.arrayWith(['Flob']),
289-
});
306+
};
307+
template.hasResourceProperties('Foo::Bar', expected);
290308

291309
// The following will throw an assertion error
292-
assert.hasResourceProperties('Foo::Bar', Match.objectLike({
293-
Fred: Match.arrayWith(['Wobble']);
294-
}});
310+
const unexpected = Match.objectLike({
311+
Fred: Match.arrayWith(['Wobble']),
312+
});
313+
template.hasResourceProperties('Foo::Bar', unexpected);
295314
```
296315

297316
*Note:* The list of items in the pattern array should be in order as they appear in the
@@ -319,14 +338,16 @@ not match the pattern specified.
319338
// }
320339

321340
// The following will NOT throw an assertion error
322-
assert.hasResourceProperties('Foo::Bar', {
341+
const expected = {
323342
Fred: Match.not(['Flob']),
324-
});
343+
};
344+
template.hasResourceProperties('Foo::Bar', expected);
325345

326346
// The following will throw an assertion error
327-
assert.hasResourceProperties('Foo::Bar', Match.objectLike({
328-
Fred: Match.not(['Flob', 'Cat']);
329-
}});
347+
const unexpected = Match.objectLike({
348+
Fred: Match.not(['Flob', 'Cat']),
349+
});
350+
template.hasResourceProperties('Foo::Bar', unexpected);
330351
```
331352

332353
### Serialized JSON
@@ -353,18 +374,20 @@ The `Match.serializedJson()` matcher allows deep matching within a stringified J
353374
// }
354375

355376
// The following will NOT throw an assertion error
356-
assert.hasResourceProperties('Foo::Bar', {
377+
const expected = {
357378
Baz: Match.serializedJson({
358379
Fred: Match.arrayWith(["Waldo"]),
359380
}),
360-
});
381+
};
382+
template.hasResourceProperties('Foo::Bar', expected);
361383

362384
// The following will throw an assertion error
363-
assert.hasResourceProperties('Foo::Bar', {
385+
const unexpected = {
364386
Baz: Match.serializedJson({
365387
Fred: ["Waldo", "Johnny"],
366388
}),
367-
});
389+
};
390+
template.hasResourceProperties('Foo::Bar', unexpected);
368391
```
369392

370393
[Pipeline BuildSpec]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codebuild-project-source.html#cfn-codebuild-project-source-buildspec
@@ -392,37 +415,12 @@ matching resource.
392415

393416
const fredCapture = new Capture();
394417
const waldoCapture = new Capture();
395-
assert.hasResourceProperties('Foo::Bar', {
418+
const expected = {
396419
Fred: fredCapture,
397420
Waldo: ["Qix", waldoCapture],
398-
});
421+
}
422+
template.hasResourceProperties('Foo::Bar', expected);
399423

400424
fredCapture.asArray(); // returns ["Flob", "Cat"]
401425
waldoCapture.asString(); // returns "Qux"
402426
```
403-
404-
## Strongly typed languages
405-
406-
Some of the APIs documented above, such as `templateMatches()` and
407-
`hasResourceProperties()` accept fluently an arbitrary JSON (like) structure
408-
its parameter.
409-
This fluency is available only in dynamically typed languages like javascript
410-
and Python.
411-
412-
For strongly typed languages, like Java, you can achieve similar fluency using
413-
any popular JSON deserializer. The following Java example uses `Gson` -
414-
415-
```java
416-
// In Java, using text blocks and Gson
417-
import com.google.gson.Gson;
418-
419-
String json = """
420-
{
421-
"Foo": "Bar",
422-
"Baz": 5,
423-
"Qux": [ "Waldo", "Fred" ],
424-
} """;
425-
426-
Map expected = new Gson().fromJson(json, Map.class);
427-
assert.hasResourceProperties("Foo::Bar", expected);
428-
```

0 commit comments

Comments
 (0)