Skip to content

Commit ef135ef

Browse files
HBobertzkaizenccmrgrain
authored
chore(cli): use CliIoHost as logger everywhere (#32708)
### Related to #32346 ### Reason for this change Capture all logs across the CLI as IoMessages so that when we allow customers to use the CDK Core functionality programmatically, these logs are delivered to the customers as messages and now just swallowed across the CLI. ### Description of changes Prevented access to `log()` and `formatLogMessage()`. Now the only ways to log something properly are either through the exported log functions (which is how everyone was doing it anyway), or through `CliIoHost.notify()` directly. CliIoHost is now exposed as a global singleton which is currently only directly exclusively used in `logging.ts` but is effectively used everywhere as all logging functions inevitably call `CliIoHost.notify()` All logging functions now optionally support the following input types ```ts error(`operation failed: ${e}`) // infers default error code `TOOLKIT_0000` error('operation failed: %s', e) // infers default error code `TOOLKIT_0000` error({ message: 'operation failed', code: 'SDK_0001' }) // specifies error code `SDK_0001` error({ message: 'operation failed: %s', code: 'SDK_0001' }, e) // specifies error code `SDK_0001` ``` and everything is now translated into an `IoMessage` and calls `CliIoHost.notify()` from these logging functions. Nothing currently specifies any message code so it's all the generic _0000, _1000, _2000 ### Description of how you validated changes added and updated unit tests ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --------- Co-authored-by: Kaizen Conroy <[email protected]> Co-authored-by: Momo Kornher <[email protected]>
1 parent fb2b229 commit ef135ef

36 files changed

+983
-795
lines changed

packages/aws-cdk/lib/api/aws-auth/credential-plugins.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { inspect } from 'util';
1+
import { inspect, format } from 'util';
22
import type { CredentialProviderSource, ForReading, ForWriting, PluginProviderResult, SDKv2CompatibleCredentials, SDKv3CompatibleCredentialProvider, SDKv3CompatibleCredentials } from '@aws-cdk/cli-plugin-contract';
33
import type { AwsCredentialIdentity, AwsCredentialIdentityProvider } from '@smithy/types';
44
import { credentialsAboutToExpire, makeCachingProvider } from './provider-caching';
5-
import { debug, warning } from '../../logging';
5+
import { debug, warning, info } from '../../logging';
66
import { AuthenticationError } from '../../toolkit/error';
77
import { formatErrorMessage } from '../../util/error';
88
import { Mode } from '../plugin/mode';
@@ -151,8 +151,7 @@ function v3ProviderFromV2Credentials(x: SDKv2CompatibleCredentials): AwsCredenti
151151

152152
function refreshFromPluginProvider(current: AwsCredentialIdentity, producer: () => Promise<PluginProviderResult>): AwsCredentialIdentityProvider {
153153
return async () => {
154-
// eslint-disable-next-line no-console
155-
console.error(current, Date.now());
154+
info(format(current), Date.now());
156155
if (credentialsAboutToExpire(current)) {
157156
const newCreds = await producer();
158157
if (!isV3Credentials(newCreds)) {

packages/aws-cdk/lib/api/cxapp/cloud-assembly.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as cxapi from '@aws-cdk/cx-api';
22
import * as chalk from 'chalk';
33
import { minimatch } from 'minimatch';
44
import * as semver from 'semver';
5-
import { error, print, warning } from '../../logging';
5+
import { error, info, warning } from '../../logging';
66
import { ToolkitError } from '../../toolkit/error';
77
import { flatten } from '../../util';
88

@@ -264,7 +264,7 @@ export class StackCollection {
264264
printMessage(error, 'Error', message.id, message.entry);
265265
break;
266266
case cxapi.SynthesisMessageLevel.INFO:
267-
printMessage(print, 'Info', message.id, message.entry);
267+
printMessage(info, 'Info', message.id, message.entry);
268268
break;
269269
}
270270
}
@@ -346,7 +346,7 @@ function includeDownstreamStacks(
346346
} while (madeProgress);
347347

348348
if (added.length > 0) {
349-
print('Including depending stacks: %s', chalk.bold(added.join(', ')));
349+
info('Including depending stacks: %s', chalk.bold(added.join(', ')));
350350
}
351351
}
352352

@@ -376,7 +376,7 @@ function includeUpstreamStacks(
376376
}
377377

378378
if (added.length > 0) {
379-
print('Including dependency stacks: %s', chalk.bold(added.join(', ')));
379+
info('Including dependency stacks: %s', chalk.bold(added.join(', ')));
380380
}
381381
}
382382

packages/aws-cdk/lib/api/deploy-stack.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { CfnEvaluationException } from './evaluate-cloudformation-template';
1515
import { HotswapMode, HotswapPropertyOverrides, ICON } from './hotswap/common';
1616
import { tryHotswapDeployment } from './hotswap-deployments';
1717
import { addMetadataAssetsToManifest } from '../assets';
18-
import { debug, print, warning } from '../logging';
18+
import { debug, info, warning } from '../logging';
1919
import {
2020
changeSetHasNoChanges,
2121
CloudFormationStack,
@@ -333,7 +333,7 @@ export async function deployStack(options: DeployStackOptions): Promise<DeploySt
333333
// if we can skip deployment and we are performing a hotswap, let the user know
334334
// that no hotswap deployment happened
335335
if (hotswapMode !== HotswapMode.FULL_DEPLOYMENT) {
336-
print(
336+
info(
337337
`\n ${ICON} %s\n`,
338338
chalk.bold('hotswap deployment skipped - no changes were detected (use --force to override)'),
339339
);
@@ -379,22 +379,22 @@ export async function deployStack(options: DeployStackOptions): Promise<DeploySt
379379
if (hotswapDeploymentResult) {
380380
return hotswapDeploymentResult;
381381
}
382-
print(
382+
info(
383383
'Could not perform a hotswap deployment, as the stack %s contains non-Asset changes',
384384
stackArtifact.displayName,
385385
);
386386
} catch (e) {
387387
if (!(e instanceof CfnEvaluationException)) {
388388
throw e;
389389
}
390-
print(
390+
info(
391391
'Could not perform a hotswap deployment, because the CloudFormation template could not be resolved: %s',
392392
formatErrorMessage(e),
393393
);
394394
}
395395

396396
if (hotswapMode === HotswapMode.FALL_BACK) {
397-
print('Falling back to doing a full deployment');
397+
info('Falling back to doing a full deployment');
398398
options.sdk.appendCustomUserAgent('cdk-hotswap/fallback');
399399
} else {
400400
return {
@@ -505,7 +505,7 @@ class FullCloudFormationDeployment {
505505
}
506506

507507
if (!execute) {
508-
print(
508+
info(
509509
'Changeset %s created and waiting in review for manual execution (--no-execute)',
510510
changeSetDescription.ChangeSetId,
511511
);
@@ -538,7 +538,7 @@ class FullCloudFormationDeployment {
538538
await this.cleanupOldChangeset(changeSetName);
539539

540540
debug(`Attempting to create ChangeSet with name ${changeSetName} to ${this.verb} stack ${this.stackName}`);
541-
print('%s: creating CloudFormation changeset...', chalk.bold(this.stackName));
541+
info('%s: creating CloudFormation changeset...', chalk.bold(this.stackName));
542542
const changeSet = await this.cfn.createChangeSet({
543543
StackName: this.stackName,
544544
ChangeSetName: changeSetName,
@@ -609,7 +609,7 @@ class FullCloudFormationDeployment {
609609
}
610610

611611
private async directDeployment(): Promise<SuccessfulDeployStackResult> {
612-
print('%s: %s stack...', chalk.bold(this.stackName), this.update ? 'updating' : 'creating');
612+
info('%s: %s stack...', chalk.bold(this.stackName), this.update ? 'updating' : 'creating');
613613

614614
const startTime = new Date();
615615

packages/aws-cdk/lib/api/deployments.ts

-1
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,6 @@ export class Deployments {
715715

716716
// No need to validate anymore, we already did that during build
717717
const publisher = this.cachedPublisher(assetManifest, stackEnv, options.stackName);
718-
// eslint-disable-next-line no-console
719718
await publisher.publishEntry(asset, { allowCrossAccount: await this.allowCrossAccountAssetPublishingForEnv(options.stack) });
720719
if (publisher.hasFailures) {
721720
throw new Error(`Failed to publish asset ${asset.id}`);

packages/aws-cdk/lib/api/garbage-collection/garbage-collector.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { ImageIdentifier } from '@aws-sdk/client-ecr';
33
import { Tag } from '@aws-sdk/client-s3';
44
import * as chalk from 'chalk';
55
import * as promptly from 'promptly';
6-
import { debug, print } from '../../logging';
6+
import { debug, info } from '../../logging';
77
import { IECRClient, IS3Client, SDK, SdkProvider } from '../aws-auth';
88
import { DEFAULT_TOOLKIT_STACK_NAME, ToolkitInfo } from '../toolkit-info';
99
import { ProgressPrinter } from './progress-printer';
@@ -526,7 +526,7 @@ export class GarbageCollector {
526526
printer.reportDeletedAsset(deletables.slice(0, deletedCount));
527527
}
528528
} catch (err) {
529-
print(chalk.red(`Error deleting images: ${err}`));
529+
info(chalk.red(`Error deleting images: ${err}`));
530530
}
531531
}
532532

@@ -559,23 +559,23 @@ export class GarbageCollector {
559559
printer.reportDeletedAsset(deletables.slice(0, deletedCount));
560560
}
561561
} catch (err) {
562-
print(chalk.red(`Error deleting objects: ${err}`));
562+
info(chalk.red(`Error deleting objects: ${err}`));
563563
}
564564
}
565565

566566
private async bootstrapBucketName(sdk: SDK, bootstrapStackName: string): Promise<string> {
567-
const info = await ToolkitInfo.lookup(this.props.resolvedEnvironment, sdk, bootstrapStackName);
568-
return info.bucketName;
567+
const toolkitInfo = await ToolkitInfo.lookup(this.props.resolvedEnvironment, sdk, bootstrapStackName);
568+
return toolkitInfo.bucketName;
569569
}
570570

571571
private async bootstrapRepositoryName(sdk: SDK, bootstrapStackName: string): Promise<string> {
572-
const info = await ToolkitInfo.lookup(this.props.resolvedEnvironment, sdk, bootstrapStackName);
573-
return info.repositoryName;
572+
const toolkitInfo = await ToolkitInfo.lookup(this.props.resolvedEnvironment, sdk, bootstrapStackName);
573+
return toolkitInfo.repositoryName;
574574
}
575575

576576
private async bootstrapQualifier(sdk: SDK, bootstrapStackName: string): Promise<string | undefined> {
577-
const info = await ToolkitInfo.lookup(this.props.resolvedEnvironment, sdk, bootstrapStackName);
578-
return info.bootstrapStack.parameters.Qualifier;
577+
const toolkitInfo = await ToolkitInfo.lookup(this.props.resolvedEnvironment, sdk, bootstrapStackName);
578+
return toolkitInfo.bootstrapStack.parameters.Qualifier;
579579
}
580580

581581
private async numObjectsInBucket(s3: IS3Client, bucket: string): Promise<number> {

packages/aws-cdk/lib/api/garbage-collection/progress-printer.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as chalk from 'chalk';
22
import { GcAsset as GCAsset } from './garbage-collector';
3-
import { print } from '../../logging';
3+
import { info } from '../../logging';
44

55
export class ProgressPrinter {
66
private totalAssets: number;
@@ -68,9 +68,9 @@ export class ProgressPrinter {
6868
const percentage = ((this.assetsScanned / this.totalAssets) * 100).toFixed(2);
6969
// print in MiB until we hit at least 1 GiB of data tagged/deleted
7070
if (Math.max(this.taggedAssetsSizeMb, this.deletedAssetsSizeMb) >= 1000) {
71-
print(chalk.green(`[${percentage}%] ${this.assetsScanned} files scanned: ${this.taggedAsset} assets (${(this.taggedAssetsSizeMb / 1000).toFixed(2)} GiB) tagged, ${this.deletedAssets} assets (${(this.deletedAssetsSizeMb / 1000).toFixed(2)} GiB) deleted.`));
71+
info(chalk.green(`[${percentage}%] ${this.assetsScanned} files scanned: ${this.taggedAsset} assets (${(this.taggedAssetsSizeMb / 1000).toFixed(2)} GiB) tagged, ${this.deletedAssets} assets (${(this.deletedAssetsSizeMb / 1000).toFixed(2)} GiB) deleted.`));
7272
} else {
73-
print(chalk.green(`[${percentage}%] ${this.assetsScanned} files scanned: ${this.taggedAsset} assets (${this.taggedAssetsSizeMb.toFixed(2)} MiB) tagged, ${this.deletedAssets} assets (${this.deletedAssetsSizeMb.toFixed(2)} MiB) deleted.`));
73+
info(chalk.green(`[${percentage}%] ${this.assetsScanned} files scanned: ${this.taggedAsset} assets (${this.taggedAssetsSizeMb.toFixed(2)} MiB) tagged, ${this.deletedAssets} assets (${this.deletedAssetsSizeMb.toFixed(2)} MiB) deleted.`));
7474
}
7575
}
7676
}

packages/aws-cdk/lib/api/hotswap-deployments.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import * as chalk from 'chalk';
55
import type { SDK, SdkProvider } from './aws-auth';
66
import type { SuccessfulDeployStackResult } from './deploy-stack';
77
import { EvaluateCloudFormationTemplate } from './evaluate-cloudformation-template';
8-
import { print } from '../logging';
8+
import { info } from '../logging';
99
import { isHotswappableAppSyncChange } from './hotswap/appsync-mapping-templates';
1010
import { isHotswappableCodeBuildProjectChange } from './hotswap/code-build-projects';
1111
import {
@@ -400,7 +400,7 @@ function isCandidateForHotswapping(
400400

401401
async function applyAllHotswappableChanges(sdk: SDK, hotswappableChanges: HotswappableChange[]): Promise<void[]> {
402402
if (hotswappableChanges.length > 0) {
403-
print(`\n${ICON} hotswapping resources:`);
403+
info(`\n${ICON} hotswapping resources:`);
404404
}
405405
const limit = pLimit(10);
406406
// eslint-disable-next-line @cdklabs/promiseall-no-unbounded-parallelism
@@ -415,7 +415,7 @@ async function applyHotswappableChange(sdk: SDK, hotswapOperation: HotswappableC
415415
sdk.appendCustomUserAgent(customUserAgent);
416416

417417
for (const name of hotswapOperation.resourceNames) {
418-
print(` ${ICON} %s`, chalk.bold(name));
418+
info(` ${ICON} %s`, chalk.bold(name));
419419
}
420420

421421
// if the SDK call fails, an error will be thrown by the SDK
@@ -436,7 +436,7 @@ async function applyHotswappableChange(sdk: SDK, hotswapOperation: HotswappableC
436436
}
437437

438438
for (const name of hotswapOperation.resourceNames) {
439-
print(`${ICON} %s %s`, chalk.bold(name), chalk.green('hotswapped!'));
439+
info(`${ICON} %s %s`, chalk.bold(name), chalk.green('hotswapped!'));
440440
}
441441

442442
sdk.removeCustomUserAgent(customUserAgent);
@@ -461,33 +461,33 @@ function logNonHotswappableChanges(nonHotswappableChanges: NonHotswappableChange
461461
}
462462
}
463463
if (hotswapMode === HotswapMode.HOTSWAP_ONLY) {
464-
print(
464+
info(
465465
'\n%s %s',
466466
chalk.red('⚠️'),
467467
chalk.red(
468468
'The following non-hotswappable changes were found. To reconcile these using CloudFormation, specify --hotswap-fallback',
469469
),
470470
);
471471
} else {
472-
print('\n%s %s', chalk.red('⚠️'), chalk.red('The following non-hotswappable changes were found:'));
472+
info('\n%s %s', chalk.red('⚠️'), chalk.red('The following non-hotswappable changes were found:'));
473473
}
474474

475475
for (const change of nonHotswappableChanges) {
476476
change.rejectedChanges.length > 0
477-
? print(
477+
? info(
478478
' logicalID: %s, type: %s, rejected changes: %s, reason: %s',
479479
chalk.bold(change.logicalId),
480480
chalk.bold(change.resourceType),
481481
chalk.bold(change.rejectedChanges),
482482
chalk.red(change.reason),
483483
)
484-
: print(
484+
: info(
485485
' logicalID: %s, type: %s, reason: %s',
486486
chalk.bold(change.logicalId),
487487
chalk.bold(change.resourceType),
488488
chalk.red(change.reason),
489489
);
490490
}
491491

492-
print(''); // newline
492+
info(''); // newline
493493
}

packages/aws-cdk/lib/api/logs/logs-monitor.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as util from 'util';
22
import * as cxapi from '@aws-cdk/cx-api';
33
import * as chalk from 'chalk';
4-
import { print, error } from '../../logging';
4+
import { info, error } from '../../logging';
55
import { flatten } from '../../util/arrays';
66
import type { SDK } from '../aws-auth';
77

@@ -162,7 +162,7 @@ export class CloudWatchLogEventMonitor {
162162
* Print out a cloudwatch event
163163
*/
164164
private print(event: CloudWatchLogEvent): void {
165-
print(
165+
info(
166166
util.format(
167167
'[%s] %s %s',
168168
chalk.blue(event.logGroupName),

packages/aws-cdk/lib/api/plugin/plugin.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { inspect } from 'util';
22
import type { CredentialProviderSource, IPluginHost, Plugin } from '@aws-cdk/cli-plugin-contract';
3-
import * as chalk from 'chalk';
43

4+
import * as chalk from 'chalk';
55
import { type ContextProviderPlugin, isContextProviderPlugin } from './context-provider-plugin';
66
import { error } from '../../logging';
77
import { ToolkitError } from '../../toolkit/error';

packages/aws-cdk/lib/api/util/cloudformation.ts

-1
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,6 @@ export async function createDiffChangeSet(
353353
// This causes CreateChangeSet to fail with `Template Error: Fn::Equals cannot be partially collapsed`.
354354
for (const resource of Object.values(options.stack.template.Resources ?? {})) {
355355
if ((resource as any).Type === 'AWS::CloudFormation::Stack') {
356-
// eslint-disable-next-line no-console
357356
debug('This stack contains one or more nested stacks, falling back to template-only diff...');
358357

359358
return undefined;

0 commit comments

Comments
 (0)