# 应用上架
# 一、注册
要在平台上架应用,首先需要注册应用,待平台审核通过后,获取相关 KEY 和 SECRET 进行应用开发。
单位管理员从左侧菜单进入【单位管理-应用中心-应用市场-开发者中心】,点击【注册】即可注册应用。
# 应用注册信息说明
# 应用适配平台。
目前主要分为三类:面向 PC 端,面向移动端和自适应多平台。
# 应用类型
按照应用功能分类。目前分为:资产应用,财务应用,办公应用,人事应用,大数据应用,物联网应用,区块链应用等。
# 目标用户
按照应用分发对象分为:集团应用,单位应用,个人应用。
- 集团应用由集团订阅后分发,可以获取到集团树,如报表应用
 - 单位应用由单位订阅,如单位内控应用
 - 个人应用一般为不依赖组织架构的应用
 
# 获取应用 KEY 和 SECRET
提交应用注册信息,经过平台管理员审核后,既可以获取应用 KEY 和 SECRET
# 二、开发
应用注册审核通过后,根据应用的 KEY 和 SECRET 调用平台提供的相关消息和接口进行应用开发
# 查看 KEY 和 SECRET
单位管理员从左侧菜单进入【单位管理-应用中心-应用市场-开发者中心】,点击行内按钮【运维】。
 
 # 前端开发
平台提供了前端 SDK,用于开发者调用平台提供的能力
导入和初始化
导入方式有两种,script 标签引入或者 npm 包引入
# script 标签引入
<script src="dist/sdk.umd.js"></script> <script> var ac = new ACSDK.SdkClient(); ac.init().then(function() { console.log("SDK已初始化"); }); </script># npm 包引入(推荐)
import SdkClient from "@assetcloud/asset-sdk"; // 初始化时可设定超时时间(秒) const ac = new SdkClient(5); await ac.init();监听和发送消息
处理消息有两种方法,添加事件监听器和直接异步发送消息并等待返回结果。
a. 直接监听事件&直接发送消息
- 支持接收来自平台主动推送的消息。
 - 支持发送没有响应结果的消息。
 
ac.addEventListener("GET_USER", (e) => { console.log(e.data.data.userId); }); ac.send("GET_USER");b. 发送消息并等待返回结果
返回
Promise,如果平台返回值的success字段为false,会自动触发 reject。try { const res = await ac.sendAsync("GET_USER"); const { userId } = res.data.data; } catch (error) { console.error(error.data.msg); }返回结果类型
AssetCloudEvent<T extends AssetCloudMessage>字段 类型 说明 data data AssetCloudMessageMap[T]承载数据 code number状态码 success boolean是否成功 msg string返回消息 type T消息类型 
# 前端可用消息
| 功能 | 消息类型  AssetCloudMessage  |  请求参数 | 返回结果中 data 的格式 AssetCloudMessageMap[T]  | 
|---|---|---|---|
| 获取用户 Id | GET_USER | 无 | { userId: string } | 
| 获取用户账号 | GET_USER_PHONE | 无 | { phone: string } | 
| 获取当前用户所属集团列表 | GET_GROUP | 无 | { groupIds: object[] } | 
| 在浏览器打开新的标签页 | OPEN_TAB | 需要打开的 url, 如:"http://www.baidu.com"  |  — | 
| 在平台打开应用 | OPEN_MENU | pcformlink:要跳转的链接地址 | { pcformlink:string } | 
| 跳转到平台首页 | GO_HOME | 无 | — | 
| 跳转到平台待办 | GO_TODO | 无 | — | 
| 获取当前应用入口菜单 | GET_MENU | 无 | object | 
| 获取当前平台主题色 | GET_THEME | 无 | {theme: string} | 
# 后端开发
平台提供了后端 SDK,用于开发者调用平台开放的接口
新建一个对象AssetCloudRequest()
url:完整的请求路径 https://platform.assetcloud.org.cn/dev-api/+请求路径;key、secret:平台获取的 key 和 secret
Get 调用方法:
AssetCloudRequest request = new AssetCloudRequest();
request.setUrl("");
request.setKey("");
request.setSecret("");
request.setHttpMethods(HttpMethods.GET);
HttpRequestUtil.send(request);
Post 调用方法:
AssetCloudRequest request = new AssetCloudRequest();
request.setUrl("");
request.setKey("");
request.setSecret("");
request.setBody("");
request.setHttpMethods(HttpMethods.POST);
HttpRequestUtil.send(request);
Delete 调用方法:
AssetCloudRequest request = new AssetCloudRequest();
request.setUrl("");
request.setKey("");
request.setSecret("");
request.setHttpMethods(HttpMethods.DELETE);
HttpRequestUtil.send(request);
Put 调用方法:
AssetCloudRequest request = new AssetCloudRequest();
request.setUrl("");
request.setKey("");
request.setSecret("");
request.setBody("");
request.setHttpMethods(HttpMethods.Put);
HttpRequestUtil.send(request);
返回结果为:AssetCloudResponse<T>
| 字段 | 类型 | 说明 | 
|---|---|---|
| code | int | 状态码 | 
| success | Boolean | 是否成功 | 
| data | T | 承载数据 | 
| msg | String | 返回消息 | 
# 后端可用接口
- 获取当前用户信息
 
