Pacakge 模型

Pacakge 模型部分介绍了 Serverless Package Model (SPM) 的建设模型,包括了:

模型的组成

Serverless Package Model 包括两个部分:

  • Component Model:组件模型,即通过Serverless Devs,可以被应用所引用,并按照用户的输入,执行预定的功能。例如某个应用中引用了FC组件,那么此时,用户可以通过传入Deploy命令进行函数的部署,而这里的FC组件,则是需要建立在组件模型基础之上,即要符合组件的开发规范;
  • Application Model:应用模型,即通过Serverless Devs,可以被初始化的应用案例,通常一个应用案例包括了一个yaml文件,在该文件中可以包括一个或多个组件来共同完成某个业务。这里所说的应用,就是需要建立在应用模型基础之上的,或者说是需要符合应用开发规范的;

模型的规范

组件模型规范

Component Model,即组件模型,需要通过指定的文件进行模型的规范和定义的。在这里,推荐的组件模型目录结构为:

|- src # 目录名字可以变更
|   └── 代码目录  
|- package.json: 需要定义好main   
|- publish.yaml: 项目的资源描述   
|- readme.md: 项目简介  
|- version.md: 版本更新内容

其中:

目录必须含义
src推荐存在统一放置功能实现,当然也可以换成其他的名称,或者平铺到项目下,但是推荐通过src来做统一的存放
package.json必须存在Node.js的package.json,需要描述清楚组件的入口文件位置
publish.yaml必须存在Serverless Devs Package的开发识别文档
readme.md必须存在对该组件的描述,或帮助文档信息
version.md推荐存在版本的描述,例如当前版本的更新内容等

组件模型元数据

组件模型元数据将会在publish.yaml中进行描述,并在Serverless Registry和Serverless Devs开发者工具侧进行识别和引用。

publish.yaml文件的基本格式如下所示:

Edition: 0.0.2
Type: Component
Name: 名称
Provider:
  - 云厂商名称 
Version: 版本,例如0.0.1
Description: 简短的描述/介绍
HomePage: 项目首页地址
Tags: #标签详情
  - 部署函数
  - 部署组件
Category: 分类 # 基础云服务/Web框架/全栈应用/人工智能/音视频处理/图文处理/监控告警/大数据/IoT/新手入门/其他
Service: # 使用的服务
  服务名:  # 函数计算/容器服务/镜像服务/消息队列/工作流/CDN/对象存储/表格存储/MNS/日志服务/API网关/数据库/解析服务/云应用/其他
    # Runtime: Python 3.6 如果服务是函数,还需要增加Runtime
    Authorities: #权限描述
      - 创建函数 # 所需要的权限
Commands: # 指令,格式为指令:指令描述,例如:
  deploy: 部署函数
  invoke: 调用函数
Properties:
  type: object
  additionalProperties: false
  required: # 必填项
    - region
    - service
  properties:
    region: # 枚举类型
      default: cn-hangzhou
      title: 地域 # 名称
      enum: # 枚举
        - cn-beijing
        - cn-hangzhou
参数详解
目录必须结构含义
EditionString当前Yaml的版本,推荐0.0.2
TypeString类型,包括Component和Application,Plugin三个取值,此处取值Component
NameString组件名称
ProviderList组件所支持的云厂商信息
VersionString组件版本号,例如0.0.1
DescriptionString组件描述(一句话的简短描述)
HomePageString组件的主页,可以填写组件的仓库地址
TagsList组件的标签
CategoryString组件的分类
ServiceStruct组件所需要的服务和相关的权限等描述,例如该组件需要函数计算,Serverless工作流等产品/服务作为支持
CommandsStruct组件支持的命令
PropertiesStruct组件的参数描述,组件的属性定义,严格遵守Json Schema规范标准
Provider

取值范围:阿里云, 百度智能云, 华为云, 腾讯云, AWS, Azure, Google Cloud, 其它

格式参考:

Provider:
    - 阿里云
    - 百度智能云
