mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-10-09 16:00:29 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51ca89daba | ||
|
|
99951029c8 | ||
|
|
2d2869d184 | ||
|
|
9d85d52005 | ||
|
|
b2ce2c86fb | ||
|
|
1f92324a45 | ||
|
|
2031295ba4 | ||
|
|
f079050545 | ||
|
|
cc6873c941 | ||
|
|
0252a30f05 | ||
|
|
8dfb4854a8 | ||
|
|
5d9e5baec1 | ||
|
|
16f9533372 | ||
|
|
9a1ced8cdd | ||
|
|
9f35e26e22 | ||
|
|
7f53c9bc57 | ||
|
|
ecffb04186 | ||
|
|
6d578e53ea | ||
|
|
cd376b2e97 | ||
|
|
c01b3764f8 | ||
|
|
faf4174adf | ||
|
|
f9e22166c1 | ||
|
|
7f12beab8f | ||
|
|
862585c2f9 | ||
|
|
db613c3bf7 | ||
|
|
2e1e76b226 | ||
|
|
23ed80298e | ||
|
|
9130d5d2c8 | ||
|
|
8f713c0eda | ||
|
|
153fe5c1db | ||
|
|
1827fb3f46 | ||
|
|
b628bce4f8 | ||
|
|
09341d2254 | ||
|
|
7f75882811 | ||
|
|
cbd4dd9e9a | ||
|
|
42e0bff8f7 | ||
|
|
5fd238c429 | ||
|
|
945f67677f | ||
|
|
150b1a2590 | ||
|
|
a4bd9362ed | ||
|
|
0496b282b1 | ||
|
|
f61345c18d | ||
|
|
256be27f92 | ||
|
|
2fdf2b9378 | ||
|
|
b8d2d4e7af | ||
|
|
7171c13e31 | ||
|
|
c0c65598c8 | ||
|
|
90ba0faa77 | ||
|
|
124d1e8884 | ||
|
|
fefb312f50 | ||
|
|
825fe792e7 | ||
|
|
5bb77d7176 | ||
|
|
517bae6910 | ||
|
|
0dda4411da | ||
|
|
71b0deddb6 | ||
|
|
5dc5b17bea | ||
|
|
fa420b9346 | ||
|
|
154ea0b4ce | ||
|
|
9d0eca723c | ||
|
|
4c650af0e9 | ||
|
|
b09c423bcc | ||
|
|
455e379ff4 | ||
|
|
221c87e71e | ||
|
|
4366714f0b | ||
|
|
d7bdf5813d | ||
|
|
f258d4e443 | ||
|
|
92c28b3ed1 | ||
|
|
e76d1e018e | ||
|
|
d685bed167 | ||
|
|
f004df42af | ||
|
|
d8df9f755e | ||
|
|
6b1cc1088e | ||
|
|
bca9777a43 | ||
|
|
dc86cbc1ee | ||
|
|
11c5558334 | ||
|
|
c6111de050 | ||
|
|
e8564f38ab | ||
|
|
2624238354 | ||
|
|
aa588205e9 | ||
|
|
ce6069da37 | ||
|
|
4ca25d51d7 | ||
|
|
1130a70052 | ||
|
|
38dadf6056 | ||
|
|
1905e55628 | ||
|
|
1cdba27cae | ||
|
|
4932c533ae | ||
|
|
f4094e03b8 | ||
|
|
975ff06d69 | ||
|
|
04eb8191ed | ||
|
|
a5b3067cc7 | ||
|
|
12d6c2c3df | ||
|
|
695f3278c3 | ||
|
|
017eb3814b | ||
|
|
a520bdbe56 | ||
|
|
bbf2c50b25 | ||
|
|
9c417e113a | ||
|
|
6876f28505 | ||
|
|
d4ab96d213 | ||
|
|
5425544a6b | ||
|
|
06f6a45289 | ||
|
|
9f0f3fa6cd | ||
|
|
88a4ea3513 | ||
|
|
5ff7085f29 | ||
|
|
072b516d10 | ||
|
|
879d640793 | ||
|
|
ac98d63fcd |
@@ -0,0 +1 @@
|
||||
custom: ["https://afdian.net/a/1Panel"]
|
||||
@@ -0,0 +1,20 @@
|
||||
name: Build
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
jobs:
|
||||
sonarcloud:
|
||||
name: SonarCloud
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: SonarCloud Scan
|
||||
uses: SonarSource/sonarcloud-github-action@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUBTOKEN }}
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
+24
-6
@@ -4,18 +4,38 @@
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
.idea
|
||||
|
||||
build/1panel
|
||||
|
||||
# Mac
|
||||
.DS_Store
|
||||
*/.DS_Store
|
||||
|
||||
# VS Code
|
||||
.vscode
|
||||
*.project
|
||||
*.factorypath
|
||||
|
||||
# IntelliJ IDEA
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
# NetBeans
|
||||
nbproject/private/
|
||||
build/
|
||||
nbbuild/
|
||||
dist/
|
||||
nbdist/
|
||||
.nb-gradle/
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
# Dependency directories
|
||||
/pkg/
|
||||
backend/__debug_bin
|
||||
cmd/server/__debug_bin
|
||||
@@ -31,7 +51,5 @@ dist/
|
||||
1panel.service
|
||||
install.sh
|
||||
quick_start.sh
|
||||
cmd/server/web/.DS_Store
|
||||
cmd/server/.DS_Store
|
||||
cmd/server/fileList.txt
|
||||
.fileList.txt
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<a href="https://github.com/1Panel-dev/1Panel/releases"><img src="https://img.shields.io/github/v/release/1Panel-dev/1Panel" alt="GitHub release"></a>
|
||||
<a href="https://github.com/1Panel-dev/1Panel"><img src="https://img.shields.io/github/stars/1Panel-dev/1Panel?color=%231890FF&style=flat-square" alt="Stars"></a>
|
||||
<a href="https://app.fossa.com/projects/git%2Bgithub.com%2F1Panel-dev%2F1Panel?ref=badge_shield"><img src="https://app.fossa.com/api/projects/git%2Bgithub.com%2F1Panel-dev%2F1Panel.svg?type=shield" alt="FOSSA Status"></a><br>
|
||||
[<a href="README_EN.md">English</a>] | [<a href="README_JP.md">日本語</a>]
|
||||
[<a href="docs/README_TW.md">中文(繁體)</a>] | [<a href="docs/README_EN.md">English</a>] | [<a href="docs/README_JP.md">日本語</a>]
|
||||
</p>
|
||||
|
||||
------------------------------
|
||||
@@ -16,7 +16,8 @@
|
||||
- **快速建站**:深度集成 Wordpress 和 [Halo](https://github.com/halo-dev/halo/),域名绑定、SSL 证书配置等一键搞定;
|
||||
- **高效管理**:通过 Web 端轻松管理 Linux 服务器,包括主机监控、文件管理、数据库管理、容器管理等;
|
||||
- **安全可靠**:基于容器来管理和部署应用,最小漏洞暴露面,提供防火墙和日志审计等功能;
|
||||
- **一键备份**:支持一键备份和恢复,备份数据到各类云端存储,永不丢失。
|
||||
- **一键备份**:支持一键备份和恢复,备份数据到各类云端存储,永不丢失;
|
||||
- **应用商店**:精选各类高质量开源工具和应用软件,助力您轻松安装和升级。
|
||||
|
||||
## UI 展示
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ func (b *BaseApi) SearchApp(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /apps/sync [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"应用商店同步","formatEN":"App store synchronization"}
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"应用商店同步","formatEN":"App store synchronization"}
|
||||
func (b *BaseApi) SyncApp(c *gin.Context) {
|
||||
go appService.SyncAppListFromLocal()
|
||||
res, err := appService.GetAppUpdate()
|
||||
@@ -50,11 +50,8 @@ func (b *BaseApi) SyncApp(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
global.LOG.Infof("sync app list start ...")
|
||||
if err := appService.SyncAppListFromRemote(); err != nil {
|
||||
global.LOG.Errorf("sync app list error [%s]", err.Error())
|
||||
} else {
|
||||
global.LOG.Infof("sync app list success!")
|
||||
global.LOG.Errorf("Synchronization with the App Store failed [%s]", err.Error())
|
||||
}
|
||||
}()
|
||||
helper.SuccessWithData(c, "")
|
||||
@@ -93,14 +90,14 @@ func (b *BaseApi) GetApp(c *gin.Context) {
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /apps/detail/:appId/:version/:type [get]
|
||||
func (b *BaseApi) GetAppDetail(c *gin.Context) {
|
||||
appId, err := helper.GetIntParamByKey(c, "appId")
|
||||
appID, err := helper.GetIntParamByKey(c, "appId")
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil)
|
||||
return
|
||||
}
|
||||
version := c.Param("version")
|
||||
appType := c.Param("type")
|
||||
appDetailDTO, err := appService.GetAppDetail(appId, version, appType)
|
||||
appDetailDTO, err := appService.GetAppDetail(appID, version, appType)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
@@ -154,7 +151,7 @@ func (b *BaseApi) GetIgnoredApp(c *gin.Context) {
|
||||
// @Success 200 {object} model.AppInstall
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /apps/install [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[{"input_column":"name","input_value":"name","isList":false,"db":"app_installs","output_column":"app_id","output_value":"appId"},{"info":"appId","isList":false,"db":"apps","output_column":"key","output_value":"appKey"}],"formatZH":"安装应用 [appKey]-[name]","formatEN":"Install app [appKey]-[name]"}
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[{"input_column":"name","input_value":"name","isList":false,"db":"app_installs","output_column":"app_id","output_value":"appId"},{"info":"appId","isList":false,"db":"apps","output_column":"key","output_value":"appKey"}],"formatZH":"安装应用 [appKey]-[name]","formatEN":"Install app [appKey]-[name]"}
|
||||
func (b *BaseApi) InstallApp(c *gin.Context) {
|
||||
var req request.AppInstallCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -161,7 +161,7 @@ func (b *BaseApi) DeleteCheck(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /apps/installed/sync [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"同步已安装应用列表","formatEN":"Sync the list of installed apps"}
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"同步已安装应用列表","formatEN":"Sync the list of installed apps"}
|
||||
func (b *BaseApi) SyncInstalled(c *gin.Context) {
|
||||
if err := appInstallService.SyncAll(false); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
@@ -178,7 +178,7 @@ func (b *BaseApi) SyncInstalled(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /apps/installed/op [post]
|
||||
// @x-panel-log {"bodyKeys":["installId","operate"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"installId","isList":false,"db":"app_installs","output_column":"app_id","output_value":"appId"},{"input_column":"id","input_value":"installId","isList":false,"db":"app_installs","output_column":"name","output_value":"appName"},{"input_column":"id","input_value":"appId","isList":false,"db":"apps","output_column":"key","output_value":"appKey"}],"formatZH":"[operate] 应用 [appKey][appName]","formatEN":"[operate] App [appKey][appName]"}
|
||||
// @x-panel-log {"bodyKeys":["installId","operate"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"installId","isList":false,"db":"app_installs","output_column":"app_id","output_value":"appId"},{"input_column":"id","input_value":"installId","isList":false,"db":"app_installs","output_column":"name","output_value":"appName"},{"input_column":"id","input_value":"appId","isList":false,"db":"apps","output_column":"key","output_value":"appKey"}],"formatZH":"[operate] 应用 [appKey][appName]","formatEN":"[operate] App [appKey][appName]"}
|
||||
func (b *BaseApi) OperateInstalled(c *gin.Context) {
|
||||
var req request.AppInstalledOperate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -240,7 +240,7 @@ func (b *BaseApi) GetUpdateVersions(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /apps/installed/port/change [post]
|
||||
// @x-panel-log {"bodyKeys":["key","name","port"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"应用端口修改 [key]-[name] => [port]","formatEN":"Application port update [key]-[name] => [port]"}
|
||||
// @x-panel-log {"bodyKeys":["key","name","port"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"应用端口修改 [key]-[name] => [port]","formatEN":"Application port update [key]-[name] => [port]"}
|
||||
func (b *BaseApi) ChangeAppPort(c *gin.Context) {
|
||||
var req request.PortUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -311,7 +311,7 @@ func (b *BaseApi) GetParams(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /apps/installed/params/update [post]
|
||||
// @x-panel-log {"bodyKeys":["installId"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"应用参数修改 [installId]","formatEN":"Application param update [installId]"}
|
||||
// @x-panel-log {"bodyKeys":["installId"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"应用参数修改 [installId]","formatEN":"Application param update [installId]"}
|
||||
func (b *BaseApi) UpdateInstalled(c *gin.Context) {
|
||||
var req request.AppInstalledUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -333,7 +333,7 @@ func (b *BaseApi) UpdateInstalled(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /apps/installed/ignore [post]
|
||||
// @x-panel-log {"bodyKeys":["installId"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"忽略应用 [installId] 版本升级","formatEN":"Application param update [installId]"}
|
||||
// @x-panel-log {"bodyKeys":["installId"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"忽略应用 [installId] 版本升级","formatEN":"Application param update [installId]"}
|
||||
func (b *BaseApi) IgnoreUpgrade(c *gin.Context) {
|
||||
var req request.AppInstalledIgnoreUpgrade
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -19,10 +19,10 @@ type BaseApi struct{}
|
||||
// @Summary User login
|
||||
// @Description 用户登录
|
||||
// @Accept json
|
||||
// @Param EntranceCode header string true "安全入口 base64 加密串"
|
||||
// @Param request body dto.Login true "request"
|
||||
// @Success 200 {object} dto.UserLoginInfo
|
||||
// @Router /auth/login [post]
|
||||
// @Header 200 {string} EntranceCode "安全入口"
|
||||
func (b *BaseApi) Login(c *gin.Context) {
|
||||
var req dto.Login
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/backup [post]
|
||||
// @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建备份账号 [type]","formatEN":"create backup account [type]"}
|
||||
// @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建备份账号 [type]","formatEN":"create backup account [type]"}
|
||||
func (b *BaseApi) CreateBackup(c *gin.Context) {
|
||||
var req dto.BackupOperate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -122,7 +122,7 @@ func (b *BaseApi) LoadOneDriveInfo(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/backup/del [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":true,"db":"backup_accounts","output_column":"type","output_value":"types"}],"formatZH":"删除备份账号 [types]","formatEN":"delete backup account [types]"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":true,"db":"backup_accounts","output_column":"type","output_value":"types"}],"formatZH":"删除备份账号 [types]","formatEN":"delete backup account [types]"}
|
||||
func (b *BaseApi) DeleteBackup(c *gin.Context) {
|
||||
var req dto.OperateByID
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -176,7 +176,7 @@ func (b *BaseApi) SearchBackupRecords(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/backup/record/download [post]
|
||||
// @x-panel-log {"bodyKeys":["source","fileName"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"下载备份记录 [source][fileName]","formatEN":"download backup records [source][fileName]"}
|
||||
// @x-panel-log {"bodyKeys":["source","fileName"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"下载备份记录 [source][fileName]","formatEN":"download backup records [source][fileName]"}
|
||||
func (b *BaseApi) DownloadRecord(c *gin.Context) {
|
||||
var req dto.DownloadRecord
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -204,7 +204,7 @@ func (b *BaseApi) DownloadRecord(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/backup/record/del [post]
|
||||
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"ids","isList":true,"db":"backup_records","output_column":"file_name","output_value":"files"}],"formatZH":"删除备份记录 [files]","formatEN":"delete backup records [files]"}
|
||||
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"backup_records","output_column":"file_name","output_value":"files"}],"formatZH":"删除备份记录 [files]","formatEN":"delete backup records [files]"}
|
||||
func (b *BaseApi) DeleteBackupRecord(c *gin.Context) {
|
||||
var req dto.BatchDeleteReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -231,7 +231,7 @@ func (b *BaseApi) DeleteBackupRecord(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/backup/update [post]
|
||||
// @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新备份账号 [types]","formatEN":"update backup account [types]"}
|
||||
// @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新备份账号 [types]","formatEN":"update backup account [types]"}
|
||||
func (b *BaseApi) UpdateBackup(c *gin.Context) {
|
||||
var req dto.BackupOperate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -317,7 +317,7 @@ func (b *BaseApi) LoadFilesFromBackup(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/backup/ [post]
|
||||
// @x-panel-log {"bodyKeys":["type","name","detailName"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"备份 [type] 数据 [name][detailName]","formatEN":"backup [type] data [name][detailName]"}
|
||||
// @x-panel-log {"bodyKeys":["type","name","detailName"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"备份 [type] 数据 [name][detailName]","formatEN":"backup [type] data [name][detailName]"}
|
||||
func (b *BaseApi) Backup(c *gin.Context) {
|
||||
var req dto.CommonBackup
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -362,7 +362,7 @@ func (b *BaseApi) Backup(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/backup/recover [post]
|
||||
// @x-panel-log {"bodyKeys":["type","name","detailName","file"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"从 [file] 恢复 [type] 数据 [name][detailName]","formatEN":"recover [type] data [name][detailName] from [file]"}
|
||||
// @x-panel-log {"bodyKeys":["type","name","detailName","file"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"从 [file] 恢复 [type] 数据 [name][detailName]","formatEN":"recover [type] data [name][detailName] from [file]"}
|
||||
func (b *BaseApi) Recover(c *gin.Context) {
|
||||
var req dto.CommonRecover
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -415,7 +415,7 @@ func (b *BaseApi) Recover(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/backup/recover/byupload [post]
|
||||
// @x-panel-log {"bodyKeys":["type","name","detailName","file"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"从 [file] 恢复 [type] 数据 [name][detailName]","formatEN":"recover [type] data [name][detailName] from [file]"}
|
||||
// @x-panel-log {"bodyKeys":["type","name","detailName","file"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"从 [file] 恢复 [type] 数据 [name][detailName]","formatEN":"recover [type] data [name][detailName] from [file]"}
|
||||
func (b *BaseApi) RecoverByUpload(c *gin.Context) {
|
||||
var req dto.CommonRecover
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /hosts/command [post]
|
||||
// @x-panel-log {"bodyKeys":["name","command"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建快捷命令 [name][command]","formatEN":"create quick command [name][command]"}
|
||||
// @x-panel-log {"bodyKeys":["name","command"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建快捷命令 [name][command]","formatEN":"create quick command [name][command]"}
|
||||
func (b *BaseApi) CreateCommand(c *gin.Context) {
|
||||
var req dto.CommandOperate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -85,7 +85,7 @@ func (b *BaseApi) ListCommand(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /hosts/command/del [post]
|
||||
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"ids","isList":true,"db":"commands","output_column":"name","output_value":"names"}],"formatZH":"删除快捷命令 [names]","formatEN":"delete quick command [names]"}
|
||||
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"commands","output_column":"name","output_value":"names"}],"formatZH":"删除快捷命令 [names]","formatEN":"delete quick command [names]"}
|
||||
func (b *BaseApi) DeleteCommand(c *gin.Context) {
|
||||
var req dto.BatchDeleteReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -112,7 +112,7 @@ func (b *BaseApi) DeleteCommand(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /hosts/command/update [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新快捷命令 [name]","formatEN":"update quick command [name]"}
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新快捷命令 [name]","formatEN":"update quick command [name]"}
|
||||
func (b *BaseApi) UpdateCommand(c *gin.Context) {
|
||||
var req dto.CommandOperate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/template [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建 compose 模版 [name]","formatEN":"create compose template [name]"}
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建 compose 模版 [name]","formatEN":"create compose template [name]"}
|
||||
func (b *BaseApi) CreateComposeTemplate(c *gin.Context) {
|
||||
var req dto.ComposeTemplateCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -87,7 +87,7 @@ func (b *BaseApi) ListComposeTemplate(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/template/del [post]
|
||||
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"ids","isList":true,"db":"compose_templates","output_column":"name","output_value":"names"}],"formatZH":"删除 compose 模版 [names]","formatEN":"delete compose template [names]"}
|
||||
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"compose_templates","output_column":"name","output_value":"names"}],"formatZH":"删除 compose 模版 [names]","formatEN":"delete compose template [names]"}
|
||||
func (b *BaseApi) DeleteComposeTemplate(c *gin.Context) {
|
||||
var req dto.BatchDeleteReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -114,7 +114,7 @@ func (b *BaseApi) DeleteComposeTemplate(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/template/update [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"compose_templates","output_column":"name","output_value":"name"}],"formatZH":"更新 compose 模版 [name]","formatEN":"update compose template information [name]"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"compose_templates","output_column":"name","output_value":"name"}],"formatZH":"更新 compose 模版 [name]","formatEN":"update compose template information [name]"}
|
||||
func (b *BaseApi) UpdateComposeTemplate(c *gin.Context) {
|
||||
var req dto.ComposeTemplateUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -95,7 +95,7 @@ func (b *BaseApi) SearchCompose(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/compose/test [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"检测 compose [name] 格式","formatEN":"check compose [name]"}
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"检测 compose [name] 格式","formatEN":"check compose [name]"}
|
||||
func (b *BaseApi) TestCompose(c *gin.Context) {
|
||||
var req dto.ComposeCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -123,7 +123,7 @@ func (b *BaseApi) TestCompose(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/compose [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建 compose [name]","formatEN":"create compose [name]"}
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建 compose [name]","formatEN":"create compose [name]"}
|
||||
func (b *BaseApi) CreateCompose(c *gin.Context) {
|
||||
var req dto.ComposeCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -151,7 +151,7 @@ func (b *BaseApi) CreateCompose(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/compose/operate [post]
|
||||
// @x-panel-log {"bodyKeys":["name","operation"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"compose [operation] [name]","formatEN":"compose [operation] [name]"}
|
||||
// @x-panel-log {"bodyKeys":["name","operation"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"compose [operation] [name]","formatEN":"compose [operation] [name]"}
|
||||
func (b *BaseApi) OperatorCompose(c *gin.Context) {
|
||||
var req dto.ComposeOperation
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -178,7 +178,7 @@ func (b *BaseApi) OperatorCompose(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/update [post]
|
||||
// @x-panel-log {"bodyKeys":["name","image"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新容器 [name][image]","formatEN":"update container [name][image]"}
|
||||
// @x-panel-log {"bodyKeys":["name","image"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新容器 [name][image]","formatEN":"update container [name][image]"}
|
||||
func (b *BaseApi) ContainerUpdate(c *gin.Context) {
|
||||
var req dto.ContainerOperate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -222,13 +222,13 @@ func (b *BaseApi) ContainerInfo(c *gin.Context) {
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
||||
// @Summary Load container limis
|
||||
// @Summary Load container limits
|
||||
// @Description 获取容器限制
|
||||
// @Success 200 {object} dto.ResourceLimit
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/limit [get]
|
||||
func (b *BaseApi) LoadResouceLimit(c *gin.Context) {
|
||||
data, err := containerService.LoadResouceLimit()
|
||||
func (b *BaseApi) LoadResourceLimit(c *gin.Context) {
|
||||
data, err := containerService.LoadResourceLimit()
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
@@ -258,7 +258,7 @@ func (b *BaseApi) ContainerListStats(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers [post]
|
||||
// @x-panel-log {"bodyKeys":["name","image"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建容器 [name][image]","formatEN":"create container [name][image]"}
|
||||
// @x-panel-log {"bodyKeys":["name","image"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建容器 [name][image]","formatEN":"create container [name][image]"}
|
||||
func (b *BaseApi) ContainerCreate(c *gin.Context) {
|
||||
var req dto.ContainerOperate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -284,7 +284,7 @@ func (b *BaseApi) ContainerCreate(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/upgrade [post]
|
||||
// @x-panel-log {"bodyKeys":["name","image"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新容器镜像 [name][image]","formatEN":"upgrade container image [name][image]"}
|
||||
// @x-panel-log {"bodyKeys":["name","image"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新容器镜像 [name][image]","formatEN":"upgrade container image [name][image]"}
|
||||
func (b *BaseApi) ContainerUpgrade(c *gin.Context) {
|
||||
var req dto.ContainerUpgrade
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -310,7 +310,7 @@ func (b *BaseApi) ContainerUpgrade(c *gin.Context) {
|
||||
// @Success 200 {object} dto.ContainerPruneReport
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/prune [post]
|
||||
// @x-panel-log {"bodyKeys":["pruneType"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"清理容器 [pruneType]","formatEN":"clean container [pruneType]"}
|
||||
// @x-panel-log {"bodyKeys":["pruneType"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清理容器 [pruneType]","formatEN":"clean container [pruneType]"}
|
||||
func (b *BaseApi) ContainerPrune(c *gin.Context) {
|
||||
var req dto.ContainerPrune
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -337,7 +337,7 @@ func (b *BaseApi) ContainerPrune(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/clean/log [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"清理容器 [name] 日志","formatEN":"clean container [name] logs"}
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清理容器 [name] 日志","formatEN":"clean container [name] logs"}
|
||||
func (b *BaseApi) CleanContainerLog(c *gin.Context) {
|
||||
var req dto.OperationWithName
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -381,7 +381,7 @@ func (b *BaseApi) LoadContainerLog(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/operate [post]
|
||||
// @x-panel-log {"bodyKeys":["name","operation","newName"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"容器 [name] 执行 [operation] [newName]","formatEN":"container [operation] [name] [newName]"}
|
||||
// @x-panel-log {"bodyKeys":["name","operation","newName"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"容器 [name] 执行 [operation] [newName]","formatEN":"container [operation] [name] [newName]"}
|
||||
func (b *BaseApi) ContainerOperation(c *gin.Context) {
|
||||
var req dto.ContainerOperation
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -532,7 +532,7 @@ func (b *BaseApi) ListNetwork(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/network/del [post]
|
||||
// @x-panel-log {"bodyKeys":["names"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"删除容器网络 [names]","formatEN":"delete container network [names]"}
|
||||
// @x-panel-log {"bodyKeys":["names"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"删除容器网络 [names]","formatEN":"delete container network [names]"}
|
||||
func (b *BaseApi) DeleteNetwork(c *gin.Context) {
|
||||
var req dto.BatchDelete
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -559,7 +559,7 @@ func (b *BaseApi) DeleteNetwork(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/network [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建容器网络 name","formatEN":"create container network [name]"}
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建容器网络 name","formatEN":"create container network [name]"}
|
||||
func (b *BaseApi) CreateNetwork(c *gin.Context) {
|
||||
var req dto.NetworkCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -634,7 +634,7 @@ func (b *BaseApi) ListVolume(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/volume/del [post]
|
||||
// @x-panel-log {"bodyKeys":["names"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"删除容器存储卷 [names]","formatEN":"delete container volume [names]"}
|
||||
// @x-panel-log {"bodyKeys":["names"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"删除容器存储卷 [names]","formatEN":"delete container volume [names]"}
|
||||
func (b *BaseApi) DeleteVolume(c *gin.Context) {
|
||||
var req dto.BatchDelete
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -661,7 +661,7 @@ func (b *BaseApi) DeleteVolume(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/volume [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建容器存储卷 [name]","formatEN":"create container volume [name]"}
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建容器存储卷 [name]","formatEN":"create container volume [name]"}
|
||||
func (b *BaseApi) CreateVolume(c *gin.Context) {
|
||||
var req dto.VolumeCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -688,7 +688,7 @@ func (b *BaseApi) CreateVolume(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/compose/update [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新 compose [name]","formatEN":"update compose information [name]"}
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 compose [name]","formatEN":"update compose information [name]"}
|
||||
func (b *BaseApi) ComposeUpdate(c *gin.Context) {
|
||||
var req dto.ComposeUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -706,3 +706,31 @@ func (b *BaseApi) ComposeUpdate(c *gin.Context) {
|
||||
}
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
// @Tags Container Compose
|
||||
// @Summary Container Compose logs
|
||||
// @Description docker-compose 日志
|
||||
// @Param compose query string false "compose 文件地址"
|
||||
// @Param since query string false "时间筛选"
|
||||
// @Param follow query string false "是否追踪"
|
||||
// @Param tail query string false "显示行号"
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/compose/search/log [get]
|
||||
func (b *BaseApi) ComposeLogs(c *gin.Context) {
|
||||
wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("gin context http handler failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
defer wsConn.Close()
|
||||
|
||||
compose := c.Query("compose")
|
||||
since := c.Query("since")
|
||||
follow := c.Query("follow") == "true"
|
||||
tail := c.Query("tail")
|
||||
|
||||
if err := containerService.ComposeLogs(wsConn, compose, since, tail, follow); err != nil {
|
||||
_ = wsConn.WriteMessage(1, []byte(err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /cronjobs [post]
|
||||
// @x-panel-log {"bodyKeys":["type","name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建计划任务 [type][name]","formatEN":"create cronjob [type][name]"}
|
||||
// @x-panel-log {"bodyKeys":["type","name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建计划任务 [type][name]","formatEN":"create cronjob [type][name]"}
|
||||
func (b *BaseApi) CreateCronjob(c *gin.Context) {
|
||||
var req dto.CronjobCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -124,7 +124,7 @@ func (b *BaseApi) LoadRecordLog(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /cronjobs/records/clean [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"cronjobs","output_column":"name","output_value":"name"}],"formatZH":"清空计划任务记录 [name]","formatEN":"clean cronjob [name] records"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"cronjobs","output_column":"name","output_value":"name"}],"formatZH":"清空计划任务记录 [name]","formatEN":"clean cronjob [name] records"}
|
||||
func (b *BaseApi) CleanRecord(c *gin.Context) {
|
||||
var req dto.CronjobClean
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -148,7 +148,7 @@ func (b *BaseApi) CleanRecord(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /cronjobs/del [post]
|
||||
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"ids","isList":true,"db":"cronjobs","output_column":"name","output_value":"names"}],"formatZH":"删除计划任务 [names]","formatEN":"delete cronjob [names]"}
|
||||
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"cronjobs","output_column":"name","output_value":"names"}],"formatZH":"删除计划任务 [names]","formatEN":"delete cronjob [names]"}
|
||||
func (b *BaseApi) DeleteCronjob(c *gin.Context) {
|
||||
var req dto.CronjobBatchDelete
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -175,7 +175,7 @@ func (b *BaseApi) DeleteCronjob(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /cronjobs/update [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"cronjobs","output_column":"name","output_value":"name"}],"formatZH":"更新计划任务 [name]","formatEN":"update cronjob [name]"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"cronjobs","output_column":"name","output_value":"name"}],"formatZH":"更新计划任务 [name]","formatEN":"update cronjob [name]"}
|
||||
func (b *BaseApi) UpdateCronjob(c *gin.Context) {
|
||||
var req dto.CronjobUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -202,7 +202,7 @@ func (b *BaseApi) UpdateCronjob(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /cronjobs/status [post]
|
||||
// @x-panel-log {"bodyKeys":["id","status"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"cronjobs","output_column":"name","output_value":"name"}],"formatZH":"修改计划任务 [name] 状态为 [status]","formatEN":"change the status of cronjob [name] to [status]."}
|
||||
// @x-panel-log {"bodyKeys":["id","status"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"cronjobs","output_column":"name","output_value":"name"}],"formatZH":"修改计划任务 [name] 状态为 [status]","formatEN":"change the status of cronjob [name] to [status]."}
|
||||
func (b *BaseApi) UpdateCronjobStatus(c *gin.Context) {
|
||||
var req dto.CronjobUpdateStatus
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -229,7 +229,7 @@ func (b *BaseApi) UpdateCronjobStatus(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /cronjobs/download [post]
|
||||
// @x-panel-log {"bodyKeys":["recordID"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"recordID","isList":false,"db":"job_records","output_column":"file","output_value":"file"}],"formatZH":"下载计划任务记录 [file]","formatEN":"download the cronjob record [file]"}
|
||||
// @x-panel-log {"bodyKeys":["recordID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"recordID","isList":false,"db":"job_records","output_column":"file","output_value":"file"}],"formatZH":"下载计划任务记录 [file]","formatEN":"download the cronjob record [file]"}
|
||||
func (b *BaseApi) TargetDownload(c *gin.Context) {
|
||||
var req dto.CronjobDownload
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -258,7 +258,7 @@ func (b *BaseApi) TargetDownload(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /cronjobs/handle [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"cronjobs","output_column":"name","output_value":"name"}],"formatZH":"手动执行计划任务 [name]","formatEN":"manually execute the cronjob [name]"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"cronjobs","output_column":"name","output_value":"name"}],"formatZH":"手动执行计划任务 [name]","formatEN":"manually execute the cronjob [name]"}
|
||||
func (b *BaseApi) HandleOnce(c *gin.Context) {
|
||||
var req dto.OperateByID
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /databases/db [post]
|
||||
// @x-panel-log {"bodyKeys":["name", "type"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建远程数据库 [name][type]","formatEN":"create database [name][type]"}
|
||||
// @x-panel-log {"bodyKeys":["name", "type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建远程数据库 [name][type]","formatEN":"create database [name][type]"}
|
||||
func (b *BaseApi) CreateDatabase(c *gin.Context) {
|
||||
var req dto.DatabaseCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -42,7 +42,7 @@ func (b *BaseApi) CreateDatabase(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /databases/db/check [post]
|
||||
// @x-panel-log {"bodyKeys":["name", "type"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"检测远程数据库 [name][type] 连接性","formatEN":"check if database [name][type] is connectable"}
|
||||
// @x-panel-log {"bodyKeys":["name", "type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"检测远程数据库 [name][type] 连接性","formatEN":"check if database [name][type] is connectable"}
|
||||
func (b *BaseApi) CheckDatabase(c *gin.Context) {
|
||||
var req dto.DatabaseCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -126,15 +126,14 @@ func (b *BaseApi) GetDatabase(c *gin.Context) {
|
||||
}
|
||||
|
||||
// @Tags Database
|
||||
// @Summary Delete database
|
||||
// @Description 删除远程数据库
|
||||
// @Summary Check before delete remote database
|
||||
// @Description Mysql 远程数据库删除前检查
|
||||
// @Accept json
|
||||
// @Param request body dto.OperateByID true "request"
|
||||
// @Success 200
|
||||
// @Success 200 {array} string
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /databases/db/del [post]
|
||||
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"ids","isList":true,"db":"databases","output_column":"name","output_value":"names"}],"formatZH":"删除远程数据库 [names]","formatEN":"delete database [names]"}
|
||||
func (b *BaseApi) DeleteDatabase(c *gin.Context) {
|
||||
// @Router /db/remote/del/check [post]
|
||||
func (b *BaseApi) DeleteCheckDatabase(c *gin.Context) {
|
||||
var req dto.OperateByID
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
@@ -145,7 +144,35 @@ func (b *BaseApi) DeleteDatabase(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := databaseService.Delete(req.ID); err != nil {
|
||||
apps, err := databaseService.DeleteCheck(req.ID)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, apps)
|
||||
}
|
||||
|
||||
// @Tags Database
|
||||
// @Summary Delete database
|
||||
// @Description 删除远程数据库
|
||||
// @Accept json
|
||||
// @Param request body dto.DatabaseDelete true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /databases/db/del [post]
|
||||
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"databases","output_column":"name","output_value":"names"}],"formatZH":"删除远程数据库 [names]","formatEN":"delete database [names]"}
|
||||
func (b *BaseApi) DeleteDatabase(c *gin.Context) {
|
||||
var req dto.DatabaseDelete
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if err := global.VALID.Struct(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := databaseService.Delete(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
@@ -160,7 +187,7 @@ func (b *BaseApi) DeleteDatabase(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /databases/db/update [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新远程数据库 [name]","formatEN":"update database [name]"}
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新远程数据库 [name]","formatEN":"update database [name]"}
|
||||
func (b *BaseApi) UpdateDatabase(c *gin.Context) {
|
||||
var req dto.DatabaseUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /databases [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建 mysql 数据库 [name]","formatEN":"create mysql database [name]"}
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建 mysql 数据库 [name]","formatEN":"create mysql database [name]"}
|
||||
func (b *BaseApi) CreateMysql(c *gin.Context) {
|
||||
var req dto.MysqlDBCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -54,7 +54,7 @@ func (b *BaseApi) CreateMysql(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /databases/description/update [post]
|
||||
// @x-panel-log {"bodyKeys":["id","description"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"database_mysqls","output_column":"name","output_value":"name"}],"formatZH":"mysql 数据库 [name] 描述信息修改 [description]","formatEN":"The description of the mysql database [name] is modified => [description]"}
|
||||
// @x-panel-log {"bodyKeys":["id","description"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"database_mysqls","output_column":"name","output_value":"name"}],"formatZH":"mysql 数据库 [name] 描述信息修改 [description]","formatEN":"The description of the mysql database [name] is modified => [description]"}
|
||||
func (b *BaseApi) UpdateMysqlDescription(c *gin.Context) {
|
||||
var req dto.UpdateDescription
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -80,7 +80,7 @@ func (b *BaseApi) UpdateMysqlDescription(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /databases/change/password [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"database_mysqls","output_column":"name","output_value":"name"}],"formatZH":"更新数据库 [name] 密码","formatEN":"Update database [name] password"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"database_mysqls","output_column":"name","output_value":"name"}],"formatZH":"更新数据库 [name] 密码","formatEN":"Update database [name] password"}
|
||||
func (b *BaseApi) ChangeMysqlPassword(c *gin.Context) {
|
||||
var req dto.ChangeDBInfo
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -115,7 +115,7 @@ func (b *BaseApi) ChangeMysqlPassword(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /databases/change/access [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"database_mysqls","output_column":"name","output_value":"name"}],"formatZH":"更新数据库 [name] 访问权限","formatEN":"Update database [name] access"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"database_mysqls","output_column":"name","output_value":"name"}],"formatZH":"更新数据库 [name] 访问权限","formatEN":"Update database [name] access"}
|
||||
func (b *BaseApi) ChangeMysqlAccess(c *gin.Context) {
|
||||
var req dto.ChangeDBInfo
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -141,7 +141,7 @@ func (b *BaseApi) ChangeMysqlAccess(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /databases/variables/update [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"调整 mysql 数据库性能参数","formatEN":"adjust mysql database performance parameters"}
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"调整 mysql 数据库性能参数","formatEN":"adjust mysql database performance parameters"}
|
||||
func (b *BaseApi) UpdateMysqlVariables(c *gin.Context) {
|
||||
var req dto.MysqlVariablesUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -164,7 +164,7 @@ func (b *BaseApi) UpdateMysqlVariables(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /databases/conffile/update [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新 mysql 数据库配置信息","formatEN":"update the mysql database configuration information"}
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 mysql 数据库配置信息","formatEN":"update the mysql database configuration information"}
|
||||
func (b *BaseApi) UpdateMysqlConfByFile(c *gin.Context) {
|
||||
var req dto.MysqlConfUpdateByFile
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -289,7 +289,7 @@ func (b *BaseApi) DeleteCheckMysql(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /databases/del [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"database_mysqls","output_column":"name","output_value":"name"}],"formatZH":"删除 mysql 数据库 [name]","formatEN":"delete mysql database [name]"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"database_mysqls","output_column":"name","output_value":"name"}],"formatZH":"删除 mysql 数据库 [name]","formatEN":"delete mysql database [name]"}
|
||||
func (b *BaseApi) DeleteMysql(c *gin.Context) {
|
||||
var req dto.MysqlDBDelete
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -70,7 +70,7 @@ func (b *BaseApi) LoadPersistenceConf(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /databases/redis/conf/update [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新 redis 数据库配置信息","formatEN":"update the redis database configuration information"}
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 redis 数据库配置信息","formatEN":"update the redis database configuration information"}
|
||||
func (b *BaseApi) UpdateRedisConf(c *gin.Context) {
|
||||
var req dto.RedisConfUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -96,7 +96,7 @@ func (b *BaseApi) UpdateRedisConf(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /databases/redis/password [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"修改 redis 数据库密码","formatEN":"change the password of the redis database"}
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改 redis 数据库密码","formatEN":"change the password of the redis database"}
|
||||
func (b *BaseApi) ChangeRedisPassword(c *gin.Context) {
|
||||
var req dto.ChangeRedisPass
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -131,7 +131,7 @@ func (b *BaseApi) ChangeRedisPassword(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /databases/redis/persistence/update [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"redis 数据库持久化配置更新","formatEN":"redis database persistence configuration update"}
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"redis 数据库持久化配置更新","formatEN":"redis database persistence configuration update"}
|
||||
func (b *BaseApi) UpdateRedisPersistenceConf(c *gin.Context) {
|
||||
var req dto.RedisConfPersistenceUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -184,7 +184,7 @@ func (b *BaseApi) RedisBackupList(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /databases/redis/conffile/update [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新 redis 数据库配置信息","formatEN":"update the redis database configuration information"}
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 redis 数据库配置信息","formatEN":"update the redis database configuration information"}
|
||||
func (b *BaseApi) UpdateRedisConfByFile(c *gin.Context) {
|
||||
var req dto.RedisConfUpdateByFile
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -62,7 +62,7 @@ func (b *BaseApi) LoadDaemonJson(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/daemonjson/update [post]
|
||||
// @x-panel-log {"bodyKeys":["key", "value"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新 docker daemon.json 配置 [key]=>[value]","formatEN":"Updated the docker daemon.json configuration [key]=>[value]"}
|
||||
// @x-panel-log {"bodyKeys":["key", "value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 docker daemon.json 配置 [key]=>[value]","formatEN":"Updated the docker daemon.json configuration [key]=>[value]"}
|
||||
func (b *BaseApi) UpdateDaemonJson(c *gin.Context) {
|
||||
var req dto.SettingUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -86,7 +86,7 @@ func (b *BaseApi) UpdateDaemonJson(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/daemonjson/update [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新 docker daemon.json 日志配置","formatEN":"Updated the docker daemon.json log option"}
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 docker daemon.json 日志配置","formatEN":"Updated the docker daemon.json log option"}
|
||||
func (b *BaseApi) UpdateLogOption(c *gin.Context) {
|
||||
var req dto.LogOption
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -110,7 +110,7 @@ func (b *BaseApi) UpdateLogOption(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/daemonjson/update/byfile [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新 docker daemon.json 配置","formatEN":"Updated the docker daemon.json configuration"}
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 docker daemon.json 配置","formatEN":"Updated the docker daemon.json configuration"}
|
||||
func (b *BaseApi) UpdateDaemonJsonByFile(c *gin.Context) {
|
||||
var req dto.DaemonJsonUpdateByFile
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -138,7 +138,7 @@ func (b *BaseApi) UpdateDaemonJsonByFile(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/docker/operate [post]
|
||||
// @x-panel-log {"bodyKeys":["operation"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"docker 服务 [operation]","formatEN":"[operation] docker service"}
|
||||
// @x-panel-log {"bodyKeys":["operation"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"docker 服务 [operation]","formatEN":"[operation] docker service"}
|
||||
func (b *BaseApi) OperateDocker(c *gin.Context) {
|
||||
var req dto.DockerOperation
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
+17
-17
@@ -106,7 +106,7 @@ func (b *BaseApi) GetFileTree(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files [post]
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建文件/文件夹 [path]","formatEN":"Create dir or file [path]"}
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建文件/文件夹 [path]","formatEN":"Create dir or file [path]"}
|
||||
func (b *BaseApi) CreateFile(c *gin.Context) {
|
||||
var req request.FileCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -129,7 +129,7 @@ func (b *BaseApi) CreateFile(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files/del [post]
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"删除文件/文件夹 [path]","formatEN":"Delete dir or file [path]"}
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"删除文件/文件夹 [path]","formatEN":"Delete dir or file [path]"}
|
||||
func (b *BaseApi) DeleteFile(c *gin.Context) {
|
||||
var req request.FileDelete
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -152,7 +152,7 @@ func (b *BaseApi) DeleteFile(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files/batch/del [post]
|
||||
// @x-panel-log {"bodyKeys":["paths"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"批量删除文件/文件夹 [paths]","formatEN":"Batch delete dir or file [paths]"}
|
||||
// @x-panel-log {"bodyKeys":["paths"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"批量删除文件/文件夹 [paths]","formatEN":"Batch delete dir or file [paths]"}
|
||||
func (b *BaseApi) BatchDeleteFile(c *gin.Context) {
|
||||
var req request.FileBatchDelete
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -175,7 +175,7 @@ func (b *BaseApi) BatchDeleteFile(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files/mode [post]
|
||||
// @x-panel-log {"bodyKeys":["path","mode"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"修改权限 [paths] => [mode]","formatEN":"Change mode [paths] => [mode]"}
|
||||
// @x-panel-log {"bodyKeys":["path","mode"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改权限 [paths] => [mode]","formatEN":"Change mode [paths] => [mode]"}
|
||||
func (b *BaseApi) ChangeFileMode(c *gin.Context) {
|
||||
var req request.FileCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -198,7 +198,7 @@ func (b *BaseApi) ChangeFileMode(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files/owner [post]
|
||||
// @x-panel-log {"bodyKeys":["path","user","group"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"修改用户/组 [paths] => [user]/[group]","formatEN":"Change owner [paths] => [user]/[group]"}
|
||||
// @x-panel-log {"bodyKeys":["path","user","group"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改用户/组 [paths] => [user]/[group]","formatEN":"Change owner [paths] => [user]/[group]"}
|
||||
func (b *BaseApi) ChangeFileOwner(c *gin.Context) {
|
||||
var req request.FileRoleUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -220,7 +220,7 @@ func (b *BaseApi) ChangeFileOwner(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files/compress [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"压缩文件 [name]","formatEN":"Compress file [name]"}
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"压缩文件 [name]","formatEN":"Compress file [name]"}
|
||||
func (b *BaseApi) CompressFile(c *gin.Context) {
|
||||
var req request.FileCompress
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -243,7 +243,7 @@ func (b *BaseApi) CompressFile(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files/decompress [post]
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"解压 [path]","formatEN":"Decompress file [path]"}
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"解压 [path]","formatEN":"Decompress file [path]"}
|
||||
func (b *BaseApi) DeCompressFile(c *gin.Context) {
|
||||
var req request.FileDeCompress
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -266,7 +266,7 @@ func (b *BaseApi) DeCompressFile(c *gin.Context) {
|
||||
// @Success 200 {object} response.FileInfo
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files/content [post]
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"获取文件内容 [path]","formatEN":"Load file content [path]"}
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"获取文件内容 [path]","formatEN":"Load file content [path]"}
|
||||
func (b *BaseApi) GetContent(c *gin.Context) {
|
||||
var req request.FileOption
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -289,7 +289,7 @@ func (b *BaseApi) GetContent(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files/save [post]
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新文件内容 [path]","formatEN":"Update file content [path]"}
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新文件内容 [path]","formatEN":"Update file content [path]"}
|
||||
func (b *BaseApi) SaveContent(c *gin.Context) {
|
||||
var req request.FileEdit
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -310,7 +310,7 @@ func (b *BaseApi) SaveContent(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files/upload [post]
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"上传文件 [path]","formatEN":"Upload file [path]"}
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"上传文件 [path]","formatEN":"Upload file [path]"}
|
||||
func (b *BaseApi) UploadFiles(c *gin.Context) {
|
||||
form, err := c.MultipartForm()
|
||||
if err != nil {
|
||||
@@ -356,7 +356,7 @@ func (b *BaseApi) UploadFiles(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files/check [post]
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"检测文件 [path] 是否存在","formatEN":"Check whether file [path] exists"}
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"检测文件 [path] 是否存在","formatEN":"Check whether file [path] exists"}
|
||||
func (b *BaseApi) CheckFile(c *gin.Context) {
|
||||
var req request.FilePathCheck
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -384,7 +384,7 @@ func (b *BaseApi) CheckFile(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files/rename [post]
|
||||
// @x-panel-log {"bodyKeys":["oldName","newName"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"重命名 [oldName] => [newName]","formatEN":"Rename [oldName] => [newName]"}
|
||||
// @x-panel-log {"bodyKeys":["oldName","newName"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"重命名 [oldName] => [newName]","formatEN":"Rename [oldName] => [newName]"}
|
||||
func (b *BaseApi) ChangeFileName(c *gin.Context) {
|
||||
var req request.FileRename
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -406,7 +406,7 @@ func (b *BaseApi) ChangeFileName(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files/wget [post]
|
||||
// @x-panel-log {"bodyKeys":["url","path","name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"下载 url => [path]/[name]","formatEN":"Download url => [path]/[name]"}
|
||||
// @x-panel-log {"bodyKeys":["url","path","name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"下载 url => [path]/[name]","formatEN":"Download url => [path]/[name]"}
|
||||
func (b *BaseApi) WgetFile(c *gin.Context) {
|
||||
var req request.FileWget
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -431,7 +431,7 @@ func (b *BaseApi) WgetFile(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files/move [post]
|
||||
// @x-panel-log {"bodyKeys":["oldPaths","newPath"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"移动文件 [oldPaths] => [newPath]","formatEN":"Move [oldPaths] => [newPath]"}
|
||||
// @x-panel-log {"bodyKeys":["oldPaths","newPath"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"移动文件 [oldPaths] => [newPath]","formatEN":"Move [oldPaths] => [newPath]"}
|
||||
func (b *BaseApi) MoveFile(c *gin.Context) {
|
||||
var req request.FileMove
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -453,7 +453,7 @@ func (b *BaseApi) MoveFile(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files/download [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"下载文件 [name]","formatEN":"Download file [name]"}
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"下载文件 [name]","formatEN":"Download file [name]"}
|
||||
func (b *BaseApi) Download(c *gin.Context) {
|
||||
filePath := c.Query("path")
|
||||
file, err := os.Open(filePath)
|
||||
@@ -474,7 +474,7 @@ func (b *BaseApi) Download(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files/chunkdownload [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"下载文件 [name]","formatEN":"Download file [name]"}
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"下载文件 [name]","formatEN":"Download file [name]"}
|
||||
func (b *BaseApi) DownloadChunkFiles(c *gin.Context) {
|
||||
var req request.FileChunkDownload
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -552,7 +552,7 @@ func (b *BaseApi) DownloadChunkFiles(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /files/size [post]
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"获取文件夹大小 [path]","formatEN":"Load file size [path]"}
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"获取文件夹大小 [path]","formatEN":"Load file size [path]"}
|
||||
func (b *BaseApi) Size(c *gin.Context) {
|
||||
var req request.DirSizeReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -63,7 +63,7 @@ func (b *BaseApi) SearchFirewallRule(c *gin.Context) {
|
||||
// @Success 200 {object} dto.PageResult
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /hosts/firewall/operate [post]
|
||||
// @x-panel-log {"bodyKeys":["operation"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"[operation] 防火墙","formatEN":"[operation] firewall"}
|
||||
// @x-panel-log {"bodyKeys":["operation"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operation] 防火墙","formatEN":"[operation] firewall"}
|
||||
func (b *BaseApi) OperateFirewall(c *gin.Context) {
|
||||
var req dto.FirewallOperation
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -91,7 +91,7 @@ func (b *BaseApi) OperateFirewall(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /hosts/firewall/port [post]
|
||||
// @x-panel-log {"bodyKeys":["port","strategy"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"添加端口规则 [strategy] [port]","formatEN":"create port rules [strategy][port]"}
|
||||
// @x-panel-log {"bodyKeys":["port","strategy"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"添加端口规则 [strategy] [port]","formatEN":"create port rules [strategy][port]"}
|
||||
func (b *BaseApi) OperatePortRule(c *gin.Context) {
|
||||
var req dto.PortRuleOperate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -117,7 +117,7 @@ func (b *BaseApi) OperatePortRule(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /hosts/firewall/ip [post]
|
||||
// @x-panel-log {"bodyKeys":["strategy","address"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"添加 ip 规则 [strategy] [address]","formatEN":"create address rules [strategy][address]"}
|
||||
// @x-panel-log {"bodyKeys":["strategy","address"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"添加 ip 规则 [strategy] [address]","formatEN":"create address rules [strategy][address]"}
|
||||
func (b *BaseApi) OperateIPRule(c *gin.Context) {
|
||||
var req dto.AddrRuleOperate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /groups [post]
|
||||
// @x-panel-log {"bodyKeys":["name","type"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建组 [name][type]","formatEN":"create group [name][type]"}
|
||||
// @x-panel-log {"bodyKeys":["name","type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建组 [name][type]","formatEN":"create group [name][type]"}
|
||||
func (b *BaseApi) CreateGroup(c *gin.Context) {
|
||||
var req dto.GroupCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -42,7 +42,7 @@ func (b *BaseApi) CreateGroup(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /groups/del [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"groups","output_column":"name","output_value":"name"},{"input_column":"id","input_value":"id","isList":false,"db":"groups","output_column":"type","output_value":"type"}],"formatZH":"删除组 [type][name]","formatEN":"delete group [type][name]"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"groups","output_column":"name","output_value":"name"},{"input_column":"id","input_value":"id","isList":false,"db":"groups","output_column":"type","output_value":"type"}],"formatZH":"删除组 [type][name]","formatEN":"delete group [type][name]"}
|
||||
func (b *BaseApi) DeleteGroup(c *gin.Context) {
|
||||
var req dto.OperateByID
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -69,7 +69,7 @@ func (b *BaseApi) DeleteGroup(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /groups/update [post]
|
||||
// @x-panel-log {"bodyKeys":["name","type"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新组 [name][type]","formatEN":"update group [name][type]"}
|
||||
// @x-panel-log {"bodyKeys":["name","type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新组 [name][type]","formatEN":"update group [name][type]"}
|
||||
func (b *BaseApi) UpdateGroup(c *gin.Context) {
|
||||
var req dto.GroupUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -17,25 +17,6 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func GeneratePaginationFromReq(c *gin.Context) (*dto.PageInfo, bool) {
|
||||
p, ok1 := c.GetQuery("page")
|
||||
ps, ok2 := c.GetQuery("pageSize")
|
||||
if !(ok1 && ok2) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
page, err := strconv.Atoi(p)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
pageSize, err := strconv.Atoi(ps)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return &dto.PageInfo{Page: page, PageSize: pageSize}, true
|
||||
}
|
||||
|
||||
func ErrorWithDetail(ctx *gin.Context, code int, msgKey string, err error) {
|
||||
res := dto.Response{
|
||||
Code: code,
|
||||
@@ -132,3 +113,15 @@ func GetTxAndContext() (tx *gorm.DB, ctx context.Context) {
|
||||
ctx = context.WithValue(context.Background(), constant.DB, tx)
|
||||
return
|
||||
}
|
||||
|
||||
func CheckBindAndValidate(req interface{}, c *gin.Context) error {
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return err
|
||||
}
|
||||
if err := global.VALID.Struct(req); err != nil {
|
||||
ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /hosts [post]
|
||||
// @x-panel-log {"bodyKeys":["name","addr"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建主机 [name][addr]","formatEN":"create host [name][addr]"}
|
||||
// @x-panel-log {"bodyKeys":["name","addr"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建主机 [name][addr]","formatEN":"create host [name][addr]"}
|
||||
func (b *BaseApi) CreateHost(c *gin.Context) {
|
||||
var req dto.HostOperate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -138,7 +138,7 @@ func (b *BaseApi) SearchHost(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /hosts/del [post]
|
||||
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"ids","isList":true,"db":"hosts","output_column":"addr","output_value":"addrs"}],"formatZH":"删除主机 [addrs]","formatEN":"delete host [addrs]"}
|
||||
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"hosts","output_column":"addr","output_value":"addrs"}],"formatZH":"删除主机 [addrs]","formatEN":"delete host [addrs]"}
|
||||
func (b *BaseApi) DeleteHost(c *gin.Context) {
|
||||
var req dto.BatchDeleteReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -165,7 +165,7 @@ func (b *BaseApi) DeleteHost(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /hosts/update [post]
|
||||
// @x-panel-log {"bodyKeys":["name","addr"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新主机信息 [name][addr]","formatEN":"update host [name][addr]"}
|
||||
// @x-panel-log {"bodyKeys":["name","addr"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新主机信息 [name][addr]","formatEN":"update host [name][addr]"}
|
||||
func (b *BaseApi) UpdateHost(c *gin.Context) {
|
||||
var req dto.HostOperate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -235,7 +235,7 @@ func (b *BaseApi) UpdateHost(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /hosts/update/group [post]
|
||||
// @x-panel-log {"bodyKeys":["id","group"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"hosts","output_column":"addr","output_value":"addr"}],"formatZH":"切换主机[addr]分组 => [group]","formatEN":"change host [addr] group => [group]"}
|
||||
// @x-panel-log {"bodyKeys":["id","group"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"hosts","output_column":"addr","output_value":"addr"}],"formatZH":"切换主机[addr]分组 => [group]","formatEN":"change host [addr] group => [group]"}
|
||||
func (b *BaseApi) UpdateHostGroup(c *gin.Context) {
|
||||
var req dto.ChangeHostGroup
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -43,7 +43,7 @@ func (b *BaseApi) GetToolStatus(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /host/tool/create [post]
|
||||
// @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建 [type] 配置","formatEN":"create [type] config"}
|
||||
// @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建 [type] 配置","formatEN":"create [type] config"}
|
||||
func (b *BaseApi) InitToolConfig(c *gin.Context) {
|
||||
var req request.HostToolCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -70,7 +70,7 @@ func (b *BaseApi) InitToolConfig(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /host/tool/operate [post]
|
||||
// @x-panel-log {"bodyKeys":["operate","type"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"[operate] [type] ","formatEN":"[operate] [type]"}
|
||||
// @x-panel-log {"bodyKeys":["operate","type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operate] [type] ","formatEN":"[operate] [type]"}
|
||||
func (b *BaseApi) OperateTool(c *gin.Context) {
|
||||
var req request.HostToolReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -98,7 +98,7 @@ func (b *BaseApi) OperateTool(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /host/tool/config [post]
|
||||
// @x-panel-log {"bodyKeys":["operate"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"[operate] 主机工具配置文件 ","formatEN":"[operate] tool config"}
|
||||
// @x-panel-log {"bodyKeys":["operate"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operate] 主机工具配置文件 ","formatEN":"[operate] tool config"}
|
||||
func (b *BaseApi) OperateToolConfig(c *gin.Context) {
|
||||
var req request.HostToolConfig
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -153,7 +153,7 @@ func (b *BaseApi) GetToolLog(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /host/tool/supervisor/process [post]
|
||||
// @x-panel-log {"bodyKeys":["operate"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"[operate] 守护进程 ","formatEN":"[operate] process"}
|
||||
// @x-panel-log {"bodyKeys":["operate"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operate] 守护进程 ","formatEN":"[operate] process"}
|
||||
func (b *BaseApi) OperateProcess(c *gin.Context) {
|
||||
var req request.SupervisorProcessConfig
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -197,7 +197,7 @@ func (b *BaseApi) GetProcess(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /host/tool/supervisor/process/file [post]
|
||||
// @x-panel-log {"bodyKeys":["operate"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"[operate] Supervisor 进程文件 ","formatEN":"[operate] Supervisor Process Config file"}
|
||||
// @x-panel-log {"bodyKeys":["operate"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operate] Supervisor 进程文件 ","formatEN":"[operate] Supervisor Process Config file"}
|
||||
func (b *BaseApi) GetProcessFile(c *gin.Context) {
|
||||
var req request.SupervisorProcessFileReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -64,7 +64,7 @@ func (b *BaseApi) ListImage(c *gin.Context) {
|
||||
// @Success 200 {string} log
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/image/build [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"构建镜像 [name]","formatEN":"build image [name]"}
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"构建镜像 [name]","formatEN":"build image [name]"}
|
||||
func (b *BaseApi) ImageBuild(c *gin.Context) {
|
||||
var req dto.ImageBuild
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -93,7 +93,7 @@ func (b *BaseApi) ImageBuild(c *gin.Context) {
|
||||
// @Success 200 {string} log
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/image/pull [post]
|
||||
// @x-panel-log {"bodyKeys":["repoID","imageName"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"repoID","isList":false,"db":"image_repos","output_column":"name","output_value":"reponame"}],"formatZH":"镜像拉取 [reponame][imageName]","formatEN":"image pull [reponame][imageName]"}
|
||||
// @x-panel-log {"bodyKeys":["repoID","imageName"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"repoID","isList":false,"db":"image_repos","output_column":"name","output_value":"reponame"}],"formatZH":"镜像拉取 [reponame][imageName]","formatEN":"image pull [reponame][imageName]"}
|
||||
func (b *BaseApi) ImagePull(c *gin.Context) {
|
||||
var req dto.ImagePull
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -122,7 +122,7 @@ func (b *BaseApi) ImagePull(c *gin.Context) {
|
||||
// @Success 200 {string} log
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/image/push [post]
|
||||
// @x-panel-log {"bodyKeys":["repoID","tagName","name"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"repoID","isList":false,"db":"image_repos","output_column":"name","output_value":"reponame"}],"formatZH":"[tagName] 推送到 [reponame][name]","formatEN":"push [tagName] to [reponame][name]"}
|
||||
// @x-panel-log {"bodyKeys":["repoID","tagName","name"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"repoID","isList":false,"db":"image_repos","output_column":"name","output_value":"reponame"}],"formatZH":"[tagName] 推送到 [reponame][name]","formatEN":"push [tagName] to [reponame][name]"}
|
||||
func (b *BaseApi) ImagePush(c *gin.Context) {
|
||||
var req dto.ImagePush
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -151,7 +151,7 @@ func (b *BaseApi) ImagePush(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/image/remove [post]
|
||||
// @x-panel-log {"bodyKeys":["names"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"移除镜像 [names]","formatEN":"remove image [names]"}
|
||||
// @x-panel-log {"bodyKeys":["names"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"移除镜像 [names]","formatEN":"remove image [names]"}
|
||||
func (b *BaseApi) ImageRemove(c *gin.Context) {
|
||||
var req dto.BatchDelete
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -179,7 +179,7 @@ func (b *BaseApi) ImageRemove(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/image/save [post]
|
||||
// @x-panel-log {"bodyKeys":["tagName","path","name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"保留 [tagName] 为 [path]/[name]","formatEN":"save [tagName] as [path]/[name]"}
|
||||
// @x-panel-log {"bodyKeys":["tagName","path","name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"保留 [tagName] 为 [path]/[name]","formatEN":"save [tagName] as [path]/[name]"}
|
||||
func (b *BaseApi) ImageSave(c *gin.Context) {
|
||||
var req dto.ImageSave
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -207,7 +207,7 @@ func (b *BaseApi) ImageSave(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/image/tag [post]
|
||||
// @x-panel-log {"bodyKeys":["repoID","targetName"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"repoID","isList":false,"db":"image_repos","output_column":"name","output_value":"reponame"}],"formatZH":"tag 镜像 [reponame][targetName]","formatEN":"tag image [reponame][targetName]"}
|
||||
// @x-panel-log {"bodyKeys":["repoID","targetName"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"repoID","isList":false,"db":"image_repos","output_column":"name","output_value":"reponame"}],"formatZH":"tag 镜像 [reponame][targetName]","formatEN":"tag image [reponame][targetName]"}
|
||||
func (b *BaseApi) ImageTag(c *gin.Context) {
|
||||
var req dto.ImageTag
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -235,7 +235,7 @@ func (b *BaseApi) ImageTag(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/image/load [post]
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"从 [path] 加载镜像","formatEN":"load image from [path]"}
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"从 [path] 加载镜像","formatEN":"load image from [path]"}
|
||||
func (b *BaseApi) ImageLoad(c *gin.Context) {
|
||||
var req dto.ImageLoad
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -92,7 +92,7 @@ func (b *BaseApi) CheckRepoStatus(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/repo [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建镜像仓库 [name]","formatEN":"create image repo [name]"}
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建镜像仓库 [name]","formatEN":"create image repo [name]"}
|
||||
func (b *BaseApi) CreateRepo(c *gin.Context) {
|
||||
var req dto.ImageRepoCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -119,7 +119,7 @@ func (b *BaseApi) CreateRepo(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/repo/del [post]
|
||||
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"ids","isList":true,"db":"image_repos","output_column":"name","output_value":"names"}],"formatZH":"删除镜像仓库 [names]","formatEN":"delete image repo [names]"}
|
||||
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"image_repos","output_column":"name","output_value":"names"}],"formatZH":"删除镜像仓库 [names]","formatEN":"delete image repo [names]"}
|
||||
func (b *BaseApi) DeleteRepo(c *gin.Context) {
|
||||
var req dto.ImageRepoDelete
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -147,7 +147,7 @@ func (b *BaseApi) DeleteRepo(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /containers/repo/update [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"image_repos","output_column":"name","output_value":"name"}],"formatZH":"更新镜像仓库 [name]","formatEN":"update image repo information [name]"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"image_repos","output_column":"name","output_value":"name"}],"formatZH":"更新镜像仓库 [name]","formatEN":"update image repo information [name]"}
|
||||
func (b *BaseApi) UpdateRepo(c *gin.Context) {
|
||||
var req dto.ImageRepoUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -70,7 +70,7 @@ func (b *BaseApi) GetOperationLogs(c *gin.Context) {
|
||||
// @Success 200 {object} dto.PageResult
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /logs/clean [post]
|
||||
// @x-panel-log {"bodyKeys":["logType"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"清空 [logType] 日志信息","formatEN":"Clean the [logType] log information"}
|
||||
// @x-panel-log {"bodyKeys":["logType"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清空 [logType] 日志信息","formatEN":"Clean the [logType] log information"}
|
||||
func (b *BaseApi) CleanLogs(c *gin.Context) {
|
||||
var req dto.CleanLog
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -91,13 +91,34 @@ func (b *BaseApi) CleanLogs(c *gin.Context) {
|
||||
}
|
||||
|
||||
// @Tags Logs
|
||||
// @Summary Load system logs
|
||||
// @Description 获取系统日志
|
||||
// @Summary Load system log files
|
||||
// @Description 获取系统日志文件列表
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /logs/system [get]
|
||||
// @Router /logs/system/files [get]
|
||||
func (b *BaseApi) GetSystemFiles(c *gin.Context) {
|
||||
data, err := logService.ListSystemLogFile()
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
||||
// @Tags Logs
|
||||
// @Summary Load system logs
|
||||
// @Description 获取系统日志
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /logs/system [post]
|
||||
func (b *BaseApi) GetSystemLogs(c *gin.Context) {
|
||||
data, err := logService.LoadSystemLog()
|
||||
var req dto.OperationWithName
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
data, err := logService.LoadSystemLog(req.Name)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
|
||||
@@ -53,7 +53,7 @@ func (b *BaseApi) GetNginxConfigByScope(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /openResty/update [post]
|
||||
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新 nginx 配置 [domain]","formatEN":"Update nginx conf [domain]"}
|
||||
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新 nginx 配置 [domain]","formatEN":"Update nginx conf [domain]"}
|
||||
func (b *BaseApi) UpdateNginxConfigByScope(c *gin.Context) {
|
||||
var req request.NginxConfigUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -90,7 +90,7 @@ func (b *BaseApi) GetNginxStatus(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /openResty/file [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新 nginx 配置","formatEN":"Update nginx conf"}
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 nginx 配置","formatEN":"Update nginx conf"}
|
||||
func (b *BaseApi) UpdateNginxFile(c *gin.Context) {
|
||||
var req request.NginxConfigFileUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -25,7 +25,7 @@ func (b *BaseApi) ProcessWs(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /process/stop [post]
|
||||
// @x-panel-log {"bodyKeys":["PID"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"结束进程 [PID]","formatEN":"结束进程 [PID]"}
|
||||
// @x-panel-log {"bodyKeys":["PID"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"结束进程 [PID]","formatEN":"结束进程 [PID]"}
|
||||
func (b *BaseApi) StopProcess(c *gin.Context) {
|
||||
var req request.ProcessReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -18,8 +18,7 @@ import (
|
||||
// @Router /runtimes/search [post]
|
||||
func (b *BaseApi) SearchRuntimes(c *gin.Context) {
|
||||
var req request.RuntimeSearch
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
total, items, err := runtimeService.Page(req)
|
||||
@@ -41,11 +40,10 @@ func (b *BaseApi) SearchRuntimes(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /runtimes [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建运行环境 [name]","formatEN":"Create runtime [name]"}
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建运行环境 [name]","formatEN":"Create runtime [name]"}
|
||||
func (b *BaseApi) CreateRuntime(c *gin.Context) {
|
||||
var req request.RuntimeCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := runtimeService.Create(req); err != nil {
|
||||
@@ -63,14 +61,13 @@ func (b *BaseApi) CreateRuntime(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /runtimes/del [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"删除网站 [name]","formatEN":"Delete website [name]"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"删除网站 [name]","formatEN":"Delete website [name]"}
|
||||
func (b *BaseApi) DeleteRuntime(c *gin.Context) {
|
||||
var req request.RuntimeDelete
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
err := runtimeService.Delete(req.ID)
|
||||
err := runtimeService.Delete(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
@@ -86,11 +83,10 @@ func (b *BaseApi) DeleteRuntime(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /runtimes/update [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新运行环境 [name]","formatEN":"Update runtime [name]"}
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新运行环境 [name]","formatEN":"Update runtime [name]"}
|
||||
func (b *BaseApi) UpdateRuntime(c *gin.Context) {
|
||||
var req request.RuntimeUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := runtimeService.Update(req); err != nil {
|
||||
@@ -121,3 +117,88 @@ func (b *BaseApi) GetRuntime(c *gin.Context) {
|
||||
}
|
||||
helper.SuccessWithData(c, res)
|
||||
}
|
||||
|
||||
// @Tags Runtime
|
||||
// @Summary Get Node package scripts
|
||||
// @Description 获取 Node 项目的 scripts
|
||||
// @Accept json
|
||||
// @Param request body request.NodePackageReq true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /runtimes/node/package [post]
|
||||
func (b *BaseApi) GetNodePackageRunScript(c *gin.Context) {
|
||||
var req request.NodePackageReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
res, err := runtimeService.GetNodePackageRunScript(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, res)
|
||||
}
|
||||
|
||||
// @Tags Runtime
|
||||
// @Summary Operate runtime
|
||||
// @Description 操作运行环境
|
||||
// @Accept json
|
||||
// @Param request body request.RuntimeOperate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /runtimes/operate [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"操作运行环境 [name]","formatEN":"Operate runtime [name]"}
|
||||
func (b *BaseApi) OperateRuntime(c *gin.Context) {
|
||||
var req request.RuntimeOperate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
err := runtimeService.OperateRuntime(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithOutData(c)
|
||||
}
|
||||
|
||||
// @Tags Runtime
|
||||
// @Summary Get Node modules
|
||||
// @Description 获取 Node 项目的 modules
|
||||
// @Accept json
|
||||
// @Param request body request.NodeModuleReq true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /runtimes/node/modules [post]
|
||||
func (b *BaseApi) GetNodeModules(c *gin.Context) {
|
||||
var req request.NodeModuleReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
res, err := runtimeService.GetNodeModules(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, res)
|
||||
}
|
||||
|
||||
// @Tags Runtime
|
||||
// @Summary Operate Node modules
|
||||
// @Description 操作 Node 项目 modules
|
||||
// @Accept json
|
||||
// @Param request body request.NodeModuleReq true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /runtimes/node/modules/operate [post]
|
||||
func (b *BaseApi) OperateNodeModules(c *gin.Context) {
|
||||
var req request.NodeModuleOperateReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
err := runtimeService.OperateNodeModules(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithOutData(c)
|
||||
}
|
||||
|
||||
@@ -2,10 +2,8 @@ package v1
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
@@ -48,7 +46,7 @@ func (b *BaseApi) GetSystemAvailable(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/update [post]
|
||||
// @x-panel-log {"bodyKeys":["key","value"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"修改系统配置 [key] => [value]","formatEN":"update system setting [key] => [value]"}
|
||||
// @x-panel-log {"bodyKeys":["key","value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改系统配置 [key] => [value]","formatEN":"update system setting [key] => [value]"}
|
||||
func (b *BaseApi) UpdateSetting(c *gin.Context) {
|
||||
var req dto.SettingUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -75,7 +73,7 @@ func (b *BaseApi) UpdateSetting(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/password/update [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"修改系统密码","formatEN":"update system password"}
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改系统密码","formatEN":"update system password"}
|
||||
func (b *BaseApi) UpdatePassword(c *gin.Context) {
|
||||
var req dto.PasswordUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -102,7 +100,7 @@ func (b *BaseApi) UpdatePassword(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/ssl/update [post]
|
||||
// @x-panel-log {"bodyKeys":["ssl"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"修改系统 ssl => [ssl]","formatEN":"update system ssl => [ssl]"}
|
||||
// @x-panel-log {"bodyKeys":["ssl"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改系统 ssl => [ssl]","formatEN":"update system ssl => [ssl]"}
|
||||
func (b *BaseApi) UpdateSSL(c *gin.Context) {
|
||||
var req dto.SSLUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -160,7 +158,7 @@ func (b *BaseApi) DownloadSSL(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/port/update [post]
|
||||
// @x-panel-log {"bodyKeys":["serverPort"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"修改系统端口 => [serverPort]","formatEN":"update system port => [serverPort]"}
|
||||
// @x-panel-log {"bodyKeys":["serverPort"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改系统端口 => [serverPort]","formatEN":"update system port => [serverPort]"}
|
||||
func (b *BaseApi) UpdatePort(c *gin.Context) {
|
||||
var req dto.PortUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -187,7 +185,7 @@ func (b *BaseApi) UpdatePort(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/expired/handle [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"重置过期密码","formatEN":"reset an expired Password"}
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"重置过期密码","formatEN":"reset an expired Password"}
|
||||
func (b *BaseApi) HandlePasswordExpired(c *gin.Context) {
|
||||
var req dto.PasswordUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -229,7 +227,7 @@ func (b *BaseApi) LoadTimeZone(c *gin.Context) {
|
||||
// @Success 200 {string} ntime
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/time/sync [post]
|
||||
// @x-panel-log {"bodyKeys":["ntpSite"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"系统时间同步[ntpSite]","formatEN":"sync system time [ntpSite]"}
|
||||
// @x-panel-log {"bodyKeys":["ntpSite"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"系统时间同步[ntpSite]","formatEN":"sync system time [ntpSite]"}
|
||||
func (b *BaseApi) SyncTime(c *gin.Context) {
|
||||
var req dto.SyncTime
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -259,7 +257,7 @@ func (b *BaseApi) LoadBaseDir(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/monitor/clean [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"清空监控数据","formatEN":"clean monitor datas"}
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清空监控数据","formatEN":"clean monitor datas"}
|
||||
func (b *BaseApi) CleanMonitor(c *gin.Context) {
|
||||
if err := global.DB.Exec("DELETE FROM monitor_bases").Error; err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
@@ -278,25 +276,52 @@ func (b *BaseApi) CleanMonitor(c *gin.Context) {
|
||||
}
|
||||
|
||||
// @Tags System Setting
|
||||
// @Summary Load mfa info
|
||||
// @Description 获取 mfa 信息
|
||||
// @Param interval path string true "request"
|
||||
// @Success 200 {object} mfa.Otp
|
||||
// @Summary Scan system
|
||||
// @Description 扫描系统垃圾文件
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/mfa/:interval [get]
|
||||
func (b *BaseApi) GetMFA(c *gin.Context) {
|
||||
intervalStr, ok := c.Params.Get("interval")
|
||||
if !ok {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error interval in path"))
|
||||
// @Router /settings/scan [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"扫描系统垃圾文件","formatEN":"scan System Junk Files"}
|
||||
func (b *BaseApi) ScanSystem(c *gin.Context) {
|
||||
helper.SuccessWithData(c, settingService.SystemScan())
|
||||
}
|
||||
|
||||
// @Tags System Setting
|
||||
// @Summary System clean
|
||||
// @Description 清理系统垃圾文件
|
||||
// @Accept json
|
||||
// @Param request body []dto.Clean true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/clean [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清理系统垃圾文件","formatEN":"Clean system junk files"}
|
||||
func (b *BaseApi) SystemClean(c *gin.Context) {
|
||||
var req []dto.Clean
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
interval, err := strconv.Atoi(intervalStr)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, fmt.Errorf("type conversion failed, err: %v", err))
|
||||
settingService.SystemClean(req)
|
||||
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
// @Tags System Setting
|
||||
// @Summary Load mfa info
|
||||
// @Description 获取 mfa 信息
|
||||
// @Accept json
|
||||
// @Param request body dto.MfaCredential true "request"
|
||||
// @Success 200 {object} mfa.Otp
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/mfa [post]
|
||||
func (b *BaseApi) LoadMFA(c *gin.Context) {
|
||||
var req dto.MfaRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
|
||||
otp, err := mfa.GetOtp("admin", interval)
|
||||
otp, err := mfa.GetOtp("admin", req.Title, req.Interval)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
@@ -313,7 +338,7 @@ func (b *BaseApi) GetMFA(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/mfa/bind [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"mfa 绑定","formatEN":"bind mfa"}
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"mfa 绑定","formatEN":"bind mfa"}
|
||||
func (b *BaseApi) MFABind(c *gin.Context) {
|
||||
var req dto.MfaCredential
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/snapshot [post]
|
||||
// @x-panel-log {"bodyKeys":["from", "description"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建系统快照 [description] 到 [from]","formatEN":"Create system backup [description] to [from]"}
|
||||
// @x-panel-log {"bodyKeys":["from", "description"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建系统快照 [description] 到 [from]","formatEN":"Create system backup [description] to [from]"}
|
||||
func (b *BaseApi) CreateSnapshot(c *gin.Context) {
|
||||
var req dto.SnapshotCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -42,7 +42,7 @@ func (b *BaseApi) CreateSnapshot(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/snapshot/import [post]
|
||||
// @x-panel-log {"bodyKeys":["from", "names"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"从 [from] 同步系统快照 [names]","formatEN":"Sync system snapshots [names] from [from]"}
|
||||
// @x-panel-log {"bodyKeys":["from", "names"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"从 [from] 同步系统快照 [names]","formatEN":"Sync system snapshots [names] from [from]"}
|
||||
func (b *BaseApi) ImportSnapshot(c *gin.Context) {
|
||||
var req dto.SnapshotImport
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -94,7 +94,7 @@ func (b *BaseApi) LoadSnapShotStatus(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/snapshot/description/update [post]
|
||||
// @x-panel-log {"bodyKeys":["id","description"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"snapshots","output_column":"name","output_value":"name"}],"formatZH":"快照 [name] 描述信息修改 [description]","formatEN":"The description of the snapshot [name] is modified => [description]"}
|
||||
// @x-panel-log {"bodyKeys":["id","description"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"snapshots","output_column":"name","output_value":"name"}],"formatZH":"快照 [name] 描述信息修改 [description]","formatEN":"The description of the snapshot [name] is modified => [description]"}
|
||||
func (b *BaseApi) UpdateSnapDescription(c *gin.Context) {
|
||||
var req dto.UpdateDescription
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -145,7 +145,7 @@ func (b *BaseApi) SearchSnapshot(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/snapshot/recover [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"snapshots","output_column":"name","output_value":"name"}],"formatZH":"从系统快照 [name] 恢复","formatEN":"Recover from system backup [name]"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"snapshots","output_column":"name","output_value":"name"}],"formatZH":"从系统快照 [name] 恢复","formatEN":"Recover from system backup [name]"}
|
||||
func (b *BaseApi) RecoverSnapshot(c *gin.Context) {
|
||||
var req dto.SnapshotRecover
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -172,7 +172,7 @@ func (b *BaseApi) RecoverSnapshot(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/snapshot/rollback [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"snapshots","output_column":"name","output_value":"name"}],"formatZH":"从系统快照 [name] 回滚","formatEN":"Rollback from system backup [name]"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"snapshots","output_column":"name","output_value":"name"}],"formatZH":"从系统快照 [name] 回滚","formatEN":"Rollback from system backup [name]"}
|
||||
func (b *BaseApi) RollbackSnapshot(c *gin.Context) {
|
||||
var req dto.SnapshotRecover
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -199,7 +199,7 @@ func (b *BaseApi) RollbackSnapshot(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/snapshot/del [post]
|
||||
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"ids","isList":true,"db":"snapshots","output_column":"name","output_value":"name"}],"formatZH":"删除系统快照 [name]","formatEN":"Delete system backup [name]"}
|
||||
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"snapshots","output_column":"name","output_value":"name"}],"formatZH":"删除系统快照 [name]","formatEN":"Delete system backup [name]"}
|
||||
func (b *BaseApi) DeleteSnapshot(c *gin.Context) {
|
||||
var req dto.BatchDeleteReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
+44
-17
@@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
// @Tags SSH
|
||||
// @Summary Load host ssh setting info
|
||||
// @Summary Load host SSH setting info
|
||||
// @Description 加载 SSH 配置信息
|
||||
// @Success 200 {object} dto.SSHInfo
|
||||
// @Security ApiKeyAuth
|
||||
@@ -24,13 +24,13 @@ func (b *BaseApi) GetSSHInfo(c *gin.Context) {
|
||||
}
|
||||
|
||||
// @Tags SSH
|
||||
// @Summary Operate ssh
|
||||
// @Summary Operate SSH
|
||||
// @Description 修改 SSH 服务状态
|
||||
// @Accept json
|
||||
// @Param request body dto.Operate true "request"
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /host/ssh/operate [post]
|
||||
// @x-panel-log {"bodyKeys":["operation"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"[operation] SSH ","formatEN":"[operation] SSH"}
|
||||
// @x-panel-log {"bodyKeys":["operation"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"[operation] SSH ","formatEN":"[operation] SSH"}
|
||||
func (b *BaseApi) OperateSSH(c *gin.Context) {
|
||||
var req dto.Operate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -50,14 +50,14 @@ func (b *BaseApi) OperateSSH(c *gin.Context) {
|
||||
}
|
||||
|
||||
// @Tags SSH
|
||||
// @Summary Update host ssh setting
|
||||
// @Summary Update host SSH setting
|
||||
// @Description 更新 SSH 配置
|
||||
// @Accept json
|
||||
// @Param request body dto.SettingUpdate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /host/ssh/update [post]
|
||||
// @x-panel-log {"bodyKeys":["key","value"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"修改 SSH 配置 [key] => [value]","formatEN":"update SSH setting [key] => [value]"}
|
||||
// @x-panel-log {"bodyKeys":["key","value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改 SSH 配置 [key] => [value]","formatEN":"update SSH setting [key] => [value]"}
|
||||
func (b *BaseApi) UpdateSSH(c *gin.Context) {
|
||||
var req dto.SettingUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -77,14 +77,14 @@ func (b *BaseApi) UpdateSSH(c *gin.Context) {
|
||||
}
|
||||
|
||||
// @Tags SSH
|
||||
// @Summary Update host ssh setting by file
|
||||
// @Summary Update host SSH setting by file
|
||||
// @Description 上传文件更新 SSH 配置
|
||||
// @Accept json
|
||||
// @Param request body dto.SSHConf true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /host/conffile/update [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"修改 SSH 配置文件","formatEN":"update SSH conf"}
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改 SSH 配置文件","formatEN":"update SSH conf"}
|
||||
func (b *BaseApi) UpdateSSHByfile(c *gin.Context) {
|
||||
var req dto.SSHConf
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -104,14 +104,14 @@ func (b *BaseApi) UpdateSSHByfile(c *gin.Context) {
|
||||
}
|
||||
|
||||
// @Tags SSH
|
||||
// @Summary Generate host ssh secret
|
||||
// @Description 生成 ssh 密钥
|
||||
// @Summary Generate host SSH secret
|
||||
// @Description 生成 SSH 密钥
|
||||
// @Accept json
|
||||
// @Param request body dto.GenerateSSH true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /host/ssh/generate [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"生成 SSH 密钥 ","formatEN":"generate SSH secret"}
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"生成 SSH 密钥 ","formatEN":"generate SSH secret"}
|
||||
func (b *BaseApi) GenerateSSH(c *gin.Context) {
|
||||
var req dto.GenerateSSH
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -131,8 +131,8 @@ func (b *BaseApi) GenerateSSH(c *gin.Context) {
|
||||
}
|
||||
|
||||
// @Tags SSH
|
||||
// @Summary Load host ssh secret
|
||||
// @Description 获取 ssh 密钥
|
||||
// @Summary Load host SSH secret
|
||||
// @Description 获取 SSH 密钥
|
||||
// @Accept json
|
||||
// @Param request body dto.GenerateLoad true "request"
|
||||
// @Success 200
|
||||
@@ -158,13 +158,40 @@ func (b *BaseApi) LoadSSHSecret(c *gin.Context) {
|
||||
}
|
||||
|
||||
// @Tags SSH
|
||||
// @Summary Load host ssh logs
|
||||
// @Description 获取 ssh 登录日志
|
||||
// @Summary Analysis host SSH logs
|
||||
// @Description 分析 SSH 登录日志
|
||||
// @Accept json
|
||||
// @Param request body dto.SearchForAnalysis true "request"
|
||||
// @Success 200 {array} dto.SSHLogAnalysis
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /host/ssh/log/analysis [post]
|
||||
func (b *BaseApi) AnalysisLog(c *gin.Context) {
|
||||
var req dto.SearchForAnalysis
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if err := global.VALID.Struct(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
|
||||
data, err := sshService.AnalysisLog(req)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
||||
// @Tags SSH
|
||||
// @Summary Load host SSH logs
|
||||
// @Description 获取 SSH 登录日志
|
||||
// @Accept json
|
||||
// @Param request body dto.SearchSSHLog true "request"
|
||||
// @Success 200 {object} dto.SSHLog
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /host/ssh/logs [post]
|
||||
// @Router /host/ssh/log [post]
|
||||
func (b *BaseApi) LoadSSHLogs(c *gin.Context) {
|
||||
var req dto.SearchSSHLog
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -185,8 +212,8 @@ func (b *BaseApi) LoadSSHLogs(c *gin.Context) {
|
||||
}
|
||||
|
||||
// @Tags SSH
|
||||
// @Summary Load host ssh conf
|
||||
// @Description 获取 ssh 配置文件
|
||||
// @Summary Load host SSH conf
|
||||
// @Description 获取 SSH 配置文件
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /host/ssh/conf [get]
|
||||
|
||||
@@ -52,7 +52,7 @@ func (b *BaseApi) GetNotesByVersion(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/upgrade [post]
|
||||
// @x-panel-log {"bodyKeys":["version"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新系统 => [version]","formatEN":"upgrade service => [version]"}
|
||||
// @x-panel-log {"bodyKeys":["version"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新系统 => [version]","formatEN":"upgrade service => [version]"}
|
||||
func (b *BaseApi) Upgrade(c *gin.Context) {
|
||||
var req dto.Upgrade
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -71,7 +71,7 @@ func (b *BaseApi) GetWebsiteOptions(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites [post]
|
||||
// @x-panel-log {"bodyKeys":["primaryDomain"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建网站 [primaryDomain]","formatEN":"Create website [primaryDomain]"}
|
||||
// @x-panel-log {"bodyKeys":["primaryDomain"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建网站 [primaryDomain]","formatEN":"Create website [primaryDomain]"}
|
||||
func (b *BaseApi) CreateWebsite(c *gin.Context) {
|
||||
var req request.WebsiteCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -95,7 +95,7 @@ func (b *BaseApi) CreateWebsite(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/operate [post]
|
||||
// @x-panel-log {"bodyKeys":["id", "operate"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"[operate] 网站 [domain]","formatEN":"[operate] website [domain]"}
|
||||
// @x-panel-log {"bodyKeys":["id", "operate"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"[operate] 网站 [domain]","formatEN":"[operate] website [domain]"}
|
||||
func (b *BaseApi) OpWebsite(c *gin.Context) {
|
||||
var req request.WebsiteOp
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -118,7 +118,7 @@ func (b *BaseApi) OpWebsite(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/del [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"删除网站 [domain]","formatEN":"Delete website [domain]"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"删除网站 [domain]","formatEN":"Delete website [domain]"}
|
||||
func (b *BaseApi) DeleteWebsite(c *gin.Context) {
|
||||
var req request.WebsiteDelete
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -142,7 +142,7 @@ func (b *BaseApi) DeleteWebsite(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/update [post]
|
||||
// @x-panel-log {"bodyKeys":["primaryDomain"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新网站 [primaryDomain]","formatEN":"Update website [primaryDomain]"}
|
||||
// @x-panel-log {"bodyKeys":["primaryDomain"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新网站 [primaryDomain]","formatEN":"Update website [primaryDomain]"}
|
||||
func (b *BaseApi) UpdateWebsite(c *gin.Context) {
|
||||
var req request.WebsiteUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -232,7 +232,7 @@ func (b *BaseApi) GetWebDomains(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/domains/del [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_domains","output_column":"domain","output_value":"domain"}],"formatZH":"删除域名 [domain]","formatEN":"Delete domain [domain]"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_domains","output_column":"domain","output_value":"domain"}],"formatZH":"删除域名 [domain]","formatEN":"Delete domain [domain]"}
|
||||
func (b *BaseApi) DeleteWebDomain(c *gin.Context) {
|
||||
var req request.WebsiteDomainDelete
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -255,7 +255,7 @@ func (b *BaseApi) DeleteWebDomain(c *gin.Context) {
|
||||
// @Success 200 {object} model.WebsiteDomain
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/domains [post]
|
||||
// @x-panel-log {"bodyKeys":["domain"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建域名 [domain]","formatEN":"Create domain [domain]"}
|
||||
// @x-panel-log {"bodyKeys":["domain"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建域名 [domain]","formatEN":"Create domain [domain]"}
|
||||
func (b *BaseApi) CreateWebDomain(c *gin.Context) {
|
||||
var req request.WebsiteDomainCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -300,7 +300,7 @@ func (b *BaseApi) GetNginxConfig(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/config/update [post]
|
||||
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"nginx 配置修改 [domain]","formatEN":"Nginx conf update [domain]"}
|
||||
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"nginx 配置修改 [domain]","formatEN":"Nginx conf update [domain]"}
|
||||
func (b *BaseApi) UpdateNginxConfig(c *gin.Context) {
|
||||
var req request.NginxConfigUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -344,7 +344,7 @@ func (b *BaseApi) GetHTTPSConfig(c *gin.Context) {
|
||||
// @Success 200 {object} response.WebsiteHTTPS
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/:id/https [post]
|
||||
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新网站 [domain] https 配置","formatEN":"Update website https [domain] conf"}
|
||||
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新网站 [domain] https 配置","formatEN":"Update website https [domain] conf"}
|
||||
func (b *BaseApi) UpdateHTTPSConfig(c *gin.Context) {
|
||||
var req request.WebsiteHTTPSOp
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -414,7 +414,7 @@ func (b *BaseApi) GetWebsiteWafConfig(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/waf/update [post]
|
||||
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"WAF 配置修改 [domain]","formatEN":"WAF conf update [domain]"}
|
||||
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"WAF 配置修改 [domain]","formatEN":"WAF conf update [domain]"}
|
||||
func (b *BaseApi) UpdateWebsiteWafConfig(c *gin.Context) {
|
||||
var req request.WebsiteWafUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -436,7 +436,7 @@ func (b *BaseApi) UpdateWebsiteWafConfig(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/waf/file/update [post]
|
||||
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"WAF 配置文件修改 [domain]","formatEN":"WAF conf file update [domain]"}
|
||||
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"WAF 配置文件修改 [domain]","formatEN":"WAF conf file update [domain]"}
|
||||
func (b *BaseApi) UpdateWebsiteWafFile(c *gin.Context) {
|
||||
var req request.WebsiteWafFileUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -458,7 +458,7 @@ func (b *BaseApi) UpdateWebsiteWafFile(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/nginx/update [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"[domain] Nginx 配置修改","formatEN":"[domain] Nginx conf update"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"[domain] Nginx 配置修改","formatEN":"[domain] Nginx conf update"}
|
||||
func (b *BaseApi) UpdateWebsiteNginxConfig(c *gin.Context) {
|
||||
var req request.WebsiteNginxUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -480,7 +480,7 @@ func (b *BaseApi) UpdateWebsiteNginxConfig(c *gin.Context) {
|
||||
// @Success 200 {object} response.WebsiteLog
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/log [post]
|
||||
// @x-panel-log {"bodyKeys":["id", "operate"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"[domain][operate] 日志","formatEN":"[domain][operate] logs"}
|
||||
// @x-panel-log {"bodyKeys":["id", "operate"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"[domain][operate] 日志","formatEN":"[domain][operate] logs"}
|
||||
func (b *BaseApi) OpWebsiteLog(c *gin.Context) {
|
||||
var req request.WebsiteLogReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -503,7 +503,7 @@ func (b *BaseApi) OpWebsiteLog(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/default/server [post]
|
||||
// @x-panel-log {"bodyKeys":["id", "operate"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改默认 server => [domain]","formatEN":"Change default server => [domain]"}
|
||||
// @x-panel-log {"bodyKeys":["id", "operate"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改默认 server => [domain]","formatEN":"Change default server => [domain]"}
|
||||
func (b *BaseApi) ChangeDefaultServer(c *gin.Context) {
|
||||
var req request.WebsiteDefaultUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -547,7 +547,7 @@ func (b *BaseApi) GetWebsitePHPConfig(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/php/config [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"[domain] PHP 配置修改","formatEN":"[domain] PHP conf update"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"[domain] PHP 配置修改","formatEN":"[domain] PHP conf update"}
|
||||
func (b *BaseApi) UpdateWebsitePHPConfig(c *gin.Context) {
|
||||
var req request.WebsitePHPConfigUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -569,7 +569,7 @@ func (b *BaseApi) UpdateWebsitePHPConfig(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/php/update [post]
|
||||
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"php 配置修改 [domain]","formatEN":"Nginx conf update [domain]"}
|
||||
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"php 配置修改 [domain]","formatEN":"Nginx conf update [domain]"}
|
||||
func (b *BaseApi) UpdatePHPFile(c *gin.Context) {
|
||||
var req request.WebsitePHPFileUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -591,7 +591,7 @@ func (b *BaseApi) UpdatePHPFile(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/php/version [post]
|
||||
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"php 版本变更 [domain]","formatEN":"php version update [domain]"}
|
||||
// @x-panel-log {"bodyKeys":["websiteId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteId","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"php 版本变更 [domain]","formatEN":"php version update [domain]"}
|
||||
func (b *BaseApi) ChangePHPVersion(c *gin.Context) {
|
||||
var req request.WebsitePHPVersionReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -635,7 +635,7 @@ func (b *BaseApi) GetRewriteConfig(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/rewrite/update [post]
|
||||
// @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"伪静态配置修改 [domain]","formatEN":"Nginx conf rewrite update [domain]"}
|
||||
// @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"伪静态配置修改 [domain]","formatEN":"Nginx conf rewrite update [domain]"}
|
||||
func (b *BaseApi) UpdateRewriteConfig(c *gin.Context) {
|
||||
var req request.NginxRewriteUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -657,7 +657,7 @@ func (b *BaseApi) UpdateRewriteConfig(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/dir/update [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新网站 [domain] 目录","formatEN":"Update domain [domain] dir"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新网站 [domain] 目录","formatEN":"Update domain [domain] dir"}
|
||||
func (b *BaseApi) UpdateSiteDir(c *gin.Context) {
|
||||
var req request.WebsiteUpdateDir
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -679,7 +679,7 @@ func (b *BaseApi) UpdateSiteDir(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/dir/permission [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新网站 [domain] 目录权限","formatEN":"Update domain [domain] dir permission"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新网站 [domain] 目录权限","formatEN":"Update domain [domain] dir permission"}
|
||||
func (b *BaseApi) UpdateSiteDirPermission(c *gin.Context) {
|
||||
var req request.WebsiteUpdateDirPermission
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -723,7 +723,7 @@ func (b *BaseApi) GetProxyConfig(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/proxies/update [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改网站 [domain] 反向代理配置 ","formatEN":"Update domain [domain] proxy config"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改网站 [domain] 反向代理配置 ","formatEN":"Update domain [domain] proxy config"}
|
||||
func (b *BaseApi) UpdateProxyConfig(c *gin.Context) {
|
||||
var req request.WebsiteProxyConfig
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -746,7 +746,7 @@ func (b *BaseApi) UpdateProxyConfig(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/proxy/file [post]
|
||||
// @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新反向代理文件 [domain]","formatEN":"Nginx conf proxy file update [domain]"}
|
||||
// @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新反向代理文件 [domain]","formatEN":"Nginx conf proxy file update [domain]"}
|
||||
func (b *BaseApi) UpdateProxyConfigFile(c *gin.Context) {
|
||||
var req request.NginxProxyUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -854,7 +854,7 @@ func (b *BaseApi) UpdateAntiLeech(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/redirect/update [post]
|
||||
// @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改网站 [domain] 重定向理配置 ","formatEN":"Update domain [domain] redirect config"}
|
||||
// @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"修改网站 [domain] 重定向理配置 ","formatEN":"Update domain [domain] redirect config"}
|
||||
func (b *BaseApi) UpdateRedirectConfig(c *gin.Context) {
|
||||
var req request.NginxRedirectReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -899,7 +899,7 @@ func (b *BaseApi) GetRedirectConfig(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/redirect/file [post]
|
||||
// @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新重定向文件 [domain]","formatEN":"Nginx conf redirect file update [domain]"}
|
||||
// @x-panel-log {"bodyKeys":["websiteID"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"websiteID","isList":false,"db":"websites","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新重定向文件 [domain]","formatEN":"Nginx conf redirect file update [domain]"}
|
||||
func (b *BaseApi) UpdateRedirectConfigFile(c *gin.Context) {
|
||||
var req request.NginxRedirectUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -41,7 +41,7 @@ func (b *BaseApi) PageWebsiteAcmeAccount(c *gin.Context) {
|
||||
// @Success 200 {object} response.WebsiteAcmeAccountDTO
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/acme [post]
|
||||
// @x-panel-log {"bodyKeys":["email"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建网站 acme [email]","formatEN":"Create website acme [email]"}
|
||||
// @x-panel-log {"bodyKeys":["email"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建网站 acme [email]","formatEN":"Create website acme [email]"}
|
||||
func (b *BaseApi) CreateWebsiteAcmeAccount(c *gin.Context) {
|
||||
var req request.WebsiteAcmeAccountCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -64,7 +64,7 @@ func (b *BaseApi) CreateWebsiteAcmeAccount(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/acme/del [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_acme_accounts","output_column":"email","output_value":"email"}],"formatZH":"删除网站 acme [email]","formatEN":"Delete website acme [email]"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_acme_accounts","output_column":"email","output_value":"email"}],"formatZH":"删除网站 acme [email]","formatEN":"Delete website acme [email]"}
|
||||
func (b *BaseApi) DeleteWebsiteAcmeAccount(c *gin.Context) {
|
||||
var req request.WebsiteResourceReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -41,7 +41,7 @@ func (b *BaseApi) PageWebsiteDnsAccount(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/dns [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建网站 dns [name]","formatEN":"Create website dns [name]"}
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建网站 dns [name]","formatEN":"Create website dns [name]"}
|
||||
func (b *BaseApi) CreateWebsiteDnsAccount(c *gin.Context) {
|
||||
var req request.WebsiteDnsAccountCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -63,7 +63,7 @@ func (b *BaseApi) CreateWebsiteDnsAccount(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/dns/update [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新网站 dns [name]","formatEN":"Update website dns [name]"}
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新网站 dns [name]","formatEN":"Update website dns [name]"}
|
||||
func (b *BaseApi) UpdateWebsiteDnsAccount(c *gin.Context) {
|
||||
var req request.WebsiteDnsAccountUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -85,7 +85,7 @@ func (b *BaseApi) UpdateWebsiteDnsAccount(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/dns/del [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_dns_accounts","output_column":"name","output_value":"name"}],"formatZH":"删除网站 dns [name]","formatEN":"Delete website dns [name]"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_dns_accounts","output_column":"name","output_value":"name"}],"formatZH":"删除网站 dns [name]","formatEN":"Delete website dns [name]"}
|
||||
func (b *BaseApi) DeleteWebsiteDnsAccount(c *gin.Context) {
|
||||
var req request.WebsiteResourceReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -52,7 +52,7 @@ func (b *BaseApi) PageWebsiteSSL(c *gin.Context) {
|
||||
// @Success 200 {object} request.WebsiteSSLCreate
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/ssl [post]
|
||||
// @x-panel-log {"bodyKeys":["primaryDomain"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建网站 ssl [primaryDomain]","formatEN":"Create website ssl [primaryDomain]"}
|
||||
// @x-panel-log {"bodyKeys":["primaryDomain"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建网站 ssl [primaryDomain]","formatEN":"Create website ssl [primaryDomain]"}
|
||||
func (b *BaseApi) CreateWebsiteSSL(c *gin.Context) {
|
||||
var req request.WebsiteSSLCreate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -75,7 +75,7 @@ func (b *BaseApi) CreateWebsiteSSL(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/ssl/renew [post]
|
||||
// @x-panel-log {"bodyKeys":["SSLId"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"SSLId","isList":false,"db":"website_ssls","output_column":"primary_domain","output_value":"domain"}],"formatZH":"重置 ssl [domain]","formatEN":"Renew ssl [domain]"}
|
||||
// @x-panel-log {"bodyKeys":["SSLId"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"SSLId","isList":false,"db":"website_ssls","output_column":"primary_domain","output_value":"domain"}],"formatZH":"重置 ssl [domain]","formatEN":"Renew ssl [domain]"}
|
||||
func (b *BaseApi) RenewWebsiteSSL(c *gin.Context) {
|
||||
var req request.WebsiteSSLRenew
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -119,7 +119,7 @@ func (b *BaseApi) GetDNSResolve(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/ssl/del [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_ssls","output_column":"primary_domain","output_value":"domain"}],"formatZH":"删除 ssl [domain]","formatEN":"Delete ssl [domain]"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_ssls","output_column":"primary_domain","output_value":"domain"}],"formatZH":"删除 ssl [domain]","formatEN":"Delete ssl [domain]"}
|
||||
func (b *BaseApi) DeleteWebsiteSSL(c *gin.Context) {
|
||||
var req request.WebsiteResourceReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -185,7 +185,7 @@ func (b *BaseApi) GetWebsiteSSLById(c *gin.Context) {
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /websites/ssl/update [post]
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_ssls","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新证书设置 [domain]","formatEN":"Update ssl config [domain]"}
|
||||
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_ssls","output_column":"primary_domain","output_value":"domain"}],"formatZH":"更新证书设置 [domain]","formatEN":"Update ssl config [domain]"}
|
||||
func (b *BaseApi) UpdateWebsiteSSL(c *gin.Context) {
|
||||
var req request.WebsiteSSLUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -98,6 +98,7 @@ type AppConfigVersion struct {
|
||||
type Tag struct {
|
||||
Key string `json:"key"`
|
||||
Name string `json:"name"`
|
||||
Sort int `json:"sort"`
|
||||
}
|
||||
|
||||
type AppForm struct {
|
||||
|
||||
@@ -11,6 +11,11 @@ type UserLoginInfo struct {
|
||||
MfaStatus string `json:"mfaStatus"`
|
||||
}
|
||||
|
||||
type MfaRequest struct {
|
||||
Title string `json:"title"`
|
||||
Interval int `json:"interval"`
|
||||
}
|
||||
|
||||
type MfaCredential struct {
|
||||
Secret string `json:"secret"`
|
||||
Code string `json:"code"`
|
||||
|
||||
@@ -44,6 +44,8 @@ type ContainerOperate struct {
|
||||
Network string `json:"network"`
|
||||
PublishAllPorts bool `json:"publishAllPorts"`
|
||||
ExposedPorts []PortHelper `json:"exposedPorts"`
|
||||
Tty bool `json:"tty"`
|
||||
OpenStdin bool `json:"openStdin"`
|
||||
Cmd []string `json:"cmd"`
|
||||
Entrypoint []string `json:"entrypoint"`
|
||||
CPUShares int64 `json:"cpuShares"`
|
||||
@@ -63,8 +65,16 @@ type ContainerUpgrade struct {
|
||||
}
|
||||
|
||||
type ContainerListStats struct {
|
||||
ContainerID string `json:"containerID"`
|
||||
ContainerID string `json:"containerID"`
|
||||
|
||||
CPUTotalUsage uint64 `json:"cpuTotalUsage"`
|
||||
SystemUsage uint64 `json:"systemUsage"`
|
||||
CPUPercent float64 `json:"cpuPercent"`
|
||||
PercpuUsage int `json:"percpuUsage"`
|
||||
|
||||
MemoryCache uint64 `json:"memoryCache"`
|
||||
MemoryUsage uint64 `json:"memoryUsage"`
|
||||
MemoryLimit uint64 `json:"memoryLimit"`
|
||||
MemoryPercent float64 `json:"memoryPercent"`
|
||||
}
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@ package dto
|
||||
import "time"
|
||||
|
||||
type DashboardBase struct {
|
||||
WebsiteNumber int `json:"websiteNumber"`
|
||||
DatabaseNumber int `json:"databaseNumber"`
|
||||
CronjobNumber int `json:"cronjobNumber"`
|
||||
AppInstalldNumber int `json:"appInstalldNumber"`
|
||||
WebsiteNumber int `json:"websiteNumber"`
|
||||
DatabaseNumber int `json:"databaseNumber"`
|
||||
CronjobNumber int `json:"cronjobNumber"`
|
||||
AppInstalledNumber int `json:"appInstalledNumber"`
|
||||
|
||||
Hostname string `json:"hostname"`
|
||||
OS string `json:"os"`
|
||||
|
||||
@@ -271,3 +271,9 @@ type DatabaseUpdate struct {
|
||||
Password string `json:"password" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type DatabaseDelete struct {
|
||||
ID uint `json:"id" validate:"required"`
|
||||
ForceDelete bool `json:"forceDelete"`
|
||||
DeleteBackup bool `json:"deleteBackup"`
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import "time"
|
||||
type ImageInfo struct {
|
||||
ID string `json:"id"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
IsUsed bool `json:"isUsed"`
|
||||
Tags []string `json:"tags"`
|
||||
Size string `json:"size"`
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ type AppSearch struct {
|
||||
Tags []string `json:"tags"`
|
||||
Type string `json:"type"`
|
||||
Recommend bool `json:"recommend"`
|
||||
Resource string `json:"resource"`
|
||||
}
|
||||
|
||||
type AppInstallCreate struct {
|
||||
|
||||
@@ -18,10 +18,19 @@ type RuntimeCreate struct {
|
||||
Type string `json:"type"`
|
||||
Version string `json:"version"`
|
||||
Source string `json:"source"`
|
||||
CodeDir string `json:"codeDir"`
|
||||
NodeConfig
|
||||
}
|
||||
|
||||
type NodeConfig struct {
|
||||
Install bool `json:"install"`
|
||||
Clean bool `json:"clean"`
|
||||
Port int `json:"port"`
|
||||
}
|
||||
|
||||
type RuntimeDelete struct {
|
||||
ID uint `json:"id"`
|
||||
ID uint `json:"id"`
|
||||
ForceDelete bool `json:"forceDelete"`
|
||||
}
|
||||
|
||||
type RuntimeUpdate struct {
|
||||
@@ -32,4 +41,26 @@ type RuntimeUpdate struct {
|
||||
Version string `json:"version"`
|
||||
Rebuild bool `json:"rebuild"`
|
||||
Source string `json:"source"`
|
||||
CodeDir string `json:"codeDir"`
|
||||
NodeConfig
|
||||
}
|
||||
|
||||
type NodePackageReq struct {
|
||||
CodeDir string `json:"codeDir"`
|
||||
}
|
||||
|
||||
type RuntimeOperate struct {
|
||||
Operate string `json:"operate"`
|
||||
ID uint `json:"ID"`
|
||||
}
|
||||
|
||||
type NodeModuleOperateReq struct {
|
||||
Operate string `json:"operate" validate:"oneof=install uninstall update"`
|
||||
ID uint `json:"ID" validate:"required"`
|
||||
Module string `json:"module"`
|
||||
PkgManager string `json:"pkgManager" validate:"oneof=npm yarn"`
|
||||
}
|
||||
|
||||
type NodeModuleReq struct {
|
||||
ID uint `json:"ID" validate:"required"`
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package response
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
|
||||
"time"
|
||||
|
||||
@@ -13,8 +14,9 @@ type AppRes struct {
|
||||
}
|
||||
|
||||
type AppUpdateRes struct {
|
||||
CanUpdate bool `json:"canUpdate"`
|
||||
AppStoreLastModified int `json:"appStoreLastModified"`
|
||||
CanUpdate bool `json:"canUpdate"`
|
||||
AppStoreLastModified int `json:"appStoreLastModified"`
|
||||
AppList *dto.AppList `json:"appList"`
|
||||
}
|
||||
|
||||
type AppDTO struct {
|
||||
@@ -77,6 +79,7 @@ type AppService struct {
|
||||
Label string `json:"label"`
|
||||
Value string `json:"value"`
|
||||
Config interface{} `json:"config"`
|
||||
From string `json:"from"`
|
||||
}
|
||||
|
||||
type AppParam struct {
|
||||
|
||||
@@ -1,10 +1,56 @@
|
||||
package response
|
||||
|
||||
import "github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
"time"
|
||||
)
|
||||
|
||||
type RuntimeRes struct {
|
||||
model.Runtime
|
||||
AppParams []AppParam `json:"appParams"`
|
||||
AppID uint `json:"appId"`
|
||||
Source string `json:"source"`
|
||||
type RuntimeDTO struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Resource string `json:"resource"`
|
||||
AppDetailID uint `json:"appDetailID"`
|
||||
AppID uint `json:"appID"`
|
||||
Source string `json:"source"`
|
||||
Status string `json:"status"`
|
||||
Type string `json:"type"`
|
||||
Image string `json:"image"`
|
||||
Params map[string]interface{} `json:"params"`
|
||||
Message string `json:"message"`
|
||||
Version string `json:"version"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
CodeDir string `json:"codeDir"`
|
||||
AppParams []AppParam `json:"appParams"`
|
||||
Port int `json:"port"`
|
||||
Path string `json:"path"`
|
||||
}
|
||||
|
||||
type PackageScripts struct {
|
||||
Name string `json:"name"`
|
||||
Script string `json:"script"`
|
||||
}
|
||||
|
||||
func NewRuntimeDTO(runtime model.Runtime) RuntimeDTO {
|
||||
return RuntimeDTO{
|
||||
ID: runtime.ID,
|
||||
Name: runtime.Name,
|
||||
Resource: runtime.Resource,
|
||||
AppDetailID: runtime.AppDetailID,
|
||||
Status: runtime.Status,
|
||||
Type: runtime.Type,
|
||||
Image: runtime.Image,
|
||||
Message: runtime.Message,
|
||||
CreatedAt: runtime.CreatedAt,
|
||||
CodeDir: runtime.CodeDir,
|
||||
Version: runtime.Version,
|
||||
Port: runtime.Port,
|
||||
Path: runtime.GetPath(),
|
||||
}
|
||||
}
|
||||
|
||||
type NodeModule struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
License string `json:"license"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
@@ -13,10 +13,14 @@ type SettingInfo struct {
|
||||
TimeZone string `json:"timeZone"`
|
||||
NtpSite string `json:"ntpSite"`
|
||||
|
||||
Port string `json:"port"`
|
||||
PanelName string `json:"panelName"`
|
||||
Theme string `json:"theme"`
|
||||
Language string `json:"language"`
|
||||
Port string `json:"port"`
|
||||
PanelName string `json:"panelName"`
|
||||
Theme string `json:"theme"`
|
||||
Language string `json:"language"`
|
||||
DefaultNetwork string `json:"defaultNetwork"`
|
||||
LastCleanTime string `json:"lastCleanTime"`
|
||||
LastCleanSize string `json:"lastCleanSize"`
|
||||
LastCleanData string `json:"lastCleanData"`
|
||||
|
||||
ServerPort string `json:"serverPort"`
|
||||
SSL string `json:"ssl"`
|
||||
@@ -135,3 +139,29 @@ type SyncTime struct {
|
||||
type Upgrade struct {
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
type CleanData struct {
|
||||
SystemClean []CleanTree `json:"systemClean"`
|
||||
UploadClean []CleanTree `json:"uploadClean"`
|
||||
DownloadClean []CleanTree `json:"downloadClean"`
|
||||
SystemLogClean []CleanTree `json:"systemLogClean"`
|
||||
}
|
||||
|
||||
type CleanTree struct {
|
||||
ID string `json:"id"`
|
||||
Label string `json:"label"`
|
||||
Children []CleanTree `json:"children"`
|
||||
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
|
||||
Size uint64 `json:"size"`
|
||||
IsCheck bool `json:"isCheck"`
|
||||
IsRecommend bool `json:"isRecommend"`
|
||||
}
|
||||
|
||||
type Clean struct {
|
||||
TreeType string `json:"treeType"`
|
||||
Name string `json:"name"`
|
||||
Size uint64 `json:"size"`
|
||||
}
|
||||
|
||||
@@ -36,6 +36,27 @@ type SSHLog struct {
|
||||
SuccessfulCount int `json:"successfulCount"`
|
||||
FailedCount int `json:"failedCount"`
|
||||
}
|
||||
|
||||
type SearchForAnalysis struct {
|
||||
PageInfo
|
||||
OrderBy string `json:"orderBy" validate:"required,oneof=Success Failed"`
|
||||
}
|
||||
|
||||
type AnalysisRes struct {
|
||||
Total int64 `json:"total"`
|
||||
Items []SSHLogAnalysis `json:"items"`
|
||||
SuccessfulCount int `json:"successfulCount"`
|
||||
FailedCount int `json:"failedCount"`
|
||||
}
|
||||
|
||||
type SSHLogAnalysis struct {
|
||||
Address string `json:"address"`
|
||||
Area string `json:"area"`
|
||||
SuccessfulCount int `json:"successfulCount"`
|
||||
FailedCount int `json:"failedCount"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
type SSHHistory struct {
|
||||
Date time.Time `json:"date"`
|
||||
DateStr string `json:"dateStr"`
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"path"
|
||||
)
|
||||
|
||||
type Runtime struct {
|
||||
BaseModel
|
||||
Name string `gorm:"type:varchar;not null" json:"name"`
|
||||
@@ -13,5 +18,23 @@ type Runtime struct {
|
||||
Type string `gorm:"type:varchar;not null" json:"type"`
|
||||
Status string `gorm:"type:varchar;not null" json:"status"`
|
||||
Resource string `gorm:"type:varchar;not null" json:"resource"`
|
||||
Port int `gorm:"type:integer;" json:"port"`
|
||||
Message string `gorm:"type:longtext;" json:"message"`
|
||||
CodeDir string `gorm:"type:varchar;" json:"codeDir"`
|
||||
}
|
||||
|
||||
func (r *Runtime) GetComposePath() string {
|
||||
return path.Join(r.GetPath(), "docker-compose.yml")
|
||||
}
|
||||
|
||||
func (r *Runtime) GetEnvPath() string {
|
||||
return path.Join(r.GetPath(), ".env")
|
||||
}
|
||||
|
||||
func (r *Runtime) GetPath() string {
|
||||
return path.Join(constant.RuntimeDir, r.Type, r.Name)
|
||||
}
|
||||
|
||||
func (r *Runtime) GetLogPath() string {
|
||||
return path.Join(r.GetPath(), "build.log")
|
||||
}
|
||||
|
||||
@@ -4,4 +4,5 @@ type Tag struct {
|
||||
BaseModel
|
||||
Key string `json:"key" gorm:"type:varchar(64);not null"`
|
||||
Name string `json:"name" gorm:"type:varchar(64);not null"`
|
||||
Sort int `json:"sort" gorm:"type:int;not null;default:1"`
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ type ICommonRepo interface {
|
||||
WithByDate(startTime, endTime time.Time) DBOption
|
||||
WithByStartDate(startTime time.Time) DBOption
|
||||
WithByStatus(status string) DBOption
|
||||
WithByFrom(from string) DBOption
|
||||
}
|
||||
|
||||
type CommonRepo struct{}
|
||||
@@ -80,6 +81,12 @@ func (c *CommonRepo) WithByStatus(status string) DBOption {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CommonRepo) WithByFrom(from string) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("`from` = ?", from)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CommonRepo) WithLikeName(name string) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
if len(name) == 0 {
|
||||
|
||||
@@ -22,6 +22,7 @@ type ICronjobRepo interface {
|
||||
WithByJobID(id int) DBOption
|
||||
WithByBackupID(id uint) DBOption
|
||||
WithByRecordDropID(id int) DBOption
|
||||
WithByRecordFile(file string) DBOption
|
||||
Save(id uint, cronjob model.Cronjob) error
|
||||
Update(id uint, vars map[string]interface{}) error
|
||||
Delete(opts ...DBOption) error
|
||||
@@ -121,6 +122,12 @@ func (c *CronjobRepo) WithByBackupID(id uint) DBOption {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CronjobRepo) WithByRecordFile(file string) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("records = ?", file)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CronjobRepo) WithByRecordDropID(id int) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("id < ?", id)
|
||||
|
||||
@@ -17,6 +17,7 @@ type IRuntimeRepo interface {
|
||||
WithNotId(id uint) DBOption
|
||||
WithStatus(status string) DBOption
|
||||
WithDetailId(id uint) DBOption
|
||||
WithPort(port int) DBOption
|
||||
Page(page, size int, opts ...DBOption) (int64, []model.Runtime, error)
|
||||
Create(ctx context.Context, runtime *model.Runtime) error
|
||||
Save(runtime *model.Runtime) error
|
||||
@@ -59,6 +60,12 @@ func (r *RuntimeRepo) WithNotId(id uint) DBOption {
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RuntimeRepo) WithPort(port int) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("port = ?", port)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RuntimeRepo) Page(page, size int, opts ...DBOption) (int64, []model.Runtime, error) {
|
||||
var runtimes []model.Runtime
|
||||
db := getDb(opts...).Model(&model.Runtime{})
|
||||
|
||||
@@ -31,7 +31,7 @@ func (t TagRepo) DeleteAll(ctx context.Context) error {
|
||||
|
||||
func (t TagRepo) All() ([]model.Tag, error) {
|
||||
var tags []model.Tag
|
||||
if err := getDb().Where("1 = 1 ").Find(&tags).Error; err != nil {
|
||||
if err := getDb().Where("1 = 1 ").Order("sort asc").Find(&tags).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tags, nil
|
||||
|
||||
+80
-63
@@ -61,6 +61,9 @@ func (a AppService) PageApp(req request.AppSearch) (interface{}, error) {
|
||||
if req.Recommend {
|
||||
opts = append(opts, appRepo.GetRecommend())
|
||||
}
|
||||
if req.Resource != "" {
|
||||
opts = append(opts, appRepo.WithResource(req.Resource))
|
||||
}
|
||||
if len(req.Tags) != 0 {
|
||||
tags, err := tagRepo.GetByKeys(req.Tags)
|
||||
if err != nil {
|
||||
@@ -151,12 +154,12 @@ func (a AppService) GetApp(key string) (*response.AppDTO, error) {
|
||||
return &appDTO, nil
|
||||
}
|
||||
|
||||
func (a AppService) GetAppDetail(appId uint, version, appType string) (response.AppDetailDTO, error) {
|
||||
func (a AppService) GetAppDetail(appID uint, version, appType string) (response.AppDetailDTO, error) {
|
||||
var (
|
||||
appDetailDTO response.AppDetailDTO
|
||||
opts []repo.DBOption
|
||||
)
|
||||
opts = append(opts, appDetailRepo.WithAppId(appId), appDetailRepo.WithVersion(version))
|
||||
opts = append(opts, appDetailRepo.WithAppId(appID), appDetailRepo.WithVersion(version))
|
||||
detail, err := appDetailRepo.GetFirst(opts...)
|
||||
if err != nil {
|
||||
return appDetailDTO, err
|
||||
@@ -165,7 +168,7 @@ func (a AppService) GetAppDetail(appId uint, version, appType string) (response.
|
||||
appDetailDTO.Enable = true
|
||||
|
||||
if appType == "runtime" {
|
||||
app, err := appRepo.GetFirst(commonRepo.WithByID(appId))
|
||||
app, err := appRepo.GetFirst(commonRepo.WithByID(appID))
|
||||
if err != nil {
|
||||
return appDetailDTO, err
|
||||
}
|
||||
@@ -176,36 +179,39 @@ func (a AppService) GetAppDetail(appId uint, version, appType string) (response.
|
||||
return appDetailDTO, err
|
||||
}
|
||||
}
|
||||
buildPath := path.Join(versionPath, "build")
|
||||
paramsPath := path.Join(buildPath, "config.json")
|
||||
if !fileOp.Stat(paramsPath) {
|
||||
return appDetailDTO, buserr.New(constant.ErrFileNotExist)
|
||||
}
|
||||
param, err := fileOp.GetContent(paramsPath)
|
||||
if err != nil {
|
||||
return appDetailDTO, err
|
||||
}
|
||||
paramMap := make(map[string]interface{})
|
||||
if err := json.Unmarshal(param, ¶mMap); err != nil {
|
||||
return appDetailDTO, err
|
||||
}
|
||||
appDetailDTO.Params = paramMap
|
||||
composePath := path.Join(buildPath, "docker-compose.yml")
|
||||
if !fileOp.Stat(composePath) {
|
||||
return appDetailDTO, buserr.New(constant.ErrFileNotExist)
|
||||
}
|
||||
compose, err := fileOp.GetContent(composePath)
|
||||
if err != nil {
|
||||
return appDetailDTO, err
|
||||
}
|
||||
composeMap := make(map[string]interface{})
|
||||
if err := yaml.Unmarshal(compose, &composeMap); err != nil {
|
||||
return appDetailDTO, err
|
||||
}
|
||||
if service, ok := composeMap["services"]; ok {
|
||||
servicesMap := service.(map[string]interface{})
|
||||
for k := range servicesMap {
|
||||
appDetailDTO.Image = k
|
||||
switch app.Type {
|
||||
case constant.RuntimePHP:
|
||||
buildPath := path.Join(versionPath, "build")
|
||||
paramsPath := path.Join(buildPath, "config.json")
|
||||
if !fileOp.Stat(paramsPath) {
|
||||
return appDetailDTO, buserr.New(constant.ErrFileNotExist)
|
||||
}
|
||||
param, err := fileOp.GetContent(paramsPath)
|
||||
if err != nil {
|
||||
return appDetailDTO, err
|
||||
}
|
||||
paramMap := make(map[string]interface{})
|
||||
if err := json.Unmarshal(param, ¶mMap); err != nil {
|
||||
return appDetailDTO, err
|
||||
}
|
||||
appDetailDTO.Params = paramMap
|
||||
composePath := path.Join(buildPath, "docker-compose.yml")
|
||||
if !fileOp.Stat(composePath) {
|
||||
return appDetailDTO, buserr.New(constant.ErrFileNotExist)
|
||||
}
|
||||
compose, err := fileOp.GetContent(composePath)
|
||||
if err != nil {
|
||||
return appDetailDTO, err
|
||||
}
|
||||
composeMap := make(map[string]interface{})
|
||||
if err := yaml.Unmarshal(compose, &composeMap); err != nil {
|
||||
return appDetailDTO, err
|
||||
}
|
||||
if service, ok := composeMap["services"]; ok {
|
||||
servicesMap := service.(map[string]interface{})
|
||||
for k := range servicesMap {
|
||||
appDetailDTO.Image = k
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -267,7 +273,7 @@ func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) (
|
||||
return
|
||||
}
|
||||
if list, _ := appInstallRepo.ListBy(commonRepo.WithByName(req.Name)); len(list) > 0 {
|
||||
err = buserr.New(constant.ErrNameIsExist)
|
||||
err = buserr.New(constant.ErrAppNameExist)
|
||||
return
|
||||
}
|
||||
var (
|
||||
@@ -450,11 +456,11 @@ func (a AppService) SyncAppListFromLocal() {
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
global.LOG.Errorf("sync app failed %v", err)
|
||||
global.LOG.Errorf("Sync local app failed %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
global.LOG.Infof("start sync local apps...")
|
||||
global.LOG.Infof("Starting local application synchronization ...")
|
||||
dirEntries, err = os.ReadDir(localAppDir)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -660,17 +666,14 @@ func (a AppService) SyncAppListFromLocal() {
|
||||
}
|
||||
}
|
||||
tx.Commit()
|
||||
global.LOG.Infof("sync local apps success")
|
||||
global.LOG.Infof("Synchronization of local applications completed")
|
||||
}
|
||||
|
||||
func (a AppService) GetAppUpdate() (*response.AppUpdateRes, error) {
|
||||
res := &response.AppUpdateRes{
|
||||
CanUpdate: false,
|
||||
}
|
||||
setting, err := NewISettingService().GetSettingInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
versionUrl := fmt.Sprintf("%s/%s/1panel.json.version.txt", global.CONF.System.AppRepo, global.CONF.System.Mode)
|
||||
versionRes, err := http2.GetHttpRes(versionUrl)
|
||||
if err != nil {
|
||||
@@ -682,38 +685,35 @@ func (a AppService) GetAppUpdate() (*response.AppUpdateRes, error) {
|
||||
return nil, err
|
||||
}
|
||||
lastModifiedStr := string(body)
|
||||
|
||||
lastModified, err := strconv.Atoi(lastModifiedStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
setting, err := NewISettingService().GetSettingInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
appStoreLastModified, _ := strconv.Atoi(setting.AppStoreLastModified)
|
||||
res.AppStoreLastModified = appStoreLastModified
|
||||
if setting.AppStoreLastModified == "" || lastModified != appStoreLastModified {
|
||||
res.CanUpdate = true
|
||||
return res, err
|
||||
}
|
||||
if err = getAppFromRepo(fmt.Sprintf("%s/%s/1panel.json.zip", global.CONF.System.AppRepo, global.CONF.System.Mode)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
listFile := path.Join(constant.ResourceDir, "1panel.json")
|
||||
content, err := os.ReadFile(listFile)
|
||||
list, err := getAppList()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
list := &dto.AppList{}
|
||||
if err = json.Unmarshal(content, list); err != nil {
|
||||
return nil, err
|
||||
return res, err
|
||||
}
|
||||
if list.Extra.Version != "" && setting.SystemVersion != list.Extra.Version && !common.CompareVersion(setting.SystemVersion, list.Extra.Version) {
|
||||
global.LOG.Errorf("The current version is too low to synchronize with the App Store. The minimum required version is %s", list.Extra.Version)
|
||||
return nil, buserr.New("ErrVersionTooLow")
|
||||
}
|
||||
res.AppList = list
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func getAppFromRepo(downloadPath string) error {
|
||||
downloadUrl := downloadPath
|
||||
global.LOG.Infof("download file from %s", downloadUrl)
|
||||
global.LOG.Infof("[AppStore] download file from %s", downloadUrl)
|
||||
fileOp := files.NewFileOp()
|
||||
packagePath := path.Join(constant.ResourceDir, path.Base(downloadUrl))
|
||||
if err := fileOp.DownloadFile(downloadUrl, packagePath); err != nil {
|
||||
@@ -728,25 +728,40 @@ func getAppFromRepo(downloadPath string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func getAppList() (*dto.AppList, error) {
|
||||
list := &dto.AppList{}
|
||||
if err := getAppFromRepo(fmt.Sprintf("%s/%s/1panel.json.zip", global.CONF.System.AppRepo, global.CONF.System.Mode)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
listFile := path.Join(constant.ResourceDir, "1panel.json")
|
||||
content, err := os.ReadFile(listFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = json.Unmarshal(content, list); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (a AppService) SyncAppListFromRemote() (err error) {
|
||||
global.LOG.Infof("Starting synchronization with App Store...")
|
||||
updateRes, err := a.GetAppUpdate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !updateRes.CanUpdate {
|
||||
global.LOG.Infof("The App Store is at the latest version")
|
||||
return
|
||||
}
|
||||
if err = getAppFromRepo(fmt.Sprintf("%s/%s/1panel.json.zip", global.CONF.System.AppRepo, global.CONF.System.Mode)); err != nil {
|
||||
return err
|
||||
}
|
||||
listFile := path.Join(constant.ResourceDir, "1panel.json")
|
||||
content, err := os.ReadFile(listFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
list := &dto.AppList{}
|
||||
if err = json.Unmarshal(content, list); err != nil {
|
||||
return
|
||||
if updateRes.AppList == nil {
|
||||
list, err = getAppList()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
list = updateRes.AppList
|
||||
}
|
||||
|
||||
if err = NewISettingService().Update("AppStoreLastModified", strconv.Itoa(list.LastModified)); err != nil {
|
||||
@@ -768,6 +783,7 @@ func (a AppService) SyncAppListFromRemote() (err error) {
|
||||
tags = append(tags, &model.Tag{
|
||||
Key: t.Key,
|
||||
Name: t.Name,
|
||||
Sort: t.Sort,
|
||||
})
|
||||
}
|
||||
oldApps, err := appRepo.GetBy(appRepo.WithResource(constant.AppResourceRemote))
|
||||
@@ -957,5 +973,6 @@ func (a AppService) SyncAppListFromRemote() (err error) {
|
||||
}
|
||||
}
|
||||
tx.Commit()
|
||||
global.LOG.Infof("Synchronization with the App Store was successful!")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -428,7 +428,7 @@ func (a *AppInstallService) SyncAll(systemInit bool) error {
|
||||
func (a *AppInstallService) GetServices(key string) ([]response.AppService, error) {
|
||||
var res []response.AppService
|
||||
if DatabaseKeys[key] > 0 {
|
||||
dbs, _ := databaseRepo.GetList(databaseRepo.WithByFrom("local"), commonRepo.WithByType(key))
|
||||
dbs, _ := databaseRepo.GetList(commonRepo.WithByType(key))
|
||||
if len(dbs) == 0 {
|
||||
return res, nil
|
||||
}
|
||||
@@ -447,6 +447,9 @@ func (a *AppInstallService) GetServices(key string) ([]response.AppService, erro
|
||||
_ = json.Unmarshal([]byte(install.Param), ¶mMap)
|
||||
}
|
||||
service.Config = paramMap
|
||||
service.From = constant.AppResourceLocal
|
||||
} else {
|
||||
service.From = constant.AppResourceRemote
|
||||
}
|
||||
res = append(res, service)
|
||||
}
|
||||
@@ -533,9 +536,9 @@ func (a *AppInstallService) ChangeAppPort(req request.PortUpdate) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *AppInstallService) DeleteCheck(installId uint) ([]dto.AppResource, error) {
|
||||
func (a *AppInstallService) DeleteCheck(installID uint) ([]dto.AppResource, error) {
|
||||
var res []dto.AppResource
|
||||
appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(installId))
|
||||
appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(installID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -559,8 +562,8 @@ func (a *AppInstallService) DeleteCheck(installId uint) ([]dto.AppResource, erro
|
||||
})
|
||||
}
|
||||
}
|
||||
if app.Type == "runtime" {
|
||||
resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithLinkId(appInstall.ID))
|
||||
if app.Type == constant.Runtime {
|
||||
resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithLinkId(appInstall.ID), commonRepo.WithByFrom(constant.AppResourceLocal))
|
||||
for _, resource := range resources {
|
||||
linkInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(resource.AppInstallId))
|
||||
res = append(res, dto.AppResource{
|
||||
|
||||
@@ -82,6 +82,33 @@ func checkPort(key string, params map[string]interface{}) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func checkPortExist(port int) error {
|
||||
errMap := make(map[string]interface{})
|
||||
errMap["port"] = port
|
||||
appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithPort(port))
|
||||
if appInstall.ID > 0 {
|
||||
errMap["type"] = i18n.GetMsgByKey("TYPE_APP")
|
||||
errMap["name"] = appInstall.Name
|
||||
return buserr.WithMap("ErrPortExist", errMap, nil)
|
||||
}
|
||||
runtime, _ := runtimeRepo.GetFirst(runtimeRepo.WithPort(port))
|
||||
if runtime != nil {
|
||||
errMap["type"] = i18n.GetMsgByKey("TYPE_RUNTIME")
|
||||
errMap["name"] = runtime.Name
|
||||
return buserr.WithMap("ErrPortExist", errMap, nil)
|
||||
}
|
||||
domain, _ := websiteDomainRepo.GetFirst(websiteDomainRepo.WithPort(port))
|
||||
if domain.ID > 0 {
|
||||
errMap["type"] = i18n.GetMsgByKey("TYPE_DOMAIN")
|
||||
errMap["name"] = domain.Domain
|
||||
return buserr.WithMap("ErrPortExist", errMap, nil)
|
||||
}
|
||||
if common.ScanPort(port) {
|
||||
return buserr.WithDetail(constant.ErrPortInUsed, port, nil)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var DatabaseKeys = map[string]uint{
|
||||
"mysql": 3306,
|
||||
"mariadb": 3306,
|
||||
@@ -173,9 +200,13 @@ func createLink(ctx context.Context, app model.App, appInstall *model.AppInstall
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(dbConfig, dto.AppDatabase{}) && dbConfig.ServiceName != "" {
|
||||
dbInstall, err := appInstallRepo.GetFirst(appInstallRepo.WithServiceName(dbConfig.ServiceName))
|
||||
if err != nil {
|
||||
return err
|
||||
hostName := params["PANEL_DB_HOST_NAME"]
|
||||
if hostName == nil || hostName.(string) == "" {
|
||||
return nil
|
||||
}
|
||||
database, _ := databaseRepo.Get(commonRepo.WithByName(hostName.(string)))
|
||||
if database.ID == 0 {
|
||||
return nil
|
||||
}
|
||||
var resourceId uint
|
||||
if dbConfig.DbName != "" && dbConfig.DbUser != "" && dbConfig.Password != "" {
|
||||
@@ -190,11 +221,11 @@ func createLink(ctx context.Context, app model.App, appInstall *model.AppInstall
|
||||
var createMysql dto.MysqlDBCreate
|
||||
createMysql.Name = dbConfig.DbName
|
||||
createMysql.Username = dbConfig.DbUser
|
||||
createMysql.Database = dbInstall.Name
|
||||
createMysql.Database = database.Name
|
||||
createMysql.Format = "utf8mb4"
|
||||
createMysql.Permission = "%"
|
||||
createMysql.Password = dbConfig.Password
|
||||
createMysql.From = "local"
|
||||
createMysql.From = database.From
|
||||
mysqldb, err := NewIMysqlService().Create(ctx, createMysql)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -205,8 +236,13 @@ func createLink(ctx context.Context, app model.App, appInstall *model.AppInstall
|
||||
var installResource model.AppInstallResource
|
||||
installResource.ResourceId = resourceId
|
||||
installResource.AppInstallId = appInstall.ID
|
||||
installResource.LinkId = dbInstall.ID
|
||||
installResource.Key = dbInstall.App.Key
|
||||
if database.AppInstallID > 0 {
|
||||
installResource.LinkId = database.AppInstallID
|
||||
} else {
|
||||
installResource.LinkId = database.ID
|
||||
}
|
||||
installResource.Key = database.Type
|
||||
installResource.From = database.From
|
||||
if err := appInstallResourceRepo.Create(ctx, &installResource); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -259,6 +295,22 @@ func deleteAppInstall(install model.AppInstall, deleteBackup bool, forceDelete b
|
||||
|
||||
switch install.App.Key {
|
||||
case constant.AppOpenresty:
|
||||
websites, _ := websiteRepo.List()
|
||||
for _, website := range websites {
|
||||
if website.AppInstallID > 0 {
|
||||
websiteAppInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID))
|
||||
if websiteAppInstall.AppId > 0 {
|
||||
websiteApp, _ := appRepo.GetFirst(commonRepo.WithByID(websiteAppInstall.AppId))
|
||||
if websiteApp.Type == constant.RuntimePHP {
|
||||
go func() {
|
||||
_, _ = compose.Down(install.GetComposePath())
|
||||
_ = op.DeleteDir(install.GetPath())
|
||||
}()
|
||||
_ = appInstallRepo.Delete(ctx, websiteAppInstall)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = websiteRepo.DeleteAll(ctx)
|
||||
_ = websiteDomainRepo.DeleteAll(ctx)
|
||||
case constant.AppMysql, constant.AppMariaDB:
|
||||
@@ -559,6 +611,8 @@ func handleMap(params map[string]interface{}, envParams map[string]string) {
|
||||
envParams[k] = strconv.FormatFloat(t, 'f', -1, 32)
|
||||
case uint:
|
||||
envParams[k] = strconv.Itoa(int(t))
|
||||
case int:
|
||||
envParams[k] = strconv.Itoa(t)
|
||||
default:
|
||||
envParams[k] = t.(string)
|
||||
}
|
||||
|
||||
@@ -173,31 +173,36 @@ func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback
|
||||
newEnvFile := ""
|
||||
resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(install.ID))
|
||||
for _, resource := range resources {
|
||||
if resource.From != "local" {
|
||||
continue
|
||||
}
|
||||
resourceApp, err := appInstallRepo.GetFirst(commonRepo.WithByID(resource.LinkId))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resource.Key == "mysql" || resource.Key == "mariadb" {
|
||||
mysqlInfo, err := appInstallRepo.LoadBaseInfo(resource.Key, resourceApp.Name)
|
||||
var database model.Database
|
||||
switch resource.From {
|
||||
case constant.AppResourceRemote:
|
||||
database, err = databaseRepo.Get(commonRepo.WithByID(resource.LinkId))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case constant.AppResourceLocal:
|
||||
resourceApp, err := appInstallRepo.GetFirst(commonRepo.WithByID(resource.LinkId))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
database, err = databaseRepo.Get(databaseRepo.WithAppInstallID(resourceApp.ID), commonRepo.WithByType(resource.Key), databaseRepo.WithByFrom(constant.AppResourceLocal), commonRepo.WithByName(resourceApp.Name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if database.Type == "mysql" || database.Type == "mariadb" {
|
||||
db, err := mysqlRepo.Get(commonRepo.WithByID(resource.ResourceId))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newDB, envMap, err := reCreateDB(db.ID, resourceApp, oldInstall.Env)
|
||||
newDB, envMap, err := reCreateDB(db.ID, database, oldInstall.Env)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
oldHost := fmt.Sprintf("\"PANEL_DB_HOST\":\"%v\"", envMap["PANEL_DB_HOST"].(string))
|
||||
newHost := fmt.Sprintf("\"PANEL_DB_HOST\":\"%v\"", mysqlInfo.ServiceName)
|
||||
newHost := fmt.Sprintf("\"PANEL_DB_HOST\":\"%v\"", database.Address)
|
||||
oldInstall.Env = strings.ReplaceAll(oldInstall.Env, oldHost, newHost)
|
||||
envMap["PANEL_DB_HOST"] = mysqlInfo.ServiceName
|
||||
envMap["PANEL_DB_HOST"] = database.Address
|
||||
newEnvFile, err = coverEnvJsonToStr(oldInstall.Env)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -252,10 +257,10 @@ func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback
|
||||
return nil
|
||||
}
|
||||
|
||||
func reCreateDB(dbID uint, app model.AppInstall, oldEnv string) (*model.DatabaseMysql, map[string]interface{}, error) {
|
||||
func reCreateDB(dbID uint, database model.Database, oldEnv string) (*model.DatabaseMysql, map[string]interface{}, error) {
|
||||
mysqlService := NewIMysqlService()
|
||||
ctx := context.Background()
|
||||
_ = mysqlService.Delete(ctx, dto.MysqlDBDelete{ID: dbID, Database: app.Name, Type: app.App.Key, DeleteBackup: false, ForceDelete: true})
|
||||
_ = mysqlService.Delete(ctx, dto.MysqlDBDelete{ID: dbID, Database: database.Name, Type: database.Type, DeleteBackup: false, ForceDelete: true})
|
||||
|
||||
envMap := make(map[string]interface{})
|
||||
if err := json.Unmarshal([]byte(oldEnv), &envMap); err != nil {
|
||||
@@ -266,8 +271,8 @@ func reCreateDB(dbID uint, app model.AppInstall, oldEnv string) (*model.Database
|
||||
oldPassword, _ := envMap["PANEL_DB_USER_PASSWORD"].(string)
|
||||
createDB, err := mysqlService.Create(context.Background(), dto.MysqlDBCreate{
|
||||
Name: oldName,
|
||||
From: "local",
|
||||
Database: app.Name,
|
||||
From: database.From,
|
||||
Database: database.Name,
|
||||
Format: "utf8mb4",
|
||||
Username: oldUser,
|
||||
Password: oldPassword,
|
||||
@@ -276,6 +281,5 @@ func reCreateDB(dbID uint, app model.AppInstall, oldEnv string) (*model.Database
|
||||
if err != nil {
|
||||
return nil, envMap, err
|
||||
}
|
||||
|
||||
return createDB, envMap, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func handleRuntimeBackup(runtime *model.Runtime, backupDir, fileName string) error {
|
||||
fileOp := files.NewFileOp()
|
||||
tmpDir := fmt.Sprintf("%s/%s", backupDir, strings.ReplaceAll(fileName, ".tar.gz", ""))
|
||||
if !fileOp.Stat(tmpDir) {
|
||||
if err := os.MkdirAll(tmpDir, os.ModePerm); err != nil {
|
||||
return fmt.Errorf("mkdir %s failed, err: %v", backupDir, err)
|
||||
}
|
||||
}
|
||||
defer func() {
|
||||
_ = os.RemoveAll(tmpDir)
|
||||
}()
|
||||
|
||||
remarkInfo, _ := json.Marshal(runtime)
|
||||
remarkInfoPath := fmt.Sprintf("%s/runtime.json", tmpDir)
|
||||
if err := fileOp.SaveFile(remarkInfoPath, string(remarkInfo), fs.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
appPath := runtime.GetPath()
|
||||
if err := handleTar(appPath, tmpDir, "runtime.tar.gz", ""); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := handleTar(tmpDir, backupDir, fileName, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleRuntimeRecover(runtime *model.Runtime, recoverFile string, isRollback bool) error {
|
||||
isOk := false
|
||||
fileOp := files.NewFileOp()
|
||||
if err := handleUnTar(recoverFile, path.Dir(recoverFile)); err != nil {
|
||||
return err
|
||||
}
|
||||
tmpPath := strings.ReplaceAll(recoverFile, ".tar.gz", "")
|
||||
defer func() {
|
||||
go startRuntime(runtime)
|
||||
_ = os.RemoveAll(strings.ReplaceAll(recoverFile, ".tar.gz", ""))
|
||||
}()
|
||||
|
||||
if !fileOp.Stat(tmpPath+"/runtime.json") || !fileOp.Stat(tmpPath+"/runtime.tar.gz") {
|
||||
return errors.New("the wrong recovery package does not have runtime.json or runtime.tar.gz files")
|
||||
}
|
||||
var oldRuntime model.Runtime
|
||||
runtimeJson, err := os.ReadFile(tmpPath + "/runtime.json")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := json.Unmarshal(runtimeJson, &oldRuntime); err != nil {
|
||||
return fmt.Errorf("unmarshal runtime.json failed, err: %v", err)
|
||||
}
|
||||
if oldRuntime.Type != runtime.Type || oldRuntime.Name != runtime.Name {
|
||||
return errors.New("the current backup file does not match the application")
|
||||
}
|
||||
|
||||
if !isRollback {
|
||||
rollbackFile := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("runtime/%s_%s.tar.gz", runtime.Name, time.Now().Format("20060102150405")))
|
||||
if err := handleRuntimeBackup(runtime, path.Dir(rollbackFile), path.Base(rollbackFile)); err != nil {
|
||||
return fmt.Errorf("backup runtime %s for rollback before recover failed, err: %v", runtime.Name, err)
|
||||
}
|
||||
defer func() {
|
||||
if !isOk {
|
||||
global.LOG.Info("recover failed, start to rollback now")
|
||||
if err := handleRuntimeRecover(runtime, rollbackFile, true); err != nil {
|
||||
global.LOG.Errorf("rollback runtime %s from %s failed, err: %v", runtime.Name, rollbackFile, err)
|
||||
return
|
||||
}
|
||||
global.LOG.Infof("rollback runtime %s from %s successful", runtime.Name, rollbackFile)
|
||||
_ = os.RemoveAll(rollbackFile)
|
||||
} else {
|
||||
_ = os.RemoveAll(rollbackFile)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
newEnvFile, err := coverEnvJsonToStr(runtime.Env)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
runtimeDir := runtime.GetPath()
|
||||
backPath := fmt.Sprintf("%s_bak", runtimeDir)
|
||||
_ = fileOp.Rename(runtimeDir, backPath)
|
||||
_ = fileOp.CreateDir(runtimeDir, 0755)
|
||||
|
||||
if err := handleUnTar(tmpPath+"/runtime.tar.gz", fmt.Sprintf("%s/%s", constant.RuntimeDir, runtime.Type)); err != nil {
|
||||
global.LOG.Errorf("handle recover from runtime.tar.gz failed, err: %v", err)
|
||||
_ = fileOp.DeleteDir(runtimeDir)
|
||||
_ = fileOp.Rename(backPath, runtimeDir)
|
||||
return err
|
||||
}
|
||||
_ = fileOp.DeleteDir(backPath)
|
||||
|
||||
if len(newEnvFile) != 0 {
|
||||
envPath := fmt.Sprintf("%s/%s/%s/.env", constant.RuntimeDir, runtime.Type, runtime.Name)
|
||||
file, err := os.OpenFile(envPath, os.O_WRONLY|os.O_TRUNC, 0640)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
_, _ = file.WriteString(newEnvFile)
|
||||
}
|
||||
|
||||
oldRuntime.ID = runtime.ID
|
||||
oldRuntime.Status = constant.RuntimeStarting
|
||||
if err := runtimeRepo.Save(&oldRuntime); err != nil {
|
||||
global.LOG.Errorf("save db app install failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
isOk = true
|
||||
return nil
|
||||
}
|
||||
@@ -132,7 +132,8 @@ func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback
|
||||
return err
|
||||
}
|
||||
|
||||
if website.Type == constant.Deployment {
|
||||
switch website.Type {
|
||||
case constant.Deployment:
|
||||
app, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -145,7 +146,19 @@ func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback
|
||||
global.LOG.Errorf("docker-compose restart failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
case constant.Runtime:
|
||||
runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(website.RuntimeID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if runtime.Type == constant.RuntimeNode {
|
||||
if err := handleRuntimeRecover(runtime, fmt.Sprintf("%s/%s.runtime.tar.gz", tmpPath, website.Alias), true); err != nil {
|
||||
return err
|
||||
}
|
||||
global.LOG.Info("put runtime.tar.gz into tmp dir successful")
|
||||
}
|
||||
}
|
||||
|
||||
siteDir := fmt.Sprintf("%s/openresty/%s/www/sites", constant.AppInstallDir, nginxInfo.Name)
|
||||
if err := handleUnTar(fmt.Sprintf("%s/%s.web.tar.gz", tmpPath, website.Alias), siteDir); err != nil {
|
||||
global.LOG.Errorf("handle recover from web.tar.gz failed, err: %v", err)
|
||||
@@ -194,7 +207,8 @@ func handleWebsiteBackup(website *model.Website, backupDir, fileName string) err
|
||||
}
|
||||
global.LOG.Info("put openresty conf into tmp dir successful")
|
||||
|
||||
if website.Type == constant.Deployment {
|
||||
switch website.Type {
|
||||
case constant.Deployment:
|
||||
app, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -203,7 +217,19 @@ func handleWebsiteBackup(website *model.Website, backupDir, fileName string) err
|
||||
return err
|
||||
}
|
||||
global.LOG.Info("put app.tar.gz into tmp dir successful")
|
||||
case constant.Runtime:
|
||||
runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(website.RuntimeID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if runtime.Type == constant.RuntimeNode {
|
||||
if err := handleRuntimeBackup(runtime, tmpDir, fmt.Sprintf("%s.runtime.tar.gz", website.Alias)); err != nil {
|
||||
return err
|
||||
}
|
||||
global.LOG.Info("put runtime.tar.gz into tmp dir successful")
|
||||
}
|
||||
}
|
||||
|
||||
websiteDir := fmt.Sprintf("%s/openresty/%s/www/sites/%s", constant.AppInstallDir, nginxInfo.Name, website.Alias)
|
||||
if err := handleTar(websiteDir, tmpDir, fmt.Sprintf("%s.web.tar.gz", website.Alias), ""); err != nil {
|
||||
return err
|
||||
|
||||
@@ -51,7 +51,7 @@ type IContainerService interface {
|
||||
ContainerUpgrade(req dto.ContainerUpgrade) error
|
||||
ContainerInfo(req dto.OperationWithName) (*dto.ContainerOperate, error)
|
||||
ContainerListStats() ([]dto.ContainerListStats, error)
|
||||
LoadResouceLimit() (*dto.ResourceLimit, error)
|
||||
LoadResourceLimit() (*dto.ResourceLimit, error)
|
||||
ContainerLogClean(req dto.OperationWithName) error
|
||||
ContainerOperation(req dto.ContainerOperation) error
|
||||
ContainerLogs(wsConn *websocket.Conn, container, since, tail string, follow bool) error
|
||||
@@ -66,6 +66,7 @@ type IContainerService interface {
|
||||
Prune(req dto.ContainerPrune) (dto.ContainerPruneReport, error)
|
||||
|
||||
LoadContainerLogs(req dto.OperationWithNameAndType) string
|
||||
ComposeLogs(wsConn *websocket.Conn, composePath, since, tail string, follow bool) error
|
||||
}
|
||||
|
||||
func NewIContainerService() IContainerService {
|
||||
@@ -208,8 +209,7 @@ func (u *ContainerService) ContainerListStats() ([]dto.ContainerListStats, error
|
||||
wg.Add(len(list))
|
||||
for i := 0; i < len(list); i++ {
|
||||
go func(item types.Container) {
|
||||
cpu, mem := loadCpuAndMem(client, item.ID)
|
||||
datas = append(datas, dto.ContainerListStats{CPUPercent: cpu, MemoryPercent: mem, ContainerID: item.ID})
|
||||
datas = append(datas, loadCpuAndMem(client, item.ID))
|
||||
wg.Done()
|
||||
}(list[i])
|
||||
}
|
||||
@@ -226,6 +226,8 @@ func (u *ContainerService) Inspect(req dto.InspectReq) (string, error) {
|
||||
switch req.Type {
|
||||
case "container":
|
||||
inspectInfo, err = client.ContainerInspect(context.Background(), req.ID)
|
||||
case "image":
|
||||
inspectInfo, _, err = client.ImageInspectWithRaw(context.Background(), req.ID)
|
||||
case "network":
|
||||
inspectInfo, err = client.NetworkInspect(context.TODO(), req.ID, types.NetworkInspectOptions{})
|
||||
case "volume":
|
||||
@@ -286,7 +288,7 @@ func (u *ContainerService) Prune(req dto.ContainerPrune) (dto.ContainerPruneRepo
|
||||
return report, nil
|
||||
}
|
||||
|
||||
func (u *ContainerService) LoadResouceLimit() (*dto.ResourceLimit, error) {
|
||||
func (u *ContainerService) LoadResourceLimit() (*dto.ResourceLimit, error) {
|
||||
cpuCounts, err := cpu.Counts(true)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("load cpu limit failed, err: %v", err)
|
||||
@@ -314,15 +316,11 @@ func (u *ContainerService) ContainerCreate(req dto.ContainerOperate) error {
|
||||
return buserr.New(constant.ErrContainerName)
|
||||
}
|
||||
|
||||
var config container.Config
|
||||
var hostConf container.HostConfig
|
||||
var networkConf network.NetworkingConfig
|
||||
if err := loadConfigInfo(req, &config, &hostConf, &networkConf); err != nil {
|
||||
config, hostConf, networkConf, err := loadConfigInfo(true, req, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
global.LOG.Infof("new container info %s has been made, now start to create", req.Name)
|
||||
|
||||
if !checkImageExist(client, req.Image) || req.ForcePull {
|
||||
if err := pullImages(ctx, client, req.Image); err != nil {
|
||||
if !req.ForcePull {
|
||||
@@ -331,7 +329,7 @@ func (u *ContainerService) ContainerCreate(req dto.ContainerOperate) error {
|
||||
global.LOG.Errorf("force pull image %s failed, err: %v", req.Image, err)
|
||||
}
|
||||
}
|
||||
container, err := client.ContainerCreate(ctx, &config, &hostConf, &networkConf, &v1.Platform{}, req.Name)
|
||||
container, err := client.ContainerCreate(ctx, config, hostConf, networkConf, &v1.Platform{}, req.Name)
|
||||
if err != nil {
|
||||
_ = client.ContainerRemove(ctx, req.Name, types.ContainerRemoveOptions{RemoveVolumes: true, Force: true})
|
||||
return err
|
||||
@@ -366,6 +364,8 @@ func (u *ContainerService) ContainerInfo(req dto.OperationWithName) (*dto.Contai
|
||||
}
|
||||
}
|
||||
data.Cmd = oldContainer.Config.Cmd
|
||||
data.OpenStdin = oldContainer.Config.OpenStdin
|
||||
data.Tty = oldContainer.Config.Tty
|
||||
data.Entrypoint = oldContainer.Config.Entrypoint
|
||||
data.Env = oldContainer.Config.Env
|
||||
data.CPUShares = oldContainer.HostConfig.CPUShares
|
||||
@@ -427,19 +427,17 @@ func (u *ContainerService) ContainerUpdate(req dto.ContainerOperate) error {
|
||||
return err
|
||||
}
|
||||
|
||||
config := oldContainer.Config
|
||||
hostConf := oldContainer.HostConfig
|
||||
var networkConf network.NetworkingConfig
|
||||
if err := loadConfigInfo(req, config, hostConf, &networkConf); err != nil {
|
||||
config, hostConf, networkConf, err := loadConfigInfo(false, req, &oldContainer)
|
||||
if err != nil {
|
||||
reCreateAfterUpdate(req.Name, client, oldContainer.Config, oldContainer.HostConfig, oldContainer.NetworkSettings)
|
||||
return err
|
||||
}
|
||||
|
||||
global.LOG.Infof("new container info %s has been update, now start to recreate", req.Name)
|
||||
container, err := client.ContainerCreate(ctx, config, hostConf, &networkConf, &v1.Platform{}, req.Name)
|
||||
container, err := client.ContainerCreate(ctx, config, hostConf, networkConf, &v1.Platform{}, req.Name)
|
||||
if err != nil {
|
||||
reCreateAfterUpdate(req.Name, client, oldContainer.Config, oldContainer.HostConfig, oldContainer.NetworkSettings)
|
||||
return fmt.Errorf("update contianer failed, err: %v", err)
|
||||
return fmt.Errorf("update container failed, err: %v", err)
|
||||
}
|
||||
global.LOG.Infof("update container %s successful! now check if the container is started.", req.Name)
|
||||
if err := client.ContainerStart(ctx, container.ID, types.ContainerStartOptions{}); err != nil {
|
||||
@@ -485,7 +483,7 @@ func (u *ContainerService) ContainerUpgrade(req dto.ContainerUpgrade) error {
|
||||
container, err := client.ContainerCreate(ctx, config, hostConf, &networkConf, &v1.Platform{}, req.Name)
|
||||
if err != nil {
|
||||
reCreateAfterUpdate(req.Name, client, oldContainer.Config, oldContainer.HostConfig, oldContainer.NetworkSettings)
|
||||
return fmt.Errorf("upgrade contianer failed, err: %v", err)
|
||||
return fmt.Errorf("upgrade container failed, err: %v", err)
|
||||
}
|
||||
global.LOG.Infof("upgrade container %s successful! now check if the container is started.", req.Name)
|
||||
if err := client.ContainerStart(ctx, container.ID, types.ContainerStartOptions{}); err != nil {
|
||||
@@ -681,14 +679,14 @@ func (u *ContainerService) LoadContainerLogs(req dto.OperationWithNameAndType) s
|
||||
}
|
||||
|
||||
func stringsToMap(list []string) map[string]string {
|
||||
var lableMap = make(map[string]string)
|
||||
var labelMap = make(map[string]string)
|
||||
for _, label := range list {
|
||||
if strings.Contains(label, "=") {
|
||||
sps := strings.SplitN(label, "=", 2)
|
||||
lableMap[sps[0]] = sps[1]
|
||||
labelMap[sps[0]] = sps[1]
|
||||
}
|
||||
}
|
||||
return lableMap
|
||||
return labelMap
|
||||
}
|
||||
|
||||
func calculateCPUPercentUnix(stats *types.StatsJSON) float64 {
|
||||
@@ -764,26 +762,36 @@ func pullImages(ctx context.Context, client *client.Client, image string) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadCpuAndMem(client *client.Client, container string) (float64, float64) {
|
||||
func loadCpuAndMem(client *client.Client, container string) dto.ContainerListStats {
|
||||
data := dto.ContainerListStats{
|
||||
ContainerID: container,
|
||||
}
|
||||
res, err := client.ContainerStats(context.Background(), container, false)
|
||||
if err != nil {
|
||||
return 0, 0
|
||||
return data
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
res.Body.Close()
|
||||
return 0, 0
|
||||
return data
|
||||
}
|
||||
res.Body.Close()
|
||||
var stats *types.StatsJSON
|
||||
if err := json.Unmarshal(body, &stats); err != nil {
|
||||
return 0, 0
|
||||
return data
|
||||
}
|
||||
|
||||
CPUPercent := calculateCPUPercentUnix(stats)
|
||||
MemPercent := calculateMemPercentUnix(stats.MemoryStats)
|
||||
return CPUPercent, MemPercent
|
||||
data.CPUTotalUsage = stats.CPUStats.CPUUsage.TotalUsage - stats.PreCPUStats.CPUUsage.TotalUsage
|
||||
data.SystemUsage = stats.CPUStats.SystemUsage - stats.PreCPUStats.SystemUsage
|
||||
data.CPUPercent = calculateCPUPercentUnix(stats)
|
||||
data.PercpuUsage = len(stats.CPUStats.CPUUsage.PercpuUsage)
|
||||
|
||||
data.MemoryCache = stats.MemoryStats.Stats["cache"]
|
||||
data.MemoryUsage = stats.MemoryStats.Usage
|
||||
data.MemoryLimit = stats.MemoryStats.Limit
|
||||
data.MemoryPercent = calculateMemPercentUnix(stats.MemoryStats)
|
||||
return data
|
||||
}
|
||||
|
||||
func checkPortStats(ports []dto.PortHelper) (nat.PortMap, error) {
|
||||
@@ -832,26 +840,36 @@ func checkPortStats(ports []dto.PortHelper) (nat.PortMap, error) {
|
||||
return portMap, nil
|
||||
}
|
||||
|
||||
func loadConfigInfo(req dto.ContainerOperate, config *container.Config, hostConf *container.HostConfig, networkConf *network.NetworkingConfig) error {
|
||||
func loadConfigInfo(isCreate bool, req dto.ContainerOperate, oldContainer *types.ContainerJSON) (*container.Config, *container.HostConfig, *network.NetworkingConfig, error) {
|
||||
var config container.Config
|
||||
var hostConf container.HostConfig
|
||||
if !isCreate {
|
||||
config = *oldContainer.Config
|
||||
hostConf = *oldContainer.HostConfig
|
||||
}
|
||||
var networkConf network.NetworkingConfig
|
||||
|
||||
portMap, err := checkPortStats(req.ExposedPorts)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
exposeds := make(nat.PortSet)
|
||||
exposed := make(nat.PortSet)
|
||||
for port := range portMap {
|
||||
exposeds[port] = struct{}{}
|
||||
exposed[port] = struct{}{}
|
||||
}
|
||||
config.Image = req.Image
|
||||
config.Cmd = req.Cmd
|
||||
config.Entrypoint = req.Entrypoint
|
||||
config.Env = req.Env
|
||||
config.Labels = stringsToMap(req.Labels)
|
||||
config.ExposedPorts = exposeds
|
||||
config.ExposedPorts = exposed
|
||||
config.OpenStdin = req.OpenStdin
|
||||
config.Tty = req.Tty
|
||||
|
||||
if len(req.Network) != 0 {
|
||||
networkConf.EndpointsConfig = map[string]*network.EndpointSettings{req.Network: {}}
|
||||
} else {
|
||||
networkConf = &network.NetworkingConfig{}
|
||||
networkConf = network.NetworkingConfig{}
|
||||
}
|
||||
|
||||
hostConf.AutoRemove = req.AutoRemove
|
||||
@@ -870,7 +888,7 @@ func loadConfigInfo(req dto.ContainerOperate, config *container.Config, hostConf
|
||||
config.Volumes[volume.ContainerDir] = struct{}{}
|
||||
hostConf.Binds = append(hostConf.Binds, fmt.Sprintf("%s:%s:%s", volume.SourceDir, volume.ContainerDir, volume.Mode))
|
||||
}
|
||||
return nil
|
||||
return &config, &hostConf, &networkConf, nil
|
||||
}
|
||||
|
||||
func reCreateAfterUpdate(name string, client *client.Client, config *container.Config, hostConf *container.HostConfig, networkConf *types.NetworkSettings) {
|
||||
@@ -892,6 +910,7 @@ func reCreateAfterUpdate(name string, client *client.Client, config *container.C
|
||||
if err := client.ContainerStart(ctx, oldContainer.ID, types.ContainerStartOptions{}); err != nil {
|
||||
global.LOG.Errorf("restart after container update failed, err: %v", err)
|
||||
}
|
||||
global.LOG.Errorf("recreate after container update successful")
|
||||
}
|
||||
|
||||
func loadVolumeBinds(binds []string) []dto.VolumeHelper {
|
||||
@@ -939,9 +958,13 @@ func simplifyPort(ports []types.Port) []string {
|
||||
return datas
|
||||
}
|
||||
if len(ports) == 1 {
|
||||
itemPortStr := fmt.Sprintf("%s:%v/%s", ports[0].IP, ports[0].PrivatePort, ports[0].Type)
|
||||
ip := ""
|
||||
if len(ports[0].IP) != 0 {
|
||||
ip = ports[0].IP + ":"
|
||||
}
|
||||
itemPortStr := fmt.Sprintf("%s%v/%s", ip, ports[0].PrivatePort, ports[0].Type)
|
||||
if ports[0].PublicPort != 0 {
|
||||
itemPortStr = fmt.Sprintf("%s:%v->%v/%s", ports[0].IP, ports[0].PublicPort, ports[0].PrivatePort, ports[0].Type)
|
||||
itemPortStr = fmt.Sprintf("%s%v->%v/%s", ip, ports[0].PublicPort, ports[0].PrivatePort, ports[0].Type)
|
||||
}
|
||||
datas = append(datas, itemPortStr)
|
||||
return datas
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gorilla/websocket"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -261,3 +262,45 @@ func (u *ContainerService) loadPath(req *dto.ComposeCreate) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *ContainerService) ComposeLogs(wsConn *websocket.Conn, composePath, since, tail string, follow bool) error {
|
||||
if cmd.CheckIllegal(composePath, since, tail) {
|
||||
return buserr.New(constant.ErrCmdIllegal)
|
||||
}
|
||||
command := fmt.Sprintf("docker-compose -f %s logs", composePath)
|
||||
if tail != "0" {
|
||||
command += " --tail " + tail
|
||||
}
|
||||
if since != "all" {
|
||||
command += " --since " + since
|
||||
}
|
||||
if follow {
|
||||
command += " -f"
|
||||
}
|
||||
command += " 2>&1"
|
||||
cmd := exec.Command("bash", "-c", command)
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buffer := make([]byte, 1024)
|
||||
for {
|
||||
n, err := stdout.Read(buffer)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
global.LOG.Errorf("read bytes from compose log failed, err: %v", err)
|
||||
continue
|
||||
}
|
||||
if err = wsConn.WriteMessage(websocket.TextMessage, buffer[:n]); err != nil {
|
||||
global.LOG.Errorf("send message with compose log to ws failed, err: %v", err)
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ func (u *DashboardService) LoadBaseInfo(ioOption string, netOption string) (*dto
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
baseInfo.AppInstalldNumber = len(appInstall)
|
||||
baseInfo.AppInstalledNumber = len(appInstall)
|
||||
dbs, err := mysqlRepo.List()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -56,11 +56,11 @@ func (u *DashboardService) LoadBaseInfo(ioOption string, netOption string) (*dto
|
||||
return nil, err
|
||||
}
|
||||
baseInfo.WebsiteNumber = len(website)
|
||||
cornjobs, err := cronjobRepo.List()
|
||||
cronjobs, err := cronjobRepo.List()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
baseInfo.CronjobNumber = len(cornjobs)
|
||||
baseInfo.CronjobNumber = len(cronjobs)
|
||||
|
||||
cpuInfo, err := cpu.Info()
|
||||
if err == nil {
|
||||
|
||||
@@ -3,10 +3,13 @@ package service
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/encrypt"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/mysql"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/mysql/client"
|
||||
@@ -22,7 +25,8 @@ type IDatabaseService interface {
|
||||
CheckDatabase(req dto.DatabaseCreate) bool
|
||||
Create(req dto.DatabaseCreate) error
|
||||
Update(req dto.DatabaseUpdate) error
|
||||
Delete(id uint) error
|
||||
DeleteCheck(id uint) ([]string, error)
|
||||
Delete(req dto.DatabaseDelete) error
|
||||
List(dbType string) ([]dto.DatabaseOption, error)
|
||||
}
|
||||
|
||||
@@ -114,16 +118,47 @@ func (u *DatabaseService) Create(req dto.DatabaseCreate) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *DatabaseService) Delete(id uint) error {
|
||||
db, _ := databaseRepo.Get(commonRepo.WithByID(id))
|
||||
func (u *DatabaseService) DeleteCheck(id uint) ([]string, error) {
|
||||
var appInUsed []string
|
||||
apps, _ := appInstallResourceRepo.GetBy(databaseRepo.WithByFrom("remote"), appInstallResourceRepo.WithLinkId(id))
|
||||
for _, app := range apps {
|
||||
appInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(app.AppInstallId))
|
||||
if appInstall.ID != 0 {
|
||||
appInUsed = append(appInUsed, appInstall.Name)
|
||||
}
|
||||
}
|
||||
|
||||
return appInUsed, nil
|
||||
}
|
||||
|
||||
func (u *DatabaseService) Delete(req dto.DatabaseDelete) error {
|
||||
db, _ := databaseRepo.Get(commonRepo.WithByID(req.ID))
|
||||
if db.ID == 0 {
|
||||
return constant.ErrRecordNotFound
|
||||
}
|
||||
if err := databaseRepo.Delete(context.Background(), commonRepo.WithByID(id)); err != nil {
|
||||
|
||||
if req.DeleteBackup {
|
||||
uploadDir := path.Join(global.CONF.System.BaseDir, fmt.Sprintf("1panel/uploads/database/%s/%s", db.Type, db.Name))
|
||||
if _, err := os.Stat(uploadDir); err == nil {
|
||||
_ = os.RemoveAll(uploadDir)
|
||||
}
|
||||
localDir, err := loadLocalDir()
|
||||
if err != nil && !req.ForceDelete {
|
||||
return err
|
||||
}
|
||||
backupDir := path.Join(localDir, fmt.Sprintf("database/%s/%s", db.Type, db.Name))
|
||||
if _, err := os.Stat(backupDir); err == nil {
|
||||
_ = os.RemoveAll(backupDir)
|
||||
}
|
||||
_ = backupRepo.DeleteRecord(context.Background(), commonRepo.WithByType(db.Type), commonRepo.WithByName(db.Name))
|
||||
global.LOG.Infof("delete database %s-%s backups successful", db.Type, db.Name)
|
||||
}
|
||||
|
||||
if err := databaseRepo.Delete(context.Background(), commonRepo.WithByID(req.ID)); err != nil && !req.ForceDelete {
|
||||
return err
|
||||
}
|
||||
if db.From != "local" {
|
||||
if err := mysqlRepo.Delete(context.Background(), mysqlRepo.WithByMysqlName(db.Name)); err != nil {
|
||||
if err := mysqlRepo.Delete(context.Background(), mysqlRepo.WithByMysqlName(db.Name)); err != nil && !req.ForceDelete {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,7 +452,7 @@ func (u *MysqlService) LoadRemoteAccess(req dto.OperationWithNameAndType) (bool,
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
hosts, err := excuteSqlForRows(app.ContainerName, app.Password, "select host from mysql.user where user='root';")
|
||||
hosts, err := executeSqlForRows(app.ContainerName, app.Password, "select host from mysql.user where user='root';")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -470,7 +470,7 @@ func (u *MysqlService) LoadVariables(req dto.OperationWithNameAndType) (*dto.Mys
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
variableMap, err := excuteSqlForMaps(app.ContainerName, app.Password, "show global variables;")
|
||||
variableMap, err := executeSqlForMaps(app.ContainerName, app.Password, "show global variables;")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -489,7 +489,7 @@ func (u *MysqlService) LoadStatus(req dto.OperationWithNameAndType) (*dto.MysqlS
|
||||
return nil, err
|
||||
}
|
||||
|
||||
statusMap, err := excuteSqlForMaps(app.ContainerName, app.Password, "show global status;")
|
||||
statusMap, err := executeSqlForMaps(app.ContainerName, app.Password, "show global status;")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -513,7 +513,7 @@ func (u *MysqlService) LoadStatus(req dto.OperationWithNameAndType) (*dto.MysqlS
|
||||
|
||||
info.File = "OFF"
|
||||
info.Position = "OFF"
|
||||
rows, err := excuteSqlForRows(app.ContainerName, app.Password, "show master status;")
|
||||
rows, err := executeSqlForRows(app.ContainerName, app.Password, "show master status;")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -552,7 +552,7 @@ func (u *MysqlService) LoadDatabaseFile(req dto.OperationWithNameAndType) (strin
|
||||
return string(content), nil
|
||||
}
|
||||
|
||||
func excuteSqlForMaps(containerName, password, command string) (map[string]string, error) {
|
||||
func executeSqlForMaps(containerName, password, command string) (map[string]string, error) {
|
||||
cmd := exec.Command("docker", "exec", containerName, "mysql", "-uroot", "-p"+password, "-e", command)
|
||||
stdout, err := cmd.CombinedOutput()
|
||||
stdStr := strings.ReplaceAll(string(stdout), "mysql: [Warning] Using a password on the command line interface can be insecure.\n", "")
|
||||
@@ -571,7 +571,7 @@ func excuteSqlForMaps(containerName, password, command string) (map[string]strin
|
||||
return rowMap, nil
|
||||
}
|
||||
|
||||
func excuteSqlForRows(containerName, password, command string) ([]string, error) {
|
||||
func executeSqlForRows(containerName, password, command string) ([]string, error) {
|
||||
cmd := exec.Command("docker", "exec", containerName, "mysql", "-uroot", "-p"+password, "-e", command)
|
||||
stdout, err := cmd.CombinedOutput()
|
||||
stdStr := strings.ReplaceAll(string(stdout), "mysql: [Warning] Using a password on the command line interface can be insecure.\n", "")
|
||||
|
||||
+122
-87
@@ -46,9 +46,6 @@ func (u *FirewallService) LoadBaseInfo() (dto.FirewallBaseInfo, error) {
|
||||
baseInfo.Name = "-"
|
||||
client, err := firewall.NewFirewallClient()
|
||||
if err != nil {
|
||||
if err.Error() == "no such type" {
|
||||
return baseInfo, nil
|
||||
}
|
||||
return baseInfo, err
|
||||
}
|
||||
baseInfo.Name = client.Name()
|
||||
@@ -111,14 +108,19 @@ func (u *FirewallService) SearchWithPage(req dto.RuleSearch) (int64, interface{}
|
||||
}
|
||||
}
|
||||
|
||||
if req.Type == "port" {
|
||||
apps := u.loadPortByApp()
|
||||
for i := 0; i < len(datas); i++ {
|
||||
datas[i].UsedStatus = checkPortUsed(datas[i].Port, datas[i].Protocol, apps)
|
||||
}
|
||||
}
|
||||
var datasFilterStatus []fireClient.FireInfo
|
||||
if len(req.Status) != 0 {
|
||||
for _, data := range datas {
|
||||
portItem, _ := strconv.Atoi(data.Port)
|
||||
if req.Status == "free" && !common.ScanPortWithProto(portItem, data.Protocol) {
|
||||
if req.Status == "free" && len(data.UsedStatus) == 0 {
|
||||
datasFilterStatus = append(datasFilterStatus, data)
|
||||
}
|
||||
if req.Status == "used" && common.ScanPortWithProto(portItem, data.Protocol) {
|
||||
if req.Status == "used" && len(data.UsedStatus) != 0 {
|
||||
datasFilterStatus = append(datasFilterStatus, data)
|
||||
}
|
||||
}
|
||||
@@ -167,23 +169,6 @@ func (u *FirewallService) SearchWithPage(req dto.RuleSearch) (int64, interface{}
|
||||
}
|
||||
}
|
||||
|
||||
if req.Type == "port" {
|
||||
apps := u.loadPortByApp()
|
||||
for i := 0; i < len(backDatas); i++ {
|
||||
port, _ := strconv.Atoi(backDatas[i].Port)
|
||||
backDatas[i].IsUsed = common.ScanPort(port)
|
||||
if backDatas[i].Protocol == "udp" {
|
||||
backDatas[i].IsUsed = common.ScanUDPPort(port)
|
||||
continue
|
||||
}
|
||||
for _, app := range apps {
|
||||
if app.HttpPort == backDatas[i].Port || app.HttpsPort == backDatas[i].Port {
|
||||
backDatas[i].APPName = app.AppName
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
go u.cleanUnUsedData(client)
|
||||
|
||||
return int64(total), backDatas, nil
|
||||
@@ -227,7 +212,6 @@ func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate, reload bool)
|
||||
protos := strings.Split(req.Protocol, "/")
|
||||
itemAddress := strings.Split(strings.TrimSuffix(req.Address, ","), ",")
|
||||
|
||||
var wg sync.WaitGroup
|
||||
if client.Name() == "ufw" {
|
||||
if strings.Contains(req.Port, ",") || strings.Contains(req.Port, "-") {
|
||||
for _, proto := range protos {
|
||||
@@ -238,36 +222,35 @@ func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate, reload bool)
|
||||
req.Address = addr
|
||||
req.Port = strings.ReplaceAll(req.Port, "-", ":")
|
||||
req.Protocol = proto
|
||||
wg.Add(1)
|
||||
go func(req dto.PortRuleOperate) {
|
||||
defer wg.Done()
|
||||
if err := u.operatePort(client, req); err != nil {
|
||||
global.LOG.Errorf("%s port %s/%s failed (strategy: %s, address: %s), err: %v", req.Operation, req.Port, req.Protocol, req.Strategy, req.Address, err)
|
||||
}
|
||||
_ = u.addPortRecord(req)
|
||||
}(req)
|
||||
if err := u.operatePort(client, req); err != nil {
|
||||
global.LOG.Errorf("%s port %s/%s failed (strategy: %s, address: %s), err: %v", req.Operation, req.Port, req.Protocol, req.Strategy, req.Address, err)
|
||||
}
|
||||
req.Port = strings.ReplaceAll(req.Port, ":", "-")
|
||||
if err := u.addPortRecord(req); err != nil {
|
||||
global.LOG.Errorf("add record %s/%s failed (strategy: %s, address: %s), err: %v", req.Port, req.Protocol, req.Strategy, req.Address, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if req.Protocol == "tcp/udp" {
|
||||
req.Protocol = ""
|
||||
}
|
||||
for _, addr := range itemAddress {
|
||||
if len(addr) == 0 {
|
||||
addr = "Anywhere"
|
||||
}
|
||||
if req.Protocol == "tcp/udp" {
|
||||
req.Protocol = ""
|
||||
}
|
||||
req.Address = addr
|
||||
wg.Add(1)
|
||||
go func(req dto.PortRuleOperate) {
|
||||
defer wg.Done()
|
||||
if err := u.operatePort(client, req); err != nil {
|
||||
global.LOG.Errorf("%s port %s/%s failed (strategy: %s, address: %s), err: %v", req.Operation, req.Port, req.Protocol, req.Strategy, req.Address, err)
|
||||
}
|
||||
_ = u.addPortRecord(req)
|
||||
}(req)
|
||||
if err := u.operatePort(client, req); err != nil {
|
||||
global.LOG.Errorf("%s port %s/%s failed (strategy: %s, address: %s), err: %v", req.Operation, req.Port, req.Protocol, req.Strategy, req.Address, err)
|
||||
}
|
||||
if len(req.Protocol) == 0 {
|
||||
req.Protocol = "tcp/udp"
|
||||
}
|
||||
if err := u.addPortRecord(req); err != nil {
|
||||
global.LOG.Errorf("add record %s/%s failed (strategy: %s, address: %s), err: %v", req.Port, req.Protocol, req.Strategy, req.Address, err)
|
||||
}
|
||||
}
|
||||
wg.Wait()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -277,14 +260,10 @@ func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate, reload bool)
|
||||
for _, addr := range itemAddress {
|
||||
req.Protocol = proto
|
||||
req.Address = addr
|
||||
wg.Add(1)
|
||||
go func(req dto.PortRuleOperate) {
|
||||
defer wg.Done()
|
||||
if err := u.operatePort(client, req); err != nil {
|
||||
global.LOG.Errorf("%s port %s/%s failed (strategy: %s, address: %s), err: %v", req.Operation, req.Port, req.Protocol, req.Strategy, req.Address, err)
|
||||
}
|
||||
_ = u.addPortRecord(req)
|
||||
}(req)
|
||||
if err := u.operatePort(client, req); err != nil {
|
||||
global.LOG.Errorf("%s port %s/%s failed (strategy: %s, address: %s), err: %v", req.Operation, req.Port, req.Protocol, req.Strategy, req.Address, err)
|
||||
}
|
||||
_ = u.addPortRecord(req)
|
||||
}
|
||||
} else {
|
||||
ports := strings.Split(itemPorts, ",")
|
||||
@@ -296,20 +275,15 @@ func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate, reload bool)
|
||||
req.Address = addr
|
||||
req.Port = port
|
||||
req.Protocol = proto
|
||||
wg.Add(1)
|
||||
go func(req dto.PortRuleOperate) {
|
||||
defer wg.Done()
|
||||
if err := u.operatePort(client, req); err != nil {
|
||||
global.LOG.Errorf("%s port %s/%s failed (strategy: %s, address: %s), err: %v", req.Operation, req.Port, req.Protocol, req.Strategy, req.Address, err)
|
||||
}
|
||||
_ = u.addPortRecord(req)
|
||||
}(req)
|
||||
if err := u.operatePort(client, req); err != nil {
|
||||
global.LOG.Errorf("%s port %s/%s failed (strategy: %s, address: %s), err: %v", req.Operation, req.Port, req.Protocol, req.Strategy, req.Address, err)
|
||||
}
|
||||
_ = u.addPortRecord(req)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
if reload {
|
||||
return client.Reload()
|
||||
}
|
||||
@@ -327,24 +301,18 @@ func (u *FirewallService) OperateAddressRule(req dto.AddrRuleOperate, reload boo
|
||||
return err
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
addressList := strings.Split(req.Address, ",")
|
||||
for _, addr := range addressList {
|
||||
if len(addr) == 0 {
|
||||
for i := 0; i < len(addressList); i++ {
|
||||
if len(addressList[i]) == 0 {
|
||||
continue
|
||||
}
|
||||
fireInfo.Address = addr
|
||||
wg.Add(1)
|
||||
go func(req dto.AddrRuleOperate) {
|
||||
defer wg.Done()
|
||||
if err := client.RichRules(fireInfo, req.Operation); err != nil {
|
||||
global.LOG.Errorf("%s address %s failed (strategy: %s), err: %v", req.Operation, req.Address, req.Strategy, err)
|
||||
}
|
||||
req.Address = fireInfo.Address
|
||||
_ = u.addAddressRecord(req)
|
||||
}(req)
|
||||
fireInfo.Address = addressList[i]
|
||||
if err := client.RichRules(fireInfo, req.Operation); err != nil {
|
||||
global.LOG.Errorf("%s address %s failed (strategy: %s), err: %v", req.Operation, addressList[i], req.Strategy, err)
|
||||
}
|
||||
req.Address = addressList[i]
|
||||
_ = u.addAddressRecord(req)
|
||||
}
|
||||
wg.Wait()
|
||||
if reload {
|
||||
return client.Reload()
|
||||
}
|
||||
@@ -392,25 +360,15 @@ func (u *FirewallService) BatchOperateRule(req dto.BatchRuleOperate) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var wgBatch sync.WaitGroup
|
||||
if req.Type == "port" {
|
||||
for _, rule := range req.Rules {
|
||||
wgBatch.Add(1)
|
||||
go func(item dto.PortRuleOperate) {
|
||||
defer wgBatch.Done()
|
||||
_ = u.OperatePortRule(item, false)
|
||||
}(rule)
|
||||
_ = u.OperatePortRule(rule, false)
|
||||
}
|
||||
wgBatch.Wait()
|
||||
return client.Reload()
|
||||
}
|
||||
for _, rule := range req.Rules {
|
||||
itemRule := dto.AddrRuleOperate{Operation: rule.Operation, Address: rule.Address, Strategy: rule.Strategy}
|
||||
wgBatch.Add(1)
|
||||
go func(item dto.AddrRuleOperate) {
|
||||
defer wgBatch.Done()
|
||||
_ = u.OperateAddressRule(item, false)
|
||||
}(itemRule)
|
||||
_ = u.OperateAddressRule(itemRule, false)
|
||||
}
|
||||
return client.Reload()
|
||||
}
|
||||
@@ -608,3 +566,80 @@ func (u *FirewallService) addAddressRecord(req dto.AddrRuleOperate) error {
|
||||
Description: req.Description,
|
||||
})
|
||||
}
|
||||
|
||||
func listIpRules(strategy string) ([]string, error) {
|
||||
client, err := firewall.NewFirewallClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addrs, err := client.ListAddress()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var rules []string
|
||||
for _, addr := range addrs {
|
||||
if addr.Strategy == strategy {
|
||||
rules = append(rules, addr.Address)
|
||||
}
|
||||
}
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func checkPortUsed(ports, proto string, apps []portOfApp) string {
|
||||
var portList []int
|
||||
if strings.Contains(ports, "-") || strings.Contains(ports, ",") {
|
||||
if strings.Contains(ports, "-") {
|
||||
port1, err := strconv.Atoi(strings.Split(ports, "-")[0])
|
||||
if err != nil {
|
||||
global.LOG.Errorf(" convert string %s to int failed, err: %v", strings.Split(ports, "-")[0], err)
|
||||
return ""
|
||||
}
|
||||
port2, err := strconv.Atoi(strings.Split(ports, "-")[1])
|
||||
if err != nil {
|
||||
global.LOG.Errorf(" convert string %s to int failed, err: %v", strings.Split(ports, "-")[1], err)
|
||||
return ""
|
||||
}
|
||||
for i := port1; i <= port2; i++ {
|
||||
portList = append(portList, i)
|
||||
}
|
||||
} else {
|
||||
portLists := strings.Split(ports, ",")
|
||||
for _, item := range portLists {
|
||||
portItem, _ := strconv.Atoi(item)
|
||||
portList = append(portList, portItem)
|
||||
}
|
||||
}
|
||||
|
||||
var usedPorts []string
|
||||
for _, port := range portList {
|
||||
portItem := fmt.Sprintf("%v", port)
|
||||
isUsedByApp := false
|
||||
for _, app := range apps {
|
||||
if app.HttpPort == portItem || app.HttpsPort == portItem {
|
||||
isUsedByApp = true
|
||||
usedPorts = append(usedPorts, fmt.Sprintf("%s (%s)", portItem, app.AppName))
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isUsedByApp && common.ScanPortWithProto(port, proto) {
|
||||
usedPorts = append(usedPorts, fmt.Sprintf("%v", port))
|
||||
}
|
||||
}
|
||||
return strings.Join(usedPorts, ",")
|
||||
}
|
||||
|
||||
for _, app := range apps {
|
||||
if app.HttpPort == ports || app.HttpsPort == ports {
|
||||
return fmt.Sprintf("(%s)", app.AppName)
|
||||
}
|
||||
}
|
||||
port, err := strconv.Atoi(ports)
|
||||
if err != nil {
|
||||
global.LOG.Errorf(" convert string %v to int failed, err: %v", port, err)
|
||||
return ""
|
||||
}
|
||||
if common.ScanPortWithProto(port, proto) {
|
||||
return "inUsed"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ func (u *ImageService) Page(req dto.SearchWithPage) (int64, interface{}, error)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
containers, _ := client.ContainerList(context.Background(), types.ContainerListOptions{All: true})
|
||||
if len(req.Info) != 0 {
|
||||
length, count := len(list), 0
|
||||
for count < length {
|
||||
@@ -77,6 +78,7 @@ func (u *ImageService) Page(req dto.SearchWithPage) (int64, interface{}, error)
|
||||
records = append(records, dto.ImageInfo{
|
||||
ID: image.ID,
|
||||
Tags: image.RepoTags,
|
||||
IsUsed: checkUsed(image.ID, containers),
|
||||
CreatedAt: time.Unix(image.Created, 0),
|
||||
Size: size,
|
||||
})
|
||||
@@ -415,3 +417,12 @@ func formatFileSize(fileSize int64) (size string) {
|
||||
return fmt.Sprintf("%.2fEB", float64(fileSize)/float64(1024*1024*1024*1024*1024))
|
||||
}
|
||||
}
|
||||
|
||||
func checkUsed(imageID string, containers []types.Container) bool {
|
||||
for _, container := range containers {
|
||||
if container.ImageID == imageID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
@@ -19,13 +24,14 @@ type LogService struct{}
|
||||
const logs = "https://resource.fit2cloud.com/installation-log.sh"
|
||||
|
||||
type ILogService interface {
|
||||
ListSystemLogFile() ([]string, error)
|
||||
CreateLoginLog(operation model.LoginLog) error
|
||||
PageLoginLog(search dto.SearchLgLogWithPage) (int64, interface{}, error)
|
||||
|
||||
CreateOperationLog(operation model.OperationLog) error
|
||||
PageOperationLog(search dto.SearchOpLogWithPage) (int64, interface{}, error)
|
||||
|
||||
LoadSystemLog() (string, error)
|
||||
LoadSystemLog(name string) (string, error)
|
||||
|
||||
CleanLogs(logtype string) error
|
||||
}
|
||||
@@ -38,6 +44,39 @@ func (u *LogService) CreateLoginLog(operation model.LoginLog) error {
|
||||
return logRepo.CreateLoginLog(&operation)
|
||||
}
|
||||
|
||||
func (u *LogService) ListSystemLogFile() ([]string, error) {
|
||||
logDir := path.Join(global.CONF.System.BaseDir, "1panel/log")
|
||||
var files []string
|
||||
if err := filepath.Walk(logDir, func(pathItem string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.IsDir() {
|
||||
if info.Name() == "1Panel.log" {
|
||||
files = append(files, time.Now().Format("2006-01-02"))
|
||||
return nil
|
||||
}
|
||||
itemFileName := strings.TrimPrefix(info.Name(), "1Panel-")
|
||||
itemFileName = strings.TrimSuffix(itemFileName, ".gz")
|
||||
itemFileName = strings.TrimSuffix(itemFileName, ".log")
|
||||
files = append(files, itemFileName)
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(files) < 2 {
|
||||
return files, nil
|
||||
}
|
||||
sort.Slice(files, func(i, j int) bool {
|
||||
return files[i] > files[j]
|
||||
})
|
||||
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func (u *LogService) PageLoginLog(req dto.SearchLgLogWithPage) (int64, interface{}, error) {
|
||||
total, ops, err := logRepo.PageLoginLog(
|
||||
req.Page,
|
||||
@@ -81,10 +120,21 @@ func (u *LogService) PageOperationLog(req dto.SearchOpLogWithPage) (int64, inter
|
||||
return total, dtoOps, err
|
||||
}
|
||||
|
||||
func (u *LogService) LoadSystemLog() (string, error) {
|
||||
filePath := path.Join(global.CONF.System.DataDir, "log/1Panel.log")
|
||||
func (u *LogService) LoadSystemLog(name string) (string, error) {
|
||||
if name == time.Now().Format("2006-01-02") {
|
||||
name = "1Panel.log"
|
||||
} else {
|
||||
name = "1Panel-" + name + ".log"
|
||||
}
|
||||
filePath := path.Join(global.CONF.System.DataDir, "log", name)
|
||||
if _, err := os.Stat(filePath); err != nil {
|
||||
return "", buserr.New("ErrHttpReqNotFound")
|
||||
fileGzPath := path.Join(global.CONF.System.DataDir, "log", name+".gz")
|
||||
if _, err := os.Stat(fileGzPath); err != nil {
|
||||
return "", buserr.New("ErrHttpReqNotFound")
|
||||
}
|
||||
if err := handleGunzip(fileGzPath); err != nil {
|
||||
return "", fmt.Errorf("handle ungzip file %s failed, err: %v", fileGzPath, err)
|
||||
}
|
||||
}
|
||||
content, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
|
||||
+128
-90
@@ -1,6 +1,7 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -15,21 +16,28 @@ import (
|
||||
"github.com/shirou/gopsutil/v3/net"
|
||||
)
|
||||
|
||||
type MonitorService struct{}
|
||||
type MonitorService struct {
|
||||
DiskIO chan ([]disk.IOCountersStat)
|
||||
NetIO chan ([]net.IOCountersStat)
|
||||
}
|
||||
|
||||
var monitorCancel context.CancelFunc
|
||||
|
||||
type IMonitorService interface {
|
||||
Run()
|
||||
|
||||
saveIODataToDB(ctx context.Context, interval float64)
|
||||
saveNetDataToDB(ctx context.Context, interval float64)
|
||||
}
|
||||
|
||||
func NewIMonitorService() IMonitorService {
|
||||
return &MonitorService{}
|
||||
return &MonitorService{
|
||||
DiskIO: make(chan []disk.IOCountersStat, 2),
|
||||
NetIO: make(chan []net.IOCountersStat, 2),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MonitorService) Run() {
|
||||
monitorStatus, _ := settingRepo.Get(settingRepo.WithByKey("MonitorStatus"))
|
||||
if monitorStatus.Value == "disable" {
|
||||
return
|
||||
}
|
||||
var itemModel model.MonitorBase
|
||||
totalPercent, _ := cpu.Percent(3*time.Second, false)
|
||||
if len(totalPercent) == 1 {
|
||||
@@ -50,8 +58,8 @@ func (m *MonitorService) Run() {
|
||||
global.LOG.Errorf("Insert basic monitoring data failed, err: %v", err)
|
||||
}
|
||||
|
||||
go loadDiskIO()
|
||||
go loadNetIO()
|
||||
m.loadDiskIO()
|
||||
m.loadNetIO()
|
||||
|
||||
MonitorStoreDays, err := settingRepo.Get(settingRepo.WithByKey("MonitorStoreDays"))
|
||||
if err != nil {
|
||||
@@ -64,115 +72,145 @@ func (m *MonitorService) Run() {
|
||||
_ = settingRepo.DelMonitorNet(timeForDelete)
|
||||
}
|
||||
|
||||
func loadDiskIO() {
|
||||
func (m *MonitorService) loadDiskIO() {
|
||||
ioStat, _ := disk.IOCounters()
|
||||
var diskIOList []disk.IOCountersStat
|
||||
for _, io := range ioStat {
|
||||
diskIOList = append(diskIOList, io)
|
||||
}
|
||||
m.DiskIO <- diskIOList
|
||||
}
|
||||
|
||||
time.Sleep(60 * time.Second)
|
||||
func (m *MonitorService) loadNetIO() {
|
||||
netStat, _ := net.IOCounters(true)
|
||||
netStatAll, _ := net.IOCounters(false)
|
||||
var netList []net.IOCountersStat
|
||||
netList = append(netList, netStat...)
|
||||
netList = append(netList, netStatAll...)
|
||||
m.NetIO <- netList
|
||||
}
|
||||
|
||||
ioStat2, _ := disk.IOCounters()
|
||||
var ioList []model.MonitorIO
|
||||
for _, io2 := range ioStat2 {
|
||||
for _, io1 := range ioStat {
|
||||
if io2.Name == io1.Name {
|
||||
var itemIO model.MonitorIO
|
||||
itemIO.Name = io1.Name
|
||||
if io2.ReadBytes != 0 && io1.ReadBytes != 0 && io2.ReadBytes > io1.ReadBytes {
|
||||
itemIO.Read = uint64(float64(io2.ReadBytes-io1.ReadBytes) / 60)
|
||||
}
|
||||
if io2.WriteBytes != 0 && io1.WriteBytes != 0 && io2.WriteBytes > io1.WriteBytes {
|
||||
itemIO.Write = uint64(float64(io2.WriteBytes-io1.WriteBytes) / 60)
|
||||
}
|
||||
func (m *MonitorService) saveIODataToDB(ctx context.Context, interval float64) {
|
||||
defer close(m.DiskIO)
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case ioStat := <-m.DiskIO:
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case ioStat2 := <-m.DiskIO:
|
||||
var ioList []model.MonitorIO
|
||||
for _, io2 := range ioStat2 {
|
||||
for _, io1 := range ioStat {
|
||||
if io2.Name == io1.Name {
|
||||
var itemIO model.MonitorIO
|
||||
itemIO.Name = io1.Name
|
||||
if io2.ReadBytes != 0 && io1.ReadBytes != 0 && io2.ReadBytes > io1.ReadBytes {
|
||||
itemIO.Read = uint64(float64(io2.ReadBytes-io1.ReadBytes) / interval / 60)
|
||||
}
|
||||
if io2.WriteBytes != 0 && io1.WriteBytes != 0 && io2.WriteBytes > io1.WriteBytes {
|
||||
itemIO.Write = uint64(float64(io2.WriteBytes-io1.WriteBytes) / interval / 60)
|
||||
}
|
||||
|
||||
if io2.ReadCount != 0 && io1.ReadCount != 0 && io2.ReadCount > io1.ReadCount {
|
||||
itemIO.Count = uint64(float64(io2.ReadCount-io1.ReadCount) / 60)
|
||||
}
|
||||
writeCount := uint64(0)
|
||||
if io2.WriteCount != 0 && io1.WriteCount != 0 && io2.WriteCount > io1.WriteCount {
|
||||
writeCount = uint64(float64(io2.WriteCount-io1.WriteCount) / 60)
|
||||
}
|
||||
if writeCount > itemIO.Count {
|
||||
itemIO.Count = writeCount
|
||||
}
|
||||
if io2.ReadCount != 0 && io1.ReadCount != 0 && io2.ReadCount > io1.ReadCount {
|
||||
itemIO.Count = uint64(float64(io2.ReadCount-io1.ReadCount) / interval / 60)
|
||||
}
|
||||
writeCount := uint64(0)
|
||||
if io2.WriteCount != 0 && io1.WriteCount != 0 && io2.WriteCount > io1.WriteCount {
|
||||
writeCount = uint64(float64(io2.WriteCount-io1.WriteCount) / interval * 60)
|
||||
}
|
||||
if writeCount > itemIO.Count {
|
||||
itemIO.Count = writeCount
|
||||
}
|
||||
|
||||
if io2.ReadTime != 0 && io1.ReadTime != 0 && io2.ReadTime > io1.ReadTime {
|
||||
itemIO.Time = uint64(float64(io2.ReadTime-io1.ReadTime) / 60)
|
||||
if io2.ReadTime != 0 && io1.ReadTime != 0 && io2.ReadTime > io1.ReadTime {
|
||||
itemIO.Time = uint64(float64(io2.ReadTime-io1.ReadTime) / interval / 60)
|
||||
}
|
||||
writeTime := uint64(0)
|
||||
if io2.WriteTime != 0 && io1.WriteTime != 0 && io2.WriteTime > io1.WriteTime {
|
||||
writeTime = uint64(float64(io2.WriteTime-io1.WriteTime) / interval / 60)
|
||||
}
|
||||
if writeTime > itemIO.Time {
|
||||
itemIO.Time = writeTime
|
||||
}
|
||||
ioList = append(ioList, itemIO)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
writeTime := uint64(0)
|
||||
if io2.WriteTime != 0 && io1.WriteTime != 0 && io2.WriteTime > io1.WriteTime {
|
||||
writeTime = uint64(float64(io2.WriteTime-io1.WriteTime) / 60)
|
||||
if err := settingRepo.BatchCreateMonitorIO(ioList); err != nil {
|
||||
global.LOG.Errorf("Insert io monitoring data failed, err: %v", err)
|
||||
}
|
||||
if writeTime > itemIO.Time {
|
||||
itemIO.Time = writeTime
|
||||
}
|
||||
ioList = append(ioList, itemIO)
|
||||
break
|
||||
m.DiskIO <- ioStat2
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := settingRepo.BatchCreateMonitorIO(ioList); err != nil {
|
||||
global.LOG.Errorf("Insert io monitoring data failed, err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func loadNetIO() {
|
||||
netStat, _ := net.IOCounters(true)
|
||||
netStatAll, _ := net.IOCounters(false)
|
||||
func (m *MonitorService) saveNetDataToDB(ctx context.Context, interval float64) {
|
||||
defer close(m.NetIO)
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case netStat := <-m.NetIO:
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case netStat2 := <-m.NetIO:
|
||||
var netList []model.MonitorNetwork
|
||||
for _, net2 := range netStat2 {
|
||||
for _, net1 := range netStat {
|
||||
if net2.Name == net1.Name {
|
||||
var itemNet model.MonitorNetwork
|
||||
itemNet.Name = net1.Name
|
||||
|
||||
time.Sleep(60 * time.Second)
|
||||
|
||||
netStat2, _ := net.IOCounters(true)
|
||||
var netList []model.MonitorNetwork
|
||||
for _, net2 := range netStat2 {
|
||||
for _, net1 := range netStat {
|
||||
if net2.Name == net1.Name {
|
||||
var itemNet model.MonitorNetwork
|
||||
itemNet.Name = net1.Name
|
||||
|
||||
if net2.BytesSent != 0 && net1.BytesSent != 0 && net2.BytesSent > net1.BytesSent {
|
||||
itemNet.Up = float64(net2.BytesSent-net1.BytesSent) / 1024 / 60
|
||||
if net2.BytesSent != 0 && net1.BytesSent != 0 && net2.BytesSent > net1.BytesSent {
|
||||
itemNet.Up = float64(net2.BytesSent-net1.BytesSent) / 1024 / interval / 60
|
||||
}
|
||||
if net2.BytesRecv != 0 && net1.BytesRecv != 0 && net2.BytesRecv > net1.BytesRecv {
|
||||
itemNet.Down = float64(net2.BytesRecv-net1.BytesRecv) / 1024 / interval / 60
|
||||
}
|
||||
netList = append(netList, itemNet)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if net2.BytesRecv != 0 && net1.BytesRecv != 0 && net2.BytesRecv > net1.BytesRecv {
|
||||
itemNet.Down = float64(net2.BytesRecv-net1.BytesRecv) / 1024 / 60
|
||||
|
||||
if err := settingRepo.BatchCreateMonitorNet(netList); err != nil {
|
||||
global.LOG.Errorf("Insert network monitoring data failed, err: %v", err)
|
||||
}
|
||||
netList = append(netList, itemNet)
|
||||
break
|
||||
m.NetIO <- netStat2
|
||||
}
|
||||
}
|
||||
}
|
||||
netStatAll2, _ := net.IOCounters(false)
|
||||
for _, net2 := range netStatAll2 {
|
||||
for _, net1 := range netStatAll {
|
||||
if net2.Name == net1.Name {
|
||||
var itemNet model.MonitorNetwork
|
||||
itemNet.Name = net1.Name
|
||||
if net2.BytesSent != 0 && net1.BytesSent != 0 && net2.BytesSent > net1.BytesSent {
|
||||
itemNet.Up = float64(net2.BytesSent-net1.BytesSent) / 1024 / 60
|
||||
}
|
||||
|
||||
if net2.BytesRecv != 0 && net1.BytesRecv != 0 && net2.BytesRecv > net1.BytesRecv {
|
||||
itemNet.Down = float64(net2.BytesRecv-net1.BytesRecv) / 1024 / 60
|
||||
}
|
||||
netList = append(netList, itemNet)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := settingRepo.BatchCreateMonitorNet(netList); err != nil {
|
||||
global.LOG.Errorf("Insert network monitoring data failed, err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func StartMonitor(removeBefore bool, interval string) error {
|
||||
if removeBefore {
|
||||
monitorCancel()
|
||||
global.Cron.Remove(cron.EntryID(global.MonitorCronID))
|
||||
}
|
||||
imservice := NewIMonitorService()
|
||||
monitorID, err := global.Cron.AddJob(fmt.Sprintf("@every %sm", interval), imservice)
|
||||
intervalItem, err := strconv.Atoi(interval)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
imservice.Run()
|
||||
|
||||
service := NewIMonitorService()
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
monitorCancel = cancel
|
||||
monitorID, err := global.Cron.AddJob(fmt.Sprintf("@every %sm", interval), service)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
service.Run()
|
||||
|
||||
go service.saveIODataToDB(ctx, float64(intervalItem))
|
||||
go service.saveNetDataToDB(ctx, float64(intervalItem))
|
||||
|
||||
global.MonitorCronID = int(monitorID)
|
||||
return nil
|
||||
}
|
||||
|
||||
+389
-152
@@ -3,7 +3,6 @@ package service
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto/response"
|
||||
@@ -12,11 +11,16 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
cmd2 "github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/compose"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/docker"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/env"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/subosito/gotenv"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@@ -25,11 +29,15 @@ type RuntimeService struct {
|
||||
}
|
||||
|
||||
type IRuntimeService interface {
|
||||
Page(req request.RuntimeSearch) (int64, []response.RuntimeRes, error)
|
||||
Page(req request.RuntimeSearch) (int64, []response.RuntimeDTO, error)
|
||||
Create(create request.RuntimeCreate) error
|
||||
Delete(id uint) error
|
||||
Delete(delete request.RuntimeDelete) error
|
||||
Update(req request.RuntimeUpdate) error
|
||||
Get(id uint) (res *response.RuntimeRes, err error)
|
||||
Get(id uint) (res *response.RuntimeDTO, err error)
|
||||
GetNodePackageRunScript(req request.NodePackageReq) ([]response.PackageScripts, error)
|
||||
OperateRuntime(req request.RuntimeOperate) error
|
||||
GetNodeModules(req request.NodeModuleReq) ([]response.NodeModule, error)
|
||||
OperateNodeModules(req request.NodeModuleOperateReq) error
|
||||
}
|
||||
|
||||
func NewRuntimeService() IRuntimeService {
|
||||
@@ -37,24 +45,52 @@ func NewRuntimeService() IRuntimeService {
|
||||
}
|
||||
|
||||
func (r *RuntimeService) Create(create request.RuntimeCreate) (err error) {
|
||||
exist, _ := runtimeRepo.GetFirst(runtimeRepo.WithName(create.Name))
|
||||
var (
|
||||
opts []repo.DBOption
|
||||
)
|
||||
if create.Name != "" {
|
||||
opts = append(opts, commonRepo.WithLikeName(create.Name))
|
||||
}
|
||||
if create.Type != "" {
|
||||
opts = append(opts, commonRepo.WithByType(create.Type))
|
||||
}
|
||||
exist, _ := runtimeRepo.GetFirst(opts...)
|
||||
if exist != nil {
|
||||
return buserr.New(constant.ErrNameIsExist)
|
||||
}
|
||||
if create.Resource == constant.ResourceLocal {
|
||||
runtime := &model.Runtime{
|
||||
Name: create.Name,
|
||||
Resource: create.Resource,
|
||||
Type: create.Type,
|
||||
Version: create.Version,
|
||||
Status: constant.RuntimeNormal,
|
||||
fileOp := files.NewFileOp()
|
||||
|
||||
switch create.Type {
|
||||
case constant.RuntimePHP:
|
||||
if create.Resource == constant.ResourceLocal {
|
||||
runtime := &model.Runtime{
|
||||
Name: create.Name,
|
||||
Resource: create.Resource,
|
||||
Type: create.Type,
|
||||
Version: create.Version,
|
||||
Status: constant.RuntimeNormal,
|
||||
}
|
||||
return runtimeRepo.Create(context.Background(), runtime)
|
||||
}
|
||||
exist, _ = runtimeRepo.GetFirst(runtimeRepo.WithImage(create.Image))
|
||||
if exist != nil {
|
||||
return buserr.New(constant.ErrImageExist)
|
||||
}
|
||||
case constant.RuntimeNode:
|
||||
if !fileOp.Stat(create.CodeDir) {
|
||||
return buserr.New(constant.ErrPathNotFound)
|
||||
}
|
||||
create.Install = true
|
||||
if err = checkPortExist(create.Port); err != nil {
|
||||
return err
|
||||
}
|
||||
if containerName, ok := create.Params["CONTAINER_NAME"]; ok {
|
||||
if err := checkContainerName(containerName.(string)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return runtimeRepo.Create(context.Background(), runtime)
|
||||
}
|
||||
exist, _ = runtimeRepo.GetFirst(runtimeRepo.WithImage(create.Image))
|
||||
if exist != nil {
|
||||
return buserr.New(constant.ErrImageExist)
|
||||
}
|
||||
|
||||
appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(create.AppDetailID))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -63,64 +99,40 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fileOp := files.NewFileOp()
|
||||
appVersionDir := path.Join(constant.AppResourceDir, app.Resource, app.Key, appDetail.Version)
|
||||
if !fileOp.Stat(appVersionDir) || appDetail.Update {
|
||||
if err := downloadApp(app, appDetail, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
buildDir := path.Join(appVersionDir, "build")
|
||||
if !fileOp.Stat(buildDir) {
|
||||
return buserr.New(constant.ErrDirNotFound)
|
||||
}
|
||||
runtimeDir := path.Join(constant.RuntimeDir, create.Type)
|
||||
tempDir := filepath.Join(runtimeDir, fmt.Sprintf("%d", time.Now().UnixNano()))
|
||||
if err = fileOp.CopyDir(buildDir, tempDir); err != nil {
|
||||
return
|
||||
}
|
||||
oldDir := path.Join(tempDir, "build")
|
||||
newNameDir := path.Join(runtimeDir, create.Name)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
_ = fileOp.DeleteDir(newNameDir)
|
||||
}
|
||||
}()
|
||||
if oldDir != newNameDir {
|
||||
if err = fileOp.Rename(oldDir, newNameDir); err != nil {
|
||||
return
|
||||
}
|
||||
if err = fileOp.DeleteDir(tempDir); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
composeContent, envContent, forms, err := handleParams(create.Image, create.Type, newNameDir, create.Source, create.Params)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
runtime := &model.Runtime{
|
||||
Name: create.Name,
|
||||
DockerCompose: string(composeContent),
|
||||
Env: string(envContent),
|
||||
AppDetailID: create.AppDetailID,
|
||||
Type: create.Type,
|
||||
Image: create.Image,
|
||||
Resource: create.Resource,
|
||||
Status: constant.RuntimeBuildIng,
|
||||
Version: create.Version,
|
||||
Params: string(forms),
|
||||
Name: create.Name,
|
||||
AppDetailID: create.AppDetailID,
|
||||
Type: create.Type,
|
||||
Image: create.Image,
|
||||
Resource: create.Resource,
|
||||
Version: create.Version,
|
||||
}
|
||||
if err = runtimeRepo.Create(context.Background(), runtime); err != nil {
|
||||
return
|
||||
|
||||
switch create.Type {
|
||||
case constant.RuntimePHP:
|
||||
if err = handlePHP(create, runtime, fileOp, appVersionDir); err != nil {
|
||||
return
|
||||
}
|
||||
case constant.RuntimeNode:
|
||||
runtime.Port = create.Port
|
||||
if err = handleNode(create, runtime, fileOp, appVersionDir); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
go buildRuntime(runtime, "", false)
|
||||
return
|
||||
return runtimeRepo.Create(context.Background(), runtime)
|
||||
}
|
||||
|
||||
func (r *RuntimeService) Page(req request.RuntimeSearch) (int64, []response.RuntimeRes, error) {
|
||||
func (r *RuntimeService) Page(req request.RuntimeSearch) (int64, []response.RuntimeDTO, error) {
|
||||
var (
|
||||
opts []repo.DBOption
|
||||
res []response.RuntimeRes
|
||||
res []response.RuntimeDTO
|
||||
)
|
||||
if req.Name != "" {
|
||||
opts = append(opts, commonRepo.WithLikeName(req.Name))
|
||||
@@ -128,116 +140,161 @@ func (r *RuntimeService) Page(req request.RuntimeSearch) (int64, []response.Runt
|
||||
if req.Status != "" {
|
||||
opts = append(opts, runtimeRepo.WithStatus(req.Status))
|
||||
}
|
||||
if req.Type != "" {
|
||||
opts = append(opts, commonRepo.WithByType(req.Type))
|
||||
}
|
||||
total, runtimes, err := runtimeRepo.Page(req.Page, req.PageSize, opts...)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
for _, runtime := range runtimes {
|
||||
res = append(res, response.RuntimeRes{
|
||||
Runtime: runtime,
|
||||
})
|
||||
runtimeDTO := response.NewRuntimeDTO(runtime)
|
||||
runtimeDTO.Params = make(map[string]interface{})
|
||||
envs, err := gotenv.Unmarshal(runtime.Env)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
for k, v := range envs {
|
||||
runtimeDTO.Params[k] = v
|
||||
}
|
||||
res = append(res, runtimeDTO)
|
||||
}
|
||||
return total, res, nil
|
||||
}
|
||||
|
||||
func (r *RuntimeService) Delete(id uint) error {
|
||||
runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(id))
|
||||
func (r *RuntimeService) Delete(runtimeDelete request.RuntimeDelete) error {
|
||||
runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(runtimeDelete.ID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
website, _ := websiteRepo.GetFirst(websiteRepo.WithRuntimeID(id))
|
||||
website, _ := websiteRepo.GetFirst(websiteRepo.WithRuntimeID(runtimeDelete.ID))
|
||||
if website.ID > 0 {
|
||||
return buserr.New(constant.ErrDelWithWebsite)
|
||||
}
|
||||
if runtime.Resource == constant.ResourceAppstore {
|
||||
client, err := docker.NewClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
imageID, err := client.GetImageIDByName(runtime.Image)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if imageID != "" {
|
||||
if err := client.DeleteImage(imageID); err != nil {
|
||||
global.LOG.Errorf("delete image id [%s] error %v", imageID, err)
|
||||
projectDir := runtime.GetPath()
|
||||
switch runtime.Type {
|
||||
case constant.RuntimePHP:
|
||||
client, err := docker.NewClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
imageID, err := client.GetImageIDByName(runtime.Image)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if imageID != "" {
|
||||
if err := client.DeleteImage(imageID); err != nil {
|
||||
global.LOG.Errorf("delete image id [%s] error %v", imageID, err)
|
||||
}
|
||||
}
|
||||
case constant.RuntimeNode:
|
||||
if out, err := compose.Down(runtime.GetComposePath()); err != nil && !runtimeDelete.ForceDelete {
|
||||
if out != "" {
|
||||
return errors.New(out)
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
runtimeDir := path.Join(constant.RuntimeDir, runtime.Type, runtime.Name)
|
||||
if err := files.NewFileOp().DeleteDir(runtimeDir); err != nil {
|
||||
if err := files.NewFileOp().DeleteDir(projectDir); err != nil && !runtimeDelete.ForceDelete {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return runtimeRepo.DeleteBy(commonRepo.WithByID(id))
|
||||
return runtimeRepo.DeleteBy(commonRepo.WithByID(runtimeDelete.ID))
|
||||
}
|
||||
|
||||
func (r *RuntimeService) Get(id uint) (*response.RuntimeRes, error) {
|
||||
func (r *RuntimeService) Get(id uint) (*response.RuntimeDTO, error) {
|
||||
runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res := &response.RuntimeRes{}
|
||||
res.Runtime = *runtime
|
||||
|
||||
res := response.NewRuntimeDTO(*runtime)
|
||||
if runtime.Resource == constant.ResourceLocal {
|
||||
return res, nil
|
||||
return &res, nil
|
||||
}
|
||||
appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(runtime.AppDetailID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res.AppID = appDetail.AppId
|
||||
var (
|
||||
appForm dto.AppForm
|
||||
appParams []response.AppParam
|
||||
)
|
||||
if err := json.Unmarshal([]byte(runtime.Params), &appForm); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
envs, err := gotenv.Unmarshal(runtime.Env)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if v, ok := envs["CONTAINER_PACKAGE_URL"]; ok {
|
||||
res.Source = v
|
||||
}
|
||||
for _, form := range appForm.FormFields {
|
||||
if v, ok := envs[form.EnvKey]; ok {
|
||||
appParam := response.AppParam{
|
||||
Edit: false,
|
||||
Key: form.EnvKey,
|
||||
Rule: form.Rule,
|
||||
Type: form.Type,
|
||||
Required: form.Required,
|
||||
}
|
||||
if form.Edit {
|
||||
appParam.Edit = true
|
||||
}
|
||||
appParam.LabelZh = form.LabelZh
|
||||
appParam.LabelEn = form.LabelEn
|
||||
appParam.Multiple = form.Multiple
|
||||
appParam.Value = v
|
||||
if form.Type == "select" {
|
||||
if form.Multiple {
|
||||
if v == "" {
|
||||
appParam.Value = []string{}
|
||||
switch runtime.Type {
|
||||
case constant.RuntimePHP:
|
||||
var (
|
||||
appForm dto.AppForm
|
||||
appParams []response.AppParam
|
||||
)
|
||||
if err := json.Unmarshal([]byte(runtime.Params), &appForm); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
envs, err := gotenv.Unmarshal(runtime.Env)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if v, ok := envs["CONTAINER_PACKAGE_URL"]; ok {
|
||||
res.Source = v
|
||||
}
|
||||
for _, form := range appForm.FormFields {
|
||||
if v, ok := envs[form.EnvKey]; ok {
|
||||
appParam := response.AppParam{
|
||||
Edit: false,
|
||||
Key: form.EnvKey,
|
||||
Rule: form.Rule,
|
||||
Type: form.Type,
|
||||
Required: form.Required,
|
||||
}
|
||||
if form.Edit {
|
||||
appParam.Edit = true
|
||||
}
|
||||
appParam.LabelZh = form.LabelZh
|
||||
appParam.LabelEn = form.LabelEn
|
||||
appParam.Multiple = form.Multiple
|
||||
appParam.Value = v
|
||||
if form.Type == "select" {
|
||||
if form.Multiple {
|
||||
if v == "" {
|
||||
appParam.Value = []string{}
|
||||
} else {
|
||||
appParam.Value = strings.Split(v, ",")
|
||||
}
|
||||
} else {
|
||||
appParam.Value = strings.Split(v, ",")
|
||||
}
|
||||
} else {
|
||||
for _, fv := range form.Values {
|
||||
if fv.Value == v {
|
||||
appParam.ShowValue = fv.Label
|
||||
break
|
||||
for _, fv := range form.Values {
|
||||
if fv.Value == v {
|
||||
appParam.ShowValue = fv.Label
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
appParam.Values = form.Values
|
||||
}
|
||||
appParam.Values = form.Values
|
||||
appParams = append(appParams, appParam)
|
||||
}
|
||||
appParams = append(appParams, appParam)
|
||||
}
|
||||
res.AppParams = appParams
|
||||
case constant.RuntimeNode:
|
||||
res.Params = make(map[string]interface{})
|
||||
envs, err := gotenv.Unmarshal(runtime.Env)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for k, v := range envs {
|
||||
switch k {
|
||||
case "NODE_APP_PORT", "PANEL_APP_PORT_HTTP":
|
||||
port, err := strconv.Atoi(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res.Params[k] = port
|
||||
default:
|
||||
res.Params[k] = v
|
||||
}
|
||||
}
|
||||
if v, ok := envs["CONTAINER_PACKAGE_URL"]; ok {
|
||||
res.Source = v
|
||||
}
|
||||
}
|
||||
res.AppParams = appParams
|
||||
return res, nil
|
||||
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
func (r *RuntimeService) Update(req request.RuntimeUpdate) error {
|
||||
@@ -245,36 +302,216 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
oldImage := runtime.Image
|
||||
if runtime.Resource == constant.ResourceLocal {
|
||||
runtime.Version = req.Version
|
||||
return runtimeRepo.Save(runtime)
|
||||
}
|
||||
exist, _ := runtimeRepo.GetFirst(runtimeRepo.WithImage(req.Name), runtimeRepo.WithNotId(req.ID))
|
||||
if exist != nil {
|
||||
return buserr.New(constant.ErrImageExist)
|
||||
oldImage := runtime.Image
|
||||
switch runtime.Type {
|
||||
case constant.RuntimePHP:
|
||||
exist, _ := runtimeRepo.GetFirst(runtimeRepo.WithImage(req.Name), runtimeRepo.WithNotId(req.ID))
|
||||
if exist != nil {
|
||||
return buserr.New(constant.ErrImageExist)
|
||||
}
|
||||
case constant.RuntimeNode:
|
||||
if runtime.Port != req.Port {
|
||||
if err = checkPortExist(req.Port); err != nil {
|
||||
return err
|
||||
}
|
||||
runtime.Port = req.Port
|
||||
}
|
||||
if containerName, ok := req.Params["CONTAINER_NAME"]; ok {
|
||||
envs, err := gotenv.Unmarshal(runtime.Env)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
oldContainerName := envs["CONTAINER_NAME"]
|
||||
if containerName != oldContainerName {
|
||||
if err := checkContainerName(containerName.(string)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
runtimeDir := path.Join(constant.RuntimeDir, runtime.Type, runtime.Name)
|
||||
composeContent, envContent, _, err := handleParams(req.Image, runtime.Type, runtimeDir, req.Source, req.Params)
|
||||
|
||||
projectDir := path.Join(constant.RuntimeDir, runtime.Type, runtime.Name)
|
||||
create := request.RuntimeCreate{
|
||||
Image: req.Image,
|
||||
Type: runtime.Type,
|
||||
Source: req.Source,
|
||||
Params: req.Params,
|
||||
CodeDir: req.CodeDir,
|
||||
Version: req.Version,
|
||||
NodeConfig: request.NodeConfig{
|
||||
Port: req.Port,
|
||||
Install: true,
|
||||
},
|
||||
}
|
||||
composeContent, envContent, _, err := handleParams(create, projectDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
runtime.Image = req.Image
|
||||
runtime.Env = string(envContent)
|
||||
runtime.DockerCompose = string(composeContent)
|
||||
runtime.Status = constant.RuntimeBuildIng
|
||||
_ = runtimeRepo.Save(runtime)
|
||||
client, err := docker.NewClient()
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
switch runtime.Type {
|
||||
case constant.RuntimePHP:
|
||||
runtime.Image = req.Image
|
||||
runtime.Status = constant.RuntimeBuildIng
|
||||
_ = runtimeRepo.Save(runtime)
|
||||
client, err := docker.NewClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
imageID, err := client.GetImageIDByName(oldImage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go buildRuntime(runtime, imageID, req.Rebuild)
|
||||
case constant.RuntimeNode:
|
||||
runtime.Version = req.Version
|
||||
runtime.CodeDir = req.CodeDir
|
||||
runtime.Port = req.Port
|
||||
runtime.Status = constant.RuntimeReCreating
|
||||
_ = runtimeRepo.Save(runtime)
|
||||
go reCreateRuntime(runtime)
|
||||
}
|
||||
imageID, err := client.GetImageIDByName(oldImage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go buildRuntime(runtime, imageID, req.Rebuild)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *RuntimeService) GetNodePackageRunScript(req request.NodePackageReq) ([]response.PackageScripts, error) {
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(req.CodeDir) {
|
||||
return nil, buserr.New(constant.ErrPathNotFound)
|
||||
}
|
||||
if !fileOp.Stat(path.Join(req.CodeDir, "package.json")) {
|
||||
return nil, buserr.New(constant.ErrPackageJsonNotFound)
|
||||
}
|
||||
content, err := fileOp.GetContent(path.Join(req.CodeDir, "package.json"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var packageMap map[string]interface{}
|
||||
err = json.Unmarshal(content, &packageMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
scripts, ok := packageMap["scripts"]
|
||||
if !ok {
|
||||
return nil, buserr.New(constant.ErrScriptsNotFound)
|
||||
}
|
||||
var packageScripts []response.PackageScripts
|
||||
for k, v := range scripts.(map[string]interface{}) {
|
||||
packageScripts = append(packageScripts, response.PackageScripts{
|
||||
Name: k,
|
||||
Script: v.(string),
|
||||
})
|
||||
}
|
||||
return packageScripts, nil
|
||||
}
|
||||
|
||||
func (r *RuntimeService) OperateRuntime(req request.RuntimeOperate) error {
|
||||
runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(req.ID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
runtime.Status = constant.RuntimeError
|
||||
runtime.Message = err.Error()
|
||||
_ = runtimeRepo.Save(runtime)
|
||||
}
|
||||
}()
|
||||
switch req.Operate {
|
||||
case constant.RuntimeUp:
|
||||
if err = runComposeCmdWithLog(req.Operate, runtime.GetComposePath(), runtime.GetLogPath()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = SyncRuntimeContainerStatus(runtime); err != nil {
|
||||
return err
|
||||
}
|
||||
case constant.RuntimeDown:
|
||||
if err = runComposeCmdWithLog(req.Operate, runtime.GetComposePath(), runtime.GetLogPath()); err != nil {
|
||||
return err
|
||||
}
|
||||
runtime.Status = constant.RuntimeStopped
|
||||
case constant.RuntimeRestart:
|
||||
if err = runComposeCmdWithLog(constant.RuntimeDown, runtime.GetComposePath(), runtime.GetLogPath()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = runComposeCmdWithLog(constant.RuntimeUp, runtime.GetComposePath(), runtime.GetLogPath()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = SyncRuntimeContainerStatus(runtime); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return runtimeRepo.Save(runtime)
|
||||
}
|
||||
|
||||
func (r *RuntimeService) GetNodeModules(req request.NodeModuleReq) ([]response.NodeModule, error) {
|
||||
runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(req.ID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var res []response.NodeModule
|
||||
nodeModulesPath := path.Join(runtime.CodeDir, "node_modules")
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(nodeModulesPath) {
|
||||
return nil, buserr.New("ErrNodeModulesNotFound")
|
||||
}
|
||||
moduleDirs, err := os.ReadDir(nodeModulesPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, moduleDir := range moduleDirs {
|
||||
packagePath := path.Join(nodeModulesPath, moduleDir.Name(), "package.json")
|
||||
if !fileOp.Stat(packagePath) {
|
||||
continue
|
||||
}
|
||||
content, err := fileOp.GetContent(packagePath)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
module := response.NodeModule{}
|
||||
if err := json.Unmarshal(content, &module); err != nil {
|
||||
continue
|
||||
}
|
||||
res = append(res, module)
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (r *RuntimeService) OperateNodeModules(req request.NodeModuleOperateReq) error {
|
||||
runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(req.ID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
containerName, err := env.GetEnvValueByKey(runtime.GetEnvPath(), "CONTAINER_NAME")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd := req.PkgManager
|
||||
switch req.Operate {
|
||||
case constant.RuntimeInstall:
|
||||
if req.PkgManager == constant.RuntimeNpm {
|
||||
cmd += " install"
|
||||
} else {
|
||||
cmd += " add"
|
||||
}
|
||||
case constant.RuntimeUninstall:
|
||||
if req.PkgManager == constant.RuntimeNpm {
|
||||
cmd += " uninstall"
|
||||
} else {
|
||||
cmd += " remove"
|
||||
}
|
||||
case constant.RuntimeUpdate:
|
||||
if req.PkgManager == constant.RuntimeNpm {
|
||||
cmd += " update"
|
||||
} else {
|
||||
cmd += " upgrade"
|
||||
}
|
||||
}
|
||||
cmd += " " + req.Module
|
||||
return cmd2.ExecContainerScript(containerName, cmd, 5*time.Minute)
|
||||
}
|
||||
|
||||
@@ -10,22 +10,213 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/docker"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/subosito/gotenv"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func handleNode(create request.RuntimeCreate, runtime *model.Runtime, fileOp files.FileOp, appVersionDir string) (err error) {
|
||||
runtimeDir := path.Join(constant.RuntimeDir, create.Type)
|
||||
if err = fileOp.CopyDir(appVersionDir, runtimeDir); err != nil {
|
||||
return
|
||||
}
|
||||
versionDir := path.Join(runtimeDir, filepath.Base(appVersionDir))
|
||||
projectDir := path.Join(runtimeDir, create.Name)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
_ = fileOp.DeleteDir(projectDir)
|
||||
}
|
||||
}()
|
||||
if err = fileOp.Rename(versionDir, projectDir); err != nil {
|
||||
return
|
||||
}
|
||||
composeContent, envContent, _, err := handleParams(create, projectDir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
runtime.DockerCompose = string(composeContent)
|
||||
runtime.Env = string(envContent)
|
||||
runtime.Status = constant.RuntimeCreating
|
||||
runtime.CodeDir = create.CodeDir
|
||||
|
||||
nodeDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(runtime.AppDetailID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go func() {
|
||||
_, _ = http.Get(nodeDetail.DownloadCallBackUrl)
|
||||
}()
|
||||
go startRuntime(runtime)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func handlePHP(create request.RuntimeCreate, runtime *model.Runtime, fileOp files.FileOp, appVersionDir string) (err error) {
|
||||
buildDir := path.Join(appVersionDir, "build")
|
||||
if !fileOp.Stat(buildDir) {
|
||||
return buserr.New(constant.ErrDirNotFound)
|
||||
}
|
||||
runtimeDir := path.Join(constant.RuntimeDir, create.Type)
|
||||
tempDir := filepath.Join(runtimeDir, fmt.Sprintf("%d", time.Now().UnixNano()))
|
||||
if err = fileOp.CopyDir(buildDir, tempDir); err != nil {
|
||||
return
|
||||
}
|
||||
oldDir := path.Join(tempDir, "build")
|
||||
projectDir := path.Join(runtimeDir, create.Name)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
_ = fileOp.DeleteDir(projectDir)
|
||||
}
|
||||
}()
|
||||
if oldDir != projectDir {
|
||||
if err = fileOp.Rename(oldDir, projectDir); err != nil {
|
||||
return
|
||||
}
|
||||
if err = fileOp.DeleteDir(tempDir); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
composeContent, envContent, forms, err := handleParams(create, projectDir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
runtime.DockerCompose = string(composeContent)
|
||||
runtime.Env = string(envContent)
|
||||
runtime.Params = string(forms)
|
||||
runtime.Status = constant.RuntimeBuildIng
|
||||
|
||||
go buildRuntime(runtime, "", false)
|
||||
return
|
||||
}
|
||||
|
||||
func startRuntime(runtime *model.Runtime) {
|
||||
if err := runComposeCmdWithLog("up", runtime.GetComposePath(), runtime.GetLogPath()); err != nil {
|
||||
runtime.Status = constant.RuntimeError
|
||||
runtime.Message = err.Error()
|
||||
_ = runtimeRepo.Save(runtime)
|
||||
return
|
||||
}
|
||||
|
||||
if err := SyncRuntimeContainerStatus(runtime); err != nil {
|
||||
runtime.Status = constant.RuntimeError
|
||||
runtime.Message = err.Error()
|
||||
_ = runtimeRepo.Save(runtime)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func reCreateRuntime(runtime *model.Runtime) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
runtime.Status = constant.RuntimeError
|
||||
runtime.Message = err.Error()
|
||||
_ = runtimeRepo.Save(runtime)
|
||||
}
|
||||
}()
|
||||
if err = runComposeCmdWithLog("down", runtime.GetComposePath(), runtime.GetLogPath()); err != nil {
|
||||
return
|
||||
}
|
||||
if err = runComposeCmdWithLog("up", runtime.GetComposePath(), runtime.GetLogPath()); err != nil {
|
||||
return
|
||||
}
|
||||
if err := SyncRuntimeContainerStatus(runtime); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func runComposeCmdWithLog(operate string, composePath string, logPath string) error {
|
||||
cmd := exec.Command("docker-compose", "-f", composePath, operate)
|
||||
if operate == "up" {
|
||||
cmd = exec.Command("docker-compose", "-f", composePath, operate, "-d")
|
||||
}
|
||||
logFile, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("Failed to open log file: %v", err)
|
||||
return err
|
||||
}
|
||||
multiWriterStdout := io.MultiWriter(os.Stdout, logFile)
|
||||
cmd.Stdout = multiWriterStdout
|
||||
var stderrBuf bytes.Buffer
|
||||
multiWriterStderr := io.MultiWriter(&stderrBuf, logFile, os.Stderr)
|
||||
cmd.Stderr = multiWriterStderr
|
||||
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return errors.New(buserr.New(constant.ErrRuntimeStart).Error() + ":" + stderrBuf.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func SyncRuntimeContainerStatus(runtime *model.Runtime) error {
|
||||
env, err := gotenv.Unmarshal(runtime.Env)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var containerNames []string
|
||||
if containerName, ok := env["CONTAINER_NAME"]; !ok {
|
||||
return buserr.New("ErrContainerNameNotFound")
|
||||
} else {
|
||||
containerNames = append(containerNames, containerName)
|
||||
}
|
||||
cli, err := docker.NewClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
containers, err := cli.ListContainersByName(containerNames)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(containers) == 0 {
|
||||
return buserr.WithNameAndErr("ErrContainerNotFound", containerNames[0], nil)
|
||||
}
|
||||
container := containers[0]
|
||||
|
||||
interval := 10 * time.Second
|
||||
retries := 60
|
||||
for i := 0; i < retries; i++ {
|
||||
resp, err := cli.InspectContainer(container.ID)
|
||||
if err != nil {
|
||||
time.Sleep(interval)
|
||||
continue
|
||||
}
|
||||
if resp.State.Health != nil {
|
||||
status := strings.ToLower(resp.State.Health.Status)
|
||||
switch status {
|
||||
case "starting":
|
||||
runtime.Status = constant.RuntimeStarting
|
||||
_ = runtimeRepo.Save(runtime)
|
||||
case "healthy":
|
||||
runtime.Status = constant.RuntimeRunning
|
||||
_ = runtimeRepo.Save(runtime)
|
||||
return nil
|
||||
case "unhealthy":
|
||||
runtime.Status = constant.RuntimeUnhealthy
|
||||
_ = runtimeRepo.Save(runtime)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
time.Sleep(interval)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildRuntime(runtime *model.Runtime, oldImageID string, rebuild bool) {
|
||||
runtimePath := path.Join(constant.RuntimeDir, runtime.Type, runtime.Name)
|
||||
composePath := path.Join(runtimePath, "docker-compose.yml")
|
||||
runtimePath := runtime.GetPath()
|
||||
composePath := runtime.GetComposePath()
|
||||
logPath := path.Join(runtimePath, "build.log")
|
||||
|
||||
logFile, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
|
||||
if err != nil {
|
||||
fmt.Println("Failed to open log file:", err)
|
||||
global.LOG.Errorf("failed to open log file: %v", err)
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
@@ -89,35 +280,51 @@ func buildRuntime(runtime *model.Runtime, oldImageID string, rebuild bool) {
|
||||
_ = runtimeRepo.Save(runtime)
|
||||
}
|
||||
|
||||
func handleParams(image, runtimeType, runtimeDir, source string, params map[string]interface{}) (composeContent []byte, envContent []byte, forms []byte, err error) {
|
||||
func handleParams(create request.RuntimeCreate, projectDir string) (composeContent []byte, envContent []byte, forms []byte, err error) {
|
||||
fileOp := files.NewFileOp()
|
||||
composeContent, err = fileOp.GetContent(path.Join(runtimeDir, "docker-compose.yml"))
|
||||
composeContent, err = fileOp.GetContent(path.Join(projectDir, "docker-compose.yml"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
env, err := gotenv.Read(path.Join(runtimeDir, ".env"))
|
||||
envPath := path.Join(projectDir, ".env")
|
||||
if !fileOp.Stat(envPath) {
|
||||
_ = fileOp.CreateFile(envPath)
|
||||
}
|
||||
env, err := gotenv.Read(envPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
forms, err = fileOp.GetContent(path.Join(runtimeDir, "config.json"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
params["IMAGE_NAME"] = image
|
||||
if runtimeType == constant.RuntimePHP {
|
||||
if extends, ok := params["PHP_EXTENSIONS"]; ok {
|
||||
switch create.Type {
|
||||
case constant.RuntimePHP:
|
||||
create.Params["IMAGE_NAME"] = create.Image
|
||||
forms, err = fileOp.GetContent(path.Join(projectDir, "config.json"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if extends, ok := create.Params["PHP_EXTENSIONS"]; ok {
|
||||
if extendsArray, ok := extends.([]interface{}); ok {
|
||||
strArray := make([]string, len(extendsArray))
|
||||
for i, v := range extendsArray {
|
||||
strArray[i] = strings.ToLower(fmt.Sprintf("%v", v))
|
||||
}
|
||||
params["PHP_EXTENSIONS"] = strings.Join(strArray, ",")
|
||||
create.Params["PHP_EXTENSIONS"] = strings.Join(strArray, ",")
|
||||
}
|
||||
}
|
||||
params["CONTAINER_PACKAGE_URL"] = source
|
||||
create.Params["CONTAINER_PACKAGE_URL"] = create.Source
|
||||
case constant.RuntimeNode:
|
||||
create.Params["CODE_DIR"] = create.CodeDir
|
||||
create.Params["NODE_VERSION"] = create.Version
|
||||
create.Params["PANEL_APP_PORT_HTTP"] = create.Port
|
||||
if create.NodeConfig.Install {
|
||||
create.Params["RUN_INSTALL"] = "1"
|
||||
} else {
|
||||
create.Params["RUN_INSTALL"] = "0"
|
||||
}
|
||||
create.Params["CONTAINER_PACKAGE_URL"] = create.Source
|
||||
}
|
||||
|
||||
newMap := make(map[string]string)
|
||||
handleMap(params, newMap)
|
||||
handleMap(create.Params, newMap)
|
||||
for k, v := range newMap {
|
||||
env[k] = v
|
||||
}
|
||||
@@ -125,9 +332,24 @@ func handleParams(image, runtimeType, runtimeDir, source string, params map[stri
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = gotenv.Write(env, path.Join(runtimeDir, ".env")); err != nil {
|
||||
if err = gotenv.Write(env, envPath); err != nil {
|
||||
return
|
||||
}
|
||||
envContent = []byte(envStr)
|
||||
return
|
||||
}
|
||||
|
||||
func checkContainerName(name string) error {
|
||||
dockerCli, err := docker.NewClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
names, err := dockerCli.ListContainersByName([]string{name})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(names) > 0 {
|
||||
return buserr.New(constant.ErrContainerName)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -38,6 +38,9 @@ type ISettingService interface {
|
||||
LoadFromCert() (*dto.SSLInfo, error)
|
||||
HandlePasswordExpired(c *gin.Context, old, new string) error
|
||||
SyncTime(req dto.SyncTime) error
|
||||
|
||||
SystemScan() dto.CleanData
|
||||
SystemClean(req []dto.Clean)
|
||||
}
|
||||
|
||||
func NewISettingService() ISettingService {
|
||||
@@ -86,6 +89,7 @@ func (u *SettingService) Update(key, value string) error {
|
||||
}
|
||||
}
|
||||
if value == "disable" && global.MonitorCronID != 0 {
|
||||
monitorCancel()
|
||||
global.Cron.Remove(cron.EntryID(global.MonitorCronID))
|
||||
global.MonitorCronID = 0
|
||||
}
|
||||
|
||||
@@ -0,0 +1,508 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||
fileUtils "github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func (u *SettingService) SystemScan() dto.CleanData {
|
||||
var (
|
||||
SystemClean dto.CleanData
|
||||
treeData []dto.CleanTree
|
||||
)
|
||||
fileOp := fileUtils.NewFileOp()
|
||||
|
||||
originalPath := path.Join(global.CONF.System.BaseDir, "1panel_original")
|
||||
originalSize, _ := fileOp.GetDirSize(originalPath)
|
||||
treeData = append(treeData, dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "1panel_original",
|
||||
Size: uint64(originalSize),
|
||||
IsCheck: true,
|
||||
IsRecommend: true,
|
||||
Type: "1panel_original",
|
||||
Children: loadTreeWithDir(true, "1panel_original", originalPath, fileOp),
|
||||
})
|
||||
|
||||
upgradePath := path.Join(global.CONF.System.BaseDir, "1panel/tmp/upgrade")
|
||||
upgradeSize, _ := fileOp.GetDirSize(upgradePath)
|
||||
treeData = append(treeData, dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "upgrade",
|
||||
Size: uint64(upgradeSize),
|
||||
IsCheck: false,
|
||||
IsRecommend: true,
|
||||
Type: "upgrade",
|
||||
Children: loadTreeWithDir(true, "upgrade", upgradePath, fileOp),
|
||||
})
|
||||
|
||||
snapTree := loadSnapshotTree(fileOp)
|
||||
snapSize := uint64(0)
|
||||
for _, snap := range snapTree {
|
||||
snapSize += uint64(snap.Size)
|
||||
}
|
||||
treeData = append(treeData, dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "snapshot",
|
||||
Size: snapSize,
|
||||
IsCheck: true,
|
||||
IsRecommend: true,
|
||||
Type: "snapshot",
|
||||
Children: snapTree,
|
||||
})
|
||||
|
||||
rollBackTree := loadRollBackTree(fileOp)
|
||||
rollbackSize := uint64(0)
|
||||
for _, rollback := range rollBackTree {
|
||||
rollbackSize += uint64(rollback.Size)
|
||||
}
|
||||
treeData = append(treeData, dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "rollback",
|
||||
Size: rollbackSize,
|
||||
IsCheck: true,
|
||||
IsRecommend: true,
|
||||
Type: "rollback",
|
||||
Children: rollBackTree,
|
||||
})
|
||||
|
||||
cachePath := path.Join(global.CONF.System.BaseDir, "1panel/cache")
|
||||
cacheSize, _ := fileOp.GetDirSize(cachePath)
|
||||
treeData = append(treeData, dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "cache",
|
||||
Size: uint64(cacheSize),
|
||||
IsCheck: false,
|
||||
IsRecommend: false,
|
||||
Type: "cache",
|
||||
})
|
||||
|
||||
unusedTree := loadUnusedFile(fileOp)
|
||||
unusedSize := uint64(0)
|
||||
for _, unused := range unusedTree {
|
||||
unusedSize += uint64(unused.Size)
|
||||
}
|
||||
treeData = append(treeData, dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "unused",
|
||||
Size: unusedSize,
|
||||
IsCheck: true,
|
||||
IsRecommend: true,
|
||||
Type: "unused",
|
||||
Children: unusedTree,
|
||||
})
|
||||
SystemClean.SystemClean = treeData
|
||||
|
||||
uploadTreeData := loadUploadTree(fileOp)
|
||||
SystemClean.UploadClean = append(SystemClean.UploadClean, uploadTreeData...)
|
||||
|
||||
downloadTreeData := loadDownloadTree(fileOp)
|
||||
SystemClean.DownloadClean = append(SystemClean.DownloadClean, downloadTreeData...)
|
||||
|
||||
logTree := loadLogTree(fileOp)
|
||||
SystemClean.SystemLogClean = append(SystemClean.SystemLogClean, logTree...)
|
||||
|
||||
return SystemClean
|
||||
}
|
||||
|
||||
func (u *SettingService) SystemClean(req []dto.Clean) {
|
||||
size := uint64(0)
|
||||
restart := false
|
||||
for _, item := range req {
|
||||
size += item.Size
|
||||
switch item.TreeType {
|
||||
case "1panel_original":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel_original", item.Name))
|
||||
|
||||
case "upgrade":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/upgrade", item.Name))
|
||||
|
||||
case "snapshot":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/system", item.Name))
|
||||
dropFileOrDir(path.Join(global.CONF.System.Backup, "system", item.Name))
|
||||
case "snapshot_tmp":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/system", item.Name))
|
||||
case "snapshot_local":
|
||||
dropFileOrDir(path.Join(global.CONF.System.Backup, "system", item.Name))
|
||||
|
||||
case "rollback":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/app"))
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/database"))
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/website"))
|
||||
case "rollback_app":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/app", item.Name))
|
||||
case "rollback_database":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/database", item.Name))
|
||||
case "rollback_website":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/website", item.Name))
|
||||
|
||||
case "cache":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/cache", item.Name))
|
||||
restart = true
|
||||
|
||||
case "unused":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "original"))
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/resource/apps_bak"))
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/download"))
|
||||
files, _ := os.ReadDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp"))
|
||||
if len(files) == 0 {
|
||||
continue
|
||||
}
|
||||
for _, file := range files {
|
||||
if strings.HasPrefix(file.Name(), "upgrade_") {
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp", file.Name()))
|
||||
}
|
||||
}
|
||||
case "old_original":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "original", item.Name))
|
||||
case "old_apps_bak":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/resource/apps_bak", item.Name))
|
||||
case "old_download":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/download", item.Name))
|
||||
case "old_upgrade":
|
||||
if len(item.Name) == 0 {
|
||||
files, _ := os.ReadDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp"))
|
||||
if len(files) == 0 {
|
||||
continue
|
||||
}
|
||||
for _, file := range files {
|
||||
if strings.HasPrefix(file.Name(), "upgrade_") {
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp", file.Name()))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp", item.Name))
|
||||
}
|
||||
|
||||
case "upload":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/uploads", item.Name))
|
||||
if len(item.Name) == 0 {
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/upload"))
|
||||
}
|
||||
case "upload_tmp":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/upload", item.Name))
|
||||
case "upload_app":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/uploads/app", item.Name))
|
||||
case "upload_database":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/uploads/database", item.Name))
|
||||
case "upload_website":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/uploads/website", item.Name))
|
||||
case "upload_directory":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/uploads/directory", item.Name))
|
||||
case "download":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/download", item.Name))
|
||||
case "download_app":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/download/app", item.Name))
|
||||
case "download_database":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/download/database", item.Name))
|
||||
case "download_website":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/download/website", item.Name))
|
||||
case "download_directory":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/download/directory", item.Name))
|
||||
|
||||
case "system_log":
|
||||
if len(item.Name) == 0 {
|
||||
files, _ := os.ReadDir(path.Join(global.CONF.System.BaseDir, "1panel/log"))
|
||||
if len(files) == 0 {
|
||||
continue
|
||||
}
|
||||
for _, file := range files {
|
||||
if file.Name() == "1Panel.log" {
|
||||
continue
|
||||
}
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/log", file.Name()))
|
||||
}
|
||||
} else {
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/log", item.Name))
|
||||
}
|
||||
case "docker_log":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/docker_logs", item.Name))
|
||||
case "task_log":
|
||||
pathItem := path.Join(global.CONF.System.BaseDir, "1panel/task", item.Name)
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/task", item.Name))
|
||||
if len(item.Name) == 0 {
|
||||
files, _ := os.ReadDir(pathItem)
|
||||
if len(files) == 0 {
|
||||
continue
|
||||
}
|
||||
for _, file := range files {
|
||||
_ = cronjobRepo.DeleteRecord(cronjobRepo.WithByRecordFile(path.Join(pathItem, file.Name())))
|
||||
}
|
||||
} else {
|
||||
_ = cronjobRepo.DeleteRecord(cronjobRepo.WithByRecordFile(pathItem))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ = settingRepo.Update("LastCleanTime", time.Now().Format("2006-01-02 15:04:05"))
|
||||
_ = settingRepo.Update("LastCleanSize", fmt.Sprintf("%v", size))
|
||||
_ = settingRepo.Update("LastCleanData", fmt.Sprintf("%v", len(req)))
|
||||
|
||||
if restart {
|
||||
go func() {
|
||||
_, err := cmd.Exec("systemctl restart 1panel.service")
|
||||
if err != nil {
|
||||
global.LOG.Errorf("restart system port failed, err: %v", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
func loadSnapshotTree(fileOp fileUtils.FileOp) []dto.CleanTree {
|
||||
var treeData []dto.CleanTree
|
||||
path1 := path.Join(global.CONF.System.BaseDir, "1panel/tmp/system")
|
||||
list1 := loadTreeWithAllFile(true, path1, "snapshot_tmp", path1, fileOp)
|
||||
if len(list1) != 0 {
|
||||
size, _ := fileOp.GetDirSize(path1)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "snapshot_tmp", Size: uint64(size), Children: list1, Type: "snapshot_tmp", IsRecommend: true})
|
||||
}
|
||||
|
||||
path2 := path.Join(global.CONF.System.Backup, "system")
|
||||
list2 := loadTreeWithAllFile(true, path2, "snapshot_local", path2, fileOp)
|
||||
if len(list2) != 0 {
|
||||
size, _ := fileOp.GetDirSize(path2)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "snapshot_local", Size: uint64(size), Children: list2, Type: "snapshot_local", IsRecommend: true})
|
||||
}
|
||||
return treeData
|
||||
}
|
||||
|
||||
func loadRollBackTree(fileOp fileUtils.FileOp) []dto.CleanTree {
|
||||
var treeData []dto.CleanTree
|
||||
path1 := path.Join(global.CONF.System.BaseDir, "1panel/tmp/app")
|
||||
list1 := loadTreeWithAllFile(true, path1, "rollback_app", path1, fileOp)
|
||||
size1, _ := fileOp.GetDirSize(path1)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "rollback_app", Size: uint64(size1), Children: list1, Type: "rollback_app", IsRecommend: true})
|
||||
|
||||
path2 := path.Join(global.CONF.System.BaseDir, "1panel/tmp/website")
|
||||
list2 := loadTreeWithAllFile(true, path2, "rollback_website", path2, fileOp)
|
||||
size2, _ := fileOp.GetDirSize(path2)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "rollback_website", Size: uint64(size2), Children: list2, Type: "rollback_website", IsRecommend: true})
|
||||
|
||||
path3 := path.Join(global.CONF.System.BaseDir, "1panel/tmp/database")
|
||||
list3 := loadTreeWithAllFile(true, path3, "rollback_database", path3, fileOp)
|
||||
size3, _ := fileOp.GetDirSize(path3)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "rollback_database", Size: uint64(size3), Children: list3, Type: "rollback_database", IsRecommend: true})
|
||||
|
||||
return treeData
|
||||
}
|
||||
|
||||
func loadUnusedFile(fileOp fileUtils.FileOp) []dto.CleanTree {
|
||||
var treeData []dto.CleanTree
|
||||
path1 := path.Join(global.CONF.System.BaseDir, "original")
|
||||
list1 := loadTreeWithAllFile(true, path1, "old_original", path1, fileOp)
|
||||
if len(list1) != 0 {
|
||||
size, _ := fileOp.GetDirSize(path1)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "old_original", Size: uint64(size), Children: list1, Type: "old_original"})
|
||||
}
|
||||
|
||||
path2 := path.Join(global.CONF.System.BaseDir, "1panel/resource/apps_bak")
|
||||
list2 := loadTreeWithAllFile(true, path2, "old_apps_bak", path2, fileOp)
|
||||
if len(list2) != 0 {
|
||||
size, _ := fileOp.GetDirSize(path2)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "old_apps_bak", Size: uint64(size), Children: list2, Type: "old_apps_bak"})
|
||||
}
|
||||
|
||||
path3 := path.Join(global.CONF.System.BaseDir, "1panel/tmp/download")
|
||||
list3 := loadTreeWithAllFile(true, path3, "old_download", path3, fileOp)
|
||||
if len(list3) != 0 {
|
||||
size, _ := fileOp.GetDirSize(path3)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "old_download", Size: uint64(size), Children: list3, Type: "old_download"})
|
||||
}
|
||||
|
||||
path4 := path.Join(global.CONF.System.BaseDir, "1panel/tmp")
|
||||
list4 := loadTreeWithDir(true, "old_upgrade", path4, fileOp)
|
||||
itemSize := uint64(0)
|
||||
for _, item := range list4 {
|
||||
itemSize += item.Size
|
||||
}
|
||||
if len(list4) != 0 {
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "old_upgrade", Size: itemSize, Children: list4, Type: "old_upgrade"})
|
||||
}
|
||||
return treeData
|
||||
}
|
||||
|
||||
func loadUploadTree(fileOp fileUtils.FileOp) []dto.CleanTree {
|
||||
var treeData []dto.CleanTree
|
||||
|
||||
path0 := path.Join(global.CONF.System.BaseDir, "1panel/tmp/upload")
|
||||
list0 := loadTreeWithAllFile(true, path0, "upload_tmp", path0, fileOp)
|
||||
size0, _ := fileOp.GetDirSize(path0)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "upload_tmp", Size: uint64(size0), Children: list0, Type: "upload_tmp", IsRecommend: true})
|
||||
|
||||
path1 := path.Join(global.CONF.System.BaseDir, "1panel/uploads/app")
|
||||
list1 := loadTreeWithAllFile(true, path1, "upload_app", path1, fileOp)
|
||||
size1, _ := fileOp.GetDirSize(path1)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "upload_app", Size: uint64(size1), Children: list1, Type: "upload_app", IsRecommend: true})
|
||||
|
||||
path2 := path.Join(global.CONF.System.BaseDir, "1panel/uploads/website")
|
||||
list2 := loadTreeWithAllFile(true, path2, "upload_website", path2, fileOp)
|
||||
size2, _ := fileOp.GetDirSize(path2)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "upload_website", Size: uint64(size2), Children: list2, Type: "upload_website", IsRecommend: true})
|
||||
|
||||
path3 := path.Join(global.CONF.System.BaseDir, "1panel/uploads/database")
|
||||
list3 := loadTreeWithAllFile(true, path3, "upload_database", path3, fileOp)
|
||||
size3, _ := fileOp.GetDirSize(path3)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "upload_database", Size: uint64(size3), Children: list3, Type: "upload_database", IsRecommend: true})
|
||||
|
||||
path4 := path.Join(global.CONF.System.BaseDir, "1panel/uploads/directory")
|
||||
list4 := loadTreeWithAllFile(true, path4, "upload_directory", path4, fileOp)
|
||||
size4, _ := fileOp.GetDirSize(path4)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "upload_directory", Size: uint64(size4), Children: list4, Type: "upload_directory", IsRecommend: true})
|
||||
|
||||
path5 := path.Join(global.CONF.System.BaseDir, "1panel/uploads")
|
||||
uploadTreeData := loadTreeWithAllFile(true, path5, "upload", path5, fileOp)
|
||||
treeData = append(treeData, uploadTreeData...)
|
||||
|
||||
return treeData
|
||||
}
|
||||
|
||||
func loadDownloadTree(fileOp fileUtils.FileOp) []dto.CleanTree {
|
||||
var treeData []dto.CleanTree
|
||||
path1 := path.Join(global.CONF.System.BaseDir, "1panel/download/app")
|
||||
list1 := loadTreeWithAllFile(true, path1, "download_app", path1, fileOp)
|
||||
size1, _ := fileOp.GetDirSize(path1)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "download_app", Size: uint64(size1), Children: list1, Type: "download_app", IsRecommend: true})
|
||||
|
||||
path2 := path.Join(global.CONF.System.BaseDir, "1panel/download/website")
|
||||
list2 := loadTreeWithAllFile(true, path2, "download_website", path2, fileOp)
|
||||
size2, _ := fileOp.GetDirSize(path2)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "download_website", Size: uint64(size2), Children: list2, Type: "download_website", IsRecommend: true})
|
||||
|
||||
path3 := path.Join(global.CONF.System.BaseDir, "1panel/download/database")
|
||||
list3 := loadTreeWithAllFile(true, path3, "download_database", path3, fileOp)
|
||||
size3, _ := fileOp.GetDirSize(path3)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "download_database", Size: uint64(size3), Children: list3, Type: "download_database", IsRecommend: true})
|
||||
|
||||
path4 := path.Join(global.CONF.System.BaseDir, "1panel/download/directory")
|
||||
list4 := loadTreeWithAllFile(true, path4, "download_directory", path4, fileOp)
|
||||
size4, _ := fileOp.GetDirSize(path4)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "download_directory", Size: uint64(size4), Children: list4, Type: "download_directory", IsRecommend: true})
|
||||
|
||||
path5 := path.Join(global.CONF.System.BaseDir, "1panel/download")
|
||||
uploadTreeData := loadTreeWithAllFile(true, path5, "download", path5, fileOp)
|
||||
treeData = append(treeData, uploadTreeData...)
|
||||
|
||||
return treeData
|
||||
}
|
||||
|
||||
func loadLogTree(fileOp fileUtils.FileOp) []dto.CleanTree {
|
||||
var treeData []dto.CleanTree
|
||||
path1 := path.Join(global.CONF.System.BaseDir, "1panel/log")
|
||||
list1 := loadTreeWithAllFile(true, path1, "system_log", path1, fileOp)
|
||||
size := uint64(0)
|
||||
for _, file := range list1 {
|
||||
size += file.Size
|
||||
}
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "system_log", Size: uint64(size), Children: list1, Type: "system_log", IsRecommend: true})
|
||||
|
||||
path2 := path.Join(global.CONF.System.BaseDir, "1panel/tmp/docker_logs")
|
||||
list2 := loadTreeWithAllFile(true, path2, "docker_log", path2, fileOp)
|
||||
size2, _ := fileOp.GetDirSize(path2)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "docker_log", Size: uint64(size2), Children: list2, Type: "docker_log", IsRecommend: true})
|
||||
|
||||
path3 := path.Join(global.CONF.System.BaseDir, "1panel/task")
|
||||
list3 := loadTreeWithAllFile(false, path3, "task_log", path3, fileOp)
|
||||
size3, _ := fileOp.GetDirSize(path3)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "task_log", Size: uint64(size3), Children: list3, Type: "task_log"})
|
||||
return treeData
|
||||
}
|
||||
|
||||
func loadTreeWithDir(isCheck bool, treeType, pathItem string, fileOp fileUtils.FileOp) []dto.CleanTree {
|
||||
var lists []dto.CleanTree
|
||||
files, err := os.ReadDir(pathItem)
|
||||
if err != nil {
|
||||
return lists
|
||||
}
|
||||
sort.Slice(files, func(i, j int) bool {
|
||||
return files[i].Name() > files[j].Name()
|
||||
})
|
||||
for _, file := range files {
|
||||
if (treeType == "old_upgrade" || treeType == "upgrade") && !strings.HasPrefix(file.Name(), "upgrade_2023") {
|
||||
continue
|
||||
}
|
||||
if file.IsDir() {
|
||||
size, err := fileOp.GetDirSize(path.Join(pathItem, file.Name()))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
item := dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: file.Name(),
|
||||
Type: treeType,
|
||||
Size: uint64(size),
|
||||
Name: strings.TrimPrefix(file.Name(), "/"),
|
||||
IsCheck: isCheck,
|
||||
IsRecommend: isCheck,
|
||||
}
|
||||
if treeType == "upgrade" && len(lists) == 0 {
|
||||
item.IsCheck = false
|
||||
item.IsRecommend = false
|
||||
}
|
||||
lists = append(lists, item)
|
||||
}
|
||||
}
|
||||
return lists
|
||||
}
|
||||
|
||||
func loadTreeWithAllFile(isCheck bool, originalPath, treeType, pathItem string, fileOp fileUtils.FileOp) []dto.CleanTree {
|
||||
var lists []dto.CleanTree
|
||||
|
||||
files, err := os.ReadDir(pathItem)
|
||||
if err != nil {
|
||||
return lists
|
||||
}
|
||||
for _, file := range files {
|
||||
if treeType == "system_log" && file.Name() == "1Panel.log" {
|
||||
continue
|
||||
}
|
||||
if (treeType == "upload" || treeType == "download") && file.IsDir() && (file.Name() == "app" || file.Name() == "database" || file.Name() == "website" || file.Name() == "directory") {
|
||||
continue
|
||||
}
|
||||
size := uint64(0)
|
||||
name := strings.TrimPrefix(path.Join(pathItem, file.Name()), originalPath+"/")
|
||||
if file.IsDir() {
|
||||
sizeItem, err := fileOp.GetDirSize(path.Join(pathItem, file.Name()))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
size = uint64(sizeItem)
|
||||
} else {
|
||||
fileInfo, err := file.Info()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
size = uint64(fileInfo.Size())
|
||||
}
|
||||
item := dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: file.Name(),
|
||||
Type: treeType,
|
||||
Size: uint64(size),
|
||||
Name: name,
|
||||
IsCheck: isCheck,
|
||||
IsRecommend: isCheck,
|
||||
}
|
||||
if file.IsDir() {
|
||||
item.Children = loadTreeWithAllFile(isCheck, originalPath, treeType, path.Join(pathItem, file.Name()), fileOp)
|
||||
}
|
||||
lists = append(lists, item)
|
||||
}
|
||||
return lists
|
||||
}
|
||||
|
||||
func dropFileOrDir(itemPath string) {
|
||||
global.LOG.Debugf("drop file %s", itemPath)
|
||||
if err := os.RemoveAll(itemPath); err != nil {
|
||||
global.LOG.Errorf("drop file %s failed, err %v", itemPath, err)
|
||||
}
|
||||
}
|
||||
@@ -139,7 +139,7 @@ func (u *SnapshotService) SnapshotCreate(req dto.SnapshotCreate) error {
|
||||
}
|
||||
|
||||
func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
|
||||
global.LOG.Info("start to recvover panel by snapshot now")
|
||||
global.LOG.Info("start to recover panel by snapshot now")
|
||||
snap, err := snapshotRepo.Get(commonRepo.WithByID(req.ID))
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
+127
-2
@@ -32,6 +32,7 @@ type ISSHService interface {
|
||||
UpdateByFile(value string) error
|
||||
Update(key, value string) error
|
||||
GenerateSSH(req dto.GenerateSSH) error
|
||||
AnalysisLog(req dto.SearchForAnalysis) (*dto.AnalysisRes, error)
|
||||
LoadSSHSecret(mode string) (string, error)
|
||||
LoadLog(req dto.SearchSSHLog) (*dto.SSHLog, error)
|
||||
|
||||
@@ -239,7 +240,7 @@ func (u *SSHService) LoadLog(req dto.SearchSSHLog) (*dto.SSHLog, error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.IsDir() && strings.HasPrefix(info.Name(), "secure") || strings.HasPrefix(info.Name(), "auth") {
|
||||
if !info.IsDir() && (strings.HasPrefix(info.Name(), "secure") || strings.HasPrefix(info.Name(), "auth")) {
|
||||
if !strings.HasSuffix(info.Name(), ".gz") {
|
||||
fileList = append(fileList, sshFileItem{Name: pathItem, Year: info.ModTime().Year()})
|
||||
return nil
|
||||
@@ -303,6 +304,89 @@ func (u *SSHService) LoadLog(req dto.SearchSSHLog) (*dto.SSHLog, error) {
|
||||
return &data, nil
|
||||
}
|
||||
|
||||
func (u *SSHService) AnalysisLog(req dto.SearchForAnalysis) (*dto.AnalysisRes, error) {
|
||||
var fileList []string
|
||||
baseDir := "/var/log"
|
||||
if err := filepath.Walk(baseDir, func(pathItem string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.IsDir() && (strings.HasPrefix(info.Name(), "secure") || strings.HasPrefix(info.Name(), "auth")) {
|
||||
if !strings.HasSuffix(info.Name(), ".gz") {
|
||||
fileList = append(fileList, pathItem)
|
||||
return nil
|
||||
}
|
||||
itemFileName := strings.TrimSuffix(pathItem, ".gz")
|
||||
if _, err := os.Stat(itemFileName); err != nil && os.IsNotExist(err) {
|
||||
if err := handleGunzip(pathItem); err == nil {
|
||||
fileList = append(fileList, itemFileName)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
command := ""
|
||||
sortMap := make(map[string]dto.SSHLogAnalysis)
|
||||
for _, file := range fileList {
|
||||
commandItem := ""
|
||||
if strings.HasPrefix(path.Base(file), "secure") {
|
||||
commandItem = fmt.Sprintf("cat %s | grep -aE '(Failed password for|Accepted)' | grep -v 'invalid' %s", file, command)
|
||||
}
|
||||
if strings.HasPrefix(path.Base(file), "auth.log") {
|
||||
commandItem = fmt.Sprintf("cat %s | grep -aE \"(Connection closed by authenticating user|Accepted)\" | grep -v 'invalid' %s", file, command)
|
||||
}
|
||||
loadSSHDataForAnalysis(sortMap, commandItem)
|
||||
}
|
||||
var sortSlice []dto.SSHLogAnalysis
|
||||
for key, value := range sortMap {
|
||||
sortSlice = append(sortSlice, dto.SSHLogAnalysis{Address: key, SuccessfulCount: value.SuccessfulCount, FailedCount: value.FailedCount, Status: "accept"})
|
||||
}
|
||||
if req.OrderBy == constant.StatusSuccess {
|
||||
sort.Slice(sortSlice, func(i, j int) bool {
|
||||
return sortSlice[i].SuccessfulCount > sortSlice[j].SuccessfulCount
|
||||
})
|
||||
} else {
|
||||
sort.Slice(sortSlice, func(i, j int) bool {
|
||||
return sortSlice[i].FailedCount > sortSlice[j].FailedCount
|
||||
})
|
||||
}
|
||||
qqWry, _ := qqwry.NewQQwry()
|
||||
rules, _ := listIpRules("drop")
|
||||
for i := 0; i < len(sortSlice); i++ {
|
||||
sortSlice[i].Area = qqWry.Find(sortSlice[i].Address).Area
|
||||
for _, rule := range rules {
|
||||
if sortSlice[i].Address == rule {
|
||||
sortSlice[i].Status = "drop"
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var backData dto.AnalysisRes
|
||||
for _, item := range sortSlice {
|
||||
backData.FailedCount += item.FailedCount
|
||||
backData.SuccessfulCount += item.SuccessfulCount
|
||||
}
|
||||
|
||||
var data []dto.SSHLogAnalysis
|
||||
total, start, end := len(sortSlice), (req.Page-1)*req.PageSize, req.Page*req.PageSize
|
||||
if start > total {
|
||||
data = make([]dto.SSHLogAnalysis, 0)
|
||||
} else {
|
||||
if end >= total {
|
||||
end = total
|
||||
}
|
||||
data = sortSlice[start:end]
|
||||
}
|
||||
backData.Items = data
|
||||
backData.Total = int64(total)
|
||||
|
||||
return &backData, nil
|
||||
}
|
||||
|
||||
func (u *SSHService) LoadSSHConf() (string, error) {
|
||||
if _, err := os.Stat("/etc/ssh/sshd_config"); err != nil {
|
||||
return "", buserr.New("ErrHttpReqNotFound")
|
||||
@@ -324,7 +408,7 @@ func sortFileList(fileNames []sshFileItem) []sshFileItem {
|
||||
return fileNames[i].Name > fileNames[j].Name
|
||||
})
|
||||
itemFile = append(itemFile, fileNames[len(fileNames)-1])
|
||||
itemFile = append(itemFile, fileNames[:len(fileNames)-2]...)
|
||||
itemFile = append(itemFile, fileNames[:len(fileNames)-1]...)
|
||||
return itemFile
|
||||
}
|
||||
sort.Slice(fileNames, func(i, j int) bool {
|
||||
@@ -412,6 +496,47 @@ func loadSSHData(command string, showCountFrom, showCountTo, currentYear int, qq
|
||||
return datas, successCount, failedCount
|
||||
}
|
||||
|
||||
func loadSSHDataForAnalysis(analysisMap map[string]dto.SSHLogAnalysis, commandItem string) {
|
||||
stdout, err := cmd.Exec(commandItem)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
lines := strings.Split(string(stdout), "\n")
|
||||
for i := len(lines) - 1; i >= 0; i-- {
|
||||
var itemData dto.SSHHistory
|
||||
switch {
|
||||
case strings.Contains(lines[i], "Failed password for"):
|
||||
itemData = loadFailedSecureDatas(lines[i])
|
||||
case strings.Contains(lines[i], "Connection closed by authenticating user"):
|
||||
itemData = loadFailedAuthDatas(lines[i])
|
||||
case strings.Contains(lines[i], "Accepted "):
|
||||
itemData = loadSuccessDatas(lines[i])
|
||||
}
|
||||
if len(itemData.Address) != 0 {
|
||||
if val, ok := analysisMap[itemData.Address]; ok {
|
||||
if itemData.Status == constant.StatusSuccess {
|
||||
val.SuccessfulCount++
|
||||
} else {
|
||||
val.FailedCount++
|
||||
}
|
||||
analysisMap[itemData.Address] = val
|
||||
} else {
|
||||
item := dto.SSHLogAnalysis{
|
||||
Address: itemData.Address,
|
||||
SuccessfulCount: 0,
|
||||
FailedCount: 0,
|
||||
}
|
||||
if itemData.Status == constant.StatusSuccess {
|
||||
item.SuccessfulCount = 1
|
||||
} else {
|
||||
item.FailedCount = 1
|
||||
}
|
||||
analysisMap[itemData.Address] = item
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func loadSuccessDatas(line string) dto.SSHHistory {
|
||||
var data dto.SSHHistory
|
||||
parts := strings.Fields(line)
|
||||
|
||||
+104
-61
@@ -185,10 +185,57 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error)
|
||||
return err
|
||||
}
|
||||
defaultHttpPort := nginxInstall.HttpPort
|
||||
primaryDomainArray := strings.Split(create.PrimaryDomain, ":")
|
||||
primaryDomain := primaryDomainArray[0]
|
||||
|
||||
var (
|
||||
domains []model.WebsiteDomain
|
||||
ports = make(map[int]struct{})
|
||||
)
|
||||
domainArray := strings.Split(create.OtherDomains, "\n")
|
||||
domainArray = append(domainArray, create.PrimaryDomain)
|
||||
for _, domain := range domainArray {
|
||||
if domain == "" {
|
||||
continue
|
||||
}
|
||||
domainModel, err := getDomain(domain, defaultHttpPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if reflect.DeepEqual(domainModel, model.WebsiteDomain{}) {
|
||||
continue
|
||||
}
|
||||
domains = append(domains, domainModel)
|
||||
if domainModel.Port != defaultHttpPort {
|
||||
ports[domainModel.Port] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
for port := range ports {
|
||||
if existPorts, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithPort(port)); len(existPorts) == 0 {
|
||||
errMap := make(map[string]interface{})
|
||||
errMap["port"] = port
|
||||
appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithPort(port))
|
||||
if appInstall.ID > 0 {
|
||||
errMap["type"] = i18n.GetMsgByKey("TYPE_APP")
|
||||
errMap["name"] = appInstall.Name
|
||||
return buserr.WithMap("ErrPortExist", errMap, nil)
|
||||
}
|
||||
runtime, _ := runtimeRepo.GetFirst(runtimeRepo.WithPort(port))
|
||||
if runtime != nil {
|
||||
errMap["type"] = i18n.GetMsgByKey("TYPE_RUNTIME")
|
||||
errMap["name"] = runtime.Name
|
||||
return buserr.WithMap("ErrPortExist", errMap, nil)
|
||||
}
|
||||
if common.ScanPort(create.Port) {
|
||||
return buserr.WithDetail(constant.ErrPortInUsed, create.Port, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaultDate, _ := time.Parse(constant.DateLayout, constant.DefaultDate)
|
||||
website := &model.Website{
|
||||
PrimaryDomain: create.PrimaryDomain,
|
||||
PrimaryDomain: primaryDomain,
|
||||
Type: create.Type,
|
||||
Alias: create.Alias,
|
||||
Remark: create.Remark,
|
||||
@@ -261,61 +308,46 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error)
|
||||
return err
|
||||
}
|
||||
website.RuntimeID = runtime.ID
|
||||
if runtime.Resource == constant.ResourceAppstore {
|
||||
var (
|
||||
req request.AppInstallCreate
|
||||
nginxInstall model.AppInstall
|
||||
install *model.AppInstall
|
||||
)
|
||||
reg, _ := regexp.Compile(`[^a-z0-9_-]+`)
|
||||
req.Name = reg.ReplaceAllString(strings.ToLower(create.PrimaryDomain), "")
|
||||
req.AppDetailId = create.AppInstall.AppDetailId
|
||||
req.Params = create.AppInstall.Params
|
||||
req.Params["IMAGE_NAME"] = runtime.Image
|
||||
req.AppContainerConfig = create.AppInstall.AppContainerConfig
|
||||
nginxInstall, err = getAppInstallByKey(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return err
|
||||
switch runtime.Type {
|
||||
case constant.RuntimePHP:
|
||||
if runtime.Resource == constant.ResourceAppstore {
|
||||
var (
|
||||
req request.AppInstallCreate
|
||||
install *model.AppInstall
|
||||
)
|
||||
reg, _ := regexp.Compile(`[^a-z0-9_-]+`)
|
||||
req.Name = reg.ReplaceAllString(strings.ToLower(create.PrimaryDomain), "")
|
||||
req.AppDetailId = create.AppInstall.AppDetailId
|
||||
req.Params = create.AppInstall.Params
|
||||
req.Params["IMAGE_NAME"] = runtime.Image
|
||||
req.AppContainerConfig = create.AppInstall.AppContainerConfig
|
||||
req.Params["PANEL_WEBSITE_DIR"] = path.Join(nginxInstall.GetPath(), "/www")
|
||||
tx, installCtx := getTxAndContext()
|
||||
install, err = NewIAppService().Install(installCtx, req)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
tx.Commit()
|
||||
website.AppInstallID = install.ID
|
||||
appInstall = install
|
||||
website.Proxy = fmt.Sprintf("127.0.0.1:%d", appInstall.HttpPort)
|
||||
} else {
|
||||
website.ProxyType = create.ProxyType
|
||||
if website.ProxyType == constant.RuntimeProxyUnix {
|
||||
proxy = fmt.Sprintf("unix:%s", path.Join("/www/sites", website.Alias, "php-pool", "php-fpm.sock"))
|
||||
}
|
||||
if website.ProxyType == constant.RuntimeProxyTcp {
|
||||
proxy = fmt.Sprintf("127.0.0.1:%d", create.Port)
|
||||
}
|
||||
website.Proxy = proxy
|
||||
}
|
||||
req.Params["PANEL_WEBSITE_DIR"] = path.Join(nginxInstall.GetPath(), "/www")
|
||||
tx, installCtx := getTxAndContext()
|
||||
install, err = NewIAppService().Install(installCtx, req)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
tx.Commit()
|
||||
website.AppInstallID = install.ID
|
||||
appInstall = install
|
||||
website.Proxy = fmt.Sprintf("127.0.0.1:%d", appInstall.HttpPort)
|
||||
} else {
|
||||
website.ProxyType = create.ProxyType
|
||||
if website.ProxyType == constant.RuntimeProxyUnix {
|
||||
proxy = fmt.Sprintf("unix:%s", path.Join("/www/sites", website.Alias, "php-pool", "php-fpm.sock"))
|
||||
}
|
||||
if website.ProxyType == constant.RuntimeProxyTcp {
|
||||
proxy = fmt.Sprintf("127.0.0.1:%d", create.Port)
|
||||
}
|
||||
website.Proxy = proxy
|
||||
case constant.RuntimeNode:
|
||||
website.Proxy = fmt.Sprintf("127.0.0.1:%d", runtime.Port)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var domains []model.WebsiteDomain
|
||||
domains = append(domains, model.WebsiteDomain{Domain: website.PrimaryDomain, Port: defaultHttpPort})
|
||||
otherDomainArray := strings.Split(create.OtherDomains, "\n")
|
||||
for _, domain := range otherDomainArray {
|
||||
if domain == "" {
|
||||
continue
|
||||
}
|
||||
domainModel, err := getDomain(domain, defaultHttpPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if reflect.DeepEqual(domainModel, model.WebsiteDomain{}) {
|
||||
continue
|
||||
}
|
||||
domains = append(domains, domainModel)
|
||||
}
|
||||
if err = configDefaultNginx(website, domains, appInstall, runtime); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -460,15 +492,21 @@ func (w WebsiteService) CreateWebsiteDomain(create request.WebsiteDomainCreate)
|
||||
return domainModel, err
|
||||
}
|
||||
|
||||
if existDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithPort(create.Port)); len(existDomains) == 0 {
|
||||
if existAppInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithPort(create.Port)); !reflect.DeepEqual(existAppInstall, model.AppInstall{}) {
|
||||
return domainModel, buserr.WithMap(constant.ErrPortInOtherApp, map[string]interface{}{"port": create.Port, "apps": existAppInstall.App.Name}, nil)
|
||||
}
|
||||
if common.ScanPort(create.Port) {
|
||||
return domainModel, buserr.WithDetail(constant.ErrPortInUsed, create.Port, nil)
|
||||
if create.Port != httpPort {
|
||||
if existPorts, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithPort(create.Port)); len(existPorts) == 0 {
|
||||
if existAppInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithPort(create.Port)); existAppInstall.ID > 0 {
|
||||
return domainModel, buserr.WithMap(constant.ErrPortInOtherApp, map[string]interface{}{"port": create.Port, "apps": existAppInstall.App.Name}, nil)
|
||||
}
|
||||
if common.ScanPort(create.Port) {
|
||||
return domainModel, buserr.WithDetail(constant.ErrPortInUsed, create.Port, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if existDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithDomain(create.Domain), websiteDomainRepo.WithPort(create.Port)); len(existDomains) > 0 {
|
||||
return domainModel, buserr.WithDetail(constant.ErrDomainIsExist, create.Domain, nil)
|
||||
}
|
||||
|
||||
website, err := websiteRepo.GetFirst(commonRepo.WithByID(create.WebsiteID))
|
||||
if err != nil {
|
||||
return domainModel, err
|
||||
@@ -476,7 +514,11 @@ func (w WebsiteService) CreateWebsiteDomain(create request.WebsiteDomainCreate)
|
||||
if oldDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(create.WebsiteID), websiteDomainRepo.WithPort(create.Port)); len(oldDomains) == 0 {
|
||||
ports = append(ports, create.Port)
|
||||
}
|
||||
domains = append(domains, create.Domain)
|
||||
|
||||
if oldDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(create.WebsiteID), websiteDomainRepo.WithDomain(create.Domain)); len(oldDomains) == 0 {
|
||||
domains = append(domains, create.Domain)
|
||||
}
|
||||
|
||||
if err := addListenAndServerName(website, ports, domains); err != nil {
|
||||
return domainModel, err
|
||||
}
|
||||
@@ -955,10 +997,11 @@ func (w WebsiteService) OpWebsiteLog(req request.WebsiteLogReq) (*response.Websi
|
||||
}
|
||||
var nginxParams []dto.NginxParam
|
||||
nginxParams = append(nginxParams, dto.NginxParam{
|
||||
Name: key,
|
||||
Name: key,
|
||||
Params: []string{"off"},
|
||||
})
|
||||
|
||||
if err := deleteNginxConfig(constant.NginxScopeServer, nginxParams, &website); err != nil {
|
||||
if err := updateNginxConfig(constant.NginxScopeServer, nginxParams, &website); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := websiteRepo.Save(context.Background(), &website); err != nil {
|
||||
|
||||
@@ -135,7 +135,9 @@ func (w WebsiteSSLService) Create(create request.WebsiteSSLCreate) (request.Webs
|
||||
return res, err
|
||||
}
|
||||
|
||||
websiteSSL.DnsAccountID = create.DnsAccountID
|
||||
if create.Provider == constant.DNSAccount {
|
||||
websiteSSL.DnsAccountID = create.DnsAccountID
|
||||
}
|
||||
websiteSSL.AcmeAccountID = acmeAccount.ID
|
||||
websiteSSL.Provider = create.Provider
|
||||
websiteSSL.Domains = strings.Join(otherDomainArray, ",")
|
||||
|
||||
@@ -154,7 +154,7 @@ func createWebsiteFolder(nginxInstall model.AppInstall, website *model.Website,
|
||||
}
|
||||
}
|
||||
}
|
||||
if website.Type == constant.Static || website.Type == constant.Runtime {
|
||||
if website.Type == constant.Static || (website.Type == constant.Runtime && runtime.Type == constant.RuntimePHP) {
|
||||
if err := createIndexFile(website, runtime); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -216,20 +216,22 @@ func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, a
|
||||
nginxInclude := fmt.Sprintf("/www/sites/%s/proxy/*.conf", website.Alias)
|
||||
server.UpdateDirective("include", []string{nginxInclude})
|
||||
case constant.Runtime:
|
||||
if runtime.Resource == constant.ResourceLocal {
|
||||
switch runtime.Type {
|
||||
case constant.RuntimePHP:
|
||||
server.UpdateRoot(rootIndex)
|
||||
localPath := path.Join(nginxInstall.GetPath(), rootIndex, "index.php")
|
||||
server.UpdatePHPProxy([]string{website.Proxy}, localPath)
|
||||
}
|
||||
}
|
||||
if runtime.Resource == constant.ResourceAppstore {
|
||||
switch runtime.Type {
|
||||
case constant.RuntimePHP:
|
||||
switch runtime.Type {
|
||||
case constant.RuntimePHP:
|
||||
if runtime.Resource == constant.ResourceLocal {
|
||||
switch runtime.Type {
|
||||
case constant.RuntimePHP:
|
||||
server.UpdateRoot(rootIndex)
|
||||
localPath := path.Join(nginxInstall.GetPath(), rootIndex, "index.php")
|
||||
server.UpdatePHPProxy([]string{website.Proxy}, localPath)
|
||||
}
|
||||
} else {
|
||||
server.UpdateRoot(rootIndex)
|
||||
server.UpdatePHPProxy([]string{website.Proxy}, "")
|
||||
}
|
||||
case constant.RuntimeNode:
|
||||
proxy := fmt.Sprintf("http://127.0.0.1:%d", runtime.Port)
|
||||
server.UpdateRootProxy([]string{proxy})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,6 @@ var (
|
||||
var (
|
||||
ErrPortInUsed = "ErrPortInUsed"
|
||||
ErrAppLimit = "ErrAppLimit"
|
||||
ErrFileToLarge = "ErrFileToLarge"
|
||||
ErrFileCanNotRead = "ErrFileCanNotRead"
|
||||
ErrNotInstall = "ErrNotInstall"
|
||||
ErrPortInOtherApp = "ErrPortInOtherApp"
|
||||
@@ -60,6 +59,7 @@ var (
|
||||
ErrFileParse = "ErrFileParse"
|
||||
ErrInstallDirNotFound = "ErrInstallDirNotFound"
|
||||
ErrContainerName = "ErrContainerName"
|
||||
ErrAppNameExist = "ErrAppNameExist"
|
||||
)
|
||||
|
||||
// website
|
||||
@@ -114,11 +114,14 @@ var (
|
||||
|
||||
// runtime
|
||||
var (
|
||||
ErrDirNotFound = "ErrDirNotFound"
|
||||
ErrFileNotExist = "ErrFileNotExist"
|
||||
ErrImageBuildErr = "ErrImageBuildErr"
|
||||
ErrImageExist = "ErrImageExist"
|
||||
ErrDelWithWebsite = "ErrDelWithWebsite"
|
||||
ErrDirNotFound = "ErrDirNotFound"
|
||||
ErrFileNotExist = "ErrFileNotExist"
|
||||
ErrImageBuildErr = "ErrImageBuildErr"
|
||||
ErrImageExist = "ErrImageExist"
|
||||
ErrDelWithWebsite = "ErrDelWithWebsite"
|
||||
ErrRuntimeStart = "ErrRuntimeStart"
|
||||
ErrPackageJsonNotFound = "ErrPackageJsonNotFound"
|
||||
ErrScriptsNotFound = "ErrScriptsNotFound"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -126,3 +129,7 @@ var (
|
||||
ErrOSSConn = "ErrOSSConn"
|
||||
ErrEntrance = "ErrEntrance"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrFirewall = "ErrFirewall"
|
||||
)
|
||||
|
||||
@@ -4,12 +4,30 @@ const (
|
||||
ResourceLocal = "local"
|
||||
ResourceAppstore = "appstore"
|
||||
|
||||
RuntimeNormal = "normal"
|
||||
RuntimeError = "error"
|
||||
RuntimeBuildIng = "building"
|
||||
RuntimeNormal = "normal"
|
||||
RuntimeError = "error"
|
||||
RuntimeBuildIng = "building"
|
||||
RuntimeStarting = "starting"
|
||||
RuntimeRunning = "running"
|
||||
RuntimeReCreating = "recreating"
|
||||
RuntimeStopped = "stopped"
|
||||
RuntimeUnhealthy = "unhealthy"
|
||||
RuntimeCreating = "creating"
|
||||
|
||||
RuntimePHP = "php"
|
||||
RuntimePHP = "php"
|
||||
RuntimeNode = "node"
|
||||
|
||||
RuntimeProxyUnix = "unix"
|
||||
RuntimeProxyTcp = "tcp"
|
||||
|
||||
RuntimeUp = "up"
|
||||
RuntimeDown = "down"
|
||||
RuntimeRestart = "restart"
|
||||
|
||||
RuntimeInstall = "install"
|
||||
RuntimeUninstall = "uninstall"
|
||||
RuntimeUpdate = "update"
|
||||
|
||||
RuntimeNpm = "npm"
|
||||
RuntimeYarn = "yarn"
|
||||
)
|
||||
|
||||
@@ -14,6 +14,10 @@ ErrNameIsExist: "Name is already exist"
|
||||
ErrDemoEnvironment: "Demo server, prohibit this operation!"
|
||||
ErrCmdTimeout: "Command execution timed out!"
|
||||
ErrCmdIllegal: "The command contains illegal characters. Please modify and try again!"
|
||||
ErrPortExist: '{{ .port }} port is already occupied by {{ .type }} [{{ .name }}]'
|
||||
TYPE_APP: "Application"
|
||||
TYPE_RUNTIME: "Runtime environment"
|
||||
TYPE_DOMAIN: "Domain name"
|
||||
|
||||
#app
|
||||
ErrPortInUsed: "{{ .detail }} port already in use"
|
||||
@@ -47,6 +51,7 @@ ErrContainerMsg: '{{ .name }} container is abnormal, please check the log on the
|
||||
ErrAppBackup: '{{ .name }} application backup failed err {{.err}}'
|
||||
ErrImagePull: '{{ .name }} image pull failed err {{.err}}'
|
||||
ErrVersionTooLow: 'The current 1Panel version is too low to update the app store, please upgrade the version'
|
||||
ErrAppNameExist: 'App name is already exist'
|
||||
|
||||
#file
|
||||
ErrFileCanNotRead: "File can not read"
|
||||
@@ -99,6 +104,11 @@ ErrFileNotExist: "{{ .detail }} file does not exist! Please check source file in
|
||||
ErrImageBuildErr: "Image build failed"
|
||||
ErrImageExist: "Image is already exist!"
|
||||
ErrDelWithWebsite: "The operating environment has been associated with a website and cannot be deleted"
|
||||
ErrRuntimeStart: "Failed to start"
|
||||
ErrPackageJsonNotFound: "package.json file does not exist"
|
||||
ErrScriptsNotFound: "No scripts configuration item was found in package.json"
|
||||
ErrContainerNameNotFound: "Unable to get container name, please check .env file"
|
||||
ErrNodeModulesNotFound: "The node_modules folder does not exist! Please edit the running environment or wait for the running environment to start successfully"
|
||||
|
||||
#setting
|
||||
ErrBackupInUsed: "The backup account is already being used in a cronjob and cannot be deleted."
|
||||
@@ -111,4 +121,7 @@ ErrConfigParse: "Configuration file format error"
|
||||
ErrConfigIsNull: "The configuration file is not allowed to be empty"
|
||||
ErrConfigDirNotFound: "The running directory does not exist"
|
||||
ErrConfigAlreadyExist: "A configuration file with the same name already exists"
|
||||
ErrUserFindErr: "Failed to find user {{ .name }} {{ .err }}"
|
||||
ErrUserFindErr: "Failed to find user {{ .name }} {{ .err }}"
|
||||
|
||||
#ssh
|
||||
ErrFirewall: "No firewalld or ufw service is detected. Please check and try again!"
|
||||
@@ -14,6 +14,10 @@ ErrNameIsExist: "名稱已存在"
|
||||
ErrDemoEnvironment: "演示伺服器,禁止此操作!"
|
||||
ErrCmdTimeout: "指令執行超時!"
|
||||
ErrCmdIllegal: "執行命令中存在不合法字符,請修改後重試!"
|
||||
ErrPortExist: '{{ .port }} 埠已被 {{ .type }} [{{ .name }}] 佔用'
|
||||
TYPE_APP: "應用"
|
||||
TYPE_RUNTIME: "運作環境"
|
||||
TYPE_DOMAIN: "網域名稱"
|
||||
|
||||
#app
|
||||
ErrPortInUsed: "{{ .detail }} 端口已被佔用!"
|
||||
@@ -47,6 +51,7 @@ ErrContainerMsg: '{{ .name }} 容器異常,具體請在容器頁面查看日
|
||||
ErrAppBackup: '{{ .name }} 應用備份失敗 err {{.err}}'
|
||||
ErrImagePull: '{{ .name }} 鏡像拉取失敗 err {{.err}}'
|
||||
ErrVersionTooLow: '當前 1Panel 版本過低,無法更新應用商店,請升級版本之後操作'
|
||||
ErrAppNameExist: '應用名稱已存在'
|
||||
|
||||
#file
|
||||
ErrFileCanNotRead: "此文件不支持預覽"
|
||||
@@ -99,6 +104,11 @@ ErrFileNotExist: "{{ .detail }} 文件不存在!請檢查源文件完整性!
|
||||
ErrImageBuildErr: "鏡像 build 失敗"
|
||||
ErrImageExist: "鏡像已存在!"
|
||||
ErrDelWithWebsite: "運行環境已經關聯網站,無法刪除"
|
||||
ErrRuntimeStart: "啟動失敗"
|
||||
ErrPackageJsonNotFound: "package.json 文件不存在"
|
||||
ErrScriptsNotFound: "沒有在 package.json 中找到 scripts 配置項"
|
||||
ErrContainerNameNotFound: "無法取得容器名稱,請檢查 .env 文件"
|
||||
ErrNodeModulesNotFound: "node_modules 文件夾不存在!請編輯運行環境或者等待運行環境啟動成功"
|
||||
|
||||
#setting
|
||||
ErrBackupInUsed: "該備份帳號已在計劃任務中使用,無法刪除"
|
||||
@@ -112,3 +122,6 @@ ErrConfigIsNull: "配置文件不允許為空"
|
||||
ErrConfigDirNotFound: "運行目錄不存在"
|
||||
ErrConfigAlreadyExist: "已存在同名配置文件"
|
||||
ErrUserFindErr: "用戶 {{ .name }} 查找失敗 {{ .err }}"
|
||||
|
||||
#ssh
|
||||
ErrFirewall: "當前未檢測到系統 firewalld 或 ufw 服務,請檢查後重試!"
|
||||
@@ -14,6 +14,10 @@ ErrNameIsExist: "名称已存在"
|
||||
ErrDemoEnvironment: "演示服务器,禁止此操作!"
|
||||
ErrCmdTimeout: "命令执行超时!"
|
||||
ErrCmdIllegal: "执行命令中存在不合法字符,请修改后重试!"
|
||||
ErrPortExist: '{{ .port }} 端口已被 {{ .type }} [{{ .name }}] 占用'
|
||||
TYPE_APP: "应用"
|
||||
TYPE_RUNTIME: "运行环境"
|
||||
TYPE_DOMAIN: "域名"
|
||||
|
||||
#app
|
||||
ErrPortInUsed: "{{ .detail }} 端口已被占用!"
|
||||
@@ -47,6 +51,7 @@ ErrContainerMsg: '{{ .name }} 容器异常,具体请在容器页面查看日
|
||||
ErrAppBackup: '{{ .name }} 应用备份失败 err {{.err}}'
|
||||
ErrImagePull: '镜像拉取失败 {{.err}}'
|
||||
ErrVersionTooLow: '当前 1Panel 版本过低,无法更新应用商店,请升级版本之后操作'
|
||||
ErrAppNameExist: '应用名称已存在'
|
||||
|
||||
#file
|
||||
ErrFileCanNotRead: "此文件不支持预览"
|
||||
@@ -99,6 +104,11 @@ ErrFileNotExist: "{{ .detail }} 文件不存在!请检查源文件完整性!
|
||||
ErrImageBuildErr: "镜像 build 失败"
|
||||
ErrImageExist: "镜像已存在!"
|
||||
ErrDelWithWebsite: "运行环境已经关联网站,无法删除"
|
||||
ErrRuntimeStart: "启动失败"
|
||||
ErrPackageJsonNotFound: "package.json 文件不存在"
|
||||
ErrScriptsNotFound: "没有在 package.json 中找到 scripts 配置项"
|
||||
ErrContainerNameNotFound: "无法获取容器名称,请检查 .env 文件"
|
||||
ErrNodeModulesNotFound: "node_modules 文件夹不存在!请编辑运行环境或者等待运行环境启动成功"
|
||||
|
||||
#setting
|
||||
ErrBackupInUsed: "该备份账号已在计划任务中使用,无法删除"
|
||||
@@ -112,3 +122,6 @@ ErrConfigIsNull: "配置文件不允许为空"
|
||||
ErrConfigDirNotFound: "运行目录不存在"
|
||||
ErrConfigAlreadyExist: "已存在同名配置文件"
|
||||
ErrUserFindErr: "用户 {{ .name }} 查找失败 {{ .err }}"
|
||||
|
||||
#ssh
|
||||
ErrFirewall: "当前未检测到系统 firewalld 或 ufw 服务,请检查后重试!"
|
||||
|
||||
@@ -6,26 +6,15 @@ import (
|
||||
)
|
||||
|
||||
func Init() {
|
||||
syncApp()
|
||||
syncInstalledApp()
|
||||
go syncApp()
|
||||
go syncInstalledApp()
|
||||
}
|
||||
|
||||
func syncApp() {
|
||||
setting, err := service.NewISettingService().GetSettingInfo()
|
||||
if err != nil {
|
||||
global.LOG.Errorf("sync app error: %s", err.Error())
|
||||
return
|
||||
}
|
||||
if setting.AppStoreLastModified != "0" {
|
||||
global.LOG.Info("no need to sync")
|
||||
return
|
||||
}
|
||||
global.LOG.Info("sync app start...")
|
||||
if err := service.NewIAppService().SyncAppListFromRemote(); err != nil {
|
||||
global.LOG.Errorf("sync app error")
|
||||
global.LOG.Errorf("App Store synchronization failed")
|
||||
return
|
||||
}
|
||||
global.LOG.Info("sync app successful")
|
||||
}
|
||||
|
||||
func syncInstalledApp() {
|
||||
|
||||
@@ -43,6 +43,10 @@ func Init() {
|
||||
migrations.UpdateDatabase,
|
||||
migrations.UpdateAppInstallResource,
|
||||
migrations.DropDatabaseLocal,
|
||||
|
||||
migrations.AddDefaultNetwork,
|
||||
migrations.UpdateRuntime,
|
||||
migrations.UpdateTag,
|
||||
})
|
||||
if err := m.Migrate(); err != nil {
|
||||
global.LOG.Error(err)
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var AddDefaultNetwork = &gormigrate.Migration{
|
||||
ID: "20230928-add-default-network",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.Create(&model.Setting{Key: "DefaultNetwork", Value: "all"}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Create(&model.Setting{Key: "LastCleanTime", Value: ""}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Create(&model.Setting{Key: "LastCleanSize", Value: ""}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Create(&model.Setting{Key: "LastCleanData", Value: ""}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var UpdateRuntime = &gormigrate.Migration{
|
||||
ID: "20230927-update-runtime",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.AutoMigrate(&model.Runtime{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var UpdateTag = &gormigrate.Migration{
|
||||
ID: "20231008-update-tag",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.AutoMigrate(&model.Tag{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var whiteUrlList = map[string]struct{}{
|
||||
@@ -18,6 +19,14 @@ var whiteUrlList = map[string]struct{}{
|
||||
"/api/v1/logs/operation": {},
|
||||
"/api/v1/logs/login": {},
|
||||
"/api/v1/auth/logout": {},
|
||||
|
||||
"/api/v1/apps/installed/loadport": {},
|
||||
"/api/v1/apps/installed/check": {},
|
||||
"/api/v1/apps/installed/conninfo": {},
|
||||
"/api/v1/databases/load/file": {},
|
||||
"/api/v1/databases/variables": {},
|
||||
"/api/v1/databases/status": {},
|
||||
"/api/v1/databases/baseinfo": {},
|
||||
}
|
||||
|
||||
func DemoHandle() gin.HandlerFunc {
|
||||
|
||||
@@ -2,11 +2,13 @@ package middleware
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@@ -25,7 +27,10 @@ func WhiteAllow() gin.HandlerFunc {
|
||||
}
|
||||
clientIP := c.ClientIP()
|
||||
for _, ip := range strings.Split(status.Value, ",") {
|
||||
if len(ip) != 0 && ip == clientIP {
|
||||
if len(ip) == 0 {
|
||||
continue
|
||||
}
|
||||
if ip == clientIP || (strings.Contains(ip, "/") && checkIpInCidr(ip, clientIP)) {
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
@@ -33,3 +38,26 @@ func WhiteAllow() gin.HandlerFunc {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrIP, constant.ErrTypeInternalServer, errors.New("IP address not allowed"))
|
||||
}
|
||||
}
|
||||
|
||||
func checkIpInCidr(cidr, checkIP string) bool {
|
||||
ip, ipNet, err := net.ParseCIDR(cidr)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("parse CIDR %s failed, err: %v", cidr, err)
|
||||
return false
|
||||
}
|
||||
for ip := ip.Mask(ipNet.Mask); ipNet.Contains(ip); incIP(ip) {
|
||||
if ip.String() == checkIP {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func incIP(ip net.IP) {
|
||||
for j := len(ip) - 1; j >= 0; j-- {
|
||||
ip[j]++
|
||||
if ip[j] > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,8 +90,8 @@ func OperationLog() gin.HandlerFunc {
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(operationDic.BeforeFuntions) != 0 {
|
||||
for _, funcs := range operationDic.BeforeFuntions {
|
||||
if len(operationDic.BeforeFunctions) != 0 {
|
||||
for _, funcs := range operationDic.BeforeFunctions {
|
||||
for key, value := range formatMap {
|
||||
if funcs.InputValue == key {
|
||||
var names []string
|
||||
@@ -109,9 +109,9 @@ func OperationLog() gin.HandlerFunc {
|
||||
}
|
||||
for key, value := range formatMap {
|
||||
if strings.Contains(operationDic.FormatEN, "["+key+"]") {
|
||||
if arrys, ok := value.([]string); ok {
|
||||
operationDic.FormatZH = strings.ReplaceAll(operationDic.FormatZH, "["+key+"]", fmt.Sprintf("[%v]", strings.Join(arrys, ",")))
|
||||
operationDic.FormatEN = strings.ReplaceAll(operationDic.FormatEN, "["+key+"]", fmt.Sprintf("[%v]", strings.Join(arrys, ",")))
|
||||
if arrays, ok := value.([]string); ok {
|
||||
operationDic.FormatZH = strings.ReplaceAll(operationDic.FormatZH, "["+key+"]", fmt.Sprintf("[%v]", strings.Join(arrays, ",")))
|
||||
operationDic.FormatEN = strings.ReplaceAll(operationDic.FormatEN, "["+key+"]", fmt.Sprintf("[%v]", strings.Join(arrays, ",")))
|
||||
} else {
|
||||
operationDic.FormatZH = strings.ReplaceAll(operationDic.FormatZH, "["+key+"]", fmt.Sprintf("[%v]", value))
|
||||
operationDic.FormatEN = strings.ReplaceAll(operationDic.FormatEN, "["+key+"]", fmt.Sprintf("[%v]", value))
|
||||
@@ -171,13 +171,13 @@ type swaggerJson struct {
|
||||
}
|
||||
|
||||
type operationJson struct {
|
||||
API string `json:"api"`
|
||||
Method string `json:"method"`
|
||||
BodyKeys []string `json:"bodyKeys"`
|
||||
ParamKeys []string `json:"paramKeys"`
|
||||
BeforeFuntions []functionInfo `json:"beforeFuntions"`
|
||||
FormatZH string `json:"formatZH"`
|
||||
FormatEN string `json:"formatEN"`
|
||||
API string `json:"api"`
|
||||
Method string `json:"method"`
|
||||
BodyKeys []string `json:"bodyKeys"`
|
||||
ParamKeys []string `json:"paramKeys"`
|
||||
BeforeFunctions []functionInfo `json:"beforeFunctions"`
|
||||
FormatZH string `json:"formatZH"`
|
||||
FormatEN string `json:"formatEN"`
|
||||
}
|
||||
type functionInfo struct {
|
||||
InputColumn string `json:"input_column"`
|
||||
@@ -208,9 +208,9 @@ func loadLogInfo(path string) string {
|
||||
if !strings.Contains(path, "/") {
|
||||
return ""
|
||||
}
|
||||
pathArrys := strings.Split(path, "/")
|
||||
if len(pathArrys) < 2 {
|
||||
pathArrays := strings.Split(path, "/")
|
||||
if len(pathArrays) < 2 {
|
||||
return ""
|
||||
}
|
||||
return pathArrys[1]
|
||||
return pathArrays[1]
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ func (s *ContainerRouter) InitContainerRouter(Router *gin.RouterGroup) {
|
||||
baRouter.POST("/list", baseApi.ListContainer)
|
||||
baRouter.GET("/list/stats", baseApi.ContainerListStats)
|
||||
baRouter.GET("/search/log", baseApi.ContainerLogs)
|
||||
baRouter.GET("/limit", baseApi.LoadResouceLimit)
|
||||
baRouter.GET("/limit", baseApi.LoadResourceLimit)
|
||||
baRouter.POST("/clean/log", baseApi.CleanContainerLog)
|
||||
baRouter.POST("/load/log", baseApi.LoadContainerLog)
|
||||
baRouter.POST("/inspect", baseApi.Inspect)
|
||||
@@ -45,6 +45,7 @@ func (s *ContainerRouter) InitContainerRouter(Router *gin.RouterGroup) {
|
||||
baRouter.POST("/compose/test", baseApi.TestCompose)
|
||||
baRouter.POST("/compose/operate", baseApi.OperatorCompose)
|
||||
baRouter.POST("/compose/update", baseApi.ComposeUpdate)
|
||||
baRouter.GET("/compose/search/log", baseApi.ComposeLogs)
|
||||
|
||||
baRouter.GET("/template", baseApi.ListComposeTemplate)
|
||||
baRouter.POST("/template/search", baseApi.SearchComposeTemplate)
|
||||
|
||||
@@ -49,6 +49,7 @@ func (s *DatabaseRouter) InitDatabaseRouter(Router *gin.RouterGroup) {
|
||||
cmdRouter.GET("/db/list/:type", baseApi.ListDatabase)
|
||||
cmdRouter.POST("/db/update", baseApi.UpdateDatabase)
|
||||
cmdRouter.POST("/db/search", baseApi.SearchDatabase)
|
||||
cmdRouter.POST("/db/del/check", baseApi.DeleteCheckDatabase)
|
||||
cmdRouter.POST("/db/del", baseApi.DeleteDatabase)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ func (s *HostRouter) InitHostRouter(Router *gin.RouterGroup) {
|
||||
hostRouter.POST("/ssh/generate", baseApi.GenerateSSH)
|
||||
hostRouter.POST("/ssh/secret", baseApi.LoadSSHSecret)
|
||||
hostRouter.POST("/ssh/log", baseApi.LoadSSHLogs)
|
||||
hostRouter.POST("/ssh/log/analysis", baseApi.AnalysisLog)
|
||||
hostRouter.POST("/ssh/conffile/update", baseApi.UpdateSSHByfile)
|
||||
hostRouter.POST("/ssh/operate", baseApi.OperateSSH)
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ func (s *LogRouter) InitLogRouter(Router *gin.RouterGroup) {
|
||||
operationRouter.POST("/login", baseApi.GetLoginLogs)
|
||||
operationRouter.POST("/operation", baseApi.GetOperationLogs)
|
||||
operationRouter.POST("/clean", baseApi.CleanLogs)
|
||||
operationRouter.GET("/system", baseApi.GetSystemLogs)
|
||||
|
||||
operationRouter.GET("/system/files", baseApi.GetSystemFiles)
|
||||
operationRouter.POST("/system", baseApi.GetSystemLogs)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,5 +20,10 @@ func (r *RuntimeRouter) InitRuntimeRouter(Router *gin.RouterGroup) {
|
||||
groupRouter.POST("/del", baseApi.DeleteRuntime)
|
||||
groupRouter.POST("/update", baseApi.UpdateRuntime)
|
||||
groupRouter.GET("/:id", baseApi.GetRuntime)
|
||||
groupRouter.POST("/node/package", baseApi.GetNodePackageRunScript)
|
||||
groupRouter.POST("/operate", baseApi.OperateRuntime)
|
||||
groupRouter.POST("/node/modules", baseApi.GetNodeModules)
|
||||
groupRouter.POST("/node/modules/operate", baseApi.OperateNodeModules)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,8 +30,10 @@ func (s *SettingRouter) InitSettingRouter(Router *gin.RouterGroup) {
|
||||
settingRouter.GET("/time/option", baseApi.LoadTimeZone)
|
||||
settingRouter.POST("/time/sync", baseApi.SyncTime)
|
||||
settingRouter.POST("/monitor/clean", baseApi.CleanMonitor)
|
||||
settingRouter.GET("/mfa/:interval", baseApi.GetMFA)
|
||||
settingRouter.POST("/mfa", baseApi.LoadMFA)
|
||||
settingRouter.POST("/mfa/bind", baseApi.MFABind)
|
||||
settingRouter.POST("/scan", baseApi.ScanSystem)
|
||||
settingRouter.POST("/clean", baseApi.SystemClean)
|
||||
|
||||
settingRouter.POST("/snapshot", baseApi.CreateSnapshot)
|
||||
settingRouter.POST("/snapshot/status", baseApi.LoadSnapShotStatus)
|
||||
|
||||
@@ -68,6 +68,18 @@ func ExecWithTimeOut(cmdStr string, timeout time.Duration) (string, error) {
|
||||
return stdout.String(), nil
|
||||
}
|
||||
|
||||
func ExecContainerScript(containerName, cmdStr string, timeout time.Duration) error {
|
||||
cmdStr = fmt.Sprintf("docker exec -i %s bash -c '%s'", containerName, cmdStr)
|
||||
out, err := ExecWithTimeOut(cmdStr, timeout)
|
||||
if err != nil {
|
||||
if out != "" {
|
||||
return fmt.Errorf("%s; err: %v", out, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ExecCronjobWithTimeOut(cmdStr string, workdir string, timeout time.Duration) (string, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
|
||||
@@ -80,6 +80,10 @@ func (c Client) DeleteImage(imageID string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c Client) InspectContainer(containerID string) (types.ContainerJSON, error) {
|
||||
return c.cli.ContainerInspect(context.Background(), containerID)
|
||||
}
|
||||
|
||||
func (c Client) PullImage(imageName string, force bool) error {
|
||||
if !force {
|
||||
exist, err := c.CheckImageExist(imageName)
|
||||
|
||||
Vendored
+13
@@ -2,6 +2,7 @@ package env
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/joho/godotenv"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
@@ -37,3 +38,15 @@ func Marshal(envMap map[string]string) (string, error) {
|
||||
sort.Strings(lines)
|
||||
return strings.Join(lines, "\n"), nil
|
||||
}
|
||||
|
||||
func GetEnvValueByKey(envPath, key string) (string, error) {
|
||||
envMap, err := godotenv.Read(envPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
value, ok := envMap[key]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("key %s not found in %s", key, envPath)
|
||||
}
|
||||
return value, nil
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package firewall
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/firewall/client"
|
||||
)
|
||||
|
||||
@@ -30,5 +31,5 @@ func NewFirewallClient() (FirewallClient, error) {
|
||||
if _, err := os.Stat("/usr/sbin/ufw"); err == nil {
|
||||
return client.NewUfw()
|
||||
}
|
||||
return nil, errors.New("no such type")
|
||||
return nil, buserr.New(constant.ErrFirewall)
|
||||
}
|
||||
|
||||
@@ -7,8 +7,7 @@ type FireInfo struct {
|
||||
Protocol string `json:"protocol"` // tcp udp tcp/udp
|
||||
Strategy string `json:"strategy"` // accept drop
|
||||
|
||||
APPName string `json:"appName"`
|
||||
IsUsed bool `json:"isUsed"`
|
||||
UsedStatus string `json:"usedStatus"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user