diff --git a/aws-cdk.code-workspace b/aws-cdk.code-workspace index e4232d5e9ea15..a7ebb6636469f 100644 --- a/aws-cdk.code-workspace +++ b/aws-cdk.code-workspace @@ -31,7 +31,7 @@ "name": "aws-custom-resource-sdk-adapter", "rootPath": "packages/@aws-cdk/aws-custom-resource-sdk-adapter" }, - { "name": "yargs-gen", "rootPath": "tools/@aws-cdk/yargs-gen" } + { "name": "cli-args-gen", "rootPath": "tools/@aws-cdk/cli-args-gen" } ] }, "extensions": { diff --git a/codecov.yml b/codecov.yml index a093a68ef04bb..bb41d9b4d440a 100644 --- a/codecov.yml +++ b/codecov.yml @@ -30,3 +30,7 @@ component_management: name: packages/aws-cdk # display name that can change freely paths: - packages/aws-cdk/** + +# https://docs.codecov.com/docs/ignoring-paths +ignore: + - packages/aws-cdk/lib/parse-command-line-arguments.ts # this file is generated and some lines cannot be tested diff --git a/lerna.json b/lerna.json index 61737fd4607ff..c10809593a0e4 100644 --- a/lerna.json +++ b/lerna.json @@ -10,7 +10,7 @@ "packages/@aws-cdk-testing/*", "packages/@aws-cdk/*/lambda-packages/*", "tools/@aws-cdk/cdk-build-tools", - "tools/@aws-cdk/yargs-gen", + "tools/@aws-cdk/cli-args-gen", "tools/@aws-cdk/cdk-release", "tools/@aws-cdk/node-bundle", "tools/@aws-cdk/pkglint", diff --git a/package.json b/package.json index b8620a59edc33..0f3eb7971f811 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "packages/@aws-cdk-testing/*", "packages/@aws-cdk/*/lambda-packages/*", "tools/@aws-cdk/cdk-build-tools", - "tools/@aws-cdk/yargs-gen", + "tools/@aws-cdk/cli-args-gen", "tools/@aws-cdk/cdk-release", "tools/@aws-cdk/node-bundle", "tools/@aws-cdk/pkglint", diff --git a/packages/aws-cdk/CONTRIBUTING.md b/packages/aws-cdk/CONTRIBUTING.md index 4a8b79abe277b..7619772294894 100644 --- a/packages/aws-cdk/CONTRIBUTING.md +++ b/packages/aws-cdk/CONTRIBUTING.md @@ -1,21 +1,21 @@ ## CLI Commands All CDK CLI Commands are defined in `lib/config.ts`. This file is translated -into a valid `yargs` configuration by `bin/yargs-gen`, which is generated by `@aws-cdk/yargs-gen`. +into a valid `yargs` configuration by `bin/cli-args-gen`, which is generated by `@aws-cdk/cli-args-gen`. The `yargs` configuration is generated into the function `parseCommandLineArguments()`, in `lib/parse-command-line-arguments.ts`, and is checked into git for readability and inspectability; do not edit this file by hand, as every subsequent `yarn build` will overwrite any manual edits. If you need to leverage a `yargs` feature not used by -the CLI, you must add support for it to `@aws-cdk/yargs-gen`. +the CLI, you must add support for it to `@aws-cdk/cli-args-gen`. -Note that `bin/yargs-gen` is executed by `ts-node`, which allows `config.ts` to +Note that `bin/cli-args-gen` is executed by `ts-node`, which allows `config.ts` to reference functions and other identifiers defined in the CLI before the CLI is built. ### Dynamic Values Some values, such as the user's platform, cannot be computed at build time. -Some commands depend on these values, and thus `yargs-gen` must generate the +Some commands depend on these values, and thus `cli-args-gen` must generate the code to compute these values at build time. The only way to do this today is to reference a parameter with `DynamicValue.fromParameter`. diff --git a/packages/aws-cdk/lib/cli-arguments.ts b/packages/aws-cdk/lib/cli-arguments.ts new file mode 100644 index 0000000000000..4a475017ca8b9 --- /dev/null +++ b/packages/aws-cdk/lib/cli-arguments.ts @@ -0,0 +1,1255 @@ +// ------------------------------------------------------------------------------------------- +// GENERATED FROM packages/aws-cdk/lib/config.ts. +// Do not edit by hand; all changes will be overwritten at build time from the config file. +// ------------------------------------------------------------------------------------------- +/* eslint-disable max-len */ +import { Command } from './settings'; + +/** + * The structure of the CLI configuration, generated from packages/aws-cdk/lib/config.ts + * + * @struct + */ +export interface CliArguments { + /** + * The CLI command name followed by any properties of the command + */ + readonly _: [Command, ...string[]]; + + /** + * Global options available to all CLI commands + */ + readonly globalOptions?: GlobalOptions; + + /** + * Lists all stacks in the app + * + * aliases: ls + */ + readonly list?: ListOptions; + + /** + * Synthesizes and prints the CloudFormation template for this stack + * + * aliases: synth + */ + readonly synthesize?: SynthesizeOptions; + + /** + * Deploys the CDK toolkit stack into an AWS environment + */ + readonly bootstrap?: BootstrapOptions; + + /** + * Garbage collect assets. Options detailed here: https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk/README.md#cdk-gc + */ + readonly gc?: GcOptions; + + /** + * Deploys the stack(s) named STACKS into your AWS account + */ + readonly deploy?: DeployOptions; + + /** + * Rolls back the stack(s) named STACKS to their last stable state + */ + readonly rollback?: RollbackOptions; + + /** + * Import existing resource(s) into the given STACK + */ + readonly import?: ImportOptions; + + /** + * Shortcut for 'deploy --watch' + */ + readonly watch?: WatchOptions; + + /** + * Destroy the stack(s) named STACKS + */ + readonly destroy?: DestroyOptions; + + /** + * Compares the specified stack with the deployed stack or a local template file, and returns with status 1 if any difference is found + */ + readonly diff?: DiffOptions; + + /** + * Returns all metadata associated with this stack + */ + readonly metadata?: MetadataOptions; + + /** + * Acknowledge a notice so that it does not show up anymore + * + * aliases: ack + */ + readonly acknowledge?: AcknowledgeOptions; + + /** + * Returns a list of relevant notices + */ + readonly notices?: NoticesOptions; + + /** + * Create a new, empty CDK project from a template. + */ + readonly init?: InitOptions; + + /** + * Migrate existing AWS resources into a CDK app + */ + readonly migrate?: MigrateOptions; + + /** + * Manage cached context values + */ + readonly context?: ContextOptions; + + /** + * Opens the reference documentation in a browser + * + * aliases: doc + */ + readonly docs?: DocsOptions; + + /** + * Check your set-up for potential problems + */ + readonly doctor?: DoctorOptions; +} + +/** + * Global options available to all CLI commands + * + * @struct + */ +export interface GlobalOptions { + /** + * REQUIRED WHEN RUNNING APP: command-line for executing your app or a cloud assembly directory (e.g. "node bin/my-app.js"). Can also be specified in cdk.json or ~/.cdk.json + * + * @default - undefined + */ + readonly app?: string; + + /** + * Command-line for a pre-synth build + * + * @default - undefined + */ + readonly build?: string; + + /** + * Add contextual string parameter (KEY=VALUE) + * + * @default - undefined + */ + readonly context?: Array; + + /** + * Name or path of a node package that extend the CDK features. Can be specified multiple times + * + * @default - undefined + */ + readonly plugin?: Array; + + /** + * Print trace for stack warnings + * + * @default - undefined + */ + readonly trace?: boolean; + + /** + * Do not construct stacks with warnings + * + * @default - undefined + */ + readonly strict?: boolean; + + /** + * Perform context lookups (synthesis fails if this is disabled and context lookups need to be performed) + * + * @default - true + */ + readonly lookups?: boolean; + + /** + * Ignores synthesis errors, which will likely produce an invalid output + * + * @default - false + */ + readonly 'ignore-errors'?: boolean; + + /** + * Use JSON output instead of YAML when templates are printed to STDOUT + * + * @default - false + */ + readonly json?: boolean; + + /** + * Show debug logs (specify multiple times to increase verbosity) + * + * @default - false + */ + readonly verbose?: boolean; + + /** + * Debug the CDK app. Log additional information during synthesis, such as creation stack traces of tokens (sets CDK_DEBUG, will slow down synthesis) + * + * @default - false + */ + readonly debug?: boolean; + + /** + * Use the indicated AWS profile as the default environment + * + * @default - undefined + */ + readonly profile?: string; + + /** + * Use the indicated proxy. Will read from HTTPS_PROXY environment variable if not specified + * + * @default - undefined + */ + readonly proxy?: string; + + /** + * Path to CA certificate to use when validating HTTPS requests. Will read from AWS_CA_BUNDLE environment variable if not specified + * + * @default - undefined + */ + readonly 'ca-bundle-path'?: string; + + /** + * Force trying to fetch EC2 instance credentials. Default: guess EC2 instance status + * + * @default - undefined + */ + readonly ec2creds?: boolean; + + /** + * Include the "AWS::CDK::Metadata" resource in synthesized templates (enabled by default) + * + * @default - undefined + */ + readonly 'version-reporting'?: boolean; + + /** + * Include "aws:cdk:path" CloudFormation metadata for each resource (enabled by default) + * + * @default - undefined + */ + readonly 'path-metadata'?: boolean; + + /** + * Include "aws:asset:*" CloudFormation metadata for resources that uses assets (enabled by default) + * + * @default - undefined + */ + readonly 'asset-metadata'?: boolean; + + /** + * ARN of Role to use when invoking CloudFormation + * + * @default - undefined + */ + readonly 'role-arn'?: string; + + /** + * Copy assets to the output directory (use --no-staging to disable the copy of assets which allows local debugging via the SAM CLI to reference the original source files) + * + * @default - true + */ + readonly staging?: boolean; + + /** + * Emits the synthesized cloud assembly into a directory (default: cdk.out) + * + * @default - undefined + */ + readonly output?: string; + + /** + * Show relevant notices + * + * @default - undefined + */ + readonly notices?: boolean; + + /** + * Removes colors and other style from console output + * + * @default - false + */ + readonly 'no-color'?: boolean; + + /** + * Force CI detection. If CI=true then logs will be sent to stdout instead of stderr + * + * @default - undefined + */ + readonly ci?: boolean; + + /** + * Opt in to unstable features. The flag indicates that the scope and API of a feature might still change. Otherwise the feature is generally production ready and fully supported. Can be specified multiple times. + * + * @default - undefined + */ + readonly unstable?: Array; +} + +/** + * Lists all stacks in the app + * + * aliases: ls + * + * @struct + */ +export interface ListOptions { + /** + * Display environment information for each stack + * + * aliases: l + * + * @default - false + */ + readonly long?: boolean; + + /** + * Display stack dependency information for each stack + * + * aliases: d + * + * @default - false + */ + readonly 'show-dependencies'?: boolean; +} + +/** + * Synthesizes and prints the CloudFormation template for this stack + * + * aliases: synth + * + * @struct + */ +export interface SynthesizeOptions { + /** + * Only synthesize requested stacks, don't include dependencies + * + * aliases: e + * + * @default - undefined + */ + readonly exclusively?: boolean; + + /** + * After synthesis, validate stacks with the "validateOnSynth" attribute set (can also be controlled with CDK_VALIDATION) + * + * @default - true + */ + readonly validation?: boolean; + + /** + * Do not output CloudFormation Template to stdout + * + * aliases: q + * + * @default - false + */ + readonly quiet?: boolean; +} + +/** + * Deploys the CDK toolkit stack into an AWS environment + * + * @struct + */ +export interface BootstrapOptions { + /** + * The name of the CDK toolkit bucket; bucket will be created and must not exist + * + * aliases: b toolkit-bucket-name + * + * @default - undefined + */ + readonly 'bootstrap-bucket-name'?: string; + + /** + * AWS KMS master key ID used for the SSE-KMS encryption + * + * @default - undefined + */ + readonly 'bootstrap-kms-key-id'?: string; + + /** + * Use the example permissions boundary. + * + * aliases: epb + * + * @default - undefined + */ + readonly 'example-permissions-boundary'?: boolean; + + /** + * Use the permissions boundary specified by name. + * + * aliases: cpb + * + * @default - undefined + */ + readonly 'custom-permissions-boundary'?: string; + + /** + * Create a Customer Master Key (CMK) for the bootstrap bucket (you will be charged but can customize permissions, modern bootstrapping only) + * + * @default - undefined + */ + readonly 'bootstrap-customer-key'?: boolean; + + /** + * String which must be unique for each bootstrap stack. You must configure it on your CDK app if you change this from the default. + * + * @default - undefined + */ + readonly qualifier?: string; + + /** + * Block public access configuration on CDK toolkit bucket (enabled by default) + * + * @default - undefined + */ + readonly 'public-access-block-configuration'?: boolean; + + /** + * Tags to add for the stack (KEY=VALUE) + * + * aliases: t + * + * @default - undefined + */ + readonly tags?: Array; + + /** + * Whether to execute ChangeSet (--no-execute will NOT execute the ChangeSet) + * + * @default - true + */ + readonly execute?: boolean; + + /** + * The AWS account IDs that should be trusted to perform deployments into this environment (may be repeated, modern bootstrapping only) + * + * @default - undefined + */ + readonly trust?: Array; + + /** + * The AWS account IDs that should be trusted to look up values in this environment (may be repeated, modern bootstrapping only) + * + * @default - undefined + */ + readonly 'trust-for-lookup'?: Array; + + /** + * The Managed Policy ARNs that should be attached to the role performing deployments into this environment (may be repeated, modern bootstrapping only) + * + * @default - undefined + */ + readonly 'cloudformation-execution-policies'?: Array; + + /** + * Always bootstrap even if it would downgrade template version + * + * aliases: f + * + * @default - false + */ + readonly force?: boolean; + + /** + * Toggle CloudFormation termination protection on the bootstrap stacks + * + * @default - undefined + */ + readonly 'termination-protection'?: boolean; + + /** + * Instead of actual bootstrapping, print the current CLI's bootstrapping template to stdout for customization + * + * @default - false + */ + readonly 'show-template'?: boolean; + + /** + * The name of the CDK toolkit stack to create + * + * @default - undefined + */ + readonly 'toolkit-stack-name'?: string; + + /** + * Use the template from the given file instead of the built-in one (use --show-template to obtain an example) + * + * @default - undefined + */ + readonly template?: string; + + /** + * Use previous values for existing parameters (you must specify all parameters on every deployment if this is disabled) + * + * @default - true + */ + readonly 'previous-parameters'?: boolean; +} + +/** + * Garbage collect assets. Options detailed here: https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk/README.md#cdk-gc + * + * @struct + */ +export interface GcOptions { + /** + * The action (or sub-action) you want to perform. Valid entires are "print", "tag", "delete-tagged", "full". + * + * @default - full + */ + readonly action?: string; + + /** + * Specify either ecr, s3, or all + * + * @default - all + */ + readonly type?: string; + + /** + * Delete assets that have been marked as isolated for this many days + * + * @default - undefined + */ + readonly 'rollback-buffer-days'?: number; + + /** + * Never delete assets younger than this (in days) + * + * @default - undefined + */ + readonly 'created-buffer-days'?: number; + + /** + * Confirm via manual prompt before deletion + * + * @default - true + */ + readonly confirm?: boolean; + + /** + * The name of the CDK toolkit stack, if different from the default "CDKToolkit" + * + * @default - undefined + */ + readonly 'bootstrap-stack-name'?: string; +} + +/** + * Deploys the stack(s) named STACKS into your AWS account + * + * @struct + */ +export interface DeployOptions { + /** + * Deploy all available stacks + * + * @default - false + */ + readonly all?: boolean; + + /** + * Do not rebuild asset with the given ID. Can be specified multiple times + * + * aliases: E + * + * @default - undefined + */ + readonly 'build-exclude'?: Array; + + /** + * Only deploy requested stacks, don't include dependencies + * + * aliases: e + * + * @default - undefined + */ + readonly exclusively?: boolean; + + /** + * What security-sensitive changes need manual approval + * + * @default - undefined + */ + readonly 'require-approval'?: string; + + /** + * ARNs of SNS topics that CloudFormation will notify with stack related events. These will be added to ARNs specified with the 'notificationArns' stack property. + * + * @default - undefined + */ + readonly 'notification-arns'?: Array; + + /** + * Tags to add to the stack (KEY=VALUE), overrides tags from Cloud Assembly (deprecated) + * + * aliases: t + * + * @default - undefined + */ + readonly tags?: Array; + + /** + * Whether to execute ChangeSet (--no-execute will NOT execute the ChangeSet) (deprecated) + * + * @deprecated true + * @default - undefined + */ + readonly execute?: boolean; + + /** + * Name of the CloudFormation change set to create (only if method is not direct) + * + * @default - undefined + */ + readonly 'change-set-name'?: string; + + /** + * How to perform the deployment. Direct is a bit faster but lacks progress information + * + * aliases: m + * + * @default - undefined + */ + readonly method?: string; + + /** + * Always deploy stack even if templates are identical + * + * aliases: f + * + * @default - false + */ + readonly force?: boolean; + + /** + * Additional parameters passed to CloudFormation at deploy time (STACK:KEY=VALUE) + * + * @default - undefined + */ + readonly parameters?: Array; + + /** + * Path to file where stack outputs will be written as JSON + * + * aliases: O + * + * @default - undefined + */ + readonly 'outputs-file'?: string; + + /** + * Use previous values for existing parameters (you must specify all parameters on every deployment if this is disabled) + * + * @default - true + */ + readonly 'previous-parameters'?: boolean; + + /** + * The name of the existing CDK toolkit stack (only used for app using legacy synthesis) + * + * @default - undefined + */ + readonly 'toolkit-stack-name'?: string; + + /** + * Display mode for stack activity events + * + * @default - undefined + */ + readonly progress?: string; + + /** + * Rollback stack to stable state on failure. Defaults to 'true', iterate more rapidly with --no-rollback or -R. Note: do **not** disable this flag for deployments with resource replacements, as that will always fail + * + * @default - undefined + */ + readonly rollback?: boolean; + + /** + * Attempts to perform a 'hotswap' deployment, but does not fall back to a full deployment if that is not possible. Instead, changes to any non-hotswappable properties are ignored.Do not use this in production environments + * + * @default - undefined + */ + readonly hotswap?: boolean; + + /** + * Attempts to perform a 'hotswap' deployment, which skips CloudFormation and updates the resources directly, and falls back to a full deployment if that is not possible. Do not use this in production environments + * + * @default - undefined + */ + readonly 'hotswap-fallback'?: boolean; + + /** + * Continuously observe the project files, and deploy the given stack(s) automatically when changes are detected. Implies --hotswap by default + * + * @default - undefined + */ + readonly watch?: boolean; + + /** + * Show CloudWatch log events from all resources in the selected Stacks in the terminal. 'true' by default, use --no-logs to turn off. Only in effect if specified alongside the '--watch' option + * + * @default - true + */ + readonly logs?: boolean; + + /** + * Maximum number of simultaneous deployments (dependency permitting) to execute. + * + * @default - undefined + */ + readonly concurrency?: number; + + /** + * Whether to build/publish assets in parallel + * + * @default - undefined + */ + readonly 'asset-parallelism'?: boolean; + + /** + * Whether to build all assets before deploying the first stack (useful for failing Docker builds) + * + * @default - true + */ + readonly 'asset-prebuild'?: boolean; + + /** + * Whether to deploy if the app contains no stacks + * + * @default - false + */ + readonly 'ignore-no-stacks'?: boolean; +} + +/** + * Rolls back the stack(s) named STACKS to their last stable state + * + * @struct + */ +export interface RollbackOptions { + /** + * Roll back all available stacks + * + * @default - false + */ + readonly all?: boolean; + + /** + * The name of the CDK toolkit stack the environment is bootstrapped with + * + * @default - undefined + */ + readonly 'toolkit-stack-name'?: string; + + /** + * Orphan all resources for which the rollback operation fails. + * + * aliases: f + * + * @default - undefined + */ + readonly force?: boolean; + + /** + * Whether to validate the bootstrap stack version. Defaults to 'true', disable with --no-validate-bootstrap-version. + * + * @default - undefined + */ + readonly 'validate-bootstrap-version'?: boolean; + + /** + * Orphan the given resources, identified by their logical ID (can be specified multiple times) + * + * @default - undefined + */ + readonly orphan?: Array; +} + +/** + * Import existing resource(s) into the given STACK + * + * @struct + */ +export interface ImportOptions { + /** + * Whether to execute ChangeSet (--no-execute will NOT execute the ChangeSet) + * + * @default - true + */ + readonly execute?: boolean; + + /** + * Name of the CloudFormation change set to create + * + * @default - undefined + */ + readonly 'change-set-name'?: string; + + /** + * The name of the CDK toolkit stack to create + * + * @default - undefined + */ + readonly 'toolkit-stack-name'?: string; + + /** + * Rollback stack to stable state on failure. Defaults to 'true', iterate more rapidly with --no-rollback or -R. Note: do **not** disable this flag for deployments with resource replacements, as that will always fail + * + * @default - undefined + */ + readonly rollback?: boolean; + + /** + * Do not abort if the template diff includes updates or deletes. This is probably safe but we're not sure, let us know how it goes. + * + * aliases: f + * + * @default - undefined + */ + readonly force?: boolean; + + /** + * If specified, CDK will generate a mapping of existing physical resources to CDK resources to be imported as. The mapping will be written in the given file path. No actual import operation will be performed + * + * aliases: r + * + * @default - undefined + */ + readonly 'record-resource-mapping'?: string; + + /** + * If specified, CDK will use the given file to map physical resources to CDK resources for import, instead of interactively asking the user. Can be run from scripts + * + * aliases: m + * + * @default - undefined + */ + readonly 'resource-mapping'?: string; +} + +/** + * Shortcut for 'deploy --watch' + * + * @struct + */ +export interface WatchOptions { + /** + * Do not rebuild asset with the given ID. Can be specified multiple times + * + * aliases: E + * + * @default - undefined + */ + readonly 'build-exclude'?: Array; + + /** + * Only deploy requested stacks, don't include dependencies + * + * aliases: e + * + * @default - undefined + */ + readonly exclusively?: boolean; + + /** + * Name of the CloudFormation change set to create + * + * @default - undefined + */ + readonly 'change-set-name'?: string; + + /** + * Always deploy stack even if templates are identical + * + * aliases: f + * + * @default - false + */ + readonly force?: boolean; + + /** + * The name of the existing CDK toolkit stack (only used for app using legacy synthesis) + * + * @default - undefined + */ + readonly 'toolkit-stack-name'?: string; + + /** + * Display mode for stack activity events + * + * @default - undefined + */ + readonly progress?: string; + + /** + * Rollback stack to stable state on failure. Defaults to 'true', iterate more rapidly with --no-rollback or -R. Note: do **not** disable this flag for deployments with resource replacements, as that will always fail + * + * @default - undefined + */ + readonly rollback?: boolean; + + /** + * Attempts to perform a 'hotswap' deployment, but does not fall back to a full deployment if that is not possible. Instead, changes to any non-hotswappable properties are ignored.'true' by default, use --no-hotswap to turn off + * + * @default - undefined + */ + readonly hotswap?: boolean; + + /** + * Attempts to perform a 'hotswap' deployment, which skips CloudFormation and updates the resources directly, and falls back to a full deployment if that is not possible. + * + * @default - undefined + */ + readonly 'hotswap-fallback'?: boolean; + + /** + * Show CloudWatch log events from all resources in the selected Stacks in the terminal. 'true' by default, use --no-logs to turn off + * + * @default - true + */ + readonly logs?: boolean; + + /** + * Maximum number of simultaneous deployments (dependency permitting) to execute. + * + * @default - undefined + */ + readonly concurrency?: number; +} + +/** + * Destroy the stack(s) named STACKS + * + * @struct + */ +export interface DestroyOptions { + /** + * Destroy all available stacks + * + * @default - false + */ + readonly all?: boolean; + + /** + * Only destroy requested stacks, don't include dependees + * + * aliases: e + * + * @default - undefined + */ + readonly exclusively?: boolean; + + /** + * Do not ask for confirmation before destroying the stacks + * + * aliases: f + * + * @default - undefined + */ + readonly force?: boolean; +} + +/** + * Compares the specified stack with the deployed stack or a local template file, and returns with status 1 if any difference is found + * + * @struct + */ +export interface DiffOptions { + /** + * Only diff requested stacks, don't include dependencies + * + * aliases: e + * + * @default - undefined + */ + readonly exclusively?: boolean; + + /** + * Number of context lines to include in arbitrary JSON diff rendering + * + * @default - undefined + */ + readonly 'context-lines'?: number; + + /** + * The path to the CloudFormation template to compare with + * + * @default - undefined + */ + readonly template?: string; + + /** + * Do not filter out AWS::CDK::Metadata resources, mangled non-ASCII characters, or the CheckBootstrapVersionRule + * + * @default - false + */ + readonly strict?: boolean; + + /** + * Only diff for broadened security changes + * + * @default - false + */ + readonly 'security-only'?: boolean; + + /** + * Fail with exit code 1 in case of diff + * + * @default - undefined + */ + readonly fail?: boolean; + + /** + * Whether to compare against the template with Transforms already processed + * + * @default - false + */ + readonly processed?: boolean; + + /** + * Do not print stack name and default message when there is no diff to stdout + * + * aliases: q + * + * @default - false + */ + readonly quiet?: boolean; + + /** + * Whether to create a changeset to analyze resource replacements. In this mode, diff will use the deploy role instead of the lookup role. + * + * aliases: changeset + * + * @default - true + */ + readonly 'change-set'?: boolean; +} + +/** + * Returns all metadata associated with this stack + * + * @struct + */ +export interface MetadataOptions {} + +/** + * Acknowledge a notice so that it does not show up anymore + * + * aliases: ack + * + * @struct + */ +export interface AcknowledgeOptions {} + +/** + * Returns a list of relevant notices + * + * @struct + */ +export interface NoticesOptions { + /** + * Returns a list of unacknowledged notices + * + * aliases: u + * + * @default - false + */ + readonly unacknowledged?: boolean; +} + +/** + * Create a new, empty CDK project from a template. + * + * @struct + */ +export interface InitOptions { + /** + * The language to be used for the new project (default can be configured in ~/.cdk.json) + * + * aliases: l + * + * @default - undefined + */ + readonly language?: string; + + /** + * List the available templates + * + * @default - undefined + */ + readonly list?: boolean; + + /** + * If true, only generates project files, without executing additional operations such as setting up a git repo, installing dependencies or compiling the project + * + * @default - false + */ + readonly 'generate-only'?: boolean; +} + +/** + * Migrate existing AWS resources into a CDK app + * + * @struct + */ +export interface MigrateOptions { + /** + * The name assigned to the stack created in the new project. The name of the app will be based off this name as well. + * + * aliases: n + * + * @default - undefined + */ + readonly 'stack-name'?: string; + + /** + * The language to be used for the new project + * + * aliases: l + * + * @default - typescript + */ + readonly language?: string; + + /** + * The account to retrieve the CloudFormation stack template from + * + * @default - undefined + */ + readonly account?: string; + + /** + * The region to retrieve the CloudFormation stack template from + * + * @default - undefined + */ + readonly region?: string; + + /** + * The path to the CloudFormation template to migrate. Use this for locally stored templates + * + * @default - undefined + */ + readonly 'from-path'?: string; + + /** + * Use this flag to retrieve the template for an existing CloudFormation stack + * + * @default - undefined + */ + readonly 'from-stack'?: boolean; + + /** + * The output path for the migrated CDK app + * + * @default - undefined + */ + readonly 'output-path'?: string; + + /** + * Determines if a new scan should be created, or the last successful existing scan should be used + * options are "new" or "most-recent" + * + * @default - undefined + */ + readonly 'from-scan'?: string; + + /** + * Filters the resource scan based on the provided criteria in the following format: "key1=value1,key2=value2" + * This field can be passed multiple times for OR style filtering: + * filtering options: + * resource-identifier: A key-value pair that identifies the target resource. i.e. {"ClusterName", "myCluster"} + * resource-type-prefix: A string that represents a type-name prefix. i.e. "AWS::DynamoDB::" + * tag-key: a string that matches resources with at least one tag with the provided key. i.e. "myTagKey" + * tag-value: a string that matches resources with at least one tag with the provided value. i.e. "myTagValue" + * + * @default - undefined + */ + readonly filter?: Array; + + /** + * Use this flag to zip the generated CDK app + * + * @default - undefined + */ + readonly compress?: boolean; +} + +/** + * Manage cached context values + * + * @struct + */ +export interface ContextOptions { + /** + * The context key (or its index) to reset + * + * aliases: e + * + * @default - undefined + */ + readonly reset?: string; + + /** + * Ignore missing key error + * + * aliases: f + * + * @default - false + */ + readonly force?: boolean; + + /** + * Clear all context + * + * @default - undefined + */ + readonly clear?: boolean; +} + +/** + * Opens the reference documentation in a browser + * + * aliases: doc + * + * @struct + */ +export interface DocsOptions { + /** + * the command to use to open the browser, using %u as a placeholder for the path of the file to open + * + * aliases: b + * + * @default - undefined + */ + readonly browser?: string; +} + +/** + * Check your set-up for potential problems + * + * @struct + */ +export interface DoctorOptions {} diff --git a/packages/aws-cdk/lib/config.ts b/packages/aws-cdk/lib/config.ts index f7aaf8d6bc013..d4c46936f990d 100644 --- a/packages/aws-cdk/lib/config.ts +++ b/packages/aws-cdk/lib/config.ts @@ -1,5 +1,5 @@ // eslint-disable-next-line import/no-extraneous-dependencies -import { CliHelpers, type CliConfig } from '@aws-cdk/yargs-gen'; +import { CliHelpers, type CliConfig } from '@aws-cdk/cli-args-gen'; import { StackActivityProgress } from './api/util/cloudformation/stack-activity-monitor'; import { MIGRATE_SUPPORTED_LANGUAGES } from './commands/migrate'; import { RequireApproval } from './diff'; @@ -8,7 +8,7 @@ import { availableInitLanguages } from './init'; export const YARGS_HELPERS = new CliHelpers('./util/yargs-helpers'); /** - * Source of truth for all CDK CLI commands. `yargs-gen` translates this into the `yargs` definition + * Source of truth for all CDK CLI commands. `cli-args-gen` translates this into the `yargs` definition * in `lib/parse-command-line-arguments.ts`. */ export async function makeConfig(): Promise { @@ -343,7 +343,7 @@ export async function makeConfig(): Promise { }, }, migrate: { - description: false as any, + description: 'Migrate existing AWS resources into a CDK app', options: { 'stack-name': { type: 'string', alias: 'n', desc: 'The name assigned to the stack created in the new project. The name of the app will be based off this name as well.', requiresArg: true }, 'language': { type: 'string', default: 'typescript', alias: 'l', desc: 'The language to be used for the new project', choices: MIGRATE_SUPPORTED_LANGUAGES }, diff --git a/packages/aws-cdk/lib/parse-command-line-arguments.ts b/packages/aws-cdk/lib/parse-command-line-arguments.ts index d5b4b9308a1d9..2432fa23ba3c8 100644 --- a/packages/aws-cdk/lib/parse-command-line-arguments.ts +++ b/packages/aws-cdk/lib/parse-command-line-arguments.ts @@ -685,7 +685,7 @@ export function parseCommandLineArguments(args: Array): any { desc: 'If true, only generates project files, without executing additional operations such as setting up a git repo, installing dependencies or compiling the project', }) ) - .command('migrate', false, (yargs: Argv) => + .command('migrate', 'Migrate existing AWS resources into a CDK app', (yargs: Argv) => yargs .option('stack-name', { type: 'string', diff --git a/packages/aws-cdk/package.json b/packages/aws-cdk/package.json index c60fb2eae4e73..589a3563f1791 100644 --- a/packages/aws-cdk/package.json +++ b/packages/aws-cdk/package.json @@ -7,7 +7,7 @@ }, "scripts": { "build": "cdk-build", - "yargs-gen": "ts-node --preferTsExts scripts/yargs-gen.ts", + "cli-args-gen": "ts-node --preferTsExts scripts/cli-args-gen.ts", "watch": "cdk-watch", "lint": "cdk-lint", "pkglint": "pkglint -f", @@ -29,7 +29,7 @@ }, "cdk-build": { "pre": [ - "yarn yargs-gen" + "yarn cli-args-gen" ], "post": [ "cp ../../node_modules/cdk-from-cfn/index_bg.wasm ./lib/", @@ -69,7 +69,7 @@ "devDependencies": { "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@aws-cdk/yargs-gen": "0.0.0", + "@aws-cdk/cli-args-gen": "0.0.0", "@octokit/rest": "^18.12.0", "@types/archiver": "^5.3.4", "@types/fs-extra": "^9.0.13", diff --git a/packages/aws-cdk/scripts/cli-args-gen b/packages/aws-cdk/scripts/cli-args-gen new file mode 100755 index 0000000000000..29484fb39cf9f --- /dev/null +++ b/packages/aws-cdk/scripts/cli-args-gen @@ -0,0 +1,2 @@ +#!/usr/bin/env node +require('./cli-args-gen.js'); diff --git a/packages/aws-cdk/scripts/yargs-gen.ts b/packages/aws-cdk/scripts/cli-args-gen.ts similarity index 68% rename from packages/aws-cdk/scripts/yargs-gen.ts rename to packages/aws-cdk/scripts/cli-args-gen.ts index 89556720063ba..cde589928e1a4 100644 --- a/packages/aws-cdk/scripts/yargs-gen.ts +++ b/packages/aws-cdk/scripts/cli-args-gen.ts @@ -1,10 +1,11 @@ import * as fs from 'fs'; // eslint-disable-next-line import/no-extraneous-dependencies -import { renderYargs } from '@aws-cdk/yargs-gen'; +import { renderYargs, renderCliType } from '@aws-cdk/cli-args-gen'; import { makeConfig, YARGS_HELPERS } from '../lib/config'; async function main() { fs.writeFileSync('./lib/parse-command-line-arguments.ts', await renderYargs(await makeConfig(), YARGS_HELPERS)); + fs.writeFileSync('./lib/cli-arguments.ts', await renderCliType(await makeConfig())); } main().then(() => { diff --git a/packages/aws-cdk/scripts/yargs-gen b/packages/aws-cdk/scripts/yargs-gen deleted file mode 100755 index 45571b6423707..0000000000000 --- a/packages/aws-cdk/scripts/yargs-gen +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env node -require('./yargs-gen.js'); diff --git a/tools/@aws-cdk/yargs-gen/.eslintrc.js b/tools/@aws-cdk/cli-args-gen/.eslintrc.js similarity index 100% rename from tools/@aws-cdk/yargs-gen/.eslintrc.js rename to tools/@aws-cdk/cli-args-gen/.eslintrc.js diff --git a/tools/@aws-cdk/yargs-gen/.gitignore b/tools/@aws-cdk/cli-args-gen/.gitignore similarity index 100% rename from tools/@aws-cdk/yargs-gen/.gitignore rename to tools/@aws-cdk/cli-args-gen/.gitignore diff --git a/tools/@aws-cdk/yargs-gen/.npmignore b/tools/@aws-cdk/cli-args-gen/.npmignore similarity index 100% rename from tools/@aws-cdk/yargs-gen/.npmignore rename to tools/@aws-cdk/cli-args-gen/.npmignore diff --git a/tools/@aws-cdk/yargs-gen/LICENSE b/tools/@aws-cdk/cli-args-gen/LICENSE similarity index 100% rename from tools/@aws-cdk/yargs-gen/LICENSE rename to tools/@aws-cdk/cli-args-gen/LICENSE diff --git a/tools/@aws-cdk/yargs-gen/NOTICE b/tools/@aws-cdk/cli-args-gen/NOTICE similarity index 100% rename from tools/@aws-cdk/yargs-gen/NOTICE rename to tools/@aws-cdk/cli-args-gen/NOTICE diff --git a/tools/@aws-cdk/yargs-gen/README.md b/tools/@aws-cdk/cli-args-gen/README.md similarity index 64% rename from tools/@aws-cdk/yargs-gen/README.md rename to tools/@aws-cdk/cli-args-gen/README.md index 224b207afb367..d3a6396495bf8 100644 --- a/tools/@aws-cdk/yargs-gen/README.md +++ b/tools/@aws-cdk/cli-args-gen/README.md @@ -1,11 +1,13 @@ -# yargs-gen +# cli-args-gen -Generates CDK CLI `yargs` configuration from the source of truth in `packages/aws-cdk/lib/config.ts` +Generates CDK CLI configurations from the source of truth in `packages/aws-cdk/lib/config.ts`. +Currently generates `yargs` config into `packages/aws-cdk/lib/parse-command-line-arguments.ts` and +strongly-typed CLI arguments interface into `packages/aws-cdk-lib/cli-arguments.ts`. ## Usage ```ts -import { renderYargs } from '@aws-cdk/yargs-gen'; +import { renderYargs } from '@aws-cdk/cli-args-gen'; declare const config: CliConfig; diff --git a/tools/@aws-cdk/yargs-gen/jest.config.js b/tools/@aws-cdk/cli-args-gen/jest.config.js similarity index 100% rename from tools/@aws-cdk/yargs-gen/jest.config.js rename to tools/@aws-cdk/cli-args-gen/jest.config.js diff --git a/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts b/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts new file mode 100644 index 0000000000000..7c92fd8c65fd4 --- /dev/null +++ b/tools/@aws-cdk/cli-args-gen/lib/cli-type-gen.ts @@ -0,0 +1,137 @@ +import { Module, SelectiveModuleImport, StructType, Type, TypeScriptRenderer } from '@cdklabs/typewriter'; +import { EsLintRules } from '@cdklabs/typewriter/lib/eslint-rules'; +import * as prettier from 'prettier'; +import { CliConfig } from './yargs-types'; + +export async function renderCliType(config: CliConfig): Promise { + const scope = new Module('aws-cdk'); + + scope.documentation.push( '-------------------------------------------------------------------------------------------'); + scope.documentation.push('GENERATED FROM packages/aws-cdk/lib/config.ts.'); + scope.documentation.push('Do not edit by hand; all changes will be overwritten at build time from the config file.'); + scope.documentation.push('-------------------------------------------------------------------------------------------'); + + const cliArgType = new StructType(scope, { + export: true, + name: 'CliArguments', + docs: { + summary: 'The structure of the CLI configuration, generated from packages/aws-cdk/lib/config.ts', + }, + }); + + // add required command + scope.addImport(new SelectiveModuleImport(scope, './settings', ['Command'])); + const commandEnum = Type.fromName(scope, 'Command'); + + cliArgType.addProperty({ + name: '_', + type: Type.ambient(`[${commandEnum}, ...string[]]`), + docs: { + summary: 'The CLI command name followed by any properties of the command', + }, + }); + + // add global options + const globalOptionType = new StructType(scope, { + export: true, + name: 'GlobalOptions', + docs: { + summary: 'Global options available to all CLI commands', + }, + }); + for (const [optionName, option] of Object.entries(config.globalOptions)) { + globalOptionType.addProperty({ + name: optionName, + type: convertType(option.type), + docs: { + default: normalizeDefault(option.default), + summary: option.desc, + deprecated: option.deprecated ? String(option.deprecated) : undefined, + }, + optional: true, + }); + } + cliArgType.addProperty({ + name: 'globalOptions', + type: Type.fromName(scope, globalOptionType.name), + docs: { + summary: 'Global options available to all CLI commands', + }, + optional: true, + }); + + // add command-specific options + for (const [commandName, command] of Object.entries(config.commands)) { + const commandType = new StructType(scope, { + export: true, + name: `${kebabToPascal(commandName)}Options`, + docs: { + summary: command.description, + remarks: command.aliases ? `aliases: ${command.aliases.join(' ')}` : undefined, + }, + }); + + for (const [optionName, option] of Object.entries(command.options ?? {})) { + commandType.addProperty({ + name: optionName, + type: convertType(option.type), + docs: { + default: normalizeDefault(option.default), + summary: option.desc, + deprecated: option.deprecated ? String(option.deprecated) : undefined, + remarks: option.alias ? `aliases: ${Array.isArray(option.alias) ? option.alias.join(' ') : option.alias}` : undefined, + }, + optional: true, + }); + } + + cliArgType.addProperty({ + name: commandName, + type: Type.fromName(scope, commandType.name), + docs: { + summary: command.description, + remarks: command.aliases ? `aliases: ${command.aliases.join(' ')}` : undefined, + }, + optional: true, + }); + } + + const ts = new TypeScriptRenderer({ + disabledEsLintRules: [EsLintRules.MAX_LEN], // the default disabled rules result in 'Definition for rule 'prettier/prettier' was not found' + }).render(scope); + + return prettier.format(ts, { + parser: 'typescript', + printWidth: 150, + singleQuote: true, + }); +} + +function convertType(type: 'string' | 'array' | 'number' | 'boolean' | 'count'): Type { + switch (type) { + case 'boolean': + return Type.BOOLEAN; + case 'string': + return Type.STRING; + case 'number': + return Type.NUMBER; + case 'array': + return Type.arrayOf(Type.STRING); + case 'count': + return Type.NUMBER; + } +} + +function kebabToPascal(str: string): string { + return str + .split('-') + .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) + .join(''); +} + +function normalizeDefault(defaultValue: any): string { + if (typeof defaultValue === 'boolean' || typeof defaultValue === 'string') { + return String(defaultValue); + } + return 'undefined'; +} diff --git a/tools/@aws-cdk/yargs-gen/lib/index.ts b/tools/@aws-cdk/cli-args-gen/lib/index.ts similarity index 65% rename from tools/@aws-cdk/yargs-gen/lib/index.ts rename to tools/@aws-cdk/cli-args-gen/lib/index.ts index 9e1623713b0a3..7b8f3eea63ace 100644 --- a/tools/@aws-cdk/yargs-gen/lib/index.ts +++ b/tools/@aws-cdk/cli-args-gen/lib/index.ts @@ -1,2 +1,3 @@ export * from './yargs-gen'; export * from './yargs-types'; +export * from './cli-type-gen'; diff --git a/tools/@aws-cdk/yargs-gen/lib/yargs-gen.ts b/tools/@aws-cdk/cli-args-gen/lib/yargs-gen.ts similarity index 100% rename from tools/@aws-cdk/yargs-gen/lib/yargs-gen.ts rename to tools/@aws-cdk/cli-args-gen/lib/yargs-gen.ts diff --git a/tools/@aws-cdk/yargs-gen/lib/yargs-types.ts b/tools/@aws-cdk/cli-args-gen/lib/yargs-types.ts similarity index 100% rename from tools/@aws-cdk/yargs-gen/lib/yargs-types.ts rename to tools/@aws-cdk/cli-args-gen/lib/yargs-types.ts diff --git a/tools/@aws-cdk/yargs-gen/package.json b/tools/@aws-cdk/cli-args-gen/package.json similarity index 90% rename from tools/@aws-cdk/yargs-gen/package.json rename to tools/@aws-cdk/cli-args-gen/package.json index 31aec381b0c3a..b290bfc3b7fcd 100644 --- a/tools/@aws-cdk/yargs-gen/package.json +++ b/tools/@aws-cdk/cli-args-gen/package.json @@ -1,12 +1,12 @@ { - "name": "@aws-cdk/yargs-gen", + "name": "@aws-cdk/cli-args-gen", "private": true, "version": "0.0.0", - "description": "Generate yargs", + "description": "Generate CLI arguments", "repository": { "type": "git", "url": "https://github.com/aws/aws-cdk.git", - "directory": "tools/@aws-cdk/yargs-gen" + "directory": "tools/@aws-cdk/cli-args-gen" }, "main": "./lib/index.js", "types": "./lib/index.d.ts", diff --git a/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts b/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts new file mode 100644 index 0000000000000..c3719aa4b9149 --- /dev/null +++ b/tools/@aws-cdk/cli-args-gen/test/cli-type-gen.test.ts @@ -0,0 +1,98 @@ +import { CliConfig, renderCliType } from '../lib'; + +describe('render', () => { + test('can generate CliArguments type', async () => { + const config: CliConfig = { + globalOptions: { + app: { + type: 'string', + desc: 'REQUIRED: Command-line for executing your app', + }, + debug: { + type: 'boolean', + desc: 'Enable debug logging', + default: false, + }, + }, + commands: { + deploy: { + description: 'Deploy a stack', + options: { + all: { + type: 'boolean', + desc: 'Deploy all stacks', + default: false, + }, + }, + }, + }, + }; + + expect(await renderCliType(config)).toMatchInlineSnapshot(` + "// ------------------------------------------------------------------------------------------- + // GENERATED FROM packages/aws-cdk/lib/config.ts. + // Do not edit by hand; all changes will be overwritten at build time from the config file. + // ------------------------------------------------------------------------------------------- + /* eslint-disable max-len */ + import { Command } from './settings'; + + /** + * The structure of the CLI configuration, generated from packages/aws-cdk/lib/config.ts + * + * @struct + */ + export interface CliArguments { + /** + * The CLI command name followed by any properties of the command + */ + readonly _: [Command, ...string[]]; + + /** + * Global options available to all CLI commands + */ + readonly globalOptions?: GlobalOptions; + + /** + * Deploy a stack + */ + readonly deploy?: DeployOptions; + } + + /** + * Global options available to all CLI commands + * + * @struct + */ + export interface GlobalOptions { + /** + * REQUIRED: Command-line for executing your app + * + * @default - undefined + */ + readonly app?: string; + + /** + * Enable debug logging + * + * @default - false + */ + readonly debug?: boolean; + } + + /** + * Deploy a stack + * + * @struct + */ + export interface DeployOptions { + /** + * Deploy all stacks + * + * @default - false + */ + readonly all?: boolean; + } + " + `); + }); +}); diff --git a/tools/@aws-cdk/yargs-gen/test/cli.test.ts b/tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts similarity index 100% rename from tools/@aws-cdk/yargs-gen/test/cli.test.ts rename to tools/@aws-cdk/cli-args-gen/test/yargs-gen.test.ts diff --git a/tools/@aws-cdk/yargs-gen/tsconfig.json b/tools/@aws-cdk/cli-args-gen/tsconfig.json similarity index 100% rename from tools/@aws-cdk/yargs-gen/tsconfig.json rename to tools/@aws-cdk/cli-args-gen/tsconfig.json