Category

取值范围:基础云服务, Web框架, 全栈应用, 人工智能, 音视频处理, 图文处理, 监控告警, 大数据, IoT, 新手入门, 其它, 开源项目

格式参考:

Category: 基础云服务
Service

取值范围:函数计算, 容器服务, 镜像服务, 消息队列, 工作流, CDN, 对象存储, 表格存储, MNS, 日志服务, API网关, 数据库, 解析服务, 云应用, 其它

格式参考:

Service: # 使用的服务
  函数计算:
    # Runtime: Python 3.6 如果服务是函数,还需要增加Runtime,取值包括:Node.JS, Python, PHP, Java, Go, 其它
    Authorities: #权限描述
      - 创建函数 # 所需要的权限
Commands

组件所支持的命令,有两种形式:

  • 形式一:
    Commands:
        demo: 案例命令
        test: 测试命令
    
  • 形式二: ``` Commands: Deploy & Build: deploy: 项目部署 build: 项目构建 Others: demo: 案例命令 test: 测试命令
Properties

Properties参数的格式,严格遵循JSON Scheme的规范标准,具体格式,可以参考以下案例:

Properties:
  type: object
  additionalProperties: false
  required: # 必填项
    - region
    - service
  properties:
    region: # 枚举类型
      default: cn-hangzhou
      title: 地域 # 名称
      enum: # 枚举
        - cn-beijing
        - cn-hangzhou
        - cn-shanghai
        - cn-qingdao
    service:
      title: 服务配置 # 名称
      type: object # 类型
      properties:
        name: # 正则校验
          title: 名称
          description: 只能包含字母、数字、下划线和中划线。不能以数字、中划线开头。长度在 1-128 之间。
          type: string
          pattern: '^[a-zA-Z0-9-_]{1,128}$'
        internetAccess: # boolean 值
          title: 允许公网访问
          description: 配置服务中的函数是否可以访问互联网
          default: true
          type: boolean
        logConfig: # 复杂类型
          title: 日志配置
          oneOf: # 只能有一个生效
            - title: 自动配置
              enum:
                - auto
            - logConfig:
                type: object
                title: 日志配置
                additionalProperties: true
                required:
                  - project
                  - logstore
                properties:
                  project:
                    type: string
                    title: 日志项目
                    default: ''
                    examples:
                      - xx-project
                  logstore:
                    type: string
                    title: 日志仓库
                    default: ''
                    examples:
                      - xx-logstore
                  logBeginRule:
                    title: 日志分割规则
                    default: None
                    enum:
                      - DefaultRegex
                      - None
                  enableRequestMetrics:
                    type: boolean
                    title: 请求级别指标
                    default: true  # 默认值
                  enableInstanceMetrics:
                    type: boolean
                    title: 实例级别指标
                    default: false
                    examples:
                      - true

组件模型代码规范

在组件模型中,代码组成规范有两个部分:

  • package.json中需要描述清楚入口文件所在地址;例如{"main": "./dist/index.js"}
  • 在代码中实现对应的用户方法。例如Package开发者希望用户可以通过deploy命令,进行项目的部署,那么就可以实现一个deploy的方法,并在方法内实现对应的部署能力;

关于代码规范部分,可以参考如下案例:

import logger from './common/logger';
import { InputProps } from './common/entity';

export default class ComponentDemo {
  /**
   * demo 实例
   * @param inputs
   * @returns
   */
  public async test(inputs: InputProps) {
    logger.debug(`input: ${JSON.stringify(inputs.props)}`);
    logger.info('command test');
    return { hello: 'world' };
  }
}

其中入参inputs的结构为:

{
    "command": "", 
    "project": {
        "projectName": "", 
        "component": "",
        "provider": "",
        "access": ""
    },
    "credentials": {},
    "props": {},
    "args": "",
    "argsObj": [],
}
目录含义
command用户所执行的命令
project用户的项目基本信息
credentials用户的密钥信息
props用户配置的属性/参数
args用户传递的参数(字符串形式)
argsObj用户传递的参数(解析后的,以数组形式传递)

在上面的案例代码中,可以看到有一个test方法,该方法就是功能实现的方法。此时当用户使用test命令时,系统就会携带参数调用该方法。以一个真实案例作为举例说明:

该组件名为hexo,组件核心代码如上所示,具备一个test方法,此时用户侧的Yaml为:

edition: 1.0.0        #  命令行YAML规范版本,遵循语义化版本(Semantic Versioning)规范
name: FullStack       #  项目名称
access: xxx-account1  #  秘钥别名

services:
  HexoComponent:
    component: hexo
    props:
      region: 'cn-hangzhou'
      codeUri: './src'

当用户执行s test mytest -a -b abc,此时,组件代码中的test方法,收到的inputs参数实际上是:

{
    "command": "test", 
    "project": {
        "projectName": "HexoComponent", 
        "component": "hexo",
        "provider": "alibaba",
        "access": "release"
    },
    "credentials": {
        "AccountID": "********",
        "AccessKeyID": "********",
        "AccessKeySecret": "********"
    },
    "props": {
        "Region": "cn-hangzhou",
        "CodeUri": "./src"
    },
    "args": "mytest -a -b abc",
    "argsObj": [
      "mytest", "-a", "-b", "abc"
    ]
}

此时test方法会打印日志信息等,并返回最终的结果给命令行工具:{ "hello": "world" }

应用模型规范

Application Model,即应用模型,需要通过指定的文件进行模型的规范和定义的,在这里,推荐的应用模型目录结构为:

|- src # 目录名字不可以变更
|   └── 应用目录
|   └── s.yml: 应用描述文件
|- publish.yaml: 项目的资源描述   
|- readme.md: 项目简介  
|- version.md: 版本更新内容

其中:

目录必须含义
src必须存在应用所在目录
s.yml必须存在应用的资源描述Yaml,需要符合该应用对应的publish,yaml规范
publish.yaml必须存在Serverless Devs Package的开发识别文档
readme.md必须存在对该应用的描述,或帮助文档信息
version.md推荐存在版本的描述,例如当前版本的更新内容等

应用模型元数据

应用模型元数据将会在publish.yaml中进行描述,并在Serverless Registry和Serverless Devs开发者工具侧进行识别和初始化。

publish.yaml文件的基本格式如下所示:

Edition: 0.0.2
Type: Application
Name: 名称
Provider:
  - 云厂商名称 
Version: 版本,例如0.0.1
Description: 简短的描述/介绍
HomePage: 项目首页地址
Tags: #标签详情
  - 部署函数
  - 部署组件
Category: 分类 # 基础云服务/Web框架/全栈应用/人工智能/音视频处理/图文处理/监控告警/大数据/IoT/新手入门/其他
Service: # 使用的服务
  服务名: # 函数计算/容器服务/镜像服务/消息队列/工作流/CDN/对象存储/表格存储/MNS/日志服务/API网关/数据库/解析服务/云应用/其他
    # Runtime: Python 3.6 如果服务是函数,还需要增加Runtime
    Authorities: #权限描述
      - 创建函数 # 所需要的权限
Parameters: # 标准的JSON Scheme
  type: object
  additionalProperties: false # 不允许增加其他属性
  required: # 必填项
    - mysqlName
    - regionName
  properties:
    mysqlName: # 正则校验
      type: string, # 类型
      description: Mysql连接串 # 描述
      title: Mysql连接串
      pattern: '^mysql:.*$' # 正则表达式
参数详解
目录必须结构含义
EditionString当前Yaml的版本,推荐0.0.2
TypeString类型,包括Component和Application,Plugin三个取值,此处取值Application
NameString组件名称
ProviderList组件所支持的云厂商信息
VersionString组件版本号,例如0.0.1
DescriptionString组件描述(一句话的简短描述)
HomePageString组件的主页,可以填写组件的仓库地址
TagsList组件的标签
CategoryString组件的分类
ServiceStruct组件所需要的服务和相关的权限等描述,例如该组件需要函数计算,Serverless工作流等产品/服务作为支持
ParametersStruct应用中Yaml内需要填写的字段,严格遵守Json Schema规范标准
Provider

取值范围:阿里云, 百度智能云, 华为云, 腾讯云, AWS, Azure, Google Cloud, 其它

格式参考:

Provider:
    - 阿里云
    - 百度智能云
Category

取值范围:基础云服务, Web框架, 全栈应用, 人工智能, 音视频处理, 图文处理, 监控告警, 大数据, IoT, 新手入门, 其它, 开源项目其他`

