in packages/aws-cdk/lib/cli/cli.ts [185:527]
async function main(command: string, args: any): Promise<number | void> {
ioHost.currentAction = command as any;
const toolkitStackName: string = ToolkitInfo.determineName(configuration.settings.get(['toolkitStackName']));
ioHost.defaults.debug(`Toolkit stack: ${chalk.bold(toolkitStackName)}`);
const cloudFormation = new Deployments({
sdkProvider,
toolkitStackName,
ioHelper: asIoHelper(ioHost, ioHost.currentAction as any),
});
if (args.all && args.STACKS) {
throw new ToolkitError('You must either specify a list of Stacks or the `--all` argument');
}
args.STACKS = args.STACKS ?? (args.STACK ? [args.STACK] : []);
args.ENVIRONMENTS = args.ENVIRONMENTS ?? [];
const selector: StackSelector = {
allTopLevel: args.all,
patterns: args.STACKS,
};
const cli = new CdkToolkit({
ioHost,
cloudExecutable,
toolkitStackName,
deployments: cloudFormation,
verbose: argv.trace || argv.verbose > 0,
ignoreErrors: argv['ignore-errors'],
strict: argv.strict,
configuration,
sdkProvider,
});
switch (command) {
case 'context':
ioHost.currentAction = 'context';
return context({
context: configuration.context,
clear: argv.clear,
json: argv.json,
force: argv.force,
reset: argv.reset,
});
case 'docs':
case 'doc':
ioHost.currentAction = 'docs';
return docs({ browser: configuration.settings.get(['browser']) });
case 'doctor':
ioHost.currentAction = 'doctor';
return doctor();
case 'ls':
case 'list':
ioHost.currentAction = 'list';
return cli.list(args.STACKS, {
long: args.long,
json: argv.json,
showDeps: args.showDependencies,
});
case 'diff':
ioHost.currentAction = 'diff';
const enableDiffNoFail = isFeatureEnabled(configuration, cxapi.ENABLE_DIFF_NO_FAIL_CONTEXT);
return cli.diff({
stackNames: args.STACKS,
exclusively: args.exclusively,
templatePath: args.template,
strict: args.strict,
contextLines: args.contextLines,
securityOnly: args.securityOnly,
fail: args.fail != null ? args.fail : !enableDiffNoFail,
compareAgainstProcessedTemplate: args.processed,
quiet: args.quiet,
changeSet: args['change-set'],
toolkitStackName: toolkitStackName,
});
case 'refactor':
if (!configuration.settings.get(['unstable']).includes('refactor')) {
throw new ToolkitError('Unstable feature use: \'refactor\' is unstable. It must be opted in via \'--unstable\', e.g. \'cdk refactor --unstable=refactor\'');
}
ioHost.currentAction = 'refactor';
return cli.refactor({
dryRun: args.dryRun,
selector,
excludeFile: args.excludeFile,
});
case 'bootstrap':
ioHost.currentAction = 'bootstrap';
const source: BootstrapSource = determineBootstrapVersion(ioHost, args);
if (args.showTemplate) {
const bootstrapper = new Bootstrapper(source, asIoHelper(ioHost, ioHost.currentAction));
return bootstrapper.showTemplate(args.json);
}
return cli.bootstrap(args.ENVIRONMENTS, {
source,
roleArn: args.roleArn,
forceDeployment: argv.force,
toolkitStackName: toolkitStackName,
execute: args.execute,
tags: configuration.settings.get(['tags']),
terminationProtection: args.terminationProtection,
usePreviousParameters: args['previous-parameters'],
parameters: {
bucketName: configuration.settings.get(['toolkitBucket', 'bucketName']),
kmsKeyId: configuration.settings.get(['toolkitBucket', 'kmsKeyId']),
createCustomerMasterKey: args.bootstrapCustomerKey,
qualifier: args.qualifier ?? configuration.context.get('@aws-cdk/core:bootstrapQualifier'),
publicAccessBlockConfiguration: args.publicAccessBlockConfiguration,
examplePermissionsBoundary: argv.examplePermissionsBoundary,
customPermissionsBoundary: argv.customPermissionsBoundary,
trustedAccounts: arrayFromYargs(args.trust),
trustedAccountsForLookup: arrayFromYargs(args.trustForLookup),
untrustedAccounts: arrayFromYargs(args.untrust),
cloudFormationExecutionPolicies: arrayFromYargs(args.cloudformationExecutionPolicies),
},
});
case 'deploy':
ioHost.currentAction = 'deploy';
const parameterMap: { [name: string]: string | undefined } = {};
for (const parameter of args.parameters) {
if (typeof parameter === 'string') {
const keyValue = (parameter as string).split('=');
parameterMap[keyValue[0]] = keyValue.slice(1).join('=');
}
}
if (args.execute !== undefined && args.method !== undefined) {
throw new ToolkitError('Can not supply both --[no-]execute and --method at the same time');
}
let deploymentMethod: DeploymentMethod | undefined;
switch (args.method) {
case 'direct':
if (args.changeSetName) {
throw new ToolkitError('--change-set-name cannot be used with method=direct');
}
if (args.importExistingResources) {
throw new ToolkitError('--import-existing-resources cannot be enabled with method=direct');
}
deploymentMethod = { method: 'direct' };
break;
case 'change-set':
deploymentMethod = {
method: 'change-set',
execute: true,
changeSetName: args.changeSetName,
importExistingResources: args.importExistingResources,
};
break;
case 'prepare-change-set':
deploymentMethod = {
method: 'change-set',
execute: false,
changeSetName: args.changeSetName,
importExistingResources: args.importExistingResources,
};
break;
case undefined:
deploymentMethod = {
method: 'change-set',
execute: args.execute ?? true,
changeSetName: args.changeSetName,
importExistingResources: args.importExistingResources,
};
break;
}
return cli.deploy({
selector,
exclusively: args.exclusively,
toolkitStackName,
roleArn: args.roleArn,
notificationArns: args.notificationArns,
requireApproval: configuration.settings.get(['requireApproval']),
reuseAssets: args['build-exclude'],
tags: configuration.settings.get(['tags']),
deploymentMethod,
force: args.force,
parameters: parameterMap,
usePreviousParameters: args['previous-parameters'],
outputsFile: configuration.settings.get(['outputsFile']),
progress: configuration.settings.get(['progress']),
ci: args.ci,
rollback: configuration.settings.get(['rollback']),
hotswap: determineHotswapMode(args.hotswap, args.hotswapFallback),
watch: args.watch,
traceLogs: args.logs,
concurrency: args.concurrency,
assetParallelism: configuration.settings.get(['assetParallelism']),
assetBuildTime: configuration.settings.get(['assetPrebuild'])
? AssetBuildTime.ALL_BEFORE_DEPLOY
: AssetBuildTime.JUST_IN_TIME,
ignoreNoStacks: args.ignoreNoStacks,
});
case 'rollback':
ioHost.currentAction = 'rollback';
return cli.rollback({
selector,
toolkitStackName,
roleArn: args.roleArn,
force: args.force,
validateBootstrapStackVersion: args['validate-bootstrap-version'],
orphanLogicalIds: args.orphan,
});
case 'import':
ioHost.currentAction = 'import';
return cli.import({
selector,
toolkitStackName,
roleArn: args.roleArn,
deploymentMethod: {
method: 'change-set',
execute: args.execute,
changeSetName: args.changeSetName,
},
progress: configuration.settings.get(['progress']),
rollback: configuration.settings.get(['rollback']),
recordResourceMapping: args['record-resource-mapping'],
resourceMappingFile: args['resource-mapping'],
force: args.force,
});
case 'watch':
ioHost.currentAction = 'watch';
await cli.watch({
selector,
exclusively: args.exclusively,
toolkitStackName,
roleArn: args.roleArn,
reuseAssets: args['build-exclude'],
deploymentMethod: {
method: 'change-set',
changeSetName: args.changeSetName,
},
force: args.force,
progress: configuration.settings.get(['progress']),
rollback: configuration.settings.get(['rollback']),
hotswap: determineHotswapMode(args.hotswap, args.hotswapFallback, true),
traceLogs: args.logs,
concurrency: args.concurrency,
});
return;
case 'destroy':
ioHost.currentAction = 'destroy';
return cli.destroy({
selector,
exclusively: args.exclusively,
force: args.force,
roleArn: args.roleArn,
});
case 'gc':
ioHost.currentAction = 'gc';
if (!configuration.settings.get(['unstable']).includes('gc')) {
throw new ToolkitError('Unstable feature use: \'gc\' is unstable. It must be opted in via \'--unstable\', e.g. \'cdk gc --unstable=gc\'');
}
return cli.garbageCollect(args.ENVIRONMENTS, {
action: args.action,
type: args.type,
rollbackBufferDays: args['rollback-buffer-days'],
createdBufferDays: args['created-buffer-days'],
bootstrapStackName: args.bootstrapStackName,
confirm: args.confirm,
});
case 'synthesize':
case 'synth':
ioHost.currentAction = 'synth';
const quiet = configuration.settings.get(['quiet']) ?? args.quiet;
if (args.exclusively) {
return cli.synth(args.STACKS, args.exclusively, quiet, args.validation, argv.json);
} else {
return cli.synth(args.STACKS, true, quiet, args.validation, argv.json);
}
case 'notices':
ioHost.currentAction = 'notices';
// If the user explicitly asks for notices, they are now the primary output
// of the command and they should go to stdout.
ioHost.noticesDestination = 'stdout';
// This is a valid command, but we're postponing its execution because displaying
// notices automatically happens after every command.
return;
case 'metadata':
ioHost.currentAction = 'metadata';
return cli.metadata(args.STACK, argv.json);
case 'acknowledge':
case 'ack':
ioHost.currentAction = 'notices';
return cli.acknowledge(args.ID);
case 'init':
ioHost.currentAction = 'init';
const language = configuration.settings.get(['language']);
if (args.list) {
return printAvailableTemplates(language);
} else {
return cliInit({
type: args.TEMPLATE,
language,
canUseNetwork: undefined,
generateOnly: args.generateOnly,
libVersion: args.libVersion,
});
}
case 'migrate':
ioHost.currentAction = 'migrate';
return cli.migrate({
stackName: args['stack-name'],
fromPath: args['from-path'],
fromStack: args['from-stack'],
language: args.language,
outputPath: args['output-path'],
fromScan: getMigrateScanType(args['from-scan']),
filter: args.filter,
account: args.account,
region: args.region,
compress: args.compress,
});
case 'version':
ioHost.currentAction = 'version';
return ioHost.defaults.result(version.displayVersion());
default:
throw new ToolkitError('Unknown command: ' + command);
}
}