Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/amplify enhanced status #7698

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
478c17a
enhanced amplify status
Jul 7, 2021
8cc5388
help and test
Jul 7, 2021
00f0868
show summary view on amplify push
Jul 7, 2021
4bc0ad6
Fixed s3
Jul 8, 2021
13997a3
unit test for showStatusTable
Jul 9, 2021
f47b3f3
fixed ViewResourceTableParams
Jul 9, 2021
1698a14
Converted cloudformation file-path to use Glob
Jul 9, 2021
a860901
cleanup and headers
Jul 9, 2021
fd931bb
1. removed custom yaml handling and used library code.
Jul 11, 2021
848ba08
addressed PR comments
Jul 12, 2021
1db112b
Added types to template, diff
Jul 12, 2021
a256d18
addressed more PR comments
Jul 12, 2021
56ead1b
updated unit test coverage and fixed test errors
Jul 13, 2021
97e4e01
Merge branch 'aws-amplify:master' into feature/amplify-enhanced-status
sachscode Jul 14, 2021
bc718d4
fix multi-env diffs for new resources
Jul 15, 2021
eea4be0
1. category filters for summary.
Jul 16, 2021
5a5d2d6
updated help to indicate summary filters
Jul 16, 2021
656a9da
Merge branch 'aws-amplify:master' into feature/amplify-enhanced-status
sachscode Jul 19, 2021
82badbe
Update Readme.md
sachscode Jul 19, 2021
6af0fca
resolved merge errors
Jul 22, 2021
0c1167c
fixed unit tests and merge errors
Jul 23, 2021
270cc71
Merge branch 'aws-amplify:master' into feature/amplify-enhanced-status
sachscode Jul 23, 2021
e9c371e
Update Readme.md
sachscode Jul 23, 2021
fb62416
Update packages/amplify-cli-core/src/cliViewAPI.ts
sachscode Jul 23, 2021
7202d8d
Update packages/amplify-cli/src/extensions/amplify-helpers/resource-s…
sachscode Jul 23, 2021
318e13d
addressed CR comments
Jul 24, 2021
926f388
Merge branch 'aws-amplify:master' into feature/amplify-enhanced-status
sachscode Jul 24, 2021
92555b6
lgtm:fix:removed unused variable
Jul 24, 2021
6b9df61
Merge branch 'feature/amplify-enhanced-status' of github.com:sachscod…
Jul 24, 2021
d78e7ab
unit-tests for cliViewAPI
Jul 27, 2021
8e1216d
removed styling from help test
Jul 27, 2021
b984488
unit-test for detailed cloudformation-diff for one resource
Aug 2, 2021
2d18841
Merge branch 'master' into feature/amplify-enhanced-status
sachscode Aug 2, 2021
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
3 changes: 2 additions & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ The Amplify CLI supports the commands shown in the following table.
| amplify push [--no-gql-override] | Provisions cloud resources with the latest local developments. The 'no-gql-override' flag does not automatically compile your annotated GraphQL schema and will override your local AppSync resolvers and templates. |
| amplify pull | Fetch upstream backend environment definition changes from the cloud and updates the local environment to match that definition. |
| amplify publish | Runs `amplify push`, publishes a static assets to Amazon S3 and Amazon CloudFront (\*hosting category is required). |
| amplify status | Displays the state of local resources that haven't been pushed to the cloud (Create/Update/Delete). |
| amplify status [ `<category>`...] | Displays the state of local resources that haven't been pushed to the cloud (Create/Update/Delete). |
| amplify status -v [ `<category>`...] | Verbose mode - Shows the detailed verbose diff between local and deployed resources, including cloudformation-diff |
| amplify serve | Runs `amplify push`, and then executes the project's start command to test run the client-side application. |
| amplify delete | Deletes resources tied to the project. |
| amplify help \| amplify `<category>` help | Displays help for the core CLI. |
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"author": "Amazon Web Services",
"license": "Apache-2.0",
"dependencies": {
"strip-ansi": "^6.0.0",
"lerna": "^4.0.0"
},
"workspaces": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`CLI View tests Status Help CLI should correctly return styled help message 1`] = `
"
NAME
amplify status -- Shows the state of local resources not yet pushed to the cloud (Create/Update/Delete)

SYNOPSIS
amplify status [-v|--verbose] [category ...]

DESCRIPTION
The amplify status command displays the difference between the deployed state and the local state of the application.
The following options are available:

[category ...] : (Summary mode) Displays the summary of local state vs deployed state of the application
usage:
#> amplify status
#> amplify status api storage

-v [category ...] : (Verbose mode) Displays the cloudformation diff for all resources for the specified category.
If no category is provided, it shows the diff for all categories.
usage:
#> amplify status -v
#> amplify status -v api storage

"
`;
65 changes: 65 additions & 0 deletions packages/amplify-cli-core/src/__tests__/cliViewAPI.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { CLIParams, ViewResourceTableParams } from '../cliViewAPI';
import chalk from 'chalk';
import stripAnsi from 'strip-ansi';