格式参考:

Category: 基础云服务
Service

取值范围:函数计算, 容器服务, 镜像服务, 消息队列, 工作流, CDN, 对象存储, 表格存储, MNS, 日志服务, API网关, 数据库, 解析服务, 云应用, 其它

格式参考:

Service: # 使用的服务
  函数计算:
    # Runtime: Python 3.6 如果服务是函数,还需要增加Runtime,取值包括:Node.JS, Python, PHP, Java, Go, 其它
    Authorities: #权限描述
      - 创建函数 # 所需要的权限
Parameters

在应用模型中,尽管已经有一个完整的s.yaml用来描述应用的信息,但是实际上还会存在诸如下面的情况:

  • 某些s.yaml中的参数需要使用者来填写,例如某些应用需要连接数据库,此时需要用户在初始化应用的时候进行参数的填写;
  • 某些s.yaml中的参数尽管存在默认值,但是仍任需要用户关注,或者需要用户在某些情况下自定义;

所以,Serverless Package模型,针对Application类型,提供了Parameters参数。通过该参数,可以描述s.yaml中的相关参数,例如:

Parameters: # 标准的JSON Scheme
  type: object
  additionalProperties: false # 不允许增加其他属性
  required: # 必填项
    - mysqlName
    - regionName
  properties:
    mysqlName: # 正则校验
      type: string, # 类型
      description: Mysql连接串 # 描述
      title: Mysql连接串
      pattern: '^mysql:.*$' # 正则表达式
    regionName: # 枚举类型
      type: string,
      description: 地域Region
      default: cn-hangzhou # 默认值
      title: 地域
      enum: # 枚举类型
        - cn-beijing
        - cn-hangzhou
        - cn-shanghai

