Skip to content

Commit

Permalink
feat(cli-lib-alpha): support hotswap deployments (#26786)
Browse files Browse the repository at this point in the history
Closes #26785.

Exemption Request: The `cli-lib-alpha` README does not currently specify the exhaustive list of arguments, which looks like a choice, thus I did not add the new argument. Currently, no integration tests were implemented for this lib, only unit tests which I did update/add.

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
amine-mf committed Sep 18, 2023
1 parent f5a5a08 commit e01faff
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 6 deletions.
14 changes: 13 additions & 1 deletion packages/@aws-cdk/cli-lib-alpha/lib/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { exec as runCli } from 'aws-cdk/lib';
// eslint-disable-next-line import/no-extraneous-dependencies
import { createAssembly, prepareContext, prepareDefaultEnvironment } from 'aws-cdk/lib/api/cxapp/exec';
import { SharedOptions, DeployOptions, DestroyOptions, BootstrapOptions, SynthOptions, ListOptions, StackActivityProgress } from './commands';
import { SharedOptions, DeployOptions, DestroyOptions, BootstrapOptions, SynthOptions, ListOptions, StackActivityProgress, HotswapMode } from './commands';

/**
* AWS CDK CLI operations
Expand Down Expand Up @@ -211,6 +211,7 @@ export class AwsCdkCli implements IAwsCdkCli {
...renderBooleanArg('asset-parallelism', options.assetParallelism),
...renderBooleanArg('asset-prebuild', options.assetPrebuild),
...renderNumberArg('concurrency', options.concurrency),
...renderHotswapArg(options.hotswap),
...options.reuseAssets ? renderArrayArg('--reuse-assets', options.reuseAssets) : [],
...options.notificationArns ? renderArrayArg('--notification-arns', options.notificationArns) : [],
...options.parameters ? renderMapArrayArg('--parameters', options.parameters) : [],
Expand Down Expand Up @@ -267,6 +268,17 @@ export class AwsCdkCli implements IAwsCdkCli {
}
}

function renderHotswapArg(hotswapMode: HotswapMode | undefined): string[] {
switch (hotswapMode) {
case HotswapMode.FALL_BACK:
return ['--hotswap-fallback'];
case HotswapMode.HOTSWAP_ONLY:
return ['--hotswap'];
default:
return [];
}
}

function renderMapArrayArg(flag: string, parameters: { [name: string]: string | undefined }): string[] {
const params: string[] = [];
for (const [key, value] of Object.entries(parameters)) {
Expand Down
26 changes: 26 additions & 0 deletions packages/@aws-cdk/cli-lib-alpha/lib/commands/deploy.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
import { SharedOptions, RequireApproval } from './common';

export enum HotswapMode {
/**
* Will fall back to CloudFormation when a non-hotswappable change is detected
*/
FALL_BACK = 'fall-back',

/**
* Will not fall back to CloudFormation when a non-hotswappable change is detected
*/
HOTSWAP_ONLY = 'hotswap-only',

/**
* Will not attempt to hotswap anything and instead go straight to CloudFormation
*/
FULL_DEPLOYMENT = 'full-deployment',
}

/**
* Options to use with cdk deploy
*/
Expand Down Expand Up @@ -68,6 +85,15 @@ export interface DeployOptions extends SharedOptions {
*/
readonly execute?: boolean;

/*
* Whether to perform a 'hotswap' deployment.
* A 'hotswap' deployment will attempt to short-circuit CloudFormation
* and update the affected resources like Lambda functions directly. Do not use this in production environments
*
* @default - `HotswapMode.FULL_DEPLOYMENT` for regular deployments, `HotswapMode.HOTSWAP_ONLY` for 'watch' deployments
*/
readonly hotswap?: HotswapMode;

/**
* Additional parameters for CloudFormation at deploy time
* @default {}
Expand Down
49 changes: 44 additions & 5 deletions packages/@aws-cdk/cli-lib-alpha/test/commands.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as core from 'aws-cdk-lib/core';
import * as cli from 'aws-cdk/lib';
import { AwsCdkCli } from '../lib';
import { RequireApproval, StackActivityProgress } from '../lib/commands';
import { HotswapMode, RequireApproval, StackActivityProgress } from '../lib/commands';

jest.mock('aws-cdk/lib');
jest.mocked(cli.exec).mockResolvedValue(0);
Expand All @@ -23,7 +23,7 @@ const cdk = AwsCdkCli.fromCloudAssemblyDirectoryProducer({
describe('deploy', () => {
test('default deploy', async () => {
// WHEN
await await cdk.deploy();
await cdk.deploy();

// THEN
expect(jest.mocked(cli.exec)).toHaveBeenCalledWith(
Expand All @@ -34,7 +34,7 @@ describe('deploy', () => {

test('deploy with all arguments', async () => {
// WHEN
await await cdk.deploy({
await cdk.deploy({
stacks: ['Stack1'],
ci: false,
json: true,
Expand All @@ -45,6 +45,7 @@ describe('deploy', () => {
trace: false,
strict: false,
execute: true,
hotswap: HotswapMode.HOTSWAP_ONLY,
lookups: false,
notices: true,
profile: 'my-profile',
Expand Down Expand Up @@ -98,6 +99,7 @@ describe('deploy', () => {
'--no-strict',
'--no-trace',
'--no-lookups',
'--hotswap',
'--no-ignore-errors',
'--json',
'--verbose',
Expand All @@ -118,9 +120,46 @@ describe('deploy', () => {
);
});

test('can parse hotswap-fallback argument', async () => {
// WHEN
await cdk.deploy({
stacks: ['Stack1'],
hotswap: HotswapMode.FALL_BACK,
});

// THEN
expect(jest.mocked(cli.exec)).toHaveBeenCalledWith(
[
'deploy',
'--hotswap-fallback',
'--progress', 'events',
'Stack1',
],
expect.anything(),
);
});

test('skip hotswap full-deployment argument', async () => {
// WHEN
await cdk.deploy({
stacks: ['Stack1'],
hotswap: HotswapMode.FULL_DEPLOYMENT,
});

// THEN
expect(jest.mocked(cli.exec)).toHaveBeenCalledWith(
[
'deploy',
'--progress', 'events',
'Stack1',
],
expect.anything(),
);
});

test('can parse boolean arguments', async () => {
// WHEN
await await cdk.deploy({
await cdk.deploy({
stacks: ['Stack1'],
json: true,
color: false,
Expand All @@ -141,7 +180,7 @@ describe('deploy', () => {

test('can parse parameters', async() => {
// WHEN
await await cdk.deploy({
await cdk.deploy({
stacks: ['Stack1'],
parameters: {
'myparam': 'test',
Expand Down

0 comments on commit e01faff

Please sign in to comment.