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

feat(core): new annotations api #9563

Merged
merged 7 commits into from
Aug 10, 2020
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions packages/@aws-cdk/core/lib/annotations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import * as cxschema from '@aws-cdk/cloud-assembly-schema';
import { IConstruct } from './construct-compat';

/**
* Includes API for attaching annotations such as warning messages to constructs.
*/
export class Annotations {
/**
* Returns the annotations API for a construct scope.
* @param scope The scope
*/
public static of(scope: IConstruct) {
return new Annotations(scope);
}

private constructor(private readonly scope: IConstruct) {

}

/**
* Adds a warning metadata entry to this construct.
*
* The CLI will display the warning when an app is synthesized, or fail if run
* in --strict mode.
*
* @param message The warning message.
*/
public addWarning(message: string) {
this.addMessage(cxschema.ArtifactMetadataEntryType.WARN, message);
}

/**
* Adds an info metadata entry to this construct.
*
* The CLI will display the info message when apps are synthesized.
*
* @param message The info message.
*/
public addInfo(message: string): void {
this.addMessage(cxschema.ArtifactMetadataEntryType.INFO, message);
}

/**
* Adds an { "error": <message> } metadata entry to this construct.
* The toolkit will fail synthesis when errors are reported.
* @param message The error message.
*/
public addError(message: string) {
this.addMessage(cxschema.ArtifactMetadataEntryType.ERROR, message);
}

/**
* Adds a message metadata entry to the construct node, to be displayed by the CDK CLI.
* @param level The message level
* @param message The message itself
*/
private addMessage(level: string, message: string) {
this.scope.node.addMetadata(level, message);
}
}
17 changes: 10 additions & 7 deletions packages/@aws-cdk/core/lib/construct-compat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
* This file, in its entirety, is expected to be removed in v2.0.
*/