此时,在s.yaml中可以引用该字段,例如:

edition: 1.0.0        #  命令行YAML规范版本,遵循语义化版本(Semantic Versioning)规范
name: component-test   #  项目名称
vars: # [全局变量,提供给各个服务使用]
  domain: xxxx.yyy.com

services:
  component-test:
    component: demo
    props:
      name: {{ inputsrgs }}

为了兼容spec 0.0.1 中,关于s.yaml的特殊格式定义,在当前版本中:

  1. 如果s.yaml中存在类似'{{ bucket | alibaba oss bucket }}'的内容 ,则直接提醒用户需要输入bucket这样的一个参数,作为Yaml中所必须的参数,并以|之后的内容"alibaba oss bucket"作为解释这个参数的含义;
  2. 如果s.yaml中存在类似"{{ access }}"内容,则判断publish.yaml中是否存在Parameters参数以及相关的Key:
    • 如果存在,则默认进行对应;
    • 如果不存在,直接提醒用户需要输入access这样的一个参数,作为Yaml中所必须的参数;

关于Parameters参数的格式,严格遵循JSON Scheme的规范标准,更多使用示例可查看Pacakge 模型 - Parameters参数文档。

插件模型规范

Plugin Model,即插件模型,需要通过指定的文件进行模型的规范和定义的。在这里,推荐的插件模型目录结构为:

|- src # 目录名字可以变更
|   └── 代码目录  
|- package.json: 需要定义好main   
|- publish.yaml: 项目的资源描述   
|- readme.md: 项目简介  
|- version.md: 版本更新内容