describe('CLI View tests', () => {
test('Verbose mode CLI status with category list should correctly initialize ViewResourceTableParams [Non-Help]', () => {
const cliParams : CLIParams = {
cliCommand: 'status',
cliSubcommands: undefined,
cliOptions: {
storage: true,
api: true,
verbose: true,
yes: false
}
}
const view = new ViewResourceTableParams(cliParams);
expect( view.command ).toBe("status");
expect( view.categoryList).toStrictEqual(['storage', 'api']);
expect( view.help ).toBe(false);
expect( view.verbose ).toBe(true);
});

test('Status Help CLI should correctly return styled help message', () => {
const cliParams : CLIParams = {
cliCommand: 'status',
cliSubcommands: [ 'help' ],
cliOptions: { yes: false }
};

const view = new ViewResourceTableParams(cliParams);
expect( view.command ).toBe("status");
expect( view.categoryList).toStrictEqual([]);
expect( view.help ).toBe(true);
expect( view.verbose ).toBe(false);
const styledHelp = stripAnsi(chalk.reset(view.getStyledHelp()));
expect(styledHelp).toMatchSnapshot();
});

test('Status Command should print error message to the screen', () => {
const cliParams : CLIParams = {
cliCommand: 'status',
cliSubcommands: [ 'help' ],
cliOptions: { yes: false }
};
const view = new ViewResourceTableParams(cliParams);
const errorMockFn = jest.fn();

const context: any = {
print : {
error: errorMockFn
}
};
const errorMessage = "Something bad happened"
try {
throw new Error(errorMessage);
}
catch(e) {
view.logErrorException(e, context);
expect(errorMockFn).toBeCalledTimes(1);
}

});

} );
88 changes: 88 additions & 0 deletions packages/amplify-cli-core/src/cliViewAPI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//Use this file to store all types used between the CLI commands and the view/display functions
// CLI=>(command-handler)==[CLI-View-API]=>(ux-handler/report-handler)=>output-stream
import chalk from 'chalk';
import { $TSAny, $TSContext } from '.';
export interface CLIParams {
cliCommand: string;
cliSubcommands: string[] | undefined;
cliOptions: Record<string,$TSAny>;
}
//Resource Table filter and display params (params used for summary/display view of resource table)
export class ViewResourceTableParams {
private _command: string;
private _verbose: boolean; //display table in verbose mode
private _help: boolean; //display help for the command
private _categoryList: string[] | []; //categories to display
private _filteredResourceList: any; //resources to *not* display - TBD define union of valid types

public get command() {
return this._command;
}
public get verbose() {
return this._verbose;
}
public get help() {
return this._help;
}
public get categoryList() {
return this._categoryList;
}
getCategoryFromCLIOptions(cliOptions: object) {
if (cliOptions) {
return Object.keys(cliOptions)
.filter(key => key != 'verbose' && key !== 'yes')
.map(category => category.toLowerCase());
} else {
return [];
}
}
styleHeader(str: string) {
return chalk.italic(chalk.bgGray.whiteBright(str));
}
styleCommand(str: string) {
return chalk.greenBright(str);
}
styleOption(str: string) {
return chalk.yellowBright(str);
}
stylePrompt(str: string) {
return chalk.bold(chalk.yellowBright(str));
}
public getStyledHelp() {
return `
${this.styleHeader('NAME')}
${this.styleCommand('amplify status')} -- Shows the state of local resources not yet pushed to the cloud (Create/Update/Delete)

${this.styleHeader('SYNOPSIS')}
${this.styleCommand('amplify status')} [${this.styleCommand('-v')}|${this.styleCommand('--verbose')}] [${this.styleOption('category ...')}]

${this.styleHeader('DESCRIPTION')}
The amplify status command displays the difference between the deployed state and the local state of the application.
The following options are available:

${this.styleCommand('[category ...]')} : (Summary mode) Displays the summary of local state vs deployed state of the application
usage:
${this.stylePrompt('#>')} ${this.styleCommand('amplify status')}
${this.stylePrompt('#>')} ${this.styleCommand('amplify status')} ${this.styleOption('api storage')}

${this.styleCommand('-v [category ...]')} : (Verbose mode) Displays the cloudformation diff for all resources for the specified category.
If no category is provided, it shows the diff for all categories.
usage:
${this.stylePrompt('#>')} ${this.styleCommand('amplify status -v')}
${this.stylePrompt('#>')} ${this.styleCommand('amplify status -v ')}${this.styleOption('api storage')}

`;
}

public logErrorException( e : Error , context : $TSContext ){
context.print.error(`Name: ${e.name} : Message: ${e.message}`);
}

public constructor(cliParams: CLIParams) {
this._command = cliParams.cliCommand;
this._verbose = cliParams.cliOptions?.verbose === true;
this._categoryList = this.getCategoryFromCLIOptions(cliParams.cliOptions);
this._filteredResourceList = []; //TBD - add support to provide resources
this._help = cliParams.cliSubcommands ? cliParams.cliSubcommands.includes('help') : false;
}
}
6 changes: 5 additions & 1 deletion packages/amplify-cli-core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ViewResourceTableParams } from './cliViewAPI';
import { ServiceSelection } from './serviceSelection';

