From e33b209ab681b5fdabccd573d68e0ac4f474cc3a Mon Sep 17 00:00:00 2001 From: seven Date: Thu, 19 Sep 2024 21:54:17 +0800 Subject: [PATCH] feat: add deploy command Signed-off-by: seven --- src/commands/deploy.ts | 13 +++++++++ src/commands/index.ts | 9 +++++++ src/commands/validate.ts | 8 +----- src/common/printer.ts | 3 ++- src/iac/iacSchema.ts | 4 +++ src/iac/parse.ts | 12 ++++++--- src/iac/resource.ts | 28 ++++++++++++++++++++ src/stack/deploy.ts | 38 +++++++++++++++++++++++++++ src/stack/index.ts | 1 + src/types.ts | 10 +++---- tests/fixtures/serverless-insignt.yml | 2 +- 11 files changed, 110 insertions(+), 18 deletions(-) create mode 100644 src/commands/deploy.ts create mode 100644 src/iac/resource.ts create mode 100644 src/stack/deploy.ts create mode 100644 src/stack/index.ts diff --git a/src/commands/deploy.ts b/src/commands/deploy.ts new file mode 100644 index 00000000..7224178c --- /dev/null +++ b/src/commands/deploy.ts @@ -0,0 +1,13 @@ +import { deployStack } from '../stack'; +import { printer } from '../common'; +import { parseYaml } from '../iac'; + +export const deploy = (location?: string) => { + printer.info('Validating yaml...'); + const iac = parseYaml(location); + printer.success('Yaml is valid! 🎉'); + + printer.info('Deploying stack...'); + deployStack(iac); + printer.success('Stack deployed! 🎉'); +}; diff --git a/src/commands/index.ts b/src/commands/index.ts index 72432b5e..dc9b1126 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -4,6 +4,7 @@ import { Command } from 'commander'; import { lang } from '../lang'; import { logger, getVersion } from '../common'; import { validate } from './validate'; +import { deploy } from './deploy'; const program = new Command(); @@ -29,4 +30,12 @@ program validate(location); }); +program + .command('deploy [location]') + .description('deploy serverless Iac yaml') + .action((location) => { + logger.debug('log command info'); + deploy(location); + }); + program.parse(); diff --git a/src/commands/validate.ts b/src/commands/validate.ts index 05577799..b8392bef 100644 --- a/src/commands/validate.ts +++ b/src/commands/validate.ts @@ -1,13 +1,7 @@ import { parseYaml } from '../iac'; -import path from 'node:path'; import { printer } from '../common'; export const validate = (location?: string) => { - const projectRoot = path.resolve(process.cwd()); - const yamlPath = location - ? path.resolve(projectRoot, location) - : path.resolve(projectRoot, 'serverless-insight.yml'); - - parseYaml(yamlPath); + parseYaml(location); printer.success('Yaml is valid! 🎉'); }; diff --git a/src/common/printer.ts b/src/common/printer.ts index bc782140..ee0413d5 100644 --- a/src/common/printer.ts +++ b/src/common/printer.ts @@ -2,7 +2,8 @@ import chalk from 'chalk'; export const printer = { success: (message: string) => - console.log(`${chalk.bgYellow(chalk.black('ServerlessInsight'))}: ${chalk.green(message)}`), + console.log(`${chalk.blue('ServerlessInsight')}: ${chalk.green(message)}`), + info: (message: string) => console.log(`${chalk.blue('ServerlessInsight')}: ${message}`), error: (message: string) => console.log(`${chalk.bgRed(chalk.black('ServerlessInsight'))}: ${chalk.red(message)}`), }; diff --git a/src/iac/iacSchema.ts b/src/iac/iacSchema.ts index dfc01527..7b6ac3a8 100644 --- a/src/iac/iacSchema.ts +++ b/src/iac/iacSchema.ts @@ -120,6 +120,10 @@ class IacSchemaErrors extends Error { type: error.keyword, })); } + + public get errors() { + return this.schemaErrors; + } } export const validateYaml = (iacJson: RawServerlessIac) => { diff --git a/src/iac/parse.ts b/src/iac/parse.ts index 6aac01f2..798b73e9 100644 --- a/src/iac/parse.ts +++ b/src/iac/parse.ts @@ -2,6 +2,7 @@ import { parse } from 'yaml'; import { existsSync, readFileSync } from 'node:fs'; import { IacFunction, RawServerlessIac, ServerlessIac, Event } from '../types'; import { validateYaml } from './iacSchema'; +import path from 'node:path'; const mapToArr = (obj: Record | string>) => { return Object.entries(obj).map(([key, value]) => @@ -28,10 +29,15 @@ const transformYaml = (iacJson: RawServerlessIac): ServerlessIac => { }; }; -export const parseYaml = (path: string): ServerlessIac => { - validateExistence(path); +export const parseYaml = (location?: string): ServerlessIac => { + const projectRoot = path.resolve(process.cwd()); + const yamlPath = location + ? path.resolve(projectRoot, location) + : path.resolve(projectRoot, 'serverless-insight.yml'); - const yamlContent = readFileSync(path, 'utf8'); + validateExistence(yamlPath); + + const yamlContent = readFileSync(yamlPath, 'utf8'); const iacJson = parse(yamlContent) as RawServerlessIac; validateYaml(iacJson); diff --git a/src/iac/resource.ts b/src/iac/resource.ts new file mode 100644 index 00000000..03eed990 --- /dev/null +++ b/src/iac/resource.ts @@ -0,0 +1,28 @@ +// import * as ros from '@alicloud/ros-cdk-core'; +// import * as fc from '@alicloud/ros-cdk-fc'; +// +// export class IacStack extends ros.Stack { +// constructor(scope: ros.Construct, id: string, props?: ros.StackProps) { +// super(scope, id, props); +// new ros.RosInfo(this, ros.RosInfo.description, 'This is the simple ros cdk app example.'); +// +// const functionCompute = new fc.RosFunction( +// this, +// 'MyFunction', +// { +// functionName: 'my-function', +// serviceName: service.attrServiceName, +// handler: 'index.handler', +// runtime: 'nodejs14', +// code: { +// zipFile: +// 'exports.handler = function(event, context, callback) { callback(null, "Hello World"); }', +// }, +// }, +// false, +// ); +// console.log(functionCompute); +// } +// } +// +// export const defineResource = (name: string, type: string, properties: Record) => {}; diff --git a/src/stack/deploy.ts b/src/stack/deploy.ts new file mode 100644 index 00000000..71781e2d --- /dev/null +++ b/src/stack/deploy.ts @@ -0,0 +1,38 @@ +import * as ros from '@alicloud/ros-cdk-core'; +import * as fc from '@alicloud/ros-cdk-fc'; +import { ServerlessIac } from '../types'; + +export class IacStack extends ros.Stack { + constructor(scope: ros.Construct, iac: ServerlessIac, props?: ros.StackProps) { + super(scope, iac.service, props); + new ros.RosInfo(this, ros.RosInfo.description, 'This is the simple ros cdk app example.'); + iac.functions.map( + (fnc) => + new fc.RosFunction( + this, + fnc.name, + { + functionName: fnc.name, + serviceName: `${fnc.name}-service`, + handler: fnc.handler, + runtime: fnc.runtime, + memorySize: fnc.memory, + timeout: fnc.timeout, + environmentVariables: fnc.environment, + code: { + zipFile: + 'exports.handler = function(event, context, callback) { callback(null, "Hello World"); }', + }, + }, + false, + ), + ); + } +} + +export const deployStack = (iac: ServerlessIac) => { + console.log(`Deploying stack... ${JSON.stringify(iac)}`); + const app = new ros.App(); + new IacStack(app, iac); + app.synth(); +}; diff --git a/src/stack/index.ts b/src/stack/index.ts new file mode 100644 index 00000000..65a7da2e --- /dev/null +++ b/src/stack/index.ts @@ -0,0 +1 @@ +export { deployStack } from './deploy'; diff --git a/src/types.ts b/src/types.ts index 4dda8bea..bca84a30 100644 --- a/src/types.ts +++ b/src/types.ts @@ -10,18 +10,16 @@ type Stages = { [key: string]: Stage; }; -type FunctionEnvironment = { - NODE_ENV: string; -}; - export type IacFunction = { name: string; runtime: string; handler: string; - code: string; + zip: string; memory: number; timeout: number; - environment: FunctionEnvironment; + environment: { + [key: string]: string; + }; }; type Functions = { diff --git a/tests/fixtures/serverless-insignt.yml b/tests/fixtures/serverless-insignt.yml index 27d0eccc..0080029c 100644 --- a/tests/fixtures/serverless-insignt.yml +++ b/tests/fixtures/serverless-insignt.yml @@ -21,7 +21,7 @@ functions: runtime: nodejs14 handler: index.handler code: artifact.zip - memory: 128 + memory: 512 timeout: 10 environment: NODE_ENV: production