其中:

目录必须含义
src推荐存在统一放置功能实现,当然也可以换成其他的名称,或者平铺到项目下,但是推荐通过src来做统一的存放
package.json必须存在Node.js的package.json,需要描述清楚组件的入口文件位置
publish.yaml必须存在Serverless Devs Package的开发识别文档
readme.md必须存在对该插件的描述,或帮助文档信息
version.md推荐存在版本的描述,例如当前版本的更新内容等

插件模型元数据

插件模型元数据将会在publish.yaml中进行描述,并在Serverless Registry和Serverless Devs开发者工具侧进行识别和初始化。

publish.yaml文件的基本格式如下所示:

Edition: 0.0.2
Type: Plugin
Name: 名称
Provider:
  - 云厂商名称 
Version: 版本,例如0.0.1
Description: 简短的描述/介绍
HomePage: 项目首页地址
Tags: #标签详情
  - 部署函数
  - 部署组件
Category: 分类 # 基础云服务/Web框架/全栈应用/人工智能/音视频处理/图文处理/监控告警/大数据/IoT/新手入门/其他
Service: # 使用的服务
  服务名: # 函数计算/容器服务/镜像服务/消息队列/工作流/CDN/对象存储/表格存储/MNS/日志服务/API网关/数据库/解析服务/云应用/其他
    # Runtime: Python 3.6 如果服务是函数,还需要增加Runtime
    Authorities: #权限描述
      - 创建函数 # 所需要的权限
Parameters: # 标准的JSON Scheme
  type: object
  additionalProperties: false # 不允许增加其他属性
  required: # 必填项
    - mysqlName
    - regionName
  properties:
    mysqlName: # 正则校验
      type: string, # 类型
      description: Mysql连接串 # 描述
      title: Mysql连接串
      pattern: '^mysql:.*$' # 正则表达式
参数详解
目录必须结构含义
EditionString当前Yaml的版本,推荐0.0.2
TypeString类型,包括Component和Application,Plugin三个取值,此处取值Plugin
NameString组件名称
ProviderList组件所支持的云厂商信息
VersionString组件版本号,例如0.0.1
DescriptionString组件描述(一句话的简短描述)
HomePageString组件的主页,可以填写组件的仓库地址
TagsList组件的标签
CategoryString组件的分类
ServiceStruct组件所需要的服务和相关的权限等描述,例如该组件需要函数计算,Serverless工作流等产品/服务作为支持
ParametersStruct应用中Yaml内需要填写的字段,严格遵守Json Schema规范标准
Provider

取值范围:阿里云, 百度智能云, 华为云, 腾讯云, AWS, Azure, Google Cloud, 其它

格式参考:

Provider:
    - 阿里云
    - 百度智能云
Category

取值范围:基础云服务, Web框架, 全栈应用, 人工智能, 音视频处理, 图文处理, 监控告警, 大数据, IoT, 新手入门, 其它, 开源项目

格式参考:

Category: 基础云服务
Service

取值范围:函数计算, 容器服务, 镜像服务, 消息队列, 工作流, CDN, 对象存储, 表格存储, MNS, 日志服务, API网关, 数据库, 解析服务, 云应用, 其它

格式参考:

Service: # 使用的服务
  函数计算:
    # Runtime: Python 3.6 如果服务是函数,还需要增加Runtime,取值包括:Node.JS, Python, PHP, Java, Go, 其它
    Authorities: #权限描述
      - 创建函数 # 所需要的权限
Parameters

在插件模型中,可以通过Parameters定义插件的参数信息:

Parameters: # 标准的JSON Scheme
  type: object
  additionalProperties: false # 不允许增加其他属性
  required: # 必填项
    - mysqlName
    - regionName
  properties:
    mysqlName: # 正则校验
      type: string, # 类型
      description: Mysql连接串 # 描述
      title: Mysql连接串
      pattern: '^mysql:.*$' # 正则表达式
    regionName: # 枚举类型
      type: string,
      description: 地域Region
      default: cn-hangzhou # 默认值
      title: 地域
      enum: # 枚举类型
        - cn-beijing
        - cn-hangzhou
        - cn-shanghai

