Files
devstar/docs/content/development/api-devstar.zh-cn.md
戴明辰 6967ba9889 !12 [Feature][Fix][Doc] repo devcontainer.json parser, WeChat QR Expiration Mask, Zombie Process Mitigation
* [Fix] Zombie/Defunct Processes caused by SSH Daemon
* [Fix]  WeChat QR Expiration Mask with a refresh button
* [Doc] Updated API response field `publicKeySsh` of GET `/api/devstar_ssh/key_pair/new_temp`
* [Feature] Get or default DevContainer image from `.devcontainer/devcontainer.json` parser
2024-10-28 11:35:35 +00:00

18 KiB
Raw Blame History

date, title, slug, sidebar_position, toc, draft, aliases, menu
date title slug sidebar_position toc draft aliases menu
2018-06-24:00:00+02:00 DevStar API 使用指南 api-devstar 40 false false
/zh-cn/api-devstar
sidebar
parent name sidebar_position identifier
development DevStar API 使用指南 40 api-devstar

DevStar API 使用指南

1. 生成临时 SSH 密钥对

请求方式

GET /api/devstar_ssh/key_pair/new_temp?_=${CurrentTimestamp}
请求参数 类型 含义 作用
_ 整数 匿名参数,存放任意值(推荐使用当前的时间戳) 用于防止 HTTP GET 请求被缓存,保证每次请求都能到达服务器端
请求头 载荷 作用
Authorization token ${accessToken} 登录凭证,用于标识用户身份,防止接口被滥用
Content-Type application/json 用于标识返回数据格式是 JSON

响应格式(操作成功)

{
    "code": 0,
    "msg": "操作成功",
    "data": {
        "KeySize": "2048",
        "privateKeyPem": "-----BEGIN RSA PRIVATE KEY-----\n......\n-----END RSA PRIVATE KEY-----\n",
        "publicKeySsh": "ssh-rsa AAAAB3N......\n",
        "publicKeyPem": "-----BEGIN PUBLIC KEY-----\n......\n-----END PUBLIC KEY-----\n"
    }
}

响应数据说明:

  • code: 错误代码,0 表示无错误
  • msg: 错误代码含义,以人类可读的方式描述错误代码的具体含义, 0 代表操作成功
  • data: 返回数据
    • KeySize: 当前系统使用的密钥长度,默认值 2048可在 app.ini 文件中的 devstar.ssh_key_pair.KEY_SIZE 指定大于 2048 位的密钥长度
    • privateKeyPem: PEM 格式的 RSA 私钥,可保存于客户端目录 ~/.ssh/id_rsa 用于 SSH 登录使用的 RSA 私钥
    • publicKeyPem: PEM 格式的 RSA 公钥
    • publicKeySsh: SSH 格式的 RSA 公钥,可保存于服务器目录 ~/.ssh/authorized_keys 用于 SSH 登录使用的 RSA 公钥

响应格式(操作失败:未登录)

{
    "code": 1,
    "msg": "未登录,禁止访问"
}

响应数据说明:

  • code: 错误代码,1 表示发生错误
  • msg: 错误代码含义,以人类可读的方式描述错误代码 1 具体含义: 未登录,禁止访问

响应格式(操作失败:发生内部错误)

{
    "code": 12001,
    "msg": "生成 SSH 密钥对失败",
    "data": {
      "ErrorMsg": "Failed to ${ACTION_NAME} for SSH Key: ${ACTION_RESULT}",
      "KeySize": "2048"
    }
}

响应数据说明:

  • code: 错误代码
  • msg: 错误代码含义,以人类可读的方式描述错误代码具体含义
  • data: 对错误信息进一步描述
    • KeySize: 当前系统使用的密钥长度,默认值 2048可在 app.ini 文件中的 devstar.ssh_key_pair.KEY_SIZE 指定大于 2048 位的密钥长度
    • ErrorMsg: API 调用过程中返回错误信息封装,其中 ACTION_NAME 表示具体操作步骤,ACTION_RESULT 表示具体操作步骤结果

2. DevContainer 管理

DevContainer 是指可以通过 SSH 连接的远程服务器开发容器环境

在 k8s 中DevContainer 被定义为 CRD 资源 DevcontainerApp,具体包含如下资源:

  • StatefulSet: 用于管理有状态应用
  • Service:用于向集群外暴露 DevContainer提供服务访问

k8s CRD 资源 DevcontainerApp 通过 k8s Operator 机制进行管理,可以通过下列 kubectl 命令查看:

kubectl get deployment -n devcontainer-operator-system devcontainer-operator-controller-manager
# NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
# devcontainer-operator-controller-manager   1/1     1            1           2d17h

