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

refactor(cli): stack monitor uses io-host #150

Merged
merged 1 commit into from
Feb 27, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions packages/@aws-cdk/toolkit-lib/CODE_REGISTRY.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@
| CDK_TOOLKIT_I5031 | Informs about any log groups that are traced as part of the deployment | info | n/a |
| CDK_TOOLKIT_I5050 | Confirm rollback during deployment | info | n/a |
| CDK_TOOLKIT_I5060 | Confirm deploy security sensitive changes | info | n/a |
| CDK_TOOLKIT_I5501 | Stack Monitoring: Start monitoring of a single stack | info | [StackMonitoringControlEvent](https://docs.aws.amazon.com/cdk/api/toolkit-lib/interfaces/StackMonitoringControlEvent.html) |
| CDK_TOOLKIT_I5502 | Stack Monitoring: Activity event for a single stack | info | [StackActivity](https://docs.aws.amazon.com/cdk/api/toolkit-lib/interfaces/StackActivity.html) |
| CDK_TOOLKIT_I5503 | Stack Monitoring: Finished monitoring of a single stack | info | [StackMonitoringControlEvent](https://docs.aws.amazon.com/cdk/api/toolkit-lib/interfaces/StackMonitoringControlEvent.html) |
| CDK_TOOLKIT_I5900 | Deployment results on success | result | [SuccessfulDeployStackResult](https://docs.aws.amazon.com/cdk/api/toolkit-lib/interfaces/SuccessfulDeployStackResult.html) |
| CDK_TOOLKIT_E5001 | No stacks found | error | n/a |
| CDK_TOOLKIT_E5500 | Stack Monitoring error | error | [ErrorPayload](https://docs.aws.amazon.com/cdk/api/toolkit-lib/interfaces/ErrorPayload.html) |
| CDK_TOOLKIT_I6000 | Provides rollback times | info | n/a |
| CDK_TOOLKIT_E6001 | No stacks found | error | n/a |
| CDK_TOOLKIT_E6900 | Rollback failed | error | n/a |
Expand Down
8 changes: 4 additions & 4 deletions packages/@aws-cdk/toolkit-lib/lib/actions/deploy/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { BaseDeployOptions } from './private/deploy-options';
import type { StackActivityProgress, Tag } from '../../api/aws-cdk';
import type { Tag } from '../../api/aws-cdk';

export type DeploymentMethod = DirectDeploymentMethod | ChangeSetDeploymentMethod;

Expand Down Expand Up @@ -164,16 +164,16 @@ export interface DeployOptions extends BaseDeployOptions {
/**
* Change stack watcher output to CI mode.
*
* @deprecated Implement in IoHost instead
* @deprecated has no functionality, please implement in your IoHost
*/
readonly ci?: boolean;

/**
* Display mode for stack deployment progress.
*
* @deprecated Implement in IoHost instead
* @deprecated has no functionality, please implement in your IoHost
*/
readonly progress?: StackActivityProgress;
readonly progress?: any;

/**
* Represents configuration property overrides for hotswap deployments.
Expand Down
1 change: 0 additions & 1 deletion packages/@aws-cdk/toolkit-lib/lib/api/aws-cdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export { Settings } from '../../../../aws-cdk/lib/api/settings';
export { tagsForStack, Tag } from '../../../../aws-cdk/lib/api/tags';
export { DEFAULT_TOOLKIT_STACK_NAME } from '../../../../aws-cdk/lib/api/toolkit-info';
export { ResourceMigrator } from '../../../../aws-cdk/lib/api/resource-import';
export { StackActivityProgress } from '../../../../aws-cdk/lib/api/stack-events';
export { CloudWatchLogEventMonitor, findCloudWatchLogGroups } from '../../../../aws-cdk/lib/api/logs';
export { type WorkGraph, WorkGraphBuilder, AssetBuildNode, AssetPublishNode, StackNode, Concurrency } from '../../../../aws-cdk/lib/api/work-graph';

Expand Down
26 changes: 26 additions & 0 deletions packages/@aws-cdk/toolkit-lib/lib/api/io/private/codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,26 @@ export const CODES = {
description: 'Confirm deploy security sensitive changes',
level: 'info',
}),

CDK_TOOLKIT_I5501: codeInfo({
code: 'CDK_TOOLKIT_I5501',
description: 'Stack Monitoring: Start monitoring of a single stack',
level: 'info',
interface: 'StackMonitoringControlEvent',
}),
CDK_TOOLKIT_I5502: codeInfo({
code: 'CDK_TOOLKIT_I5502',
description: 'Stack Monitoring: Activity event for a single stack',
level: 'info',
interface: 'StackActivity',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have our own copy of this type? I'm not comfortable exposing other people's types as part of our API.

Also if we make our own copy of the type, we'll have the ability to add fields if we feel that's convenient, and we can simplify and omit fields that aren't necessary for our current implementation.

Copy link
Contributor Author

@mrgrain mrgrain Feb 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is our own copy of StackActivity.

However its event property is typed as @aws-sdk/client-cloudformation.StackEvent. I'm inclined to pass this on as is, since the CFN API is well defined und unlikely to change badly or even at all.

}),
CDK_TOOLKIT_I5503: codeInfo({
code: 'CDK_TOOLKIT_I5503',
description: 'Stack Monitoring: Finished monitoring of a single stack',
level: 'info',
interface: 'StackMonitoringControlEvent',
}),

CDK_TOOLKIT_I5900: codeInfo({
code: 'CDK_TOOLKIT_I5900',
description: 'Deployment results on success',
Expand All @@ -121,6 +141,12 @@ export const CODES = {
description: 'No stacks found',
level: 'error',
}),
CDK_TOOLKIT_E5500: codeInfo({
code: 'CDK_TOOLKIT_E5500',
description: 'Stack Monitoring error',
level: 'error',
interface: 'ErrorPayload',
}),

// 6: Rollback
CDK_TOOLKIT_I6000: codeInfo({
Expand Down
8 changes: 1 addition & 7 deletions packages/@aws-cdk/toolkit-lib/lib/toolkit/toolkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { type SynthOptions } from '../actions/synth';
import { WatchOptions } from '../actions/watch';
import { patternsArrayForWatch } from '../actions/watch/private';
import { type SdkConfig } from '../api/aws-auth';
import { DEFAULT_TOOLKIT_STACK_NAME, SdkProvider, SuccessfulDeployStackResult, StackCollection, Deployments, HotswapMode, StackActivityProgress, ResourceMigrator, obscureTemplate, serializeStructure, tagsForStack, CliIoHost, validateSnsTopicArn, Concurrency, WorkGraphBuilder, AssetBuildNode, AssetPublishNode, StackNode, formatErrorMessage, CloudWatchLogEventMonitor, findCloudWatchLogGroups, formatTime, StackDetails } from '../api/aws-cdk';
import { DEFAULT_TOOLKIT_STACK_NAME, SdkProvider, SuccessfulDeployStackResult, StackCollection, Deployments, HotswapMode, ResourceMigrator, obscureTemplate, serializeStructure, tagsForStack, CliIoHost, validateSnsTopicArn, Concurrency, WorkGraphBuilder, AssetBuildNode, AssetPublishNode, StackNode, formatErrorMessage, CloudWatchLogEventMonitor, findCloudWatchLogGroups, formatTime, StackDetails } from '../api/aws-cdk';
import { ICloudAssemblySource, StackSelectionStrategy } from '../api/cloud-assembly';
import { ALL_STACKS, CachedCloudAssemblySource, CloudAssemblySourceBuilder, IdentityCloudAssemblySource, StackAssembly } from '../api/cloud-assembly/private';
import { ToolkitError } from '../api/errors';
Expand Down Expand Up @@ -375,8 +375,6 @@ export class Toolkit extends CloudAssemblySourceBuilder implements AsyncDisposab
force: options.force,
parameters: Object.assign({}, parameterMap['*'], parameterMap[stack.stackName]),
usePreviousParameters: options.parameters?.keepExistingParameters,
progress,
ci: options.ci,
rollback,
hotswap: hotswapMode,
extraUserAgent: options.extraUserAgent,
Expand Down Expand Up @@ -494,10 +492,6 @@ export class Toolkit extends CloudAssemblySourceBuilder implements AsyncDisposab
const assetBuildTime = options.assetBuildTime ?? AssetBuildTime.ALL_BEFORE_DEPLOY;
const prebuildAssets = assetBuildTime === AssetBuildTime.ALL_BEFORE_DEPLOY;
const concurrency = options.concurrency || 1;
const progress = concurrency > 1 ? StackActivityProgress.EVENTS : options.progress;
if (concurrency > 1 && options.progress && options.progress != StackActivityProgress.EVENTS) {
await ioHost.notify(warn('⚠️ The --concurrency flag only supports --progress "events". Switching to "events".'));
}

const stacksAndTheirAssetManifests = stacks.flatMap((stack) => [
stack,
Expand Down
10 changes: 10 additions & 0 deletions packages/@aws-cdk/toolkit-lib/lib/toolkit/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,13 @@ export interface Duration {
*/
readonly duration: number;
}

/**
* Generic payload of error IoMessages that pass on an instance of `Error`
*/
export interface ErrorPayload {
/**
* The error that occurred
*/
readonly error: Error;
}
61 changes: 22 additions & 39 deletions packages/aws-cdk/lib/api/deployments/deploy-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import type { SDK, SdkProvider, ICloudFormationClient } from '../aws-auth';
import type { EnvironmentResources } from '../environment';
import { CfnEvaluationException } from '../evaluate-cloudformation-template';
import { HotswapMode, HotswapPropertyOverrides, ICON } from '../hotswap/common';
import { StackActivityMonitor, type StackActivityProgress } from '../stack-events';
import { StackActivityMonitor } from '../stack-events';
import { StringWithoutPlaceholders } from '../util/placeholders';
import { type TemplateBodyParameter, makeBodyParameter } from '../util/template-body-parameter';

Expand Down Expand Up @@ -105,13 +105,6 @@ export interface DeployStackOptions {
*/
readonly deployName?: string;

/**
* Quiet or verbose deployment
*
* @default false
*/
readonly quiet?: boolean;

/**
* List of asset IDs which shouldn't be built
*
Expand Down Expand Up @@ -153,27 +146,12 @@ export interface DeployStackOptions {
*/
readonly usePreviousParameters?: boolean;

/**
* Display mode for stack deployment progress.
*
* @default StackActivityProgress.Bar stack events will be displayed for
* the resource currently being deployed.
*/
readonly progress?: StackActivityProgress;

/**
* Deploy even if the deployed template is identical to the one we are about to deploy.
* @default false
*/
readonly force?: boolean;

/**
* Whether we are on a CI system
*
* @default false
*/
readonly ci?: boolean;

/**
* Rollback failed deployments
*
Expand Down Expand Up @@ -612,14 +590,16 @@ class FullCloudFormationDeployment {
}

private async monitorDeployment(startTime: Date, expectedChanges: number | undefined): Promise<SuccessfulDeployStackResult> {
const monitor = this.options.quiet
? undefined
: StackActivityMonitor.withDefaultPrinter(this.cfn, this.stackName, this.stackArtifact, {
resourcesTotal: expectedChanges,
progress: this.options.progress,
changeSetCreationTime: startTime,
ci: this.options.ci,
}).start();
const monitor = new StackActivityMonitor({
cfn: this.cfn,
stack: this.stackArtifact,
stackName: this.stackName,
resourcesTotal: expectedChanges,
ioHost: this.ioHost,
action: this.action,
changeSetCreationTime: startTime,
});
await monitor.start();

let finalState = this.cloudFormationStack;
try {
Expand All @@ -631,9 +611,9 @@ class FullCloudFormationDeployment {
}
finalState = successStack;
} catch (e: any) {
throw new ToolkitError(suffixWithErrors(formatErrorMessage(e), monitor?.errors));
throw new ToolkitError(suffixWithErrors(formatErrorMessage(e), monitor.errors));
} finally {
await monitor?.stop();
await monitor.stop();
}
debug(this.action, format('Stack %s has completed updating', this.stackName));
return {
Expand Down Expand Up @@ -696,11 +676,14 @@ export async function destroyStack(options: DestroyStackOptions, { ioHost, actio
if (!currentStack.exists) {
return;
}
const monitor = options.quiet
? undefined
: StackActivityMonitor.withDefaultPrinter(cfn, deployName, options.stack, {
ci: options.ci,
}).start();
const monitor = new StackActivityMonitor({
cfn,
stack: options.stack,
stackName: deployName,
ioHost,
action,
});
await monitor.start();

try {
await cfn.deleteStack({ StackName: deployName, RoleARN: options.roleArn });
Expand All @@ -709,7 +692,7 @@ export async function destroyStack(options: DestroyStackOptions, { ioHost, actio
throw new ToolkitError(`Failed to destroy ${deployName}: ${destroyedStack.stackStatus}`);
}
} catch (e: any) {
throw new ToolkitError(suffixWithErrors(formatErrorMessage(e), monitor?.errors));
throw new ToolkitError(suffixWithErrors(formatErrorMessage(e), monitor.errors));
} finally {
if (monitor) {
await monitor.stop();
Expand Down
54 changes: 12 additions & 42 deletions packages/aws-cdk/lib/api/deployments/deployments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { formatErrorMessage } from '../../util/format-error';
import type { SdkProvider } from '../aws-auth/sdk-provider';
import { type EnvironmentResources, EnvironmentAccess } from '../environment';
import { HotswapMode, HotswapPropertyOverrides } from '../hotswap/common';
import { StackActivityMonitor, StackActivityProgress, StackEventPoller, RollbackChoice } from '../stack-events';
import { StackActivityMonitor, StackEventPoller, RollbackChoice } from '../stack-events';
import type { Tag } from '../tags';
import { DEFAULT_TOOLKIT_STACK_NAME } from '../toolkit-info';
import { makeBodyParameter } from '../util/template-body-parameter';
Expand Down Expand Up @@ -65,13 +65,6 @@ export interface DeployStackOptions {
*/
readonly deployName?: string;

/**
* Don't show stack deployment events, just wait
*
* @default false
*/
readonly quiet?: boolean;

/**
* Name of the toolkit stack, if not the default name
*
Expand Down Expand Up @@ -135,21 +128,6 @@ export interface DeployStackOptions {
*/
readonly usePreviousParameters?: boolean;

/**
* Display mode for stack deployment progress.
*
* @default - StackActivityProgress.Bar - stack events will be displayed for
* the resource currently being deployed.
*/
readonly progress?: StackActivityProgress;

/**
* Whether we are on a CI system
*
* @default false
*/
readonly ci?: boolean;

/**
* Rollback failed deployments
*
Expand Down Expand Up @@ -255,14 +233,6 @@ export interface RollbackStackOptions {
*/
readonly orphanLogicalIds?: string[];

/**
* Display mode for stack deployment progress.
*
* @default - StackActivityProgress.Bar - stack events will be displayed for
* the resource currently being deployed.
*/
readonly progress?: StackActivityProgress;

/**
* Whether to validate the version of the bootstrap stack permissions
*
Expand Down Expand Up @@ -463,7 +433,6 @@ export class Deployments {
resolvedEnvironment: env.resolvedEnvironment,
deployName: options.deployName,
notificationArns: options.notificationArns,
quiet: options.quiet,
sdk: env.sdk,
sdkProvider: this.deployStackSdkProvider,
roleArn: executionRoleArn,
Expand All @@ -474,8 +443,6 @@ export class Deployments {
force: options.force,
parameters: options.parameters,
usePreviousParameters: options.usePreviousParameters,
progress: options.progress,
ci: options.ci,
rollback: options.rollback,
hotswap: options.hotswap,
hotswapPropertyOverrides: options.hotswapPropertyOverrides,
Expand Down Expand Up @@ -565,11 +532,14 @@ export class Deployments {
throw new ToolkitError(`Unexpected rollback choice: ${cloudFormationStack.stackStatus.rollbackChoice}`);
}

const monitor = options.quiet
? undefined
: StackActivityMonitor.withDefaultPrinter(cfn, deployName, options.stack, {
ci: options.ci,
}).start();
const monitor = new StackActivityMonitor({
cfn,
stack: options.stack,
stackName: deployName,
ioHost: this.ioHost,
action: this.action,
});
await monitor.start();

let stackErrorMessage: string | undefined = undefined;
let finalStackState = cloudFormationStack;
Expand All @@ -582,14 +552,14 @@ export class Deployments {
}
finalStackState = successStack;

const errors = monitor?.errors?.join(', ');
const errors = monitor.errors.join(', ');
if (errors) {
stackErrorMessage = errors;
}
} catch (e: any) {
stackErrorMessage = suffixWithErrors(formatErrorMessage(e), monitor?.errors);
stackErrorMessage = suffixWithErrors(formatErrorMessage(e), monitor.errors);
} finally {
await monitor?.stop();
await monitor.stop();
}

if (finalStackState.stackStatus.isRollbackSuccess || !stackErrorMessage) {
Expand Down
9 changes: 0 additions & 9 deletions packages/aws-cdk/lib/api/resource-import/importer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { error, info, warn } from '../../cli/messages';
import { IIoHost, ToolkitAction } from '../../toolkit/cli-io-host';
import { ToolkitError } from '../../toolkit/error';
import { assertIsSuccessfulDeployStackResult, type Deployments, DeploymentMethod, ResourceIdentifierProperties, ResourcesToImport } from '../deployments';
import type { StackActivityProgress } from '../stack-events';
import type { Tag } from '../tags';

export interface ResourceImporterProps {
Expand Down Expand Up @@ -49,14 +48,6 @@ export interface ImportDeploymentOptions {
*/
readonly usePreviousParameters?: boolean;

/**
* Display mode for stack deployment progress.
*
* @default - StackActivityProgress.Bar - stack events will be displayed for
* the resource currently being deployed.
*/
readonly progress?: StackActivityProgress;

/**
* Rollback failed deployments
*
Expand Down
1 change: 0 additions & 1 deletion packages/aws-cdk/lib/api/resource-import/migrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ export class ResourceMigrator {
roleArn: options.roleArn,
deploymentMethod: options.deploymentMethod,
usePreviousParameters: true,
progress: options.progress,
rollback: options.rollback,
});

Expand Down
Loading