mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-10-09 08:00:27 +00:00
Compare commits
116
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f9f4ae740 | ||
|
|
8bec6f2b28 | ||
|
|
b397363c9d | ||
|
|
acb800b505 | ||
|
|
ec37af2f18 | ||
|
|
d2b030e698 | ||
|
|
c6f496f2a5 | ||
|
|
722e1929f1 | ||
|
|
f9a20ec443 | ||
|
|
f5568d4874 | ||
|
|
87bbe4ee12 | ||
|
|
a034b03c1d | ||
|
|
470f4e4db7 | ||
|
|
9428efd8c0 | ||
|
|
bf4d91b68b | ||
|
|
781155b029 | ||
|
|
3caf0ac529 | ||
|
|
7d25228e55 | ||
|
|
4fb099912e | ||
|
|
b3350b54b3 | ||
|
|
cd4e0374d0 | ||
|
|
5d2084fda4 | ||
|
|
8c32fa3e6c | ||
|
|
fef13211a0 | ||
|
|
5ff5b0a5ad | ||
|
|
8ac9d022b6 | ||
|
|
2c02dc07e9 | ||
|
|
ba999c516a | ||
|
|
28303ffa82 | ||
|
|
1f9a3aa51a | ||
|
|
656dda234c | ||
|
|
63b62f4074 | ||
|
|
158180a052 | ||
|
|
dbe479e920 | ||
|
|
7aefa34871 | ||
|
|
7d92436b92 | ||
|
|
66a070c239 | ||
|
|
bb9d9042f0 | ||
|
|
a5d86d4c00 | ||
|
|
e867deb547 | ||
|
|
af15659d99 | ||
|
|
f63658db9e | ||
|
|
d4edf2f874 | ||
|
|
94f7d78cc9 | ||
|
|
5cede39e5c | ||
|
|
508ac2ae84 | ||
|
|
997b820a42 | ||
|
|
5de83985e3 | ||
|
|
c0220dbed0 | ||
|
|
2e9305b9b1 | ||
|
|
b18bdea1c9 | ||
|
|
25fb431163 | ||
|
|
ac43f00273 | ||
|
|
8ccf1fcbf3 | ||
|
|
b2803f574b | ||
|
|
bbc14bb723 | ||
|
|
e89311d5d4 | ||
|
|
b5e56c6b65 | ||
|
|
3d2023858c | ||
|
|
74b48a18be | ||
|
|
42f61f60fb | ||
|
|
e32a11910e | ||
|
|
dc9fdf897b | ||
|
|
35c946a064 | ||
|
|
747a0c45ee | ||
|
|
8e03b24b0c | ||
|
|
18c65c3096 | ||
|
|
3b306f990a | ||
|
|
92fa6552b1 | ||
|
|
a39dc33770 | ||
|
|
0a42d4942c | ||
|
|
8086d5cecb | ||
|
|
a6875614f6 | ||
|
|
6b061fa327 | ||
|
|
b416e6b6f1 | ||
|
|
ac1f49f8dd | ||
|
|
6ddee2649d | ||
|
|
fd14f53cb9 | ||
|
|
029e2210f5 | ||
|
|
69769e6203 | ||
|
|
2a21f194d3 | ||
|
|
e46d8c5812 | ||
|
|
938605a169 | ||
|
|
c3cc26a136 | ||
|
|
dda83b6307 | ||
|
|
48e2e01a57 | ||
|
|
d6b00967ca | ||
|
|
6d4c1f8e79 | ||
|
|
e88fe0ac2f | ||
|
|
496c0b50b4 | ||
|
|
9d73d74c63 | ||
|
|
7e4e12107a | ||
|
|
5b15de91e6 | ||
|
|
98b3dc9d7d | ||
|
|
c05e610b13 | ||
|
|
63f9368e26 | ||
|
|
3f47a6e701 | ||
|
|
d7c9b3b192 | ||
|
|
063ed23acb | ||
|
|
7c33dd9026 | ||
|
|
a853d8c869 | ||
|
|
4ddeb81972 | ||
|
|
4dd9f00637 | ||
|
|
49f3779fd2 | ||
|
|
7389aad122 | ||
|
|
bf095c677c | ||
|
|
fb929687d8 | ||
|
|
bddcf76fc3 | ||
|
|
9370bdb5ac | ||
|
|
ef6d8bb17b | ||
|
|
99c2eb04c9 | ||
|
|
d83b673c90 | ||
|
|
7498f3f66b | ||
|
|
147eda529c | ||
|
|
c1f0da4248 | ||
|
|
8656dada06 |
@@ -6,6 +6,7 @@ permissions:
|
||||
jobs:
|
||||
generic_handler:
|
||||
name: Add Labels to PR
|
||||
if: github.repository == '1Panel-dev/1Panel'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.23'
|
||||
go-version: '1.24'
|
||||
- name: Build Release
|
||||
uses: goreleaser/goreleaser-action@v6
|
||||
with:
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.23'
|
||||
go-version: '1.24'
|
||||
- name: Build Release
|
||||
uses: goreleaser/goreleaser-action@v6
|
||||
with:
|
||||
|
||||
@@ -8,6 +8,7 @@ on:
|
||||
jobs:
|
||||
sonarcloud:
|
||||
name: SonarCloud
|
||||
if: github.repository == '1Panel-dev/1Panel'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
@@ -2,6 +2,7 @@ name: Synchronize to Gitee
|
||||
on: [push]
|
||||
jobs:
|
||||
repo-sync:
|
||||
if: github.repository == '1Panel-dev/1Panel'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Mirror the Github organization repos to Gitee.
|
||||
|
||||
@@ -33,9 +33,6 @@ builds:
|
||||
- ppc64le
|
||||
- s390x
|
||||
- riscv64
|
||||
hooks:
|
||||
post:
|
||||
- ./ci/script.sh compress_binary {{ .Path }} {{ .Arch }}
|
||||
|
||||
- id: core
|
||||
dir: core
|
||||
@@ -59,9 +56,6 @@ builds:
|
||||
- ppc64le
|
||||
- s390x
|
||||
- riscv64
|
||||
hooks:
|
||||
post:
|
||||
- ./ci/script.sh compress_binary {{ .Path }} {{ .Arch }}
|
||||
|
||||
archives:
|
||||
- formats: [ 'tar.gz' ]
|
||||
|
||||
@@ -46,4 +46,4 @@ build_agent_on_darwin:
|
||||
|
||||
build_all: build_frontend build_core_on_linux build_agent_on_linux
|
||||
|
||||
build_on_local: clean_assets build_frontend build_core_on_darwin build_agent_on_darwin upx_bin
|
||||
build_on_local: clean_assets build_frontend build_core_on_darwin build_agent_on_darwin
|
||||
|
||||
+29
-1
@@ -1,6 +1,9 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
|
||||
@@ -26,7 +29,7 @@ func (b *BaseApi) SearchApp(c *gin.Context) {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, list)
|
||||
helper.SuccessWithDataGzipped(c, list)
|
||||
}
|
||||
|
||||
// @Tags App
|
||||
@@ -192,3 +195,28 @@ func (b *BaseApi) GetAppListUpdate(c *gin.Context) {
|
||||
}
|
||||
helper.SuccessWithData(c, res)
|
||||
}
|
||||
|
||||
// @Tags App
|
||||
// @Summary Get app icon by app_id
|
||||
// @Accept json
|
||||
// @Param appId path integer true "app id"
|
||||
// @Success 200 {file} file "app icon"
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /apps/icon/:appId [get]
|
||||
func (b *BaseApi) GetAppIcon(c *gin.Context) {
|
||||
appID, err := helper.GetIntParamByKey(c, "appID")
|
||||
if err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
iconBytes, err := appService.GetAppIcon(appID)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
c.Header("Content-Type", "image/png")
|
||||
c.Header("Cache-Control", "public, max-age=31536000, immutable")
|
||||
c.Header("Last-Modified", time.Now().UTC().Format(http.TimeFormat))
|
||||
c.Data(http.StatusOK, "image/png", iconBytes)
|
||||
}
|
||||
|
||||
@@ -263,6 +263,27 @@ func (b *BaseApi) ContainerListStats(c *gin.Context) {
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
||||
// @Summary Load container stats size
|
||||
// @Accept json
|
||||
// @Param request body dto.OperationWithName true "request"
|
||||
// @Success 200 {object} dto.ContainerItemStats
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/item/stats [post]
|
||||
func (b *BaseApi) ContainerItemStats(c *gin.Context) {
|
||||
var req dto.OperationWithName
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
data, err := containerService.ContainerItemStats(req)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
||||
// @Tags Container
|
||||
// @Summary Create container
|
||||
// @Accept json
|
||||
@@ -372,6 +393,28 @@ func (b *BaseApi) CleanContainerLog(c *gin.Context) {
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Container
|
||||
// @Summary Clean compose log
|
||||
// @Accept json
|
||||
// @Param request body dto.ComposeLogClean true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/compose/clean/log [post]
|
||||
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"清理容器编排 [name] 日志","formatEN":"clean compose [name] logs"}
|
||||
func (b *BaseApi) CleanComposeLog(c *gin.Context) {
|
||||
var req dto.ComposeLogClean
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := containerService.ComposeLogClean(req); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Container
|
||||
// @Summary Rename Container
|
||||
// @Accept json
|
||||
|
||||
@@ -37,7 +37,7 @@ func (b *BaseApi) LoadAppLauncher(c *gin.Context) {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, data)
|
||||
helper.SuccessWithDataGzipped(c, data)
|
||||
}
|
||||
|
||||
// @Tags Dashboard
|
||||
@@ -179,6 +179,28 @@ func (b *BaseApi) LoadDashboardCurrentInfo(c *gin.Context) {
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
||||
// @Tags Dashboard
|
||||
// @Summary Load top cpu processes
|
||||
// @Success 200 {Array} dto.Process
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /dashboard/current/top/cpu [get]
|
||||
func (b *BaseApi) LoadDashboardTopCPU(c *gin.Context) {
|
||||
data := dashboardService.LoadTopCPU()
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
||||
// @Tags Dashboard
|
||||
// @Summary Load top memory processes
|
||||
// @Success 200 {Array} dto.Process
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /dashboard/current/top/mem [get]
|
||||
func (b *BaseApi) LoadDashboardTopMem(c *gin.Context) {
|
||||
data := dashboardService.LoadTopMem()
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
||||
// @Tags Dashboard
|
||||
// @Summary System restart
|
||||
// @Accept json
|
||||
|
||||
@@ -195,21 +195,19 @@ func (b *BaseApi) SearchMysql(c *gin.Context) {
|
||||
}
|
||||
|
||||
// @Tags Database Mysql
|
||||
// @Summary List mysql database names
|
||||
// @Summary List mysql database format collation options
|
||||
// @Accept json
|
||||
// @Param request body dto.PageInfo true "request"
|
||||
// @Success 200 {array} dto.MysqlOption
|
||||
// @Param request body dto.OperationWithName true "request"
|
||||
// @Success 200 {array} dto.MysqlFormatCollationOption
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /databases/options [get]
|
||||
func (b *BaseApi) ListDBName(c *gin.Context) {
|
||||
list, err := mysqlService.ListDBOption()
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
// @Router /databases/format/options [post]
|
||||
func (b *BaseApi) ListDBFormatCollationOptions(c *gin.Context) {
|
||||
var req dto.OperationWithName
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithData(c, list)
|
||||
helper.SuccessWithData(c, mysqlService.LoadFormatOption(req))
|
||||
}
|
||||
|
||||
// @Tags Database Mysql
|
||||
|
||||
@@ -90,7 +90,7 @@ func (b *BaseApi) GetFileTree(c *gin.Context) {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, tree)
|
||||
helper.SuccessWithDataGzipped(c, tree)
|
||||
}
|
||||
|
||||
// @Tags File
|
||||
@@ -265,7 +265,11 @@ func (b *BaseApi) GetContent(c *gin.Context) {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, info)
|
||||
if info.Size > 2*1024 && info.Size < 5*1024*1024 {
|
||||
helper.SuccessWithDataGzipped(c, info)
|
||||
} else {
|
||||
helper.SuccessWithData(c, info)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags File
|
||||
@@ -521,9 +525,14 @@ func (b *BaseApi) Download(c *gin.Context) {
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
info, _ := file.Stat()
|
||||
info, err := file.Stat()
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
c.Header("Content-Length", strconv.FormatInt(info.Size(), 10))
|
||||
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(info.Name()))
|
||||
http.ServeContent(c.Writer, c.Request, info.Name(), info.ModTime(), file)
|
||||
@@ -841,7 +850,11 @@ func (b *BaseApi) ReadFileByLine(c *gin.Context) {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, res)
|
||||
if res.TotalLines > 100 {
|
||||
helper.SuccessWithDataGzipped(c, res)
|
||||
} else {
|
||||
helper.SuccessWithData(c, res)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags File
|
||||
|
||||
@@ -269,7 +269,7 @@ func (b *BaseApi) OperateFilterRule(c *gin.Context) {
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := iptablesService.OperateRule(req); err != nil {
|
||||
if err := iptablesService.OperateRule(req, true); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package helper
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"gorm.io/gorm"
|
||||
@@ -46,6 +50,42 @@ func SuccessWithData(ctx *gin.Context, data interface{}) {
|
||||
ctx.Abort()
|
||||
}
|
||||
|
||||
var gzipWriterPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return gzip.NewWriter(nil)
|
||||
},
|
||||
}
|
||||
|
||||
func SuccessWithDataGzipped(ctx *gin.Context, data interface{}) {
|
||||
if !strings.Contains(ctx.GetHeader("Accept-Encoding"), "gzip") {
|
||||
SuccessWithData(ctx, data)
|
||||
return
|
||||
}
|
||||
if data == nil {
|
||||
data = gin.H{}
|
||||
}
|
||||
res := dto.Response{
|
||||
Code: http.StatusOK,
|
||||
Data: data,
|
||||
}
|
||||
jsonBytes, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
ErrorWithDetail(ctx, http.StatusInternalServerError, "ErrInternalServer", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Header("Content-Encoding", "gzip")
|
||||
ctx.Header("Content-Type", "application/json; charset=utf-8")
|
||||
ctx.Status(http.StatusOK)
|
||||
|
||||
gz := gzipWriterPool.Get().(*gzip.Writer)
|
||||
gz.Reset(ctx.Writer)
|
||||
_, _ = gz.Write(jsonBytes)
|
||||
_ = gz.Close()
|
||||
gzipWriterPool.Put(gz)
|
||||
ctx.Abort()
|
||||
}
|
||||
|
||||
func Success(ctx *gin.Context) {
|
||||
res := dto.Response{
|
||||
Code: http.StatusOK,
|
||||
|
||||
@@ -28,6 +28,27 @@ func (b *BaseApi) LoadMonitor(c *gin.Context) {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithDataGzipped(c, data)
|
||||
}
|
||||
|
||||
// @Tags Monitor
|
||||
// @Summary Load monitor data
|
||||
// @Param request body dto.MonitorGPUSearch true "request"
|
||||
// @Success 200 {object} dto.dto.MonitorGPUData
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts/monitor/gpu/search [post]
|
||||
func (b *BaseApi) LoadGPUMonitor(c *gin.Context) {
|
||||
var req dto.MonitorGPUSearch
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
data, err := monitorService.LoadGPUMonitorData(req)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, data)
|
||||
}
|
||||
|
||||
@@ -105,3 +126,7 @@ func (b *BaseApi) GetIOOptions(c *gin.Context) {
|
||||
sort.Strings(options)
|
||||
helper.SuccessWithData(c, options)
|
||||
}
|
||||
|
||||
func (b *BaseApi) GetCPUOptions(c *gin.Context) {
|
||||
helper.SuccessWithData(c, monitorService.LoadGPUOptions())
|
||||
}
|
||||
|
||||
@@ -155,3 +155,24 @@ func (b *BaseApi) GetSettingByKey(c *gin.Context) {
|
||||
value := settingService.GetSettingByKey(key)
|
||||
helper.SuccessWithData(c, value)
|
||||
}
|
||||
|
||||
// @Tags System Setting
|
||||
// @Summary Save common description
|
||||
// @Accept json
|
||||
// @Param request body dto.CommonDescription true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /settings/description/save [post]
|
||||
func (b *BaseApi) SaveDescription(c *gin.Context) {
|
||||
var req dto.CommonDescription
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := settingService.SaveDescription(req); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
@@ -228,8 +228,8 @@ func wshandleError(ws *websocket.Conn, err error) bool {
|
||||
}
|
||||
|
||||
var upGrader = websocket.Upgrader{
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024 * 1024 * 10,
|
||||
ReadBufferSize: 4096,
|
||||
WriteBufferSize: 16384,
|
||||
CheckOrigin: func(r *http.Request) bool {
|
||||
return true
|
||||
},
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
@@ -9,6 +8,8 @@ import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
|
||||
@@ -34,7 +35,7 @@ func (b *BaseApi) PageWebsiteSSL(c *gin.Context) {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, dto.PageResult{
|
||||
helper.SuccessWithDataGzipped(c, dto.PageResult{
|
||||
Total: total,
|
||||
Items: accounts,
|
||||
})
|
||||
@@ -44,7 +45,7 @@ func (b *BaseApi) PageWebsiteSSL(c *gin.Context) {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, list)
|
||||
helper.SuccessWithDataGzipped(c, list)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ type AppDatabase struct {
|
||||
DbUser string `json:"PANEL_DB_USER"`
|
||||
Password string `json:"PANEL_DB_USER_PASSWORD"`
|
||||
DatabaseName string `json:"DATABASE_NAME"`
|
||||
Format string `json:"format"`
|
||||
Collation string `json:"collation"`
|
||||
}
|
||||
|
||||
type AuthParam struct {
|
||||
@@ -91,13 +93,13 @@ type AppProperty struct {
|
||||
Key string `json:"key"`
|
||||
Required []string `json:"Required"`
|
||||
CrossVersionUpdate bool `json:"crossVersionUpdate"`
|
||||
Limit int `json:"limit"`
|
||||
Recommend int `json:"recommend"`
|
||||
Limit int `json:"limit" yaml:"limit"`
|
||||
Recommend int `json:"recommend" yaml:"recommend"`
|
||||
Website string `json:"website"`
|
||||
Github string `json:"github"`
|
||||
Document string `json:"document"`
|
||||
Architectures []string `json:"architectures"`
|
||||
MemoryRequired int `json:"memoryRequired"`
|
||||
MemoryRequired int `json:"memoryRequired" yaml:"memoryRequired"`
|
||||
GpuSupport bool `json:"gpuSupport"`
|
||||
Version float64 `json:"version"`
|
||||
Deprecated float64 `json:"deprecated"`
|
||||
|
||||
+36
-23
@@ -31,15 +31,15 @@ type ContainerInfo struct {
|
||||
Network []string `json:"network"`
|
||||
Ports []string `json:"ports"`
|
||||
|
||||
SizeRw int64 `json:"sizeRw"`
|
||||
SizeRootFs int64 `json:"sizeRootFs"`
|
||||
|
||||
IsFromApp bool `json:"isFromApp"`
|
||||
IsFromCompose bool `json:"isFromCompose"`
|
||||
|
||||
AppName string `json:"appName"`
|
||||
AppInstallName string `json:"appInstallName"`
|
||||
Websites []string `json:"websites"`
|
||||
|
||||
IsPinned bool `json:"isPinned"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type ContainerOptions struct {
|
||||
@@ -63,15 +63,6 @@ type ContainerStatus struct {
|
||||
NetworkCount int `json:"networkCount"`
|
||||
VolumeCount int `json:"volumeCount"`
|
||||
RepoCount int `json:"repoCount"`
|
||||
|
||||
ContainerUsage int64 `json:"containerUsage"`
|
||||
ContainerReclaimable int64 `json:"containerReclaimable"`
|
||||
ImageUsage int64 `json:"imageUsage"`
|
||||
ImageReclaimable int64 `json:"imageReclaimable"`
|
||||
VolumeUsage int64 `json:"volumeUsage"`
|
||||
VolumeReclaimable int64 `json:"volumeReclaimable"`
|
||||
BuildCacheUsage int64 `json:"buildCacheUsage"`
|
||||
BuildCacheReclaimable int64 `json:"buildCacheReclaimable"`
|
||||
}
|
||||
type ResourceLimit struct {
|
||||
CPU int `json:"cpu"`
|
||||
@@ -79,17 +70,16 @@ type ResourceLimit struct {
|
||||
}
|
||||
|
||||
type ContainerOperate struct {
|
||||
TaskID string `json:"taskID"`
|
||||
ForcePull bool `json:"forcePull"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Image string `json:"image" validate:"required"`
|
||||
Network string `json:"network"`
|
||||
Hostname string `json:"hostname"`
|
||||
DomainName string `json:"domainName"`
|
||||
MacAddr string `json:"macAddr"`
|
||||
DNS []string `json:"dns"`
|
||||
Ipv4 string `json:"ipv4"`
|
||||
Ipv6 string `json:"ipv6"`
|
||||
TaskID string `json:"taskID"`
|
||||
ForcePull bool `json:"forcePull"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Image string `json:"image" validate:"required"`
|
||||
|
||||
Hostname string `json:"hostname"`
|
||||
DomainName string `json:"domainName"`
|
||||
DNS []string `json:"dns"`
|
||||
Networks []ContainerNetwork `json:"networks"`
|
||||
|
||||
PublishAllPorts bool `json:"publishAllPorts"`
|
||||
ExposedPorts []PortHelper `json:"exposedPorts"`
|
||||
Tty bool `json:"tty"`
|
||||
@@ -108,6 +98,12 @@ type ContainerOperate struct {
|
||||
Env []string `json:"env"`
|
||||
RestartPolicy string `json:"restartPolicy"`
|
||||
}
|
||||
type ContainerNetwork struct {
|
||||
Network string `json:"network"`
|
||||
Ipv4 string `json:"ipv4"`
|
||||
Ipv6 string `json:"ipv6"`
|
||||
MacAddr string `json:"macAddr"`
|
||||
}
|
||||
|
||||
type ContainerCreateByCommand struct {
|
||||
TaskID string `json:"taskID"`
|
||||
@@ -121,6 +117,19 @@ type ContainerUpgrade struct {
|
||||
ForcePull bool `json:"forcePull"`
|
||||
}
|
||||
|
||||
type ContainerItemStats struct {
|
||||
SizeRw int64 `json:"sizeRw"`
|
||||
SizeRootFs int64 `json:"sizeRootFs"`
|
||||
|
||||
ContainerUsage int64 `json:"containerUsage"`
|
||||
ContainerReclaimable int64 `json:"containerReclaimable"`
|
||||
ImageUsage int64 `json:"imageUsage"`
|
||||
ImageReclaimable int64 `json:"imageReclaimable"`
|
||||
VolumeUsage int64 `json:"volumeUsage"`
|
||||
VolumeReclaimable int64 `json:"volumeReclaimable"`
|
||||
BuildCacheUsage int64 `json:"buildCacheUsage"`
|
||||
BuildCacheReclaimable int64 `json:"buildCacheReclaimable"`
|
||||
}
|
||||
type ContainerListStats struct {
|
||||
ContainerID string `json:"containerID"`
|
||||
|
||||
@@ -282,6 +291,10 @@ type ComposeUpdate struct {
|
||||
Content string `json:"content" validate:"required"`
|
||||
Env []string `json:"env"`
|
||||
}
|
||||
type ComposeLogClean struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Path string `json:"path" validate:"required"`
|
||||
}
|
||||
|
||||
type ContainerLog struct {
|
||||
Container string `json:"container" validate:"required"`
|
||||
|
||||
+15
-10
@@ -13,15 +13,17 @@ type DashboardBase struct {
|
||||
Platform string `json:"platform"`
|
||||
PlatformFamily string `json:"platformFamily"`
|
||||
PlatformVersion string `json:"platformVersion"`
|
||||
PrettyDistro string `json:"prettyDistro"`
|
||||
KernelArch string `json:"kernelArch"`
|
||||
KernelVersion string `json:"kernelVersion"`
|
||||
VirtualizationSystem string `json:"virtualizationSystem"`
|
||||
IpV4Addr string `json:"ipV4Addr"`
|
||||
SystemProxy string `json:"systemProxy"`
|
||||
|
||||
CPUCores int `json:"cpuCores"`
|
||||
CPULogicalCores int `json:"cpuLogicalCores"`
|
||||
CPUModelName string `json:"cpuModelName"`
|
||||
CPUCores int `json:"cpuCores"`
|
||||
CPULogicalCores int `json:"cpuLogicalCores"`
|
||||
CPUModelName string `json:"cpuModelName"`
|
||||
CPUMhz float64 `json:"cpuMhz"`
|
||||
|
||||
QuickJumps []QuickJump `json:"quickJump"`
|
||||
CurrentInfo DashboardCurrent `json:"currentInfo"`
|
||||
@@ -48,6 +50,7 @@ type OsInfo struct {
|
||||
PlatformFamily string `json:"platformFamily"`
|
||||
KernelArch string `json:"kernelArch"`
|
||||
KernelVersion string `json:"kernelVersion"`
|
||||
PrettyDistro string `json:"prettyDistro"`
|
||||
|
||||
DiskSize int64 `json:"diskSize"`
|
||||
}
|
||||
@@ -58,9 +61,10 @@ type NodeCurrent struct {
|
||||
Load15 float64 `json:"load15"`
|
||||
LoadUsagePercent float64 `json:"loadUsagePercent"`
|
||||
|
||||
CPUUsedPercent float64 `json:"cpuUsedPercent"`
|
||||
CPUUsed float64 `json:"cpuUsed"`
|
||||
CPUTotal int `json:"cpuTotal"`
|
||||
CPUUsedPercent float64 `json:"cpuUsedPercent"`
|
||||
CPUUsed float64 `json:"cpuUsed"`
|
||||
CPUTotal int `json:"cpuTotal"`
|
||||
CPUDetailedPercent []float64 `json:"cpuDetailedPercent"`
|
||||
|
||||
MemoryTotal uint64 `json:"memoryTotal"`
|
||||
MemoryAvailable uint64 `json:"memoryAvailable"`
|
||||
@@ -84,10 +88,11 @@ type DashboardCurrent struct {
|
||||
Load15 float64 `json:"load15"`
|
||||
LoadUsagePercent float64 `json:"loadUsagePercent"`
|
||||
|
||||
CPUPercent []float64 `json:"cpuPercent"`
|
||||
CPUUsedPercent float64 `json:"cpuUsedPercent"`
|
||||
CPUUsed float64 `json:"cpuUsed"`
|
||||
CPUTotal int `json:"cpuTotal"`
|
||||
CPUPercent []float64 `json:"cpuPercent"`
|
||||
CPUUsedPercent float64 `json:"cpuUsedPercent"`
|
||||
CPUUsed float64 `json:"cpuUsed"`
|
||||
CPUTotal int `json:"cpuTotal"`
|
||||
CPUDetailedPercent []float64 `json:"cpuDetailedPercent"`
|
||||
|
||||
MemoryTotal uint64 `json:"memoryTotal"`
|
||||
MemoryUsed uint64 `json:"memoryUsed"`
|
||||
|
||||
@@ -38,6 +38,7 @@ type MysqlDBInfo struct {
|
||||
From string `json:"from"`
|
||||
MysqlName string `json:"mysqlName"`
|
||||
Format string `json:"format"`
|
||||
Collation string `json:"collation"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Permission string `json:"permission"`
|
||||
@@ -57,13 +58,19 @@ type MysqlDBCreate struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
From string `json:"from" validate:"required,oneof=local remote"`
|
||||
Database string `json:"database" validate:"required"`
|
||||
Format string `json:"format" validate:"required,oneof=utf8mb4 utf8 gbk big5"`
|
||||
Format string `json:"format" validate:"required"`
|
||||
Collation string `json:"collation"`
|
||||
Username string `json:"username" validate:"required"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
Permission string `json:"permission" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type MysqlFormatCollationOption struct {
|
||||
Format string `json:"format"`
|
||||
Collations []string `json:"collations"`
|
||||
}
|
||||
|
||||
type BindUser struct {
|
||||
Database string `json:"database" validate:"required"`
|
||||
DB string `json:"db" validate:"required"`
|
||||
@@ -251,6 +258,7 @@ type DatabaseInfo struct {
|
||||
Version string `json:"version"`
|
||||
Address string `json:"address"`
|
||||
Port uint `json:"port"`
|
||||
InitialDB string `json:"initialDB"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
|
||||
@@ -302,13 +310,14 @@ type DatabaseCreate struct {
|
||||
}
|
||||
|
||||
type DatabaseUpdate struct {
|
||||
ID uint `json:"id"`
|
||||
Type string `json:"type" validate:"required"`
|
||||
Version string `json:"version" validate:"required"`
|
||||
Address string `json:"address"`
|
||||
Port uint `json:"port"`
|
||||
Username string `json:"username" validate:"required"`
|
||||
Password string `json:"password"`
|
||||
ID uint `json:"id"`
|
||||
Type string `json:"type" validate:"required"`
|
||||
Version string `json:"version" validate:"required"`
|
||||
Address string `json:"address"`
|
||||
Port uint `json:"port"`
|
||||
InitialDB string `json:"initialDB"`
|
||||
Username string `json:"username" validate:"required"`
|
||||
Password string `json:"password"`
|
||||
|
||||
SSL bool `json:"ssl"`
|
||||
RootCert string `json:"rootCert"`
|
||||
|
||||
@@ -15,6 +15,9 @@ type ImageInfo struct {
|
||||
IsUsed bool `json:"isUsed"`
|
||||
Tags []string `json:"tags"`
|
||||
Size int64 `json:"size"`
|
||||
|
||||
IsPinned bool `json:"isPinned"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type ImageLoad struct {
|
||||
|
||||
@@ -11,7 +11,7 @@ type MonitorSearch struct {
|
||||
}
|
||||
|
||||
type MonitorData struct {
|
||||
Param string `json:"param" validate:"required,oneof=cpu memory load io network"`
|
||||
Param string `json:"param"`
|
||||
Date []time.Time `json:"date"`
|
||||
Value []interface{} `json:"value"`
|
||||
}
|
||||
@@ -37,3 +37,34 @@ type MonitorSettingUpdate struct {
|
||||
Key string `json:"key" validate:"required,oneof=MonitorStatus MonitorStoreDays MonitorInterval DefaultNetwork DefaultIO"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type MonitorGPUOptions struct {
|
||||
GPUType string `json:"gpuType"`
|
||||
Options []string `json:"options"`
|
||||
}
|
||||
type MonitorGPUSearch struct {
|
||||
ProductName string `json:"productName"`
|
||||
StartTime time.Time `json:"startTime"`
|
||||
EndTime time.Time `json:"endTime"`
|
||||
}
|
||||
type MonitorGPUData struct {
|
||||
Date []time.Time `json:"date"`
|
||||
GPUValue []float64 `json:"gpuValue"`
|
||||
TemperatureValue []float64 `json:"temperatureValue"`
|
||||
PowerTotal []float64 `json:"powerTotal"`
|
||||
PowerUsed []float64 `json:"powerUsed"`
|
||||
PowerPercent []float64 `json:"powerPercent"`
|
||||
MemoryTotal []float64 `json:"memoryTotal"`
|
||||
MemoryUsed []float64 `json:"memoryUsed"`
|
||||
MemoryPercent []float64 `json:"memoryPercent"`
|
||||
SpeedValue []int `json:"speedValue"`
|
||||
|
||||
GPUProcesses [][]GPUProcess `json:"gpuProcesses"`
|
||||
}
|
||||
|
||||
type GPUProcess struct {
|
||||
Pid string `json:"pid"`
|
||||
Type string `json:"type"`
|
||||
ProcessName string `json:"processName"`
|
||||
UsedMemory string `json:"usedMemory"`
|
||||
}
|
||||
|
||||
@@ -33,18 +33,13 @@ type AppItem struct {
|
||||
Key string `json:"key"`
|
||||
ID uint `json:"id"`
|
||||
Description string `json:"description"`
|
||||
Icon string `json:"icon"`
|
||||
Type string `json:"type"`
|
||||
Status string `json:"status"`
|
||||
Resource string `json:"resource"`
|
||||
Installed bool `json:"installed"`
|
||||
Versions []string `json:"versions"`
|
||||
Limit int `json:"limit"`
|
||||
Tags []TagDTO `json:"tags"`
|
||||
Github string `json:"github"`
|
||||
Website string `json:"website"`
|
||||
Tags []string `json:"tags"`
|
||||
GpuSupport bool `json:"gpuSupport"`
|
||||
Recommend int `json:"recommend"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
type TagDTO struct {
|
||||
|
||||
@@ -81,3 +81,11 @@ type SystemProxy struct {
|
||||
User string `json:"user"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
type CommonDescription struct {
|
||||
ID string `json:"id" validate:"required"`
|
||||
Type string `json:"type" validate:"required"`
|
||||
DetailType string `json:"detailType"`
|
||||
IsPinned bool `json:"isPinned"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ type DatabaseMysql struct {
|
||||
From string `json:"from" gorm:"not null;default:local"`
|
||||
MysqlName string `json:"mysqlName" gorm:"not null"`
|
||||
Format string `json:"format" gorm:"not null"`
|
||||
Collation string `json:"collation"`
|
||||
Username string `json:"username" gorm:"not null"`
|
||||
Password string `json:"password" gorm:"not null"`
|
||||
Permission string `json:"permission" gorm:"not null"`
|
||||
|
||||
@@ -31,3 +31,16 @@ type MonitorNetwork struct {
|
||||
Up float64 `json:"up"`
|
||||
Down float64 `json:"down"`
|
||||
}
|
||||
|
||||
type MonitorGPU struct {
|
||||
BaseModel
|
||||
ProductName string `json:"productName"`
|
||||
GPUUtil float64 `json:"gpuUtil"`
|
||||
Temperature float64 `json:"temperature"`
|
||||
PowerDraw float64 `json:"powerDraw"`
|
||||
MaxPowerLimit float64 `json:"maxPowerLimit"`
|
||||
MemUsed float64 `json:"memUsed"`
|
||||
MemTotal float64 `json:"memTotal"`
|
||||
FanSpeed int `json:"fanSpeed"`
|
||||
Processes string `json:"processes"`
|
||||
}
|
||||
|
||||
@@ -7,6 +7,14 @@ type Setting struct {
|
||||
About string `json:"about"`
|
||||
}
|
||||
|
||||
type CommonDescription struct {
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
DetailType string `json:"detailType"`
|
||||
IsPinned bool `json:"isPinned"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type NodeInfo struct {
|
||||
Scope string `json:"scope"`
|
||||
BaseDir string `json:"baseDir"`
|
||||
|
||||
@@ -77,6 +77,11 @@ func WithByType(tp string) DBOption {
|
||||
return g.Where("`type` = ?", tp)
|
||||
}
|
||||
}
|
||||
func WithByDetailType(tp string) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("`detail_type` = ?", tp)
|
||||
}
|
||||
}
|
||||
|
||||
func WithTypes(types []string) DBOption {
|
||||
return func(db *gorm.DB) *gorm.DB {
|
||||
|
||||
@@ -5,21 +5,27 @@ import (
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type MonitorRepo struct{}
|
||||
|
||||
type IMonitorRepo interface {
|
||||
GetBase(opts ...DBOption) ([]model.MonitorBase, error)
|
||||
GetGPU(opts ...DBOption) ([]model.MonitorGPU, error)
|
||||
GetIO(opts ...DBOption) ([]model.MonitorIO, error)
|
||||
GetNetwork(opts ...DBOption) ([]model.MonitorNetwork, error)
|
||||
|
||||
CreateMonitorBase(model model.MonitorBase) error
|
||||
BatchCreateMonitorGPU(list []model.MonitorGPU) error
|
||||
BatchCreateMonitorIO(ioList []model.MonitorIO) error
|
||||
BatchCreateMonitorNet(ioList []model.MonitorNetwork) error
|
||||
DelMonitorBase(timeForDelete time.Time) error
|
||||
DelMonitorGPU(timeForDelete time.Time) error
|
||||
DelMonitorIO(timeForDelete time.Time) error
|
||||
DelMonitorNet(timeForDelete time.Time) error
|
||||
|
||||
WithByProductName(name string) DBOption
|
||||
}
|
||||
|
||||
func NewIMonitorRepo() IMonitorRepo {
|
||||
@@ -53,10 +59,22 @@ func (u *MonitorRepo) GetNetwork(opts ...DBOption) ([]model.MonitorNetwork, erro
|
||||
err := db.Find(&data).Error
|
||||
return data, err
|
||||
}
|
||||
func (u *MonitorRepo) GetGPU(opts ...DBOption) ([]model.MonitorGPU, error) {
|
||||
var data []model.MonitorGPU
|
||||
db := global.GPUMonitorDB
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
err := db.Find(&data).Error
|
||||
return data, err
|
||||
}
|
||||
|
||||
func (u *MonitorRepo) CreateMonitorBase(model model.MonitorBase) error {
|
||||
return global.MonitorDB.Create(&model).Error
|
||||
}
|
||||
func (s *MonitorRepo) BatchCreateMonitorGPU(list []model.MonitorGPU) error {
|
||||
return global.GPUMonitorDB.CreateInBatches(&list, len(list)).Error
|
||||
}
|
||||
func (u *MonitorRepo) BatchCreateMonitorIO(ioList []model.MonitorIO) error {
|
||||
return global.MonitorDB.CreateInBatches(ioList, len(ioList)).Error
|
||||
}
|
||||
@@ -72,3 +90,12 @@ func (u *MonitorRepo) DelMonitorIO(timeForDelete time.Time) error {
|
||||
func (u *MonitorRepo) DelMonitorNet(timeForDelete time.Time) error {
|
||||
return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorNetwork{}).Error
|
||||
}
|
||||
func (s *MonitorRepo) DelMonitorGPU(timeForDelete time.Time) error {
|
||||
return global.GPUMonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorGPU{}).Error
|
||||
}
|
||||
|
||||
func (s *MonitorRepo) WithByProductName(name string) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("product_name = ?", name)
|
||||
}
|
||||
}
|
||||
|
||||
+40
-26
@@ -2,7 +2,6 @@ package repo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
@@ -19,13 +18,14 @@ type ISettingRepo interface {
|
||||
Update(key, value string) error
|
||||
WithByKey(key string) DBOption
|
||||
|
||||
CreateMonitorBase(model model.MonitorBase) error
|
||||
BatchCreateMonitorIO(ioList []model.MonitorIO) error
|
||||
BatchCreateMonitorNet(ioList []model.MonitorNetwork) error
|
||||
DelMonitorBase(timeForDelete time.Time) error
|
||||
DelMonitorIO(timeForDelete time.Time) error
|
||||
DelMonitorNet(timeForDelete time.Time) error
|
||||
UpdateOrCreate(key, value string) error
|
||||
|
||||
GetDescription(opts ...DBOption) (model.CommonDescription, error)
|
||||
GetDescriptionList(opts ...DBOption) ([]model.CommonDescription, error)
|
||||
CreateDescription(data *model.CommonDescription) error
|
||||
UpdateDescription(id string, val map[string]interface{}) error
|
||||
DelDescription(id string) error
|
||||
WithByDescriptionID(id string) DBOption
|
||||
}
|
||||
|
||||
func NewISettingRepo() ISettingRepo {
|
||||
@@ -78,25 +78,6 @@ func (s *SettingRepo) Update(key, value string) error {
|
||||
return global.DB.Model(&model.Setting{}).Where("key = ?", key).Updates(map[string]interface{}{"value": value}).Error
|
||||
}
|
||||
|
||||
func (s *SettingRepo) CreateMonitorBase(model model.MonitorBase) error {
|
||||
return global.MonitorDB.Create(&model).Error
|
||||
}
|
||||
func (s *SettingRepo) BatchCreateMonitorIO(ioList []model.MonitorIO) error {
|
||||
return global.MonitorDB.CreateInBatches(ioList, len(ioList)).Error
|
||||
}
|
||||
func (s *SettingRepo) BatchCreateMonitorNet(ioList []model.MonitorNetwork) error {
|
||||
return global.MonitorDB.CreateInBatches(ioList, len(ioList)).Error
|
||||
}
|
||||
func (s *SettingRepo) DelMonitorBase(timeForDelete time.Time) error {
|
||||
return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorBase{}).Error
|
||||
}
|
||||
func (s *SettingRepo) DelMonitorIO(timeForDelete time.Time) error {
|
||||
return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorIO{}).Error
|
||||
}
|
||||
func (s *SettingRepo) DelMonitorNet(timeForDelete time.Time) error {
|
||||
return global.MonitorDB.Where("created_at < ?", timeForDelete).Delete(&model.MonitorNetwork{}).Error
|
||||
}
|
||||
|
||||
func (s *SettingRepo) UpdateOrCreate(key, value string) error {
|
||||
var setting model.Setting
|
||||
result := global.DB.Where("key = ?", key).First(&setting)
|
||||
@@ -108,3 +89,36 @@ func (s *SettingRepo) UpdateOrCreate(key, value string) error {
|
||||
}
|
||||
return global.DB.Model(&setting).UpdateColumn("value", value).Error
|
||||
}
|
||||
|
||||
func (s *SettingRepo) GetDescriptionList(opts ...DBOption) ([]model.CommonDescription, error) {
|
||||
var lists []model.CommonDescription
|
||||
db := global.DB.Model(&model.CommonDescription{})
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
err := db.Find(&lists).Error
|
||||
return lists, err
|
||||
}
|
||||
func (s *SettingRepo) GetDescription(opts ...DBOption) (model.CommonDescription, error) {
|
||||
var data model.CommonDescription
|
||||
db := global.DB.Model(&model.CommonDescription{})
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
err := db.First(&data).Error
|
||||
return data, err
|
||||
}
|
||||
func (s *SettingRepo) CreateDescription(data *model.CommonDescription) error {
|
||||
return global.DB.Create(data).Error
|
||||
}
|
||||
func (s *SettingRepo) UpdateDescription(id string, val map[string]interface{}) error {
|
||||
return global.DB.Model(&model.CommonDescription{}).Where("id = ?", id).Updates(val).Error
|
||||
}
|
||||
func (s *SettingRepo) DelDescription(id string) error {
|
||||
return global.DB.Where("id = ?", id).Delete(&model.CommonDescription{}).Error
|
||||
}
|
||||
func (s *SettingRepo) WithByDescriptionID(id string) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("id = ?", id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
alertUtil "github.com/1Panel-dev/1Panel/agent/utils/alert"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/psutil"
|
||||
versionUtil "github.com/1Panel-dev/1Panel/agent/utils/version"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
|
||||
"github.com/shirou/gopsutil/v4/cpu"
|
||||
@@ -352,7 +353,7 @@ func loadLoadInfo(alert dto.AlertDTO) {
|
||||
return
|
||||
}
|
||||
var loadValue float64
|
||||
CPUTotal, _ := cpu.Counts(true)
|
||||
CPUTotal, _ := psutil.CPUInfo.GetLogicalCores(false)
|
||||
switch alert.Cycle {
|
||||
case 1:
|
||||
loadValue = avgStat.Load1 / (float64(CPUTotal*2) * 0.75) * 100
|
||||
@@ -839,7 +840,7 @@ func processSingleDisk(alert dto.AlertDTO) error {
|
||||
}
|
||||
|
||||
func checkAndCreateDiskAlert(alert dto.AlertDTO, path string) (bool, error) {
|
||||
usageStat, err := disk.Usage(path)
|
||||
usageStat, err := psutil.DISK.GetUsage(path, false)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("error getting disk usage for %s, err: %v", path, err)
|
||||
return false, err
|
||||
|
||||
+26
-30
@@ -37,7 +37,7 @@ type AppService struct {
|
||||
}
|
||||
|
||||
type IAppService interface {
|
||||
PageApp(ctx *gin.Context, req request.AppSearch) (interface{}, error)
|
||||
PageApp(ctx *gin.Context, req request.AppSearch) (*response.AppRes, error)
|
||||
GetAppTags(ctx *gin.Context) ([]response.TagDTO, error)
|
||||
GetApp(ctx *gin.Context, key string) (*response.AppDTO, error)
|
||||
GetAppDetail(appId uint, version, appType string) (response.AppDetailDTO, error)
|
||||
@@ -46,13 +46,14 @@ type IAppService interface {
|
||||
GetAppUpdate() (*response.AppUpdateRes, error)
|
||||
GetAppDetailByID(id uint) (*response.AppDetailDTO, error)
|
||||
SyncAppListFromLocal(taskID string)
|
||||
GetAppIcon(appID uint) ([]byte, error)
|
||||
}
|
||||
|
||||
func NewIAppService() IAppService {
|
||||
return &AppService{}
|
||||
}
|
||||
|
||||
func (a AppService) PageApp(ctx *gin.Context, req request.AppSearch) (interface{}, error) {
|
||||
func (a AppService) PageApp(ctx *gin.Context, req request.AppSearch) (*response.AppRes, error) {
|
||||
var opts []repo.DBOption
|
||||
opts = append(opts, appRepo.OrderByRecommend())
|
||||
if req.Name != "" {
|
||||
@@ -98,7 +99,7 @@ func (a AppService) PageApp(ctx *gin.Context, req request.AppSearch) (interface{
|
||||
}
|
||||
opts = append(opts, repo.WithByIDs(appIds))
|
||||
}
|
||||
var res response.AppRes
|
||||
res := &response.AppRes{}
|
||||
|
||||
total, apps, err := appRepo.Page(req.Page, req.PageSize, opts...)
|
||||
if err != nil {
|
||||
@@ -120,22 +121,20 @@ func (a AppService) PageApp(ctx *gin.Context, req request.AppSearch) (interface{
|
||||
ID: ap.ID,
|
||||
Name: ap.Name,
|
||||
Key: ap.Key,
|
||||
Type: ap.Type,
|
||||
Icon: ap.Icon,
|
||||
Resource: ap.Resource,
|
||||
Limit: ap.Limit,
|
||||
Website: ap.Website,
|
||||
Github: ap.Github,
|
||||
GpuSupport: ap.GpuSupport,
|
||||
Recommend: ap.Recommend,
|
||||
Description: ap.GetDescription(ctx),
|
||||
Type: ap.Type,
|
||||
}
|
||||
appDTOs = append(appDTOs, appDTO)
|
||||
tags, err := getAppTags(ap.ID, lang)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
appDTO.Tags = tags
|
||||
for _, tag := range tags {
|
||||
appDTO.Tags = append(appDTO.Tags, tag.Name)
|
||||
}
|
||||
if ap.Type == constant.RuntimePHP || ap.Type == constant.RuntimeGo || ap.Type == constant.RuntimeNode || ap.Type == constant.RuntimePython || ap.Type == constant.RuntimeJava || ap.Type == constant.RuntimeDotNet {
|
||||
details, _ := appDetailRepo.GetBy(appDetailRepo.WithAppId(ap.ID))
|
||||
var ids []uint
|
||||
@@ -195,24 +194,7 @@ func (a AppService) GetApp(ctx *gin.Context, key string) (*response.AppDTO, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var versionsRaw []string
|
||||
hasLatest := false
|
||||
latestVersion := ""
|
||||
for _, detail := range details {
|
||||
if strings.Contains(detail.Version, "latest") {
|
||||
hasLatest = true
|
||||
latestVersion = detail.Version
|
||||
continue
|
||||
}
|
||||
if key == "openresty" && !common.CompareAppVersion(detail.Version, "1.27") {
|
||||
continue
|
||||
}
|
||||
versionsRaw = append(versionsRaw, detail.Version)
|
||||
}
|
||||
appDTO.Versions = common.GetSortedVersions(versionsRaw)
|
||||
if hasLatest {
|
||||
appDTO.Versions = append([]string{latestVersion}, appDTO.Versions...)
|
||||
}
|
||||
appDTO.Versions = getAppVersions(key, details)
|
||||
tags, err := getAppTags(app.ID, strings.ToLower(common.GetLang(ctx)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -864,13 +846,15 @@ func getAppList() (*dto.AppList, error) {
|
||||
return nil, err
|
||||
}
|
||||
listFile := filepath.Join(global.Dir.ResourceDir, "1panel.json")
|
||||
content, err := os.ReadFile(listFile)
|
||||
file, err := os.Open(listFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = json.Unmarshal(content, list); err != nil {
|
||||
defer file.Close()
|
||||
if err = json.NewDecoder(file).Decode(list); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return list, nil
|
||||
}
|
||||
|
||||
@@ -1153,7 +1137,7 @@ func (a AppService) SyncAppListFromRemote(taskID string) (err error) {
|
||||
}, nil)
|
||||
|
||||
go func() {
|
||||
if err = syncTask.Execute(); err != nil {
|
||||
if err := syncTask.Execute(); err != nil {
|
||||
_ = NewISettingService().Update("AppStoreLastModified", "0")
|
||||
_ = NewISettingService().Update("AppStoreSyncStatus", constant.StatusError)
|
||||
}
|
||||
@@ -1161,3 +1145,15 @@ func (a AppService) SyncAppListFromRemote(taskID string) (err error) {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a AppService) GetAppIcon(appID uint) ([]byte, error) {
|
||||
app, err := appRepo.GetFirst(repo.WithByID(appID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
iconBytes, err := base64.StdEncoding.DecodeString(app.Icon)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return iconBytes, nil
|
||||
}
|
||||
|
||||
@@ -515,6 +515,7 @@ func (a *AppInstallService) GetServices(key string) ([]response.AppService, erro
|
||||
} else {
|
||||
service.From = constant.AppResourceRemote
|
||||
service.Status = constant.StatusRunning
|
||||
service.Config = map[string]string{"PANEL_DB_ROOT_PASSWORD": db.Password, "PANEL_DB_ROOT_USER": db.Username}
|
||||
}
|
||||
res = append(res, service)
|
||||
}
|
||||
|
||||
@@ -300,10 +300,11 @@ func createLink(ctx context.Context, installTask *task.Task, app model.App, appI
|
||||
createMysql.Name = dbConfig.DbName
|
||||
createMysql.Username = dbConfig.DbUser
|
||||
createMysql.Database = database.Name
|
||||
createMysql.Format = "utf8mb4"
|
||||
createMysql.Format = dbConfig.Format
|
||||
createMysql.Permission = "%"
|
||||
createMysql.Password = dbConfig.Password
|
||||
createMysql.From = database.From
|
||||
createMysql.Collation = dbConfig.Collation
|
||||
mysqldb, err := NewIMysqlService().Create(ctx, createMysql)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -540,8 +541,18 @@ func handleUpgradeCompose(install model.AppInstall, detail model.AppDetail) (map
|
||||
if !ok || oldValue == nil {
|
||||
return nil, buserr.New("ErrFileParse")
|
||||
}
|
||||
oldValueMap := oldValue.(map[string]interface{})
|
||||
oldServiceValue := oldValueMap[install.ServiceName].(map[string]interface{})
|
||||
oldValueMap, ok := oldValue.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, buserr.New("ErrFileParse")
|
||||
}
|
||||
oldServiceValueInterface, ok := oldValueMap[install.ServiceName]
|
||||
if !ok || oldServiceValueInterface == nil {
|
||||
return nil, buserr.New("ErrFileParse")
|
||||
}
|
||||
oldServiceValue, ok := oldServiceValueInterface.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, buserr.New("ErrFileParse")
|
||||
}
|
||||
if oldServiceValue["deploy"] != nil {
|
||||
serviceValue["deploy"] = oldServiceValue["deploy"]
|
||||
}
|
||||
@@ -1414,6 +1425,7 @@ func handleLocalApp(appDir string) (app *model.App, err error) {
|
||||
app.Key = "local" + appDefine.Key
|
||||
app.Architectures = strings.Join(appDefine.Architectures, ",")
|
||||
app.GpuSupport = appDefine.GpuSupport
|
||||
app.MemoryRequired = appDefine.MemoryRequired
|
||||
|
||||
app.Resource = constant.AppResourceLocal
|
||||
app.Status = constant.AppNormal
|
||||
@@ -1555,7 +1567,6 @@ func handleInstalled(appInstallList []model.AppInstall, updated bool, sync bool)
|
||||
Message: installed.Message,
|
||||
HttpPort: installed.HttpPort,
|
||||
HttpsPort: installed.HttpsPort,
|
||||
Icon: installed.App.Icon,
|
||||
AppName: installed.App.Name,
|
||||
AppKey: installed.App.Key,
|
||||
AppType: installed.App.Type,
|
||||
@@ -2163,3 +2174,28 @@ func isEditCompose(installed model.AppInstall) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func getAppVersions(key string, details []model.AppDetail) []string {
|
||||
var (
|
||||
versionsRaw []string
|
||||
versions []string
|
||||
)
|
||||
hasLatest := false
|
||||
latestVersion := ""
|
||||
for _, detail := range details {
|
||||
if key != "mssql" && strings.Contains(detail.Version, "latest") {
|
||||
hasLatest = true
|
||||
latestVersion = detail.Version
|
||||
continue
|
||||
}
|
||||
if key == "openresty" && !common.CompareAppVersion(detail.Version, "1.27") {
|
||||
continue
|
||||
}
|
||||
versionsRaw = append(versionsRaw, detail.Version)
|
||||
}
|
||||
versions = common.GetSortedVersions(versionsRaw)
|
||||
if hasLatest {
|
||||
versions = append([]string{latestVersion}, versions...)
|
||||
}
|
||||
return versions
|
||||
}
|
||||
|
||||
@@ -8,17 +8,14 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/i18n"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/task"
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/i18n"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/files"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/mysql/client"
|
||||
@@ -94,7 +91,7 @@ func handleMysqlBackup(db DatabaseHelper, parentTask *task.Task, recordID uint,
|
||||
if parentTask != nil {
|
||||
return itemHandler()
|
||||
}
|
||||
backupTask.AddSubTaskWithOps(task.GetTaskName(itemName, task.TaskBackup, task.TaskScopeBackup), func(t *task.Task) error { return itemHandler() }, nil, 3, time.Hour)
|
||||
backupTask.AddSubTaskWithOps(task.GetTaskName(itemName, task.TaskBackup, task.TaskScopeBackup), func(t *task.Task) error { return itemHandler() }, nil, 0, 3*time.Hour)
|
||||
go func() {
|
||||
if err := backupTask.Execute(); err != nil {
|
||||
backupRepo.UpdateRecordByMap(recordID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
|
||||
@@ -196,7 +193,7 @@ func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback
|
||||
return recoverDatabase(parentTask)
|
||||
}
|
||||
|
||||
itemTask.AddSubTaskWithOps(i18n.GetMsgByKey("TaskRecover"), recoverDatabase, nil, 3, time.Hour)
|
||||
itemTask.AddSubTaskWithOps(i18n.GetMsgByKey("TaskRecover"), recoverDatabase, nil, 0, 3*time.Hour)
|
||||
go func() {
|
||||
_ = itemTask.Execute()
|
||||
}()
|
||||
|
||||
@@ -82,11 +82,11 @@ func handlePostgresqlBackup(db DatabaseHelper, parentTask *task.Task, recordID u
|
||||
}
|
||||
}
|
||||
|
||||
itemHandler := func() error { return doPostgresqlgBackup(db, targetDir, fileName, secret) }
|
||||
itemHandler := func() error { return doPostgresqlgBackup(db, targetDir, fileName, secret, backupTask) }
|
||||
if parentTask != nil {
|
||||
return itemHandler()
|
||||
}
|
||||
backupTask.AddSubTaskWithOps(task.GetTaskName(itemName, task.TaskBackup, task.TaskScopeBackup), func(t *task.Task) error { return itemHandler() }, nil, 3, time.Hour)
|
||||
backupTask.AddSubTaskWithOps(task.GetTaskName(itemName, task.TaskBackup, task.TaskScopeBackup), func(t *task.Task) error { return itemHandler() }, nil, 0, 3*time.Hour)
|
||||
go func() {
|
||||
if err := backupTask.Execute(); err != nil {
|
||||
backupRepo.UpdateRecordByMap(recordID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
|
||||
@@ -130,10 +130,12 @@ func handlePostgresqlRecover(req dto.CommonRecover, parentTask *task.Task, isRol
|
||||
if !isRollback {
|
||||
rollbackFile := path.Join(global.Dir.TmpDir, fmt.Sprintf("database/%s/%s_%s.sql.gz", req.Type, req.DetailName, time.Now().Format(constant.DateTimeSlimLayout)))
|
||||
if err := cli.Backup(client.BackupInfo{
|
||||
Database: req.Name,
|
||||
Name: req.DetailName,
|
||||
TargetDir: path.Dir(rollbackFile),
|
||||
FileName: path.Base(rollbackFile),
|
||||
|
||||
Task: t,
|
||||
Timeout: 300,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("backup postgresql db %s for rollback before recover failed, err: %v", req.DetailName, err)
|
||||
@@ -142,9 +144,11 @@ func handlePostgresqlRecover(req dto.CommonRecover, parentTask *task.Task, isRol
|
||||
if !isOk {
|
||||
global.LOG.Info("recover failed, start to rollback now")
|
||||
if err := cli.Recover(client.RecoverInfo{
|
||||
Database: req.Name,
|
||||
Name: req.DetailName,
|
||||
SourceFile: rollbackFile,
|
||||
|
||||
Task: t,
|
||||
Timeout: 300,
|
||||
}); err != nil {
|
||||
global.LOG.Errorf("rollback postgresql db %s from %s failed, err: %v", req.DetailName, rollbackFile, err)
|
||||
@@ -167,9 +171,11 @@ func handlePostgresqlRecover(req dto.CommonRecover, parentTask *task.Task, isRol
|
||||
t.LogWithStatus(i18n.GetMsgByKey("Decrypt"), err)
|
||||
}
|
||||
if err := cli.Recover(client.RecoverInfo{
|
||||
Database: req.Name,
|
||||
Name: req.DetailName,
|
||||
SourceFile: req.File,
|
||||
Username: dbInfo.Username,
|
||||
Task: t,
|
||||
Timeout: 300,
|
||||
}); err != nil {
|
||||
global.LOG.Errorf("recover postgresql db %s from %s failed, err: %v", req.DetailName, req.File, err)
|
||||
@@ -182,24 +188,26 @@ func handlePostgresqlRecover(req dto.CommonRecover, parentTask *task.Task, isRol
|
||||
return recoverDatabase(parentTask)
|
||||
}
|
||||
|
||||
itemTask.AddSubTaskWithOps(i18n.GetMsgByKey("TaskRecover"), recoverDatabase, nil, 3, time.Hour)
|
||||
itemTask.AddSubTaskWithOps(i18n.GetMsgByKey("TaskRecover"), recoverDatabase, nil, 0, 3*time.Hour)
|
||||
go func() {
|
||||
_ = itemTask.Execute()
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func doPostgresqlgBackup(db DatabaseHelper, targetDir, fileName, secret string) error {
|
||||
func doPostgresqlgBackup(db DatabaseHelper, targetDir, fileName, secret string, task *task.Task) error {
|
||||
cli, err := LoadPostgresqlClientByFrom(db.Database)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cli.Close()
|
||||
backupInfo := pgclient.BackupInfo{
|
||||
Database: db.Database,
|
||||
Name: db.Name,
|
||||
TargetDir: targetDir,
|
||||
FileName: fileName,
|
||||
|
||||
Task: task,
|
||||
Timeout: 300,
|
||||
}
|
||||
if err := cli.Backup(backupInfo); err != nil {
|
||||
|
||||
+199
-165
@@ -70,6 +70,7 @@ type IContainerService interface {
|
||||
ContainerUpgrade(req dto.ContainerUpgrade) error
|
||||
ContainerInfo(req dto.OperationWithName) (*dto.ContainerOperate, error)
|
||||
ContainerListStats() ([]dto.ContainerListStats, error)
|
||||
ContainerItemStats(req dto.OperationWithName) (dto.ContainerItemStats, error)
|
||||
LoadResourceLimit() (*dto.ResourceLimit, error)
|
||||
ContainerRename(req dto.ContainerRename) error
|
||||
ContainerCommit(req dto.ContainerCommit) error
|
||||
@@ -84,6 +85,7 @@ type IContainerService interface {
|
||||
CreateVolume(req dto.VolumeCreate) error
|
||||
TestCompose(req dto.ComposeCreate) (bool, error)
|
||||
ComposeUpdate(req dto.ComposeUpdate) error
|
||||
ComposeLogClean(req dto.ComposeLogClean) error
|
||||
Prune(req dto.ContainerPrune) error
|
||||
|
||||
LoadUsers(req dto.OperationWithName) []string
|
||||
@@ -96,19 +98,12 @@ func NewIContainerService() IContainerService {
|
||||
}
|
||||
|
||||
func (u *ContainerService) Page(req dto.PageContainer) (int64, interface{}, error) {
|
||||
var (
|
||||
records []container.Summary
|
||||
list []container.Summary
|
||||
)
|
||||
client, err := docker.NewDockerClient()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
defer client.Close()
|
||||
options := container.ListOptions{
|
||||
All: true,
|
||||
Size: true,
|
||||
}
|
||||
options := container.ListOptions{All: true}
|
||||
if len(req.Filters) != 0 {
|
||||
options.Filters = filters.NewArgs()
|
||||
options.Filters.Add("label", req.Filters)
|
||||
@@ -117,114 +112,32 @@ func (u *ContainerService) Page(req dto.PageContainer) (int64, interface{}, erro
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
if req.ExcludeAppStore {
|
||||
for _, item := range containers {
|
||||
if created, ok := item.Labels[composeCreatedBy]; ok && created == "Apps" {
|
||||
continue
|
||||
}
|
||||
list = append(list, item)
|
||||
}
|
||||
} else {
|
||||
list = containers
|
||||
}
|
||||
records := searchWithFilter(req, containers)
|
||||
|
||||
if len(req.Name) != 0 {
|
||||
length, count := len(list), 0
|
||||
for count < length {
|
||||
if !strings.Contains(list[count].Names[0][1:], req.Name) && !strings.Contains(list[count].Image, req.Name) {
|
||||
list = append(list[:count], list[(count+1):]...)
|
||||
length--
|
||||
} else {
|
||||
count++
|
||||
}
|
||||
}
|
||||
}
|
||||
if req.State != "all" {
|
||||
length, count := len(list), 0
|
||||
for count < length {
|
||||
if list[count].State != req.State {
|
||||
list = append(list[:count], list[(count+1):]...)
|
||||
length--
|
||||
} else {
|
||||
count++
|
||||
}
|
||||
}
|
||||
}
|
||||
switch req.OrderBy {
|
||||
case "name":
|
||||
sort.Slice(list, func(i, j int) bool {
|
||||
if req.Order == constant.OrderAsc {
|
||||
return list[i].Names[0][1:] < list[j].Names[0][1:]
|
||||
}
|
||||
return list[i].Names[0][1:] > list[j].Names[0][1:]
|
||||
})
|
||||
default:
|
||||
sort.Slice(list, func(i, j int) bool {
|
||||
if req.Order == constant.OrderAsc {
|
||||
return list[i].Created < list[j].Created
|
||||
}
|
||||
return list[i].Created > list[j].Created
|
||||
})
|
||||
}
|
||||
|
||||
total, start, end := len(list), (req.Page-1)*req.PageSize, req.Page*req.PageSize
|
||||
var backData []dto.ContainerInfo
|
||||
total, start, end := len(records), (req.Page-1)*req.PageSize, req.Page*req.PageSize
|
||||
if start > total {
|
||||
records = make([]container.Summary, 0)
|
||||
backData = make([]dto.ContainerInfo, 0)
|
||||
} else {
|
||||
if end >= total {
|
||||
end = total
|
||||
}
|
||||
records = list[start:end]
|
||||
backData = records[start:end]
|
||||
}
|
||||
|
||||
backDatas := make([]dto.ContainerInfo, len(records))
|
||||
for i := 0; i < len(records); i++ {
|
||||
item := records[i]
|
||||
IsFromCompose := false
|
||||
if _, ok := item.Labels[composeProjectLabel]; ok {
|
||||
IsFromCompose = true
|
||||
}
|
||||
IsFromApp := false
|
||||
if created, ok := item.Labels[composeCreatedBy]; ok && created == "Apps" {
|
||||
IsFromApp = true
|
||||
}
|
||||
|
||||
exposePorts := transPortToStr(records[i].Ports)
|
||||
info := dto.ContainerInfo{
|
||||
ContainerID: item.ID,
|
||||
CreateTime: time.Unix(item.Created, 0).Format(constant.DateTimeLayout),
|
||||
Name: item.Names[0][1:],
|
||||
ImageId: strings.Split(item.ImageID, ":")[1],
|
||||
ImageName: item.Image,
|
||||
State: item.State,
|
||||
RunTime: item.Status,
|
||||
Ports: exposePorts,
|
||||
IsFromApp: IsFromApp,
|
||||
IsFromCompose: IsFromCompose,
|
||||
SizeRw: item.SizeRw,
|
||||
SizeRootFs: item.SizeRootFs,
|
||||
}
|
||||
install, _ := appInstallRepo.GetFirst(appInstallRepo.WithContainerName(info.Name))
|
||||
for i := 0; i < len(backData); i++ {
|
||||
install, _ := appInstallRepo.GetFirst(appInstallRepo.WithContainerName(backData[i].Name))
|
||||
if install.ID > 0 {
|
||||
info.AppInstallName = install.Name
|
||||
info.AppName = install.App.Name
|
||||
backData[i].AppInstallName = install.Name
|
||||
backData[i].AppName = install.App.Name
|
||||
websites, _ := websiteRepo.GetBy(websiteRepo.WithAppInstallId(install.ID))
|
||||
for _, website := range websites {
|
||||
info.Websites = append(info.Websites, website.PrimaryDomain)
|
||||
backData[i].Websites = append(backData[i].Websites, website.PrimaryDomain)
|
||||
}
|
||||
}
|
||||
backDatas[i] = info
|
||||
if item.NetworkSettings != nil && len(item.NetworkSettings.Networks) > 0 {
|
||||
networks := make([]string, 0, len(item.NetworkSettings.Networks))
|
||||
for key := range item.NetworkSettings.Networks {
|
||||
networks = append(networks, item.NetworkSettings.Networks[key].IPAddress)
|
||||
}
|
||||
sort.Strings(networks)
|
||||
backDatas[i].Network = networks
|
||||
}
|
||||
}
|
||||
|
||||
return int64(total), backDatas, nil
|
||||
return int64(total), backData, nil
|
||||
}
|
||||
|
||||
func (u *ContainerService) List() []dto.ContainerOptions {
|
||||
@@ -287,13 +200,60 @@ func (u *ContainerService) LoadStatus() (dto.ContainerStatus, error) {
|
||||
defer client.Close()
|
||||
c := context.Background()
|
||||
|
||||
usage, err := client.DiskUsage(c, types.DiskUsageOptions{})
|
||||
images, _ := client.ImageList(c, image.ListOptions{All: true})
|
||||
data.ImageCount = len(images)
|
||||
repo, _ := imageRepoRepo.List()
|
||||
data.RepoCount = len(repo)
|
||||
templates, _ := composeRepo.List()
|
||||
data.ComposeTemplateCount = len(templates)
|
||||
networks, _ := client.NetworkList(c, network.ListOptions{})
|
||||
data.NetworkCount = len(networks)
|
||||
volumes, _ := client.VolumeList(c, volume.ListOptions{})
|
||||
data.VolumeCount = len(volumes.Volumes)
|
||||
data.ComposeCount = loadComposeCount(client)
|
||||
containers, _ := client.ContainerList(c, container.ListOptions{All: true})
|
||||
data.ContainerCount = len(containers)
|
||||
for _, item := range containers {
|
||||
switch item.State {
|
||||
case "created":
|
||||
data.Created++
|
||||
case "running":
|
||||
data.Running++
|
||||
case "paused":
|
||||
data.Paused++
|
||||
case "restarting":
|
||||
data.Restarting++
|
||||
case "dead":
|
||||
data.Dead++
|
||||
case "exited":
|
||||
data.Exited++
|
||||
case "removing":
|
||||
data.Removing++
|
||||
}
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
func (u *ContainerService) ContainerItemStats(req dto.OperationWithName) (dto.ContainerItemStats, error) {
|
||||
var data dto.ContainerItemStats
|
||||
client, err := docker.NewDockerClient()
|
||||
if err != nil {
|
||||
return data, err
|
||||
}
|
||||
if req.Name != "system" {
|
||||
defer client.Close()
|
||||
containerInfo, _, err := client.ContainerInspectWithRaw(context.Background(), req.Name, true)
|
||||
if err != nil {
|
||||
return data, err
|
||||
}
|
||||
data.SizeRw = *containerInfo.SizeRw
|
||||
data.SizeRootFs = *containerInfo.SizeRootFs
|
||||
return data, nil
|
||||
}
|
||||
|
||||
data.ImageCount = len(usage.Images)
|
||||
data.VolumeCount = len(usage.Volumes)
|
||||
usage, err := client.DiskUsage(context.Background(), types.DiskUsageOptions{})
|
||||
if err != nil {
|
||||
return data, err
|
||||
}
|
||||
for _, item := range usage.Images {
|
||||
data.ImageUsage += item.Size
|
||||
if item.Containers < 1 {
|
||||
@@ -315,34 +275,6 @@ func (u *ContainerService) LoadStatus() (dto.ContainerStatus, error) {
|
||||
for _, item := range usage.BuildCache {
|
||||
data.BuildCacheUsage += item.Size
|
||||
}
|
||||
repo, _ := imageRepoRepo.List()
|
||||
data.RepoCount = len(repo)
|
||||
templates, _ := composeRepo.List()
|
||||
data.ComposeTemplateCount = len(templates)
|
||||
networks, _ := client.NetworkList(c, network.ListOptions{})
|
||||
data.NetworkCount = len(networks)
|
||||
volumes, _ := client.VolumeList(c, volume.ListOptions{})
|
||||
data.VolumeCount = len(volumes.Volumes)
|
||||
data.ComposeCount = loadComposeCount(client)
|
||||
data.ContainerCount = len(usage.Containers)
|
||||
for _, item := range usage.Containers {
|
||||
switch item.State {
|
||||
case "created":
|
||||
data.Created++
|
||||
case "running":
|
||||
data.Running++
|
||||
case "paused":
|
||||
data.Paused++
|
||||
case "restarting":
|
||||
data.Restarting++
|
||||
case "dead":
|
||||
data.Dead++
|
||||
case "exited":
|
||||
data.Exited++
|
||||
case "removing":
|
||||
data.Removing++
|
||||
}
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
func (u *ContainerService) ContainerListStats() ([]dto.ContainerListStats, error) {
|
||||
@@ -667,27 +599,27 @@ func (u *ContainerService) ContainerInfo(req dto.OperationWithName) (*dto.Contai
|
||||
data.Name = strings.ReplaceAll(oldContainer.Name, "/", "")
|
||||
data.Image = oldContainer.Config.Image
|
||||
if oldContainer.NetworkSettings != nil {
|
||||
for network := range oldContainer.NetworkSettings.Networks {
|
||||
data.Network = network
|
||||
break
|
||||
for net, val := range oldContainer.NetworkSettings.Networks {
|
||||
netItem := dto.ContainerNetwork{
|
||||
Network: net,
|
||||
MacAddr: val.MacAddress,
|
||||
}
|
||||
if val.IPAMConfig != nil {
|
||||
if netItem.Network != "bridge" {
|
||||
netItem.Ipv4 = val.IPAMConfig.IPv4Address
|
||||
netItem.Ipv6 = val.IPAMConfig.IPv6Address
|
||||
}
|
||||
} else {
|
||||
if netItem.Network != "bridge" {
|
||||
netItem.Ipv4 = val.IPAddress
|
||||
}
|
||||
}
|
||||
data.Networks = append(data.Networks, netItem)
|
||||
}
|
||||
}
|
||||
|
||||
exposePorts, _ := loadPortByInspect(oldContainer.ID, client)
|
||||
data.ExposedPorts = loadContainerPortForInfo(exposePorts)
|
||||
networkSettings := oldContainer.NetworkSettings
|
||||
bridgeNetworkSettings := networkSettings.Networks[data.Network]
|
||||
if bridgeNetworkSettings.IPAMConfig != nil {
|
||||
data.MacAddr = bridgeNetworkSettings.MacAddress
|
||||
if data.Network != "bridge" {
|
||||
data.Ipv4 = bridgeNetworkSettings.IPAMConfig.IPv4Address
|
||||
data.Ipv6 = bridgeNetworkSettings.IPAMConfig.IPv6Address
|
||||
}
|
||||
} else {
|
||||
if data.Network != "bridge" {
|
||||
data.Ipv4 = bridgeNetworkSettings.IPAddress
|
||||
}
|
||||
}
|
||||
data.Hostname = oldContainer.Config.Hostname
|
||||
data.DNS = oldContainer.HostConfig.DNS
|
||||
data.DomainName = oldContainer.Config.Domainname
|
||||
@@ -1505,25 +1437,25 @@ func loadConfigInfo(isCreate bool, req dto.ContainerOperate, oldContainer *conta
|
||||
config.User = req.User
|
||||
config.WorkingDir = req.WorkingDir
|
||||
|
||||
if len(req.Network) != 0 {
|
||||
switch req.Network {
|
||||
case "host", "none", "bridge":
|
||||
hostConf.NetworkMode = container.NetworkMode(req.Network)
|
||||
}
|
||||
if req.Ipv4 != "" || req.Ipv6 != "" {
|
||||
networkConf.EndpointsConfig = map[string]*network.EndpointSettings{req.Network: {
|
||||
IPAMConfig: &network.EndpointIPAMConfig{
|
||||
IPv4Address: req.Ipv4,
|
||||
IPv6Address: req.Ipv6,
|
||||
}, MacAddress: req.MacAddr}}
|
||||
} else {
|
||||
networkConf.EndpointsConfig = map[string]*network.EndpointSettings{req.Network: {}}
|
||||
if len(req.Networks) != 0 {
|
||||
networkConf.EndpointsConfig = make(map[string]*network.EndpointSettings)
|
||||
for _, item := range req.Networks {
|
||||
switch item.Network {
|
||||
case "host", "none", "bridge":
|
||||
hostConf.NetworkMode = container.NetworkMode(item.Network)
|
||||
}
|
||||
if item.Ipv4 != "" || item.Ipv6 != "" {
|
||||
networkConf.EndpointsConfig[item.Network] = &network.EndpointSettings{
|
||||
IPAMConfig: &network.EndpointIPAMConfig{
|
||||
IPv4Address: item.Ipv4,
|
||||
IPv6Address: item.Ipv6,
|
||||
}, MacAddress: item.MacAddr}
|
||||
} else {
|
||||
networkConf.EndpointsConfig[item.Network] = &network.EndpointSettings{}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if req.Ipv4 != "" || req.Ipv6 != "" {
|
||||
return nil, nil, nil, fmt.Errorf("please set up the network")
|
||||
}
|
||||
networkConf = network.NetworkingConfig{}
|
||||
return nil, nil, nil, fmt.Errorf("please set up the network")
|
||||
}
|
||||
|
||||
hostConf.Privileged = req.Privileged
|
||||
@@ -1771,3 +1703,105 @@ func loadContainerPortForInfo(itemPorts []container.Port) []dto.PortHelper {
|
||||
}
|
||||
return exposedPorts
|
||||
}
|
||||
|
||||
func searchWithFilter(req dto.PageContainer, containers []container.Summary) []dto.ContainerInfo {
|
||||
var (
|
||||
records []dto.ContainerInfo
|
||||
list []container.Summary
|
||||
)
|
||||
|
||||
if req.ExcludeAppStore {
|
||||
for _, item := range containers {
|
||||
if created, ok := item.Labels[composeCreatedBy]; ok && created == "Apps" {
|
||||
continue
|
||||
}
|
||||
list = append(list, item)
|
||||
}
|
||||
} else {
|
||||
list = containers
|
||||
}
|
||||
|
||||
if len(req.Name) != 0 {
|
||||
length, count := len(list), 0
|
||||
for count < length {
|
||||
if !strings.Contains(list[count].Names[0][1:], req.Name) && !strings.Contains(list[count].Image, req.Name) {
|
||||
list = append(list[:count], list[(count+1):]...)
|
||||
length--
|
||||
} else {
|
||||
count++
|
||||
}
|
||||
}
|
||||
}
|
||||
if req.State != "all" {
|
||||
length, count := len(list), 0
|
||||
for count < length {
|
||||
if list[count].State != req.State {
|
||||
list = append(list[:count], list[(count+1):]...)
|
||||
length--
|
||||
} else {
|
||||
count++
|
||||
}
|
||||
}
|
||||
}
|
||||
switch req.OrderBy {
|
||||
case "name":
|
||||
sort.Slice(list, func(i, j int) bool {
|
||||
if req.Order == constant.OrderAsc {
|
||||
return list[i].Names[0][1:] < list[j].Names[0][1:]
|
||||
}
|
||||
return list[i].Names[0][1:] > list[j].Names[0][1:]
|
||||
})
|
||||
default:
|
||||
sort.Slice(list, func(i, j int) bool {
|
||||
if req.Order == constant.OrderAsc {
|
||||
return list[i].Created < list[j].Created
|
||||
}
|
||||
return list[i].Created > list[j].Created
|
||||
})
|
||||
}
|
||||
for _, item := range list {
|
||||
IsFromCompose := false
|
||||
if _, ok := item.Labels[composeProjectLabel]; ok {
|
||||
IsFromCompose = true
|
||||
}
|
||||
IsFromApp := false
|
||||
if created, ok := item.Labels[composeCreatedBy]; ok && created == "Apps" {
|
||||
IsFromApp = true
|
||||
}
|
||||
exposePorts := transPortToStr(item.Ports)
|
||||
info := dto.ContainerInfo{
|
||||
ContainerID: item.ID,
|
||||
CreateTime: time.Unix(item.Created, 0).Format(constant.DateTimeLayout),
|
||||
Name: item.Names[0][1:],
|
||||
Ports: exposePorts,
|
||||
ImageId: strings.Split(item.ImageID, ":")[1],
|
||||
ImageName: item.Image,
|
||||
State: item.State,
|
||||
RunTime: item.Status,
|
||||
IsFromApp: IsFromApp,
|
||||
IsFromCompose: IsFromCompose,
|
||||
}
|
||||
if item.NetworkSettings != nil && len(item.NetworkSettings.Networks) > 0 {
|
||||
networks := make([]string, 0, len(item.NetworkSettings.Networks))
|
||||
for key := range item.NetworkSettings.Networks {
|
||||
networks = append(networks, item.NetworkSettings.Networks[key].IPAddress)
|
||||
}
|
||||
sort.Strings(networks)
|
||||
info.Network = networks
|
||||
}
|
||||
records = append(records, info)
|
||||
}
|
||||
descriptions, _ := settingRepo.GetDescriptionList(repo.WithByType("container"))
|
||||
for i := 0; i < len(records); i++ {
|
||||
for _, desc := range descriptions {
|
||||
if desc.ID == records[i].ContainerID {
|
||||
records[i].Description = desc.Description
|
||||
records[i].IsPinned = desc.IsPinned
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Slice(records, func(i, j int) bool {
|
||||
return records[i].IsPinned && !records[j].IsPinned
|
||||
})
|
||||
return records
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -203,14 +204,13 @@ func (u *ContainerService) CreateCompose(req dto.ComposeCreate) error {
|
||||
}
|
||||
go func() {
|
||||
taskItem.AddSubTask(i18n.GetMsgByKey("ComposeCreate"), func(t *task.Task) error {
|
||||
cmd := getComposeCmd(req.Path, "up")
|
||||
out, err := cmd.CombinedOutput()
|
||||
taskItem.Log(i18n.GetWithName("ComposeCreateRes", string(out)))
|
||||
err := compose.UpWithTask(req.Path, t)
|
||||
t.LogWithStatus(i18n.GetMsgByKey("ComposeCreate"), err)
|
||||
if err != nil {
|
||||
_, _ = compose.Down(req.Path)
|
||||
return err
|
||||
}
|
||||
_ = composeRepo.CreateRecord(&model.Compose{Name: req.Name, Path: req.Path})
|
||||
_ = composeRepo.CreateRecord(&model.Compose{Name: strings.ToLower(req.Name), Path: req.Path})
|
||||
return nil
|
||||
}, nil)
|
||||
_ = taskItem.Execute()
|
||||
@@ -285,6 +285,57 @@ func (u *ContainerService) ComposeUpdate(req dto.ComposeUpdate) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *ContainerService) ComposeLogClean(req dto.ComposeLogClean) error {
|
||||
client, err := docker.NewDockerClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
options := container.ListOptions{All: true}
|
||||
options.Filters = filters.NewArgs()
|
||||
options.Filters.Add("label", composeProjectLabel)
|
||||
|
||||
list, err := client.ContainerList(context.Background(), options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctx := context.Background()
|
||||
for _, item := range list {
|
||||
if name, ok := item.Labels[composeProjectLabel]; ok {
|
||||
if name != req.Name {
|
||||
continue
|
||||
}
|
||||
containerItem, err := client.ContainerInspect(ctx, item.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := client.ContainerStop(ctx, containerItem.ID, container.StopOptions{}); err != nil {
|
||||
return err
|
||||
}
|
||||
file, err := os.OpenFile(containerItem.LogPath, os.O_RDWR|os.O_CREATE, constant.FilePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
if err = file.Truncate(0); err != nil {
|
||||
return err
|
||||
}
|
||||
_, _ = file.Seek(0, 0)
|
||||
|
||||
files, _ := filepath.Glob(fmt.Sprintf("%s.*", containerItem.LogPath))
|
||||
for _, file := range files {
|
||||
_ = os.Remove(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
return u.ComposeOperation(dto.ComposeOperation{
|
||||
Name: req.Name,
|
||||
Path: req.Path,
|
||||
Operation: "restart",
|
||||
})
|
||||
}
|
||||
|
||||
func (u *ContainerService) loadPath(req *dto.ComposeCreate) error {
|
||||
if req.From == "template" || req.From == "edit" {
|
||||
dir := fmt.Sprintf("%s/docker/compose/%s", global.Dir.DataDir, req.Name)
|
||||
|
||||
@@ -117,10 +117,8 @@ func (u *ContainerService) CreateNetwork(req dto.NetworkCreate) error {
|
||||
return err
|
||||
}
|
||||
defer client.Close()
|
||||
var (
|
||||
ipams []network.IPAMConfig
|
||||
enableV6 bool
|
||||
)
|
||||
var ipams []network.IPAMConfig
|
||||
|
||||
if req.Ipv4 {
|
||||
var itemIpam network.IPAMConfig
|
||||
if len(req.AuxAddress) != 0 {
|
||||
@@ -141,7 +139,6 @@ func (u *ContainerService) CreateNetwork(req dto.NetworkCreate) error {
|
||||
ipams = append(ipams, itemIpam)
|
||||
}
|
||||
if req.Ipv6 {
|
||||
enableV6 = true
|
||||
var itemIpam network.IPAMConfig
|
||||
if len(req.AuxAddress) != 0 {
|
||||
itemIpam.AuxAddress = make(map[string]string)
|
||||
@@ -162,7 +159,7 @@ func (u *ContainerService) CreateNetwork(req dto.NetworkCreate) error {
|
||||
}
|
||||
|
||||
options := network.CreateOptions{
|
||||
EnableIPv6: &enableV6,
|
||||
EnableIPv6: &req.Ipv6,
|
||||
Driver: req.Driver,
|
||||
Options: stringsToMap(req.Options),
|
||||
Labels: stringsToMap(req.Labels),
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
@@ -20,6 +19,7 @@ func (u *ContainerService) PageVolume(req dto.SearchWithPage) (int64, interface{
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
defer client.Close()
|
||||
list, err := client.VolumeList(context.TODO(), volume.ListOptions{})
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
@@ -57,7 +57,7 @@ func (u *ContainerService) PageVolume(req dto.SearchWithPage) (int64, interface{
|
||||
var volume dto.Volume
|
||||
volume.Driver = item.Driver
|
||||
volume.Mountpoint = item.Mountpoint
|
||||
volume.Name = simplifyVolumeName(item.Name)
|
||||
volume.Name = item.Name
|
||||
for key, val := range item.Labels {
|
||||
volume.Labels = append(volume.Labels, dto.VolumeOption{Key: key, Value: val})
|
||||
}
|
||||
@@ -143,16 +143,3 @@ func (u *ContainerService) CreateVolume(req dto.VolumeCreate) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func simplifyVolumeName(name string) string {
|
||||
if len(name) != 64 {
|
||||
return name
|
||||
}
|
||||
|
||||
for _, char := range name {
|
||||
if !unicode.Is(unicode.ASCII_Hex_Digit, char) {
|
||||
return name
|
||||
}
|
||||
}
|
||||
return name[:12]
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/task"
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
"github.com/1Panel-dev/1Panel/agent/i18n"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
@@ -21,7 +22,6 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/files"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (u *CronjobService) handleApp(cronjob model.Cronjob, startTime time.Time, taskItem *task.Task) error {
|
||||
@@ -32,7 +32,7 @@ func (u *CronjobService) handleApp(cronjob model.Cronjob, startTime time.Time, t
|
||||
}
|
||||
accountMap := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
|
||||
if !accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].isOk {
|
||||
return errors.New(i18n.GetMsgWithDetail("LoadBackupFailed", accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].message))
|
||||
return buserr.New(i18n.GetMsgWithDetail("LoadBackupFailed", accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].message))
|
||||
}
|
||||
for _, app := range apps {
|
||||
retry := 0
|
||||
@@ -90,7 +90,7 @@ func (u *CronjobService) handleWebsite(cronjob model.Cronjob, startTime time.Tim
|
||||
}
|
||||
accountMap := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
|
||||
if !accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].isOk {
|
||||
return errors.New(i18n.GetMsgWithDetail("LoadBackupFailed", accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].message))
|
||||
return buserr.New(i18n.GetMsgWithDetail("LoadBackupFailed", accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].message))
|
||||
}
|
||||
for _, web := range webs {
|
||||
retry := 0
|
||||
@@ -149,7 +149,7 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Ti
|
||||
}
|
||||
accountMap := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
|
||||
if !accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].isOk {
|
||||
return errors.New(i18n.GetMsgWithDetail("LoadBackupFailed", accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].message))
|
||||
return buserr.New(i18n.GetMsgWithDetail("LoadBackupFailed", accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].message))
|
||||
}
|
||||
for _, dbInfo := range dbs {
|
||||
retry := 0
|
||||
@@ -178,7 +178,7 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Ti
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if err := doPostgresqlgBackup(dbInfo, backupDir, record.FileName, cronjob.Secret); err != nil {
|
||||
if err := doPostgresqlgBackup(dbInfo, backupDir, record.FileName, cronjob.Secret, taskItem); err != nil {
|
||||
if retry < int(cronjob.RetryTimes) || !cronjob.IgnoreErr {
|
||||
retry++
|
||||
return err
|
||||
@@ -217,7 +217,7 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Ti
|
||||
func (u *CronjobService) handleDirectory(cronjob model.Cronjob, startTime time.Time, taskItem *task.Task) error {
|
||||
accountMap := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
|
||||
if !accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].isOk {
|
||||
return errors.New(i18n.GetMsgWithDetail("LoadBackupFailed", accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].message))
|
||||
return buserr.New(i18n.GetMsgWithDetail("LoadBackupFailed", accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].message))
|
||||
}
|
||||
taskItem.AddSubTaskWithOps(task.GetTaskName(cronjob.SourceDir, task.TaskBackup, task.TaskScopeCronjob), func(task *task.Task) error {
|
||||
fileName := fmt.Sprintf("%s.tar.gz", startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(2))
|
||||
@@ -267,7 +267,7 @@ func (u *CronjobService) handleDirectory(cronjob model.Cronjob, startTime time.T
|
||||
func (u *CronjobService) handleSystemLog(cronjob model.Cronjob, startTime time.Time, taskItem *task.Task) error {
|
||||
accountMap := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
|
||||
if !accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].isOk {
|
||||
return errors.New(i18n.GetMsgWithDetail("LoadBackupFailed", accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].message))
|
||||
return buserr.New(i18n.GetMsgWithDetail("LoadBackupFailed", accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].message))
|
||||
}
|
||||
taskItem.AddSubTaskWithOps(task.GetTaskName(i18n.GetMsgByKey("SystemLog"), task.TaskBackup, task.TaskScopeCronjob), func(task *task.Task) error {
|
||||
nameItem := startTime.Format(constant.DateTimeSlimLayout) + common.RandStrAndNum(5)
|
||||
@@ -303,7 +303,7 @@ func (u *CronjobService) handleSystemLog(cronjob model.Cronjob, startTime time.T
|
||||
func (u *CronjobService) handleSnapshot(cronjob model.Cronjob, jobRecord model.JobRecords, taskItem *task.Task) error {
|
||||
accountMap := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
|
||||
if !accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].isOk {
|
||||
return errors.New(i18n.GetMsgWithDetail("LoadBackupFailed", accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].message))
|
||||
return buserr.New(i18n.GetMsgWithDetail("LoadBackupFailed", accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].message))
|
||||
}
|
||||
var record model.BackupRecord
|
||||
record.Status = constant.StatusSuccess
|
||||
|
||||
@@ -8,14 +8,13 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
pathUtils "path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/alert_push"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
@@ -147,7 +146,7 @@ func (u *CronjobService) handleShell(cronjob model.Cronjob, taskItem *task.Task)
|
||||
if len(cronjob.ContainerName) != 0 {
|
||||
scriptItem := cronjob.Script
|
||||
if cronjob.ScriptMode == "select" {
|
||||
scriptItem = path.Join("/tmp", path.Base(cronjob.Script))
|
||||
scriptItem = pathUtils.Join("/tmp", pathUtils.Base(cronjob.Script))
|
||||
if err := cmdMgr.Run("docker", "cp", cronjob.Script, cronjob.ContainerName+":"+scriptItem); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -195,10 +194,17 @@ func (u *CronjobService) handleShell(cronjob model.Cronjob, taskItem *task.Task)
|
||||
}
|
||||
|
||||
func (u *CronjobService) handleCurl(cronjob model.Cronjob, taskItem *task.Task) {
|
||||
taskItem.AddSubTaskWithOps(i18n.GetWithName("HandleShell", cronjob.Name), func(t *task.Task) error {
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTask(*taskItem))
|
||||
return cmdMgr.Run("curl", cronjob.URL)
|
||||
}, nil, int(cronjob.RetryTimes), time.Duration(cronjob.Timeout)*time.Second)
|
||||
urls := strings.Split(cronjob.URL, ",")
|
||||
for _, url := range urls {
|
||||
if len(strings.TrimSpace(url)) == 0 {
|
||||
continue
|
||||
}
|
||||
taskItem.AddSubTaskWithOps(i18n.GetWithName("HandleCurl", url), func(t *task.Task) error {
|
||||
taskItem.LogStart(i18n.GetWithName("HandleCurl", url))
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTask(*taskItem))
|
||||
return cmdMgr.Run("curl", url)
|
||||
}, nil, int(cronjob.RetryTimes), time.Duration(cronjob.Timeout)*time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
func (u *CronjobService) handleNtpSync(cronjob model.Cronjob, taskItem *task.Task) {
|
||||
@@ -245,11 +251,11 @@ func (u *CronjobService) handleCleanLog(cronjob model.Cronjob, taskItem *task.Ta
|
||||
if appInstall.ID > 0 {
|
||||
curStr := i18n.GetWithName("CleanLogByName", "OpenResty")
|
||||
t.LogStart(curStr)
|
||||
accessLogPath := path.Join(appInstall.GetPath(), "log", "access.log")
|
||||
accessLogPath := pathUtils.Join(appInstall.GetPath(), "log", "access.log")
|
||||
if err := os.Truncate(accessLogPath, 0); err != nil {
|
||||
t.LogFailedWithErr(curStr, err)
|
||||
}
|
||||
errLogPath := path.Join(appInstall.GetPath(), "log", "error.log")
|
||||
errLogPath := pathUtils.Join(appInstall.GetPath(), "log", "error.log")
|
||||
if err := os.Truncate(errLogPath, 0); err != nil {
|
||||
t.LogFailedWithErr(curStr, err)
|
||||
}
|
||||
@@ -267,8 +273,8 @@ func (u *CronjobService) handleSyncIpGroup(cronjob model.Cronjob, taskItem *task
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ipGroupDir := path.Join(appInstall.GetPath(), "1pwaf", "data", "rules", "ip_group")
|
||||
urlDir := path.Join(ipGroupDir, "ip_group_url")
|
||||
ipGroupDir := pathUtils.Join(appInstall.GetPath(), "1pwaf", "data", "rules", "ip_group")
|
||||
urlDir := pathUtils.Join(ipGroupDir, "ip_group_url")
|
||||
|
||||
urlsFiles, err := os.ReadDir(urlDir)
|
||||
if err != nil {
|
||||
@@ -332,7 +338,7 @@ func (u *CronjobService) handleSyncIpGroup(cronjob model.Cronjob, taskItem *task
|
||||
func (u *CronjobService) handleCutWebsiteLog(cronjob *model.Cronjob, startTime time.Time, taskItem *task.Task) error {
|
||||
clientMap := NewBackupClientMap([]string{fmt.Sprintf("%v", cronjob.DownloadAccountID)})
|
||||
if !clientMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].isOk {
|
||||
return errors.New(i18n.GetMsgWithDetail("LoadBackupFailed", clientMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].message))
|
||||
return buserr.New(i18n.GetMsgWithDetail("LoadBackupFailed", clientMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].message))
|
||||
}
|
||||
taskItem.AddSubTaskWithOps(i18n.GetWithName("CutWebsiteLog", cronjob.Name), func(t *task.Task) error {
|
||||
websites := loadWebsForJob(*cronjob)
|
||||
@@ -464,7 +470,7 @@ func (u *CronjobService) removeExpiredLog(cronjob model.Cronjob) {
|
||||
}
|
||||
_ = cronjobRepo.DeleteRecord(repo.WithByID(records[i].ID))
|
||||
_ = taskRepo.Delete(taskRepo.WithByID(records[i].TaskID))
|
||||
_ = os.Remove(path.Join(global.CONF.Base.InstallDir, "1panel/log/task/Cronjob", records[i].TaskID+".log"))
|
||||
_ = os.Remove(pathUtils.Join(global.CONF.Base.InstallDir, "1panel/log/task/Cronjob", records[i].TaskID+".log"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@@ -23,10 +24,9 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/controller"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/copier"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/psutil"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/shirou/gopsutil/v4/cpu"
|
||||
"github.com/shirou/gopsutil/v4/disk"
|
||||
"github.com/shirou/gopsutil/v4/host"
|
||||
"github.com/shirou/gopsutil/v4/load"
|
||||
"github.com/shirou/gopsutil/v4/mem"
|
||||
"github.com/shirou/gopsutil/v4/net"
|
||||
@@ -39,6 +39,8 @@ type IDashboardService interface {
|
||||
LoadBaseInfo(ioOption string, netOption string) (*dto.DashboardBase, error)
|
||||
LoadCurrentInfoForNode() *dto.NodeCurrent
|
||||
LoadCurrentInfo(ioOption string, netOption string) *dto.DashboardCurrent
|
||||
LoadTopCPU() []dto.Process
|
||||
LoadTopMem() []dto.Process
|
||||
|
||||
LoadQuickOptions() []dto.QuickJump
|
||||
ChangeQuick(req dto.ChangeQuicks) error
|
||||
@@ -77,7 +79,7 @@ func (u *DashboardService) Restart(operation string) error {
|
||||
|
||||
func (u *DashboardService) LoadOsInfo() (*dto.OsInfo, error) {
|
||||
var baseInfo dto.OsInfo
|
||||
hostInfo, err := host.Info()
|
||||
hostInfo, err := psutil.HOST.GetHostInfo(false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -86,8 +88,9 @@ func (u *DashboardService) LoadOsInfo() (*dto.OsInfo, error) {
|
||||
baseInfo.PlatformFamily = hostInfo.PlatformFamily
|
||||
baseInfo.KernelArch = hostInfo.KernelArch
|
||||
baseInfo.KernelVersion = hostInfo.KernelVersion
|
||||
baseInfo.PrettyDistro = psutil.HOST.GetDistro()
|
||||
|
||||
diskInfo, err := disk.Usage(global.Dir.BaseDir)
|
||||
diskInfo, err := psutil.DISK.GetUsage(global.Dir.BaseDir, false)
|
||||
if err == nil {
|
||||
baseInfo.DiskSize = int64(diskInfo.Free)
|
||||
}
|
||||
@@ -104,12 +107,17 @@ func (u *DashboardService) LoadOsInfo() (*dto.OsInfo, error) {
|
||||
func (u *DashboardService) LoadCurrentInfoForNode() *dto.NodeCurrent {
|
||||
var currentInfo dto.NodeCurrent
|
||||
|
||||
currentInfo.CPUTotal, _ = cpu.Counts(true)
|
||||
totalPercent, _ := cpu.Percent(100*time.Millisecond, false)
|
||||
if len(totalPercent) == 1 {
|
||||
currentInfo.CPUUsedPercent = totalPercent[0]
|
||||
currentInfo.CPUUsed = currentInfo.CPUUsedPercent * 0.01 * float64(currentInfo.CPUTotal)
|
||||
currentInfo.CPUTotal, _ = psutil.CPUInfo.GetLogicalCores(false)
|
||||
|
||||
cpuUsedPercent, perCore, cpuDetailedPercent := psutil.CPU.GetCPUUsage()
|
||||
if len(perCore) == 0 {
|
||||
currentInfo.CPUTotal = psutil.CPU.NumCPU()
|
||||
} else {
|
||||
currentInfo.CPUTotal = len(perCore)
|
||||
}
|
||||
currentInfo.CPUUsedPercent = cpuUsedPercent
|
||||
currentInfo.CPUUsed = cpuUsedPercent * 0.01 * float64(currentInfo.CPUTotal)
|
||||
currentInfo.CPUDetailedPercent = cpuDetailedPercent
|
||||
|
||||
loadInfo, _ := load.Avg()
|
||||
currentInfo.Load1 = loadInfo.Load1
|
||||
@@ -134,38 +142,39 @@ func (u *DashboardService) LoadCurrentInfoForNode() *dto.NodeCurrent {
|
||||
|
||||
func (u *DashboardService) LoadBaseInfo(ioOption string, netOption string) (*dto.DashboardBase, error) {
|
||||
var baseInfo dto.DashboardBase
|
||||
hostInfo, err := host.Info()
|
||||
hostInfo, err := psutil.HOST.GetHostInfo(false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
baseInfo.Hostname = hostInfo.Hostname
|
||||
baseInfo.OS = hostInfo.OS
|
||||
baseInfo.Platform = hostInfo.Platform
|
||||
baseInfo.PlatformFamily = hostInfo.PlatformFamily
|
||||
baseInfo.PlatformVersion = hostInfo.PlatformVersion
|
||||
baseInfo.KernelArch = hostInfo.KernelArch
|
||||
baseInfo.KernelVersion = hostInfo.KernelVersion
|
||||
ss, _ := json.Marshal(hostInfo)
|
||||
baseInfo.VirtualizationSystem = string(ss)
|
||||
baseInfo.IpV4Addr = loadOutboundIP()
|
||||
httpProxy := os.Getenv("http_proxy")
|
||||
if httpProxy == "" {
|
||||
httpProxy = os.Getenv("HTTP_PROXY")
|
||||
baseInfo = dto.DashboardBase{
|
||||
Hostname: hostInfo.Hostname,
|
||||
OS: hostInfo.OS,
|
||||
Platform: hostInfo.Platform,
|
||||
PlatformFamily: hostInfo.PlatformFamily,
|
||||
PlatformVersion: hostInfo.PlatformVersion,
|
||||
PrettyDistro: psutil.HOST.GetDistro(),
|
||||
KernelArch: hostInfo.KernelArch,
|
||||
KernelVersion: hostInfo.KernelVersion,
|
||||
VirtualizationSystem: string(ss),
|
||||
IpV4Addr: loadOutboundIP(),
|
||||
SystemProxy: "noProxy",
|
||||
}
|
||||
if httpProxy != "" {
|
||||
baseInfo.SystemProxy = httpProxy
|
||||
|
||||
if proxy := cmp.Or(os.Getenv("http_proxy"), os.Getenv("HTTP_PROXY")); proxy != "" {
|
||||
baseInfo.SystemProxy = proxy
|
||||
}
|
||||
baseInfo.SystemProxy = "noProxy"
|
||||
|
||||
loadQuickJump(&baseInfo)
|
||||
|
||||
cpuInfo, err := cpu.Info()
|
||||
if err == nil {
|
||||
cpuInfo, err := psutil.CPUInfo.GetCPUInfo(false)
|
||||
if err == nil && len(cpuInfo) > 0 {
|
||||
baseInfo.CPUModelName = cpuInfo[0].ModelName
|
||||
}
|
||||
|
||||
baseInfo.CPUCores, _ = cpu.Counts(false)
|
||||
baseInfo.CPULogicalCores, _ = cpu.Counts(true)
|
||||
baseInfo.CPUCores, _ = psutil.CPUInfo.GetPhysicalCores(false)
|
||||
baseInfo.CPULogicalCores, _ = psutil.CPUInfo.GetLogicalCores(false)
|
||||
baseInfo.CPUMhz = cpuInfo[0].Mhz
|
||||
|
||||
baseInfo.CurrentInfo = *u.LoadCurrentInfo(ioOption, netOption)
|
||||
return &baseInfo, nil
|
||||
@@ -173,18 +182,22 @@ func (u *DashboardService) LoadBaseInfo(ioOption string, netOption string) (*dto
|
||||
|
||||
func (u *DashboardService) LoadCurrentInfo(ioOption string, netOption string) *dto.DashboardCurrent {
|
||||
var currentInfo dto.DashboardCurrent
|
||||
hostInfo, _ := host.Info()
|
||||
hostInfo, _ := psutil.HOST.GetHostInfo(false)
|
||||
currentInfo.Uptime = hostInfo.Uptime
|
||||
currentInfo.TimeSinceUptime = time.Now().Add(-time.Duration(hostInfo.Uptime) * time.Second).Format(constant.DateTimeLayout)
|
||||
currentInfo.TimeSinceUptime = time.Unix(int64(hostInfo.BootTime), 0).Format(constant.DateTimeLayout)
|
||||
currentInfo.Procs = hostInfo.Procs
|
||||
currentInfo.CPUTotal, _ = psutil.CPUInfo.GetLogicalCores(false)
|
||||
|
||||
currentInfo.CPUTotal, _ = cpu.Counts(true)
|
||||
totalPercent, _ := cpu.Percent(100*time.Millisecond, false)
|
||||
if len(totalPercent) == 1 {
|
||||
currentInfo.CPUUsedPercent = totalPercent[0]
|
||||
currentInfo.CPUUsed = currentInfo.CPUUsedPercent * 0.01 * float64(currentInfo.CPUTotal)
|
||||
cpuUsedPercent, perCore, cpuDetailedPercent := psutil.CPU.GetCPUUsage()
|
||||
if len(perCore) == 0 {
|
||||
currentInfo.CPUTotal = psutil.CPU.NumCPU()
|
||||
} else {
|
||||
currentInfo.CPUTotal = len(perCore)
|
||||
}
|
||||
currentInfo.CPUPercent, _ = cpu.Percent(100*time.Millisecond, true)
|
||||
currentInfo.CPUPercent = perCore
|
||||
currentInfo.CPUUsedPercent = cpuUsedPercent
|
||||
currentInfo.CPUUsed = cpuUsedPercent * 0.01 * float64(currentInfo.CPUTotal)
|
||||
currentInfo.CPUDetailedPercent = cpuDetailedPercent
|
||||
|
||||
loadInfo, _ := load.Avg()
|
||||
currentInfo.Load1 = loadInfo.Load1
|
||||
@@ -211,9 +224,6 @@ func (u *DashboardService) LoadCurrentInfo(ioOption string, netOption string) *d
|
||||
currentInfo.GPUData = loadGPUInfo()
|
||||
currentInfo.XPUData = loadXpuInfo()
|
||||
|
||||
currentInfo.TopCPUItems = loadTopCPU()
|
||||
currentInfo.TopMemItems = loadTopMem()
|
||||
|
||||
if ioOption == "all" {
|
||||
diskInfo, _ := disk.IOCounters()
|
||||
for _, state := range diskInfo {
|
||||
@@ -246,6 +256,7 @@ func (u *DashboardService) LoadCurrentInfo(ioOption string, netOption string) *d
|
||||
if state.Name == netOption {
|
||||
currentInfo.NetBytesSent = state.BytesSent
|
||||
currentInfo.NetBytesRecv = state.BytesRecv
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,6 +265,14 @@ func (u *DashboardService) LoadCurrentInfo(ioOption string, netOption string) *d
|
||||
return ¤tInfo
|
||||
}
|
||||
|
||||
func (u *DashboardService) LoadTopCPU() []dto.Process {
|
||||
return loadTopCPU()
|
||||
}
|
||||
|
||||
func (u *DashboardService) LoadTopMem() []dto.Process {
|
||||
return loadTopMem()
|
||||
}
|
||||
|
||||
func (u *DashboardService) LoadAppLauncher(ctx *gin.Context) ([]dto.AppLauncher, error) {
|
||||
var data []dto.AppLauncher
|
||||
appInstalls, err := appInstallRepo.ListBy(context.Background())
|
||||
@@ -455,41 +474,52 @@ func loadDiskInfo() []dto.DiskInfo {
|
||||
)
|
||||
wg.Add(len(mounts))
|
||||
for i := 0; i < len(mounts); i++ {
|
||||
go func(timeoutCh <-chan time.Time, mount diskInfo) {
|
||||
go func(mount diskInfo) {
|
||||
defer wg.Done()
|
||||
|
||||
var itemData dto.DiskInfo
|
||||
itemData.Path = mount.Mount
|
||||
itemData.Type = mount.Type
|
||||
itemData.Device = mount.Device
|
||||
|
||||
type diskResult struct {
|
||||
state *disk.UsageStat
|
||||
err error
|
||||
}
|
||||
resultCh := make(chan diskResult, 1)
|
||||
|
||||
go func() {
|
||||
state, err := psutil.DISK.GetUsage(mount.Mount, false)
|
||||
resultCh <- diskResult{state: state, err: err}
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-timeoutCh:
|
||||
case <-time.After(5 * time.Second):
|
||||
mu.Lock()
|
||||
datas = append(datas, itemData)
|
||||
mu.Unlock()
|
||||
global.LOG.Errorf("load disk info from %s failed, err: timeout", mount.Mount)
|
||||
default:
|
||||
state, err := disk.Usage(mount.Mount)
|
||||
if err != nil {
|
||||
case result := <-resultCh:
|
||||
if result.err != nil {
|
||||
mu.Lock()
|
||||
datas = append(datas, itemData)
|
||||
mu.Unlock()
|
||||
global.LOG.Errorf("load disk info from %s failed, err: %v", mount.Mount, err)
|
||||
global.LOG.Errorf("load disk info from %s failed, err: %v", mount.Mount, result.err)
|
||||
return
|
||||
}
|
||||
itemData.Total = state.Total
|
||||
itemData.Free = state.Free
|
||||
itemData.Used = state.Used
|
||||
itemData.UsedPercent = state.UsedPercent
|
||||
itemData.InodesTotal = state.InodesTotal
|
||||
itemData.InodesUsed = state.InodesUsed
|
||||
itemData.InodesFree = state.InodesFree
|
||||
itemData.InodesUsedPercent = state.InodesUsedPercent
|
||||
itemData.Total = result.state.Total
|
||||
itemData.Free = result.state.Free
|
||||
itemData.Used = result.state.Used
|
||||
itemData.UsedPercent = result.state.UsedPercent
|
||||
itemData.InodesTotal = result.state.InodesTotal
|
||||
itemData.InodesUsed = result.state.InodesUsed
|
||||
itemData.InodesFree = result.state.InodesFree
|
||||
itemData.InodesUsedPercent = result.state.InodesUsedPercent
|
||||
mu.Lock()
|
||||
datas = append(datas, itemData)
|
||||
mu.Unlock()
|
||||
}
|
||||
}(time.After(5*time.Second), mounts[i])
|
||||
}(mounts[i])
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
|
||||
@@ -119,9 +119,10 @@ func (u *DatabaseService) CheckDatabase(req dto.DatabaseCreate) bool {
|
||||
if req.Timeout == 0 {
|
||||
req.Timeout = 30
|
||||
}
|
||||
var err error
|
||||
switch req.Type {
|
||||
case constant.AppPostgresql:
|
||||
_, err := postgresql.NewPostgresqlClient(pgclient.DBInfo{
|
||||
_, err = postgresql.NewPostgresqlClient(pgclient.DBInfo{
|
||||
From: "remote",
|
||||
Address: req.Address,
|
||||
Port: req.Port,
|
||||
@@ -130,17 +131,15 @@ func (u *DatabaseService) CheckDatabase(req dto.DatabaseCreate) bool {
|
||||
Password: req.Password,
|
||||
Timeout: req.Timeout,
|
||||
})
|
||||
return err == nil
|
||||
case constant.AppRedis:
|
||||
_, err := redisclient.NewRedisClient(redisclient.DBInfo{
|
||||
_, err = redisclient.NewRedisClient(redisclient.DBInfo{
|
||||
Address: req.Address,
|
||||
Port: req.Port,
|
||||
Password: req.Password,
|
||||
Timeout: req.Timeout,
|
||||
})
|
||||
return err == nil
|
||||
case "mysql", "mariadb":
|
||||
_, err := mysql.NewMysqlClient(client.DBInfo{
|
||||
_, err = mysql.NewMysqlClient(client.DBInfo{
|
||||
From: "remote",
|
||||
Address: req.Address,
|
||||
Port: req.Port,
|
||||
@@ -154,10 +153,13 @@ func (u *DatabaseService) CheckDatabase(req dto.DatabaseCreate) bool {
|
||||
SkipVerify: req.SkipVerify,
|
||||
Timeout: req.Timeout,
|
||||
})
|
||||
return err == nil
|
||||
}
|
||||
if err != nil {
|
||||
global.LOG.Errorf("check database connection failed, err: %v", err)
|
||||
return false
|
||||
}
|
||||
|
||||
return false
|
||||
return true
|
||||
}
|
||||
|
||||
func (u *DatabaseService) Create(req dto.DatabaseCreate) error {
|
||||
@@ -174,12 +176,13 @@ func (u *DatabaseService) Create(req dto.DatabaseCreate) error {
|
||||
switch req.Type {
|
||||
case constant.AppPostgresql:
|
||||
if _, err := postgresql.NewPostgresqlClient(pgclient.DBInfo{
|
||||
From: "remote",
|
||||
Address: req.Address,
|
||||
Port: req.Port,
|
||||
Username: req.Username,
|
||||
Password: req.Password,
|
||||
Timeout: req.Timeout,
|
||||
From: "remote",
|
||||
Address: req.Address,
|
||||
Port: req.Port,
|
||||
InitialDB: req.InitialDB,
|
||||
Username: req.Username,
|
||||
Password: req.Password,
|
||||
Timeout: req.Timeout,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -275,12 +278,13 @@ func (u *DatabaseService) Update(req dto.DatabaseUpdate) error {
|
||||
switch req.Type {
|
||||
case constant.AppPostgresql:
|
||||
if _, err := postgresql.NewPostgresqlClient(pgclient.DBInfo{
|
||||
From: "remote",
|
||||
Address: req.Address,
|
||||
Port: req.Port,
|
||||
Username: req.Username,
|
||||
Password: req.Password,
|
||||
Timeout: req.Timeout,
|
||||
From: "remote",
|
||||
Address: req.Address,
|
||||
Port: req.Port,
|
||||
InitialDB: req.InitialDB,
|
||||
Username: req.Username,
|
||||
Password: req.Password,
|
||||
Timeout: req.Timeout,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -326,6 +330,7 @@ func (u *DatabaseService) Update(req dto.DatabaseUpdate) error {
|
||||
upMap["port"] = req.Port
|
||||
upMap["username"] = req.Username
|
||||
upMap["password"] = pass
|
||||
upMap["initial_db"] = req.InitialDB
|
||||
upMap["timeout"] = req.Timeout
|
||||
upMap["description"] = req.Description
|
||||
upMap["ssl"] = req.SSL
|
||||
|
||||
@@ -5,8 +5,10 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
@@ -51,7 +53,14 @@ func (u *DBCommonService) LoadDatabaseFile(req dto.OperationWithNameAndType) (st
|
||||
case "mariadb-conf":
|
||||
filePath = path.Join(global.Dir.DataDir, fmt.Sprintf("apps/mariadb/%s/conf/my.cnf", req.Name))
|
||||
case "postgresql-conf":
|
||||
database, err := databaseRepo.Get(repo.WithByName(req.Name))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
filePath = path.Join(global.Dir.DataDir, fmt.Sprintf("apps/postgresql/%s/data/postgresql.conf", req.Name))
|
||||
if strings.HasPrefix(database.Version, "18.") {
|
||||
filePath = path.Join(global.Dir.DataDir, fmt.Sprintf("apps/postgresql/%s/data/18/docker/postgresql.conf", req.Name))
|
||||
}
|
||||
case "redis-conf":
|
||||
filePath = path.Join(global.Dir.DataDir, fmt.Sprintf("apps/redis/%s/conf/redis.conf", req.Name))
|
||||
case "redis-cluster-conf":
|
||||
@@ -76,8 +85,13 @@ func (u *DBCommonService) UpdateConfByFile(req dto.DBConfUpdateByFile) error {
|
||||
switch req.Type {
|
||||
case constant.AppMariaDB, constant.AppMysql, constant.AppMysqlCluster:
|
||||
path = fmt.Sprintf("%s/%s/%s/conf/my.cnf", global.Dir.AppInstallDir, req.Type, app.Name)
|
||||
case constant.AppPostgresql, constant.AppPostgresqlCluster:
|
||||
case constant.AppPostgresqlCluster:
|
||||
path = fmt.Sprintf("%s/%s/%s/data/postgresql.conf", global.Dir.AppInstallDir, req.Type, app.Name)
|
||||
case constant.AppPostgresql:
|
||||
path = fmt.Sprintf("%s/%s/%s/data/postgresql.conf", global.Dir.AppInstallDir, req.Type, app.Name)
|
||||
if strings.HasPrefix(app.Version, "18.") {
|
||||
path = fmt.Sprintf("%s/%s/%s/data/18/docker/postgresql.conf", global.Dir.AppInstallDir, req.Type, app.Name)
|
||||
}
|
||||
case constant.AppRedis, constant.AppRedisCluster:
|
||||
path = fmt.Sprintf("%s/%s/%s/conf/redis.conf", global.Dir.AppInstallDir, req.Type, app.Name)
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/compose"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/encrypt"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/mysql"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/re"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/mysql/client"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/re"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/pkg/errors"
|
||||
@@ -45,6 +45,7 @@ type IMysqlService interface {
|
||||
DeleteCheck(req dto.MysqlDBDeleteCheck) ([]dto.DBResource, error)
|
||||
Delete(ctx context.Context, req dto.MysqlDBDelete) error
|
||||
|
||||
LoadFormatOption(req dto.OperationWithName) []dto.MysqlFormatCollationOption
|
||||
LoadStatus(req dto.OperationWithNameAndType) (*dto.MysqlStatus, error)
|
||||
LoadVariables(req dto.OperationWithNameAndType) (*dto.MysqlVariables, error)
|
||||
LoadRemoteAccess(req dto.OperationWithNameAndType) (bool, error)
|
||||
@@ -99,7 +100,7 @@ func (u *MysqlService) ListDBOption() ([]dto.MysqlOption, error) {
|
||||
}
|
||||
|
||||
func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*model.DatabaseMysql, error) {
|
||||
if cmd.CheckIllegal(req.Name, req.Username, req.Password, req.Format, req.Permission) {
|
||||
if cmd.CheckIllegal(req.Name, req.Username, req.Password, req.Format, req.Collation, req.Permission) {
|
||||
return nil, buserr.New("ErrCmdIllegal")
|
||||
}
|
||||
|
||||
@@ -114,7 +115,7 @@ func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*mode
|
||||
}
|
||||
|
||||
if req.From == "local" && req.Username == "root" {
|
||||
return nil, errors.New("Cannot set root as user name")
|
||||
return nil, errors.New("cannot set root as user name")
|
||||
}
|
||||
|
||||
cli, version, err := LoadMysqlClientByFrom(req.Database)
|
||||
@@ -126,6 +127,7 @@ func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*mode
|
||||
if err := cli.Create(client.CreateInfo{
|
||||
Name: req.Name,
|
||||
Format: req.Format,
|
||||
Collation: req.Collation,
|
||||
Username: req.Username,
|
||||
Password: req.Password,
|
||||
Permission: req.Permission,
|
||||
@@ -584,6 +586,19 @@ func (u *MysqlService) LoadStatus(req dto.OperationWithNameAndType) (*dto.MysqlS
|
||||
return &info, nil
|
||||
}
|
||||
|
||||
func (u *MysqlService) LoadFormatOption(req dto.OperationWithName) []dto.MysqlFormatCollationOption {
|
||||
defaultList := []dto.MysqlFormatCollationOption{{Format: "utf8mb4"}, {Format: "utf8mb3"}, {Format: "gbk"}, {Format: "big5"}}
|
||||
client, _, err := LoadMysqlClientByFrom(req.Name)
|
||||
if err != nil {
|
||||
return defaultList
|
||||
}
|
||||
options, err := client.LoadFormatCollation(3)
|
||||
if err != nil {
|
||||
return defaultList
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
func executeSqlForMaps(containerName, dbType, password, command string) (map[string]string, error) {
|
||||
if dbType == "mysql-cluster" {
|
||||
dbType = "mysql"
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/postgresql/client"
|
||||
_ "github.com/jackc/pgx/v5/stdlib"
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type PostgresqlService struct{}
|
||||
@@ -138,10 +137,6 @@ func (u *PostgresqlService) Create(ctx context.Context, req dto.PostgresqlDBCrea
|
||||
return nil, buserr.WithDetail("ErrStructTransform", err.Error(), nil)
|
||||
}
|
||||
|
||||
if req.From == "local" && req.Username == "root" {
|
||||
return nil, errors.New("Cannot set root as user name")
|
||||
}
|
||||
|
||||
cli, err := LoadPostgresqlClientByFrom(req.Database)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -185,6 +180,7 @@ func LoadPostgresqlClientByFrom(database string) (postgresql.PostgresqlClient, e
|
||||
dbInfo.Port = databaseItem.Port
|
||||
dbInfo.Username = databaseItem.Username
|
||||
dbInfo.Password = databaseItem.Password
|
||||
dbInfo.InitialDB = databaseItem.InitialDB
|
||||
} else {
|
||||
app, err := appInstallRepo.LoadBaseInfo(databaseItem.Type, database)
|
||||
if err != nil {
|
||||
|
||||
@@ -80,9 +80,9 @@ func (u *RedisService) CheckHasCli() bool {
|
||||
|
||||
func (u *RedisService) InstallCli() error {
|
||||
item := dto.ContainerOperate{
|
||||
Name: "1Panel-redis-cli-tools",
|
||||
Image: "redis:7.4.4",
|
||||
Network: "1panel-network",
|
||||
Name: "1Panel-redis-cli-tools",
|
||||
Image: "redis:7.4.4",
|
||||
Networks: []dto.ContainerNetwork{{Network: "1panel-network"}},
|
||||
}
|
||||
return NewIContainerService().ContainerCreate(item, false)
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/controller"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/ntp"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/psutil"
|
||||
"github.com/shirou/gopsutil/v4/mem"
|
||||
)
|
||||
|
||||
@@ -134,6 +135,7 @@ func (u *DeviceService) Update(key, value string) error {
|
||||
if err := cmd.RunDefaultBashCf("%s hostnamectl set-hostname %s", cmd.SudoHandleCmd(), value); err != nil {
|
||||
return err
|
||||
}
|
||||
_, _ = psutil.HOST.GetHostInfo(true)
|
||||
case "Ntp", "LocalTime":
|
||||
if cmd.CheckIllegal(value) {
|
||||
return buserr.New("ErrCmdIllegal")
|
||||
|
||||
@@ -413,6 +413,7 @@ func loadContainerTree() []dto.CleanTree {
|
||||
if err != nil {
|
||||
return treeData
|
||||
}
|
||||
defer client.Close()
|
||||
diskUsage, err := client.DiskUsage(context.Background(), types.DiskUsageOptions{})
|
||||
if err != nil {
|
||||
return treeData
|
||||
@@ -552,6 +553,7 @@ func dropBuildCache() (int, int) {
|
||||
global.LOG.Errorf("do not get docker client")
|
||||
return 0, 0
|
||||
}
|
||||
defer client.Close()
|
||||
opts := build.CachePruneOptions{}
|
||||
opts.All = true
|
||||
res, err := client.BuildCachePrune(context.Background(), opts)
|
||||
@@ -568,6 +570,7 @@ func dropImages() (int, int) {
|
||||
global.LOG.Errorf("do not get docker client")
|
||||
return 0, 0
|
||||
}
|
||||
defer client.Close()
|
||||
pruneFilters := filters.NewArgs()
|
||||
pruneFilters.Add("dangling", "false")
|
||||
res, err := client.ImagesPrune(context.Background(), pruneFilters)
|
||||
@@ -584,6 +587,7 @@ func dropContainers() (int, int) {
|
||||
global.LOG.Errorf("do not get docker client")
|
||||
return 0, 0
|
||||
}
|
||||
defer client.Close()
|
||||
pruneFilters := filters.NewArgs()
|
||||
res, err := client.ContainersPrune(context.Background(), pruneFilters)
|
||||
if err != nil {
|
||||
@@ -599,6 +603,7 @@ func dropVolumes() (int, int) {
|
||||
global.LOG.Errorf("do not get docker client")
|
||||
return 0, 0
|
||||
}
|
||||
defer client.Close()
|
||||
pruneFilters := filters.NewArgs()
|
||||
versions, err := client.ServerVersion(context.Background())
|
||||
if err != nil {
|
||||
@@ -647,11 +652,13 @@ func dropTaskLog(logDir string) {
|
||||
if err == nil {
|
||||
_ = xpackDB.Table("tampers").Where("task_id != ?", "").Select("task_id").Find(&usedTasks).Error
|
||||
}
|
||||
defer common.CloseDB(xpackDB)
|
||||
case "System":
|
||||
xpackDB, err := common.LoadDBConnByPathWithErr(path.Join(global.CONF.Base.InstallDir, "1panel/db/xpack.db"), "xpack.db")
|
||||
if err == nil {
|
||||
_ = xpackDB.Model("nodes").Where("task_id != ?", "").Select("task_id").Find(&usedTasks).Error
|
||||
}
|
||||
defer common.CloseDB(xpackDB)
|
||||
default:
|
||||
dropFileOrDir(logDir)
|
||||
_ = taskRepo.Delete(repo.WithByType(taskType))
|
||||
|
||||
+11
-12
@@ -32,20 +32,19 @@ func (s *DiskService) GetCompleteDiskInfo() (*response.CompleteDiskInfo, error)
|
||||
output, err := cmd.RunDefaultWithStdoutBashC("lsblk -J -o NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE,MODEL,SERIAL,TRAN,ROTA")
|
||||
if err == nil {
|
||||
diskInfos, err = parseLsblkJsonOutput(output)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse lsblk output: %v", err)
|
||||
}
|
||||
} else {
|
||||
output, err = cmd.RunDefaultWithStdoutBashC("lsblk -P -o NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE,MODEL,SERIAL,TRAN,ROTA")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to run lsblk command: %v", err)
|
||||
}
|
||||
diskInfos, err = parseLsblkOutput(output)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse lsblk output: %v", err)
|
||||
if err == nil {
|
||||
result := organizeDiskInfo(diskInfos)
|
||||
return &result, nil
|
||||
}
|
||||
}
|
||||
|
||||
output, err = cmd.RunDefaultWithStdoutBashC("lsblk -P -o NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE,MODEL,SERIAL,TRAN,ROTA")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to run lsblk command: %v", err)
|
||||
}
|
||||
diskInfos, err = parseLsblkOutput(output)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse lsblk output: %v", err)
|
||||
}
|
||||
result := organizeDiskInfo(diskInfos)
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
@@ -5,10 +5,6 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/task"
|
||||
"github.com/1Panel-dev/1Panel/agent/i18n"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/convert"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/ini_conf"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
@@ -21,6 +17,11 @@ import (
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/task"
|
||||
"github.com/1Panel-dev/1Panel/agent/i18n"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/convert"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/ini_conf"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/jinzhu/copier"
|
||||
"golang.org/x/text/encoding"
|
||||
@@ -241,6 +242,8 @@ func (f *FileService) Create(op request.FileCreate) error {
|
||||
if err := fo.LinkFile(op.LinkPath, op.Path, op.IsSymlink); err != nil {
|
||||
return err
|
||||
}
|
||||
handleDefaultOwn(op.Path)
|
||||
return nil
|
||||
}
|
||||
if err := fo.CreateFileWithMode(op.Path, fs.FileMode(mode)); err != nil {
|
||||
return err
|
||||
@@ -591,7 +594,7 @@ func (f *FileService) ReadLogByLine(req request.FileReadByLineReq) (*response.Fi
|
||||
scope string
|
||||
logFileRes *dto.LogFileRes
|
||||
)
|
||||
if stat.Size() > 500*1024*1024 {
|
||||
if stat.Size() > files.MaxReadFileSize {
|
||||
lines, err = files.TailFromEnd(logFilePath, req.PageSize)
|
||||
isEndOfFile = true
|
||||
scope = "tail"
|
||||
|
||||
@@ -68,7 +68,7 @@ func (u *FirewallService) LoadBaseInfo(tab string) (dto.FirewallBaseInfo, error)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
baseInfo.IsActive, _ = client.Status()
|
||||
baseInfo.IsInit, baseInfo.IsBind = loadInitStatus(baseInfo.Name, tab)
|
||||
baseInfo.IsInit, baseInfo.IsBind = iptables.LoadInitStatus(baseInfo.Name, tab)
|
||||
}()
|
||||
wg.Wait()
|
||||
return baseInfo, nil
|
||||
@@ -826,96 +826,3 @@ func checkPortUsed(ports, proto string, apps []portOfApp) string {
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func loadInitStatus(clientName, tab string) (bool, bool) {
|
||||
if clientName == "firewalld" {
|
||||
return true, true
|
||||
}
|
||||
if clientName == "ufw" && tab != "forward" {
|
||||
return true, true
|
||||
}
|
||||
switch tab {
|
||||
case "base":
|
||||
if isExist, _ := iptables.CheckChainExist(iptables.FilterTab, iptables.Chain1PanelBasicBefore); !isExist {
|
||||
return false, false
|
||||
}
|
||||
if exist := iptables.CheckRuleExist(iptables.FilterTab, iptables.Chain1PanelBasicBefore, iptables.IoRuleIn); !exist {
|
||||
return false, false
|
||||
}
|
||||
if exist := iptables.CheckRuleExist(iptables.FilterTab, iptables.Chain1PanelBasicBefore, iptables.EstablishedRule); !exist {
|
||||
return false, false
|
||||
}
|
||||
if exist, _ := iptables.CheckChainExist(iptables.FilterTab, iptables.Chain1PanelBasic); !exist {
|
||||
return false, false
|
||||
}
|
||||
if exist, _ := iptables.CheckChainExist(iptables.FilterTab, iptables.Chain1PanelBasicAfter); !exist {
|
||||
return false, false
|
||||
}
|
||||
if exist := iptables.CheckRuleExist(iptables.FilterTab, iptables.Chain1PanelBasicAfter, iptables.DropAllTcp); !exist {
|
||||
return false, false
|
||||
}
|
||||
if exist := iptables.CheckRuleExist(iptables.FilterTab, iptables.Chain1PanelBasicAfter, iptables.DropAllUdp); !exist {
|
||||
return false, false
|
||||
}
|
||||
if bind, _ := iptables.CheckChainBind(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicBefore); !bind {
|
||||
return true, false
|
||||
}
|
||||
if bind, _ := iptables.CheckChainBind(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasic); !bind {
|
||||
return true, false
|
||||
}
|
||||
if bind, _ := iptables.CheckChainBind(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicAfter); !bind {
|
||||
return true, false
|
||||
}
|
||||
return true, true
|
||||
case "advance":
|
||||
isExist, _ := iptables.CheckChainExist(iptables.FilterTab, iptables.Chain1PanelInput)
|
||||
if !isExist {
|
||||
return false, false
|
||||
}
|
||||
isExist, _ = iptables.CheckChainExist(iptables.FilterTab, iptables.Chain1PanelOutput)
|
||||
if !isExist {
|
||||
return false, false
|
||||
}
|
||||
|
||||
isBind, _ := iptables.CheckChainBind(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelInput)
|
||||
if !isBind {
|
||||
return true, false
|
||||
}
|
||||
isBind, _ = iptables.CheckChainBind(iptables.FilterTab, iptables.ChainOutput, iptables.Chain1PanelOutput)
|
||||
return true, isBind
|
||||
case "forward":
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashC("cat /proc/sys/net/ipv4/ip_forward")
|
||||
if err != nil {
|
||||
global.LOG.Errorf("check /proc/sys/net/ipv4/ip_forward failed, err: %v", err)
|
||||
return false, false
|
||||
}
|
||||
if strings.TrimSpace(stdout) == "0" {
|
||||
return false, false
|
||||
}
|
||||
|
||||
exist, _ := iptables.CheckChainExist(iptables.NatTab, iptables.Chain1PanelPreRouting)
|
||||
if !exist {
|
||||
return false, false
|
||||
}
|
||||
exist, _ = iptables.CheckChainExist(iptables.NatTab, iptables.Chain1PanelPostRouting)
|
||||
if !exist {
|
||||
return false, false
|
||||
}
|
||||
exist, _ = iptables.CheckChainExist(iptables.FilterTab, iptables.Chain1PanelForward)
|
||||
if !exist {
|
||||
return false, false
|
||||
}
|
||||
isBind, _ := iptables.CheckChainBind(iptables.NatTab, "PREROUTING", iptables.Chain1PanelPreRouting)
|
||||
if !isBind {
|
||||
return false, false
|
||||
}
|
||||
isBind, _ = iptables.CheckChainBind(iptables.NatTab, "POSTROUTING", iptables.Chain1PanelPostRouting)
|
||||
if !isBind {
|
||||
return false, false
|
||||
}
|
||||
isBind, _ = iptables.CheckChainBind(iptables.FilterTab, "FORWARD", iptables.Chain1PanelForward)
|
||||
return true, isBind
|
||||
default:
|
||||
return false, false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,6 +128,18 @@ func (u *ImageService) Page(req dto.PageImage) (int64, interface{}, error) {
|
||||
})
|
||||
}
|
||||
|
||||
imageDescriptions, _ := settingRepo.GetDescriptionList(repo.WithByType("image"))
|
||||
for i := 0; i < len(list); i++ {
|
||||
for _, desc := range imageDescriptions {
|
||||
if "sha256:"+desc.ID == records[i].ID {
|
||||
records[i].Description = desc.Description
|
||||
records[i].IsPinned = desc.IsPinned
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Slice(records, func(i, j int) bool {
|
||||
return records[i].IsPinned && !records[j].IsPinned
|
||||
})
|
||||
total, start, end := len(records), (req.Page-1)*req.PageSize, req.Page*req.PageSize
|
||||
if start > total {
|
||||
backDatas = make([]dto.ImageInfo, 0)
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/firewall/client"
|
||||
@@ -16,7 +17,7 @@ import (
|
||||
|
||||
type IIptablesService interface {
|
||||
Search(req dto.SearchPageWithType) (int64, interface{}, error)
|
||||
OperateRule(req dto.IptablesRuleOp) error
|
||||
OperateRule(req dto.IptablesRuleOp, withSave bool) error
|
||||
BatchOperate(req dto.IptablesBatchOperate) error
|
||||
LoadChainStatus(req dto.OperationWithName) dto.IptablesChainStatus
|
||||
|
||||
@@ -63,7 +64,7 @@ func (s *IptablesService) Search(req dto.SearchPageWithType) (int64, interface{}
|
||||
return int64(total), records, nil
|
||||
}
|
||||
|
||||
func (s *IptablesService) OperateRule(req dto.IptablesRuleOp) error {
|
||||
func (s *IptablesService) OperateRule(req dto.IptablesRuleOp, withSave bool) error {
|
||||
action := "ACCEPT"
|
||||
if req.Strategy == "drop" {
|
||||
action = "DROP"
|
||||
@@ -122,6 +123,9 @@ func (s *IptablesService) OperateRule(req dto.IptablesRuleOp) error {
|
||||
}
|
||||
}
|
||||
|
||||
if !withSave {
|
||||
return nil
|
||||
}
|
||||
if err := iptables.SaveRulesToFile(iptables.FilterTab, req.Chain, name); err != nil {
|
||||
global.LOG.Errorf("persistence for %s failed, err: %v", iptables.Chain1PanelBasic, err)
|
||||
}
|
||||
@@ -129,11 +133,23 @@ func (s *IptablesService) OperateRule(req dto.IptablesRuleOp) error {
|
||||
}
|
||||
|
||||
func (s *IptablesService) BatchOperate(req dto.IptablesBatchOperate) error {
|
||||
if len(req.Rules) == 0 {
|
||||
return errors.New("no rules to operate")
|
||||
}
|
||||
for _, rule := range req.Rules {
|
||||
if err := s.OperateRule(rule); err != nil {
|
||||
if err := s.OperateRule(rule, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
chain := iptables.Chain1PanelInput
|
||||
fileName := iptables.InputFileName
|
||||
if req.Rules[0].Chain == iptables.Chain1PanelOutput {
|
||||
chain = iptables.Chain1PanelOutput
|
||||
fileName = iptables.OutputFileName
|
||||
}
|
||||
if err := iptables.SaveRulesToFile(iptables.FilterTab, chain, fileName); err != nil {
|
||||
global.LOG.Errorf("persistence for %s failed, err: %v", iptables.Chain1PanelBasic, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -168,9 +184,20 @@ func (s *IptablesService) Operate(req dto.IptablesOp) error {
|
||||
if err := iptables.BindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicAfter, 3); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := iptables.SaveRulesToFile(iptables.FilterTab, iptables.Chain1PanelBasicBefore, iptables.BasicBeforeFileName); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := iptables.SaveRulesToFile(iptables.FilterTab, iptables.Chain1PanelBasicAfter, iptables.BasicAfterFileName); err != nil {
|
||||
return err
|
||||
}
|
||||
_ = settingRepo.Update("IptablesStatus", constant.StatusEnable)
|
||||
return nil
|
||||
case "init-forward":
|
||||
return client.EnableIptablesForward()
|
||||
if err := client.EnableIptablesForward(); err != nil {
|
||||
return err
|
||||
}
|
||||
_ = settingRepo.Update("IptablesForwardStatus", constant.StatusEnable)
|
||||
return nil
|
||||
case "init-advance":
|
||||
if err := iptables.AddChain(iptables.FilterTab, iptables.Chain1PanelInput); err != nil {
|
||||
return err
|
||||
@@ -185,6 +212,8 @@ func (s *IptablesService) Operate(req dto.IptablesOp) error {
|
||||
if err := iptables.BindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelInput, number); err != nil {
|
||||
return err
|
||||
}
|
||||
_ = settingRepo.Update("IptablesInputStatus", constant.StatusEnable)
|
||||
_ = settingRepo.Update("IptablesOutputStatus", constant.StatusEnable)
|
||||
return nil
|
||||
case "bind-base":
|
||||
if err := initPreRules(); err != nil {
|
||||
@@ -199,6 +228,7 @@ func (s *IptablesService) Operate(req dto.IptablesOp) error {
|
||||
if err := iptables.BindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicAfter, 3); err != nil {
|
||||
return err
|
||||
}
|
||||
_ = settingRepo.Update("IptablesStatus", constant.StatusEnable)
|
||||
return nil
|
||||
case "unbind-base":
|
||||
if err := iptables.UnbindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasicAfter); err != nil {
|
||||
@@ -210,16 +240,29 @@ func (s *IptablesService) Operate(req dto.IptablesOp) error {
|
||||
if err := iptables.UnbindChain(iptables.FilterTab, iptables.ChainInput, iptables.Chain1PanelBasic); err != nil {
|
||||
return err
|
||||
}
|
||||
_ = settingRepo.Update("IptablesStatus", constant.StatusDisable)
|
||||
return nil
|
||||
case "bind":
|
||||
if err := iptables.BindChain(iptables.FilterTab, targetChain, req.Name, loadBindNumber(req.Name)); err != nil {
|
||||
return err
|
||||
}
|
||||
if req.Name == iptables.Chain1PanelInput {
|
||||
_ = settingRepo.Update("IptablesInputStatus", constant.StatusEnable)
|
||||
}
|
||||
if req.Name == iptables.Chain1PanelOutput {
|
||||
_ = settingRepo.Update("IptablesOutputStatus", constant.StatusEnable)
|
||||
}
|
||||
return nil
|
||||
case "unbind":
|
||||
if err := iptables.UnbindChain(iptables.FilterTab, targetChain, req.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
if req.Name == iptables.Chain1PanelInput {
|
||||
_ = settingRepo.Update("IptablesInputStatus", constant.StatusDisable)
|
||||
}
|
||||
if req.Name == iptables.Chain1PanelOutput {
|
||||
_ = settingRepo.Update("IptablesOutputStatus", constant.StatusDisable)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
@@ -310,16 +353,7 @@ func initPreRules() error {
|
||||
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, iptables.EstablishedRule); err != nil {
|
||||
return err
|
||||
}
|
||||
panelPort := ""
|
||||
if !global.IsMaster {
|
||||
panelPort = global.CONF.Base.Port
|
||||
} else {
|
||||
var portSetting model.Setting
|
||||
_ = global.CoreDB.Where("key = ?", "ServerPort").First(&portSetting).Error
|
||||
if len(portSetting.Value) != 0 {
|
||||
panelPort = portSetting.Value
|
||||
}
|
||||
}
|
||||
panelPort := LoadPanelPort()
|
||||
if len(panelPort) == 0 {
|
||||
return errors.New("find 1panel service port failed")
|
||||
}
|
||||
@@ -337,3 +371,16 @@ func initPreRules() error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func LoadPanelPort() string {
|
||||
if !global.IsMaster {
|
||||
return global.CONF.Base.Port
|
||||
} else {
|
||||
var portSetting model.Setting
|
||||
_ = global.CoreDB.Where("key = ?", "ServerPort").First(&portSetting).Error
|
||||
if len(portSetting.Value) != 0 {
|
||||
return portSetting.Value
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
@@ -15,7 +16,10 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/ai_tools/gpu"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/ai_tools/xpu"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/psutil"
|
||||
"github.com/robfig/cron/v3"
|
||||
"github.com/shirou/gopsutil/v4/cpu"
|
||||
"github.com/shirou/gopsutil/v4/disk"
|
||||
@@ -35,6 +39,8 @@ var monitorCancel context.CancelFunc
|
||||
type IMonitorService interface {
|
||||
Run()
|
||||
LoadMonitorData(req dto.MonitorSearch) ([]dto.MonitorData, error)
|
||||
LoadGPUOptions() dto.MonitorGPUOptions
|
||||
LoadGPUMonitorData(req dto.MonitorGPUSearch) (dto.MonitorGPUData, error)
|
||||
LoadSetting() (*dto.MonitorSetting, error)
|
||||
UpdateSetting(key, value string) error
|
||||
CleanData() error
|
||||
@@ -113,6 +119,78 @@ func (m *MonitorService) LoadMonitorData(req dto.MonitorSearch) ([]dto.MonitorDa
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (m *MonitorService) LoadGPUOptions() dto.MonitorGPUOptions {
|
||||
var data dto.MonitorGPUOptions
|
||||
gpuExist, gpuClient := gpu.New()
|
||||
xpuExist, xpuClient := xpu.New()
|
||||
if !gpuExist && !xpuExist {
|
||||
return data
|
||||
}
|
||||
if gpuExist {
|
||||
data.GPUType = "gpu"
|
||||
gpuInfo, err := gpuClient.LoadGpuInfo()
|
||||
if err != nil || len(gpuInfo.GPUs) == 0 {
|
||||
global.LOG.Error("Load GPU info failed or no GPU found, err: ", err)
|
||||
return data
|
||||
}
|
||||
sort.Slice(gpuInfo.GPUs, func(i, j int) bool {
|
||||
return gpuInfo.GPUs[i].Index < gpuInfo.GPUs[j].Index
|
||||
})
|
||||
for _, item := range gpuInfo.GPUs {
|
||||
data.Options = append(data.Options, fmt.Sprintf("%d - %s", item.Index, item.ProductName))
|
||||
}
|
||||
return data
|
||||
} else {
|
||||
data.GPUType = "xpu"
|
||||
var err error
|
||||
data.Options, err = xpuClient.LoadDeviceList()
|
||||
if err != nil || len(data.Options) == 0 {
|
||||
global.LOG.Error("Load XPU info failed or no XPU found, err: ", err)
|
||||
}
|
||||
return data
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MonitorService) LoadGPUMonitorData(req dto.MonitorGPUSearch) (dto.MonitorGPUData, error) {
|
||||
loc, _ := time.LoadLocation(common.LoadTimeZoneByCmd())
|
||||
req.StartTime = req.StartTime.In(loc)
|
||||
req.EndTime = req.EndTime.In(loc)
|
||||
var data dto.MonitorGPUData
|
||||
gpuList, err := monitorRepo.GetGPU(repo.WithByCreatedAt(req.StartTime, req.EndTime), monitorRepo.WithByProductName(req.ProductName))
|
||||
if err != nil {
|
||||
return data, err
|
||||
}
|
||||
|
||||
for _, gpu := range gpuList {
|
||||
data.Date = append(data.Date, gpu.CreatedAt)
|
||||
data.GPUValue = append(data.GPUValue, gpu.GPUUtil)
|
||||
data.TemperatureValue = append(data.TemperatureValue, gpu.Temperature)
|
||||
data.PowerUsed = append(data.PowerUsed, gpu.PowerDraw)
|
||||
data.PowerTotal = append(data.PowerTotal, gpu.MaxPowerLimit)
|
||||
if gpu.MaxPowerLimit != 0 {
|
||||
data.PowerPercent = append(data.PowerPercent, gpu.PowerDraw/gpu.MaxPowerLimit*100)
|
||||
} else {
|
||||
data.PowerPercent = append(data.PowerPercent, float64(0))
|
||||
}
|
||||
|
||||
data.MemoryTotal = append(data.MemoryTotal, gpu.MemTotal)
|
||||
data.MemoryUsed = append(data.MemoryUsed, gpu.MemUsed)
|
||||
if gpu.MemTotal != 0 {
|
||||
data.MemoryPercent = append(data.MemoryPercent, gpu.MemUsed/gpu.MemTotal*100)
|
||||
} else {
|
||||
data.MemoryPercent = append(data.MemoryPercent, float64(0))
|
||||
}
|
||||
var process []dto.GPUProcess
|
||||
if err := json.Unmarshal([]byte(gpu.Processes), &process); err == nil {
|
||||
data.GPUProcesses = append(data.GPUProcesses, process)
|
||||
} else {
|
||||
data.GPUProcesses = append(data.GPUProcesses, []dto.GPUProcess{})
|
||||
}
|
||||
data.SpeedValue = append(data.SpeedValue, gpu.FanSpeed)
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (m *MonitorService) LoadSetting() (*dto.MonitorSetting, error) {
|
||||
setting, err := settingRepo.GetList()
|
||||
if err != nil {
|
||||
@@ -174,10 +252,13 @@ func (m *MonitorService) CleanData() error {
|
||||
if err := global.MonitorDB.Exec("DELETE FROM monitor_networks").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
_ = global.GPUMonitorDB.Exec("DELETE FROM monitor_gpus").Error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MonitorService) Run() {
|
||||
saveGPUDataToDB()
|
||||
saveXPUDataToDB()
|
||||
var itemModel model.MonitorBase
|
||||
totalPercent, _ := cpu.Percent(3*time.Second, false)
|
||||
if len(totalPercent) == 1 {
|
||||
@@ -190,7 +271,7 @@ func (m *MonitorService) Run() {
|
||||
itemModel.TopCPU = string(topItemCPU)
|
||||
}
|
||||
}
|
||||
cpuCount, _ := cpu.Counts(false)
|
||||
cpuCount, _ := psutil.CPUInfo.GetPhysicalCores(false)
|
||||
loadInfo, _ := load.Avg()
|
||||
itemModel.CpuLoad1 = loadInfo.Load1
|
||||
itemModel.CpuLoad5 = loadInfo.Load5
|
||||
@@ -207,7 +288,7 @@ func (m *MonitorService) Run() {
|
||||
}
|
||||
}
|
||||
|
||||
if err := settingRepo.CreateMonitorBase(itemModel); err != nil {
|
||||
if err := monitorRepo.CreateMonitorBase(itemModel); err != nil {
|
||||
global.LOG.Errorf("Insert basic monitoring data failed, err: %v", err)
|
||||
}
|
||||
|
||||
@@ -220,9 +301,9 @@ func (m *MonitorService) Run() {
|
||||
}
|
||||
storeDays, _ := strconv.Atoi(MonitorStoreDays.Value)
|
||||
timeForDelete := time.Now().AddDate(0, 0, -storeDays)
|
||||
_ = settingRepo.DelMonitorBase(timeForDelete)
|
||||
_ = settingRepo.DelMonitorIO(timeForDelete)
|
||||
_ = settingRepo.DelMonitorNet(timeForDelete)
|
||||
_ = monitorRepo.DelMonitorBase(timeForDelete)
|
||||
_ = monitorRepo.DelMonitorIO(timeForDelete)
|
||||
_ = monitorRepo.DelMonitorNet(timeForDelete)
|
||||
}
|
||||
|
||||
func (m *MonitorService) loadDiskIO() {
|
||||
@@ -302,7 +383,7 @@ func (m *MonitorService) saveIODataToDB(ctx context.Context, interval float64) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := settingRepo.BatchCreateMonitorIO(ioList); err != nil {
|
||||
if err := monitorRepo.BatchCreateMonitorIO(ioList); err != nil {
|
||||
global.LOG.Errorf("Insert io monitoring data failed, err: %v", err)
|
||||
}
|
||||
m.DiskIO <- ioStat2
|
||||
@@ -341,7 +422,7 @@ func (m *MonitorService) saveNetDataToDB(ctx context.Context, interval float64)
|
||||
}
|
||||
}
|
||||
|
||||
if err := settingRepo.BatchCreateMonitorNet(netList); err != nil {
|
||||
if err := monitorRepo.BatchCreateMonitorNet(netList); err != nil {
|
||||
global.LOG.Errorf("Insert network monitoring data failed, err: %v", err)
|
||||
}
|
||||
m.NetIO <- netStat2
|
||||
@@ -482,3 +563,92 @@ func StartMonitor(removeBefore bool, interval string) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func saveGPUDataToDB() {
|
||||
exist, client := gpu.New()
|
||||
if !exist {
|
||||
return
|
||||
}
|
||||
gpuInfo, err := client.LoadGpuInfo()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var list []model.MonitorGPU
|
||||
for _, gpuItem := range gpuInfo.GPUs {
|
||||
item := model.MonitorGPU{
|
||||
ProductName: fmt.Sprintf("%d - %s", gpuItem.Index, gpuItem.ProductName),
|
||||
GPUUtil: loadGPUInfoFloat(gpuItem.GPUUtil),
|
||||
Temperature: loadGPUInfoFloat(gpuItem.Temperature),
|
||||
PowerDraw: loadGPUInfoFloat(gpuItem.PowerDraw),
|
||||
MaxPowerLimit: loadGPUInfoFloat(gpuItem.MaxPowerLimit),
|
||||
MemUsed: loadGPUInfoFloat(gpuItem.MemUsed),
|
||||
MemTotal: loadGPUInfoFloat(gpuItem.MemTotal),
|
||||
FanSpeed: loadGPUInfoInt(gpuItem.FanSpeed),
|
||||
}
|
||||
process, _ := json.Marshal(gpuItem.Processes)
|
||||
if len(process) != 0 {
|
||||
item.Processes = string(process)
|
||||
}
|
||||
list = append(list, item)
|
||||
}
|
||||
if err := repo.NewIMonitorRepo().BatchCreateMonitorGPU(list); err != nil {
|
||||
global.LOG.Errorf("batch create gpu monitor data failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
func saveXPUDataToDB() {
|
||||
exist, client := xpu.New()
|
||||
if !exist {
|
||||
return
|
||||
}
|
||||
xpuInfo, err := client.LoadGpuInfo()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var list []model.MonitorGPU
|
||||
for _, xpuItem := range xpuInfo.Xpu {
|
||||
item := model.MonitorGPU{
|
||||
ProductName: fmt.Sprintf("%d - %s", xpuItem.Basic.DeviceID, xpuItem.Basic.DeviceName),
|
||||
Temperature: loadGPUInfoFloat(xpuItem.Stats.Temperature),
|
||||
PowerDraw: loadGPUInfoFloat(xpuItem.Stats.Power),
|
||||
MemUsed: loadGPUInfoFloat(xpuItem.Stats.MemoryUsed),
|
||||
MemTotal: loadGPUInfoFloat(xpuItem.Basic.Memory),
|
||||
}
|
||||
if len(xpuItem.Processes) != 0 {
|
||||
var processItem []dto.GPUProcess
|
||||
for _, ps := range xpuItem.Processes {
|
||||
processItem = append(processItem, dto.GPUProcess{
|
||||
Pid: fmt.Sprintf("%v", ps.PID),
|
||||
Type: ps.SHR,
|
||||
ProcessName: ps.Command,
|
||||
UsedMemory: ps.Memory,
|
||||
})
|
||||
}
|
||||
process, _ := json.Marshal(processItem)
|
||||
if len(process) != 0 {
|
||||
item.Processes = string(process)
|
||||
}
|
||||
}
|
||||
list = append(list, item)
|
||||
}
|
||||
if err := repo.NewIMonitorRepo().BatchCreateMonitorGPU(list); err != nil {
|
||||
global.LOG.Errorf("batch create gpu monitor data failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
func loadGPUInfoInt(val string) int {
|
||||
val = strings.TrimSuffix(val, "%")
|
||||
val = strings.TrimSpace(val)
|
||||
data, _ := strconv.Atoi(val)
|
||||
return data
|
||||
}
|
||||
func loadGPUInfoFloat(val string) float64 {
|
||||
val = strings.TrimSpace(val)
|
||||
suffixes := []string{"W", "MB", "MiB", "°C", "C", "%"}
|
||||
for _, suffix := range suffixes {
|
||||
val = strings.TrimSuffix(val, suffix)
|
||||
}
|
||||
val = strings.TrimSpace(val)
|
||||
data, _ := strconv.ParseFloat(val, 64)
|
||||
return data
|
||||
}
|
||||
|
||||
+167
-18
@@ -1,11 +1,15 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/websocket"
|
||||
"github.com/shirou/gopsutil/v4/process"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -103,24 +107,20 @@ func (ps *ProcessService) GetProcessInfoByPID(pid int32) (*websocket.PsProcessDa
|
||||
data.CmdLine = cmdline
|
||||
}
|
||||
|
||||
if memInfo, err := p.MemoryInfo(); err == nil {
|
||||
data.Rss = common.FormatBytes(memInfo.RSS)
|
||||
data.VMS = common.FormatBytes(memInfo.VMS)
|
||||
data.HWM = common.FormatBytes(memInfo.HWM)
|
||||
data.Data = common.FormatBytes(memInfo.Data)
|
||||
data.Stack = common.FormatBytes(memInfo.Stack)
|
||||
data.Locked = common.FormatBytes(memInfo.Locked)
|
||||
data.Swap = common.FormatBytes(memInfo.Swap)
|
||||
data.RssValue = memInfo.RSS
|
||||
} else {
|
||||
data.Rss = "--"
|
||||
data.Data = "--"
|
||||
data.VMS = "--"
|
||||
data.HWM = "--"
|
||||
data.Stack = "--"
|
||||
data.Locked = "--"
|
||||
data.Swap = "--"
|
||||
data.RssValue = 0
|
||||
if memDetail, err := getMemoryDetail(p.Pid); err == nil {
|
||||
data.Rss = common.FormatBytes(memDetail.RSS)
|
||||
data.VMS = common.FormatBytes(memDetail.VMS)
|
||||
data.HWM = common.FormatBytes(memDetail.HWM)
|
||||
data.Data = common.FormatBytes(memDetail.Data)
|
||||
data.Stack = common.FormatBytes(memDetail.Stack)
|
||||
data.Locked = common.FormatBytes(memDetail.Locked)
|
||||
data.Swap = common.FormatBytes(memDetail.Swap)
|
||||
data.Dirty = common.FormatBytes(memDetail.Dirty)
|
||||
data.RssValue = memDetail.RSS
|
||||
data.PSS = common.FormatBytes(memDetail.PSS)
|
||||
data.USS = common.FormatBytes(memDetail.USS)
|
||||
data.Shared = common.FormatBytes(memDetail.Shared)
|
||||
data.Text = common.FormatBytes(memDetail.Text)
|
||||
}
|
||||
|
||||
if envs, err := p.Environ(); err == nil {
|
||||
@@ -133,3 +133,152 @@ func (ps *ProcessService) GetProcessInfoByPID(pid int32) (*websocket.PsProcessDa
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
type MemoryDetail struct {
|
||||
RSS uint64
|
||||
VMS uint64
|
||||
HWM uint64
|
||||
Data uint64
|
||||
Stack uint64
|
||||
Locked uint64
|
||||
Swap uint64
|
||||
|
||||
PSS uint64
|
||||
USS uint64
|
||||
Shared uint64
|
||||
Text uint64
|
||||
Dirty uint64
|
||||
}
|
||||
|
||||
func getMemoryDetail(pid int32) (*MemoryDetail, error) {
|
||||
mem := &MemoryDetail{}
|
||||
|
||||
if err := readStatus(pid, mem); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := readSmapsRollup(pid, mem); err != nil {
|
||||
if err := readSmaps(pid, mem); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return mem, nil
|
||||
}
|
||||
|
||||
func readStatus(pid int32, mem *MemoryDetail) error {
|
||||
filePath := fmt.Sprintf("/proc/%d/status", pid)
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) < 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
key := strings.TrimSuffix(fields[0], ":")
|
||||
value, _ := strconv.ParseUint(fields[1], 10, 64)
|
||||
value *= 1024
|
||||
|
||||
switch key {
|
||||
case "VmRSS":
|
||||
mem.RSS = value
|
||||
case "VmSize":
|
||||
mem.VMS = value
|
||||
case "VmData":
|
||||
mem.Data = value
|
||||
case "VmSwap":
|
||||
mem.Swap = value
|
||||
case "VmExe":
|
||||
mem.Text = value
|
||||
case "RssShmem":
|
||||
mem.Shared = value
|
||||
case "VmHWM":
|
||||
mem.HWM = value
|
||||
case "VmStk":
|
||||
mem.Stack = value
|
||||
case "VmLck":
|
||||
mem.Locked = value
|
||||
}
|
||||
}
|
||||
|
||||
return scanner.Err()
|
||||
}
|
||||
|
||||
func readSmapsRollup(pid int32, mem *MemoryDetail) error {
|
||||
filePath := fmt.Sprintf("/proc/%d/smaps_rollup", pid)
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) < 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
key := strings.TrimSuffix(fields[0], ":")
|
||||
value, _ := strconv.ParseUint(fields[1], 10, 64)
|
||||
value *= 1024
|
||||
|
||||
switch key {
|
||||
case "Pss":
|
||||
mem.PSS = value
|
||||
case "Private_Clean", "Private_Dirty":
|
||||
mem.USS += value
|
||||
case "Shared_Clean", "Shared_Dirty":
|
||||
if mem.Shared == 0 {
|
||||
mem.Shared = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return scanner.Err()
|
||||
}
|
||||
|
||||
func readSmaps(pid int32, mem *MemoryDetail) error {
|
||||
filePath := fmt.Sprintf("/proc/%d/smaps", pid)
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) < 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
key := strings.TrimSuffix(fields[0], ":")
|
||||
value, _ := strconv.ParseUint(fields[1], 10, 64)
|
||||
value *= 1024
|
||||
|
||||
switch key {
|
||||
case "Pss":
|
||||
mem.PSS += value
|
||||
case "Private_Clean", "Private_Dirty":
|
||||
mem.USS += value
|
||||
case "Shared_Clean", "Shared_Dirty":
|
||||
if mem.Shared == 0 {
|
||||
mem.Shared += value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return scanner.Err()
|
||||
}
|
||||
|
||||
@@ -76,6 +76,9 @@ func (r RecycleBinService) Page(search dto.PageInfo) (int64, []response.RecycleB
|
||||
}
|
||||
|
||||
func (r RecycleBinService) Create(create request.RecycleBinCreate) error {
|
||||
if files.IsProtected(create.SourcePath) {
|
||||
return buserr.New("ErrPathNotDelete")
|
||||
}
|
||||
op := files.NewFileOp()
|
||||
if !op.Stat(create.SourcePath) {
|
||||
return buserr.New("ErrLinkPathNotFound")
|
||||
|
||||
@@ -722,7 +722,7 @@ func unInstallPHPExtension(runtime *model.Runtime, delExtensions []string) error
|
||||
if ext.Name == del {
|
||||
exist = true
|
||||
delMap[ext.Check] = struct{}{}
|
||||
delPHPExtensions(dir, phpExtensionDir, ext.Check, ext.Name)
|
||||
delPHPExtensions(dir, phpExtensionDir, ext.File, ext.Name)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/encrypt"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/ssh"
|
||||
@@ -24,6 +25,8 @@ type ISettingService interface {
|
||||
GetSystemProxy() (*dto.SystemProxy, error)
|
||||
GetLocalConn() dto.SSHConnData
|
||||
GetSettingByKey(key string) string
|
||||
|
||||
SaveDescription(req dto.CommonDescription) error
|
||||
}
|
||||
|
||||
func NewISettingService() ISettingService {
|
||||
@@ -170,3 +173,24 @@ func (u *SettingService) GetSettingByKey(key string) string {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
func (u *SettingService) SaveDescription(req dto.CommonDescription) error {
|
||||
if len(req.Description) == 0 && !req.IsPinned {
|
||||
_ = settingRepo.DelDescription(req.ID)
|
||||
return nil
|
||||
}
|
||||
data, _ := settingRepo.GetDescription(settingRepo.WithByDescriptionID(req.ID), repo.WithByType(req.Type), repo.WithByDetailType(req.DetailType))
|
||||
if data.ID == "" {
|
||||
if err := copier.Copy(&data, &req); err != nil {
|
||||
return err
|
||||
}
|
||||
return settingRepo.CreateDescription(&data)
|
||||
}
|
||||
valMap := make(map[string]interface{})
|
||||
valMap["type"] = req.Type
|
||||
valMap["detail_type"] = req.DetailType
|
||||
valMap["is_pinned"] = req.IsPinned
|
||||
valMap["description"] = req.Description
|
||||
|
||||
return settingRepo.UpdateDescription(data.ID, valMap)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
"github.com/docker/docker/api/types/image"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
@@ -23,6 +25,7 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/controller"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/copier"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/docker"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/files"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@@ -259,11 +262,12 @@ func loadDbConn(snap *snapHelper, targetDir string, req dto.SnapshotCreate) erro
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
taskDB, err := common.LoadDBConnByPathWithErr(path.Join(targetDir, "db/task.db"), "core.db")
|
||||
taskDB, err := common.LoadDBConnByPathWithErr(path.Join(targetDir, "db/task.db"), "task.db")
|
||||
snap.Task.LogWithStatus(i18n.GetWithName("SnapNewDB", "task"), err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer common.CloseDB(taskDB)
|
||||
_ = taskDB.Where("id = ?", req.TaskID).Delete(&model.Task{}).Error
|
||||
}
|
||||
if !req.WithOperationLog && global.IsMaster {
|
||||
@@ -368,9 +372,21 @@ func snapAppImage(snap snapHelper, req dto.SnapshotCreate, targetDir string) err
|
||||
}
|
||||
}
|
||||
|
||||
client, err := docker.NewDockerClient()
|
||||
if err != nil {
|
||||
snap.Task.Log("load docker client failed, skip save app images")
|
||||
return nil
|
||||
}
|
||||
images, err := client.ImageList(context.Background(), image.ListOptions{})
|
||||
if err != nil {
|
||||
snap.Task.Log("list docker images failed, skip save app images")
|
||||
return nil
|
||||
}
|
||||
var existImages []string
|
||||
for _, img := range images {
|
||||
existImages = append(existImages, img.RepoTags...)
|
||||
}
|
||||
var imageList []string
|
||||
existStr, _ := cmd.RunDefaultWithStdoutBashC("docker images | awk '{print $1\":\"$2}' | grep -v REPOSITORY:TAG")
|
||||
existImages := strings.Split(existStr, "\n")
|
||||
for _, app := range req.AppData {
|
||||
for _, item := range app.Children {
|
||||
if item.Label == "appImage" && item.IsCheck {
|
||||
@@ -546,5 +562,8 @@ func snapUpload(snap snapHelper, accounts string, downloadID, retry uint, file s
|
||||
src := path.Join(global.Dir.LocalBackupDir, "tmp/system", path.Base(file))
|
||||
dst := path.Join("system_snapshot", path.Base(file))
|
||||
accountMap := NewBackupClientMap(strings.Split(accounts, ","))
|
||||
if !accountMap[fmt.Sprintf("%d", downloadID)].isOk {
|
||||
return buserr.New(i18n.GetMsgWithDetail("LoadBackupFailed", accountMap[fmt.Sprintf("%d", downloadID)].message))
|
||||
}
|
||||
return uploadWithMap(snap.Task, accountMap, src, dst, accounts, downloadID, retry)
|
||||
}
|
||||
|
||||
@@ -88,31 +88,25 @@ func (t TensorRTLLMService) Page(req request.TensorRTLLMSearch) response.TensorR
|
||||
}
|
||||
|
||||
composeByte, err := files.NewFileOp().GetContent(path.Join(global.Dir.TensorRTLLMDir, item.Name, "docker-compose.yml"))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
serverDTO.Environments, err = getDockerComposeEnvironments(composeByte)
|
||||
if err != nil {
|
||||
continue
|
||||
if err == nil {
|
||||
serverDTO.Environments, _ = getDockerComposeEnvironments(composeByte)
|
||||
}
|
||||
volumes, err := getDockerComposeVolumes(composeByte)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
var defaultVolumes = map[string]string{
|
||||
"${MODEL_PATH}": "${MODEL_PATH}",
|
||||
}
|
||||
for _, volume := range volumes {
|
||||
exist := false
|
||||
for key, value := range defaultVolumes {
|
||||
if key == volume.Source && value == volume.Target {
|
||||
exist = true
|
||||
break
|
||||
}
|
||||
if err == nil {
|
||||
var defaultVolumes = map[string]string{
|
||||
"${MODEL_PATH}": "${MODEL_PATH}",
|
||||
}
|
||||
if !exist {
|
||||
serverDTO.Volumes = append(serverDTO.Volumes, volume)
|
||||
for _, volume := range volumes {
|
||||
exist := false
|
||||
for key, value := range defaultVolumes {
|
||||
if key == volume.Source && value == volume.Target {
|
||||
exist = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !exist {
|
||||
serverDTO.Volumes = append(serverDTO.Volumes, volume)
|
||||
}
|
||||
}
|
||||
}
|
||||
items = append(items, serverDTO)
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"runtime/pprof"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
cpuProfile string
|
||||
memProfile string
|
||||
duration time.Duration
|
||||
showMemStats bool
|
||||
showGoroutine bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
RootCmd.AddCommand(debugCmd)
|
||||
|
||||
debugCmd.Flags().StringVar(&cpuProfile, "cpuprofile", "", "write cpu profile to file")
|
||||
debugCmd.Flags().StringVar(&memProfile, "memprofile", "", "write memory profile to file")
|
||||
debugCmd.Flags().DurationVar(&duration, "duration", 30*time.Second, "duration for cpu profiling")
|
||||
debugCmd.Flags().BoolVar(&showMemStats, "memstats", false, "show memory statistics")
|
||||
debugCmd.Flags().BoolVar(&showGoroutine, "goroutine", false, "show goroutine profile")
|
||||
}
|
||||
|
||||
var debugCmd = &cobra.Command{
|
||||
Use: "debug",
|
||||
Short: "Performance debugging with pprof",
|
||||
Long: `Debug command provides CPU and memory profiling capabilities using pprof.
|
||||
|
||||
Examples:
|
||||
# CPU profiling for 30 seconds
|
||||
1panel-agent debug --cpuprofile=cpu.prof --duration=30s
|
||||
|
||||
# Memory profiling
|
||||
1panel-agent debug --memprofile=mem.prof
|
||||
|
||||
# Show memory statistics
|
||||
1panel-agent debug --memstats
|
||||
|
||||
# Show goroutine information
|
||||
1panel-agent debug --goroutine
|
||||
|
||||
# Combined profiling
|
||||
1panel-agent debug --cpuprofile=cpu.prof --memprofile=mem.prof --memstats`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if cpuProfile != "" {
|
||||
if err := startCPUProfile(cpuProfile); err != nil {
|
||||
return fmt.Errorf("failed to start CPU profile: %v", err)
|
||||
}
|
||||
defer stopCPUProfile()
|
||||
time.Sleep(duration)
|
||||
fmt.Printf("CPU profile saved to: %s\n", cpuProfile)
|
||||
}
|
||||
|
||||
if memProfile != "" {
|
||||
if err := writeMemProfile(memProfile); err != nil {
|
||||
return fmt.Errorf("failed to write memory profile: %v", err)
|
||||
}
|
||||
fmt.Printf("Memory profile saved to: %s\n", memProfile)
|
||||
}
|
||||
|
||||
if showMemStats {
|
||||
printMemStats()
|
||||
}
|
||||
|
||||
if showGoroutine {
|
||||
printGoroutineInfo()
|
||||
}
|
||||
|
||||
if cpuProfile == "" && memProfile == "" && !showMemStats && !showGoroutine {
|
||||
printBasicInfo()
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func startCPUProfile(filename string) error {
|
||||
f, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := pprof.StartCPUProfile(f); err != nil {
|
||||
f.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func stopCPUProfile() {
|
||||
pprof.StopCPUProfile()
|
||||
}
|
||||
|
||||
func writeMemProfile(filename string) error {
|
||||
f, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
runtime.GC()
|
||||
|
||||
if err := pprof.WriteHeapProfile(f); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func printMemStats() {
|
||||
var m runtime.MemStats
|
||||
runtime.ReadMemStats(&m)
|
||||
|
||||
fmt.Println("\n=== Memory Statistics ===")
|
||||
fmt.Printf("Allocated memory: %d KB (%d MB)\n", m.Alloc/1024, m.Alloc/1024/1024)
|
||||
fmt.Printf("Total allocated: %d KB (%d MB)\n", m.TotalAlloc/1024, m.TotalAlloc/1024/1024)
|
||||
fmt.Printf("System memory: %d KB (%d MB)\n", m.Sys/1024, m.Sys/1024/1024)
|
||||
fmt.Printf("Heap allocated: %d KB (%d MB)\n", m.HeapAlloc/1024, m.HeapAlloc/1024/1024)
|
||||
fmt.Printf("Heap system: %d KB (%d MB)\n", m.HeapSys/1024, m.HeapSys/1024/1024)
|
||||
fmt.Printf("Heap idle: %d KB (%d MB)\n", m.HeapIdle/1024, m.HeapIdle/1024/1024)
|
||||
fmt.Printf("Heap in use: %d KB (%d MB)\n", m.HeapInuse/1024, m.HeapInuse/1024/1024)
|
||||
fmt.Printf("Heap released: %d KB (%d MB)\n", m.HeapReleased/1024, m.HeapReleased/1024/1024)
|
||||
fmt.Printf("Heap objects: %d\n", m.HeapObjects)
|
||||
fmt.Printf("GC runs: %d\n", m.NumGC)
|
||||
fmt.Printf("GC pause total: %d ns\n", m.PauseTotalNs)
|
||||
fmt.Printf("Next GC: %d KB (%d MB)\n", m.NextGC/1024, m.NextGC/1024/1024)
|
||||
fmt.Printf("Last GC: %s\n", time.Unix(0, int64(m.LastGC)).Format("2006-01-02 15:04:05"))
|
||||
}
|
||||
|
||||
func printGoroutineInfo() {
|
||||
fmt.Println("\n=== Goroutine Information ===")
|
||||
fmt.Printf("Number of goroutines: %d\n", runtime.NumGoroutine())
|
||||
fmt.Printf("Number of CPUs: %d\n", runtime.NumCPU())
|
||||
fmt.Printf("GOMAXPROCS: %d\n", runtime.GOMAXPROCS(0))
|
||||
|
||||
buf := make([]byte, 1024*1024)
|
||||
stackSize := runtime.Stack(buf, true)
|
||||
fmt.Printf("\nGoroutine stack trace (first 2048 bytes):\n")
|
||||
if stackSize > 2048 {
|
||||
fmt.Printf("%s...\n", buf[:2048])
|
||||
fmt.Printf("(truncated, total size: %d bytes)\n", stackSize)
|
||||
} else {
|
||||
fmt.Printf("%s\n", buf[:stackSize])
|
||||
}
|
||||
}
|
||||
|
||||
func printBasicInfo() {
|
||||
fmt.Println("=== Performance Debug Info ===")
|
||||
fmt.Printf("Go version: %s\n", runtime.Version())
|
||||
fmt.Printf("OS/Arch: %s/%s\n", runtime.GOOS, runtime.GOARCH)
|
||||
fmt.Printf("CPUs: %d\n", runtime.NumCPU())
|
||||
fmt.Printf("GOMAXPROCS: %d\n", runtime.GOMAXPROCS(0))
|
||||
fmt.Printf("Goroutines: %d\n", runtime.NumGoroutine())
|
||||
|
||||
var m runtime.MemStats
|
||||
runtime.ReadMemStats(&m)
|
||||
fmt.Printf("Memory allocated: %d KB\n", m.Alloc/1024)
|
||||
fmt.Printf("Total allocations: %d KB\n", m.TotalAlloc/1024)
|
||||
fmt.Printf("GC runs: %d\n", m.NumGC)
|
||||
|
||||
fmt.Println("\nUse --help to see available profiling options.")
|
||||
}
|
||||
@@ -13,11 +13,12 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
DB *gorm.DB
|
||||
MonitorDB *gorm.DB
|
||||
TaskDB *gorm.DB
|
||||
CoreDB *gorm.DB
|
||||
AlertDB *gorm.DB
|
||||
DB *gorm.DB
|
||||
MonitorDB *gorm.DB
|
||||
GPUMonitorDB *gorm.DB
|
||||
TaskDB *gorm.DB
|
||||
CoreDB *gorm.DB
|
||||
AlertDB *gorm.DB
|
||||
|
||||
LOG *logrus.Logger
|
||||
CONF ServerConfig
|
||||
|
||||
+40
-21
@@ -4,22 +4,27 @@ go 1.24.9
|
||||
|
||||
require (
|
||||
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
|
||||
github.com/aws/aws-sdk-go v1.55.0
|
||||
github.com/aws/aws-sdk-go-v2 v1.40.0
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.2
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.2
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.20.7
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.92.1
|
||||
github.com/aws/smithy-go v1.23.2
|
||||
github.com/compose-spec/compose-go/v2 v2.9.0
|
||||
github.com/creack/pty v1.1.24
|
||||
github.com/docker/cli v28.5.1+incompatible
|
||||
github.com/docker/compose/v2 v2.40.2
|
||||
github.com/docker/docker v28.5.1+incompatible
|
||||
github.com/docker/go-connections v0.6.0
|
||||
github.com/fsnotify/fsnotify v1.9.0
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/glebarez/sqlite v1.11.0
|
||||
github.com/go-acme/lego/v4 v4.27.0
|
||||
github.com/go-acme/lego/v4 v4.29.0
|
||||
github.com/go-gormigrate/gormigrate/v2 v2.1.2
|
||||
github.com/go-playground/validator/v10 v10.26.0
|
||||
github.com/go-redis/redis v6.15.9+incompatible
|
||||
github.com/go-resty/resty/v2 v2.16.5
|
||||
github.com/go-sql-driver/mysql v1.8.1
|
||||
github.com/goccy/go-yaml v1.9.8
|
||||
github.com/goh-chunlin/go-onedrive v1.1.1
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674
|
||||
@@ -47,11 +52,11 @@ require (
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.7.54
|
||||
github.com/tomasen/fcgi_client v0.0.0-20180423082037-2bb3d819fd19
|
||||
github.com/upyun/go-sdk v2.1.0+incompatible
|
||||
golang.org/x/crypto v0.43.0
|
||||
golang.org/x/net v0.46.0
|
||||
golang.org/x/oauth2 v0.32.0
|
||||
golang.org/x/sys v0.37.0
|
||||
golang.org/x/text v0.30.0
|
||||
golang.org/x/crypto v0.45.0
|
||||
golang.org/x/net v0.47.0
|
||||
golang.org/x/oauth2 v0.33.0
|
||||
golang.org/x/sys v0.38.0
|
||||
golang.org/x/text v0.31.0
|
||||
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38
|
||||
gopkg.in/ini.v1 v1.67.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
@@ -71,7 +76,22 @@ require (
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.7 // indirect
|
||||
github.com/aliyun/credentials-go v1.4.7 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/baidubce/bce-sdk-go v0.9.248 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.14 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.14 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.14 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.14 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.14 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.14 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.61.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.0.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.30.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.41.2 // indirect
|
||||
github.com/baidubce/bce-sdk-go v0.9.252 // indirect
|
||||
github.com/bodgit/plumbing v1.2.0 // indirect
|
||||
github.com/bodgit/sevenzip v1.3.0 // indirect
|
||||
github.com/bodgit/windows v1.0.0 // indirect
|
||||
@@ -97,6 +117,7 @@ require (
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73 // indirect
|
||||
github.com/distribution/reference v0.6.0 // indirect
|
||||
github.com/docker/buildx v0.29.1 // indirect
|
||||
github.com/docker/cli v28.5.1+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.9.3 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/dsnet/compress v0.0.1 // indirect
|
||||
@@ -108,8 +129,9 @@ require (
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/glebarez/go-sqlite v1.22.0 // indirect
|
||||
github.com/go-acme/alidns-20150109/v4 v4.6.1 // indirect
|
||||
github.com/go-acme/tencentclouddnspod v1.1.10 // indirect
|
||||
github.com/go-acme/alidns-20150109/v4 v4.7.0 // indirect
|
||||
github.com/go-acme/esa-20240910/v2 v2.40.1 // indirect
|
||||
github.com/go-acme/tencentclouddnspod v1.1.25 // indirect
|
||||
github.com/go-ini/ini v1.67.0 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.1.3 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
@@ -119,8 +141,7 @@ require (
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/goccy/go-yaml v1.9.8 // indirect
|
||||
github.com/gofrs/flock v0.12.1 // indirect
|
||||
github.com/gofrs/flock v0.13.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
@@ -133,7 +154,7 @@ require (
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-version v1.7.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.172 // indirect
|
||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.178 // indirect
|
||||
github.com/in-toto/in-toto-golang v0.9.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
@@ -141,7 +162,6 @@ require (
|
||||
github.com/jackc/puddle/v2 v2.2.1 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/json-iterator/go v1.1.13-0.20220915233716-71ac16282d12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
|
||||
github.com/klauspost/pgzip v1.2.5 // indirect
|
||||
@@ -178,7 +198,6 @@ require (
|
||||
github.com/nrdcg/dnspod-go v0.4.0 // indirect
|
||||
github.com/nrdcg/freemyip v0.3.0 // indirect
|
||||
github.com/nrdcg/goacmedns v0.2.0 // indirect
|
||||
github.com/nrdcg/mailinabox v0.2.0 // indirect
|
||||
github.com/nrdcg/namesilo v0.5.0 // indirect
|
||||
github.com/nwaples/rardecode/v2 v2.2.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
@@ -199,7 +218,7 @@ require (
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/cast v1.7.0 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.1.41 // indirect
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.3 // indirect
|
||||
github.com/therootcompany/xz v1.0.1 // indirect
|
||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.15 // indirect
|
||||
@@ -212,7 +231,7 @@ require (
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
github.com/ulikunitz/xz v0.5.15 // indirect
|
||||
github.com/volcengine/volc-sdk-golang v1.0.223 // indirect
|
||||
github.com/volcengine/volc-sdk-golang v1.0.229 // indirect
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
go.mongodb.org/mongo-driver v1.13.1 // indirect
|
||||
@@ -235,12 +254,12 @@ require (
|
||||
golang.org/x/arch v0.8.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
|
||||
golang.org/x/mod v0.29.0 // indirect
|
||||
golang.org/x/sync v0.17.0 // indirect
|
||||
golang.org/x/sync v0.18.0 // indirect
|
||||
golang.org/x/time v0.14.0 // indirect
|
||||
golang.org/x/tools v0.37.0 // indirect
|
||||
golang.org/x/tools v0.38.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101 // indirect
|
||||
google.golang.org/grpc v1.76.0 // indirect
|
||||
google.golang.org/protobuf v1.36.10 // indirect
|
||||
modernc.org/libc v1.66.1 // indirect
|
||||
|
||||
+88
-71
@@ -48,9 +48,8 @@ github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXY
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/Microsoft/hcsshim v0.13.0 h1:/BcXOiS6Qi7N9XqUcv27vkIuVOkBEcWstd2pMlWSeaA=
|
||||
github.com/Microsoft/hcsshim v0.13.0/go.mod h1:9KWJ/8DgU+QzYGupX4tzMhRQE8h6w90lH6HAaclpEok=
|
||||
github.com/Microsoft/hcsshim v0.14.0-rc.1 h1:qAPXKwGOkVn8LlqgBN8GS0bxZ83hOJpcjxzmlQKxKsQ=
|
||||
github.com/Microsoft/hcsshim v0.14.0-rc.1/go.mod h1:hTKFGbnDtQb1wHiOWv4v0eN+7boSWAHyK/tNAaYZL0c=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
|
||||
@@ -79,7 +78,6 @@ github.com/alibabacloud-go/darabonba-encode-util v0.0.2 h1:1uJGrbsGEVqWcWxrS9MyC
|
||||
github.com/alibabacloud-go/darabonba-encode-util v0.0.2/go.mod h1:JiW9higWHYXm7F4PKuMgEUETNZasrDM6vqVr/Can7H8=
|
||||
github.com/alibabacloud-go/darabonba-map v0.0.2 h1:qvPnGB4+dJbJIxOOfawxzF3hzMnIpjmafa0qOTp6udc=
|
||||
github.com/alibabacloud-go/darabonba-map v0.0.2/go.mod h1:28AJaX8FOE/ym8OUFWga+MtEzBunJwQGceGQlvaPGPc=
|
||||
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.12/go.mod h1:f2wDpbM7hK9SvLIH09zSKVU1TsyemUNOqErMscMMl7c=
|
||||
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.13 h1:Q00FU3H94Ts0ZIHDmY+fYGgB7dV9D/YX6FGsgorQPgw=
|
||||
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.13/go.mod h1:lxFGfobinVsQ49ntjpgWghXmIF0/Sm4+wvBJ1h5RtaE=
|
||||
github.com/alibabacloud-go/darabonba-signature-util v0.0.7 h1:UzCnKvsjPFzApvODDNEYqBHMFt1w98wC7FOo0InLyxg=
|
||||
@@ -102,7 +100,6 @@ github.com/alibabacloud-go/tea v1.1.11/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/Ke
|
||||
github.com/alibabacloud-go/tea v1.1.17/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
|
||||
github.com/alibabacloud-go/tea v1.1.20/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
|
||||
github.com/alibabacloud-go/tea v1.2.2/go.mod h1:CF3vOzEMAG+bR4WOql8gc2G9H3EkH3ZLAQdpmpXMgwk=
|
||||
github.com/alibabacloud-go/tea v1.3.12/go.mod h1:A560v/JTQ1n5zklt2BEpurJzZTI8TUT+Psg2drWlxRg=
|
||||
github.com/alibabacloud-go/tea v1.3.13 h1:WhGy6LIXaMbBM6VBYcsDCz6K/TPsT1Ri2hPmmZffZ94=
|
||||
github.com/alibabacloud-go/tea v1.3.13/go.mod h1:A560v/JTQ1n5zklt2BEpurJzZTI8TUT+Psg2drWlxRg=
|
||||
github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE=
|
||||
@@ -130,13 +127,53 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj
|
||||
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
|
||||
github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
|
||||
github.com/aws/aws-sdk-go v1.55.0 h1:hVALKPjXz33kP1R9nTyJpUK7qF59dO2mleQxUW9mCVE=
|
||||
github.com/aws/aws-sdk-go v1.55.0/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
|
||||
github.com/aws/aws-sdk-go-v2 v1.9.1/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
|
||||
github.com/aws/aws-sdk-go-v2 v1.40.0 h1:/WMUA0kjhZExjOQN2z3oLALDREea1A7TobfuiBrKlwc=
|
||||
github.com/aws/aws-sdk-go-v2 v1.40.0/go.mod h1:c9pm7VwuW0UPxAEYGyTmyurVcNrbF6Rt/wixFqDhcjE=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.3 h1:DHctwEM8P8iTXFxC/QK0MRjwEpWQeM9yzidCRjldUz0=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.3/go.mod h1:xdCzcZEtnSTKVDOmUZs4l/j3pSV6rpo1WXl5ugNsL8Y=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.2 h1:4liUsdEpUUPZs5WVapsJLx5NPmQhQdez7nYFcovrytk=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.2/go.mod h1:l0hs06IFz1eCT+jTacU/qZtC33nvcnLADAPL/XyrkZI=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.2 h1:qZry8VUyTK4VIo5aEdUcBjPZHL2v4FyQ3QEOaWcFLu4=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.2/go.mod h1:YUqm5a1/kBnoK+/NY5WEiMocZihKSo15/tJdmdXnM5g=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.14 h1:WZVR5DbDgxzA0BJeudId89Kmgy6DIU4ORpxwsVHz0qA=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.14/go.mod h1:Dadl9QO0kHgbrH1GRqGiZdYtW5w+IXXaBNCHTIaheM4=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.20.7 h1:u8danF+A2Zv//pFZvj5V23v/6XG4AxuSVup5s6nxSnI=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.20.7/go.mod h1:uvLIvU8iJPEU5so7b6lLDNArWpOX6sRBfL5wBABmlfc=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.14 h1:PZHqQACxYb8mYgms4RZbhZG0a7dPW06xOjmaH0EJC/I=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.14/go.mod h1:VymhrMJUWs69D8u0/lZ7jSB6WgaG/NqHi3gX0aYf6U0=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.14 h1:bOS19y6zlJwagBfHxs0ESzr1XCOU2KXJCWcq3E2vfjY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.14/go.mod h1:1ipeGBMAxZ0xcTm6y6paC2C/J6f6OO7LBODV9afuAyM=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.14 h1:ITi7qiDSv/mSGDSWNpZ4k4Ve0DQR6Ug2SJQ8zEHoDXg=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.14/go.mod h1:k1xtME53H1b6YpZt74YmwlONMWf4ecM+lut1WQLAF/U=
|
||||
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.3 h1:x2Ibm/Af8Fi+BH+Hsn9TXGdT+hKbDd5XOTZxTMxDk7o=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.3/go.mod h1:IW1jwyrQgMdhisceG8fQLmQIydcT/jWY21rFhzgaKwo=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.5 h1:Hjkh7kE6D81PgrHlE/m9gx+4TyyeLHuY8xJs7yXN5C4=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.5/go.mod h1:nPRXgyCfAurhyaTMoBMwRBYBhaHI4lNPAnJmjM0Tslc=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.14 h1:FIouAnCE46kyYqyhs0XEBDFFSREtdnr8HQuLPQPLCrY=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.14/go.mod h1:UTwDc5COa5+guonQU8qBikJo1ZJ4ln2r1MkF7Dqag1E=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.14 h1:FzQE21lNtUor0Fb7QNgnEyiRCBlolLTX/Z1j65S7teM=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.14/go.mod h1:s1ydyWG9pm3ZwmmYN21HKyG9WzAZhYVW85wMHs5FV6w=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.61.0 h1:W3+0Cbc9awFBr9Yt7nFUkvB4N4e7vVIGtKD1qDttXn4=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.61.0/go.mod h1:Wa3q5R2uwIfIL3HZH+vG1/P9y7CjjfzTgcz5IWXlsZs=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.92.1 h1:OgQy/+0+Kc3khtqiEOk23xQAglXi3Tj0y5doOxbi5tg=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.92.1/go.mod h1:wYNqY3L02Z3IgRYxOBPH9I1zD9Cjh9hI5QOy/eOjQvw=
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.0.2 h1:MxMBdKTYBjPQChlJhi4qlEueqB1p1KcbTEa7tD5aqPs=
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.0.2/go.mod h1:iS6EPmNeqCsGo+xQmXv0jIMjyYtQfnwg36zl2FwEouk=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.30.5 h1:ksUT5KtgpZd3SAiFJNJ0AFEJVva3gjBmN7eXUZjzUwQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.30.5/go.mod h1:av+ArJpoYf3pgyrj6tcehSFW+y9/QvAY8kMooR9bZCw=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.10 h1:GtsxyiF3Nd3JahRBJbxLCCdYW9ltGQYrFWg8XdkGDd8=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.10/go.mod h1:/j67Z5XBVDx8nZVp9EuFM9/BS5dvBznbqILGuu73hug=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.41.2 h1:a5UTtD4mHBU3t0o6aHQZFJTNKVfxFWfPX7J0Lr7G+uY=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.41.2/go.mod h1:6TxbXoDSgBQ225Qd8Q+MbxUxUh6TtNKwbRt/EPS9xso=
|
||||
github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
|
||||
github.com/baidubce/bce-sdk-go v0.9.248 h1:vB5OMuEC2xnO197M6OWUi24C8mYOZHKXT/8HuKQJUhU=
|
||||
github.com/baidubce/bce-sdk-go v0.9.248/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
|
||||
github.com/aws/smithy-go v1.23.2 h1:Crv0eatJUQhaManss33hS5r40CG3ZFH+21XSkqMrIUM=
|
||||
github.com/aws/smithy-go v1.23.2/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0=
|
||||
github.com/baidubce/bce-sdk-go v0.9.252 h1:TONS/utgfEkDjvHllVZFBrTsjsNhk51rhWuj3ppcL4s=
|
||||
github.com/baidubce/bce-sdk-go v0.9.252/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
@@ -190,17 +227,12 @@ github.com/compose-spec/compose-go/v2 v2.9.0 h1:UHSv/QHlo6QJtrT4igF1rdORgIUhDo1g
|
||||
github.com/compose-spec/compose-go/v2 v2.9.0/go.mod h1:Oky9AZGTRB4E+0VbTPZTUu4Kp+oEMMuwZXZtPPVT1iE=
|
||||
github.com/connesc/cipherio v0.2.1 h1:FGtpTPMbKNNWByNrr9aEBtaJtXjqOzkIXNYJp6OEycw=
|
||||
github.com/connesc/cipherio v0.2.1/go.mod h1:ukY0MWJDFnJEbXMQtOcn2VmTpRfzcTz4OoVrWGGJZcA=
|
||||
github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
|
||||
github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
|
||||
github.com/containerd/cgroups/v3 v3.1.0 h1:azxYVj+91ZgSnIBp2eI3k9y2iYQSR/ZQIgh9vKO+HSY=
|
||||
github.com/containerd/cgroups/v3 v3.1.0/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
|
||||
github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc=
|
||||
github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
|
||||
github.com/containerd/containerd/api v1.9.0 h1:HZ/licowTRazus+wt9fM6r/9BQO7S0vD5lMcWspGIg0=
|
||||
github.com/containerd/containerd/api v1.9.0/go.mod h1:GhghKFmTR3hNtyznBoQ0EMWr9ju5AqHjcZPsSpTKutI=
|
||||
github.com/containerd/containerd/api v1.10.0 h1:5n0oHYVBwN4VhoX9fFykCV9dF1/BvAXeg2F8W6UYq1o=
|
||||
github.com/containerd/containerd/api v1.10.0/go.mod h1:NBm1OAk8ZL+LG8R0ceObGxT5hbUYj7CzTmR3xh0DlMM=
|
||||
github.com/containerd/containerd/v2 v2.1.4 h1:/hXWjiSFd6ftrBOBGfAZ6T30LJcx1dBjdKEeI8xucKQ=
|
||||
github.com/containerd/containerd/v2 v2.1.4/go.mod h1:8C5QV9djwsYDNhxfTCFjWtTBZrqjditQ4/ghHSYjnHM=
|
||||
github.com/containerd/containerd/v2 v2.2.0 h1:K7TqcXy+LnFmZaui2DgHsnp2gAHhVNWYaHlx7HXfys8=
|
||||
github.com/containerd/containerd/v2 v2.2.0/go.mod h1:YCMjKjA4ZA7egdHNi3/93bJR1+2oniYlnS+c0N62HdE=
|
||||
github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
|
||||
@@ -215,8 +247,6 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||
github.com/containerd/nydus-snapshotter v0.15.2 h1:qsHI4M+Wwrf6Jr4eBqhNx8qh+YU0dSiJ+WPmcLFWNcg=
|
||||
github.com/containerd/nydus-snapshotter v0.15.2/go.mod h1:FfwH2KBkNYoisK/e+KsmNr7xTU53DmnavQHMFOcXwfM=
|
||||
github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E=
|
||||
github.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4=
|
||||
github.com/containerd/platforms v1.0.0-rc.2 h1:0SPgaNZPVWGEi4grZdV8VRYQn78y+nm6acgLGv/QzE4=
|
||||
github.com/containerd/platforms v1.0.0-rc.2/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4=
|
||||
github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y=
|
||||
@@ -322,12 +352,14 @@ github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec
|
||||
github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc=
|
||||
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
|
||||
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
|
||||
github.com/go-acme/alidns-20150109/v4 v4.6.1 h1:Dch3aWRcw4U62+jKPjPQN3iW3TPvgIywATbvHzojXeo=
|
||||
github.com/go-acme/alidns-20150109/v4 v4.6.1/go.mod h1:RBcqBA5IvUWtlpjx6dC6EkPVyBNLQ+mR18XoaP38BFY=
|
||||
github.com/go-acme/lego/v4 v4.27.0 h1:cIhWd7Uj4BNFLEF3IpwuMkukVVRs5qjlp4KdUGa75yU=
|
||||
github.com/go-acme/lego/v4 v4.27.0/go.mod h1:9FfNZHZmg6hf5CWOp4Lzo4gU8aBEvqZvrwdkBboa+4g=
|
||||
github.com/go-acme/tencentclouddnspod v1.1.10 h1:ERVJ4mc3cT4Nb3+n6H/c1AwZnChGBqLoymE0NVYscKI=
|
||||
github.com/go-acme/tencentclouddnspod v1.1.10/go.mod h1:Bo/0YQJ/99FM+44HmCQkByuptX1tJsJ9V14MGV/2Qco=
|
||||
github.com/go-acme/alidns-20150109/v4 v4.7.0 h1:PqJ/wR0JTpL4v0Owu1uM7bPQ1Yww0eQLAuuSdLjjQaQ=
|
||||
github.com/go-acme/alidns-20150109/v4 v4.7.0/go.mod h1:btQvB6xZoN6ykKB74cPhiR+uvhrEE2AFVXm6RDmCHm0=
|
||||
github.com/go-acme/esa-20240910/v2 v2.40.1 h1:pog3UlF5d+3LPoo1L8u8PqB189recIXX8T7pGoEz18A=
|
||||
github.com/go-acme/esa-20240910/v2 v2.40.1/go.mod h1:ZYdN9EN9ikn26SNapxCVjZ65pHT/1qm4fzuJ7QGVX6g=
|
||||
github.com/go-acme/lego/v4 v4.29.0 h1:vKMEtvoKb0gOO9rWO9zMBwE4CgI5A5CWDsK4QEeBqzo=
|
||||
github.com/go-acme/lego/v4 v4.29.0/go.mod h1:rnYyDj1NdDd9y1dHkVuUS97j7bfe9I61+oY9odKaHM8=
|
||||
github.com/go-acme/tencentclouddnspod v1.1.25 h1:7H3ZKshkaHzCXfRpAHVB5nvxeDDl2XLeNZfrNHiZj/s=
|
||||
github.com/go-acme/tencentclouddnspod v1.1.25/go.mod h1:XXfzp0AYV7UAUsHKT6R0KAUJFhqAUXmWGF07Elpa5cE=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
@@ -386,8 +418,8 @@ github.com/goccy/go-yaml v1.9.8 h1:5gMyLUeU1/6zl+WFfR1hN7D2kf+1/eRGa7DFtToiBvQ=
|
||||
github.com/goccy/go-yaml v1.9.8/go.mod h1:JubOolP3gh0HpiBc4BLRD4YmjEjHAmIIB2aaXKkTfoE=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=
|
||||
github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0=
|
||||
github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw=
|
||||
github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
@@ -401,9 +433,9 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
@@ -486,8 +518,6 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
|
||||
github.com/grafov/m3u8 v0.12.0/go.mod h1:nqzOkfBiZJENr52zTVd/Dcl03yzphIMbJqkXGu+u080=
|
||||
@@ -533,8 +563,8 @@ github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg
|
||||
github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
|
||||
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.172 h1:68VUVbLKwBxPh8tjCXwnLO/d8/thdZ+ExpxdFMEdK5A=
|
||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.172/go.mod h1:M+yna96Fx9o5GbIUnF3OvVvQGjgfVSyeJbV9Yb1z/wI=
|
||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.178 h1:eNVkjzdPMgM2qih9aECiFUI8S9zgpOwXxeBPAwQqtvU=
|
||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.178/go.mod h1:M+yna96Fx9o5GbIUnF3OvVvQGjgfVSyeJbV9Yb1z/wI=
|
||||
github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo=
|
||||
github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
@@ -568,9 +598,7 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr
|
||||
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
@@ -593,8 +621,6 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
|
||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
|
||||
github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
@@ -711,7 +737,6 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
|
||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
@@ -744,8 +769,6 @@ github.com/nrdcg/freemyip v0.3.0 h1:0D2rXgvLwe2RRaVIjyUcQ4S26+cIS2iFwnhzDsEuuwc=
|
||||
github.com/nrdcg/freemyip v0.3.0/go.mod h1:c1PscDvA0ukBF0dwelU/IwOakNKnVxetpAQ863RMJoM=
|
||||
github.com/nrdcg/goacmedns v0.2.0 h1:ADMbThobzEMnr6kg2ohs4KGa3LFqmgiBA22/6jUWJR0=
|
||||
github.com/nrdcg/goacmedns v0.2.0/go.mod h1:T5o6+xvSLrQpugmwHvrSNkzWht0UGAwj2ACBMhh73Cg=
|
||||
github.com/nrdcg/mailinabox v0.2.0 h1:IKq8mfKiVwNW2hQii/ng1dJ4yYMMv3HAP3fMFIq2CFk=
|
||||
github.com/nrdcg/mailinabox v0.2.0/go.mod h1:0yxqeYOiGyxAu7Sb94eMxHPIOsPYXAjTeA9ZhePhGnc=
|
||||
github.com/nrdcg/namesilo v0.5.0 h1:6QNxT/XxE+f5B+7QlfWorthNzOzcGlBLRQxqi6YeBrE=
|
||||
github.com/nrdcg/namesilo v0.5.0/go.mod h1:4UkwlwQfDt74kSGmhLaDylnBrD94IfflnpoEaj6T2qw=
|
||||
github.com/nwaples/rardecode/v2 v2.2.0 h1:4ufPGHiNe1rYJxYfehALLjup4Ls3ck42CWwjKiOqu0A=
|
||||
@@ -813,33 +836,29 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn
|
||||
github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
||||
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
||||
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||
github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
|
||||
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
|
||||
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
|
||||
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/qiniu/dyn v1.3.0/go.mod h1:E8oERcm8TtwJiZvkQPbcAh0RL8jO1G0VXJMW3FAWdkk=
|
||||
github.com/qiniu/go-sdk/v7 v7.21.1 h1:D/IjVOlg5pTw0jeDjqTo6H5QM73Obb1AYfPOHmIFN+Q=
|
||||
github.com/qiniu/go-sdk/v7 v7.21.1/go.mod h1:8EM2awITynlem2VML2dXGHkMYP2UyECsGLOdp6yMpco=
|
||||
@@ -928,9 +947,9 @@ github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.563/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.1.10/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.1.41 h1:XQDGrLX6v4McMP+2myhgQcy5JaPqSgwpLM1qa7ngUII=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.1.41/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.1.25/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.3 h1:r05ohLc0LVEpiEQeOJ5QwCiKk6XM9kjTca6+UAbNR/8=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.3/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.563/go.mod h1:uom4Nvi9W+Qkom0exYiJ9VWJjXwyxtPYTkKkaLMlfE0=
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.7.54 h1:FRamEhNBbSeggyYfWfzFejTLftgbICocSYFk4PKTSV4=
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.7.54/go.mod h1:UN+VdbCl1hg+kKi5RXqZgaP+Boqfmk+D04GRc4XFk70=
|
||||
@@ -970,8 +989,8 @@ github.com/upyun/go-sdk v2.1.0+incompatible/go.mod h1:eu3F5Uz4b9ZE5bE5QsCL6mgSNW
|
||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
github.com/vbatts/tar-split v0.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnnbo=
|
||||
github.com/vbatts/tar-split v0.12.1/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=
|
||||
github.com/volcengine/volc-sdk-golang v1.0.223 h1:1EEK6VOUaA2Tu0VBD4VC5iSTTFag+KuNo+Vix469Tz4=
|
||||
github.com/volcengine/volc-sdk-golang v1.0.223/go.mod h1:zHJlaqiMbIB+0mcrsZPTwOb3FB7S/0MCfqlnO8R7hlM=
|
||||
github.com/volcengine/volc-sdk-golang v1.0.229 h1:gOkDltTS6Fta8OyfYrbeY9bqCHHyiJuGYNJpR5MR+Fo=
|
||||
github.com/volcengine/volc-sdk-golang v1.0.229/go.mod h1:zHJlaqiMbIB+0mcrsZPTwOb3FB7S/0MCfqlnO8R7hlM=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
|
||||
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
|
||||
@@ -1043,6 +1062,8 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
|
||||
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
|
||||
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
go4.org v0.0.0-20200411211856-f5505b9728dd h1:BNJlw5kRTzdmyfh5U8F93HA2OwkP7ZGwA51eJ/0wKOU=
|
||||
@@ -1081,8 +1102,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
|
||||
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
|
||||
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
|
||||
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@@ -1126,8 +1147,6 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
|
||||
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
|
||||
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
||||
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -1186,8 +1205,8 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
|
||||
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -1195,8 +1214,8 @@ golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4Iltr
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
|
||||
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -1213,8 +1232,8 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
|
||||
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -1294,8 +1313,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
|
||||
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
||||
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
@@ -1310,8 +1329,8 @@ golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
|
||||
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
|
||||
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
|
||||
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
|
||||
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -1329,8 +1348,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
|
||||
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@@ -1392,8 +1411,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
|
||||
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
|
||||
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
|
||||
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -1464,8 +1483,8 @@ google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 h1:Q3nlH8iSQSRUwOs
|
||||
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38/go.mod h1:xBI+tzfqGGN2JBeSebfKXFSdBpWVQ7sLW40PTupVRm4=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c h1:AtEkQdl5b6zsybXcbz00j1LwNodDuH6hVifIaNqk7NQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c/go.mod h1:ea2MjsO70ssTfCjiwHgI0ZFqcw45Ksuk2ckf9G468GA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 h1:CirRxTOwnRWVLKzDNrs0CXAaVozJoR4G9xvdRecrdpk=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101 h1:tRPGkdGHuewF4UisLzzHHr1spKw92qLM98nIzxbC0wY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
@@ -1483,8 +1502,6 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI=
|
||||
google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
|
||||
google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=
|
||||
google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
|
||||
+24
-12
@@ -13,6 +13,19 @@ import (
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
var langFiles = map[string]string{
|
||||
"zh": "lang/zh.yaml",
|
||||
"en": "lang/en.yaml",
|
||||
"zh-Hant": "lang/zh-Hant.yaml",
|
||||
"pt-BR": "lang/pt-BR.yaml",
|
||||
"ja": "lang/ja.yaml",
|
||||
"ru": "lang/ru.yaml",
|
||||
"ms": "lang/ms.yaml",
|
||||
"ko": "lang/ko.yaml",
|
||||
"tr": "lang/tr.yaml",
|
||||
"es-ES": "lang/es-ES.yaml",
|
||||
}
|
||||
|
||||
func GetMsgWithMap(key string, maps map[string]interface{}) string {
|
||||
var content string
|
||||
if maps == nil {
|
||||
@@ -123,18 +136,17 @@ func UseI18n() gin.HandlerFunc {
|
||||
func Init() {
|
||||
bundle = i18n.NewBundle(language.Chinese)
|
||||
bundle.RegisterUnmarshalFunc("yaml", yaml.Unmarshal)
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/zh.yaml")
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/en.yaml")
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/zh-Hant.yaml")
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/fa.yaml")
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/pt.yaml")
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/pt-BR.yaml")
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/ja.yaml")
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/ru.yaml")
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/ms.yaml")
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/ko.yaml")
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/tr.yaml")
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/es-ES.yaml")
|
||||
isSuccess := true
|
||||
for _, file := range langFiles {
|
||||
if _, err := bundle.LoadMessageFileFS(fs, file); err != nil {
|
||||
global.LOG.Errorf("[i18n] load language file %s failed: %v\n", file, err)
|
||||
isSuccess = false
|
||||
}
|
||||
}
|
||||
|
||||
if !isSuccess {
|
||||
panic("[i18n] failed to init language files, See log above for details")
|
||||
}
|
||||
lang := GetLanguageFromDB()
|
||||
global.I18n = i18n.NewLocalizer(bundle, lang)
|
||||
}
|
||||
|
||||
@@ -197,6 +197,8 @@ ErrDatabaseIsExist: 'The current database already exists, please re-enter'
|
||||
ErrExecTimeOut: 'SQL execution timed out, please check the database'
|
||||
ErrRemoteExist: 'The remote database already exists with this name, please modify it and try again'
|
||||
ErrLocalExist: 'The name already exists in the local database, please modify it and try again'
|
||||
RemoteBackup: "To back up the remote database, the local container database service needs to be started first using the image {{ .name }}, please wait..."
|
||||
RemoteRecover: "To restore the remote database, the local container database service needs to be started first using the image {{ .name }}, please wait..."
|
||||
|
||||
#redis
|
||||
ErrTypeOfRedis: 'The recovery file type does not match the current persistence method, please modify it and try again'
|
||||
@@ -239,6 +241,7 @@ ErrUserFindErr: 'User {{ .name }} search failed {{ .err }}'
|
||||
#cronjob
|
||||
CutWebsiteLogSuccess: '{{ .name }} website log cut successfully, backup path {{ .path }}'
|
||||
HandleShell: 'Execute script {{ .name }}'
|
||||
HandleCurl: "Access URL {{ .name }}"
|
||||
HandleNtpSync: 'System time synchronization'
|
||||
HandleSystemClean: 'System cache cleanup'
|
||||
SystemLog: 'System Log'
|
||||
@@ -251,7 +254,7 @@ IgnoreUploadErr: "Upload failed, error: {{ .detail }}, ignoring this error..."
|
||||
LoadBackupFailed: "Failed to get backup account connection, error: {{ .detail }}"
|
||||
InExecuting: "The current task is being executed, please do not repeat the execution!"
|
||||
NoSuchResource: "No backup content found in the database, skipping..."
|
||||
CleanLog: "Clean Log",
|
||||
CleanLog: "Clean Log"
|
||||
CleanLogByName: "Clean {{.name}} Log"
|
||||
|
||||
#toolbox
|
||||
|
||||
@@ -196,6 +196,8 @@ ErrDatabaseIsExist: 'La base de datos actual ya existe, intente con otro nombre'
|
||||
ErrExecTimeOut: 'Tiempo de espera en la ejecución SQL, revise la base de datos'
|
||||
ErrRemoteExist: 'La base de datos remota ya existe con ese nombre, modifíquelo e intente de nuevo'
|
||||
ErrLocalExist: 'El nombre ya existe en la base de datos local, modifíquelo e intente de nuevo'
|
||||
RemoteBackup: "Para hacer una copia de seguridad de la base de datos remota, primero debe iniciarse el servicio de base de datos del contenedor local utilizando la imagen {{ .name }}, espere por favor..."
|
||||
RemoteRecover: "Para restaurar la base de datos remota, primero debe iniciarse el servicio de base de datos del contenedor local utilizando la imagen {{ .name }}, espere por favor..."
|
||||
|
||||
#redis
|
||||
ErrTypeOfRedis: 'El tipo de archivo de recuperación no coincide con el método de persistencia actual, modifíquelo e intente'
|
||||
@@ -238,6 +240,7 @@ ErrUserFindErr: 'Búsqueda del usuario {{ .name }} fallida {{ .err }}'
|
||||
#cronjob
|
||||
CutWebsiteLogSuccess: 'Log del sitio web {{ .name }} cortado con éxito, ruta de respaldo {{ .path }}'
|
||||
HandleShell: 'Ejecutar script {{ .name }}'
|
||||
HandleCurl: "URL {{ .name }} にアクセス"
|
||||
HandleNtpSync: 'Sincronizar hora del sistema'
|
||||
HandleSystemClean: 'Limpiar caché del sistema'
|
||||
SystemLog: 'Log del sistema'
|
||||
|
||||
@@ -196,6 +196,8 @@ ErrDatabaseIsExist: '現在のデータベースは既に存在します。再
|
||||
ErrExecTimeOut: 'SQL 実行がタイムアウトしました。データベースを確認してください'
|
||||
ErrRemoteExist: 'この名前のリモート データベースは既に存在します。変更してもう一度お試しください'
|
||||
ErrLocalExist: '名前はローカル データベースに既に存在します。変更してもう一度お試しください'
|
||||
RemoteBackup: "リモートデータベースをバックアップするには、まずイメージ {{ .name }} を使用してローカルコンテナデータベースサービスを起動する必要があります。しばらくお待ちください..."
|
||||
RemoteRecover: "リモートデータベースを復元するには、まずイメージ {{ .name }} を使用してローカルコンテナデータベースサービスを起動する必要があります。しばらくお待ちください..."
|
||||
|
||||
#redis
|
||||
ErrTypeOfRedis: 'リカバリ ファイルの種類が現在の永続化方法と一致しません。変更して再試行してください'
|
||||
@@ -238,6 +240,7 @@ ErrUserFindErr: 'ユーザー {{ .name }} の検索に失敗しました {{ .err
|
||||
#cronjob
|
||||
CutWebsiteLogSuccess: '{{ .name }} ウェブサイトのログが正常にカットされました。バックアップ パス {{ .path }}'
|
||||
HandleShell: 'スクリプト {{ .name }} を実行します'
|
||||
HandleCurl: "URL {{ .name }} にアクセス"
|
||||
HandleNtpSync: 'システム時刻の同期'
|
||||
HandleSystemClean: 'システム キャッシュのクリーンアップ'
|
||||
SystemLog: 'システムログ'
|
||||
|
||||
@@ -197,6 +197,8 @@ ErrDatabaseIsExist: '현재 데이터베이스가 이미 존재합니다. 다시
|
||||
ErrExecTimeOut: 'SQL 실행 시간이 초과되었습니다. 데이터베이스를 확인하십시오.'
|
||||
ErrRemoteExist: '이 이름을 가진 원격 데이터베이스가 이미 존재합니다. 수정하고 다시 시도하세요'
|
||||
ErrLocalExist: '이름이 로컬 데이터베이스에 이미 존재합니다. 이름을 수정하고 다시 시도하세요'
|
||||
RemoteBackup: "원격 데이터베이스를 백업하려면 먼저 이미지 {{ .name }}을(를) 사용하여 로컬 컨테이너 데이터베이스 서비스를 시작해야 합니다. 잠시만 기다려 주세요..."
|
||||
RemoteRecover: "원격 데이터베이스를 복원하려면 먼저 이미지 {{ .name }}을(를) 사용하여 로컬 컨테이너 데이터베이스 서비스를 시작해야 합니다. 잠시만 기다려 주세요..."
|
||||
|
||||
#레디스
|
||||
ErrTypeOfRedis: '복구 파일 유형이 현재 지속성 방법과 일치하지 않습니다. 수정하고 다시 시도하세요'
|
||||
@@ -239,6 +241,7 @@ ErrUserFindErr: '사용자 {{ .name }} 검색에 실패했습니다 {{ .err }}'
|
||||
#크론잡
|
||||
CutWebsiteLogSuccess: '{{ .name }} 웹사이트 로그가 성공적으로 잘렸습니다. 백업 경로 {{ .path }}'
|
||||
HandleShell: '스크립트 {{ .name }} 실행'
|
||||
HandleCurl: "URL {{ .name }} 접근"
|
||||
HandleNtpSync: '시스템 시간 동기화'
|
||||
HandleSystemClean: '시스템 캐시 정리'
|
||||
SystemLog: '시스템 로그'
|
||||
|
||||
@@ -197,6 +197,8 @@ ErrDatabaseIsExist: 'Pangkalan data semasa sudah wujud, sila masukkan semula'
|
||||
ErrExecTimeOut: 'Pelaksanaan SQL tamat masa, sila semak pangkalan data'
|
||||
ErrRemoteExist: 'Pangkalan data jauh sudah wujud dengan nama ini, sila ubah suainya dan cuba lagi'
|
||||
ErrLocalExist: 'Nama sudah wujud dalam pangkalan data tempatan, sila ubah suai dan cuba lagi'
|
||||
RemoteBackup: "Untuk menyandarkan pangkalan data jauh, perkhidmatan pangkalan data bekas tempatan perlu dimulakan terlebih dahulu menggunakan imej {{ .name }}, sila tunggu..."
|
||||
RemoteRecover: "Untuk memulihkan pangkalan data jauh, perkhidmatan pangkalan data bekas tempatan perlu dimulakan terlebih dahulu menggunakan imej {{ .name }}, sila tunggu..."
|
||||
|
||||
#redis
|
||||
ErrTypeOfRedis: 'Jenis fail pemulihan tidak sepadan dengan kaedah kegigihan semasa, sila ubah suai dan cuba lagi'
|
||||
@@ -239,6 +241,7 @@ ErrUserFindErr: 'Pengguna {{ .name }} carian gagal {{ .err }}'
|
||||
#cronjob
|
||||
CutWebsiteLogSuccess: '{{ .name }} log tapak web berjaya dipotong, laluan sandaran {{ .path }}'
|
||||
HandleShell: 'Laksanakan skrip {{ .name }}'
|
||||
HandleCurl: "Akses URL {{ .name }}"
|
||||
HandleNtpSync: 'Penyegerakan masa sistem'
|
||||
HandleSystemClean: 'Pembersihan cache sistem'
|
||||
SystemLog: 'Log Sistem'
|
||||
|
||||
@@ -197,6 +197,8 @@ ErrDatabaseIsExist: 'O banco de dados atual já existe, digite novamente'
|
||||
ErrExecTimeOut: 'Tempo limite de execução do SQL expirou, verifique o banco de dados'
|
||||
ErrRemoteExist: 'O banco de dados remoto já existe com este nome, modifique-o e tente novamente'
|
||||
ErrLocalExist: 'O nome já existe no banco de dados local, modifique-o e tente novamente'
|
||||
RemoteBackup: "Para fazer backup do banco de dados remoto, o serviço de banco de dados do contêiner local precisa ser iniciado primeiro usando a imagem {{ .name }}, por favor aguarde..."
|
||||
RemoteRecover: "Para restaurar o banco de dados remoto, o serviço de banco de dados do contêiner local precisa ser iniciado primeiro usando a imagem {{ .name }}, por favor aguarde..."
|
||||
|
||||
#redis
|
||||
ErrTypeOfRedis: 'O tipo de arquivo de recuperação não corresponde ao método de persistência atual, modifique-o e tente novamente'
|
||||
@@ -239,6 +241,7 @@ ErrUserFindErr: 'Falha na pesquisa do usuário {{ .name }} {{ .err }}'
|
||||
#cronjob
|
||||
CutWebsiteLogSuccess: '{{ .name }} registro do site cortado com sucesso, caminho de backup {{ .path }}'
|
||||
HandleShell: 'Executar script {{ .name }}'
|
||||
HandleCurl: "Acessar URL {{ .name }}"
|
||||
HandleNtpSync: 'Sincronização de hora do sistema'
|
||||
HandleSystemClean: 'Limpeza de cache do sistema'
|
||||
SystemLog: 'Log do Sistema'
|
||||
|
||||
@@ -197,6 +197,8 @@ ErrDatabaseIsExist: 'Текущая база данных уже существ
|
||||
ErrExecTimeOut: 'Время выполнения SQL истекло, проверьте базу данных'
|
||||
ErrRemoteExist: 'Удаленная база данных с таким именем уже существует. Измените его и повторите попытку'
|
||||
ErrLocalExist: 'Имя уже существует в локальной базе данных, измените его и повторите попытку'
|
||||
RemoteBackup: "Для резервного копирования удаленной базы данных необходимо сначала запустить службу базы данных локального контейнера с помощью образа {{ .name }}, пожалуйста, подождите..."
|
||||
RemoteRecover: "Для восстановления удаленной базы данных необходимо сначала запустить службу базы данных локального контейнера с помощью образа {{ .name }}, пожалуйста, подождите..."
|
||||
|
||||
#редис
|
||||
ErrTypeOfRedis: 'Тип файла восстановления не соответствует текущему методу сохранения. Измените его и повторите попытку'
|
||||
@@ -239,6 +241,7 @@ ErrUserFindErr: 'Поиск пользователя {{ .name }} не удалс
|
||||
#cronjob
|
||||
CutWebsiteLogSuccess: 'Журнал веб-сайта {{ .name }} успешно вырезан, путь к резервной копии {{ .path }}'
|
||||
HandleShell: 'Выполнить скрипт {{ .name }}'
|
||||
HandleCurl: "Доступ к URL {{ .name }}"
|
||||
HandleNtpSync: 'Синхронизация системного времени'
|
||||
HandleSystemClean: 'Очистка системного кэша'
|
||||
SystemLog: 'Системный лог'
|
||||
|
||||
@@ -112,14 +112,14 @@ ExportDate: "Zaman"
|
||||
|
||||
#file
|
||||
ErrFileCanNotRead: 'Bu dosya önizlemeyi desteklemiyor'
|
||||
ErrFileToLarge: 'Dosya 10M'dan büyük ve açılamıyor'
|
||||
ErrFileToLarge: 'Dosya 10M dan büyük ve açılamıyor'
|
||||
ErrPathNotFound: 'Dizin mevcut değil'
|
||||
ErrMovePathFailed: 'Hedef yol orijinal yolu içeremez!'
|
||||
ErrLinkPathNotFound: 'Hedef yol mevcut değil!'
|
||||
ErrFileIsExist: 'Dosya veya klasör zaten mevcut!'
|
||||
ErrFileUpload: '{{ .name }} dosya yükleme başarısız {{ .detail }}'
|
||||
ErrFileDownloadDir: 'Klasör indirme desteklenmiyor'
|
||||
ErrCmdNotFound: '{{ .name}} komutu mevcut değil, lütfen önce bu komutu host'a yükleyin'
|
||||
ErrCmdNotFound: '{{ .name}} komutu mevcut değil, lütfen önce bu komutu host a yükleyin'
|
||||
ErrSourcePathNotFound: 'Kaynak dizin mevcut değil'
|
||||
ErrFavoriteExist: 'Bu yol zaten favorilere eklendi'
|
||||
ErrInvalidChar: 'Yasak karakterlere izin verilmiyor'
|
||||
@@ -198,6 +198,8 @@ ErrDatabaseIsExist: 'Mevcut veritabanı zaten mevcut, lütfen yeniden girin'
|
||||
ErrExecTimeOut: 'SQL yürütme zaman aşımı, lütfen veritabanını kontrol edin'
|
||||
ErrRemoteExist: 'Uzak veritabanında bu adla zaten mevcut, lütfen değiştirin ve tekrar deneyin'
|
||||
ErrLocalExist: 'Yerel veritabanında bu ad zaten mevcut, lütfen değiştirin ve tekrar deneyin'
|
||||
RemoteBackup: "Uzak veritabanını yedeklemek için önce {{ .name }} görüntüsü kullanılarak yerel konteyner veritabanı hizmetinin başlatılması gerekiyor, lütfen bekleyin..."
|
||||
RemoteRecover: "Uzak veritabanını geri yüklemek için önce {{ .name }} görüntüsü kullanılarak yerel konteyner veritabanı hizmetinin başlatılması gerekiyor, lütfen bekleyin..."
|
||||
|
||||
#redis
|
||||
ErrTypeOfRedis: 'Kurtarma dosyası türü mevcut kalıcılık yöntemiyle eşleşmiyor, lütfen değiştirin ve tekrar deneyin'
|
||||
@@ -240,6 +242,7 @@ ErrUserFindErr: 'Kullanıcı {{ .name }} arama başarısız {{ .err }}'
|
||||
#cronjob
|
||||
CutWebsiteLogSuccess: '{{ .name }} web sitesi günlüğü başarıyla kesildi, yedekleme yolu {{ .path }}'
|
||||
HandleShell: 'Betik {{ .name }} yürüt'
|
||||
HandleCurl: "URL'ye Eriş {{ .name }}"
|
||||
HandleNtpSync: 'Sistem zaman senkronizasyonu'
|
||||
HandleSystemClean: 'Sistem önbellek temizliği'
|
||||
SystemLog: 'Sistem Günlüğü'
|
||||
@@ -405,7 +408,7 @@ SnapNewDB: 'Veritabanı {{ .name }} bağlantısını başlat'
|
||||
SnapDeleteOperationLog: 'İşlem günlüğünü sil'
|
||||
SnapDeleteLoginLog: 'Erişim günlüğünü sil'
|
||||
SnapDeleteMonitor: 'İzleme verilerini sil'
|
||||
SnapRemoveSystemIP: 'Sistem IP'sini kaldır'
|
||||
SnapRemoveSystemIP: 'Sistem IP sini kaldır'
|
||||
SnapBaseInfo: '1Panel temel bilgilerini yaz'
|
||||
SnapInstallAppImageEmpty: 'Uygulama imageı seçilmedi, atlanıyor...'
|
||||
SnapInstallApp: '1Panel yüklü uygulamaları yedekle'
|
||||
|
||||
@@ -196,6 +196,8 @@ ErrDatabaseIsExist: '目前資料庫已存在,請重新輸入'
|
||||
ErrExecTimeOut: 'SQL 執行逾時,請檢查資料庫'
|
||||
ErrRemoteExist: '遠端資料庫已存在該名稱,請修改後重試'
|
||||
ErrLocalExist: '本機資料庫已存在該名稱,請修改後重試'
|
||||
RemoteBackup: "備份遠端資料庫需要先使用映像 {{ .name }} 啟動本機容器資料庫服務,請稍候..."
|
||||
RemoteRecover: "恢復遠端資料庫需要先使用映像 {{ .name }} 啟動本機容器資料庫服務,請稍候..."
|
||||
|
||||
#redis
|
||||
ErrTypeOfRedis: '復原檔案類型與目前持久化方式不符,請修改後重試'
|
||||
@@ -238,6 +240,7 @@ ErrUserFindErr: '使用者{{ .name }} 尋找失敗{{ .err }}'
|
||||
#cronjob
|
||||
CutWebsiteLogSuccess: '{{ .name }} 網站日誌切割成功,備份路徑{{ .path }}'
|
||||
HandleShell: '執行腳本{{ .name }}'
|
||||
HandleCurl: "存取 URL {{ .name }}"
|
||||
HandleNtpSync: '系統時間同步'
|
||||
HandleSystemClean: '系統快取清理'
|
||||
SystemLog: '系統日誌'
|
||||
|
||||
@@ -197,6 +197,8 @@ ErrDatabaseIsExist: "当前数据库已存在,请重新输入"
|
||||
ErrExecTimeOut: "SQL 执行超时,请检查数据库"
|
||||
ErrRemoteExist: "远程数据库已存在该名称,请修改后重试"
|
||||
ErrLocalExist: "本地数据库已存在该名称,请修改后重试"
|
||||
RemoteBackup: "备份远程数据库需要先使用镜像 {{ .name }} 启动本地容器数据库服务,请稍候..."
|
||||
RemoteRecover: "恢复远程数据库需要先使用镜像 {{ .name }} 启动本地容器数据库服务,请稍候..."
|
||||
|
||||
#redis
|
||||
ErrTypeOfRedis: "恢复文件类型与当前持久化方式不符,请修改后重试"
|
||||
@@ -239,6 +241,7 @@ ErrUserFindErr: "用户 {{ .name }} 查找失败 {{ .err }}"
|
||||
#cronjob
|
||||
CutWebsiteLogSuccess: "{{ .name }} 网站日志切割成功,备份路径 {{ .path }}"
|
||||
HandleShell: "执行脚本 {{ .name }}"
|
||||
HandleCurl: "访问 URL {{ .name }}"
|
||||
HandleNtpSync: "系统时间同步"
|
||||
HandleSystemClean: "系统缓存清理"
|
||||
SystemLog: "系统日志"
|
||||
|
||||
+3
-1
@@ -1,6 +1,7 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
@@ -11,9 +12,10 @@ func Init() {
|
||||
global.DB = common.LoadDBConnByPath(path.Join(global.Dir.DbDir, "agent.db"), "agent")
|
||||
global.TaskDB = common.LoadDBConnByPath(path.Join(global.Dir.DbDir, "task.db"), "task")
|
||||
global.MonitorDB = common.LoadDBConnByPath(path.Join(global.Dir.DbDir, "monitor.db"), "monitor")
|
||||
global.GPUMonitorDB = common.LoadDBConnByPath(path.Join(global.Dir.DbDir, "gpu_monitor.db"), "gpu_monitor")
|
||||
global.AlertDB = common.LoadDBConnByPath(path.Join(global.Dir.DbDir, "alert.db"), "alert")
|
||||
|
||||
if global.IsMaster {
|
||||
if _, err := os.Stat("/usr/bin/1panel-core"); err == nil {
|
||||
global.CoreDB = common.LoadDBConnByPath(path.Join(global.Dir.DbDir, "core.db"), "core")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
package firewall
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/service"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/firewall"
|
||||
firewallClient "github.com/1Panel-dev/1Panel/agent/utils/firewall/client"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/firewall/client/iptables"
|
||||
)
|
||||
|
||||
func Init() {
|
||||
if !needInit() {
|
||||
return
|
||||
}
|
||||
global.LOG.Info("initializing firewall settings...")
|
||||
client, err := firewall.NewFirewallClient()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
clientName := client.Name()
|
||||
|
||||
settingRepo := repo.NewISettingRepo()
|
||||
if clientName == "ufw" || clientName == "iptables" {
|
||||
if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelForward, iptables.ForwardFileName); err != nil {
|
||||
global.LOG.Errorf("load forward rules from file failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
if err := iptables.LoadRulesFromFile(iptables.NatTab, iptables.Chain1PanelPreRouting, iptables.ForwardFileName1); err != nil {
|
||||
global.LOG.Errorf("load prerouting rules from file failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
if err := iptables.LoadRulesFromFile(iptables.NatTab, iptables.Chain1PanelPostRouting, iptables.ForwardFileName2); err != nil {
|
||||
global.LOG.Errorf("load postrouting rules from file failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
global.LOG.Infof("loaded iptables rules for forward from file successfully")
|
||||
|
||||
iptablesForwardStatus, _ := settingRepo.GetValueByKey("IptablesForwardStatus")
|
||||
if iptablesForwardStatus == constant.StatusEnable {
|
||||
if err := firewallClient.EnableIptablesForward(); err != nil {
|
||||
global.LOG.Errorf("enable iptables forward failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if clientName != "iptables" {
|
||||
return
|
||||
}
|
||||
if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelBasicBefore, iptables.BasicBeforeFileName); err != nil {
|
||||
global.LOG.Errorf("load basic before rules from file failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelBasic, iptables.BasicFileName); err != nil {
|
||||
global.LOG.Errorf("load basic rules from file failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelBasicAfter, iptables.BasicAfterFileName); err != nil {
|
||||
global.LOG.Errorf("load basic after rules from file failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
panelPort := service.LoadPanelPort()
|
||||
if len(panelPort) == 0 {
|
||||
global.LOG.Errorf("find 1panel service port failed")
|
||||
return
|
||||
}
|
||||
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicBefore, fmt.Sprintf("-p tcp -m tcp --dport %v -j ACCEPT", panelPort)); err != nil {
|
||||
global.LOG.Errorf("add port accept rule %v failed, err: %v", panelPort, err)
|
||||
return
|
||||
}
|
||||
global.LOG.Infof("loaded iptables rules for basic from file successfully")
|
||||
iptablesService := service.IptablesService{}
|
||||
iptablesStatus, _ := settingRepo.GetValueByKey("IptablesStatus")
|
||||
if iptablesStatus == constant.StatusEnable {
|
||||
if err := iptablesService.Operate(dto.IptablesOp{Operate: "bind-base"}); err != nil {
|
||||
global.LOG.Errorf("bind base chains failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelInput, iptables.InputFileName); err != nil {
|
||||
global.LOG.Errorf("load input rules from file failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
if err := iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelOutput, iptables.OutputFileName); err != nil {
|
||||
global.LOG.Errorf("load output rules from file failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
global.LOG.Infof("loaded iptables rules for input and output from file successfully")
|
||||
iptablesInputStatus, _ := settingRepo.GetValueByKey("IptablesInputStatus")
|
||||
if iptablesInputStatus == constant.StatusEnable {
|
||||
if err := iptablesService.Operate(dto.IptablesOp{Name: iptables.Chain1PanelInput, Operate: "bind"}); err != nil {
|
||||
global.LOG.Errorf("bind input chains failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
iptablesOutputStatus, _ := settingRepo.GetValueByKey("IptablesOutputStatus")
|
||||
if iptablesOutputStatus == constant.StatusEnable {
|
||||
if err := iptablesService.Operate(dto.IptablesOp{Name: iptables.Chain1PanelOutput, Operate: "bind"}); err != nil {
|
||||
global.LOG.Errorf("bind output chains failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func needInit() bool {
|
||||
file, err := os.OpenFile("/run/1panel_boot_mark", os.O_RDWR|os.O_CREATE|os.O_EXCL, 0644)
|
||||
if err != nil {
|
||||
if os.IsExist(err) {
|
||||
return false
|
||||
}
|
||||
global.LOG.Errorf("check boot mark file failed: %v", err)
|
||||
return true
|
||||
}
|
||||
defer file.Close()
|
||||
fmt.Fprintf(file, "Boot Mark for 1panel\n")
|
||||
return true
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package firewall
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/firewall"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/firewall/client/iptables"
|
||||
)
|
||||
|
||||
func Init() {
|
||||
client, err := firewall.NewFirewallClient()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
clientName := client.Name()
|
||||
if clientName == "ufw" || clientName == "iptables" {
|
||||
_ = iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelForward, iptables.ForwardFileName)
|
||||
_ = iptables.LoadRulesFromFile(iptables.NatTab, iptables.Chain1PanelPreRouting, iptables.ForwardFileName1)
|
||||
_ = iptables.LoadRulesFromFile(iptables.NatTab, iptables.Chain1PanelPostRouting, iptables.ForwardFileName2)
|
||||
}
|
||||
if clientName == "iptables" {
|
||||
_ = iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelBasic, iptables.BasicFileName)
|
||||
_ = iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelInput, iptables.InputFileName)
|
||||
_ = iptables.LoadRulesFromFile(iptables.FilterTab, iptables.Chain1PanelOutput, iptables.OutputFileName)
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,11 @@ func InitAgentDB() {
|
||||
migrations.UpdateCronJob,
|
||||
migrations.UpdateTensorrtLLM,
|
||||
migrations.AddIptablesFilterRuleTable,
|
||||
migrations.AddCommonDescription,
|
||||
migrations.UpdateDatabase,
|
||||
migrations.AddGPUMonitor,
|
||||
migrations.UpdateDatabaseMysql,
|
||||
migrations.InitIptablesStatus,
|
||||
})
|
||||
if err := m.Migrate(); err != nil {
|
||||
global.LOG.Error(err)
|
||||
|
||||
@@ -706,9 +706,72 @@ var UpdateTensorrtLLM = &gormigrate.Migration{
|
||||
},
|
||||
}
|
||||
|
||||
var AddCommonDescription = &gormigrate.Migration{
|
||||
ID: "20251117-add-common-description",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
return tx.AutoMigrate(&model.CommonDescription{})
|
||||
},
|
||||
}
|
||||
|
||||
var UpdateDatabase = &gormigrate.Migration{
|
||||
ID: "20251117-update-database",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
return tx.AutoMigrate(&model.Database{})
|
||||
},
|
||||
}
|
||||
|
||||
var AddGPUMonitor = &gormigrate.Migration{
|
||||
ID: "20251122-add-gpu-monitor",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
return global.GPUMonitorDB.AutoMigrate(&model.MonitorGPU{})
|
||||
},
|
||||
}
|
||||
|
||||
var UpdateDatabaseMysql = &gormigrate.Migration{
|
||||
ID: "20251126-update-database-mysql",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.AutoMigrate(&model.DatabaseMysql{}); err != nil {
|
||||
return err
|
||||
}
|
||||
var data []model.DatabaseMysql
|
||||
_ = tx.Where("1 = 1").Find(&data).Error
|
||||
for _, item := range data {
|
||||
if len(item.Collation) == 0 {
|
||||
collation := ""
|
||||
switch item.Format {
|
||||
case "utf8":
|
||||
collation = "utf8_general_ci"
|
||||
case "utf8mb4":
|
||||
collation = "utf8mb4_general_ci"
|
||||
case "gbk":
|
||||
collation = "gbk_chinese_ci"
|
||||
case "big5":
|
||||
collation = "big5_chinese_ci"
|
||||
default:
|
||||
collation = "utf8mb4_general_ci"
|
||||
}
|
||||
_ = tx.Model(&model.DatabaseMysql{}).Where("id = ?", item.ID).Updates(map[string]interface{}{"collation": collation}).Error
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var InitIptablesStatus = &gormigrate.Migration{
|
||||
ID: "20251201-init-iptables-status",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.Create(&model.Setting{Key: "IptablesStatus", Value: constant.StatusDisable}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Create(&model.Setting{Key: "IptablesForwardStatus", Value: constant.StatusDisable}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Create(&model.Setting{Key: "IptablesInputStatus", Value: constant.StatusDisable}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Create(&model.Setting{Key: "IptablesOutputStatus", Value: constant.StatusDisable}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ func (a *AppRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
appRouter.GET("/details/:id", baseApi.GetAppDetailByID)
|
||||
appRouter.POST("/install", baseApi.InstallApp)
|
||||
appRouter.GET("/tags", baseApi.GetAppTags)
|
||||
appRouter.GET("/icon/:appID", baseApi.GetAppIcon)
|
||||
|
||||
appRouter.POST("/installed/check", baseApi.CheckAppInstalled)
|
||||
appRouter.POST("/installed/loadport", baseApi.LoadPort)
|
||||
|
||||
@@ -24,6 +24,7 @@ func (s *ContainerRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
baRouter.POST("/list/byimage", baseApi.ListContainerByImage)
|
||||
baRouter.GET("/status", baseApi.LoadContainerStatus)
|
||||
baRouter.GET("/list/stats", baseApi.ContainerListStats)
|
||||
baRouter.POST("/item/stats", baseApi.ContainerItemStats)
|
||||
baRouter.GET("/search/log", baseApi.ContainerStreamLogs)
|
||||
baRouter.POST("/download/log", baseApi.DownloadContainerLogs)
|
||||
baRouter.GET("/limit", baseApi.LoadResourceLimit)
|
||||
@@ -47,6 +48,7 @@ func (s *ContainerRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
baRouter.POST("/compose", baseApi.CreateCompose)
|
||||
baRouter.POST("/compose/test", baseApi.TestCompose)
|
||||
baRouter.POST("/compose/operate", baseApi.OperatorCompose)
|
||||
baRouter.POST("/compose/clean/log", baseApi.CleanComposeLog)
|
||||
baRouter.POST("/compose/update", baseApi.ComposeUpdate)
|
||||
|
||||
baRouter.GET("/template", baseApi.ListComposeTemplate)
|
||||
|
||||
@@ -20,6 +20,8 @@ func (s *DashboardRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
cmdRouter.GET("/base/:ioOption/:netOption", baseApi.LoadDashboardBaseInfo)
|
||||
cmdRouter.GET("/current/node", baseApi.LoadCurrentInfoForNode)
|
||||
cmdRouter.GET("/current/:ioOption/:netOption", baseApi.LoadDashboardCurrentInfo)
|
||||
cmdRouter.GET("/current/top/cpu", baseApi.LoadDashboardTopCPU)
|
||||
cmdRouter.GET("/current/top/mem", baseApi.LoadDashboardTopMem)
|
||||
cmdRouter.POST("/system/restart/:operation", baseApi.SystemRestart)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ func (s *DatabaseRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
cmdRouter.POST("/variables", baseApi.LoadVariables)
|
||||
cmdRouter.POST("/status", baseApi.LoadStatus)
|
||||
cmdRouter.POST("/remote", baseApi.LoadRemoteAccess)
|
||||
cmdRouter.GET("/options", baseApi.ListDBName)
|
||||
cmdRouter.POST("/format/options", baseApi.ListDBFormatCollationOptions)
|
||||
|
||||
cmdRouter.POST("/redis/persistence/conf", baseApi.LoadPersistenceConf)
|
||||
cmdRouter.POST("/redis/status", baseApi.LoadRedisStatus)
|
||||
|
||||
@@ -29,7 +29,9 @@ func (s *HostRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
hostRouter.POST("/firewall/filter/chain/status", baseApi.LoadChainStatus)
|
||||
|
||||
hostRouter.POST("/monitor/search", baseApi.LoadMonitor)
|
||||
hostRouter.POST("/monitor/gpu/search", baseApi.LoadGPUMonitor)
|
||||
hostRouter.POST("/monitor/clean", baseApi.CleanMonitor)
|
||||
hostRouter.GET("/monitor/gpuoptions", baseApi.GetCPUOptions)
|
||||
hostRouter.GET("/monitor/netoptions", baseApi.GetNetworkOptions)
|
||||
hostRouter.GET("/monitor/iooptions", baseApi.GetIOOptions)
|
||||
hostRouter.GET("/monitor/setting", baseApi.LoadMonitorSetting)
|
||||
|
||||
@@ -16,6 +16,8 @@ func (s *SettingRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
settingRouter.POST("/update", baseApi.UpdateSetting)
|
||||
settingRouter.GET("/get/:key", baseApi.GetSettingByKey)
|
||||
|
||||
settingRouter.POST("/description/save", baseApi.SaveDescription)
|
||||
|
||||
settingRouter.GET("/snapshot/load", baseApi.LoadSnapshotData)
|
||||
settingRouter.POST("/snapshot", baseApi.CreateSnapshot)
|
||||
settingRouter.POST("/snapshot/recreate", baseApi.RecreateSnapshot)
|
||||
|
||||
@@ -42,11 +42,11 @@ func Start() {
|
||||
i18n.Init()
|
||||
cache.Init()
|
||||
app.Init()
|
||||
firewall.Init()
|
||||
lang.Init()
|
||||
validator.Init()
|
||||
cron.Run()
|
||||
hook.Init()
|
||||
go firewall.Init()
|
||||
InitOthers()
|
||||
|
||||
rootRouter := router.Routers()
|
||||
|
||||
@@ -120,6 +120,23 @@ func (x XpuSMI) LoadDashData() ([]XPUSimpleInfo, error) {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (x XpuSMI) LoadDeviceList() ([]string, error) {
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(5 * time.Second))
|
||||
data, err := cmdMgr.RunWithStdoutBashC("xpu-smi discovery -j")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("calling xpu-smi failed, %v", err)
|
||||
}
|
||||
var deviceInfo DeviceInfo
|
||||
if err := json.Unmarshal([]byte(data), &deviceInfo); err != nil {
|
||||
return nil, fmt.Errorf("deviceInfo json unmarshal failed, err: %w", err)
|
||||
}
|
||||
var deviceNames []string
|
||||
for _, device := range deviceInfo.DeviceList {
|
||||
deviceNames = append(deviceNames, fmt.Sprintf("%d - %s", device.DeviceID, device.DeviceName))
|
||||
}
|
||||
return deviceNames, nil
|
||||
}
|
||||
|
||||
func (x XpuSMI) LoadGpuInfo() (*XpuInfo, error) {
|
||||
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(5 * time.Second))
|
||||
data, err := cmdMgr.RunWithStdoutBashC("xpu-smi discovery -j")
|
||||
|
||||
@@ -65,12 +65,12 @@ func AnalysisFromLog(pathItem string, record *model.ClamRecord) {
|
||||
|
||||
func StopAllClamJob(withCheck bool, clamRepo repo.IClamRepo) bool {
|
||||
if withCheck {
|
||||
isActive := false
|
||||
isexist, _ := controller.CheckExist("clam")
|
||||
if isexist {
|
||||
isActive, _ = controller.CheckActive("clam")
|
||||
isExist, _ := controller.CheckExist("clam")
|
||||
if !isExist {
|
||||
return false
|
||||
}
|
||||
if isActive {
|
||||
isActive, _ := controller.CheckActive("clam")
|
||||
if !isActive {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,16 +72,6 @@ func NewAutoAuth(login string, secret string) Authorizer {
|
||||
return az
|
||||
}
|
||||
|
||||
func NewEmptyAuth() Authorizer {
|
||||
fmap := make([]authfactory, 0)
|
||||
az := &authorizer{factories: fmap, defAuthMux: sync.Mutex{}, defAuth: &nullAuth{}}
|
||||
return az
|
||||
}
|
||||
|
||||
func NewPreemptiveAuth(auth Authenticator) Authorizer {
|
||||
return &preemptiveAuthorizer{auth: auth}
|
||||
}
|
||||
|
||||
func (a *authorizer) NewAuthenticator(body io.Reader) (Authenticator, io.Reader) {
|
||||
var retryBuf io.Reader = body
|
||||
if body != nil {
|
||||
@@ -296,11 +286,3 @@ func (n *nullAuth) Clone() Authenticator {
|
||||
func (n *nullAuth) String() string {
|
||||
return "NullAuth"
|
||||
}
|
||||
|
||||
func (b *preemptiveAuthorizer) NewAuthenticator(body io.Reader) (Authenticator, io.Reader) {
|
||||
return b.auth.Clone(), body
|
||||
}
|
||||
|
||||
func (b *preemptiveAuthorizer) AddAuthenticator(key string, fn AuthFactory) {
|
||||
panic("You're funny! A preemptive authorizer may only have a single authentication method")
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package webdav
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"io"
|
||||
"net/url"
|
||||
@@ -63,13 +62,6 @@ func Join(path0 string, path1 string) string {
|
||||
return strings.TrimSuffix(path0, "/") + "/" + strings.TrimPrefix(path1, "/")
|
||||
}
|
||||
|
||||
func String(r io.Reader) string {
|
||||
buf := new(bytes.Buffer)
|
||||
// TODO - make String return an error as well
|
||||
_, _ = buf.ReadFrom(r)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func parseInt64(s *string) int64 {
|
||||
if n, e := strconv.ParseInt(*s, 10, 64); e == nil {
|
||||
return n
|
||||
|
||||
@@ -197,7 +197,7 @@ func (c *Client) MkdirAll(path string, _ os.FileMode) (err error) {
|
||||
return fmt.Errorf("mkdir %s failed, err: %v", item, err)
|
||||
}
|
||||
defer rs.Body.Close()
|
||||
if rs.StatusCode != 201 || rs.StatusCode == 200 {
|
||||
if rs.StatusCode != 201 && rs.StatusCode != 200 {
|
||||
return fmt.Errorf("mkdir %s failed, code: %d, err: %v", item, rs.StatusCode, rs.Status)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,25 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/aws/aws-sdk-go/service/s3/s3manager"
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/config"
|
||||
"github.com/aws/aws-sdk-go-v2/credentials"
|
||||
"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3/types"
|
||||
"github.com/aws/smithy-go"
|
||||
)
|
||||
|
||||
type s3Client struct {
|
||||
scType string
|
||||
bucket string
|
||||
Sess session.Session
|
||||
client *s3.Client
|
||||
}
|
||||
|
||||
func NewS3Client(vars map[string]interface{}) (*s3Client, error) {
|
||||
@@ -31,22 +36,26 @@ func NewS3Client(vars map[string]interface{}) (*s3Client, error) {
|
||||
if len(mode) == 0 {
|
||||
mode = "virtual hosted"
|
||||
}
|
||||
sess, err := session.NewSession(&aws.Config{
|
||||
Credentials: credentials.NewStaticCredentials(accessKey, secretKey, ""),
|
||||
Endpoint: aws.String(endpoint),
|
||||
Region: aws.String(region),
|
||||
DisableSSL: aws.Bool(true), S3ForcePathStyle: aws.Bool(mode == "path"),
|
||||
})
|
||||
cfg, err := config.LoadDefaultConfig(context.Background(),
|
||||
config.WithRegion(region),
|
||||
config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(accessKey, secretKey, "")),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &s3Client{scType: scType, bucket: bucket, Sess: *sess}, nil
|
||||
client := s3.NewFromConfig(cfg, func(o *s3.Options) {
|
||||
o.UsePathStyle = mode == "path"
|
||||
if endpoint != "" {
|
||||
o.BaseEndpoint = aws.String(normalizeEndpoint(endpoint))
|
||||
}
|
||||
})
|
||||
|
||||
return &s3Client{scType: scType, bucket: bucket, client: client}, nil
|
||||
}
|
||||
|
||||
func (s s3Client) ListBuckets() ([]interface{}, error) {
|
||||
func (s *s3Client) ListBuckets() ([]interface{}, error) {
|
||||
var result []interface{}
|
||||
svc := s3.New(&s.Sess)
|
||||
res, err := svc.ListBuckets(nil)
|
||||
res, err := s.client.ListBuckets(context.Background(), &s3.ListBucketsInput{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -56,50 +65,54 @@ func (s s3Client) ListBuckets() ([]interface{}, error) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s s3Client) Exist(path string) (bool, error) {
|
||||
svc := s3.New(&s.Sess)
|
||||
if _, err := svc.HeadObject(&s3.HeadObjectInput{
|
||||
Bucket: &s.bucket,
|
||||
Key: &path,
|
||||
}); err != nil {
|
||||
if aerr, ok := err.(awserr.RequestFailure); ok {
|
||||
if aerr.StatusCode() == 404 {
|
||||
func (s *s3Client) Exist(path string) (bool, error) {
|
||||
_, err := s.client.HeadObject(context.Background(), &s3.HeadObjectInput{
|
||||
Bucket: aws.String(s.bucket),
|
||||
Key: aws.String(path),
|
||||
})
|
||||
if err != nil {
|
||||
var apiErr smithy.APIError
|
||||
if errors.As(err, &apiErr) {
|
||||
switch apiErr.ErrorCode() {
|
||||
case "NotFound", "NoSuchKey":
|
||||
return false, nil
|
||||
}
|
||||
} else {
|
||||
return false, aerr
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (s *s3Client) Size(path string) (int64, error) {
|
||||
svc := s3.New(&s.Sess)
|
||||
file, err := svc.GetObject(&s3.GetObjectInput{
|
||||
Bucket: &s.bucket,
|
||||
Key: &path,
|
||||
file, err := s.client.GetObject(context.Background(), &s3.GetObjectInput{
|
||||
Bucket: aws.String(s.bucket),
|
||||
Key: aws.String(path),
|
||||
})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return *file.ContentLength, nil
|
||||
defer file.Body.Close()
|
||||
return aws.ToInt64(file.ContentLength), nil
|
||||
}
|
||||
|
||||
func (s s3Client) Delete(path string) (bool, error) {
|
||||
svc := s3.New(&s.Sess)
|
||||
if _, err := svc.DeleteObject(&s3.DeleteObjectInput{Bucket: aws.String(s.bucket), Key: aws.String(path)}); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := svc.WaitUntilObjectNotExists(&s3.HeadObjectInput{
|
||||
func (s *s3Client) Delete(path string) (bool, error) {
|
||||
if _, err := s.client.DeleteObject(context.Background(), &s3.DeleteObjectInput{
|
||||
Bucket: aws.String(s.bucket),
|
||||
Key: aws.String(path),
|
||||
}); err != nil {
|
||||
return false, err
|
||||
}
|
||||
waiter := s3.NewObjectNotExistsWaiter(s.client)
|
||||
if err := waiter.Wait(context.Background(), &s3.HeadObjectInput{
|
||||
Bucket: aws.String(s.bucket),
|
||||
Key: aws.String(path),
|
||||
}, 30*time.Second); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (s s3Client) Upload(src, target string) (bool, error) {
|
||||
func (s *s3Client) Upload(src, target string) (bool, error) {
|
||||
fileInfo, err := os.Stat(src)
|
||||
if err != nil {
|
||||
return false, err
|
||||
@@ -110,22 +123,23 @@ func (s s3Client) Upload(src, target string) (bool, error) {
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
uploader := s3manager.NewUploader(&s.Sess)
|
||||
if fileInfo.Size() > s3manager.MaxUploadParts*s3manager.DefaultUploadPartSize {
|
||||
uploader.PartSize = fileInfo.Size() / (s3manager.MaxUploadParts - 1)
|
||||
uploader := manager.NewUploader(s.client)
|
||||
maxUploadSize := int64(manager.MaxUploadParts) * manager.DefaultUploadPartSize
|
||||
if fileInfo.Size() > maxUploadSize {
|
||||
uploader.PartSize = fileInfo.Size() / (int64(manager.MaxUploadParts) - 1)
|
||||
}
|
||||
if _, err := uploader.Upload(&s3manager.UploadInput{
|
||||
if _, err := uploader.Upload(context.Background(), &s3.PutObjectInput{
|
||||
Bucket: aws.String(s.bucket),
|
||||
Key: aws.String(target),
|
||||
Body: file,
|
||||
StorageClass: &s.scType,
|
||||
StorageClass: types.StorageClass(s.scType),
|
||||
}); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (s s3Client) Download(src, target string) (bool, error) {
|
||||
func (s *s3Client) Download(src, target string) (bool, error) {
|
||||
if _, err := os.Stat(target); err == nil {
|
||||
_ = os.Remove(target)
|
||||
}
|
||||
@@ -134,8 +148,8 @@ func (s s3Client) Download(src, target string) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
defer file.Close()
|
||||
downloader := s3manager.NewDownloader(&s.Sess)
|
||||
if _, err = downloader.Download(file, &s3.GetObjectInput{
|
||||
downloader := manager.NewDownloader(s.client)
|
||||
if _, err = downloader.Download(context.Background(), file, &s3.GetObjectInput{
|
||||
Bucket: aws.String(s.bucket),
|
||||
Key: aws.String(src),
|
||||
}); err != nil {
|
||||
@@ -146,17 +160,23 @@ func (s s3Client) Download(src, target string) (bool, error) {
|
||||
}
|
||||
|
||||
func (s *s3Client) ListObjects(prefix string) ([]string, error) {
|
||||
svc := s3.New(&s.Sess)
|
||||
var result []string
|
||||
outputs, err := svc.ListObjects(&s3.ListObjectsInput{
|
||||
Bucket: &s.bucket,
|
||||
Prefix: &prefix,
|
||||
outputs, err := s.client.ListObjectsV2(context.Background(), &s3.ListObjectsV2Input{
|
||||
Bucket: aws.String(s.bucket),
|
||||
Prefix: aws.String(prefix),
|
||||
})
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
for _, item := range outputs.Contents {
|
||||
result = append(result, *item.Key)
|
||||
result = append(result, aws.ToString(item.Key))
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func normalizeEndpoint(endpoint string) string {
|
||||
if strings.HasPrefix(endpoint, "http://") || strings.HasPrefix(endpoint, "https://") {
|
||||
return endpoint
|
||||
}
|
||||
return "http://" + endpoint
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ package client
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
@@ -25,7 +25,7 @@ func NewWebDAVClient(vars map[string]interface{}) (*webDAVClient, error) {
|
||||
username := loadParamFromVars("username", vars)
|
||||
bucket := loadParamFromVars("bucket", vars)
|
||||
|
||||
url := net.JoinHostPort(address, port)
|
||||
url := fmt.Sprintf("%s:%s", address, port)
|
||||
if len(port) == 0 {
|
||||
url = address
|
||||
}
|
||||
|
||||
@@ -71,8 +71,9 @@ func GetDBWithPath(dbPath string) (*gorm.DB, error) {
|
||||
if dbError != nil {
|
||||
return nil, dbError
|
||||
}
|
||||
sqlDB.SetConnMaxIdleTime(10)
|
||||
sqlDB.SetMaxOpenConns(100)
|
||||
sqlDB.SetMaxOpenConns(4)
|
||||
sqlDB.SetMaxIdleConns(1)
|
||||
sqlDB.SetConnMaxIdleTime(15 * time.Minute)
|
||||
sqlDB.SetConnMaxLifetime(time.Hour)
|
||||
return db, nil
|
||||
}
|
||||
|
||||
@@ -1,11 +1,21 @@
|
||||
package compose
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/task"
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/i18n"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/common"
|
||||
"time"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/docker"
|
||||
"github.com/goccy/go-yaml"
|
||||
)
|
||||
|
||||
func checkCmd() error {
|
||||
@@ -27,6 +37,58 @@ func Up(filePath string) (string, error) {
|
||||
return stdout, err
|
||||
}
|
||||
|
||||
func UpWithTask(filePath string, task *task.Task) error {
|
||||
content, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
env, _ := os.ReadFile(path.Join(path.Dir(filePath), ".env"))
|
||||
var compose docker.ComposeProject
|
||||
if err := yaml.Unmarshal(content, &compose); err != nil {
|
||||
return fmt.Errorf("parse docker-compose file failed: %v", err)
|
||||
}
|
||||
images, err := docker.GetImagesFromDockerCompose(env, content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dockerCLi, err := docker.NewClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
errMsg := ""
|
||||
for _, image := range images {
|
||||
task.Log(i18n.GetWithName("PullImageStart", image))
|
||||
if err = dockerCLi.PullImageWithProcess(task, image); err != nil {
|
||||
errOur := err.Error()
|
||||
if errOur != "" {
|
||||
if strings.Contains(errOur, "no such host") {
|
||||
errMsg = i18n.GetMsgByKey("ErrNoSuchHost") + ":"
|
||||
}
|
||||
if strings.Contains(errOur, "Error response from daemon") {
|
||||
errMsg = i18n.GetMsgByKey("PullImageTimeout") + ":"
|
||||
}
|
||||
}
|
||||
message := errMsg + errOur
|
||||
installErr := errors.New(message)
|
||||
task.LogFailedWithErr(i18n.GetMsgByKey("PullImage"), installErr)
|
||||
if exist, _ := dockerCLi.ImageExists(image); !exist {
|
||||
return installErr
|
||||
} else {
|
||||
task.Log(i18n.GetMsgByKey("UseExistImage"))
|
||||
}
|
||||
} else {
|
||||
task.Log(i18n.GetMsgByKey("PullImageSuccess"))
|
||||
}
|
||||
}
|
||||
|
||||
dockerCommand := global.CONF.DockerConfig.Command
|
||||
if dockerCommand == "docker-compose" {
|
||||
return cmd.NewCommandMgr(cmd.WithTask(*task)).Run("docker-compose", "-f", filePath, "up", "-d")
|
||||
} else {
|
||||
return cmd.NewCommandMgr(cmd.WithTask(*task)).Run("docker", "compose", "-f", filePath, "up", "-d")
|
||||
}
|
||||
}
|
||||
|
||||
func Down(filePath string) (string, error) {
|
||||
if err := checkCmd(); err != nil {
|
||||
return "", err
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user