This commit is contained in:
Darren 2023-07-20 17:51:24 +08:00 committed by GitHub
parent cb0cf9f758
commit 4cbf0ed576
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 375 additions and 408 deletions

View file

@ -6,7 +6,7 @@
# What is Websoft9?
Websoft9 is web-based PaaS for running 200+ hot [open source application](https://github.com/Websoft9/docker-library/tree/main/apps) on your own server.
Websoft9 is web-based PaaS platform for running 200+ hot [open source application](https://github.com/Websoft9/docker-library/tree/main/apps) on your own server.
Websoft9 help you running multiple applications in a single server, that means we believe Microservices on single machine is reasonable. On the contrary, it becomes more and more valuable as computing power increases
@ -44,18 +44,14 @@ You should have root privileges user to install or upgrade Websoft9, if you use
wget https://websoft9.github.io/websoft9/install/install.sh && bash install.sh
```
When installation completed, you can access it by: **http://Internet IP:9000** and using **Linux user** for login
## Upgrade
```
curl https://websoft9.github.io/websoft9/install/update.sh | bash
```
## Getting Started
Using local Chrome or Firefox to visit the URL http://domain:9000 name or http://Internet IP:9000, you will enter the websoft9
> Login using the username and password of the Linux operating system
# Contributing
Follow the [contributing guidelines](CONTRIBUTING.md) if you want to propose a change in the Websoft9 core. For more information about participating in the community and contributing to the Websoft9 project, see [this page](https://support.websoft9.com/docs/community/contributing).

View file

@ -1,4 +1,8 @@
# 概述
# AppManage
appmange 是软件商店的一个重要微服务管理商店App的安装、卸载、启动、停止以及查询功能。
AppManage is the core of Websoft9 which can manage application: Create, Stop, Uninstall, Listing
* [API-design](docs/API-design.md)
* [Architecture](docs/architecture.md)
* [Developer](docs/developer.md)

View file

@ -0,0 +1,289 @@
# API Design
## API 结构
### 请求
#### 请求方式
支持如下两种调用方式:
- get
- post
#### 请求头(公共参数)
| 参数名称 | 用途 | 类型 | 必要性 |
| -------- | ------------ | ------ | ------ |
| Version | 接口版本 | string | 可选 |
| Language | 接口显示语言 | string | 可选 |
#### 安全验证
本微服务没有安全验证模块,需通过 API 网关实现
#### 请求主体
[业务接口详情](#业务接口详情)
### 响应结果
#### 响应头(公共参数)
| 返回参数 | 用途 | 类型 | 必要性 |
| ----------- | ---------------------------------- | ------- | ------ |
| HTTP 状态码 | 判断接口调用是否成功200 或 404 | Integer | 必须 |
#### 响应主体
| 返回参数 | 用途 | 类型 | 必要性 |
| ------------ | -------------------- | -------------------- | ---------------------- |
| ResponseData | 各个接口的业务数据 | object(依据接口而异) | 必须 |
| Error | 错误 code 和错误信息 | ErrorInfo | 非必须 ,无错误时不返回 |
```
{
"ResponseData": {
app_id: "xxxx",
StatusReason: {
Code: "Requirement.NotEnough",
Message: "Insufficient system resources (cpu, memory, disk space).",
Detail: "Error detail information"
}
},
"Error": {
Code: "Requirement.NotEnough",
Message: "Insufficient system resources (cpu, memory, disk space).",
Detail: "Error detail information"
}
}
```
#### 错误代码设计
错误代码参考 [AWS API](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/errors-overview.html) 的分类方式:
- Client errors: These errors are usually caused by something the client did, such as specifying an incorrect or invalid parameter in the request, or using an action or resource on behalf of a user that doesn't have permission to use the action or resource. These errors are accompanied by a 400-series HTTP response code.
- Server errors: These errors are usually caused by an AWS server-side issue. These errors are accompanied by a 500-series HTTP response code.
##### Client errors
| code | message | detail |
| ------------------------------------- | -------------- | ------ |
| Client.Parameter.Blank.Error | p 必填参数为空 | null |
| Client.Parameter.Format.Error | p 参数语法不符 | null |
| Client.Parameter.Value.NotExist.Error | p 参数值错误 | null |
| Client.Parameter.Value.Repeat.Error | p 参数值重复 | null |
##### Server errors
| code | message | detail |
| ---------------------- | ---------------------- | ------------ |
| Server.Container.Error | Docker 返回原始错误 | 错误详细信息 |
| Server.SystemError | 系统原始错误 | 错误详细信息 |
| Server.\*\*\* | 其他可以友好提示的错误 | 错误详细信息 |
## 业务接口详情
各个业务接口的详细说明,公共参数不在这里继续说明。
### App 安装
#### Action
AppInstall
#### 请求参数
| 参数名称 | 用途 | 类型 | 必要性 |
| ----------------- | ------------------ | ------ | ------ |
| app_name | 应用名称 | string | 必须 |
| customer_app_name | 用户自定义应用名称 | string | 必须 |
| app_version | 应用版本 | string | 必须 |
#### 返回结果
| 返回值 | 类型 | 必要性 |
| ------------ | ------------- | ------ |
| ResponseData | String(AppID) | 必须 |
| Error | ErrorInfo | 非必须 |
### App 卸载
#### Action
AppUninstall
#### 请求参数
| 参数名称 | 用途 | 类型 | 必要性 |
| -------- | ---------- | ------ | ------ |
| app_id | 卸载该 app | string | 必须 |
#### 返回结果
| 返回值 | 类型 | 必要性 |
| ------------ | ------------- | ------ |
| ResponseData | String(AppID) | 必须 |
| error | ErrorInfo | 非必须 |
### App 重启
#### Action
AppRestart
#### 请求参数
| 参数名称 | 用途 | 类型 | 必要性 |
| -------- | ---------- | ------ | ------ |
| app_id | 重启该 app | string | 必须 |
#### 返回结果
| 返回值 | 类型 | 必要性 |
| ------------ | ------------- | ------ |
| ResponseData | String(AppID) | 必须 |
| error | ErrorInfo | 非必须 |
### App 启动
#### Action
AppStart
#### 请求参数
| 参数名称 | 用途 | 类型 | 必要性 |
| -------- | ---------- | ------ | ------ |
| app_id | 启动该 app | string | 必须 |
#### 返回结果
| 返回值 | 类型 | 必要性 |
| ------------ | ------------- | ------ |
| ResponseData | String(AppID) | 必须 |
| error | ErrorInfo | 非必须 |
### App 停止
#### Action
AppStop
#### 请求参数
| 参数名称 | 用途 | 类型 | 必要性 |
| -------- | ---------- | ------ | ------ |
| app_id | 停止该 app | string | 必须 |
#### 返回结果
| 返回值 | 类型 | 必要性 |
| ------------ | ------------- | ------ |
| ResponseData | String(AppID) | 必须 |
| error | ErrorInfo | 非必须 |
### App 状态查询
#### Action
AppStatus
#### 请求参数
| 参数名称 | 用途 | 类型 | 必要性 |
| -------- | ----------------- | ------ | ------ |
| app_id | 查询该 app 的信息 | string | 必须 |
#### 返回结果
| 返回值 | 类型 | 必要性 |
| ------------ | ------------- | ------ |
| ResponseData | AppStatusInfo | 必须 |
| error | ErrorInfo | 非必须 |
AppStatusInfo 说明:
```
{
app_id应用ID,
status应用运行状态,[installing(创建中)running(运行中)exited(停止)restarting(反复重启)failed(失败)]
status_reason{ // 只有failed时才有内容
Code错误代码
Message错误提示信息
Detail错误真实信息
}
}
```
### App 列表查询
#### Action
AppList
#### 请求参数
| 参数名称 | 用途 | 类型 | 必要性 |
| -------- | -------------- | ------ | ------ |
| app_id | 查询指定的 app | string | 非必须 |
#### 返回结果
| 返回值 | 类型 | 必要性 |
| ------------ | ---------------------- | ------ |
| ResponseData | Array of AppDetailInfo | 必须 |
| error | ErrorInfo | 非必须 |
AppDetailInfo 说明:
```
{
app_id应用ID,
name应用名,
customer_name自定义应用名,
trade_mark应用商标,
status应用运行状态,[installing(创建中)running(运行中)exited(停止)restarting(反复重启)failed(失败)]
status_reason{ // 只有failed时才有内容
Code错误代码
Message错误提示信息
Detail错误真实信息
},
official_app是否为官方应用,
image_url图片路径,
running_info: { // 只有status=running才有值其他时候为空
port应用端口,
compose_filedocker compose文件路径,
url应用网址,
admin_url管理员网址,
user_name用户名,
password密码,
default_domain: 默认域名,
set_domain: 用户自定义域名,
}
}
```

View file

@ -1,22 +0,0 @@
# Administrator 管理手册
## 环境
### 安装组件
1. python 环境
确保安装 python3.6+
2. python 的 pip 包 fastapi,uvicorn[standard],gunicorn
```
pip install -r requirements.txt
```
3. 安装 docker 以及 docker compose、创建 docker 网络 websoft9
### 启动
```
git clone https://github.com/Websoft9/stackhub.git && cd stackhub/docker/appmanage && docker compose up -d
```

View file

@ -1,37 +1,82 @@
# appmanage
# Architecture
![image](https://user-images.githubusercontent.com/43192516/231104572-a57940b1-273b-4761-ae82-7139a8966f70.png)
AppManage is develop by Python3.10, use [FastAPI](https://github.com/Websoft9/stackhub/blob/main/appmanage/docs/developer.md), [RQ](https://python-rq.org/), logging packages and Redis, Sqlite for data storage
It have the privilege of host machine, and running below jobs on host:
* docker and docker compose
* modify file
## RQ
## Asynchronous jobs - RQ
### 设计
Create application by docker some time need many time, so we use [RQ](https://python-rq.org/) for queueing jobs and processing them in the background with workers
RQ 用于异步处理**创建应用**的事务任务,需保证任务成功或失败后续处理。
它提供的状态有:
- creating: 创建中
- failed: 创建失败
![image](images/rq.png)
### RQ status
RQ sample for development:
RQ 主要解决创建应用的状态
```
# Job started
rq worker --url redis://websoft9-redis:6379/0
![image](https://user-images.githubusercontent.com/43192516/231103506-22bbfc80-f31f-4ba0-a331-4a05a345ec25.png)
# RQ 队列创建:
## 指定 Redis 容器的主机名和端口
redis_conn = Redis(host='websoft9-redis', port=6379)
## docker compose status
## 使用指定的 Redis 连接创建 RQ 队列
q = Queue(connection=redis_conn,default_timeout=3600)
- running: 运行中
- exited: 停止
- restarting: 重启
- created: 创建失败
#RQ 队列新增排队任务:
q.enqueue(install_app_delay, app_name, customer_name, app_version, job_id=app_id)
## API status
#获取队列中任务的信息
## 获取 StartedJobRegistry 实例
started = StartedJobRegistry(queue=q)
finish = FinishedJobRegistry(queue=q)
deferred = DeferredJobRegistry(queue=q)
failed = FailedJobRegistry(queue=q)
scheduled = ScheduledJobRegistry(queue=q)
cancel = CanceledJobRegistry(queue=q)
## 获取正在执行的作业 ID 列表
run_job_ids = started.get_job_ids()
finish_job_ids = finish.get_job_ids()
wait_job_ids = deferred.get_job_ids()
failed_jobs = failed.get_job_ids()
scheduled_jobs = scheduled.get_job_ids()
cancel_jobs = cancel.get_job_ids()
```
## Logs partition
```
logPath = 'logs/'
if not os.path.exists(logPath):
os.makedirs(logPath)
logName = 'app_manage.log'
logFile = logPath + logName
formatter = logging.Formatter('%(asctime)s %(levelname)s: %(message)s')
# handler
time_rotating_file_handler = handlers.TimedRotatingFileHandler(filename=logFile, when="MIDNIGHT", interval=1, encoding='utf-8')
time_rotating_file_handler.setLevel(logging.DEBUG)
time_rotating_file_handler.setFormatter(formatter)
```
## Application Status
Application status is very import for developer to understand AppManage, it combine the [Docker compose status](https://docs.docker.com/engine/reference/commandline/compose_ps/#options) and [RQ status](https://python-rq.org/docs/job_registries/)
- installing(创建中): 来源于 RQ 的queue或StartedJobRegistry 可进行操作[无法进行任何操作]
- running(运行中): 来源于docker compose可进行操作[所有操作]
- exited(停止): 来源于docker compose可进行操作[Start,Restart,Uninstall,日志查看]
- restarting(反复重启): 来源于docker compose可进行操作[Stop,Restart,Uninstall,日志查看]
- failed(失败): 来源于 docker compose 中的 created || RQ 的 FailedJobRegistry 可进行操作[Uninstall]
> docker compose have status: [paused | restarting | removing | running | dead | created | exited]
## API
FastAPI can create API and API docs of swagger, you can get [API design details](API-design.md)

View file

@ -1,289 +1,19 @@
# API 设计文档
# Developer
## API 结构
## Deployment
### 请求
#### 请求方式
支持如下两种调用方式:
- get
- post
#### 请求头(公共参数)
| 参数名称 | 用途 | 类型 | 必要性 |
| -------- | ------------ | ------ | ------ |
| Version | 接口版本 | string | 可选 |
| Language | 接口显示语言 | string | 可选 |
#### 安全验证
本微服务没有安全验证模块,需通过 API 网关实现
#### 请求主体
[业务接口详情](#业务接口详情)
### 响应结果
#### 响应头(公共参数)
| 返回参数 | 用途 | 类型 | 必要性 |
| ----------- | ---------------------------------- | ------- | ------ |
| HTTP 状态码 | 判断接口调用是否成功200 或 404 | Integer | 必须 |
#### 响应主体
| 返回参数 | 用途 | 类型 | 必要性 |
| ------------ | -------------------- | -------------------- | ---------------------- |
| ResponseData | 各个接口的业务数据 | object(依据接口而异) | 必须 |
| Error | 错误 code 和错误信息 | ErrorInfo | 非必须 ,无错误时不返回 |
Install python3.6+ and Docker, then
```
{
"ResponseData": {
app_id: "xxxx",
StatusReason: {
Code: "Requirement.NotEnough",
Message: "Insufficient system resources (cpu, memory, disk space).",
Detail: "Error detail information"
}
},
"Error": {
Code: "Requirement.NotEnough",
Message: "Insufficient system resources (cpu, memory, disk space).",
Detail: "Error detail information"
}
}
pip install -r requirements.txt
docker network create websoft9
git clone https://github.com/Websoft9/stackhub.git && cd stackhub/docker/appmanage && docker compose up -d
```
#### 错误代码设计
## API UI
错误代码参考 [AWS API](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/errors-overview.html) 的分类方式:
Access API by: **http://Internet IP:port/docs**
- Client errors: These errors are usually caused by something the client did, such as specifying an incorrect or invalid parameter in the request, or using an action or resource on behalf of a user that doesn't have permission to use the action or resource. These errors are accompanied by a 400-series HTTP response code.
### Test Automation
- Server errors: These errors are usually caused by an AWS server-side issue. These errors are accompanied by a 500-series HTTP response code.
##### Client errors
| code | message | detail |
| ------------------------------------- | -------------- | ------ |
| Client.Parameter.Blank.Error | p 必填参数为空 | null |
| Client.Parameter.Format.Error | p 参数语法不符 | null |
| Client.Parameter.Value.NotExist.Error | p 参数值错误 | null |
| Client.Parameter.Value.Repeat.Error | p 参数值重复 | null |
##### Server errors
| code | message | detail |
| ---------------------- | ---------------------- | ------------ |
| Server.Container.Error | Docker 返回原始错误 | 错误详细信息 |
| Server.SystemError | 系统原始错误 | 错误详细信息 |
| Server.\*\*\* | 其他可以友好提示的错误 | 错误详细信息 |
## 业务接口详情
各个业务接口的详细说明,公共参数不在这里继续说明。
### App 安装
#### Action
AppInstall
#### 请求参数
| 参数名称 | 用途 | 类型 | 必要性 |
| ----------------- | ------------------ | ------ | ------ |
| app_name | 应用名称 | string | 必须 |
| customer_app_name | 用户自定义应用名称 | string | 必须 |
| app_version | 应用版本 | string | 必须 |
#### 返回结果
| 返回值 | 类型 | 必要性 |
| ------------ | ------------- | ------ |
| ResponseData | String(AppID) | 必须 |
| Error | ErrorInfo | 非必须 |
### App 卸载
#### Action
AppUninstall
#### 请求参数
| 参数名称 | 用途 | 类型 | 必要性 |
| -------- | ---------- | ------ | ------ |
| app_id | 卸载该 app | string | 必须 |
#### 返回结果
| 返回值 | 类型 | 必要性 |
| ------------ | ------------- | ------ |
| ResponseData | String(AppID) | 必须 |
| error | ErrorInfo | 非必须 |
### App 重启
#### Action
AppRestart
#### 请求参数
| 参数名称 | 用途 | 类型 | 必要性 |
| -------- | ---------- | ------ | ------ |
| app_id | 重启该 app | string | 必须 |
#### 返回结果
| 返回值 | 类型 | 必要性 |
| ------------ | ------------- | ------ |
| ResponseData | String(AppID) | 必须 |
| error | ErrorInfo | 非必须 |
### App 启动
#### Action
AppStart
#### 请求参数
| 参数名称 | 用途 | 类型 | 必要性 |
| -------- | ---------- | ------ | ------ |
| app_id | 启动该 app | string | 必须 |
#### 返回结果
| 返回值 | 类型 | 必要性 |
| ------------ | ------------- | ------ |
| ResponseData | String(AppID) | 必须 |
| error | ErrorInfo | 非必须 |
### App 停止
#### Action
AppStop
#### 请求参数
| 参数名称 | 用途 | 类型 | 必要性 |
| -------- | ---------- | ------ | ------ |
| app_id | 停止该 app | string | 必须 |
#### 返回结果
| 返回值 | 类型 | 必要性 |
| ------------ | ------------- | ------ |
| ResponseData | String(AppID) | 必须 |
| error | ErrorInfo | 非必须 |
### App 状态查询
#### Action
AppStatus
#### 请求参数
| 参数名称 | 用途 | 类型 | 必要性 |
| -------- | ----------------- | ------ | ------ |
| app_id | 查询该 app 的信息 | string | 必须 |
#### 返回结果
| 返回值 | 类型 | 必要性 |
| ------------ | ------------- | ------ |
| ResponseData | AppStatusInfo | 必须 |
| error | ErrorInfo | 非必须 |
AppStatusInfo 说明:
```
{
app_id应用ID,
status应用运行状态,[installing(创建中)running(运行中)exited(停止)restarting(反复重启)failed(失败)]
status_reason{ // 只有failed时才有内容
Code错误代码
Message错误提示信息
Detail错误真实信息
}
}
```
### App 列表查询
#### Action
AppList
#### 请求参数
| 参数名称 | 用途 | 类型 | 必要性 |
| -------- | -------------- | ------ | ------ |
| app_id | 查询指定的 app | string | 非必须 |
#### 返回结果
| 返回值 | 类型 | 必要性 |
| ------------ | ---------------------- | ------ |
| ResponseData | Array of AppDetailInfo | 必须 |
| error | ErrorInfo | 非必须 |
AppDetailInfo 说明:
```
{
app_id应用ID,
name应用名,
customer_name自定义应用名,
trade_mark应用商标,
status应用运行状态,[installing(创建中)running(运行中)exited(停止)restarting(反复重启)failed(失败)]
status_reason{ // 只有failed时才有内容
Code错误代码
Message错误提示信息
Detail错误真实信息
},
official_app是否为官方应用,
image_url图片路径,
running_info: { // 只有status=running才有值其他时候为空
port应用端口,
compose_filedocker compose文件路径,
url应用网址,
admin_url管理员网址,
user_name用户名,
password密码,
default_domain: 默认域名,
set_domain: 用户自定义域名,
}
}
```
Coming soon...

View file

@ -1,9 +0,0 @@
## 使用
### API
安装 appmanage 后可使用浏览器或Postman访问接口自动生成文档地址http://ip:port/redoc 或 http://ip:port/docs
### CLI
暂未提供

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 KiB

3
appmanage/test/README.md Normal file
View file

@ -0,0 +1,3 @@
# Test
Automatic testing script for API

View file

@ -1,75 +1,6 @@
# Developer Guide
## Appmanage
### 开发环境以及组件
Python3.10, FastAPI, RQ, logging
### 关键技术实现
#### 日志分割
```
logPath = 'logs/'
if not os.path.exists(logPath):
os.makedirs(logPath)
logName = 'app_manage.log'
logFile = logPath + logName
formatter = logging.Formatter('%(asctime)s %(levelname)s: %(message)s')
# handler
time_rotating_file_handler = handlers.TimedRotatingFileHandler(filename=logFile, when="MIDNIGHT", interval=1, encoding='utf-8')
time_rotating_file_handler.setLevel(logging.DEBUG)
time_rotating_file_handler.setFormatter(formatter)
```
#### RQ
任务管理器启动:
```
rq worker --url redis://websoft9-redis:6379/0
```
RQ 队列创建:
```
# 指定 Redis 容器的主机名和端口
redis_conn = Redis(host='websoft9-redis', port=6379)
# 使用指定的 Redis 连接创建 RQ 队列
q = Queue(connection=redis_conn,default_timeout=3600)
```
RQ 队列新增排队任务:
```
q.enqueue(install_app_delay, app_name, customer_name, app_version, job_id=app_id)
```
获取队列中任务的信息:
```
# 获取 StartedJobRegistry 实例
started = StartedJobRegistry(queue=q)
finish = FinishedJobRegistry(queue=q)
deferred = DeferredJobRegistry(queue=q)
failed = FailedJobRegistry(queue=q)
scheduled = ScheduledJobRegistry(queue=q)
cancel = CanceledJobRegistry(queue=q)
# 获取正在执行的作业 ID 列表
run_job_ids = started.get_job_ids()
finish_job_ids = finish.get_job_ids()
wait_job_ids = deferred.get_job_ids()
failed_jobs = failed.get_job_ids()
scheduled_jobs = scheduled.get_job_ids()
cancel_jobs = cancel.get_job_ids()
```
### API 文档
[FastAPI 文档](https://github.com/Websoft9/stackhub/blob/main/appmanage/docs/developer.md) 使用 swagger 自动生成访问地址http://IP:PORT/docs。
## 版本管理

View file