对于部署在 k8s 上的 DevContainerSSH 连接依此经过:

  1. 云服务厂商的 NAT 路由器
  2. k8s NodePort Service
  3. k8s Pod
  4. k8s Pod 中运行的 OpenSSH 服务器

对 DevContainer 管理主要包括下述操作:

  • 创建一个新的 DevContainer
  • 查看当前用户创建的所有 DevContainer
  • 获取 DevContainer 打开信息
  • 删除 DevContainer

2.1 创建 DevContainer

请求方式

POST /api/devcontainer
请求参数 类型 含义 作用
repoId 字符串 仓库 ID 标识当前用户希望创建 DevContainer 所关联的 仓库
sshPublicKeyList 字符串数组 SSH公钥列表 标识用户除了使用 DevStar 后台添加的用户永久 SSH 公钥外,该 DevContainer SSH 会话使用额外的临时 SSH 公钥列表

注:上述请求参数需要以 JSON 格式封装在 POST 请求 Body 域:

{
    "repoId": "${REPO_ID}",
    "sshPublicKeyList": [
      "ssh-rsa AAAAB3N......Pn9TWOE= SSH_PUBLIC_KEY_1",
      "ssh-rsa AAAAB3N......Pn9TWOE= SSH_PUBLIC_KEY_2",
    ]
}

请求头 载荷 作用
Authorization token ${accessToken} 登录凭证,用于标识用户身份,防止接口被滥用
Content-Type application/json 用于标识返回数据格式是 JSON

响应格式(操作成功)

{
    "code": 0,
    "msg": "操作成功"
}

响应数据说明:

  • code: 错误代码,0 表示无错误
  • msg: 错误代码含义,以人类可读的方式描述错误代码的具体含义, 0 代表创建 DevContainer 成功

响应格式(操作失败:未登录)

{
    "code": 1,
    "msg": "未登录,禁止访问"
}

响应数据说明:

  • code: 错误代码
  • msg: 错误代码含义,以人类可读的方式描述错误代码具体含义

响应格式(操作失败:数据校验失败)

{
    "code": 11002,
    "msg": "无效参数",
    "data": {
      "ErrorMsg": "......"
    }
}

响应数据说明:

  • code: 错误代码
  • msg: 错误代码含义,以人类可读的方式描述错误代码具体含义
  • data: 对错误信息进一步描述
    • ErrorMsg: 描述数据校验失败的报错信息(可能是传入 repoId 不是数字,或者 repoId 字符串长度过长)

响应格式(操作失败:发生内部错误)

{
    "code": 11003,
    "msg": "创建 DevContainer 失败",
    "data": {
      "ErrorMsg": "Failed to ${ACTION_NAME} in DevContainer Service: ${ACTION_RESULT}"
    }
}

响应数据说明:

  • code: 错误代码
  • msg: 错误代码含义,以人类可读的方式描述错误代码具体含义
  • data: 对错误信息进一步描述
    • ErrorMsg: 描述数据校验失败的报错信息,${ACTION_NAME} 表示操作名称,${ACTION_RESULT} 表示操作结果

2.2 获取当前登录用户的 DevContainer 列表

请求方式

