Skip to content

Commit

Permalink
feat: add command to show ros template
Browse files Browse the repository at this point in the history
Signed-off-by: seven <[email protected]>
  • Loading branch information
Blankll committed Dec 3, 2024
1 parent af91ea7 commit 70a3883
Show file tree
Hide file tree
Showing 7 changed files with 359 additions and 3 deletions.
12 changes: 11 additions & 1 deletion src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { lang } from '../lang';
import { logger, getVersion } from '../common';
import { validate } from './validate';
import { deploy } from './deploy';
import { template } from './template';

const program = new Command();

Expand Down Expand Up @@ -48,8 +49,17 @@ program
{},
)
.action(async (stackName, { file, parameter, stage }) => {
logger.debug('log command info');
await deploy(stackName, { location: file, parameters: parameter, stage });
});

program
.command('template <stackName>')
.description('print ROS template')
.option('-f, --file <path>', 'specify the yaml file')
.option('-s, --stage <stage>', 'specify the stage')
.option('-t, --format <type>', 'output content type (JSON or YAML)', 'JSON')
.action((stackName, { format, file, stage }) => {
template(stackName, { format, location: file, stage });
});

program.parse();
21 changes: 21 additions & 0 deletions src/commands/template.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { TemplateFormat } from '../types';
import yaml from 'yaml';
import { generateStackTemplate } from '../stack/deploy';
import { constructActionContext, logger } from '../common';
import { parseYaml } from '../stack';