# SDK 实现说明
# 前端通信
通信规则
平台返回数据格式
{
  data: {},           //数据
  from: "HOST",       //数据发送源
  to: "",             //数据接收源
  code: "200",        //请求码
  success: true,      //请求状态
  msg: "发送成功",     //请求消息
  type: "GET_USER",   //当前消息类型
}
第三方发送数据格式
{
  data: {}, //[可选]数据
  from: `${window.location.origin}${window.location.pathname}`, //[必填]数据发送源,固定内容
  to: "*", //[必填]数据接收源,固定内容
  type: "", //[必填]当前消息类型,根据平台提供接口设置
  checkCode: "", //[必填]时间戳
}
通信方式
监听平台消息,处理返回数据
window.addEventListener("message", (e) => { if (e.data.from === "HOST") { //处理平台返回的数据 let data = e.data; //来自平台的数据 if (data.type == "GER_USER") { this.getUserInfo(data.data); //调用后端接口访问中台数据 } } });向平台发送消息,获取请求参数
window.top.postMessage( { data: {}, from: `${window.location.origin}${window.location.pathname}`, to: "*", type: "GET_USER", checkCode: new Date().getTime(), }, "*" );
# 后端使用 KEY 和 SECRET
应用开发者通过使用 key 和 secret 访问平台接口。
# 接口访问方式:GET
# 请求头 Headers:添加应用 key
例如:key:2b3dd4af198c4f49935de8cadf049fc9D3hw8EcAyOA211Ib47
 # 请求参数类型
在请求参数的最后按顺序添加如下参数:
- timestamp: 当前时间戳,精确到毫秒级,long 类型
 - sign: String 类型。所有请求参数(包括上面的时间戳)串联起来(包括&符号)的字符串,根据HmacSHA256算法用 secret 生成签名 sign
 
以访问http://127.0.0.1:8088/asset-system/person/get/person/by/id 接口,传入用户 id,获取用户信息为例:
let userId = req.query.userId; //前端通过消息机制获取的平台提供的用户Id
let timestamp = Date.parse(new Date()); //获取当前时间戳
//以CryptoJS为例,调用CryptoJS.HmacSHA256,传入请求参数串联的字符串和应用secret,生成sign
let hash = CryptoJS.HmacSHA256(
  "userId=" + userId + "×tamp=" + timestamp,
  "c38fac5362014ae497ef355e457740cfB1DD0FF4CF774E64F92952106943E3350703FEE32EE412817FF703DF67FAD1C265B3"
);
request(
  {
    headers: {
      Connection: "close",
      key: "2b3dd4af198c4f49935de8cadf049fc9D3hw8EcAyOA211Ib47",
    },
    url: "http://127.0.0.1:8088/asset-system/person/get/person/by/id",
    method: "GET",
    json: true,
    body: req.body,
    qs: {
      userId: userId,
      timestamp: timestamp,
      sign: hash.toString(CryptoJS.enc.Hex), //转换成字符串
    },
  },
  (error, response, data) => {
    //将平台返回的用户信息发送给前端
    res.send(data);
  }
);
Postman 请求示例:
 # 三、部署
# 部署应用
应用分为集中部署和独立部署
- 集中部署是指平台统一提供资源,统一部署。集中部署的应用,应填写应用部署相关信息,上传应用 helm 包,提交后等待平台管理员审核。
 - 独立部署是指在自有资源部署应用,注册到平台管理的应用。独立部署应用跳过这一步直接进入下一环节。
 
# 应用打包规范
应用以 Helm Chart 的形式上传部署到平台中。
- 准备 Helm 客户端工具
 
安装 Helm 客户端工具,若您的个人环境还没有安装 Helm 客户端工具,请参考 Helm 安装文档 (opens new window)。
- 准备本地仓库
 
执行下列命令,在本地创建目录作为本地仓库。
$ mkdir helm-repo
$ cd helm-repo
- 创建应用
 
执行 helm create 创建一个名为 nginx 的文件夹且默认生成一个 nginx 基本的 yaml 文件模板和目录,通常情况下不建议修改生成的一级目录下文件和目录的命名。
$ helm create nginx
$ tree nginx/
nginx/
├── charts
├── Chart.yaml
├── templates
│   ├── deployment.yaml
│   ├── _helpers.tpl
│   ├── ingress.yaml
│   ├── NOTES.txt
│   └── service.yaml
└── values.yaml
2 directories, 7 files
Chart.yaml 是用于描述 Chart 的基本信息,包括名称、API 和应用版本等,其中 appVersion 字段与 version 字段无关。这是一种指定应用程序版本的方法详见 Chart.yaml 文件。
Chart.yaml 文件示例:
apiVersion: v1
appVersion: "1.0"
description: A Helm chart for Kubernetes
name: nginx
version: 0.1.0
包含在 chart 内的默认 values 文件必须命名 values.yaml,可以为 chart 及其任何依赖项提供值。通过 values.yaml 文件提供的值可以从.Values 模板中的对象访问。在部署 Helm Chart 类型的应用到 Kuberntes 运行环境时,支持在 UI 界面可以对 values.yaml 进行编辑配置。
values.yaml:
# Default values for test.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
  repository: nginx
  tag: stable
  pullPolicy: IfNotPresent
nameOverride: ""
fullnameOverride: ""
service:
  type: ClusterIP
  port: 80
ingress:
  enabled: false
  annotations:
    {}
    # kubernetes.io/ingress.class: nginx
    # kubernetes.io/tls-acme: "true"
  path: /
  hosts:
    - chart-example.local
  tls: []
  #  - secretName: chart-example-tls
  #    hosts:
  #      - chart-example.local
resources:
  {}
  # We usually recommend not to specify default resources and to leave this as a conscious
  # choice for the user. This also increases chances charts run on environments with little
  # resources, such as Minikube. If you do want to specify resources, uncomment the following
  # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
  # limits:
  #  cpu: 100m
  #  memory: 128Mi
  # requests:
  #  cpu: 100m
  #  memory: 128Mi
nodeSelector: {}
tolerations: []
affinity: {}
可根据 Helm 应用开发规范 编辑 nginx 目录下文件,编辑好后保存。
- 生成索引文件(可选)
 
若添加 HTTP 或 HTTPS 协议的仓库,则需要预先在对象存储中上传索引文件 index.yaml,该文件由 Helm 客户端工具生成。若添加 S3 协议的仓库,在上传应用到仓库时将自动在对象存储中生成索引文件。在 nginx 上一级目录执行以下命令生成索引文件:
$ helm repo index .
$ ls
index.yaml  nginx
- 打包应用
 
回到 nginx 上级目录,执行打包命令,将生成一个 tgz 格式的压缩文件,即 nginx 应用配置包:
$ helm package nginx
$ ls
nginx  nginx-0.1.0.tgz
至此,应用配置包就已经准备完毕。
# 上传应用
接下来就可以通过开发者中心上传应用到平台,由平台管理员部署应用到 K8S 中。
# Helm 开发模板参考
Helm Chart 是一种打包规范,将各种 Kubernetes 资源以配置文件的形式组织。更详细的介绍请参考 Chart 官网文档 (opens new window)
# Chart 文件结构
一个 Chart 包由以下几个配置文件组成:
wordpress/
  Chart.yaml          # Yaml文件,用于描述 Chart 的基本信息,包括名称版本等
  LICENSE             # [可选] 文本格式的协议
  README.md           # [可选] 应用介绍、使用说明
  requirements.yaml   # [可选] 用于存放当前 Chart 依赖的其它 Chart 的说明文件
  values.yaml         # Chart 的默认值配置文件
  charts/             # [可选] 该目录中放置当前 Chart 依赖的其它 Chart
  templates/          # [可选] 部署文件模版目录,模版填入 values.yaml 中相应值,生成最终的 kubernetes 配置文件
  templates/NOTES.txt # [可选] 使用指南
# Chart.yaml 文件
apiVersion: [必须] Chart API 版本,可用值 v1
name: [必须] Chart 名称
version: [必须] 版本,遵循 [SemVer 2 标准](https://semver.org/)
kubeVersion: [可选] 兼容的 Kubernetes 版本,遵循 [SemVer 2 标准](https://semver.org/)
description: [可选] 一句话的应用描述
keywords:
  - [可选] 应用关键字列表
home: [可选] 应用主页 URL
sources:
  - [可选] 当前应用下载地址列表
maintainers: [可选]
  - name: [必须] name
    email: [可选] email
    url: [可选] url
engine: [可选] 模板引擎,默认值是 gotpl
icon: [可选] SVG 或者 PNG 格式的图片地址
appVersion: [可选] 应用版本
deprecated: [可选] boolean 类型,是否不建议使用
tillerVersion: [可选] Chart 需要的 Tiller 版本,遵循 [SemVer 2 标准](https://semver.org/),需要 ">2.0.0"
# Requirements.yaml 文件和 Charts 目录
Chart 支持两种方式表示依赖关系,可以写入 requirements.yaml 文件动态链接[推荐],也可以将依赖的 Chart 放入 charts 目录手动管理。
requirements.yaml 文件样例:
dependencies:
  - name: apache
    version: 1.2.3
    repository: http://example.com/charts
  - name: mysql
    version: 3.2.1
    repository: http://another.example.com/charts
- name:Chart 名称
 - version:Chart 版本
 - repository: Chart 仓库 URL 地址
 
有了 requirements.yaml 文件,可以运行 helm dependency update,依赖的 Chart 会被自动的下载到 charts 目录下。
# Values.yaml 文件和 Templates 目录
values.yaml 文件中记录了模板中引用的默认值。
templates 目录中存放了 Kubernetes 部署文件的模版,遵循 Go template 语法 (opens new window)
templates 中模板文件样例:
apiVersion: v1
kind: ReplicationController
metadata:
  name: deis-database
  namespace: deis
  labels:
    app.kubernetes.io/managed-by: deis
spec:
  replicas: 1
  selector:
    app.kubernetes.io/name: deis-database
  template:
    metadata:
      labels:
        app.kubernetes.io/name: deis-database
    spec:
      serviceAccount: deis-database
      containers:
        - name: deis-database
          image: {{.Values.imageRegistry}}/postgres:{{.Values.dockerTag}}
          imagePullPolicy: {{.Values.pullPolicy}}
          ports:
            - containerPort: 5432
          env:
            - name: DATABASE_STORAGE
              value: {{default "minio" .Values.storage}}
上述样例是一个 k8s 中 replication controller 的模板文件定义,其中引用了以下几个值(一般定义在 values.yaml 中)
- imageRegistry:Docker 映像仓库
 - dockerTag: Docker 映像标签
 - pullPolicy: 下载映像策略
 - storage: 存储后端,默认值是 "minio"
 
values.yaml 文件样例:
imageRegistry: "quay.io/deis"
dockerTag: "latest"
pullPolicy: "Always"
storage: "s3"
# 部署环境
TODO
# 鉴权
TODO
# 四、测试
# 五、发布
# 填写应用发布信息
应用部署通过平台管理员审核后,填写应用发布相关信息。
# 应用菜单权限注册
注册应用对应的角色,给每个角色分配菜单。url 需要填写完成路径信息,如:http://www.assetcloud.org.cn。
完成角色菜单注册后,提交发布后,等待平台管理员审核。