插件模型代码规范

在插件模型中,代码组成规范有两个部分:

  • package.json中需要描述清楚入口文件所在地址;例如{"main": "./dist/index.js"}
  • 在代码中实现默认等方法。

关于代码规范部分,可以参考如下案例:

const core = require("@serverless-devs/core");
const { lodash, fse, rimraf } = core;
/**
 * Plugin 插件入口
 * @param inputs 组件的入口参数
 * @param args 插件的自定义参数
 * @return inputs
 */

module.exports = async function index(inputs, args) {
  return lodash.merge(inputs, {
    props: {
      function: {
        runtime: "custom",
        codeUri: path.join(__dirname, "./code"),
        customRuntimeConfig: {
          command: ["node"],
          args: ["/code/index.js"],
        },
      },
    },
  });
};

在上面的案例中,插件的方法有两个入参,分别是inputsargs的结构为:

  • inputs参数:

    {
        "command": "", 
        "project": {
            "projectName": "", 
            "component": "",
            "provider": "",
            "access": ""
        },
        "credentials": {},
        "props": {},
        "args": "",
        "argsObj": [],
        "services": [],
        "output": {},
    }
    
    目录含义
    command用户所执行的命令
    project用户的项目基本信息
    credentials用户的密钥信息
    props用户配置的属性/参数
    args用户传递的参数(字符串形式)
    argsObj用户传递的参数(解析后的,以数组形式传递)
    services记录服务的传递参数
    output如果在组件执行之前使用插件,无此参数,如果在组件执行之后使用插件,有此参数,此参数表示组件的输出结果
  • args参数是插件的入参,格式为object

由于返回结果(reutrn),可能会作为组件的输入,所以该格式,与inputs的整体规范基本一致(无outputs对象),即:

{
    "command": "", 
    "project": {
        "projectName": "", 
        "component": "",
        "provider": "",
        "access": ""
    },
    "credentials": {},
    "props": {},
    "args": "",
    "argsObj": [],
    "services": [],
    "plugin": {}
}

例如上面的案例中,返回内容是:

return lodash.merge(inputs, {
    props: {
      function: {
        runtime: "custom",
        codeUri: path.join(__dirname, "./code"),
        customRuntimeConfig: {
          command: ["node"],
          args: ["/code/index.js"],
        },
      },
    },
  });

即将原结构返回,并针对props重的部分参数进行升级。

以一个真实案例作为举例说明:

该组件名为hexo,组件核心代码如上所示,具备一个test方法,此时用户侧的Yaml为:

edition: 1.0.0        #  命令行YAML规范版本,遵循语义化版本(Semantic Versioning)规范
name: FullStack       #  项目名称
access: xxx-account1  #  秘钥别名

services:
  HexoComponent:
    component: hexo
    actions: 
      - pre-deploy:
          - plugin: test
            args:
              key: value
    props:
      region: 'cn-hangzhou'
      codeUri: './src'

当用户执行s test mytest -a -b abc,此时,插件代码中的默认方法,收到的inputs参数实际上是:

{
    "command": "test", 
    "project": {
        "projectName": "HexoComponent", 
        "component": "hexo",
        "provider": "alibaba",
        "access": "release"
    },
    "credentials": {
        "AccountID": "********",
        "AccessKeyID": "********",
        "AccessKeySecret": "********"
    },
    "props": {
        "Region": "cn-hangzhou",
        "CodeUri": "./src"
    },
    "args": "mytest -a -b abc",
    "argsObj": [
      "mytest", "-a", "-b", "abc"
    ]
}

args参数实际上是:

{
  "key": "value"
}
在 GitHub 上编辑本页面 更新时间: Wed, May 10, 2023