Skip to content

Commit fa937ec

Browse files
authored
feat: new command template (#13)
feat: new command template - add new command template to print stack ros template with json/yaml - unit test Refs: #5 --------- Signed-off-by: seven <zilisheng1996@gmail.com>
1 parent af91ea7 commit fa937ec

File tree

8 files changed

+360
-4
lines changed

8 files changed

+360
-4
lines changed

src/commands/index.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { lang } from '../lang';
55
import { logger, getVersion } from '../common';
66
import { validate } from './validate';
77
import { deploy } from './deploy';
8+
import { template } from './template';
89

910
const program = new Command();
1011

@@ -48,8 +49,17 @@ program
4849
{},
4950
)
5051
.action(async (stackName, { file, parameter, stage }) => {
51-
logger.debug('log command info');
5252
await deploy(stackName, { location: file, parameters: parameter, stage });
5353
});
5454

55+
program
56+
.command('template <stackName>')
57+
.description('print ROS template')
58+
.option('-f, --file <path>', 'specify the yaml file')
59+
.option('-s, --stage <stage>', 'specify the stage')
60+
.option('-t, --format <type>', 'output content type (JSON or YAML)', 'JSON')
61+
.action((stackName, { format, file, stage }) => {
62+
template(stackName, { format, location: file, stage });
63+
});
64+
5565
program.parse();

src/commands/template.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { TemplateFormat } from '../types';
2+
import yaml from 'yaml';
3+
import { generateStackTemplate } from '../stack/deploy';
4+
import { constructActionContext, logger } from '../common';
5+
import { parseYaml } from '../stack';
6+
7+
export const template = (
8+
stackName: string,
9+
options: { format: TemplateFormat; location: string; stage: string | undefined },
10+
) => {
11+
const context = constructActionContext({ ...options, stackName });
12+
const iac = parseYaml(context.iacLocation);
13+
const { template } = generateStackTemplate(stackName, iac, context);
14+
15+
const output =
16+
options.format === TemplateFormat.JSON
17+
? JSON.stringify(template, null, 2)
18+
: yaml.stringify(template);
19+
20+
logger.info(`\n${output}`);
21+
};

src/common/actionContext.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const constructActionContext = (config?: {
2323
iacLocation: (() => {
2424
const projectRoot = path.resolve(process.cwd());
2525
return config?.location
26-
? path.resolve(projectRoot, config?.location)
26+
? path.resolve(projectRoot, config.location)
2727
: path.resolve(projectRoot, 'serverlessinsight.yml') ||
2828
path.resolve(projectRoot, 'serverlessInsight.yml') ||
2929
path.resolve(projectRoot, 'ServerlessInsight.yml') ||

src/stack/deploy.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ import { ActionContext, ServerlessIac } from '../types';
33
import { logger, rosStackDeploy } from '../common';
44
import { IacStack } from './iacStack';
55

6-
const generateStackTemplate = (stackName: string, iac: ServerlessIac, context: ActionContext) => {
6+
export const generateStackTemplate = (
7+
stackName: string,
8+
iac: ServerlessIac,
9+
context: ActionContext,
10+
) => {
711
const app = new ros.App();
812
new IacStack(app, iac, context);
913

src/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,8 @@ export type ActionContext = {
7979
parameters?: Array<{ key: string; value: string }>;
8080
tags?: Array<{ key: string; value: string }>;
8181
};
82+
83+
export enum TemplateFormat {
84+
YAML = 'YAML',
85+
JSON = 'JSON',
86+
}

tests/commands/template.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { template } from '../../src/commands/template';
2+
import { TemplateFormat } from '../../src/types';
3+
import { jsonTemplate, yamlTemplate } from '../fixtures/templateFixture';
4+
5+
const mockedLogger = jest.fn();
6+
jest.mock('../../src/common/logger', () => ({
7+
logger: { info: (...args: unknown[]) => mockedLogger(...args), debug: jest.fn() },
8+
}));
9+
const stackName = 'printTemplateStack';
10+
const location = 'tests/fixtures/serverless-insight.yml';
11+
12+
describe('Unit test for template command', () => {
13+
beforeEach(() => {
14+
mockedLogger.mockRestore();
15+
});
16+
it('should print the template in JSON format by default', () => {
17+
const options = {
18+
format: TemplateFormat.JSON,
19+
location,
20+
stage: undefined,
21+
};
22+
23+
template(stackName, options);
24+
25+
expect(mockedLogger).toHaveBeenCalledWith(`\n${JSON.stringify(jsonTemplate, null, 2)}`);
26+
});
27+
28+
it('should print the template in YAML format when specified', () => {
29+
const options = { format: TemplateFormat.YAML, location, stage: undefined };
30+
31+
template(stackName, options);
32+
33+
expect(mockedLogger).toHaveBeenCalledWith(yamlTemplate);
34+
});
35+
});

tests/fixtures/serverless-insight.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ functions:
2626
name: insight-poc-fn
2727
runtime: nodejs18
2828
handler: ${vars.handler}
29-
code: artifacts/artifact.zip
29+
code: tests/fixtures/artifacts/artifact.zip
3030
memory: 512
3131
timeout: 10
3232
environment:

0 commit comments

Comments
 (0)