import * as cxschema from '@aws-cdk/cloud-assembly-schema';
import * as cxapi from '@aws-cdk/cx-api';
import * as constructs from 'constructs';
import { Annotations } from './annotations';
import { IAspect, Aspects } from './aspect';
import { IDependable } from './dependency';
import { Token } from './token';
Expand Down Expand Up @@ -411,31 +411,34 @@ export class ConstructNode {
public addMetadata(type: string, data: any, fromFunction?: any): void { this._actualNode.addMetadata(type, data, fromFunction); }

/**
* Adds a { "info": <message> } metadata entry to this construct.
* DEPRECATED: Adds a { "info": <message> } metadata entry to this construct.
* The toolkit will display the info message when apps are synthesized.
* @param message The info message.
* @deprecated use `Annotations.of(construct).addInfo()`
*/
public addInfo(message: string): void {
this._actualNode.addMetadata(cxschema.ArtifactMetadataEntryType.INFO, message);
Annotations.of(this.host).addInfo(message);
}

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

/**
* Adds an { "error": <message> } metadata entry to this construct.
* DEPRECATED: Adds an { "error": <message> } metadata entry to this construct.
* The toolkit will fail synthesis when errors are reported.
* @param message The error message.
* @deprecated use `Annotations.of(construct).addError()`
*/
public addError(message: string) {
this._actualNode.addMetadata(cxschema.ArtifactMetadataEntryType.ERROR, message);
Annotations.of(this.host).addError(message);
}

/**
Expand Down
3 changes: 2 additions & 1 deletion packages/@aws-cdk/core/lib/context-provider.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as cxschema from '@aws-cdk/cloud-assembly-schema';
import * as cxapi from '@aws-cdk/cx-api';
import { Annotations } from './annotations';
import { Construct } from './construct-compat';
import { Stack } from './stack';
import { Token } from './token';
Expand Down Expand Up @@ -107,7 +108,7 @@ export class ContextProvider {
});

if (providerError !== undefined) {
scope.node.addError(providerError);
Annotations.of(scope).addError(providerError);
}
return { value: options.dummyValue };
}
Expand Down
3 changes: 2 additions & 1 deletion packages/@aws-cdk/core/lib/private/synthesis.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as cxapi from '@aws-cdk/cx-api';
import * as constructs from 'constructs';
import { Annotations } from '../annotations';
import { Aspects, IAspect } from '../aspect';
import { Construct, IConstruct, SynthesisOptions, ValidationError } from '../construct-compat';
import { Stack } from '../stack';
Expand Down Expand Up @@ -84,7 +85,7 @@ function invokeAspects(root: IConstruct) {
// if an aspect was added to the node while invoking another aspect it will not be invoked, emit a warning
// the `nestedAspectWarning` flag is used to prevent the warning from being emitted for every child
if (!nestedAspectWarning && nodeAspectsCount !== aspects.aspects.length) {
construct.node.addWarning('We detected an Aspect was added via another Aspect, and will not be applied');
Annotations.of(construct).addWarning('We detected an Aspect was added via another Aspect, and will not be applied');
nestedAspectWarning = true;
}

Expand Down
3 changes: 2 additions & 1 deletion packages/@aws-cdk/core/lib/private/tree-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as fs from 'fs';
import * as path from 'path';

import { ArtifactType } from '@aws-cdk/cloud-assembly-schema';
import { Annotations } from '../annotations';
import { Construct, IConstruct, ISynthesisSession } from '../construct-compat';
import { Stack } from '../stack';
import { IInspectable, TreeInspector } from '../tree';
Expand Down Expand Up @@ -32,7 +33,7 @@ export class TreeMetadata extends Construct {
try {
return visit(c);
} catch (e) {
this.node.addWarning(`Failed to render tree metadata for node [${c.node.id}]. Reason: ${e}`);
Annotations.of(this).addWarning(`Failed to render tree metadata for node [${c.node.id}]. Reason: ${e}`);
return undefined;
}
});
Expand Down
9 changes: 5 additions & 4 deletions packages/@aws-cdk/core/lib/stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import * as fs from 'fs';
import * as path from 'path';
import * as cxschema from '@aws-cdk/cloud-assembly-schema';
import * as cxapi from '@aws-cdk/cx-api';
import { Annotations } from './annotations';
import { App } from './app';
import { Arn, ArnComponents } from './arn';
import { DockerImageAssetLocation, DockerImageAssetSource, FileAssetLocation, FileAssetSource } from './assets';
import { CfnElement } from './cfn-element';
Expand Down Expand Up @@ -201,7 +203,7 @@ export class Stack extends Construct implements ITaggable {
* value is an unresolved token (`Token.isUnresolved(stack.region)` returns
* `true`), this implies that the user wishes that this stack will synthesize
* into a **region-agnostic template**. In this case, your code should either
* fail (throw an error, emit a synth error using `node.addError`) or
* fail (throw an error, emit a synth error using `Annotations.of(construct).addError()`) or
* implement some other region-agnostic behavior.
*/
public readonly region: string;
Expand All @@ -223,7 +225,7 @@ export class Stack extends Construct implements ITaggable {
* value is an unresolved token (`Token.isUnresolved(stack.account)` returns
* `true`), this implies that the user wishes that this stack will synthesize
* into a **account-agnostic template**. In this case, your code should either
* fail (throw an error, emit a synth error using `node.addError`) or
* fail (throw an error, emit a synth error using `Annotations.of(construct).addError()`) or
* implement some other region-agnostic behavior.
*/
public readonly account: string;
Expand Down Expand Up @@ -800,7 +802,7 @@ export class Stack extends Construct implements ITaggable {

if (this.templateOptions.transform) {
// eslint-disable-next-line max-len
this.node.addWarning('This stack is using the deprecated `templateOptions.transform` property. Consider switching to `addTransform()`.');
Annotations.of(this).addWarning('This stack is using the deprecated `templateOptions.transform` property. Consider switching to `addTransform()`.');
this.addTransform(this.templateOptions.transform);
}

Expand Down Expand Up @@ -1094,7 +1096,6 @@ import { Stage } from './stage';
import { ITaggable, TagManager } from './tag-manager';
import { Token } from './token';
import { FileSystem } from './fs';
import { App } from './app';

interface StackDependency {
stack: Stack;
Expand Down
5 changes: 3 additions & 2 deletions packages/@aws-cdk/core/test/test.app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ContextProvider } from '@aws-cdk/cloud-assembly-schema';
import * as cxapi from '@aws-cdk/cx-api';
import { Test } from 'nodeunit';
import { CfnResource, Construct, Stack, StackProps } from '../lib';
import { Annotations } from '../lib/annotations';
import { App, AppProps } from '../lib/app';

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

// add some metadata
stack1.node.addMetadata('meta', 111);
r2.node.addWarning('warning1');
r2.node.addWarning('warning2');
Annotations.of(r2).addWarning('warning1');
Annotations.of(r2).addWarning('warning2');
c1.node.addMetadata('meta', { key: 'value' });
app.node.addMetadata('applevel', 123); // apps can also have metadata
});
Expand Down
7 changes: 4 additions & 3 deletions packages/@aws-cdk/core/test/test.construct.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as cxschema from '@aws-cdk/cloud-assembly-schema';
import { Test } from 'nodeunit';
import { App as Root, Aws, Construct, ConstructNode, ConstructOrder, IConstruct, Lazy, ValidationError } from '../lib';
import { Annotations } from '../lib/annotations';
import { reEnableStackTraceCollection, restoreStackTraceColection } from './util';

/* eslint-disable @typescript-eslint/naming-convention */
Expand Down Expand Up @@ -288,7 +289,7 @@ export = {
const previousValue = reEnableStackTraceCollection();
const root = new Root();
const con = new Construct(root, 'MyConstruct');
con.node.addWarning('This construct is deprecated, use the other one instead');
Annotations.of(con).addWarning('This construct is deprecated, use the other one instead');
restoreStackTraceColection(previousValue);

test.deepEqual(con.node.metadata[0].type, cxschema.ArtifactMetadataEntryType.WARN);
Expand All @@ -301,7 +302,7 @@ export = {
const previousValue = reEnableStackTraceCollection();
const root = new Root();
const con = new Construct(root, 'MyConstruct');
con.node.addError('Stop!');
Annotations.of(con).addError('Stop!');
restoreStackTraceColection(previousValue);

test.deepEqual(con.node.metadata[0].type, cxschema.ArtifactMetadataEntryType.ERROR);
Expand All @@ -314,7 +315,7 @@ export = {
const previousValue = reEnableStackTraceCollection();
const root = new Root();
const con = new Construct(root, 'MyConstruct');
con.node.addInfo('Hey there, how do you do?');
Annotations.of(con).addInfo('Hey there, how do you do?');
restoreStackTraceColection(previousValue);

test.deepEqual(con.node.metadata[0].type, cxschema.ArtifactMetadataEntryType.INFO);
Expand Down