Skip to content

Commit d40fff4

Browse files
authored
Merge branch 'master' into global-accelerator-sg
2 parents 5e1176c + 41940d3 commit d40fff4

12 files changed

+202
-19
lines changed

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

+14
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ The following widgets are available:
230230
- `AlarmWidget` -- shows the graph and alarm line for a single alarm.
231231
- `SingleValueWidget` -- shows the current value of a set of metrics.
232232
- `TextWidget` -- shows some static Markdown.
233+
- `AlarmStatusWidget` -- shows the status of your alarms in a grid view.
233234

234235
### Graph widget
235236

@@ -319,6 +320,19 @@ dashboard.addWidgets(new TextWidget({
319320
}));
320321
```
321322

323+
### Alarm Status widget
324+
325+
An alarm status widget displays instantly the status of any type of alarms and gives the
326+
ability to aggregate one or more alarms together in a small surface.
327+
328+
```ts
329+
dashboard.addWidgets(
330+
new AlarmStatusWidget({
331+
alarms: [errorAlarm],
332+
})
333+
);
334+
```
335+
322336
### Query results widget
323337

324338
A `LogQueryWidget` shows the results of a query from Logs Insights:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { IAlarm } from './alarm-base';
2+
import { ConcreteWidget } from './widget';
3+
4+
/**
5+
* Properties for an Alarm Status Widget
6+
*/
7+
export interface AlarmStatusWidgetProps {
8+
/**
9+
* CloudWatch Alarms to show in widget
10+
*/
11+
readonly alarms: IAlarm[];
12+
/**
13+
* The title of the widget
14+
*
15+
* @default 'Alarm Status'
16+
*/
17+
readonly title?: string;
18+
/**
19+
* Width of the widget, in a grid of 24 units wide
20+
*
21+
* @default 6
22+
*/
23+
readonly width?: number;
24+
/**
25+
* Height of the widget
26+
*
27+
* @default 3
28+
*/
29+
readonly height?: number;
30+
}
31+
32+
/**
33+
* A dashboard widget that displays alarms in a grid view
34+
*/
35+
export class AlarmStatusWidget extends ConcreteWidget {
36+
private readonly props: AlarmStatusWidgetProps;
37+
38+
constructor(props: AlarmStatusWidgetProps) {
39+
super(props.width || 6, props.height || 3);
40+
this.props = props;
41+
}
42+
43+
public position(x: number, y: number): void {
44+
this.x = x;
45+
this.y = y;
46+
}
47+
48+
public toJson(): any[] {
49+
return [
50+
{
51+
type: 'alarm',
52+
width: this.width,
53+
height: this.height,
54+
x: this.x,
55+
y: this.y,
56+
properties: {
57+
title: this.props.title ? this.props.title : 'Alarm Status',
58+
alarms: this.props.alarms.map((alarm) => alarm.alarmArn),
59+
},
60+
},
61+
];
62+
}
63+
}

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

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export * from './metric-types';
1111
export * from './log-query';
1212
export * from './text';
1313
export * from './widget';
14+
export * from './alarm-status-widget';
1415

1516
// AWS::CloudWatch CloudFormation Resources:
1617
export * from './cloudwatch.generated';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { Stack } from '@aws-cdk/core';
2+
import { Test } from 'nodeunit';
3+
import { Metric, Alarm, AlarmStatusWidget } from '../lib';
4+
export = {
5+
'alarm status widget'(test: Test) {
6+
// GIVEN
7+
const stack = new Stack();
8+
const metric = new Metric({ namespace: 'CDK', metricName: 'Test' });
9+
const alarm = new Alarm(stack, 'Alarm', {
10+
metric,
11+
threshold: 1,
12+
evaluationPeriods: 1,
13+
});
14+
15+
// WHEN
16+
const widget = new AlarmStatusWidget({
17+
alarms: [alarm],
18+
});
19+
20+
// THEN
21+
test.deepEqual(stack.resolve(widget.toJson()), [
22+
{
23+
type: 'alarm',
24+
width: 6,
25+
height: 3,
26+
properties: {
27+
title: 'Alarm Status',
28+
alarms: [{ 'Fn::GetAtt': ['Alarm7103F465', 'Arn'] }],
29+
},
30+
},
31+
]);
32+
33+
test.done();
34+
},
35+
};
+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import * as cxschema from '@aws-cdk/cloud-assembly-schema';
2+
import { IConstruct } from './construct-compat';
3+
4+
/**
5+
* Includes API for attaching annotations such as warning messages to constructs.
6+
*/
7+
export class Annotations {
8+
/**
9+
* Returns the annotations API for a construct scope.
10+
* @param scope The scope
11+
*/
12+
public static of(scope: IConstruct) {
13+
return new Annotations(scope);
14+
}
15+
16+
private constructor(private readonly scope: IConstruct) {
17+
18+
}
19+
20+
/**
21+
* Adds a warning metadata entry to this construct.
22+
*
23+
* The CLI will display the warning when an app is synthesized, or fail if run
24+
* in --strict mode.
25+
*
26+
* @param message The warning message.
27+
*/
28+
public addWarning(message: string) {
29+
this.addMessage(cxschema.ArtifactMetadataEntryType.WARN, message);
30+
}
31+
32+
/**
33+
* Adds an info metadata entry to this construct.
34+
*
35+
* The CLI will display the info message when apps are synthesized.
36+
*
37+
* @param message The info message.
38+
*/
39+
public addInfo(message: string): void {
40+
this.addMessage(cxschema.ArtifactMetadataEntryType.INFO, message);
41+
}
42+
43+
/**
44+
* Adds an { "error": <message> } metadata entry to this construct.
45+
* The toolkit will fail synthesis when errors are reported.
46+
* @param message The error message.
47+
*/
48+
public addError(message: string) {
49+
this.addMessage(cxschema.ArtifactMetadataEntryType.ERROR, message);
50+
}
51+
52+
/**
53+
* Adds a message metadata entry to the construct node, to be displayed by the CDK CLI.
54+
* @param level The message level
55+
* @param message The message itself
56+
*/
57+
private addMessage(level: string, message: string) {
58+
this.scope.node.addMetadata(level, message);
59+
}
60+
}

packages/@aws-cdk/core/lib/construct-compat.ts

+10-7
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
* This file, in its entirety, is expected to be removed in v2.0.
1111
*/
1212

13-
import * as cxschema from '@aws-cdk/cloud-assembly-schema';
1413
import * as cxapi from '@aws-cdk/cx-api';
1514
import * as constructs from 'constructs';
15+
import { Annotations } from './annotations';
1616
import { IAspect, Aspects } from './aspect';
1717
import { IDependable } from './dependency';
1818
import { Token } from './token';
@@ -426,31 +426,34 @@ export class ConstructNode {
426426
public addMetadata(type: string, data: any, fromFunction?: any): void { this._actualNode.addMetadata(type, data, fromFunction); }
427427

428428
/**
429-
* Adds a { "info": <message> } metadata entry to this construct.
429+
* DEPRECATED: Adds a { "info": <message> } metadata entry to this construct.
430430
* The toolkit will display the info message when apps are synthesized.
431431
* @param message The info message.
432+
* @deprecated use `Annotations.of(construct).addInfo()`
432433
*/
433434
public addInfo(message: string): void {
434-
this._actualNode.addMetadata(cxschema.ArtifactMetadataEntryType.INFO, message);
435+
Annotations.of(this.host).addInfo(message);
435436
}
436437

437438
/**
438-
* Adds a { "warning": <message> } metadata entry to this construct.
439+
* DEPRECATED: Adds a { "warning": <message> } metadata entry to this construct.
439440
* The toolkit will display the warning when an app is synthesized, or fail
440441
* if run in --strict mode.
441442
* @param message The warning message.
443+
* @deprecated use `Annotations.of(construct).addWarning()`
442444
*/
443445
public addWarning(message: string): void {
444-
this._actualNode.addMetadata(cxschema.ArtifactMetadataEntryType.WARN, message);
446+
Annotations.of(this.host).addWarning(message);
445447
}
446448

447449
/**
448-
* Adds an { "error": <message> } metadata entry to this construct.
450+
* DEPRECATED: Adds an { "error": <message> } metadata entry to this construct.
449451
* The toolkit will fail synthesis when errors are reported.
450452
* @param message The error message.
453+
* @deprecated use `Annotations.of(construct).addError()`
451454
*/
452455
public addError(message: string) {
453-
this._actualNode.addMetadata(cxschema.ArtifactMetadataEntryType.ERROR, message);
456+
Annotations.of(this.host).addError(message);
454457
}
455458

456459
/**

packages/@aws-cdk/core/lib/context-provider.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as cxschema from '@aws-cdk/cloud-assembly-schema';
22
import * as cxapi from '@aws-cdk/cx-api';
3+
import { Annotations } from './annotations';
34
import { Construct } from './construct-compat';
45
import { Stack } from './stack';
56
import { Token } from './token';
@@ -107,8 +108,9 @@ export class ContextProvider {
107108
});
108109

109110
if (providerError !== undefined) {
110-
scope.construct.addError(providerError);
111+
Annotations.of(scope).addError(providerError);
111112
}
113+
112114
return { value: options.dummyValue };
113115
}
114116

packages/@aws-cdk/core/lib/private/synthesis.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as cxapi from '@aws-cdk/cx-api';
22
import * as constructs from 'constructs';
3+
import { Annotations } from '../annotations';
34
import { Aspects, IAspect } from '../aspect';
45
import { Construct, IConstruct, SynthesisOptions, ValidationError } from '../construct-compat';
56
import { Stack } from '../stack';
@@ -84,7 +85,7 @@ function invokeAspects(root: IConstruct) {
8485
// if an aspect was added to the node while invoking another aspect it will not be invoked, emit a warning
8586
// the `nestedAspectWarning` flag is used to prevent the warning from being emitted for every child
8687
if (!nestedAspectWarning && nodeAspectsCount !== aspects.aspects.length) {
87-
construct.construct.addWarning('We detected an Aspect was added via another Aspect, and will not be applied');
88+
Annotations.of(construct).addWarning('We detected an Aspect was added via another Aspect, and will not be applied');
8889
nestedAspectWarning = true;
8990
}
9091

packages/@aws-cdk/core/lib/private/tree-metadata.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as fs from 'fs';
22
import * as path from 'path';
33

44
import { ArtifactType } from '@aws-cdk/cloud-assembly-schema';
5+
import { Annotations } from '../annotations';
56
import { Construct, IConstruct, ISynthesisSession } from '../construct-compat';
67
import { Stack } from '../stack';
78
import { IInspectable, TreeInspector } from '../tree';
@@ -32,7 +33,7 @@ export class TreeMetadata extends Construct {
3233
try {
3334
return visit(c);
3435
} catch (e) {
35-
this.construct.addWarning(`Failed to render tree metadata for node [${c.construct.id}]. Reason: ${e}`);
36+
Annotations.of(this).addWarning(`Failed to render tree metadata for node [${c.node.id}]. Reason: ${e}`);
3637
return undefined;
3738
}
3839
});

packages/@aws-cdk/core/lib/stack.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import * as fs from 'fs';
22
import * as path from 'path';
33
import * as cxschema from '@aws-cdk/cloud-assembly-schema';
44
import * as cxapi from '@aws-cdk/cx-api';
5+
import { Annotations } from './annotations';
6+
import { App } from './app';
57
import { Arn, ArnComponents } from './arn';
68
import { DockerImageAssetLocation, DockerImageAssetSource, FileAssetLocation, FileAssetSource } from './assets';
79
import { CfnElement } from './cfn-element';
@@ -201,7 +203,7 @@ export class Stack extends Construct implements ITaggable {
201203
* value is an unresolved token (`Token.isUnresolved(stack.region)` returns
202204
* `true`), this implies that the user wishes that this stack will synthesize
203205
* into a **region-agnostic template**. In this case, your code should either
204-
* fail (throw an error, emit a synth error using `node.addError`) or
206+
* fail (throw an error, emit a synth error using `Annotations.of(construct).addError()`) or
205207
* implement some other region-agnostic behavior.
206208
*/
207209
public readonly region: string;
@@ -223,7 +225,7 @@ export class Stack extends Construct implements ITaggable {
223225
* value is an unresolved token (`Token.isUnresolved(stack.account)` returns
224226
* `true`), this implies that the user wishes that this stack will synthesize
225227
* into a **account-agnostic template**. In this case, your code should either
226-
* fail (throw an error, emit a synth error using `node.addError`) or
228+
* fail (throw an error, emit a synth error using `Annotations.of(construct).addError()`) or
227229
* implement some other region-agnostic behavior.
228230
*/
229231
public readonly account: string;
@@ -800,7 +802,7 @@ export class Stack extends Construct implements ITaggable {
800802

801803
if (this.templateOptions.transform) {
802804
// eslint-disable-next-line max-len
803-
this.construct.addWarning('This stack is using the deprecated `templateOptions.transform` property. Consider switching to `addTransform()`.');
805+
Annotations.of(this).addWarning('This stack is using the deprecated `templateOptions.transform` property. Consider switching to `addTransform()`.');
804806
this.addTransform(this.templateOptions.transform);
805807
}
806808

@@ -1094,7 +1096,6 @@ import { Stage } from './stage';
10941096
import { ITaggable, TagManager } from './tag-manager';
10951097
import { Token } from './token';
10961098
import { FileSystem } from './fs';
1097-
import { App } from './app';
10981099

10991100
interface StackDependency {
11001101
stack: Stack;

packages/@aws-cdk/core/test/test.app.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { ContextProvider } from '@aws-cdk/cloud-assembly-schema';
22
import * as cxapi from '@aws-cdk/cx-api';
33
import { Test } from 'nodeunit';
44
import { CfnResource, Construct, Stack, StackProps } from '../lib';
5+
import { Annotations } from '../lib/annotations';
56
import { App, AppProps } from '../lib/app';
67

78
function withApp(props: AppProps, block: (app: App) => void): cxapi.CloudAssembly {
@@ -28,8 +29,8 @@ function synth(context?: { [key: string]: any }): cxapi.CloudAssembly {
2829

2930
// add some metadata
3031
stack1.construct.addMetadata('meta', 111);
31-
r2.construct.addWarning('warning1');
32-
r2.construct.addWarning('warning2');
32+
Annotations.of(r2).addWarning('warning1');
33+
Annotations.of(r2).addWarning('warning2');
3334
c1.construct.addMetadata('meta', { key: 'value' });
3435
app.construct.addMetadata('applevel', 123); // apps can also have metadata
3536
});

packages/@aws-cdk/core/test/test.construct.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as cxschema from '@aws-cdk/cloud-assembly-schema';
22
import { Test } from 'nodeunit';
33
import { App as Root, Aws, Construct, ConstructNode, ConstructOrder, IConstruct, Lazy, ValidationError } from '../lib';
4+
import { Annotations } from '../lib/annotations';
45
import { reEnableStackTraceCollection, restoreStackTraceColection } from './util';
56

67
/* eslint-disable @typescript-eslint/naming-convention */
@@ -288,7 +289,7 @@ export = {
288289
const previousValue = reEnableStackTraceCollection();
289290
const root = new Root();
290291
const con = new Construct(root, 'MyConstruct');
291-
con.construct.addWarning('This construct is deprecated, use the other one instead');
292+
Annotations.of(con).addWarning('This construct is deprecated, use the other one instead');
292293
restoreStackTraceColection(previousValue);
293294

294295
test.deepEqual(con.construct.metadata[0].type, cxschema.ArtifactMetadataEntryType.WARN);
@@ -301,7 +302,7 @@ export = {
301302
const previousValue = reEnableStackTraceCollection();
302303
const root = new Root();
303304
const con = new Construct(root, 'MyConstruct');
304-
con.construct.addError('Stop!');
305+
Annotations.of(con).addError('Stop!');
305306
restoreStackTraceColection(previousValue);
306307

307308
test.deepEqual(con.construct.metadata[0].type, cxschema.ArtifactMetadataEntryType.ERROR);
@@ -314,7 +315,7 @@ export = {
314315
const previousValue = reEnableStackTraceCollection();
315316
const root = new Root();
316317
const con = new Construct(root, 'MyConstruct');
317-
con.construct.addInfo('Hey there, how do you do?');
318+
Annotations.of(con).addInfo('Hey there, how do you do?');
318319
restoreStackTraceColection(previousValue);
319320

320321
test.deepEqual(con.construct.metadata[0].type, cxschema.ArtifactMetadataEntryType.INFO);

0 commit comments

Comments
 (0)