export const template = (
stackName: string,
options: { format: TemplateFormat; location: string; stage: string | undefined },
) => {
const context = constructActionContext({ ...options, stackName });
const iac = parseYaml(context.iacLocation);
const { template } = generateStackTemplate(stackName, iac, context);

const output =
options.format === TemplateFormat.JSON
? JSON.stringify(template, null, 2)
: yaml.stringify(template);

logger.info(`\n${output}`);
};
2 changes: 1 addition & 1 deletion src/common/actionContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const constructActionContext = (config?: {
iacLocation: (() => {
const projectRoot = path.resolve(process.cwd());
return config?.location
? path.resolve(projectRoot, config?.location)
? path.resolve(projectRoot, config.location)
: path.resolve(projectRoot, 'serverlessinsight.yml') ||
path.resolve(projectRoot, 'serverlessInsight.yml') ||
path.resolve(projectRoot, 'ServerlessInsight.yml') ||
Expand Down
6 changes: 5 additions & 1 deletion src/stack/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import { ActionContext, ServerlessIac } from '../types';
import { logger, rosStackDeploy } from '../common';
import { IacStack } from './iacStack';

const generateStackTemplate = (stackName: string, iac: ServerlessIac, context: ActionContext) => {
export const generateStackTemplate = (
stackName: string,
iac: ServerlessIac,
context: ActionContext,
) => {
const app = new ros.App();
new IacStack(app, iac, context);

Expand Down
5 changes: 5 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,8 @@ export type ActionContext = {
parameters?: Array<{ key: string; value: string }>;
tags?: Array<{ key: string; value: string }>;
};

export enum TemplateFormat {
YAML = 'YAML',
JSON = 'JSON',
}
35 changes: 35 additions & 0 deletions tests/commands/template.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { template } from '../../src/commands/template';
import { TemplateFormat } from '../../src/types';
import { jsonTemplate, yamlTemplate } from '../fixtures/templateFixture';

const mockedLogger = jest.fn();
jest.mock('../../src/common/logger', () => ({
logger: { info: (...args: unknown[]) => mockedLogger(...args), debug: jest.fn() },
}));
const stackName = 'printTemplateStack';
const location = 'tests/fixtures/serverless-insight.yml';

describe('Unit test for template command', () => {
beforeEach(() => {
mockedLogger.mockRestore();
});
it('should print the template in JSON format by default', () => {
const options = {
format: TemplateFormat.JSON,
location,
stage: undefined,
};

template(stackName, options);

expect(mockedLogger).toHaveBeenCalledWith(`\n${JSON.stringify(jsonTemplate, null, 2)}`);
});

it('should print the template in YAML format when specified', () => {
const options = { format: TemplateFormat.YAML, location, stage: undefined };

template(stackName, options);

expect(mockedLogger).toHaveBeenCalledWith(yamlTemplate);
});
});
281 changes: 281 additions & 0 deletions tests/fixtures/templateFixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,281 @@
export const jsonTemplate = {
Description: 'insight-poc stack',
Metadata: {
'ALIYUN::ROS::Interface': {
TemplateTags: ['Create by ROS CDK'],
},
},
ROSTemplateFormatVersion: '2015-09-01',
Parameters: {
region: {
Type: 'String',
Default: 'cn-hangzhou',
},
testv: {
Type: 'String',
Default: 'testVarValue',
},
handler: {
Type: 'String',
Default: 'index.handler',
},
},
Mappings: {
stages: {
default: {
region: {
Ref: 'region',
},
node_env: 'default',
},
dev: {
region: {
Ref: 'region',
},
node_env: 'development',
},
prod: {
region: 'cn-shanghai',
},
},
},
Resources: {
insight_poc_fn: {
Type: 'ALIYUN::FC3::Function',
Properties: {
FunctionName: 'insight-poc-fn',
Handler: {
Ref: 'handler',
},
Runtime: 'nodejs18',
Code: {
ZipFile:
'UEsDBBQAAAAAADiNNVkAAAAAAAAAAAAAAAAJACAAYXJ0aWZhY3QvVVQNAAfdlO5m7pTuZt2U7mZ1eAsAAQT1AQAABBQAAABQSwMEFAAIAAgA44w1WQAAAAAAAAAAngAAABEAIABhcnRpZmFjdC9pbmRleC5qc1VUDQAHO5TuZt6U7mbdlO5mdXgLAAEE9QEAAAQUAAAAhYuxCsJAEAX7fMV2uUDIDwR7rS2sz8uaBB+7srsJAfHf5cDebhhm+HiphQ9LlglsdKLHJiVWFUq8s0RPRSX4qJCBey7Pjt4NVe0KHqBzaq9sOxvY/SK+zkvQmQGlmxqmthtr/7uTbEBP/5fP2HwBUEsHCG5M74NvAAAAngAAAFBLAQIUAxQAAAAAADiNNVkAAAAAAAAAAAAAAAAJACAAAAAAAAAAAADtQQAAAABhcnRpZmFjdC9VVA0AB92U7mbulO5m3ZTuZnV4CwABBPUBAAAEFAAAAFBLAQIUAxQACAAIAOOMNVluTO+DbwAAAJ4AAAARACAAAAAAAAAAAACkgUcAAABhcnRpZmFjdC9pbmRleC5qc1VUDQAHO5TuZt6U7mbdlO5mdXgLAAEE9QEAAAQUAAAAUEsFBgAAAAACAAIAtgAAABUBAAAAAA==',
},
EnvironmentVariables: {
NODE_ENV: {
'Fn::FindInMap': ['stages', 'default', 'node_env'],
},
TEST_VAR: {
Ref: 'testv',
},
TEST_VAR_EXTRA: {
'Fn::Sub': 'abcds-${testv}-andyou',
},
},
MemorySize: 512,
Timeout: 10,
},
},
'insight-poc_role': {
Type: 'ALIYUN::RAM::Role',
Properties: {
AssumeRolePolicyDocument: {
Version: '1',
Statement: [
{
Action: 'sts:AssumeRole',
Effect: 'Allow',
Principal: {
Service: ['apigateway.aliyuncs.com'],
},
},
],
},
RoleName: 'insight-poc-gateway-access-role',
Description: 'insight-poc role',
Policies: [
{
PolicyName: 'insight-poc-policy',
PolicyDocument: {
Version: '1',
Statement: [
{
Action: ['fc:InvokeFunction'],
Resource: ['*'],
Effect: 'Allow',
},
],
},
},
],
},
},
'insight-poc_apigroup': {
Type: 'ALIYUN::ApiGateway::Group',
Properties: {
GroupName: 'insight-poc_apigroup',
Tags: [
{
Value: 'ServerlessInsight',
Key: 'iac-provider',
},
{
Value: 'geek-fun',
Key: 'owner',
},
],
},
},
gateway_event_api_get__api_hello: {
Type: 'ALIYUN::ApiGateway::Api',
Properties: {
ApiName: 'insight-poc-gateway_api_get__api_hello',
GroupId: {
'Fn::GetAtt': ['insight-poc_apigroup', 'GroupId'],
},
RequestConfig: {
RequestPath: '/api/hello',
RequestMode: 'PASSTHROUGH',
RequestProtocol: 'HTTP',
RequestHttpMethod: 'GET',
},
ServiceConfig: {
FunctionComputeConfig: {
FcVersion: '3.0',
FcRegionId: 'cn-hangzhou',
RoleArn: {
'Fn::GetAtt': ['insight-poc_role', 'Arn'],
},
FunctionName: {
'Fn::GetAtt': ['insight_poc_fn', 'FunctionName'],
},
},
ServiceProtocol: 'FunctionCompute',
},
Visibility: 'PRIVATE',
ResultSample: 'ServerlessInsight resultSample',
ResultType: 'JSON',
Tags: [
{
Value: 'ServerlessInsight',
Key: 'iac-provider',
},
{
Value: 'geek-fun',
Key: 'owner',
},
],
},
},
},
};

export const yamlTemplate = `
Description: insight-poc stack
Metadata:
ALIYUN::ROS::Interface:
TemplateTags:
- Create by ROS CDK
ROSTemplateFormatVersion: 2015-09-01
Parameters:
region:
Type: String
Default: cn-hangzhou
testv:
Type: String
Default: testVarValue
handler:
Type: String
Default: index.handler
Mappings:
stages:
default:
region:
Ref: region
node_env: default
dev:
region:
Ref: region
node_env: development
prod:
region: cn-shanghai
Resources:
insight_poc_fn:
Type: ALIYUN::FC3::Function
Properties:
FunctionName: insight-poc-fn
Handler:
Ref: handler
Runtime: nodejs18
Code:
ZipFile: UEsDBBQAAAAAADiNNVkAAAAAAAAAAAAAAAAJACAAYXJ0aWZhY3QvVVQNAAfdlO5m7pTuZt2U7mZ1eAsAAQT1AQAABBQAAABQSwMEFAAIAAgA44w1WQAAAAAAAAAAngAAABEAIABhcnRpZmFjdC9pbmRleC5qc1VUDQAHO5TuZt6U7mbdlO5mdXgLAAEE9QEAAAQUAAAAhYuxCsJAEAX7fMV2uUDIDwR7rS2sz8uaBB+7srsJAfHf5cDebhhm+HiphQ9LlglsdKLHJiVWFUq8s0RPRSX4qJCBey7Pjt4NVe0KHqBzaq9sOxvY/SK+zkvQmQGlmxqmthtr/7uTbEBP/5fP2HwBUEsHCG5M74NvAAAAngAAAFBLAQIUAxQAAAAAADiNNVkAAAAAAAAAAAAAAAAJACAAAAAAAAAAAADtQQAAAABhcnRpZmFjdC9VVA0AB92U7mbulO5m3ZTuZnV4CwABBPUBAAAEFAAAAFBLAQIUAxQACAAIAOOMNVluTO+DbwAAAJ4AAAARACAAAAAAAAAAAACkgUcAAABhcnRpZmFjdC9pbmRleC5qc1VUDQAHO5TuZt6U7mbdlO5mdXgLAAEE9QEAAAQUAAAAUEsFBgAAAAACAAIAtgAAABUBAAAAAA==
EnvironmentVariables:
NODE_ENV:
Fn::FindInMap:
- stages
- default
- node_env
TEST_VAR:
Ref: testv
TEST_VAR_EXTRA:
Fn::Sub: abcds-\${testv}-andyou
MemorySize: 512
Timeout: 10
insight-poc_role:
Type: ALIYUN::RAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "1"
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service:
- apigateway.aliyuncs.com
RoleName: insight-poc-gateway-access-role
Description: insight-poc role
Policies:
- PolicyName: insight-poc-policy
PolicyDocument:
Version: "1"
Statement:
- Action:
- fc:InvokeFunction
Resource:
- "*"
Effect: Allow
insight-poc_apigroup:
Type: ALIYUN::ApiGateway::Group
Properties:
GroupName: insight-poc_apigroup
Tags:
- Value: ServerlessInsight
Key: iac-provider
- Value: geek-fun
Key: owner
gateway_event_api_get__api_hello:
Type: ALIYUN::ApiGateway::Api
Properties:
ApiName: insight-poc-gateway_api_get__api_hello
GroupId:
Fn::GetAtt:
- insight-poc_apigroup
- GroupId
RequestConfig:
RequestPath: /api/hello
RequestMode: PASSTHROUGH
RequestProtocol: HTTP
RequestHttpMethod: GET
ServiceConfig:
FunctionComputeConfig:
FcVersion: "3.0"
FcRegionId: cn-hangzhou
RoleArn:
Fn::GetAtt:
- insight-poc_role
- Arn
FunctionName:
Fn::GetAtt:
- insight_poc_fn
- FunctionName
ServiceProtocol: FunctionCompute
Visibility: PRIVATE
ResultSample: ServerlessInsight resultSample
ResultType: JSON
Tags:
- Value: ServerlessInsight
Key: iac-provider
- Value: geek-fun
Key: owner
`;

0 comments on commit 70a3883

Please sign in to comment.