Skip to content

Commit

Permalink
Add print-change-set function to org-formation cli (#547)
Browse files Browse the repository at this point in the history
* Add print-change-set function to org-formation cli

The print-change-set function will output the changes a changeset will
perform, in either yaml or json.

* chore: made some minor tweaks

* Remove unused import from print-changesets

---------

Co-authored-by: Olaf Conijn <[email protected]>
  • Loading branch information
castaples and OlafConijn authored Feb 18, 2024
1 parent 85b66b1 commit 54f5c19
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 2 deletions.
2 changes: 2 additions & 0 deletions cli-program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
InitOrganizationCommand,
InitPipelineCommand,
PerformTasksCommand,
PrintChangeSetCommand,
PrintOrganizationCommand,
PrintStacksCommand,
UpdateOrganizationCommand,
Expand Down Expand Up @@ -50,6 +51,7 @@ export class CliProgram {
new InitPipelineCommand(this.program);
new InitOrganizationCommand(this.program);
new PerformTasksCommand(this.program);
new PrintChangeSetCommand(this.program);
new PrintOrganizationCommand(this.program);
new PrintTasksCommand(this.program);
new PrintStacksCommand(this.program);
Expand Down
7 changes: 7 additions & 0 deletions docs/cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Typing ``help`` after any command in the commandline will print documentation.
- [``org-formation update``](#org-formation-update)
- [``org-formation create-change-set``](#org-formation-create-change-set)
- [``org-formation execute-change-set``](#org-formation-execute-change-set)
- [``org-formation print-change-set``](#org-formation-print-change-set)
- [Operations on stacks](#operations-on-stacks)
- [``org-formation update-stacks``](#org-formation-update-stacks)
- [``org-formation validate-stacks``](#org-formation-validate-stacks)
Expand Down Expand Up @@ -92,6 +93,12 @@ Execute a changeset by name of *changeSetName*.

``> org-formation execute-change-set change-set-name``

### ``org-formation print-change-set``

Display a changeset by name of *changeSetName*.

``> org-formation print-change-set change-set-name``

## Operations on stacks

### ``org-formation update-stacks``
Expand Down
15 changes: 13 additions & 2 deletions src/commands/create-organization-changeset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ChangeSetProvider } from '~change-set/change-set-provider';
import { TemplateRoot } from '~parser/parser';
import { GlobalState } from '~util/global-state';
import { AwsUtil } from '~util/aws-util';
import { yamlDump } from '~yaml-cfn/index';

const commandName = 'create-change-set <templateFile>';
const commandDescription = 'create change set that can be reviewed and executed later';
Expand All @@ -18,10 +19,16 @@ export class CreateChangeSetCommand extends BaseCliCommand<ICreateChangeSetComma
public addOptions(command: Command): void {
super.addOptions(command);
command.option('--change-set-name [change-set-name]', 'change set name');
command.option('--output <output>', 'serialization format used when printing change set. Either json or yaml.', 'json');
}

public async performCommand(command: ICreateChangeSetCommandArgs): Promise<void> {

if (!['json', 'yaml'].includes(command.output)) {
ConsoleUtil.LogError(`Invalid output format '${command.output}'. Must be either 'json' or 'yaml'.`);
return;
}

const template = await TemplateRoot.create(command.templateFile);
const state = await this.getState(command);

Expand All @@ -42,13 +49,17 @@ export class CreateChangeSetCommand extends BaseCliCommand<ICreateChangeSetComma

}

const contents = JSON.stringify(changeSet, null, 2);
ConsoleUtil.Out(contents);
if (command.output === 'json') {
ConsoleUtil.Out(JSON.stringify(changeSet, null, 2));
} else if (command.output === 'yaml') {
ConsoleUtil.Out(yamlDump(changeSet));
}
}
}

export interface ICreateChangeSetCommandArgs extends ICommandArgs {
masterAccountId?: any;
templateFile: string;
changeSetName?: string;
output?: 'json' | 'yaml';
}
1 change: 1 addition & 0 deletions src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export * from './execute-organization-changeset';
export * from './init-organization-pipeline';
export * from './init-organization';
export * from './perform-tasks';
export * from './print-changeset';
export * from './print-org';
export * from './print-stacks';
export * from './update-organization';
Expand Down
54 changes: 54 additions & 0 deletions src/commands/print-changeset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { Command } from 'commander';
import { ConsoleUtil } from '../util/console-util';
import { BaseCliCommand, ICommandArgs } from './base-command';
import { ChangeSetProvider } from '~change-set/change-set-provider';
import { yamlDump } from '~yaml-cfn/index';

const commandName = 'print-change-set <change-set-name>';
const commandDescription = 'outputs change set details';

export class PrintChangeSetCommand extends BaseCliCommand<IPrintChangeSetCommandArgs> {

public static async Perform(command: IPrintChangeSetCommandArgs): Promise<void> {
const x = new PrintChangeSetCommand();
await x.performCommand(command);
}

constructor(command?: Command) {
super(command, commandName, commandDescription, 'changeSetName');
}

public addOptions(command: Command): void {
super.addOptions(command);
command.option('--change-set-name [change-set-name]', 'change set name');
command.option('--output <output>', 'serialization format used when printing change set. Either json or yaml.', 'json');
}

public async performCommand(command: IPrintChangeSetCommandArgs): Promise<void> {
if (!['json', 'yaml'].includes(command.output)) {
ConsoleUtil.LogError(`Invalid output format '${command.output}'. Must be either 'json' or 'yaml'.`);
return;
}
const changeSetName = command.changeSetName;
const stateBucketName = await BaseCliCommand.GetStateBucketName(command.stateBucketName);
const provider = new ChangeSetProvider(stateBucketName);
const changeSetObj = await provider.getChangeSet(changeSetName);
if (!changeSetObj) {
ConsoleUtil.LogError(`change set '${changeSetName}' not found.`);
return;
}
const changeSet = changeSetObj.changeSet;

if (command.output === 'json') {
ConsoleUtil.Out(JSON.stringify(changeSet, null, 2));
} else if (command.output === 'yaml') {
ConsoleUtil.Out(yamlDump(changeSet));
}

}
}

export interface IPrintChangeSetCommandArgs extends ICommandArgs {
changeSetName?: string;
output?: 'json' | 'yaml';
}
33 changes: 33 additions & 0 deletions test/unit-tests/commands/print-change-set.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Command, Option } from "commander";
import { PrintChangeSetCommand } from "~commands/print-changeset";

describe('when creating print change set command', () => {
let command: PrintChangeSetCommand;
let commanderCommand: Command;
let subCommanderCommand: Command;

beforeEach(() => {
commanderCommand = new Command('root');
command = new PrintChangeSetCommand(commanderCommand);
subCommanderCommand = commanderCommand.commands[0];
});

test('print change set command is created', () => {
expect(command).toBeDefined();
expect(subCommanderCommand).toBeDefined();
expect(subCommanderCommand.name()).toBe('print-change-set');
});

test('print change set command has description', () => {
expect(subCommanderCommand).toBeDefined();
expect(subCommanderCommand.description()).toBeDefined();
});

test('command has required output parameter with default', () => {
const opts: Option[] = subCommanderCommand.options;
const stackNameOpt = opts.find((x) => x.long === '--output');
expect(stackNameOpt).toBeDefined();
expect(stackNameOpt.required).toBeTruthy();
expect(subCommanderCommand.output).toBe('yaml');
});
});

0 comments on commit 54f5c19

Please sign in to comment.