diff --git a/packages/aws-cdk/lib/api/cxapp/cloud-executable.ts b/packages/aws-cdk/lib/api/cxapp/cloud-executable.ts index 5c0f1a2c2a289..7a26d7e253830 100644 --- a/packages/aws-cdk/lib/api/cxapp/cloud-executable.ts +++ b/packages/aws-cdk/lib/api/cxapp/cloud-executable.ts @@ -41,7 +41,7 @@ export class CloudExecutable { * Return whether there is an app command from the configuration */ public get hasApp() { - return !!this.props.configuration.settings.get(['app']); + return !!this.props.configuration.settings.get(['globalOptions', 'app']); } /** @@ -106,7 +106,7 @@ export class CloudExecutable { } private get canLookup() { - return !!(this.props.configuration.settings.get(['lookups']) ?? true); + return !!(this.props.configuration.settings.get(['globalOptions', 'lookups']) ?? true); } } diff --git a/packages/aws-cdk/lib/api/cxapp/exec.ts b/packages/aws-cdk/lib/api/cxapp/exec.ts index b02ad38445a07..0268e50d7f299 100644 --- a/packages/aws-cdk/lib/api/cxapp/exec.ts +++ b/packages/aws-cdk/lib/api/cxapp/exec.ts @@ -5,6 +5,7 @@ import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import * as cxapi from '@aws-cdk/cx-api'; import * as fs from 'fs-extra'; import * as semver from 'semver'; +import { Command } from '../../command'; import { debug, warning } from '../../logging'; import { Configuration, PROJECT_CONFIG, USER_DEFAULTS } from '../../settings'; import { ToolkitError } from '../../toolkit/error'; @@ -24,12 +25,12 @@ export async function execProgram(aws: SdkProvider, config: Configuration): Prom const env = await prepareDefaultEnvironment(aws); const context = await prepareContext(config, env); - const build = config.settings.get(['build']); + const build = config.settings.get(['globalOptions', 'build']); if (build) { await exec(build); } - const app = config.settings.get(['app']); + const app = config.settings.get(['globalOptions', 'app']); if (!app) { throw new ToolkitError(`--app is required either in command-line, in ${PROJECT_CONFIG} or in ${USER_DEFAULTS}`); } @@ -46,7 +47,7 @@ export async function execProgram(aws: SdkProvider, config: Configuration): Prom const commandLine = await guessExecutable(appToArray(app)); - const outdir = config.settings.get(['output']); + const outdir = config.settings.get(['globalOptions', 'output']); if (!outdir) { throw new ToolkitError('unexpected: --output is required'); } @@ -189,32 +190,32 @@ export async function prepareDefaultEnvironment(aws: SdkProvider): Promise<{ [ke export async function prepareContext(config: Configuration, env: { [key: string]: string | undefined}) { const context = config.context.all; - const debugMode: boolean = config.settings.get(['debug']) ?? true; + const debugMode: boolean = config.settings.get(['globalOptions', 'debug']) ?? true; if (debugMode) { env.CDK_DEBUG = 'true'; } - const pathMetadata: boolean = config.settings.get(['pathMetadata']) ?? true; + const pathMetadata: boolean = config.settings.get(['globalOptions', 'pathMetadata']) ?? true; if (pathMetadata) { context[cxapi.PATH_METADATA_ENABLE_CONTEXT] = true; } - const assetMetadata: boolean = config.settings.get(['assetMetadata']) ?? true; + const assetMetadata: boolean = config.settings.get(['globalOptions', 'assetMetadata']) ?? true; if (assetMetadata) { context[cxapi.ASSET_RESOURCE_METADATA_ENABLED_CONTEXT] = true; } - const versionReporting: boolean = config.settings.get(['versionReporting']) ?? true; + const versionReporting: boolean = config.settings.get(['globalOptions', 'versionReporting']) ?? true; if (versionReporting) { context[cxapi.ANALYTICS_REPORTING_ENABLED_CONTEXT] = true; } // We need to keep on doing this for framework version from before this flag was deprecated. if (!versionReporting) { context['aws:cdk:disable-version-reporting'] = true; } - const stagingEnabled = config.settings.get(['staging']) ?? true; + const stagingEnabled = config.settings.get(['globalOptions', 'staging']) ?? true; if (!stagingEnabled) { context[cxapi.DISABLE_ASSET_STAGING_CONTEXT] = true; } - const bundlingStacks = config.settings.get(['bundlingStacks']) ?? ['**']; + const bundlingStacks = setBundlingStacks(config); context[cxapi.BUNDLING_STACKS] = bundlingStacks; debug('context:', context); @@ -222,6 +223,34 @@ export async function prepareContext(config: Configuration, env: { [key: string] return context; } +function setBundlingStacks(config: Configuration) { + // Command may not exist if we are not executing a CLI command + if (!config.command) { + return []; + } + + const stackCommands = [ + Command.DEPLOY, + Command.DIFF, + Command.SYNTH, + Command.SYNTHESIZE, + Command.WATCH, + ]; + + // command doesn't operate on a stack selection + if (!stackCommands.includes(config.command)) { + return []; + } + + // If we deploy, diff, synth or watch a list of stacks exclusively we skip + // bundling for all other stacks. + if (config.settings.get(['globalOptions', 'exclusively']) && config.settings.get([config.command, 'STACKS'])) { + return config.settings.get([config.command, 'STACKS']); + } + + return ['**']; +} + /** * Make sure the 'app' is an array * diff --git a/packages/aws-cdk/lib/cdk-toolkit.ts b/packages/aws-cdk/lib/cdk-toolkit.ts index 3f0db42c289ba..ed38899c79555 100644 --- a/packages/aws-cdk/lib/cdk-toolkit.ts +++ b/packages/aws-cdk/lib/cdk-toolkit.ts @@ -641,7 +641,7 @@ export class CdkToolkit { // 2. Any file whose name starts with a dot. // 3. Any directory's content whose name starts with a dot. // 4. Any node_modules and its content (even if it's not a JS/TS project, you might be using a local aws-cli package) - const outputDir = this.props.configuration.settings.get(['output']); + const outputDir = this.props.configuration.settings.get(['globalOptions', 'output']); const watchExcludes = this.patternsArrayForWatch(watchSettings.exclude, { rootDir, returnRootDirIfEmpty: false, diff --git a/packages/aws-cdk/lib/cli.ts b/packages/aws-cdk/lib/cli.ts index 75ab612a8d828..c0110ebe2ecb0 100644 --- a/packages/aws-cdk/lib/cli.ts +++ b/packages/aws-cdk/lib/cli.ts @@ -4,6 +4,7 @@ import * as chalk from 'chalk'; import { DeploymentMethod } from './api'; import { HotswapMode } from './api/hotswap/common'; import { ILock } from './api/util/rwlock'; +import { convertYargsToUserInput } from './convert-to-user-input'; import { parseCommandLineArguments } from './parse-command-line-arguments'; import { checkForPlatformWarnings } from './platform-warnings'; import { IoMessageLevel, CliIoHost } from './toolkit/cli-io-host'; @@ -17,7 +18,7 @@ import { execProgram } from '../lib/api/cxapp/exec'; import { Deployments } from '../lib/api/deployments'; import { PluginHost } from '../lib/api/plugin'; import { ToolkitInfo } from '../lib/api/toolkit-info'; -import { CdkToolkit, AssetBuildTime } from '../lib/cdk-toolkit'; +import { CdkToolkit, AssetBuildTime, Tag } from '../lib/cdk-toolkit'; import { contextHandler as context } from '../lib/commands/context'; import { docs } from '../lib/commands/docs'; import { doctor } from '../lib/commands/doctor'; @@ -25,10 +26,12 @@ import { getMigrateScanType } from '../lib/commands/migrate'; import { cliInit, printAvailableTemplates } from '../lib/init'; import { data, debug, error, info, setCI, setIoMessageThreshold } from '../lib/logging'; import { Notices } from '../lib/notices'; -import { Command, Configuration, Settings } from '../lib/settings'; +import { Configuration, Settings } from '../lib/settings'; import * as version from '../lib/version'; import { SdkToCliLogger } from './api/aws-auth/sdk-logger'; +import { StringWithoutPlaceholders } from './api/util/placeholders'; import { ToolkitError } from './toolkit/error'; +import { UserInput } from './user-input'; /* eslint-disable max-len */ /* eslint-disable @typescript-eslint/no-shadow */ // yargs @@ -39,13 +42,21 @@ if (!process.stdout.isTTY) { } export async function exec(args: string[], synthesizer?: Synthesizer): Promise { - const argv = await parseCommandLineArguments(args); + const argv: UserInput = convertYargsToUserInput(await parseCommandLineArguments(args)); + + debug('Command line arguments:', argv); + + const configuration = new Configuration({ + commandLineArguments: argv, + }); + await configuration.load(); + const settings = configuration.settings.all; // if one -v, log at a DEBUG level // if 2 -v, log at a TRACE level - if (argv.verbose) { + if (settings.globalOptions?.verbose) { let ioMessageLevel: IoMessageLevel; - switch (argv.verbose) { + switch (settings.globalOptions.verbose) { case 1: ioMessageLevel = 'debug'; break; @@ -58,11 +69,11 @@ export async function exec(args: string[], synthesizer?: Synthesizer): Promise 2) { + if (settings.globalOptions?.debug || (settings.globalOptions?.verbose ?? 0) > 2) { enableTracing(true); } - if (argv.ci) { + if (settings.globalOptions?.ci) { setCI(true); } @@ -73,35 +84,27 @@ export async function exec(args: string[], synthesizer?: Synthesizer): Promise { - const toolkitStackName: string = ToolkitInfo.determineName(configuration.settings.get(['toolkitStackName'])); + async function main(command: string, settings: UserInput): Promise { + const toolkitStackName: string = ToolkitInfo.determineName(configuration.settings.get([command, 'toolkitStackName'])); debug(`Toolkit stack: ${chalk.bold(toolkitStackName)}`); - const cloudFormation = new Deployments({ sdkProvider, toolkitStackName }); - - 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 globalOptions = settings.globalOptions ?? {}; - const selector: StackSelector = { - allTopLevel: args.all, - patterns: args.STACKS, - }; + const cloudFormation = new Deployments({ sdkProvider, toolkitStackName }); const cli = new CdkToolkit({ cloudExecutable, deployments: cloudFormation, - verbose: argv.trace || argv.verbose > 0, - ignoreErrors: argv['ignore-errors'], - strict: argv.strict, + verbose: globalOptions.trace || (globalOptions.verbose ?? 0) > 0, + ignoreErrors: globalOptions.ignoreErrors, + strict: globalOptions.strict, configuration, sdkProvider, }); switch (command) { case 'context': + const contextOptions = settings.context ?? {}; return context({ context: configuration.context, - clear: argv.clear, - json: argv.json, - force: argv.force, - reset: argv.reset, + clear: contextOptions.clear, + json: globalOptions.json, + force: contextOptions.force, + reset: contextOptions.reset, }); case 'docs': - return docs({ browser: configuration.settings.get(['browser']) }); + return docs({ browser: settings.docs?.browser ?? '' }); case 'doctor': return doctor(); @@ -221,81 +215,89 @@ export async function exec(args: string[], synthesizer?: Synthesizer): Promise t !== ''); + if (nonEmptyTags.length === 0) { return []; } + + const tags: Tag[] = []; + + for (const assignment of nonEmptyTags) { + const parts = assignment.split(/=(.*)/, 2); + if (parts.length === 2) { + debug('CLI argument tags: %s=%s', parts[0], parts[1]); + tags.push({ + Key: parts[0], + Value: parts[1], + }); + } else { + warning('Tags argument is not an assignment (key=value): %s', assignment); + } + } + return tags.length > 0 ? tags : undefined; +} diff --git a/packages/aws-cdk/lib/command.ts b/packages/aws-cdk/lib/command.ts new file mode 100644 index 0000000000000..3183c764733ae --- /dev/null +++ b/packages/aws-cdk/lib/command.ts @@ -0,0 +1,26 @@ +export enum Command { + LS = 'ls', + LIST = 'list', + DIFF = 'diff', + BOOTSTRAP = 'bootstrap', + DEPLOY = 'deploy', + DESTROY = 'destroy', + SYNTHESIZE = 'synthesize', + SYNTH = 'synth', + METADATA = 'metadata', + INIT = 'init', + VERSION = 'version', + WATCH = 'watch', + GC = 'gc', + ROLLBACK = 'rollback', + IMPORT = 'import', + ACK = 'ack', + ACKNOWLEDGE = 'acknowledge', + NOTICES = 'notices', + MIGRATE = 'migrate', + CONTEXT = 'context', + DOC = 'doc', + DOCS = 'docs', + DOCTOR = 'doctor', + SOME = 'some', +} diff --git a/packages/aws-cdk/lib/convert-to-user-input.ts b/packages/aws-cdk/lib/convert-to-user-input.ts index 4b400aa844424..cb103b8f65f5c 100644 --- a/packages/aws-cdk/lib/convert-to-user-input.ts +++ b/packages/aws-cdk/lib/convert-to-user-input.ts @@ -3,7 +3,7 @@ // Do not edit by hand; all changes will be overwritten at build time from the config file. // ------------------------------------------------------------------------------------------- /* eslint-disable @stylistic/max-len */ -import { Command } from './settings'; +import { Command } from './command'; import { UserInput, GlobalOptions } from './user-input'; // @ts-ignore TS6133 diff --git a/packages/aws-cdk/lib/settings.ts b/packages/aws-cdk/lib/settings.ts index 9c6e680e6c8d8..fcb361e994b52 100644 --- a/packages/aws-cdk/lib/settings.ts +++ b/packages/aws-cdk/lib/settings.ts @@ -1,9 +1,11 @@ import * as os from 'os'; import * as fs_path from 'path'; import * as fs from 'fs-extra'; -import { Tag } from './cdk-toolkit'; +import { Command } from './command'; +import { convertConfigToUserInput } from './convert-to-user-input'; import { debug, warning } from './logging'; import { ToolkitError } from './toolkit/error'; +import { UserInput } from './user-input'; import * as util from './util'; export type SettingsMap = {[key: string]: any}; @@ -19,55 +21,13 @@ export const TRANSIENT_CONTEXT_KEY = '$dontSaveContext'; const CONTEXT_KEY = 'context'; -export enum Command { - LS = 'ls', - LIST = 'list', - DIFF = 'diff', - BOOTSTRAP = 'bootstrap', - DEPLOY = 'deploy', - DESTROY = 'destroy', - SYNTHESIZE = 'synthesize', - SYNTH = 'synth', - METADATA = 'metadata', - INIT = 'init', - VERSION = 'version', - WATCH = 'watch', - GC = 'gc', - ROLLBACK = 'rollback', - IMPORT = 'import', - ACKNOWLEDGE = 'acknowledge', - ACK = 'ack', - NOTICES = 'notices', - MIGRATE = 'migrate', - CONTEXT = 'context', - DOCS = 'docs', - DOC = 'doc', - DOCTOR = 'doctor', -} - -const BUNDLING_COMMANDS = [ - Command.DEPLOY, - Command.DIFF, - Command.SYNTH, - Command.SYNTHESIZE, - Command.WATCH, -]; - -export type Arguments = { - readonly _: [Command, ...string[]]; - readonly exclusively?: boolean; - readonly STACKS?: string[]; - readonly lookups?: boolean; - readonly [name: string]: unknown; -}; - export interface ConfigurationProps { /** * Configuration passed via command line arguments * * @default - Nothing passed */ - readonly commandLineArguments?: Arguments; + readonly commandLineArguments?: UserInput; /** * Whether or not to use context from `.cdk.json` in user home directory @@ -81,26 +41,30 @@ export interface ConfigurationProps { * All sources of settings combined */ export class Configuration { - public settings = new Settings(); + public settings = new ArgumentSettings(); public context = new Context(); - - public readonly defaultConfig = new Settings({ - versionReporting: true, - assetMetadata: true, - pathMetadata: true, - output: 'cdk.out', + public command?: Command; + + public readonly defaultConfig = new ArgumentSettings({ + globalOptions: { + versionReporting: true, + assetMetadata: true, + pathMetadata: true, + output: 'cdk.out', + }, }); - private readonly commandLineArguments: Settings; + private readonly commandLineArguments: ArgumentSettings; private readonly commandLineContext: Settings; private _projectConfig?: Settings; private _projectContext?: Settings; private loaded = false; constructor(private readonly props: ConfigurationProps = {}) { + this.command = props.commandLineArguments?.command; this.commandLineArguments = props.commandLineArguments - ? Settings.fromCommandLineArguments(props.commandLineArguments) - : new Settings(); + ? ArgumentSettings.fromCommandLineArguments(props.commandLineArguments) + : new ArgumentSettings(); this.commandLineContext = this.commandLineArguments.subSettings([CONTEXT_KEY]).makeReadOnly(); } @@ -128,15 +92,12 @@ export class Configuration { const readUserContext = this.props.readUserContext ?? true; - if (userConfig.get(['build'])) { - throw new ToolkitError('The `build` key cannot be specified in the user config (~/.cdk.json), specify it in the project config (cdk.json) instead'); - } - const contextSources = [ { bag: this.commandLineContext }, { fileName: PROJECT_CONFIG, bag: this.projectConfig.subSettings([CONTEXT_KEY]).makeReadOnly() }, { fileName: PROJECT_CONTEXT, bag: this.projectContext }, ]; + if (readUserContext) { contextSources.push({ fileName: USER_DEFAULTS, bag: userConfig.subSettings([CONTEXT_KEY]).makeReadOnly() }); } @@ -145,8 +106,8 @@ export class Configuration { // Build settings from what's left this.settings = this.defaultConfig - .merge(userConfig) - .merge(this.projectConfig) + .merge(new ArgumentSettings(convertConfigToUserInput(userConfig.all))) + .merge(new ArgumentSettings(convertConfigToUserInput(this.projectConfig.all))) .merge(this.commandLineArguments) .makeReadOnly(); @@ -276,81 +237,29 @@ export class Context { } } +// cdk.json is gonna look like this: +// { +// 'someGlobalOption': true, +// 'deploy': { +// 'someDeployOption': true, +// } +// } +// for backwards compat we will allow existing options to be specified at the base rather than within command +// this will translate to +// UserInput: { +// command: Command.ALL, +// globalOptions: { +// someGlobalOption: true, +// } +// deploy: { +// someDeployOption: true, +// } +// } + /** * A single bag of settings */ export class Settings { - /** - * Parse Settings out of CLI arguments. - * - * CLI arguments in must be accessed in the CLI code via - * `configuration.settings.get(['argName'])` instead of via `args.argName`. - * - * The advantage is that they can be configured via `cdk.json` and - * `$HOME/.cdk.json`. Arguments not listed below and accessed via this object - * can only be specified on the command line. - * - * @param argv the received CLI arguments. - * @returns a new Settings object. - */ - public static fromCommandLineArguments(argv: Arguments): Settings { - const context = this.parseStringContextListToObject(argv); - const tags = this.parseStringTagsListToObject(expectStringList(argv.tags)); - - // Determine bundling stacks - let bundlingStacks: string[]; - if (BUNDLING_COMMANDS.includes(argv._[0])) { - // If we deploy, diff, synth or watch a list of stacks exclusively we skip - // bundling for all other stacks. - bundlingStacks = argv.exclusively - ? argv.STACKS ?? ['**'] - : ['**']; - } else { // Skip bundling for all stacks - bundlingStacks = []; - } - - return new Settings({ - app: argv.app, - browser: argv.browser, - build: argv.build, - caBundlePath: argv.caBundlePath, - context, - debug: argv.debug, - tags, - language: argv.language, - pathMetadata: argv.pathMetadata, - assetMetadata: argv.assetMetadata, - profile: argv.profile, - plugin: argv.plugin, - requireApproval: argv.requireApproval, - toolkitStackName: argv.toolkitStackName, - toolkitBucket: { - bucketName: argv.bootstrapBucketName, - kmsKeyId: argv.bootstrapKmsKeyId, - }, - versionReporting: argv.versionReporting, - staging: argv.staging, - output: argv.output, - outputsFile: argv.outputsFile, - progress: argv.progress, - proxy: argv.proxy, - bundlingStacks, - lookups: argv.lookups, - rollback: argv.rollback, - notices: argv.notices, - assetParallelism: argv['asset-parallelism'], - assetPrebuild: argv['asset-prebuild'], - ignoreNoStacks: argv['ignore-no-stacks'], - hotswap: { - ecs: { - minimumEcsHealthyPercent: argv.minimumEcsHealthyPercent, - maximumEcsHealthyPercent: argv.maximumEcsHealthyPercent, - }, - }, - unstable: argv.unstable, - }); - } - public static mergeAll(...settings: Settings[]): Settings { let ret = new Settings(); for (const setting of settings) { @@ -359,54 +268,7 @@ export class Settings { return ret; } - private static parseStringContextListToObject(argv: Arguments): any { - const context: any = {}; - - for (const assignment of ((argv as any).context || [])) { - const parts = assignment.split(/=(.*)/, 2); - if (parts.length === 2) { - debug('CLI argument context: %s=%s', parts[0], parts[1]); - if (parts[0].match(/^aws:.+/)) { - throw new ToolkitError(`User-provided context cannot use keys prefixed with 'aws:', but ${parts[0]} was provided.`); - } - context[parts[0]] = parts[1]; - } else { - warning('Context argument is not an assignment (key=value): %s', assignment); - } - } - return context; - } - - /** - * Parse tags out of arguments - * - * Return undefined if no tags were provided, return an empty array if only empty - * strings were provided - */ - private static parseStringTagsListToObject(argTags: string[] | undefined): Tag[] | undefined { - if (argTags === undefined) { return undefined; } - if (argTags.length === 0) { return undefined; } - const nonEmptyTags = argTags.filter(t => t !== ''); - if (nonEmptyTags.length === 0) { return []; } - - const tags: Tag[] = []; - - for (const assignment of nonEmptyTags) { - const parts = assignment.split(/=(.*)/, 2); - if (parts.length === 2) { - debug('CLI argument tags: %s=%s', parts[0], parts[1]); - tags.push({ - Key: parts[0], - Value: parts[1], - }); - } else { - warning('Tags argument is not an assignment (key=value): %s', assignment); - } - } - return tags.length > 0 ? tags : undefined; - } - - constructor(private settings: SettingsMap = {}, public readonly readOnly = false) {} + constructor(protected settings: SettingsMap = {}, public readonly readOnly = false) {} public async load(fileName: string): Promise { if (this.readOnly) { @@ -500,6 +362,44 @@ export class Settings { } } +/** + * A specific bag of settings related to Arguments specified via CLI or cdk.json + */ +export class ArgumentSettings extends Settings { + /** + * Parse Settings out of CLI arguments. + * + * CLI arguments in must be accessed in the CLI code via + * `configuration.settings.get(['argName'])` instead of via `args.argName`. + * + * The advantage is that they can be configured via `cdk.json` and + * `$HOME/.cdk.json`. Arguments not listed below and accessed via this object + * can only be specified on the command line. + * + * @param argv the received CLI arguments. + * @returns a new Settings object. + */ + public static fromCommandLineArguments(argv: UserInput): ArgumentSettings { + return new ArgumentSettings(argv); + } + + public static fromConfigFileArguments(argv: UserInput): ArgumentSettings { + return new ArgumentSettings(argv); + } + + public constructor(args: UserInput = {}) { + super(args); + } + + public merge(other: ArgumentSettings): ArgumentSettings { + return new ArgumentSettings(util.deepMerge(this.settings, other.settings)); + } + + public get all(): UserInput { + return this.get([]); + } +} + function expandHomeDir(x: string) { if (x.startsWith('~')) { return fs_path.join(os.homedir(), x.slice(1)); @@ -528,15 +428,3 @@ function stripTransientValues(obj: {[key: string]: any}) { function isTransientValue(value: any) { return typeof value === 'object' && value !== null && (value as any)[TRANSIENT_CONTEXT_KEY]; } - -function expectStringList(x: unknown): string[] | undefined { - if (x === undefined) { return undefined; } - if (!Array.isArray(x)) { - throw new ToolkitError(`Expected array, got '${x}'`); - } - const nonStrings = x.filter(e => typeof e !== 'string'); - if (nonStrings.length > 0) { - throw new ToolkitError(`Expected list of strings, found ${nonStrings}`); - } - return x; -} diff --git a/packages/aws-cdk/lib/user-input.ts b/packages/aws-cdk/lib/user-input.ts index 369a7fe325515..03342227148fe 100644 --- a/packages/aws-cdk/lib/user-input.ts +++ b/packages/aws-cdk/lib/user-input.ts @@ -3,7 +3,7 @@ // Do not edit by hand; all changes will be overwritten at build time from the config file. // ------------------------------------------------------------------------------------------- /* eslint-disable @stylistic/max-len */ -import { Command } from './settings'; +import { Command } from './command'; /** * The structure of the user input -- either CLI options or cdk.json -- generated from packages/aws-cdk/lib/config.ts diff --git a/packages/aws-cdk/test/api/exec.test.ts b/packages/aws-cdk/test/api/exec.test.ts index fa450d241a6ae..2f169a8a9973f 100644 --- a/packages/aws-cdk/test/api/exec.test.ts +++ b/packages/aws-cdk/test/api/exec.test.ts @@ -261,7 +261,7 @@ test('cli releases the outdir lock when execProgram throws', async () => { // WHEN await expect(execProgram(sdkProvider, config)).rejects.toThrow(); - const output = config.settings.get(['output']); + const output = config.settings.get(['globalOptions', 'output']); expect(output).toBeDefined(); // check that the lock is released diff --git a/packages/aws-cdk/test/settings.test.ts b/packages/aws-cdk/test/settings.test.ts index 7edc2e9b487a2..679fe6827883e 100644 --- a/packages/aws-cdk/test/settings.test.ts +++ b/packages/aws-cdk/test/settings.test.ts @@ -1,6 +1,8 @@ /* eslint-disable import/order */ -import { Command, Context, Settings } from '../lib/settings'; +import { Context, ArgumentSettings, Settings } from '../lib/settings'; import { Tag } from '../lib/cdk-toolkit'; +import { convertYargsToUserInput } from '../lib/convert-to-user-input'; +import { Command } from '../lib/command'; test('can delete values from Context object', () => { // GIVEN @@ -64,8 +66,8 @@ test('can clear all values in all objects', () => { test('can parse string context from command line arguments', () => { // GIVEN - const settings1 = Settings.fromCommandLineArguments({ context: ['foo=bar'], _: [Command.DEPLOY] }); - const settings2 = Settings.fromCommandLineArguments({ context: ['foo='], _: [Command.DEPLOY] }); + const settings1 = ArgumentSettings.fromCommandLineArguments(convertYargsToUserInput({ context: ['foo=bar'], _: [Command.DEPLOY] })); + const settings2 = ArgumentSettings.fromCommandLineArguments(convertYargsToUserInput({ context: ['foo='], _: [Command.DEPLOY] })); // THEN expect(settings1.get(['context']).foo).toEqual( 'bar'); @@ -74,8 +76,8 @@ test('can parse string context from command line arguments', () => { test('can parse string context from command line arguments with equals sign in value', () => { // GIVEN - const settings1 = Settings.fromCommandLineArguments({ context: ['foo==bar='], _: [Command.DEPLOY] }); - const settings2 = Settings.fromCommandLineArguments({ context: ['foo=bar='], _: [Command.DEPLOY] }); + const settings1 = ArgumentSettings.fromCommandLineArguments(convertYargsToUserInput({ context: ['foo==bar='], _: [Command.DEPLOY] })); + const settings2 = ArgumentSettings.fromCommandLineArguments(convertYargsToUserInput({ context: ['foo=bar='], _: [Command.DEPLOY] })); // THEN expect(settings1.get(['context']).foo).toEqual( '=bar='); @@ -84,8 +86,8 @@ test('can parse string context from command line arguments with equals sign in v test('can parse tag values from command line arguments', () => { // GIVEN - const settings1 = Settings.fromCommandLineArguments({ tags: ['foo=bar'], _: [Command.DEPLOY] }); - const settings2 = Settings.fromCommandLineArguments({ tags: ['foo='], _: [Command.DEPLOY] }); + const settings1 = ArgumentSettings.fromCommandLineArguments(convertYargsToUserInput({ tags: ['foo=bar'], _: [Command.DEPLOY] })); + const settings2 = ArgumentSettings.fromCommandLineArguments(convertYargsToUserInput({ tags: ['foo='], _: [Command.DEPLOY] })); // THEN expect(settings1.get(['tags']).find((tag: Tag) => tag.Key === 'foo').Value).toEqual('bar'); @@ -94,8 +96,8 @@ test('can parse tag values from command line arguments', () => { test('can parse tag values from command line arguments with equals sign in value', () => { // GIVEN - const settings1 = Settings.fromCommandLineArguments({ tags: ['foo==bar='], _: [Command.DEPLOY] }); - const settings2 = Settings.fromCommandLineArguments({ tags: ['foo=bar='], _: [Command.DEPLOY] }); + const settings1 = ArgumentSettings.fromCommandLineArguments(convertYargsToUserInput({ tags: ['foo==bar='], _: [Command.DEPLOY] })); + const settings2 = ArgumentSettings.fromCommandLineArguments(convertYargsToUserInput({ tags: ['foo=bar='], _: [Command.DEPLOY] })); // THEN expect(settings1.get(['tags']).find((tag: Tag) => tag.Key === 'foo').Value).toEqual('=bar='); @@ -104,9 +106,9 @@ test('can parse tag values from command line arguments with equals sign in value test('bundling stacks defaults to an empty list', () => { // GIVEN - const settings = Settings.fromCommandLineArguments({ + const settings = ArgumentSettings.fromCommandLineArguments(convertYargsToUserInput({ _: [Command.LIST], - }); + })); // THEN expect(settings.get(['bundlingStacks'])).toEqual([]); @@ -114,9 +116,9 @@ test('bundling stacks defaults to an empty list', () => { test('bundling stacks defaults to ** for deploy', () => { // GIVEN - const settings = Settings.fromCommandLineArguments({ + const settings = ArgumentSettings.fromCommandLineArguments(convertYargsToUserInput({ _: [Command.DEPLOY], - }); + })); // THEN expect(settings.get(['bundlingStacks'])).toEqual(['**']); @@ -124,9 +126,9 @@ test('bundling stacks defaults to ** for deploy', () => { test('bundling stacks defaults to ** for watch', () => { // GIVEN - const settings = Settings.fromCommandLineArguments({ + const settings = ArgumentSettings.fromCommandLineArguments(convertYargsToUserInput({ _: [Command.WATCH], - }); + })); // THEN expect(settings.get(['bundlingStacks'])).toEqual(['**']); @@ -134,11 +136,11 @@ test('bundling stacks defaults to ** for watch', () => { test('bundling stacks with deploy exclusively', () => { // GIVEN - const settings = Settings.fromCommandLineArguments({ + const settings = ArgumentSettings.fromCommandLineArguments(convertYargsToUserInput({ _: [Command.DEPLOY], exclusively: true, STACKS: ['cool-stack'], - }); + })); // THEN expect(settings.get(['bundlingStacks'])).toEqual(['cool-stack']); @@ -146,11 +148,11 @@ test('bundling stacks with deploy exclusively', () => { test('bundling stacks with watch exclusively', () => { // GIVEN - const settings = Settings.fromCommandLineArguments({ + const settings = ArgumentSettings.fromCommandLineArguments(convertYargsToUserInput({ _: [Command.WATCH], exclusively: true, STACKS: ['cool-stack'], - }); + })); // THEN expect(settings.get(['bundlingStacks'])).toEqual(['cool-stack']); @@ -158,10 +160,10 @@ test('bundling stacks with watch exclusively', () => { test('should include outputs-file in settings', () => { // GIVEN - const settings = Settings.fromCommandLineArguments({ + const settings = ArgumentSettings.fromCommandLineArguments(convertYargsToUserInput({ _: [Command.DEPLOY], outputsFile: 'my-outputs-file.json', - }); + })); // THEN expect(settings.get(['outputsFile'])).toEqual('my-outputs-file.json'); @@ -169,10 +171,10 @@ test('should include outputs-file in settings', () => { test('providing a build arg', () => { // GIVEN - const settings = Settings.fromCommandLineArguments({ + const settings = ArgumentSettings.fromCommandLineArguments(convertYargsToUserInput({ _: [Command.SYNTH], build: 'mvn package', - }); + })); // THEN expect(settings.get(['build'])).toEqual('mvn package'); diff --git a/packages/aws-cdk/test/usersettings.test.ts b/packages/aws-cdk/test/usersettings.test.ts index 6f5e0fb4fb642..2113f0e749aa9 100644 --- a/packages/aws-cdk/test/usersettings.test.ts +++ b/packages/aws-cdk/test/usersettings.test.ts @@ -110,5 +110,5 @@ test('Can specify the `quiet` key in the user config', async () => { // THEN const config = await new Configuration().load(); - expect(config.settings.get(['quiet'])).toBe(true); + expect(config.settings.get(['globalOptions', 'quiet'])).toBe(true); }); diff --git a/tools/@aws-cdk/user-input-gen/lib/convert-to-user-input-gen.ts b/tools/@aws-cdk/user-input-gen/lib/convert-to-user-input-gen.ts index b348059eff33e..c7dc010328864 100644 --- a/tools/@aws-cdk/user-input-gen/lib/convert-to-user-input-gen.ts +++ b/tools/@aws-cdk/user-input-gen/lib/convert-to-user-input-gen.ts @@ -15,7 +15,7 @@ export async function renderUserInputFuncs(config: CliConfig): Promise { scope.documentation.push('Do not edit by hand; all changes will be overwritten at build time from the config file.'); scope.documentation.push('-------------------------------------------------------------------------------------------'); - scope.addImport(new SelectiveModuleImport(scope, './settings', ['Command'])); + scope.addImport(new SelectiveModuleImport(scope, './command', ['Command'])); scope.addImport(new SelectiveModuleImport(scope, './user-input', ['UserInput', 'GlobalOptions'])); const userInputType = Type.fromName(scope, 'UserInput'); diff --git a/tools/@aws-cdk/user-input-gen/lib/user-input-gen.ts b/tools/@aws-cdk/user-input-gen/lib/user-input-gen.ts index e6f97f90e8865..9f9661acd2d21 100644 --- a/tools/@aws-cdk/user-input-gen/lib/user-input-gen.ts +++ b/tools/@aws-cdk/user-input-gen/lib/user-input-gen.ts @@ -21,7 +21,7 @@ export async function renderUserInputType(config: CliConfig): Promise { }); // add required command - scope.addImport(new SelectiveModuleImport(scope, './settings', ['Command'])); + scope.addImport(new SelectiveModuleImport(scope, './command', ['Command'])); const commandEnum = Type.fromName(scope, 'Command'); userInputType.addProperty({ diff --git a/tools/@aws-cdk/user-input-gen/test/convert-to-user-input-gen.test.ts b/tools/@aws-cdk/user-input-gen/test/convert-to-user-input-gen.test.ts index 6afc40e224592..f860985c10beb 100644 --- a/tools/@aws-cdk/user-input-gen/test/convert-to-user-input-gen.test.ts +++ b/tools/@aws-cdk/user-input-gen/test/convert-to-user-input-gen.test.ts @@ -49,7 +49,7 @@ describe('render', () => { // Do not edit by hand; all changes will be overwritten at build time from the config file. // ------------------------------------------------------------------------------------------- /* eslint-disable @stylistic/max-len */ - import { Command } from './settings'; + import { Command } from './command'; import { UserInput, GlobalOptions } from './user-input'; // @ts-ignore TS6133 diff --git a/tools/@aws-cdk/user-input-gen/test/user-input-gen.test.ts b/tools/@aws-cdk/user-input-gen/test/user-input-gen.test.ts index f88360f34f1d7..72253f935f3ce 100644 --- a/tools/@aws-cdk/user-input-gen/test/user-input-gen.test.ts +++ b/tools/@aws-cdk/user-input-gen/test/user-input-gen.test.ts @@ -49,7 +49,7 @@ describe('render', () => { // Do not edit by hand; all changes will be overwritten at build time from the config file. // ------------------------------------------------------------------------------------------- /* eslint-disable @stylistic/max-len */ - import { Command } from './settings'; + import { Command } from './command'; /** * The structure of the user input -- either CLI options or cdk.json -- generated from packages/aws-cdk/lib/config.ts @@ -158,7 +158,7 @@ describe('render', () => { // Do not edit by hand; all changes will be overwritten at build time from the config file. // ------------------------------------------------------------------------------------------- /* eslint-disable @stylistic/max-len */ - import { Command } from './settings'; + import { Command } from './command'; /** * The structure of the user input -- either CLI options or cdk.json -- generated from packages/aws-cdk/lib/config.ts @@ -240,7 +240,7 @@ describe('render', () => { // Do not edit by hand; all changes will be overwritten at build time from the config file. // ------------------------------------------------------------------------------------------- /* eslint-disable @stylistic/max-len */ - import { Command } from './settings'; + import { Command } from './command'; /** * The structure of the user input -- either CLI options or cdk.json -- generated from packages/aws-cdk/lib/config.ts