export * from './cfnUtilities';
Expand All @@ -21,6 +22,7 @@ export * from './utils';
export * from './banner-message';
export * from './cliGetCategories';
export * from './cliRemoveResourcePrompt';
export * from "./cliViewAPI";

// Temporary types until we can finish full type definition across the whole CLI

Expand Down Expand Up @@ -164,6 +166,7 @@ export interface AmplifyProjectConfig {

export type $TSCopyJob = any;


// Temporary interface until Context refactor
interface AmplifyToolkit {
confirmPrompt: (prompt: string, defaultValue?: boolean) => Promise<boolean>;
Expand Down Expand Up @@ -214,8 +217,9 @@ interface AmplifyToolkit {
sharedQuestions: () => $TSAny;
showAllHelp: () => $TSAny;
showHelp: (header: string, commands: { name: string; description: string }[]) => $TSAny;
showHelpfulProviderLinks: () => $TSAny;
showHelpfulProviderLinks: (context : $TSContext) => $TSAny;
showResourceTable: () => $TSAny;
showStatusTable:( resourceTableParams : ViewResourceTableParams )=> $TSAny; //Enhanced Status with CFN-Diff
serviceSelectionPrompt: (
context: $TSContext,
category: string,
Expand Down
98 changes: 98 additions & 0 deletions packages/amplify-cli/src/__tests__/commands/status.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { UnknownArgumentError } from 'amplify-cli-core';

describe('amplify status: ', () => {
const { run } = require('../../commands/status');
const runStatusCmd = run;
const statusPluginInfo = `${process.cwd()}/../amplify-console-hosting`;
const mockPath = './';

it('status run method should exist', () => {
expect(runStatusCmd).toBeDefined();
});

it('status run method should call context.amplify.showStatusTable', async () => {
const cliInput = {
command: 'status',
subCommands: [],
options: {
verbose: true,
},
};

const mockContextNoCLArgs = {
amplify: {
showStatusTable: jest.fn(),
showHelpfulProviderLinks: jest.fn(),
getCategoryPluginInfo: jest.fn().mockReturnValue({ packageLocation: mockPath }),
},
parameters: {
input: {
command: 'status',
subCommands: [],
options: {
verbose: true,
},
},
},
};
runStatusCmd(mockContextNoCLArgs);
expect(mockContextNoCLArgs.amplify.showStatusTable).toBeCalled();
});

it('status -v run method should call context.amplify.showStatusTable', async () => {
const mockContextWithVerboseOptionAndCLArgs = {
amplify: {
showStatusTable: jest.fn(),
showHelpfulProviderLinks: jest.fn(),
getCategoryPluginInfo: jest.fn().mockReturnValue({ packageLocation: statusPluginInfo }),
},
input: {
command: 'status',
options: {
verbose: true,
},
},
};
runStatusCmd(mockContextWithVerboseOptionAndCLArgs);
expect(mockContextWithVerboseOptionAndCLArgs.amplify.showStatusTable).toBeCalled();
});

it('status -v <category>* run method should call context.amplify.showStatusTable', async () => {
const mockContextWithVerboseOptionWithCategoriesAndCLArgs = {
amplify: {
showStatusTable: jest.fn(),
showHelpfulProviderLinks: jest.fn(),
getCategoryPluginInfo: jest.fn().mockReturnValue({ packageLocation: statusPluginInfo }),
},
input: {
command: 'status',
options: {
verbose: true,
api: true,
storage: true,
},
},
};

runStatusCmd(mockContextWithVerboseOptionWithCategoriesAndCLArgs);
expect(mockContextWithVerboseOptionWithCategoriesAndCLArgs.amplify.showStatusTable).toBeCalled();
});

it('status help run method should call ViewResourceTableParams.getStyledHelp', async () => {
const mockContextWithHelpSubcommandAndCLArgs = {
amplify: {
showStatusTable: jest.fn(),
showHelpfulProviderLinks: jest.fn(),
getCategoryPluginInfo: jest.fn().mockReturnValue({ packageLocation: statusPluginInfo }),
},
input: {
command: 'status',
subCommands: ['help'],
},
};
runStatusCmd(mockContextWithHelpSubcommandAndCLArgs);
//TBD: to move ViewResourceTableParams into a separate file for mocking instance functions.
expect(mockContextWithHelpSubcommandAndCLArgs.amplify.showStatusTable.mock.calls.length).toBe(0);
});

});
Loading