Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { integTest, withoutBootstrap } from '../../../lib';

integTest('bootstrap can re-bootstrap after stack deletion', withoutBootstrap(async (fixture) => {
const bootstrapStackName = fixture.bootstrapStackName;

// Bootstrap the environment
await fixture.cdkBootstrapModern({
toolkitStackName: bootstrapStackName,
cfnExecutionPolicy: 'arn:aws:iam::aws:policy/AdministratorAccess',
});

// Delete the bootstrap stack (resources like the S3 bucket will be retained)
await fixture.aws.deleteStacks(bootstrapStackName);

// Re-bootstrap should succeed because importExistingResources is enabled,
// allowing the change set to import the retained resources back into the stack.
await fixture.cdkBootstrapModern({
toolkitStackName: bootstrapStackName,
cfnExecutionPolicy: 'arn:aws:iam::aws:policy/AdministratorAccess',
});
}));
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ export interface BootstrapEnvironmentOptions {
* @default true
*/
usePreviousParameters?: boolean;

/**
* Whether to import existing resources into the stack instead of failing
* when they already exist.
*
* @default true
*/
readonly importExistingResources?: boolean;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,11 @@ export class BootstrapStack {
forceDeployment: options.forceDeployment,
roleArn: options.roleArn,
tags: options.tags,
deploymentMethod: { method: 'change-set', execute: options.execute },
deploymentMethod: {
method: 'change-set',
execute: options.execute,
importExistingResources: options.importExistingResources ?? true,
},
parameters,
usePreviousParameters: options.usePreviousParameters ?? true,
// Obviously we can't need a bootstrap stack to deploy a bootstrap stack
Expand Down
1 change: 1 addition & 0 deletions packages/aws-cdk/lib/cli/cli-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ export async function makeConfig(): Promise<CliConfig> {
'toolkit-stack-name': { type: 'string', desc: 'The name of the CDK toolkit stack to create', requiresArg: true },
'template': { type: 'string', requiresArg: true, desc: 'Use the template from the given file instead of the built-in one (use --show-template to obtain an example)' },
'previous-parameters': { type: 'boolean', default: true, desc: 'Use previous values for existing parameters (you must specify all parameters on every deployment if this is disabled)' },
'import-existing-resources': { type: 'boolean', desc: 'Whether to import existing resources into the bootstrap stack instead of failing if they already exist', default: true },
},
},
'gc': {
Expand Down
5 changes: 5 additions & 0 deletions packages/aws-cdk/lib/cli/cli-type-registry.json
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,11 @@
"type": "boolean",
"default": true,
"desc": "Use previous values for existing parameters (you must specify all parameters on every deployment if this is disabled)"
},
"import-existing-resources": {
"type": "boolean",
"desc": "Whether to import existing resources into the bootstrap stack instead of failing if they already exist",
"default": true
}
}
},
Expand Down
1 change: 1 addition & 0 deletions packages/aws-cdk/lib/cli/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ export async function exec(args: string[], synthesizer?: Synthesizer): Promise<n
tags: configuration.settings.get(['tags']),
terminationProtection: args.terminationProtection,
usePreviousParameters: args['previous-parameters'],
importExistingResources: args.importExistingResources,
parameters: {
bucketName: configuration.settings.get(['toolkitBucket', 'bucketName']),
kmsKeyId: configuration.settings.get(['toolkitBucket', 'kmsKeyId']),
Expand Down
2 changes: 2 additions & 0 deletions packages/aws-cdk/lib/cli/convert-to-user-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export function convertYargsToUserInput(args: any): UserInput {
toolkitStackName: args.toolkitStackName,
template: args.template,
previousParameters: args.previousParameters,
importExistingResources: args.importExistingResources,
ENVIRONMENTS: args.ENVIRONMENTS,
};
break;
Expand Down Expand Up @@ -412,6 +413,7 @@ export function convertConfigToUserInput(config: any): UserInput {
toolkitStackName: config.bootstrap?.toolkitStackName,
template: config.bootstrap?.template,
previousParameters: config.bootstrap?.previousParameters,
importExistingResources: config.bootstrap?.importExistingResources,
};
const gcOptions = {
action: config.gc?.action,
Expand Down
5 changes: 5 additions & 0 deletions packages/aws-cdk/lib/cli/parse-command-line-arguments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,11 @@ export function parseCommandLineArguments(args: Array<string>): any {
default: true,
type: 'boolean',
desc: 'Use previous values for existing parameters (you must specify all parameters on every deployment if this is disabled)',
})
.option('import-existing-resources', {
default: true,
type: 'boolean',
desc: 'Whether to import existing resources into the bootstrap stack instead of failing if they already exist',
}),
)
.command(
Expand Down
7 changes: 7 additions & 0 deletions packages/aws-cdk/lib/cli/user-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,13 @@ export interface BootstrapOptions {
*/
readonly previousParameters?: boolean;

/**
* Whether to import existing resources into the bootstrap stack instead of failing if they already exist
*
* @default - true
*/
readonly importExistingResources?: boolean;

/**
* Positional argument for bootstrap
*/
Expand Down
Loading