GET /api/devcontainer/user?_=${CurrentTimestamp}&page=1&page_size=2
请求参数 类型 含义 作用
_ 整数 匿名参数,存放任意值(推荐使用当前的时间戳) 用于防止 HTTP GET 请求被缓存,保证每次请求都能到达服务器端
page 整数 当前所在页码(默认值 1 用于分页展示 DevContainer
page_size 整数 当前所在页码(必须小于等于默认值:app.ini 中的 ui.admin.DEV_CONTAINERS_PAGING_NUM 用于控制每页展示 DevContainer 个数
请求头 载荷 作用
Authorization token ${accessToken} 登录凭证,用于标识用户身份,防止接口被滥用
Content-Type application/json 用于标识返回数据格式是 JSON

响应格式(操作成功)

{
    "code": 0,
    "msg": "操作成功",
    "data": {
        "userId": 5,
        "username": "daimingchen",
        "devContainers": [
            {
                "devContainerId": 41,
                "devContainerName": "daimingchen-devstar-fa72bebd8bb611ef9c1a4e1bce2a7080",
                "devContainerHost": "devcontainer.devstar.cn",
                "devContainerUsername": "root",
                "devContainerWorkDir": "/data",
                "repoId": 3,
                "repoName": "devstar",
                "repo_owner_name": "devstar",
                "repo_link": "/devstar/devstar",
                "repoDescription": "DevStar Studio"
            },
            {
                "devContainerId": 38,
                "devContainerName": "daimingchen-12-dcbb9c5b8a0611ef9c1a4e1bce2a7080",
                "devContainerHost": "devcontainer.devstar.cn",
                "devContainerUsername": "root",
                "devContainerWorkDir": "/data",
                "repoId": 19,
                "repoName": "12",
                "repo_owner_name": "leviyanx",
                "repo_link": "/leviyanx/12"
            }
        ],
        "page": 1,
        "pageSize": 30,
        "pageTotalNum": 1,
        "itemTotalNum": 2
    }
}

响应数据说明:

  • code: 错误代码,0 表示无错误
  • msg: 错误代码含义,以人类可读的方式描述错误代码的具体含义, 0 代表获取用户 DevContainer 列表成功
  • data: 返回数据
    • userId: 当前已登录用户 ID
    • username: 当前已登录用户名
    • itemTotalNum: 当前用户 DevContainer 总数
    • pageSize: 每个页面最多展示 DevContainer 个数
    • page: 当前页码
    • devContainers: 当前页面 DevContainer 列表
    • pageTotalNum: 总页数

其中,对于 devContainers 中的每个元素,具体含义如下:

字段名称 类型 含义
devContainerId 整数 DevContainer ID
devContainerName 字符串 唯一标识 DevContainer 名称
devContainerHost 字符串 SSH 连接主机的 IP 或者 DNS 域名
devContainerUsername 字符串 SSH 登录用户名
devContainerWorkDir 字符串 SSH 登录成功后工作目录
repoId 整数 DevContainer 关联的仓库的 ID
repoName 字符串 DevContainer 关联的仓库的名称
repo_owner_name 字符串 DevContainer 关联的仓库的所有者用户 ID
repo_link 字符串 DevContainer 关联的仓库的访问绝对地址 URL
repoDescription 字符串 DevContainer 关联的仓库的描述信息(可选字段)

响应格式(操作失败:未登录)

{
    "code": 1,
    "msg": "未登录,禁止访问"
}

响应数据说明:

  • code: 错误代码
  • msg: 错误代码含义,以人类可读的方式描述错误代码具体含义

响应格式(操作失败:发生内部错误)

{
    "code": 11006,
    "msg": "查询用户 DevContainer 列表失败",
    "data": {
      "ErrorMsg": "Failed to ${ACTION_NAME} in DevStar DevContainer DB: ${ACTION_RESULT}"
    }
}

响应数据说明:

  • code: 错误代码
  • msg: 错误代码含义,以人类可读的方式描述错误代码具体含义
  • data: 对错误信息进一步描述
    • ErrorMsg: 描述数据校验失败的报错信息,${ACTION_NAME} 表示操作名称,${ACTION_RESULT} 表示操作结果

2.3 打开 DevContainer

请求方式

GET /api/devcontainer?_=${CurrentTimestamp}&repoId=${REPO_ID}&wait=${IS_WAITING}
请求参数 类型 含义 作用
_ 整数 匿名参数,存放任意值(推荐使用当前的时间戳) 用于防止 HTTP GET 请求被缓存,保证每次请求都能到达服务器端
repoId 字符串 仓库 ID 根据仓库打开关联的 DevContainer
wait 布尔 是否阻塞等待 DevContainer 就绪 是否注册监听器,在超时时间内阻塞等待 DevContainer 就绪
请求头 载荷 作用
Authorization token ${accessToken} 登录凭证,用于标识用户身份,防止接口被滥用
Content-Type application/json 用于标识返回数据格式是 JSON

响应格式(操作成功)

{
    "code": 0,
    "msg": "操作成功",
    "data": {
        "devContainerId": 38,
        "devContainerName": "daimingchen-12-dcbb9c5b8a0611ef9c1a4e1bce2a7080",
        "devContainerHost": "devcontainer.devstar.cn",
        "devContainerUsername": "root",
        "devContainerWorkDir": "/data",
        "repoId": 19,
        "repoName": "12",
        "repo_owner_name": "leviyanx",
        "repo_link": "/leviyanx/12",
        "devContainerPort": 30000
    }
}

响应数据说明:

  • code: 错误代码,0 表示无错误
  • msg: 错误代码含义,以人类可读的方式描述错误代码的具体含义, 0 代表获取用户 DevContainer 连接信息成功
  • data: 返回数据
    data 字段名称 类型 含义
    devContainerId 整数 DevContainer ID
    devContainerName 字符串 唯一标识 DevContainer 名称
    devContainerHost 字符串 SSH 连接主机的 IP 或者 DNS 域名
    devContainerPort 整数 SSH 连接主机的端口号
    devContainerUsername 字符串 SSH 登录用户名
    devContainerWorkDir 字符串 SSH 登录成功后工作目录
    repoId 整数 DevContainer 关联的仓库的 ID
    repoName 字符串 DevContainer 关联的仓库的名称
    repo_owner_name 字符串 DevContainer 关联的仓库的所有者用户 ID
    repo_link 字符串 DevContainer 关联的仓库的访问绝对地址 URL
    repoDescription 字符串 DevContainer 关联的仓库的描述信息(可选字段)

响应格式(操作失败:未登录)

{
    "code": 1,
    "msg": "未登录,禁止访问"
}

响应数据说明:

  • code: 错误代码
  • msg: 错误代码含义,以人类可读的方式描述错误代码具体含义

响应格式(操作失败:无效参数)

{
    "code": 11002,
    "msg": "无效参数"
}

响应数据说明:

  • code: 错误代码
  • msg: 错误代码含义,以人类可读的方式描述错误代码具体含义

响应格式(操作失败:发生内部错误,包括 DevContainer 未在超时时间内就绪)

{
    "code": 11004,
    "msg": "打开 DevContainer 失败",
    "data": {
      "ErrorMsg": "......"
    }
}

响应数据说明:

  • code: 错误代码
  • msg: 错误代码含义,以人类可读的方式描述错误代码具体含义
  • data: 对错误信息进一步描述
    • ErrorMsg: 描述数据校验失败的报错信息
      • 参数无效Illegal Params
      • DevContainer 未找到DevContainer NOT found in repo '${REPO_NAME}'(repoId = ${REPO_ID}) of user '${USERNAME}'(userId = ${USER_ID})
      • 其他Failed to ${ACTION_NAME} in DevContainer Service: ${ACTION_RESULT}

补充 如何判断 DevContainer 就绪状态

在 k8s 中DevContainer 以 k8s CRD DevcontainerApp 资源定义,可参考如下 YAML:

apiVersion: devcontainer.devstar.cn/v1
kind: DevcontainerApp
metadata:
  name: studio-test
  namespace: devstar-studio-ns
spec:
  statefulset:
    image: devstar.cn/public/base-ssh-devcontainer:ubuntu-20.04-20241014
    gitRepositoryURL: https://gitee.com/daimingchen_gitee/mock-repo
    command:
      - /bin/bash
      - -c
      - service ssh restart && tail -f /dev/null
    containerPort: 22
    sshPublicKeyList:
      - ssh-rsa AAA......e8 SSHPublicKey
      - ssh-rsa AAA......e9 YetAnotherSSHPublicKey

使用 kubectl 创建 DevcontainerApp:

kubectl apply -f devcontainerapp-demo.yaml

等待一段时间后,获取 DevcontainerApp studio-test 的状态:

kubectl get devcontainerapp -n devstar-studio-ns studio-test -o yaml

即可得到下列 YAML

apiVersion: devcontainer.devstar.cn/v1
kind: DevcontainerApp
metadata:
  name: studio-test
  namespace: devstar-studio-ns
  creationTimestamp: "2024-10-16T12:05:47Z"
  generation: 1
  resourceVersion: "92973809"
  uid: 867c8bc6-1b79-4c41-8659-686b176f4c56
spec:
  statefulset:
    image: devstar.cn/public/base-ssh-devcontainer:ubuntu-20.04-20241014
    gitRepositoryURL: https://gitee.com/daimingchen_gitee/mock-repo
    command:
      - /bin/bash
      - -c
      - service ssh restart && tail -f /dev/null
    containerPort: 22
    sshPublicKeyList:
      - ssh-rsa AAA......e8 SSHPublicKey
      - ssh-rsa AAA......e9 YetAnotherSSHPublicKey
status:
  nodePortAssigned: 30000
  ready: true

更详细地,status.ready 域具体赋值由下列两个指标判断:

  • 分配的 NodePort 端口值 nodePortAssigned 取值范围在左闭右闭区间 [30000, 32767]
  • StatefulSet 控制下的 Pod 中的容器就绪探针探测成功

总之,在 DevStar Studio 中,只需要读取集群中 k8s CRD DevcontainerAppstatus.ready 域即可判断 DevContainer 是否就绪

2.4 删除 DevContainer

请求方式

DELETE /api/devcontainer?repoId=${REPO_ID}
请求参数 类型 含义 作用
repoId 字符串 仓库 ID 根据仓库打开关联的 DevContainer
请求头 载荷 作用
Authorization token ${accessToken} 登录凭证,用于标识用户身份,防止接口被滥用
Content-Type application/json 用于标识返回数据格式是 JSON

响应格式(操作成功)

{
    "code": 0,
    "msg": "操作成功"
}

响应格式(操作失败:未登录)

{
    "code": 1,
    "msg": "未登录,禁止访问"
}

响应格式(操作失败:未找到 DevContainer)

{
    "code": 11005,
    "msg": "删除 DevContainer 失败",
    "data": {
        "ErrorMsg": "Illegal Params: [opts.RepoId]"
    }
}