mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-10-09 16:00:29 +00:00
Compare commits
130
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c92226f88 | ||
|
|
cd9cb9b9c9 | ||
|
|
b2777055bc | ||
|
|
c8673b60bb | ||
|
|
21975dff2d | ||
|
|
6ab14185e0 | ||
|
|
1f70646952 | ||
|
|
c90ed9e873 | ||
|
|
e4ee07d36b | ||
|
|
8fb3e78554 | ||
|
|
01ab004876 | ||
|
|
6205eac51c | ||
|
|
d9a5418029 | ||
|
|
74a8e61f3e | ||
|
|
e18472f1a3 | ||
|
|
e3dea80cb7 | ||
|
|
50947f4ddc | ||
|
|
d302bc07b3 | ||
|
|
c6df20e565 | ||
|
|
6f9a1321d1 | ||
|
|
eb4eb31578 | ||
|
|
f8f5fcfca2 | ||
|
|
4e7b654090 | ||
|
|
e8059d3676 | ||
|
|
ffadc6721b | ||
|
|
e2e774d215 | ||
|
|
f23d3678fb | ||
|
|
dfade50bd8 | ||
|
|
d25b5f4f2a | ||
|
|
9a17bc74b0 | ||
|
|
015605526d | ||
|
|
099896dc96 | ||
|
|
aa1bc6fa8e | ||
|
|
f27a429fc5 | ||
|
|
f4587d0ae5 | ||
|
|
41bae1e636 | ||
|
|
5295fd08d4 | ||
|
|
36fdf05d2b | ||
|
|
5794dbc0a6 | ||
|
|
c10474db69 | ||
|
|
d68309fd44 | ||
|
|
1c634756a0 | ||
|
|
ae536550c3 | ||
|
|
63d5d70314 | ||
|
|
0be73600e5 | ||
|
|
c9cc064f51 | ||
|
|
dc47eb5ae4 | ||
|
|
955d9db699 | ||
|
|
3c1549e288 | ||
|
|
9fd030b6c3 | ||
|
|
63a10691b3 | ||
|
|
5674673c5d | ||
|
|
74f29e3dc3 | ||
|
|
1dac8593ae | ||
|
|
71fd123be1 | ||
|
|
d4d66cad2e | ||
|
|
c78a6ec047 | ||
|
|
1ae3198b10 | ||
|
|
a6c172b1ab | ||
|
|
9e9d68f841 | ||
|
|
123e6b90a3 | ||
|
|
00b4a6caf5 | ||
|
|
8642e20d19 | ||
|
|
2b81f7ef7a | ||
|
|
c08e83e5d4 | ||
|
|
863ee5c172 | ||
|
|
a91f372fbd | ||
|
|
825acd5b46 | ||
|
|
70e64e648f | ||
|
|
7855e89ca9 | ||
|
|
75273abda7 | ||
|
|
02b278ecff | ||
|
|
e43d7b7a59 | ||
|
|
61f321a04d | ||
|
|
7885b00213 | ||
|
|
2ad882b7c2 | ||
|
|
2546809013 | ||
|
|
4fcf3e11cd | ||
|
|
1f6cd6f4e9 | ||
|
|
5c1ce232db | ||
|
|
172e9e212b | ||
|
|
279a16c256 | ||
|
|
e772cdff3c | ||
|
|
8881827f9d | ||
|
|
d9579901fe | ||
|
|
682d78698f | ||
|
|
2cc8567c2f | ||
|
|
184a214bff | ||
|
|
c6376541ed | ||
|
|
6aca579854 | ||
|
|
15bc6cf884 | ||
|
|
895dde74dd | ||
|
|
c477d20a05 | ||
|
|
2fdb1700e5 | ||
|
|
11764e1ba5 | ||
|
|
3212e23f43 | ||
|
|
84a58f2bb1 | ||
|
|
191396c78a | ||
|
|
956a64c692 | ||
|
|
6f9a8d5afe | ||
|
|
9424d061fa | ||
|
|
3db8e47679 | ||
|
|
5602741550 | ||
|
|
1ef3f540c2 | ||
|
|
51846895d5 | ||
|
|
551542c99c | ||
|
|
ab13ddec48 | ||
|
|
2d1792c6de | ||
|
|
3aedb7e82d | ||
|
|
a9c9f0272a | ||
|
|
8606427e8c | ||
|
|
3d3d22dc06 | ||
|
|
23a3a5cf74 | ||
|
|
0f5410d225 | ||
|
|
1b7be836ef | ||
|
|
66e7223db9 | ||
|
|
d801b811d4 | ||
|
|
307029272e | ||
|
|
9aa3caab16 | ||
|
|
b47a4525dc | ||
|
|
38ab0d9ca0 | ||
|
|
38985671c6 | ||
|
|
d1c2a69820 | ||
|
|
3a1b9fedd1 | ||
|
|
8119ba75fc | ||
|
|
be4c22012e | ||
|
|
60fef48cf0 | ||
|
|
bb72ea0fc0 | ||
|
|
af48fed3c2 | ||
|
|
ce3fa94708 |
@@ -220,3 +220,23 @@ func (b *BaseApi) GetAppIcon(c *gin.Context) {
|
||||
c.Header("Last-Modified", time.Now().UTC().Format(http.TimeFormat))
|
||||
c.Data(http.StatusOK, "image/png", iconBytes)
|
||||
}
|
||||
|
||||
// @Tags App
|
||||
// @Summary Search app detail by appkey and version
|
||||
// @Accept json
|
||||
// @Param appId path integer true "app key"
|
||||
// @Param version path string true "app version"
|
||||
// @Success 200 {object} response.AppDetailSimpleDTO
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /apps/detail/node/:appKey/:version [get]
|
||||
func (b *BaseApi) GetAppDetailForNode(c *gin.Context) {
|
||||
appKey := c.Param("appKey")
|
||||
version := c.Param("version")
|
||||
appDetailDTO, err := appService.GetAppDetailByKey(appKey, version)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, appDetailDTO)
|
||||
}
|
||||
|
||||
@@ -25,6 +25,23 @@ func (b *BaseApi) CheckBackupUsed(c *gin.Context) {
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Backup Account
|
||||
// @Summary Check backup account
|
||||
// @Accept json
|
||||
// @Param request body dto.BackupOperate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /backups/check [post]
|
||||
func (b *BaseApi) CheckBackup(c *gin.Context) {
|
||||
var req dto.BackupOperate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithData(c, backupService.CheckConn(req))
|
||||
}
|
||||
|
||||
// @Tags Backup Account
|
||||
// @Summary Create backup account
|
||||
// @Accept json
|
||||
|
||||
@@ -524,7 +524,6 @@ func (b *BaseApi) Inspect(c *gin.Context) {
|
||||
helper.SuccessWithData(c, result)
|
||||
}
|
||||
|
||||
// @Router /containers/download/log [post]
|
||||
func (b *BaseApi) DownloadContainerLogs(c *gin.Context) {
|
||||
var req dto.ContainerLog
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
@@ -738,6 +737,7 @@ func (b *BaseApi) ComposeUpdate(c *gin.Context) {
|
||||
// @Param since query string false "时间筛选"
|
||||
// @Param follow query string false "是否追踪"
|
||||
// @Param tail query string false "显示行号"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /containers/search/log [get]
|
||||
|
||||
@@ -27,7 +27,7 @@ func (b *BaseApi) LoadDashboardOsInfo(c *gin.Context) {
|
||||
// @Tags Dashboard
|
||||
// @Summary Load app launcher
|
||||
// @Accept json
|
||||
// @Success 200 {Array} dto.AppLauncher
|
||||
// @Success 200 {array} dto.AppLauncher
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /dashboard/app/launcher [get]
|
||||
@@ -44,7 +44,7 @@ func (b *BaseApi) LoadAppLauncher(c *gin.Context) {
|
||||
// @Summary Load app launcher options
|
||||
// @Accept json
|
||||
// @Param request body dto.SearchByFilter true "request"
|
||||
// @Success 200 {Array} dto.LauncherOption
|
||||
// @Success 200 {array} dto.LauncherOption
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /dashboard/app/launcher/option [post]
|
||||
@@ -85,7 +85,7 @@ func (b *BaseApi) UpdateAppLauncher(c *gin.Context) {
|
||||
|
||||
// @Tags Dashboard
|
||||
// @Summary Load quick jump options
|
||||
// @Success 200 {Array} dto.QuickJump
|
||||
// @Success 200 {array} dto.QuickJump
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /dashboard/quick/option [get]
|
||||
@@ -181,7 +181,7 @@ func (b *BaseApi) LoadDashboardCurrentInfo(c *gin.Context) {
|
||||
|
||||
// @Tags Dashboard
|
||||
// @Summary Load top cpu processes
|
||||
// @Success 200 {Array} dto.Process
|
||||
// @Success 200 {array} dto.Process
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /dashboard/current/top/cpu [get]
|
||||
@@ -192,7 +192,7 @@ func (b *BaseApi) LoadDashboardTopCPU(c *gin.Context) {
|
||||
|
||||
// @Tags Dashboard
|
||||
// @Summary Load top memory processes
|
||||
// @Success 200 {Array} dto.Process
|
||||
// @Success 200 {array} dto.Process
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /dashboard/current/top/mem [get]
|
||||
|
||||
@@ -214,6 +214,7 @@ func (b *BaseApi) ListDBFormatCollationOptions(c *gin.Context) {
|
||||
// @Summary Load mysql database from remote
|
||||
// @Accept json
|
||||
// @Param request body dto.MysqlLoadDB true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /databases/load [post]
|
||||
|
||||
@@ -167,6 +167,7 @@ func (b *BaseApi) SearchPostgresql(c *gin.Context) {
|
||||
// @Summary Load postgresql database from remote
|
||||
// @Accept json
|
||||
// @Param request body dto.PostgresqlLoadDB true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /databases/pg/:database/load [post]
|
||||
|
||||
@@ -27,7 +27,7 @@ func (b *BaseApi) LoadDeviceBaseInfo(c *gin.Context) {
|
||||
// @Tags Device
|
||||
// @Summary list time zone options
|
||||
// @Accept json
|
||||
// @Success 200 {Array} string
|
||||
// @Success 200 {array} string
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /toolbox/device/zone/options [get]
|
||||
|
||||
@@ -28,7 +28,7 @@ func (b *BaseApi) LoadFail2BanBaseInfo(c *gin.Context) {
|
||||
// @Summary Page fail2ban ip list
|
||||
// @Accept json
|
||||
// @Param request body dto.Fail2BanSearch true "request"
|
||||
// @Success 200 {Array} string
|
||||
// @Success 200 {array} string
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /toolbox/fail2ban/search [post]
|
||||
@@ -51,6 +51,7 @@ func (b *BaseApi) SearchFail2Ban(c *gin.Context) {
|
||||
// @Summary Operate fail2ban
|
||||
// @Accept json
|
||||
// @Param request body dto.Operate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /toolbox/fail2ban/operate [post]
|
||||
@@ -72,7 +73,8 @@ func (b *BaseApi) OperateFail2Ban(c *gin.Context) {
|
||||
// @Tags Fail2ban
|
||||
// @Summary Operate sshd of fail2ban
|
||||
// @Accept json
|
||||
// @Param request body dto.Operate true "request"
|
||||
// @Param request body dto.Fail2BanSet true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /toolbox/fail2ban/operate/sshd [post]
|
||||
|
||||
@@ -272,6 +272,29 @@ func (b *BaseApi) GetContent(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags File
|
||||
// @Summary Preview file content
|
||||
// @Accept json
|
||||
// @Param request body request.FileContentReq true "request"
|
||||
// @Success 200 {object} response.FileInfo
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /files/preview [post]
|
||||
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"预览文件内容 [path]","formatEN":"Preview file content [path]"}
|
||||
func (b *BaseApi) PreviewContent(c *gin.Context) {
|
||||
var req request.FileContentReq
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
info, err := fileService.GetPreviewContent(req)
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithData(c, info)
|
||||
}
|
||||
|
||||
// @Tags File
|
||||
// @Summary Update file content
|
||||
// @Accept json
|
||||
|
||||
@@ -54,6 +54,7 @@ func (b *BaseApi) LoadFtpLogInfo(c *gin.Context) {
|
||||
// @Summary Operate FTP
|
||||
// @Accept json
|
||||
// @Param request body dto.Operate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /toolbox/ftp/operate [post]
|
||||
|
||||
@@ -34,7 +34,7 @@ func (b *BaseApi) LoadMonitor(c *gin.Context) {
|
||||
// @Tags Monitor
|
||||
// @Summary Load monitor data
|
||||
// @Param request body dto.MonitorGPUSearch true "request"
|
||||
// @Success 200 {object} dto.dto.MonitorGPUData
|
||||
// @Success 200 {object} dto.MonitorGPUData
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /hosts/monitor/gpu/search [post]
|
||||
|
||||
@@ -84,9 +84,31 @@ func (b *BaseApi) CheckLocalConn(c *gin.Context) {
|
||||
helper.SuccessWithData(c, err == nil)
|
||||
}
|
||||
|
||||
// @Tags System Setting
|
||||
// @Summary Update local is conn
|
||||
// @Accept json
|
||||
// @Param request body dto.SSHDefaultConn true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /settings/ssh/conn/default [post]
|
||||
// @x-panel-log {"bodyKeys":["defaultConn"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"本地终端默认连接 [defaultConn]","formatEN":"update system default conn [defaultConn]"}
|
||||
func (b *BaseApi) SetDefaultIsConn(c *gin.Context) {
|
||||
var req dto.SSHDefaultConn
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := settingService.SetDefaultIsConn(req); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags System Setting
|
||||
// @Summary Check local conn info
|
||||
// @Success 200 {bool} isOk
|
||||
// @Success 200 {boolean} isOk
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /settings/ssh/check/info [post]
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
// @Tags Host
|
||||
// @Summary Check if a system component exists
|
||||
// @Accept json
|
||||
// @Param name query string true "Component name to check (e.g., rsync, docker)"
|
||||
// @Param name path string true "Component name to check (e.g., rsync, docker)"
|
||||
// @Success 200 {object} response.ComponentInfo
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
|
||||
@@ -73,7 +73,7 @@ func (b *BaseApi) GetWebsiteOptions(c *gin.Context) {
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites [post]
|
||||
// @x-panel-log {"bodyKeys":["primaryDomain"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建网站 [primaryDomain]","formatEN":"Create website [primaryDomain]"}
|
||||
// @x-panel-log {"bodyKeys":["alias"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"创建网站 [alias]","formatEN":"Create website [alias]"}
|
||||
func (b *BaseApi) CreateWebsite(c *gin.Context) {
|
||||
var req request.WebsiteCreate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
@@ -1223,3 +1223,43 @@ func (b *BaseApi) UpdateCORSConfig(c *gin.Context) {
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Website
|
||||
// @Summary Update Stream Config
|
||||
// @Accept json
|
||||
// @Param request body request.StreamUpdate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/stream/update [post]
|
||||
func (b *BaseApi) UpdateStreamConfig(c *gin.Context) {
|
||||
var req request.StreamUpdate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := websiteService.UpdateStream(req); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
// @Tags Website
|
||||
// @Summary Batch set HTTPS for websites
|
||||
// @Accept json
|
||||
// @Param request body request.BatchWebsiteHttps true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Security Timestamp
|
||||
// @Router /websites/batch/https [post]
|
||||
func (b *BaseApi) BatchSetHttps(c *gin.Context) {
|
||||
var req request.BatchWebsiteHttps
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := websiteService.BatchSetHttps(c, req); err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.Success(c)
|
||||
}
|
||||
|
||||
+20
-19
@@ -84,25 +84,26 @@ type ExtraProperties struct {
|
||||
}
|
||||
|
||||
type AppProperty struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Tags []string `json:"tags"`
|
||||
ShortDescZh string `json:"shortDescZh" yaml:"shortDescZh"`
|
||||
ShortDescEn string `json:"shortDescEn" yaml:"shortDescEn"`
|
||||
Description Locale `json:"description"`
|
||||
Key string `json:"key"`
|
||||
Required []string `json:"Required"`
|
||||
CrossVersionUpdate bool `json:"crossVersionUpdate"`
|
||||
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" yaml:"memoryRequired"`
|
||||
GpuSupport bool `json:"gpuSupport"`
|
||||
Version float64 `json:"version"`
|
||||
Deprecated float64 `json:"deprecated"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Tags []string `json:"tags"`
|
||||
ShortDescZh string `json:"shortDescZh" yaml:"shortDescZh"`
|
||||
ShortDescEn string `json:"shortDescEn" yaml:"shortDescEn"`
|
||||
Description Locale `json:"description"`
|
||||
Key string `json:"key"`
|
||||
Required []string `json:"Required"`
|
||||
CrossVersionUpdate bool `json:"crossVersionUpdate" yaml:"crossVersionUpdate"`
|
||||
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" yaml:"memoryRequired"`
|
||||
GpuSupport bool `json:"gpuSupport" yaml:"gpuSupport"`
|
||||
Version float64 `json:"version"`
|
||||
Deprecated float64 `json:"deprecated"`
|
||||
BatchInstallSupport bool `json:"batchInstallSupport"`
|
||||
}
|
||||
|
||||
type AppConfigVersion struct {
|
||||
|
||||
@@ -33,6 +33,12 @@ type BackupInfo struct {
|
||||
RememberAuth bool `json:"rememberAuth"`
|
||||
}
|
||||
|
||||
type BackupCheckRes struct {
|
||||
IsOk bool `json:"isOk"`
|
||||
Msg string `json:"msg"`
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
type ForBuckets struct {
|
||||
Type string `json:"type" validate:"required"`
|
||||
AccessKey string `json:"accessKey"`
|
||||
@@ -77,6 +83,7 @@ type CommonRecover struct {
|
||||
Secret string `json:"secret"`
|
||||
TaskID string `json:"taskID"`
|
||||
BackupRecordID uint `json:"backupRecordID"`
|
||||
Timeout int `json:"timeout"`
|
||||
}
|
||||
|
||||
type RecordSearch struct {
|
||||
|
||||
+25
-21
@@ -15,8 +15,9 @@ type PageContainer struct {
|
||||
}
|
||||
|
||||
type InspectReq struct {
|
||||
ID string `json:"id" validate:"required"`
|
||||
Type string `json:"type" validate:"required"`
|
||||
ID string `json:"id" validate:"required"`
|
||||
Type string `json:"type" validate:"required"`
|
||||
Detail string `json:"detail"`
|
||||
}
|
||||
|
||||
type ContainerInfo struct {
|
||||
@@ -261,39 +262,42 @@ type ComposeInfo struct {
|
||||
Workdir string `json:"workdir"`
|
||||
Path string `json:"path"`
|
||||
Containers []ComposeContainer `json:"containers"`
|
||||
Env []string `json:"env"`
|
||||
Env string `json:"env"`
|
||||
}
|
||||
type ComposeContainer struct {
|
||||
ContainerID string `json:"containerID"`
|
||||
Name string `json:"name"`
|
||||
CreateTime string `json:"createTime"`
|
||||
State string `json:"state"`
|
||||
ContainerID string `json:"containerID"`
|
||||
Name string `json:"name"`
|
||||
CreateTime string `json:"createTime"`
|
||||
State string `json:"state"`
|
||||
Ports []string `json:"ports"`
|
||||
}
|
||||
type ComposeCreate struct {
|
||||
TaskID string `json:"taskID"`
|
||||
Name string `json:"name"`
|
||||
From string `json:"from" validate:"required,oneof=edit path template"`
|
||||
File string `json:"file"`
|
||||
Path string `json:"path"`
|
||||
Template uint `json:"template"`
|
||||
Env []string `json:"env"`
|
||||
TaskID string `json:"taskID"`
|
||||
Name string `json:"name"`
|
||||
From string `json:"from" validate:"required,oneof=edit path template"`
|
||||
File string `json:"file"`
|
||||
Path string `json:"path"`
|
||||
Template uint `json:"template"`
|
||||
Env string `json:"env"`
|
||||
}
|
||||
type ComposeOperation struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Path string `json:"path"`
|
||||
Operation string `json:"operation" validate:"required,oneof=up start restart stop down delete"`
|
||||
WithFile bool `json:"withFile"`
|
||||
Force bool `josn:"force"`
|
||||
Force bool `json:"force"`
|
||||
}
|
||||
type ComposeUpdate struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Path string `json:"path" validate:"required"`
|
||||
Content string `json:"content" validate:"required"`
|
||||
Env []string `json:"env"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Path string `json:"path" validate:"required"`
|
||||
DetailPath string `json:"detailPath"`
|
||||
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"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Path string `json:"path" validate:"required"`
|
||||
DetailPath string `json:"detailPath"`
|
||||
}
|
||||
|
||||
type ContainerLog struct {
|
||||
|
||||
@@ -19,7 +19,7 @@ type RuleSearch struct {
|
||||
}
|
||||
|
||||
type FirewallOperation struct {
|
||||
Operation string `json:"operation" validate:"required,oneof=start stop restart disablePing enablePing"`
|
||||
Operation string `json:"operation" validate:"required,oneof=start stop restart disableBanPing enableBanPing"`
|
||||
WithDockerRestart bool `json:"withDockerRestart"`
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,18 @@ type MonitorSettingUpdate struct {
|
||||
}
|
||||
|
||||
type MonitorGPUOptions struct {
|
||||
GPUType string `json:"gpuType"`
|
||||
Options []string `json:"options"`
|
||||
GPUType string `json:"gpuType"`
|
||||
ChartHide []GPUChartHide `json:"chartHide"`
|
||||
Options []string `json:"options"`
|
||||
}
|
||||
type GPUChartHide struct {
|
||||
ProductName string `json:"productName"`
|
||||
Process bool `json:"process"`
|
||||
GPU bool `json:"gpu"`
|
||||
Memory bool `json:"memory"`
|
||||
Power bool `json:"power"`
|
||||
Temperature bool `json:"temperature"`
|
||||
Speed bool `json:"speed"`
|
||||
}
|
||||
type MonitorGPUSearch struct {
|
||||
ProductName string `json:"productName"`
|
||||
@@ -59,6 +69,7 @@ type MonitorGPUData struct {
|
||||
MemoryPercent []float64 `json:"memoryPercent"`
|
||||
SpeedValue []int `json:"speedValue"`
|
||||
|
||||
ProcessCount []int `json:"processCount"`
|
||||
GPUProcesses [][]GPUProcess `json:"gpuProcesses"`
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,16 @@ type AppInstallCreate struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Services map[string]string `json:"services"`
|
||||
TaskID string `json:"taskID"`
|
||||
|
||||
AppContainerConfig
|
||||
NodePushConfig
|
||||
}
|
||||
|
||||
type NodePushConfig struct {
|
||||
Nodes []string `json:"nodes"`
|
||||
PushNode bool `json:"pushNode"`
|
||||
AppKey string `json:"appKey"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
type AppContainerConfig struct {
|
||||
|
||||
@@ -13,6 +13,7 @@ type DiskMountRequest struct {
|
||||
MountPoint string `json:"mountPoint" validate:"required"`
|
||||
Filesystem string `json:"filesystem" validate:"required,oneof=ext4 xfs"`
|
||||
AutoMount bool `json:"autoMount"`
|
||||
NoFail bool `json:"noFail"`
|
||||
}
|
||||
|
||||
type DiskUnmountRequest struct {
|
||||
|
||||
@@ -13,7 +13,6 @@ type FileContentReq struct {
|
||||
Path string `json:"path" validate:"required"`
|
||||
IsDetail bool `json:"isDetail"`
|
||||
}
|
||||
|
||||
type SearchUploadWithPage struct {
|
||||
dto.PageInfo
|
||||
Path string `json:"path" validate:"required"`
|
||||
|
||||
@@ -38,6 +38,22 @@ type WebsiteCreate struct {
|
||||
FtpConfig
|
||||
DataBaseConfig
|
||||
SSLConfig
|
||||
StreamConfig
|
||||
}
|
||||
|
||||
type StreamConfig struct {
|
||||
StreamPorts string `json:"streamPorts"`
|
||||
Name string `json:"name"`
|
||||
Algorithm string `json:"algorithm"`
|
||||
UDP bool `json:"udp"`
|
||||
|
||||
Servers []dto.NginxUpstreamServer `json:"servers"`
|
||||
}
|
||||
|
||||
type StreamUpdate struct {
|
||||
WebsiteID uint `json:"websiteID" validate:"required"`
|
||||
|
||||
StreamConfig
|
||||
}
|
||||
|
||||
type WebsiteOptionReq struct {
|
||||
@@ -114,6 +130,25 @@ type BatchWebsiteGroup struct {
|
||||
GroupID uint `json:"groupID" validate:"required"`
|
||||
}
|
||||
|
||||
type BatchWebsiteHttps struct {
|
||||
IDs []uint `json:"ids" validate:"required"`
|
||||
TaskID string `json:"taskID" validate:"required"`
|
||||
WebsiteSSLID uint `json:"websiteSSLId"`
|
||||
Type string `json:"type" validate:"oneof=existed auto manual"`
|
||||
PrivateKey string `json:"privateKey"`
|
||||
Certificate string `json:"certificate"`
|
||||
PrivateKeyPath string `json:"privateKeyPath"`
|
||||
CertificatePath string `json:"certificatePath"`
|
||||
ImportType string `json:"importType"`
|
||||
HttpConfig string `json:"httpConfig" validate:"oneof=HTTPSOnly HTTPAlso HTTPToHTTPS"`
|
||||
SSLProtocol []string `json:"SSLProtocol"`
|
||||
Algorithm string `json:"algorithm"`
|
||||
Hsts bool `json:"hsts"`
|
||||
HstsIncludeSubDomains bool `json:"hstsIncludeSubDomains"`
|
||||
HttpsPorts []int `json:"httpsPorts"`
|
||||
Http3 bool `json:"http3"`
|
||||
}
|
||||
|
||||
type WebsiteRedirectUpdate struct {
|
||||
WebsiteID uint `json:"websiteId" validate:"required"`
|
||||
Key string `json:"key" validate:"required"`
|
||||
@@ -276,6 +311,7 @@ type WebsiteHtmlReq struct {
|
||||
type WebsiteHtmlUpdate struct {
|
||||
Type string `json:"type" validate:"required"`
|
||||
Content string `json:"content" validate:"required"`
|
||||
Sync bool `json:"sync"`
|
||||
}
|
||||
|
||||
type WebsiteLBCreate struct {
|
||||
|
||||
@@ -31,6 +31,7 @@ type WebsiteSSLCreate struct {
|
||||
Shell string `json:"shell"`
|
||||
PushNode bool `json:"pushNode"`
|
||||
Nodes string `json:"nodes"`
|
||||
IsIp bool `json:"isIp"`
|
||||
}
|
||||
|
||||
type WebsiteDNSReq struct {
|
||||
|
||||
@@ -29,17 +29,18 @@ type AppDTO struct {
|
||||
}
|
||||
|
||||
type AppItem struct {
|
||||
Name string `json:"name"`
|
||||
Key string `json:"key"`
|
||||
ID uint `json:"id"`
|
||||
Description string `json:"description"`
|
||||
Status string `json:"status"`
|
||||
Installed bool `json:"installed"`
|
||||
Limit int `json:"limit"`
|
||||
Tags []string `json:"tags"`
|
||||
GpuSupport bool `json:"gpuSupport"`
|
||||
Recommend int `json:"recommend"`
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
Key string `json:"key"`
|
||||
ID uint `json:"id"`
|
||||
Description string `json:"description"`
|
||||
Status string `json:"status"`
|
||||
Installed bool `json:"installed"`
|
||||
Limit int `json:"limit"`
|
||||
Tags []string `json:"tags"`
|
||||
GpuSupport bool `json:"gpuSupport"`
|
||||
Recommend int `json:"recommend"`
|
||||
Type string `json:"type"`
|
||||
BatchInstallSupport bool `json:"batchInstallSupport"`
|
||||
}
|
||||
|
||||
type TagDTO struct {
|
||||
@@ -75,6 +76,10 @@ type AppDetailDTO struct {
|
||||
GpuSupport bool `json:"gpuSupport"`
|
||||
}
|
||||
|
||||
type AppDetailSimpleDTO struct {
|
||||
ID uint `json:"id"`
|
||||
}
|
||||
|
||||
type IgnoredApp struct {
|
||||
Icon string `json:"icon"`
|
||||
Name string `json:"name"`
|
||||
|
||||
@@ -3,6 +3,7 @@ package response
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
)
|
||||
|
||||
@@ -16,6 +17,10 @@ type WebsiteDTO struct {
|
||||
RuntimeType string `json:"runtimeType"`
|
||||
SiteDir string `json:"siteDir"`
|
||||
OpenBaseDir bool `json:"openBaseDir"`
|
||||
Algorithm string `json:"algorithm"`
|
||||
UDP bool `json:"udp"`
|
||||
|
||||
Servers []dto.NginxUpstreamServer `json:"servers"`
|
||||
}
|
||||
|
||||
type WebsiteRes struct {
|
||||
|
||||
@@ -37,6 +37,7 @@ type SyncTime struct {
|
||||
|
||||
type CleanData struct {
|
||||
SystemClean []CleanTree `json:"systemClean"`
|
||||
BackupClean []CleanTree `json:"backupClean"`
|
||||
UploadClean []CleanTree `json:"uploadClean"`
|
||||
DownloadClean []CleanTree `json:"downloadClean"`
|
||||
SystemLogClean []CleanTree `json:"systemLogClean"`
|
||||
@@ -62,6 +63,10 @@ type Clean struct {
|
||||
Size uint64 `json:"size"`
|
||||
}
|
||||
|
||||
type SSHDefaultConn struct {
|
||||
WithReset bool `json:"withReset"`
|
||||
DefaultConn string `json:"defaultConn"`
|
||||
}
|
||||
type SSHConnData struct {
|
||||
Addr string `json:"addr" validate:"required"`
|
||||
Port uint `json:"port" validate:"required,number,max=65535,min=1"`
|
||||
|
||||
@@ -52,6 +52,7 @@ type DataTree struct {
|
||||
Label string `json:"label"`
|
||||
Key string `json:"key"`
|
||||
Name string `json:"name"`
|
||||
IsLocal bool `json:"isLocal"`
|
||||
Size uint64 `json:"size"`
|
||||
IsCheck bool `json:"isCheck"`
|
||||
IsDisable bool `json:"isDisable"`
|
||||
|
||||
@@ -34,6 +34,7 @@ type App struct {
|
||||
MemoryRequired int `json:"memoryRequired"`
|
||||
GpuSupport bool `json:"gpuSupport"`
|
||||
RequiredPanelVersion float64 `json:"requiredPanelVersion"`
|
||||
BatchInstallSupport bool `json:"batchInstallSupport" yaml:"batchInstallSupport"`
|
||||
|
||||
Details []AppDetail `json:"-" gorm:"-:migration"`
|
||||
TagsKey []string `json:"tags" yaml:"tags" gorm:"-"`
|
||||
|
||||
@@ -37,6 +37,8 @@ type Website struct {
|
||||
|
||||
Favorite bool `json:"favorite"`
|
||||
|
||||
StreamPorts string `json:"streamPorts"`
|
||||
|
||||
Domains []WebsiteDomain `json:"domains" gorm:"-:migration"`
|
||||
WebsiteSSL WebsiteSSL `json:"webSiteSSL" gorm:"-:migration"`
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ type WebsiteSSL struct {
|
||||
PushNode bool `json:"pushNode"`
|
||||
PrivateKeyPath string `json:"privateKeyPath"`
|
||||
CertPath string `json:"certPath"`
|
||||
IsIp bool `json:"isIP"`
|
||||
|
||||
AcmeAccount WebsiteAcmeAccount `json:"acmeAccount" gorm:"-:migration"`
|
||||
DnsAccount WebsiteDnsAccount `json:"dnsAccount" gorm:"-:migration"`
|
||||
|
||||
@@ -33,7 +33,7 @@ type IAppRepo interface {
|
||||
DeleteByIDs(ctx context.Context, ids []uint) error
|
||||
DeleteBy(opts ...DBOption) error
|
||||
|
||||
GetTopRecomment() ([]string, error)
|
||||
GetTopRecommend() ([]string, error)
|
||||
}
|
||||
|
||||
func NewIAppRepo() IAppRepo {
|
||||
@@ -124,7 +124,7 @@ func (a AppRepo) GetBy(opts ...DBOption) ([]model.App, error) {
|
||||
return apps, nil
|
||||
}
|
||||
|
||||
func (a AppRepo) GetTopRecomment() ([]string, error) {
|
||||
func (a AppRepo) GetTopRecommend() ([]string, error) {
|
||||
var (
|
||||
apps []model.App
|
||||
names []string
|
||||
|
||||
@@ -47,6 +47,7 @@ type IAppService interface {
|
||||
GetAppDetailByID(id uint) (*response.AppDetailDTO, error)
|
||||
SyncAppListFromLocal(taskID string)
|
||||
GetAppIcon(appID uint) ([]byte, error)
|
||||
GetAppDetailByKey(appKey, version string) (response.AppDetailSimpleDTO, error)
|
||||
}
|
||||
|
||||
func NewIAppService() IAppService {
|
||||
@@ -118,14 +119,15 @@ func (a AppService) PageApp(ctx *gin.Context, req request.AppSearch) (*response.
|
||||
}
|
||||
}
|
||||
appDTO := &response.AppItem{
|
||||
ID: ap.ID,
|
||||
Name: ap.Name,
|
||||
Key: ap.Key,
|
||||
Limit: ap.Limit,
|
||||
GpuSupport: ap.GpuSupport,
|
||||
Recommend: ap.Recommend,
|
||||
Description: ap.GetDescription(ctx),
|
||||
Type: ap.Type,
|
||||
ID: ap.ID,
|
||||
Name: ap.Name,
|
||||
Key: ap.Key,
|
||||
Limit: ap.Limit,
|
||||
GpuSupport: ap.GpuSupport,
|
||||
Recommend: ap.Recommend,
|
||||
Description: ap.GetDescription(ctx),
|
||||
Type: ap.Type,
|
||||
BatchInstallSupport: ap.BatchInstallSupport,
|
||||
}
|
||||
appDTOs = append(appDTOs, appDTO)
|
||||
tags, err := getAppTags(ap.ID, lang)
|
||||
@@ -203,6 +205,20 @@ func (a AppService) GetApp(ctx *gin.Context, key string) (*response.AppDTO, erro
|
||||
return &appDTO, nil
|
||||
}
|
||||
|
||||
func (a AppService) GetAppDetailByKey(appKey, version string) (response.AppDetailSimpleDTO, error) {
|
||||
var appDetailDTO response.AppDetailSimpleDTO
|
||||
app, err := appRepo.GetFirst(appRepo.WithKey(appKey))
|
||||
if err != nil {
|
||||
return appDetailDTO, err
|
||||
}
|
||||
appDetail, err := appDetailRepo.GetFirst(appDetailRepo.WithAppId(app.ID), appDetailRepo.WithVersion(version))
|
||||
if err != nil {
|
||||
return appDetailDTO, err
|
||||
}
|
||||
appDetailDTO.ID = appDetail.ID
|
||||
return appDetailDTO, nil
|
||||
}
|
||||
|
||||
func (a AppService) GetAppDetail(appID uint, version, appType string) (response.AppDetailDTO, error) {
|
||||
var (
|
||||
appDetailDTO response.AppDetailDTO
|
||||
@@ -386,11 +402,21 @@ func (a AppService) Install(req request.AppInstallCreate) (appInstall *model.App
|
||||
App: app,
|
||||
}
|
||||
composeMap := make(map[string]interface{})
|
||||
var composeRes []byte
|
||||
if req.EditCompose {
|
||||
if err = yaml.Unmarshal([]byte(req.DockerCompose), &composeMap); err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if appDetail.DockerCompose == "" {
|
||||
dockerComposeUrl := fmt.Sprintf("%s/%s/1panel/%s/%s/docker-compose.yml", global.CONF.RemoteURL.AppRepo, global.CONF.Base.Mode, app.Key, appDetail.Version)
|
||||
_, composeRes, err = req_helper.HandleRequest(dockerComposeUrl, http.MethodGet, constant.TimeOut20s)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
appDetail.DockerCompose = string(composeRes)
|
||||
_ = appDetailRepo.Update(context.Background(), appDetail)
|
||||
}
|
||||
if err = yaml.Unmarshal([]byte(appDetail.DockerCompose), &composeMap); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"maps"
|
||||
"math"
|
||||
"net/http"
|
||||
@@ -45,6 +44,7 @@ import (
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/subosito/gotenv"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@@ -959,7 +959,7 @@ func handleMap(params map[string]interface{}, envParams map[string]string) {
|
||||
}
|
||||
}
|
||||
|
||||
func downloadApp(app model.App, appDetail model.AppDetail, appInstall *model.AppInstall, logger *log.Logger) (err error) {
|
||||
func downloadApp(app model.App, appDetail model.AppDetail, appInstall *model.AppInstall, logger *logrus.Logger) (err error) {
|
||||
if app.IsLocalApp() || app.IsCustomApp() {
|
||||
return nil
|
||||
}
|
||||
@@ -1312,6 +1312,7 @@ func getApps(oldApps []model.App, items []dto.AppDefine, systemVersion string, t
|
||||
app.MemoryRequired = config.MemoryRequired
|
||||
app.Architectures = strings.Join(config.Architectures, ",")
|
||||
app.GpuSupport = config.GpuSupport
|
||||
app.BatchInstallSupport = config.BatchInstallSupport
|
||||
apps[key] = app
|
||||
}
|
||||
return apps
|
||||
|
||||
+50
-37
@@ -34,6 +34,7 @@ type IBackupService interface {
|
||||
LoadBackupOptions() ([]dto.BackupOption, error)
|
||||
SearchWithPage(search dto.SearchPageWithType) (int64, interface{}, error)
|
||||
Create(backupDto dto.BackupOperate) error
|
||||
CheckConn(req dto.BackupOperate) dto.BackupCheckRes
|
||||
GetBuckets(backupDto dto.ForBuckets) ([]interface{}, error)
|
||||
Update(req dto.BackupOperate) error
|
||||
Delete(id uint) error
|
||||
@@ -123,6 +124,43 @@ func (u *BackupService) SearchWithPage(req dto.SearchPageWithType) (int64, inter
|
||||
return count, data, nil
|
||||
}
|
||||
|
||||
func (u *BackupService) CheckConn(req dto.BackupOperate) dto.BackupCheckRes {
|
||||
var res dto.BackupCheckRes
|
||||
var backup model.BackupAccount
|
||||
if err := copier.Copy(&backup, &req); err != nil {
|
||||
res.Msg = i18n.GetMsgWithDetail("ErrStructTransform", err.Error())
|
||||
return res
|
||||
}
|
||||
itemAccessKey, err := base64.StdEncoding.DecodeString(backup.AccessKey)
|
||||
if err != nil {
|
||||
res.Msg = err.Error()
|
||||
return res
|
||||
}
|
||||
backup.AccessKey = string(itemAccessKey)
|
||||
itemCredential, err := base64.StdEncoding.DecodeString(backup.Credential)
|
||||
if err != nil {
|
||||
res.Msg = err.Error()
|
||||
return res
|
||||
}
|
||||
backup.Credential = string(itemCredential)
|
||||
|
||||
if req.Type == constant.OneDrive || req.Type == constant.GoogleDrive {
|
||||
refreshToken, err := loadRefreshTokenByCode(&backup)
|
||||
if err != nil {
|
||||
res.Msg = err.Error()
|
||||
return res
|
||||
}
|
||||
res.Token = base64.StdEncoding.EncodeToString([]byte(refreshToken))
|
||||
}
|
||||
isOk, err := u.checkBackupConn(&backup)
|
||||
if err != nil {
|
||||
res.Msg = err.Error()
|
||||
return res
|
||||
}
|
||||
res.IsOk = isOk
|
||||
return res
|
||||
}
|
||||
|
||||
func (u *BackupService) Create(req dto.BackupOperate) error {
|
||||
if req.Type == constant.Local {
|
||||
return buserr.New("ErrBackupLocalCreate")
|
||||
@@ -147,19 +185,6 @@ func (u *BackupService) Create(req dto.BackupOperate) error {
|
||||
return err
|
||||
}
|
||||
backup.Credential = string(itemCredential)
|
||||
|
||||
if req.Type == constant.OneDrive || req.Type == constant.GoogleDrive || req.Type == constant.ALIYUN {
|
||||
if err := loadRefreshTokenByCode(&backup); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if req.Type != constant.Local {
|
||||
isOk, err := u.checkBackupConn(&backup)
|
||||
if err != nil || !isOk {
|
||||
return buserr.WithMap("ErrBackupCheck", map[string]interface{}{"err": err.Error()}, err)
|
||||
}
|
||||
}
|
||||
|
||||
backup.AccessKey, err = encrypt.StringEncrypt(backup.AccessKey)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -248,16 +273,7 @@ func (u *BackupService) Update(req dto.BackupOperate) error {
|
||||
global.Dir.LocalBackupDir = newBackup.BackupPath
|
||||
}
|
||||
|
||||
if newBackup.Type == constant.OneDrive || newBackup.Type == constant.GoogleDrive || newBackup.Type == constant.ALIYUN {
|
||||
if err := loadRefreshTokenByCode(&newBackup); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if backup.Type != constant.Local {
|
||||
isOk, err := u.checkBackupConn(&newBackup)
|
||||
if err != nil || !isOk {
|
||||
return buserr.WithMap("ErrBackupCheck", map[string]interface{}{"err": err.Error()}, err)
|
||||
}
|
||||
newBackup.AccessKey, err = encrypt.StringEncrypt(newBackup.AccessKey)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -514,37 +530,34 @@ func newClient(account *model.BackupAccount, isEncrypt bool) (cloud_storage.Clou
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func loadRefreshTokenByCode(backup *model.BackupAccount) error {
|
||||
func loadRefreshTokenByCode(backup *model.BackupAccount) (string, error) {
|
||||
varMap := make(map[string]interface{})
|
||||
if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil {
|
||||
return fmt.Errorf("unmarshal backup vars failed, err: %v", err)
|
||||
return "", fmt.Errorf("unmarshal backup vars failed, err: %v", err)
|
||||
}
|
||||
if _, ok := varMap["refresh_token"]; ok {
|
||||
return "", nil
|
||||
}
|
||||
refreshToken := ""
|
||||
var err error
|
||||
if backup.Type == constant.GoogleDrive {
|
||||
switch backup.Type {
|
||||
case constant.GoogleDrive:
|
||||
refreshToken, err = client.RefreshGoogleToken("authorization_code", "refreshToken", varMap)
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
if backup.Type == constant.OneDrive {
|
||||
case constant.OneDrive:
|
||||
refreshToken, err = client.RefreshToken("authorization_code", "refreshToken", varMap)
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
if backup.Type != constant.ALIYUN {
|
||||
delete(varMap, "code")
|
||||
varMap["refresh_token"] = refreshToken
|
||||
}
|
||||
varMap["refresh_status"] = constant.StatusSuccess
|
||||
varMap["refresh_time"] = time.Now().Format(constant.DateTimeLayout)
|
||||
itemVars, err := json.Marshal(varMap)
|
||||
if err != nil {
|
||||
return fmt.Errorf("json marshal var map failed, err: %v", err)
|
||||
}
|
||||
itemVars, _ := json.Marshal(varMap)
|
||||
backup.Vars = string(itemVars)
|
||||
return nil
|
||||
return refreshToken, nil
|
||||
}
|
||||
|
||||
func loadBackupNamesByID(accountIDs string, downloadID uint) ([]string, string, error) {
|
||||
|
||||
@@ -57,11 +57,11 @@ func (u *BackupService) MysqlRecover(req dto.CommonRecover) error {
|
||||
}
|
||||
|
||||
func (u *BackupService) MysqlRecoverByUpload(req dto.CommonRecover) error {
|
||||
recoveFile, err := loadSqlFile(req.File)
|
||||
recoverFile, err := loadSqlFile(req.File)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.File = recoveFile
|
||||
req.File = recoverFile
|
||||
|
||||
if err := handleMysqlRecover(req, nil, false); err != nil {
|
||||
return err
|
||||
@@ -193,7 +193,16 @@ func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback
|
||||
return recoverDatabase(parentTask)
|
||||
}
|
||||
|
||||
itemTask.AddSubTaskWithOps(i18n.GetMsgByKey("TaskRecover"), recoverDatabase, nil, 0, 3*time.Hour)
|
||||
var timeout time.Duration
|
||||
switch req.Timeout {
|
||||
case -1:
|
||||
timeout = 0
|
||||
case 0:
|
||||
timeout = 3 * time.Hour
|
||||
default:
|
||||
timeout = time.Duration(req.Timeout) * time.Second
|
||||
}
|
||||
itemTask.AddSubTaskWithOps(i18n.GetMsgByKey("TaskRecover"), recoverDatabase, nil, 0, timeout)
|
||||
go func() {
|
||||
_ = itemTask.Execute()
|
||||
}()
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/files"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/postgresql/client"
|
||||
pgclient "github.com/1Panel-dev/1Panel/agent/utils/postgresql/client"
|
||||
)
|
||||
|
||||
func (u *BackupService) PostgresqlBackup(req dto.CommonBackup) error {
|
||||
@@ -56,11 +55,11 @@ func (u *BackupService) PostgresqlRecover(req dto.CommonRecover) error {
|
||||
}
|
||||
|
||||
func (u *BackupService) PostgresqlRecoverByUpload(req dto.CommonRecover) error {
|
||||
recoveFile, err := loadSqlFile(req.File)
|
||||
recoverFile, err := loadSqlFile(req.File)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.File = recoveFile
|
||||
req.File = recoverFile
|
||||
if err := handlePostgresqlRecover(req, nil, false); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -82,7 +81,7 @@ func handlePostgresqlBackup(db DatabaseHelper, parentTask *task.Task, recordID u
|
||||
}
|
||||
}
|
||||
|
||||
itemHandler := func() error { return doPostgresqlgBackup(db, targetDir, fileName, secret, backupTask) }
|
||||
itemHandler := func() error { return doPostgresqlBackup(db, targetDir, fileName, secret, backupTask) }
|
||||
if parentTask != nil {
|
||||
return itemHandler()
|
||||
}
|
||||
@@ -188,20 +187,29 @@ func handlePostgresqlRecover(req dto.CommonRecover, parentTask *task.Task, isRol
|
||||
return recoverDatabase(parentTask)
|
||||
}
|
||||
|
||||
itemTask.AddSubTaskWithOps(i18n.GetMsgByKey("TaskRecover"), recoverDatabase, nil, 0, 3*time.Hour)
|
||||
var timeout time.Duration
|
||||
switch req.Timeout {
|
||||
case -1:
|
||||
timeout = 0
|
||||
case 0:
|
||||
timeout = 3 * time.Hour
|
||||
default:
|
||||
timeout = time.Duration(req.Timeout) * time.Second
|
||||
}
|
||||
itemTask.AddSubTaskWithOps(i18n.GetMsgByKey("TaskRecover"), recoverDatabase, nil, 0, timeout)
|
||||
go func() {
|
||||
_ = itemTask.Execute()
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func doPostgresqlgBackup(db DatabaseHelper, targetDir, fileName, secret string, task *task.Task) error {
|
||||
func doPostgresqlBackup(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{
|
||||
backupInfo := client.BackupInfo{
|
||||
Database: db.Database,
|
||||
Name: db.Name,
|
||||
TargetDir: targetDir,
|
||||
|
||||
@@ -131,7 +131,7 @@ func handleWebsiteRecover(website *model.Website, parentTask *task.Task, recover
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = fileOp.CopyFile(fmt.Sprintf("%s/%s.conf", tmpPath, website.Alias), GetOpenrestyDir(SiteConfDir)); err != nil {
|
||||
if err = fileOp.CopyFile(fmt.Sprintf("%s/%s.conf", tmpPath, website.Alias), GetConfDir(*website)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -259,7 +259,7 @@ func doWebsiteBackup(website *model.Website, parentTask *task.Task, backupDir, f
|
||||
if err := fileOp.SaveFile(tmpDir+"/website.json", string(remarkInfo), fs.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
nginxConfFile := GetSitePath(*website, SiteConf)
|
||||
nginxConfFile := GetWebsiteConfigPath(*website)
|
||||
if err := fileOp.CopyFile(nginxConfFile, tmpDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -19,12 +19,8 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"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"
|
||||
@@ -45,7 +41,9 @@ import (
|
||||
"github.com/docker/docker/api/types/volume"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/go-connections/nat"
|
||||
"github.com/gin-gonic/gin"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/shirou/gopsutil/v4/cpu"
|
||||
"github.com/shirou/gopsutil/v4/mem"
|
||||
)
|
||||
@@ -362,6 +360,9 @@ func (u *ContainerService) Inspect(req dto.InspectReq) (string, error) {
|
||||
}
|
||||
for _, container := range containers {
|
||||
config := container.Labels[composeConfigLabel]
|
||||
if len(req.Detail) != 0 && strings.Contains(config, req.Detail) {
|
||||
config = req.Detail
|
||||
}
|
||||
workdir := container.Labels[composeWorkdirLabel]
|
||||
if len(config) != 0 && len(workdir) != 0 && strings.Contains(config, workdir) {
|
||||
filePath = config
|
||||
@@ -969,12 +970,18 @@ func collectLogs(done <-chan struct{}, params dto.StreamLog, messageChan chan<-
|
||||
|
||||
var dockerCmd *exec.Cmd
|
||||
if params.Type == "compose" {
|
||||
dockerComposCmd := common.GetDockerComposeCommand()
|
||||
if dockerComposCmd == "docker-compose" {
|
||||
newCmdArgs := append([]string{"-f", params.Compose}, cmdArgs...)
|
||||
dockerCmd = exec.Command(dockerComposCmd, newCmdArgs...)
|
||||
dockerComposeCmd := common.GetDockerComposeCommand()
|
||||
var yamlFiles []string
|
||||
for _, item := range strings.Split(params.Compose, ",") {
|
||||
if len(item) != 0 {
|
||||
yamlFiles = append(yamlFiles, "-f", item)
|
||||
}
|
||||
}
|
||||
if dockerComposeCmd == "docker-compose" {
|
||||
newCmdArgs := append(yamlFiles, cmdArgs...)
|
||||
dockerCmd = exec.Command(dockerComposeCmd, newCmdArgs...)
|
||||
} else {
|
||||
newCmdArgs := append([]string{"compose", "-f", params.Compose}, cmdArgs...)
|
||||
newCmdArgs := append(append([]string{"compose"}, yamlFiles...), cmdArgs...)
|
||||
dockerCmd = exec.Command("docker", newCmdArgs...)
|
||||
}
|
||||
} else {
|
||||
@@ -1054,10 +1061,16 @@ func (u *ContainerService) DownloadContainerLogs(containerType, container, since
|
||||
commandArg := []string{"logs", container}
|
||||
dockerCommand := global.CONF.DockerConfig.Command
|
||||
if containerType == "compose" {
|
||||
var yamlFiles []string
|
||||
for _, item := range strings.Split(container, ",") {
|
||||
if len(item) != 0 {
|
||||
yamlFiles = append(yamlFiles, "-f", item)
|
||||
}
|
||||
}
|
||||
if dockerCommand == "docker-compose" {
|
||||
commandArg = []string{"-f", container, "logs"}
|
||||
commandArg = append(yamlFiles, "logs")
|
||||
} else {
|
||||
commandArg = []string{"compose", "-f", container, "logs"}
|
||||
commandArg = append(append([]string{"compose"}, yamlFiles...), "logs")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1144,10 +1157,8 @@ func (u *ContainerService) ContainerStats(id string) (*dto.ContainerStats, error
|
||||
|
||||
body, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
res.Body.Close()
|
||||
return nil, err
|
||||
}
|
||||
res.Body.Close()
|
||||
var stats *container.StatsResponse
|
||||
if err := json.Unmarshal(body, &stats); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -2,6 +2,7 @@ package service
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
@@ -24,7 +25,6 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/docker"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
const composeProjectLabel = "com.docker.compose.project"
|
||||
@@ -74,6 +74,7 @@ func (u *ContainerService) PageCompose(req dto.SearchWithPage) (int64, interface
|
||||
Name: container.Names[0][1:],
|
||||
State: container.State,
|
||||
CreateTime: time.Unix(container.Created, 0).Format(constant.DateTimeLayout),
|
||||
Ports: transPortToStr(container.Ports),
|
||||
}
|
||||
if compose, has := composeMap[name]; has {
|
||||
compose.ContainerCount++
|
||||
@@ -180,7 +181,7 @@ func (u *ContainerService) TestCompose(req dto.ComposeCreate) (bool, error) {
|
||||
cmd := getComposeCmd(req.Path, "config")
|
||||
stdout, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return false, errors.New(string(stdout))
|
||||
return false, fmt.Errorf("docker-compose config failed, std: %s, err: %v", string(stdout), err)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
@@ -232,24 +233,24 @@ func (u *ContainerService) ComposeOperation(req dto.ComposeOperation) error {
|
||||
return err
|
||||
}
|
||||
if req.WithFile {
|
||||
_ = os.RemoveAll(path.Dir(req.Path))
|
||||
for _, item := range strings.Split(req.Path, ",") {
|
||||
if len(item) != 0 {
|
||||
_ = os.RemoveAll(path.Dir(item))
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = composeRepo.DeleteRecord(repo.WithByName(req.Name))
|
||||
return nil
|
||||
}
|
||||
if _, err := os.Stat(req.Path); err != nil {
|
||||
return fmt.Errorf("load file with path %s failed, %v", req.Path, err)
|
||||
}
|
||||
if req.Operation == "up" {
|
||||
if stdout, err := compose.Up(req.Path); err != nil {
|
||||
return errors.New(string(stdout))
|
||||
return fmt.Errorf("docker-compose up failed, std: %s, err: %v", stdout, err)
|
||||
}
|
||||
} else {
|
||||
if stdout, err := compose.Operate(req.Path, req.Operation); err != nil {
|
||||
return errors.New(string(stdout))
|
||||
return fmt.Errorf("docker-compose %s failed, std: %s, err: %v", req.Operation, stdout, err)
|
||||
}
|
||||
}
|
||||
global.LOG.Infof("docker-compose %s %s successful", req.Operation, req.Name)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -257,11 +258,11 @@ func (u *ContainerService) ComposeUpdate(req dto.ComposeUpdate) error {
|
||||
if cmd.CheckIllegal(req.Name, req.Path) {
|
||||
return buserr.New("ErrCmdIllegal")
|
||||
}
|
||||
oldFile, err := os.ReadFile(req.Path)
|
||||
oldFile, err := os.ReadFile(req.DetailPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("load file with path %s failed, %v", req.Path, err)
|
||||
return fmt.Errorf("load file with path %s failed, %v", req.DetailPath, err)
|
||||
}
|
||||
file, err := os.OpenFile(req.Path, os.O_WRONLY|os.O_TRUNC, 0640)
|
||||
file, err := os.OpenFile(req.DetailPath, os.O_WRONLY|os.O_TRUNC, 0640)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -270,16 +271,17 @@ func (u *ContainerService) ComposeUpdate(req dto.ComposeUpdate) error {
|
||||
_, _ = write.WriteString(req.Content)
|
||||
write.Flush()
|
||||
|
||||
global.LOG.Infof("docker-compose.yml %s has been replaced, now start to docker-compose restart", req.Path)
|
||||
if err := newComposeEnv(req.Path, req.Env); err != nil {
|
||||
global.LOG.Infof("docker-compose.yml %s has been replaced, now start to docker-compose restart", req.DetailPath)
|
||||
if err := newComposeEnv(req.DetailPath, req.Env); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if stdout, err := compose.Up(req.Path); err != nil {
|
||||
global.LOG.Errorf("update failed when handle compose up, std: %s, err: %s, now try to recreate the old compose file", stdout, err)
|
||||
if err := recreateCompose(string(oldFile), req.Path); err != nil {
|
||||
return fmt.Errorf("update failed when handle compose up, err: %s, recreate failed: %v", string(stdout), err)
|
||||
return fmt.Errorf("update failed and recreate old compose file also failed, err: %v", err)
|
||||
}
|
||||
return fmt.Errorf("update failed when handle compose up, err: %s", string(stdout))
|
||||
return fmt.Errorf("update failed when handle compose up, std: %v, err: %s", stdout, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -360,11 +362,8 @@ func (u *ContainerService) loadPath(req *dto.ComposeCreate) error {
|
||||
}
|
||||
|
||||
func removeContainerForCompose(composeName, composePath string) error {
|
||||
if _, err := os.Stat(composePath); err == nil {
|
||||
if stdout, err := compose.Operate(composePath, "down"); err != nil {
|
||||
return errors.New(stdout)
|
||||
}
|
||||
return nil
|
||||
if stdout, err := compose.Operate(composePath, "down"); err != nil {
|
||||
return errors.New(stdout)
|
||||
}
|
||||
var options container.ListOptions
|
||||
options.All = true
|
||||
@@ -404,40 +403,31 @@ func recreateCompose(content, path string) error {
|
||||
|
||||
func loadEnv(list []dto.ComposeInfo) []dto.ComposeInfo {
|
||||
for i := 0; i < len(list); i++ {
|
||||
envFilePath := path.Join(path.Dir(list[i].Path), "1panel.env")
|
||||
tmpPath := list[i].Path
|
||||
if strings.Contains(list[i].Path, ",") {
|
||||
tmpPath = strings.Split(list[i].Path, ",")[0]
|
||||
}
|
||||
envFilePath := path.Join(path.Dir(tmpPath), ".env")
|
||||
file, err := os.ReadFile(envFilePath)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
lines := strings.Split(string(file), "\n")
|
||||
for _, line := range lines {
|
||||
lineItem := strings.TrimSpace(line)
|
||||
if len(lineItem) != 0 && !strings.HasPrefix(lineItem, "#") {
|
||||
list[i].Env = append(list[i].Env, lineItem)
|
||||
}
|
||||
}
|
||||
list[i].Env = string(file)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func newComposeEnv(pathItem string, env []string) error {
|
||||
if len(env) == 0 {
|
||||
return nil
|
||||
}
|
||||
envFilePath := path.Join(path.Dir(pathItem), "1panel.env")
|
||||
func newComposeEnv(pathItem string, env string) error {
|
||||
envFilePath := path.Join(path.Dir(pathItem), ".env")
|
||||
file, err := os.OpenFile(envFilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, constant.FilePerm)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("failed to create env file: %v", err)
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
for _, env := range env {
|
||||
envItem := strings.TrimSpace(env)
|
||||
if _, err := file.WriteString(fmt.Sprintf("%s\n", envItem)); err != nil {
|
||||
global.LOG.Errorf("failed to write env to file: %v", err)
|
||||
return err
|
||||
}
|
||||
if _, err := file.WriteString(env); err != nil {
|
||||
global.LOG.Errorf("failed to write env to file: %v", err)
|
||||
return err
|
||||
}
|
||||
global.LOG.Infof("1panel.env file successfully created or updated with env variables in %s", envFilePath)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -447,7 +447,7 @@ func (u *CronjobService) SearchRecords(search dto.SearchRecord) (int64, interfac
|
||||
func (u *CronjobService) LoadNextHandle(specStr string) ([]string, error) {
|
||||
spec := cron.NewParser(cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow)
|
||||
now := time.Now()
|
||||
var nexts [5]string
|
||||
var next [5]string
|
||||
if strings.HasPrefix(specStr, "@every ") {
|
||||
duration := time.Minute
|
||||
if strings.HasSuffix(specStr, "s") {
|
||||
@@ -462,10 +462,10 @@ func (u *CronjobService) LoadNextHandle(specStr string) ([]string, error) {
|
||||
}
|
||||
for i := 0; i < 5; i++ {
|
||||
nextTime := now.Add(time.Duration(durationItem) * duration)
|
||||
nexts[i] = nextTime.Format(constant.DateTimeLayout)
|
||||
next[i] = nextTime.Format(constant.DateTimeLayout)
|
||||
now = nextTime
|
||||
}
|
||||
return nexts[:], nil
|
||||
return next[:], nil
|
||||
}
|
||||
sched, err := spec.Parse(specStr)
|
||||
if err != nil {
|
||||
@@ -473,10 +473,10 @@ func (u *CronjobService) LoadNextHandle(specStr string) ([]string, error) {
|
||||
}
|
||||
for i := 0; i < 5; i++ {
|
||||
nextTime := sched.Next(now)
|
||||
nexts[i] = nextTime.Format(constant.DateTimeLayout)
|
||||
next[i] = nextTime.Format(constant.DateTimeLayout)
|
||||
now = nextTime
|
||||
}
|
||||
return nexts[:], nil
|
||||
return next[:], nil
|
||||
}
|
||||
|
||||
func (u *CronjobService) LoadRecordLog(req dto.OperateByID) string {
|
||||
@@ -633,8 +633,8 @@ func (u *CronjobService) HandleStop(id uint) error {
|
||||
if len(record.TaskID) == 0 {
|
||||
return nil
|
||||
}
|
||||
if cancle, ok := global.TaskCtxMap[record.TaskID]; ok {
|
||||
cancle()
|
||||
if cancel, ok := global.TaskCtxMap[record.TaskID]; ok {
|
||||
cancel()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Ti
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if err := doPostgresqlgBackup(dbInfo, backupDir, record.FileName, cronjob.Secret, taskItem); err != nil {
|
||||
if err := doPostgresqlBackup(dbInfo, backupDir, record.FileName, cronjob.Secret, taskItem); err != nil {
|
||||
if retry < int(cronjob.RetryTimes) || !cronjob.IgnoreErr {
|
||||
retry++
|
||||
return err
|
||||
@@ -440,10 +440,10 @@ func loadDbsForJob(cronjob model.Cronjob) []DatabaseHelper {
|
||||
}
|
||||
|
||||
func loadWebsForJob(cronjob model.Cronjob) []model.Website {
|
||||
var weblist []model.Website
|
||||
var list []model.Website
|
||||
if cronjob.Website == "all" {
|
||||
weblist, _ = websiteRepo.List()
|
||||
return weblist
|
||||
list, _ = websiteRepo.List()
|
||||
return list
|
||||
}
|
||||
websites := strings.Split(cronjob.Website, ",")
|
||||
var idItems []uint
|
||||
@@ -451,8 +451,8 @@ func loadWebsForJob(cronjob model.Cronjob) []model.Website {
|
||||
itemID, _ := strconv.Atoi(websites[i])
|
||||
idItems = append(idItems, uint(itemID))
|
||||
}
|
||||
weblist, _ = websiteRepo.GetBy(repo.WithByIDs(idItems))
|
||||
return weblist
|
||||
list, _ = websiteRepo.GetBy(repo.WithByIDs(idItems))
|
||||
return list
|
||||
}
|
||||
|
||||
func handleBackupLogs(taskItem *task.Task, targetDir, fileName string, secret string) error {
|
||||
|
||||
@@ -64,7 +64,7 @@ func (u *CronjobService) HandleJob(cronjob *model.Cronjob) {
|
||||
return
|
||||
}
|
||||
if err = u.loadTask(cronjob, &record, taskItem); err != nil {
|
||||
global.LOG.Debugf("preper to handle cron job [%s] %s failed, err: %v", cronjob.Type, cronjob.Name, err)
|
||||
global.LOG.Debugf("prepare to handle cron job [%s] %s failed, err: %v", cronjob.Type, cronjob.Name, err)
|
||||
item, _ := taskRepo.GetFirst(taskRepo.WithByID(record.TaskID))
|
||||
if len(item.ID) == 0 {
|
||||
record.TaskID = ""
|
||||
@@ -275,6 +275,10 @@ func (u *CronjobService) handleSyncIpGroup(cronjob model.Cronjob, taskItem *task
|
||||
}
|
||||
ipGroupDir := pathUtils.Join(appInstall.GetPath(), "1pwaf", "data", "rules", "ip_group")
|
||||
urlDir := pathUtils.Join(ipGroupDir, "ip_group_url")
|
||||
_, err = os.Stat(urlDir)
|
||||
if err != nil && os.IsNotExist(err) {
|
||||
return buserr.New("WafIpGroupNotFound")
|
||||
}
|
||||
|
||||
urlsFiles, err := os.ReadDir(urlDir)
|
||||
if err != nil {
|
||||
|
||||
@@ -285,7 +285,7 @@ func (u *DashboardService) LoadAppLauncher(ctx *gin.Context) ([]dto.AppLauncher,
|
||||
}
|
||||
|
||||
showList, err := launcherRepo.ListName()
|
||||
defaultList, err := appRepo.GetTopRecomment()
|
||||
defaultList, err := appRepo.GetTopRecommend()
|
||||
if err != nil {
|
||||
return data, nil
|
||||
}
|
||||
|
||||
+493
-124
@@ -11,36 +11,27 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/i18n"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/controller"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/docker"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/build"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
|
||||
"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/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/docker"
|
||||
fileUtils "github.com/1Panel-dev/1Panel/agent/utils/files"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/build"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const (
|
||||
upgradePath = "1panel/tmp/upgrade"
|
||||
snapshotTmpPath = "1panel/tmp/system"
|
||||
rollbackPath = "1panel/tmp"
|
||||
cachePath = "1panel/cache"
|
||||
oldOriginalPath = "original"
|
||||
oldAppBackupPath = "1panel/resource/apps_bak"
|
||||
oldDownloadPath = "1panel/tmp/download"
|
||||
oldUpgradePath = "1panel/tmp"
|
||||
tmpUploadPath = "1panel/tmp/upload"
|
||||
uploadPath = "1panel/uploads"
|
||||
downloadPath = "1panel/download"
|
||||
rollbackPath = "1panel/tmp"
|
||||
upgradePath = "1panel/tmp/upgrade"
|
||||
uploadPath = "1panel/uploads"
|
||||
downloadPath = "1panel/download"
|
||||
)
|
||||
|
||||
func (u *DeviceService) Scan() dto.CleanData {
|
||||
@@ -61,54 +52,10 @@ func (u *DeviceService) Scan() dto.CleanData {
|
||||
Type: "1panel_original",
|
||||
Children: loadTreeWithDir(true, "1panel_original", originalPath, fileOp),
|
||||
})
|
||||
treeData = append(treeData, loadUpgradeTree(fileOp))
|
||||
treeData = append(treeData, loadAgentPackage(fileOp))
|
||||
|
||||
upgradePath := path.Join(global.Dir.BaseDir, upgradePath)
|
||||
upgradeSize, _ := fileOp.GetDirSize(upgradePath)
|
||||
upgradeTree := dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "upgrade",
|
||||
Size: uint64(upgradeSize),
|
||||
IsCheck: false,
|
||||
IsRecommend: true,
|
||||
Type: "upgrade",
|
||||
Children: loadTreeWithDir(true, "upgrade", upgradePath, fileOp),
|
||||
}
|
||||
if len(upgradeTree.Children) != 0 {
|
||||
sort.Slice(upgradeTree.Children, func(i, j int) bool {
|
||||
return common.CompareVersion(upgradeTree.Children[i].Label, upgradeTree.Children[j].Label)
|
||||
})
|
||||
if global.IsMaster {
|
||||
var copiesSeeting model.Setting
|
||||
_ = global.CoreDB.Where("key = ?", "UpgradeBackupCopies").First(&copiesSeeting).Error
|
||||
copies, _ := strconv.Atoi(copiesSeeting.Value)
|
||||
if copies == 0 || copies > len(upgradeTree.Children) {
|
||||
copies = len(upgradeTree.Children)
|
||||
}
|
||||
for i := 0; i < copies; i++ {
|
||||
upgradeTree.Children[i].IsCheck = false
|
||||
upgradeTree.Children[i].IsRecommend = false
|
||||
}
|
||||
} else {
|
||||
upgradeTree.Children[0].IsCheck = false
|
||||
upgradeTree.Children[0].IsRecommend = false
|
||||
}
|
||||
}
|
||||
treeData = append(treeData, upgradeTree)
|
||||
|
||||
tmpBackupTree := loadTmpBackupTree(fileOp)
|
||||
tmpBackupSize := uint64(0)
|
||||
for _, tmp := range tmpBackupTree {
|
||||
tmpBackupSize += tmp.Size
|
||||
}
|
||||
treeData = append(treeData, dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "backup",
|
||||
Size: tmpBackupSize,
|
||||
IsCheck: tmpBackupSize > 0,
|
||||
IsRecommend: true,
|
||||
Type: "backup",
|
||||
Children: tmpBackupTree,
|
||||
})
|
||||
SystemClean.BackupClean = loadBackupTree(fileOp)
|
||||
|
||||
rollBackTree := loadRollBackTree(fileOp)
|
||||
rollbackSize := uint64(0)
|
||||
@@ -124,17 +71,6 @@ func (u *DeviceService) Scan() dto.CleanData {
|
||||
Type: "rollback",
|
||||
Children: rollBackTree,
|
||||
})
|
||||
|
||||
cachePath := path.Join(global.Dir.BaseDir, cachePath)
|
||||
cacheSize, _ := fileOp.GetDirSize(cachePath)
|
||||
treeData = append(treeData, dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "cache",
|
||||
Size: uint64(cacheSize),
|
||||
IsCheck: false,
|
||||
IsRecommend: false,
|
||||
Type: "cache",
|
||||
})
|
||||
SystemClean.SystemClean = treeData
|
||||
|
||||
uploadTreeData := loadUploadTree(fileOp)
|
||||
@@ -154,7 +90,6 @@ func (u *DeviceService) Scan() dto.CleanData {
|
||||
|
||||
func (u *DeviceService) Clean(req []dto.Clean) {
|
||||
size := uint64(0)
|
||||
restart := false
|
||||
for _, item := range req {
|
||||
size += item.Size
|
||||
switch item.TreeType {
|
||||
@@ -164,13 +99,13 @@ func (u *DeviceService) Clean(req []dto.Clean) {
|
||||
case "upgrade":
|
||||
dropFileOrDir(path.Join(global.Dir.BaseDir, upgradePath, item.Name))
|
||||
|
||||
case "backup":
|
||||
dropFileOrDir(path.Join(global.Dir.LocalBackupDir, "tmp/app"))
|
||||
dropFileOrDir(path.Join(global.Dir.LocalBackupDir, "tmp/database"))
|
||||
dropFileOrDir(path.Join(global.Dir.LocalBackupDir, "tmp/website"))
|
||||
dropFileOrDir(path.Join(global.Dir.LocalBackupDir, "tmp/directory"))
|
||||
dropFileOrDir(path.Join(global.Dir.LocalBackupDir, "tmp/log"))
|
||||
dropFileOrDir(path.Join(global.Dir.LocalBackupDir, "tmp/system"))
|
||||
case "agent":
|
||||
dropFileOrDir(path.Join(global.Dir.BaseDir, "1panel/agent/package", item.Name))
|
||||
|
||||
case "tmp_backup":
|
||||
dropFileOrDir(path.Join(global.Dir.LocalBackupDir, "tmp"))
|
||||
case "unknown_backup":
|
||||
dropFileOrDir(item.Name)
|
||||
|
||||
case "rollback":
|
||||
dropFileOrDir(path.Join(global.Dir.BaseDir, rollbackPath, "app"))
|
||||
@@ -183,25 +118,14 @@ func (u *DeviceService) Clean(req []dto.Clean) {
|
||||
case "rollback_website":
|
||||
dropFileOrDir(path.Join(global.Dir.BaseDir, rollbackPath, "website", item.Name))
|
||||
|
||||
case "cache":
|
||||
dropFileOrDir(path.Join(global.Dir.BaseDir, cachePath, item.Name))
|
||||
restart = true
|
||||
|
||||
case "upload":
|
||||
dropFileOrDir(path.Join(global.Dir.BaseDir, uploadPath, item.Name))
|
||||
if len(item.Name) == 0 {
|
||||
dropFileOrDir(path.Join(global.Dir.BaseDir, tmpUploadPath))
|
||||
}
|
||||
case "upload_tmp":
|
||||
dropFileOrDir(path.Join(global.Dir.BaseDir, tmpUploadPath, item.Name))
|
||||
case "upload_app":
|
||||
dropFileOrDir(path.Join(global.Dir.BaseDir, uploadPath, "app", item.Name))
|
||||
case "upload_database":
|
||||
dropFileOrDir(path.Join(global.Dir.BaseDir, uploadPath, "database", item.Name))
|
||||
case "upload_website":
|
||||
dropFileOrDir(path.Join(global.Dir.BaseDir, uploadPath, "website", item.Name))
|
||||
case "upload_directory":
|
||||
dropFileOrDir(path.Join(global.Dir.BaseDir, uploadPath, "directory", item.Name))
|
||||
case "download":
|
||||
dropFileOrDir(path.Join(global.Dir.BaseDir, downloadPath, item.Name))
|
||||
case "download_app":
|
||||
@@ -210,8 +134,6 @@ func (u *DeviceService) Clean(req []dto.Clean) {
|
||||
dropFileOrDir(path.Join(global.Dir.BaseDir, downloadPath, "database", item.Name))
|
||||
case "download_website":
|
||||
dropFileOrDir(path.Join(global.Dir.BaseDir, downloadPath, "website", item.Name))
|
||||
case "download_directory":
|
||||
dropFileOrDir(path.Join(global.Dir.BaseDir, downloadPath, "directory", item.Name))
|
||||
|
||||
case "system_log":
|
||||
if len(item.Name) == 0 {
|
||||
@@ -243,6 +165,8 @@ func (u *DeviceService) Clean(req []dto.Clean) {
|
||||
} else {
|
||||
dropTaskLog(path.Join(global.Dir.TaskDir, item.Name))
|
||||
}
|
||||
case "website_log":
|
||||
dropWebsiteLog(item.Name)
|
||||
case "script":
|
||||
dropFileOrDir(path.Join(global.Dir.TmpDir, "script", item.Name))
|
||||
case "images":
|
||||
@@ -253,16 +177,14 @@ func (u *DeviceService) Clean(req []dto.Clean) {
|
||||
_, _ = dropVolumes()
|
||||
case "build_cache":
|
||||
_, _ = dropBuildCache()
|
||||
case "app_tmp_download_version":
|
||||
dropFileOrDir(path.Join(global.Dir.RemoteAppResourceDir, item.Name))
|
||||
}
|
||||
}
|
||||
|
||||
_ = settingRepo.Update("LastCleanTime", time.Now().Format(constant.DateTimeLayout))
|
||||
_ = settingRepo.Update("LastCleanSize", fmt.Sprintf("%v", size))
|
||||
_ = settingRepo.Update("LastCleanData", fmt.Sprintf("%v", len(req)))
|
||||
|
||||
if restart {
|
||||
go controller.RestartPanel(false, true, false)
|
||||
}
|
||||
}
|
||||
|
||||
func doSystemClean(taskItem *task.Task) func(t *task.Task) error {
|
||||
@@ -284,25 +206,20 @@ func doSystemClean(taskItem *task.Task) func(t *task.Task) error {
|
||||
}
|
||||
}
|
||||
|
||||
dropWithTask(path.Join(global.Dir.BaseDir, snapshotTmpPath), taskItem, &size, &fileCount)
|
||||
dropWithTask(path.Join(global.Dir.LocalBackupDir, "tmp/system"), taskItem, &size, &fileCount)
|
||||
|
||||
dropWithTask(path.Join(global.Dir.BaseDir, rollbackPath, "app"), taskItem, &size, &fileCount)
|
||||
dropWithTask(path.Join(global.Dir.BaseDir, rollbackPath, "website"), taskItem, &size, &fileCount)
|
||||
dropWithTask(path.Join(global.Dir.BaseDir, rollbackPath, "database"), taskItem, &size, &fileCount)
|
||||
|
||||
dropWithTask(path.Join(global.Dir.BaseDir, oldOriginalPath), taskItem, &size, &fileCount)
|
||||
dropWithTask(path.Join(global.Dir.BaseDir, oldAppBackupPath), taskItem, &size, &fileCount)
|
||||
dropWithTask(path.Join(global.Dir.BaseDir, oldDownloadPath), taskItem, &size, &fileCount)
|
||||
oldUpgradePath := path.Join(global.Dir.BaseDir, oldUpgradePath)
|
||||
oldUpgradeFiles, _ := os.ReadDir(oldUpgradePath)
|
||||
upgrades := path.Join(global.Dir.BaseDir, upgradePath)
|
||||
oldUpgradeFiles, _ := os.ReadDir(upgrades)
|
||||
if len(oldUpgradeFiles) != 0 {
|
||||
for i := 0; i < len(oldUpgradeFiles); i++ {
|
||||
dropWithTask(path.Join(oldUpgradePath, oldUpgradeFiles[i].Name()), taskItem, &size, &fileCount)
|
||||
dropWithTask(path.Join(upgrades, oldUpgradeFiles[i].Name()), taskItem, &size, &fileCount)
|
||||
}
|
||||
}
|
||||
|
||||
dropWithTask(path.Join(global.Dir.BaseDir, tmpUploadPath), taskItem, &size, &fileCount)
|
||||
dropWithExclude(path.Join(global.Dir.BaseDir, uploadPath), []string{"theme"}, taskItem, &size, &fileCount)
|
||||
dropWithTask(path.Join(global.Dir.BaseDir, downloadPath), taskItem, &size, &fileCount)
|
||||
|
||||
@@ -338,17 +255,356 @@ func doSystemClean(taskItem *task.Task) func(t *task.Task) error {
|
||||
}
|
||||
}
|
||||
|
||||
func loadTmpBackupTree(fileOp fileUtils.FileOp) []dto.CleanTree {
|
||||
func loadUpgradeTree(fileOp fileUtils.FileOp) dto.CleanTree {
|
||||
upgradePath := path.Join(global.Dir.BaseDir, upgradePath)
|
||||
upgradeSize, _ := fileOp.GetDirSize(upgradePath)
|
||||
upgradeTree := dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "upgrade",
|
||||
Size: uint64(upgradeSize),
|
||||
IsCheck: false,
|
||||
IsRecommend: true,
|
||||
Type: "upgrade",
|
||||
Children: loadTreeWithDir(true, "upgrade", upgradePath, fileOp),
|
||||
}
|
||||
if len(upgradeTree.Children) != 0 {
|
||||
sort.Slice(upgradeTree.Children, func(i, j int) bool {
|
||||
return common.CompareVersion(upgradeTree.Children[i].Label, upgradeTree.Children[j].Label)
|
||||
})
|
||||
if global.IsMaster {
|
||||
var copiesSetting model.Setting
|
||||
_ = global.CoreDB.Where("key = ?", "UpgradeBackupCopies").First(&copiesSetting).Error
|
||||
copies, _ := strconv.Atoi(copiesSetting.Value)
|
||||
if copies == 0 || copies > len(upgradeTree.Children) {
|
||||
copies = len(upgradeTree.Children)
|
||||
}
|
||||
for i := 0; i < copies; i++ {
|
||||
upgradeTree.Children[i].IsCheck = false
|
||||
upgradeTree.Children[i].IsRecommend = false
|
||||
}
|
||||
} else {
|
||||
upgradeTree.Children[0].IsCheck = false
|
||||
upgradeTree.Children[0].IsRecommend = false
|
||||
}
|
||||
}
|
||||
return upgradeTree
|
||||
}
|
||||
|
||||
func loadAgentPackage(fileOp fileUtils.FileOp) dto.CleanTree {
|
||||
pathItem := path.Join(global.Dir.BaseDir, "1panel/agent/package")
|
||||
itemTree := dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "agent_packages",
|
||||
IsCheck: true,
|
||||
IsRecommend: true,
|
||||
Type: "agent",
|
||||
}
|
||||
files, _ := os.ReadDir(pathItem)
|
||||
for _, file := range files {
|
||||
if file.IsDir() {
|
||||
itemSize, _ := fileOp.GetDirSize(path.Join(pathItem, file.Name()))
|
||||
itemTree.Size += uint64(itemSize)
|
||||
itemTree.Children = append(itemTree.Children, dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: file.Name(),
|
||||
Name: file.Name(),
|
||||
Size: uint64(itemSize),
|
||||
IsCheck: true,
|
||||
IsRecommend: true,
|
||||
Type: "agent",
|
||||
})
|
||||
} else {
|
||||
if strings.HasPrefix(file.Name(), fmt.Sprintf("1panel-agent_%s_a", global.CONF.Base.Version)) {
|
||||
continue
|
||||
}
|
||||
itemSize, _ := file.Info()
|
||||
itemTree.Size += uint64(itemSize.Size())
|
||||
itemTree.Children = append(itemTree.Children, dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: file.Name(),
|
||||
Name: file.Name(),
|
||||
Size: uint64(itemSize.Size()),
|
||||
IsCheck: true,
|
||||
IsRecommend: true,
|
||||
Type: "agent",
|
||||
})
|
||||
}
|
||||
}
|
||||
if itemTree.Size == 0 {
|
||||
itemTree.IsCheck = false
|
||||
}
|
||||
return itemTree
|
||||
}
|
||||
|
||||
func loadBackupTree(fileOp fileUtils.FileOp) []dto.CleanTree {
|
||||
var treeData []dto.CleanTree
|
||||
treeData = loadTreeWithCheck(treeData, path.Join(global.Dir.LocalBackupDir, "tmp/app"), "tmp_backup_app", fileOp)
|
||||
treeData = loadTreeWithCheck(treeData, path.Join(global.Dir.LocalBackupDir, "tmp/website"), "tmp_backup_website", fileOp)
|
||||
treeData = loadTreeWithCheck(treeData, path.Join(global.Dir.LocalBackupDir, "tmp/database"), "tmp_backup_database", fileOp)
|
||||
treeData = loadTreeWithCheck(treeData, path.Join(global.Dir.LocalBackupDir, "tmp/system"), "tmp_backup_snapshot", fileOp)
|
||||
treeData = loadTreeWithCheck(treeData, path.Join(global.Dir.LocalBackupDir, "tmp/directory"), "tmp_backup_directory", fileOp)
|
||||
treeData = loadTreeWithCheck(treeData, path.Join(global.Dir.LocalBackupDir, "tmp/log"), "tmp_backup_log", fileOp)
|
||||
|
||||
tmpSize, _ := fileOp.GetDirSize(path.Join(global.Dir.LocalBackupDir, "tmp"))
|
||||
treeData = append(treeData, dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "tmp_backup",
|
||||
Size: uint64(tmpSize),
|
||||
IsCheck: tmpSize != 0,
|
||||
IsRecommend: true,
|
||||
Type: "tmp_backup",
|
||||
})
|
||||
backupRecords, _ := backupRepo.ListRecord()
|
||||
var recordMap = make(map[string][]string)
|
||||
for _, record := range backupRecords {
|
||||
if val, ok := recordMap[record.FileDir]; ok {
|
||||
val = append(val, record.FileName)
|
||||
recordMap[record.FileDir] = val
|
||||
} else {
|
||||
recordMap[record.FileDir] = []string{record.FileName}
|
||||
}
|
||||
}
|
||||
|
||||
treeData = append(treeData, loadUnknownApps(fileOp, recordMap))
|
||||
treeData = append(treeData, loadUnknownDbs(fileOp, recordMap))
|
||||
treeData = append(treeData, loadUnknownWebsites(fileOp, recordMap))
|
||||
treeData = append(treeData, loadUnknownSnapshot(fileOp))
|
||||
treeData = append(treeData, loadUnknownWebsiteLog(fileOp, recordMap))
|
||||
return treeData
|
||||
}
|
||||
|
||||
func loadUnknownApps(fileOp fileUtils.FileOp, recordMap map[string][]string) dto.CleanTree {
|
||||
apps, _ := appInstallRepo.ListBy(context.Background())
|
||||
var excludePaths []string
|
||||
for _, app := range apps {
|
||||
itemName := fmt.Sprintf("app/%s/%s", app.App.Key, app.Name)
|
||||
if val, ok := recordMap[itemName]; ok {
|
||||
for _, item := range val {
|
||||
excludePaths = append(excludePaths, path.Join(global.Dir.LocalBackupDir, itemName, item))
|
||||
}
|
||||
} else {
|
||||
excludePaths = append(excludePaths, path.Join(global.Dir.LocalBackupDir, itemName))
|
||||
}
|
||||
}
|
||||
treeData := dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "unknown_app",
|
||||
IsCheck: false,
|
||||
IsRecommend: false,
|
||||
Type: "unknown_backup",
|
||||
}
|
||||
_ = loadFileOrDirWithExclude(fileOp, 0, path.Join(global.Dir.LocalBackupDir, "app"), &treeData, excludePaths)
|
||||
loadBackupIsCheck(&treeData)
|
||||
return treeData
|
||||
}
|
||||
func loadUnknownDbs(fileOp fileUtils.FileOp, recordMap map[string][]string) dto.CleanTree {
|
||||
apps, _ := appInstallRepo.ListBy(context.Background())
|
||||
var excludePaths []string
|
||||
appMap := make(map[string]struct{})
|
||||
for _, app := range apps {
|
||||
appMap[fmt.Sprintf("database/%s/%s", app.App.Key, app.Name)] = struct{}{}
|
||||
}
|
||||
for key, val := range recordMap {
|
||||
itemName := path.Dir(key)
|
||||
if _, ok := appMap[itemName]; ok {
|
||||
for _, item := range val {
|
||||
excludePaths = append(excludePaths, path.Join(global.Dir.LocalBackupDir, key, item))
|
||||
}
|
||||
}
|
||||
}
|
||||
treeData := dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "unknown_database",
|
||||
IsCheck: false,
|
||||
IsRecommend: false,
|
||||
Type: "unknown_backup",
|
||||
}
|
||||
_ = loadFileOrDirWithExclude(fileOp, 0, path.Join(global.Dir.LocalBackupDir, "database"), &treeData, excludePaths)
|
||||
|
||||
loadBackupIsCheck(&treeData)
|
||||
return treeData
|
||||
}
|
||||
func loadUnknownWebsites(fileOp fileUtils.FileOp, recordMap map[string][]string) dto.CleanTree {
|
||||
websites, _ := websiteRepo.List()
|
||||
var excludePaths []string
|
||||
for _, website := range websites {
|
||||
itemName := fmt.Sprintf("website/%s", website.PrimaryDomain)
|
||||
if val, ok := recordMap[itemName]; ok {
|
||||
for _, item := range val {
|
||||
excludePaths = append(excludePaths, path.Join(global.Dir.LocalBackupDir, itemName, item))
|
||||
}
|
||||
} else {
|
||||
excludePaths = append(excludePaths, path.Join(global.Dir.LocalBackupDir, itemName))
|
||||
}
|
||||
}
|
||||
treeData := dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "unknown_website",
|
||||
IsCheck: false,
|
||||
IsRecommend: false,
|
||||
Type: "unknown_backup",
|
||||
}
|
||||
_ = loadFileOrDirWithExclude(fileOp, 0, path.Join(global.Dir.LocalBackupDir, "website"), &treeData, excludePaths)
|
||||
loadBackupIsCheck(&treeData)
|
||||
return treeData
|
||||
}
|
||||
func loadUnknownSnapshot(fileOp fileUtils.FileOp) dto.CleanTree {
|
||||
snaps, _ := snapshotRepo.GetList()
|
||||
var excludePaths []string
|
||||
for _, item := range snaps {
|
||||
excludePaths = append(excludePaths, path.Join(global.Dir.LocalBackupDir, "system_snapshot", item.Name+".tar.gz"))
|
||||
}
|
||||
treeData := dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "unknown_snapshot",
|
||||
IsCheck: false,
|
||||
IsRecommend: false,
|
||||
Type: "unknown_backup",
|
||||
}
|
||||
dir := path.Join(global.Dir.LocalBackupDir, "system_snapshot")
|
||||
entries, _ := os.ReadDir(dir)
|
||||
for _, entry := range entries {
|
||||
childPath := filepath.Join(dir, entry.Name())
|
||||
if isExactPathMatch(childPath, excludePaths) {
|
||||
continue
|
||||
}
|
||||
|
||||
childNode := dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: entry.Name(),
|
||||
IsCheck: false,
|
||||
IsRecommend: false,
|
||||
Name: childPath,
|
||||
Type: "unknown_backup",
|
||||
}
|
||||
if entry.IsDir() {
|
||||
itemSize, _ := fileOp.GetDirSize(childPath)
|
||||
childNode.Size = uint64(itemSize)
|
||||
childNode.IsCheck = true
|
||||
childNode.IsRecommend = true
|
||||
treeData.Size += childNode.Size
|
||||
} else {
|
||||
info, _ := entry.Info()
|
||||
childNode.Size = uint64(info.Size())
|
||||
treeData.Size += childNode.Size
|
||||
}
|
||||
|
||||
treeData.Children = append(treeData.Children, childNode)
|
||||
}
|
||||
return treeData
|
||||
}
|
||||
|
||||
func loadUnknownWebsiteLog(fileOp fileUtils.FileOp, recordMap map[string][]string) dto.CleanTree {
|
||||
treeData := dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "unknown_website_log",
|
||||
IsCheck: false,
|
||||
IsRecommend: true,
|
||||
Type: "unknown_backup",
|
||||
}
|
||||
dir := path.Join(global.Dir.LocalBackupDir, "log/website")
|
||||
entries, _ := os.ReadDir(dir)
|
||||
for _, entry := range entries {
|
||||
if !entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
dirName := entry.Name()
|
||||
itemName := fmt.Sprintf("log/website/%s", dirName)
|
||||
if _, ok := recordMap[itemName]; !ok {
|
||||
dirPath := path.Join(dir, dirName)
|
||||
itemSize, _ := fileOp.GetDirSize(dirPath)
|
||||
childData := dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: dirName,
|
||||
IsCheck: true,
|
||||
IsRecommend: true,
|
||||
Name: dirPath,
|
||||
Type: "unknown_backup",
|
||||
Size: uint64(itemSize),
|
||||
}
|
||||
treeData.Size += uint64(itemSize)
|
||||
treeData.Children = append(treeData.Children, childData)
|
||||
}
|
||||
}
|
||||
if treeData.Size > 0 {
|
||||
treeData.IsCheck = true
|
||||
}
|
||||
return treeData
|
||||
}
|
||||
|
||||
func loadFileOrDirWithExclude(fileOp fileUtils.FileOp, index uint, dir string, rootTree *dto.CleanTree, excludes []string) error {
|
||||
index++
|
||||
entries, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, entry := range entries {
|
||||
childPath := filepath.Join(dir, entry.Name())
|
||||
if isExactPathMatch(childPath, excludes) {
|
||||
continue
|
||||
}
|
||||
|
||||
childNode := dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: entry.Name(),
|
||||
IsCheck: false,
|
||||
IsRecommend: false,
|
||||
Name: childPath,
|
||||
Type: "unknown_backup",
|
||||
}
|
||||
if entry.IsDir() {
|
||||
if index < 4 {
|
||||
if err = loadFileOrDirWithExclude(fileOp, index, childPath, &childNode, excludes); err != nil {
|
||||
return err
|
||||
}
|
||||
childNode.Size = 0
|
||||
for _, child := range childNode.Children {
|
||||
childNode.Size += child.Size
|
||||
}
|
||||
rootTree.Size += childNode.Size
|
||||
} else {
|
||||
itemSize, _ := fileOp.GetDirSize(childPath)
|
||||
childNode.Size = uint64(itemSize)
|
||||
rootTree.Size += childNode.Size
|
||||
}
|
||||
} else {
|
||||
info, _ := entry.Info()
|
||||
childNode.Size = uint64(info.Size())
|
||||
rootTree.Size += childNode.Size
|
||||
}
|
||||
|
||||
rootTree.Children = append(rootTree.Children, childNode)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadBackupIsCheck(treeData *dto.CleanTree) {
|
||||
for i := 0; i < len(treeData.Children); i++ {
|
||||
if len(treeData.Children[i].Children) == 0 {
|
||||
treeData.Children[i].IsCheck = true
|
||||
treeData.Children[i].IsRecommend = true
|
||||
continue
|
||||
}
|
||||
if treeData.Label != "unknown_database" && treeData.Label != "unknown_app" {
|
||||
continue
|
||||
}
|
||||
for j := 0; j < len(treeData.Children[i].Children); j++ {
|
||||
if len(treeData.Children[i].Children[j].Children) == 0 {
|
||||
treeData.Children[i].Children[j].IsCheck = true
|
||||
treeData.Children[i].Children[j].IsRecommend = true
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isExactPathMatch(path string, excludePaths []string) bool {
|
||||
cleanPath := filepath.Clean(path)
|
||||
|
||||
for _, excludePath := range excludePaths {
|
||||
cleanExclude := filepath.Clean(excludePath)
|
||||
if cleanPath == cleanExclude {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func loadRollBackTree(fileOp fileUtils.FileOp) []dto.CleanTree {
|
||||
var treeData []dto.CleanTree
|
||||
treeData = loadTreeWithCheck(treeData, path.Join(global.Dir.BaseDir, rollbackPath, "app"), "rollback_app", fileOp)
|
||||
@@ -360,7 +616,6 @@ func loadRollBackTree(fileOp fileUtils.FileOp) []dto.CleanTree {
|
||||
|
||||
func loadUploadTree(fileOp fileUtils.FileOp) []dto.CleanTree {
|
||||
var treeData []dto.CleanTree
|
||||
treeData = loadTreeWithCheck(treeData, path.Join(global.Dir.BaseDir, tmpUploadPath), "upload_tmp", fileOp)
|
||||
treeData = loadTreeWithCheck(treeData, path.Join(global.Dir.BaseDir, uploadPath, "app"), "upload_app", fileOp)
|
||||
treeData = loadTreeWithCheck(treeData, path.Join(global.Dir.BaseDir, uploadPath, "website"), "upload_website", fileOp)
|
||||
treeData = loadTreeWithCheck(treeData, path.Join(global.Dir.BaseDir, uploadPath, "database"), "upload_database", fileOp)
|
||||
@@ -382,6 +637,22 @@ func loadDownloadTree(fileOp fileUtils.FileOp) []dto.CleanTree {
|
||||
uploadTreeData := loadTreeWithAllFile(true, path5, "download", path5, fileOp)
|
||||
treeData = append(treeData, uploadTreeData...)
|
||||
|
||||
appTmpDownloadTree := loadAppTmpDownloadTree(fileOp)
|
||||
if len(appTmpDownloadTree) > 0 {
|
||||
parentTree := dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "app_tmp_download",
|
||||
IsCheck: true,
|
||||
IsRecommend: true,
|
||||
Type: "app_tmp_download",
|
||||
Name: "apps",
|
||||
}
|
||||
for _, child := range appTmpDownloadTree {
|
||||
parentTree.Size += child.Size
|
||||
}
|
||||
parentTree.Children = appTmpDownloadTree
|
||||
treeData = append(treeData, parentTree)
|
||||
}
|
||||
return treeData
|
||||
}
|
||||
|
||||
@@ -393,20 +664,106 @@ func loadLogTree(fileOp fileUtils.FileOp) []dto.CleanTree {
|
||||
for _, file := range list1 {
|
||||
size += file.Size
|
||||
}
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "system_log", Size: uint64(size), Children: list1, Type: "system_log", IsRecommend: true})
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "system_log", Size: size, Children: list1, Type: "system_log", IsRecommend: true})
|
||||
|
||||
path2 := path.Join(global.Dir.TaskDir)
|
||||
list2 := loadTreeWithDir(false, "task_log", path2, fileOp)
|
||||
size2, _ := fileOp.GetDirSize(path2)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "task_log", Size: uint64(size2), Children: list2, Type: "task_log"})
|
||||
|
||||
path3 := path.Join(global.Dir.TmpDir, "script")
|
||||
list3 := loadTreeWithAllFile(true, path3, "script", path3, fileOp)
|
||||
size3, _ := fileOp.GetDirSize(path3)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "script", Size: uint64(size3), Children: list3, Type: "script", IsRecommend: true})
|
||||
websiteLogList := loadWebsiteLogTree(fileOp)
|
||||
logTotalSize := uint64(0)
|
||||
for _, websiteLog := range websiteLogList {
|
||||
logTotalSize += websiteLog.Size
|
||||
}
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "website_log", Size: logTotalSize, Children: websiteLogList, Type: "website_log", IsRecommend: false})
|
||||
|
||||
return treeData
|
||||
}
|
||||
|
||||
func loadWebsiteLogTree(fileOp fileUtils.FileOp) []dto.CleanTree {
|
||||
websites, _ := websiteRepo.List()
|
||||
if len(websites) == 0 {
|
||||
return nil
|
||||
}
|
||||
var res []dto.CleanTree
|
||||
for _, website := range websites {
|
||||
size3, _ := fileOp.GetDirSize(path.Join(GetSiteDir(website.Alias), "log"))
|
||||
res = append(res, dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: website.PrimaryDomain,
|
||||
Size: uint64(size3),
|
||||
Type: "website_log",
|
||||
Name: website.Alias,
|
||||
})
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func loadAppTmpDownloadTree(fileOp fileUtils.FileOp) []dto.CleanTree {
|
||||
appDirs, err := os.ReadDir(global.Dir.RemoteAppResourceDir)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
var res []dto.CleanTree
|
||||
for _, appDir := range appDirs {
|
||||
if !appDir.IsDir() {
|
||||
continue
|
||||
}
|
||||
appKey := appDir.Name()
|
||||
app, _ := appRepo.GetFirst(appRepo.WithKey(appKey))
|
||||
if app.ID == 0 {
|
||||
continue
|
||||
}
|
||||
appPath := filepath.Join(global.Dir.RemoteAppResourceDir, appKey)
|
||||
versionDirs, err := os.ReadDir(appPath)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
appDetails, _ := appDetailRepo.GetBy(appDetailRepo.WithAppId(app.ID))
|
||||
existingVersions := make(map[string]bool)
|
||||
for _, appDetail := range appDetails {
|
||||
existingVersions[appDetail.Version] = true
|
||||
}
|
||||
var missingVersions []string
|
||||
for _, versionDir := range versionDirs {
|
||||
if !versionDir.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
version := versionDir.Name()
|
||||
if !existingVersions[version] {
|
||||
missingVersions = append(missingVersions, version)
|
||||
}
|
||||
}
|
||||
if len(missingVersions) > 0 {
|
||||
var appTree dto.CleanTree
|
||||
appTree.ID = uuid.NewString()
|
||||
appTree.Label = app.Name
|
||||
appTree.Type = "app_tmp_download"
|
||||
appTree.Name = appKey
|
||||
appTree.IsRecommend = true
|
||||
appTree.IsCheck = true
|
||||
for _, version := range missingVersions {
|
||||
versionPath := filepath.Join(appPath, version)
|
||||
size, _ := fileOp.GetDirSize(versionPath)
|
||||
appTree.Size += uint64(size)
|
||||
appTree.Children = append(appTree.Children, dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: version,
|
||||
Size: uint64(size),
|
||||
IsCheck: true,
|
||||
IsRecommend: true,
|
||||
Type: "app_tmp_download_version",
|
||||
Name: path.Join(appKey, version),
|
||||
})
|
||||
}
|
||||
res = append(res, appTree)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func loadContainerTree() []dto.CleanTree {
|
||||
var treeData []dto.CleanTree
|
||||
client, err := docker.NewDockerClient()
|
||||
@@ -528,7 +885,7 @@ func loadTreeWithAllFile(isCheck bool, originalPath, treeType, pathItem string,
|
||||
ID: uuid.NewString(),
|
||||
Label: file.Name(),
|
||||
Type: treeType,
|
||||
Size: uint64(size),
|
||||
Size: size,
|
||||
Name: name,
|
||||
IsCheck: isCheck,
|
||||
IsRecommend: isCheck,
|
||||
@@ -621,6 +978,18 @@ func dropVolumes() (int, int) {
|
||||
return len(res.VolumesDeleted), int(res.SpaceReclaimed)
|
||||
}
|
||||
|
||||
func dropWebsiteLog(alias string) {
|
||||
accessLogPath := path.Join(GetSiteDir(alias), "log", "access.log")
|
||||
errorLogPath := path.Join(GetSiteDir(alias), "log", "error.log")
|
||||
if err := os.Truncate(accessLogPath, 0); err != nil {
|
||||
global.LOG.Errorf("truncate access log %s failed, err %v", accessLogPath, err)
|
||||
}
|
||||
|
||||
if err := os.Truncate(errorLogPath, 0); err != nil {
|
||||
global.LOG.Errorf("truncate error log %s failed, err %v", errorLogPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
func dropTaskLog(logDir string) {
|
||||
files, err := os.ReadDir(logDir)
|
||||
if err != nil {
|
||||
|
||||
@@ -131,7 +131,11 @@ func (s *DiskService) MountDisk(req request.DiskMountRequest) error {
|
||||
return buserr.WithErr("MountDiskErr", err)
|
||||
}
|
||||
if req.AutoMount {
|
||||
if err := addToFstabWithOptions(req.Device, req.MountPoint, req.Filesystem, ""); err != nil {
|
||||
options := ""
|
||||
if req.NoFail {
|
||||
options = "defaults,nofail"
|
||||
}
|
||||
if err := addToFstabWithOptions(req.Device, req.MountPoint, req.Filesystem, options); err != nil {
|
||||
return buserr.WithErr("MountDiskErr", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,6 +463,11 @@ func isPointMounted(mountPoint string) bool {
|
||||
}
|
||||
|
||||
func addToFstabWithOptions(device, mountPoint, filesystem, options string) error {
|
||||
uuid, err := getDeviceUUID(device)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get UUID for device %s: %v", device, err)
|
||||
}
|
||||
|
||||
if filesystem == "" {
|
||||
fsType, err := getFilesystemType(device)
|
||||
if err != nil {
|
||||
@@ -476,7 +481,7 @@ func addToFstabWithOptions(device, mountPoint, filesystem, options string) error
|
||||
options = "defaults"
|
||||
}
|
||||
|
||||
entry := fmt.Sprintf("%s %s %s %s 0 2\n", device, mountPoint, filesystem, options)
|
||||
entry := fmt.Sprintf("UUID=%s %s %s %s 0 2\n", uuid, mountPoint, filesystem, options)
|
||||
|
||||
file, err := os.OpenFile("/etc/fstab", os.O_APPEND|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
@@ -568,3 +573,15 @@ func parseSizeToBytes(sizeStr string) int64 {
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
func getDeviceUUID(device string) (string, error) {
|
||||
output, err := cmd.RunDefaultWithStdoutBashC(fmt.Sprintf("blkid -s UUID -o value %s", device))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
uuid := strings.TrimSpace(output)
|
||||
if uuid == "" {
|
||||
return "", fmt.Errorf("no UUID found for device %s", device)
|
||||
}
|
||||
return uuid, nil
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ type IFileService interface {
|
||||
Compress(c request.FileCompress) error
|
||||
DeCompress(c request.FileDeCompress) error
|
||||
GetContent(op request.FileContentReq) (response.FileInfo, error)
|
||||
GetPreviewContent(op request.FileContentReq) (response.FileInfo, error)
|
||||
SaveContent(edit request.FileEdit) error
|
||||
FileDownload(d request.FileDownload) (string, error)
|
||||
DirSize(req request.DirSizeReq) (response.DirSizeRes, error)
|
||||
@@ -171,7 +172,6 @@ func shouldFilterPath(path string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// 递归构建文件树(只取当前目录以及当前目录下的第一层子节点)
|
||||
func (f *FileService) buildFileTree(node *response.FileTree, items []*files.FileInfo, op request.FileOption, level int) error {
|
||||
for _, v := range items {
|
||||
if shouldFilterPath(v.Path) {
|
||||
@@ -271,6 +271,11 @@ func (f *FileService) Delete(op request.FileDelete) error {
|
||||
return fo.DeleteFile(op.Path)
|
||||
}
|
||||
}
|
||||
info, _ := fo.Fs.Stat(op.Path)
|
||||
if info == nil || files.IsSymlink(info.Mode()) {
|
||||
return os.Remove(op.Path)
|
||||
}
|
||||
|
||||
if err := NewIRecycleBinService().Create(request.RecycleBinCreate{SourcePath: op.Path}); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -374,6 +379,82 @@ func (f *FileService) GetContent(op request.FileContentReq) (response.FileInfo,
|
||||
return response.FileInfo{FileInfo: *info}, nil
|
||||
}
|
||||
|
||||
func (f *FileService) GetPreviewContent(op request.FileContentReq) (response.FileInfo, error) {
|
||||
info, err := files.NewFileInfo(files.FileOption{
|
||||
Path: op.Path,
|
||||
Expand: false,
|
||||
IsDetail: op.IsDetail,
|
||||
})
|
||||
if err != nil {
|
||||
return response.FileInfo{}, err
|
||||
}
|
||||
|
||||
if files.IsBlockDevice(info.FileMode) {
|
||||
return response.FileInfo{FileInfo: *info}, nil
|
||||
}
|
||||
|
||||
file, err := os.Open(op.Path)
|
||||
if err != nil {
|
||||
return response.FileInfo{}, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
headBuf := make([]byte, 1024)
|
||||
n, err := file.Read(headBuf)
|
||||
if err != nil && err != io.EOF {
|
||||
return response.FileInfo{}, err
|
||||
}
|
||||
headBuf = headBuf[:n]
|
||||
|
||||
if len(headBuf) > 0 && files.DetectBinary(headBuf) {
|
||||
return response.FileInfo{FileInfo: *info}, nil
|
||||
}
|
||||
|
||||
const maxSize = 10 * 1024 * 1024
|
||||
if info.Size <= maxSize {
|
||||
if _, err := file.Seek(0, 0); err != nil {
|
||||
return response.FileInfo{}, err
|
||||
}
|
||||
content, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
return response.FileInfo{}, err
|
||||
}
|
||||
info.Content = string(content)
|
||||
} else {
|
||||
lines, err := files.TailFromEnd(op.Path, 300)
|
||||
if err != nil {
|
||||
return response.FileInfo{}, err
|
||||
}
|
||||
info.Content = strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
content := []byte(info.Content)
|
||||
if len(content) > 1024 {
|
||||
content = content[:1024]
|
||||
}
|
||||
if !utf8.Valid(content) {
|
||||
_, decodeName, _ := charset.DetermineEncoding(content, "")
|
||||
decoder := files.GetDecoderByName(decodeName)
|
||||
if decoder != nil {
|
||||
reader := strings.NewReader(info.Content)
|
||||
var dec *encoding.Decoder
|
||||
if decodeName == "windows-1252" {
|
||||
dec = simplifiedchinese.GBK.NewDecoder()
|
||||
} else {
|
||||
dec = decoder.NewDecoder()
|
||||
}
|
||||
decodedReader := transform.NewReader(reader, dec)
|
||||
contents, err := io.ReadAll(decodedReader)
|
||||
if err != nil {
|
||||
return response.FileInfo{}, err
|
||||
}
|
||||
info.Content = string(contents)
|
||||
}
|
||||
}
|
||||
|
||||
return response.FileInfo{FileInfo: *info}, nil
|
||||
}
|
||||
|
||||
func (f *FileService) SaveContent(edit request.FileEdit) error {
|
||||
info, err := files.NewFileInfo(files.FileOption{
|
||||
Path: edit.Path,
|
||||
@@ -577,6 +658,9 @@ func (f *FileService) ReadLogByLine(req request.FileReadByLineReq) (*response.Fi
|
||||
configPath = pathSet.Value
|
||||
}
|
||||
logFilePath, _ = ini_conf.GetIniValue(configPath, "supervisord", "logfile")
|
||||
case constant.Supervisor:
|
||||
logDir := path.Join(global.Dir.DataDir, "tools", "supervisord", "log")
|
||||
logFilePath = path.Join(logDir, req.Name)
|
||||
}
|
||||
|
||||
file, err := os.Open(logFilePath)
|
||||
|
||||
+16
-109
@@ -3,7 +3,6 @@ package service
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -14,7 +13,6 @@ import (
|
||||
"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/utils/cmd"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/common"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/controller"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/firewall"
|
||||
@@ -23,9 +21,6 @@ import (
|
||||
"github.com/jinzhu/copier"
|
||||
)
|
||||
|
||||
const confPath = "/etc/sysctl.conf"
|
||||
const panelSysctlPath = "/etc/sysctl.d/98-onepanel.conf"
|
||||
|
||||
type FirewallService struct{}
|
||||
|
||||
type IFirewallService interface {
|
||||
@@ -62,7 +57,7 @@ func (u *FirewallService) LoadBaseInfo(tab string) (dto.FirewallBaseInfo, error)
|
||||
wg.Add(2)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
baseInfo.PingStatus = u.pingStatus()
|
||||
baseInfo.PingStatus = firewall.LoadPingStatus()
|
||||
baseInfo.Version, _ = client.Version()
|
||||
}()
|
||||
go func() {
|
||||
@@ -206,10 +201,18 @@ func (u *FirewallService) OperateFirewall(req dto.FirewallOperation) error {
|
||||
return err
|
||||
}
|
||||
needRestartDocker = true
|
||||
case "disablePing":
|
||||
return u.updatePingStatus("0")
|
||||
case "enablePing":
|
||||
return u.updatePingStatus("1")
|
||||
case "disableBanPing":
|
||||
if err := firewall.UpdatePingStatus("0"); err != nil {
|
||||
_ = settingRepo.Update("BanPing", constant.StatusDisable)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
case "enableBanPing":
|
||||
if err := firewall.UpdatePingStatus("1"); err != nil {
|
||||
_ = settingRepo.Update("BanPing", constant.StatusEnable)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("not supported operation: %s", req.Operation)
|
||||
}
|
||||
@@ -589,105 +592,6 @@ func (u *FirewallService) cleanUnUsedData(client firewall.FirewallClient) {
|
||||
}
|
||||
}
|
||||
|
||||
func (u *FirewallService) pingStatus() string {
|
||||
data, err := os.ReadFile("/proc/sys/net/ipv4/icmp_echo_ignore_all")
|
||||
if err != nil {
|
||||
return constant.StatusNone
|
||||
}
|
||||
v6Data, v6err := os.ReadFile("/proc/sys/net/ipv6/icmp/echo_ignore_all")
|
||||
if v6err != nil {
|
||||
if strings.TrimSpace(string(data)) == "1" {
|
||||
return constant.StatusEnable
|
||||
}
|
||||
return constant.StatusDisable
|
||||
} else {
|
||||
if strings.TrimSpace(string(data)) == "1" && strings.TrimSpace(string(v6Data)) == "1" {
|
||||
return constant.StatusEnable
|
||||
}
|
||||
return constant.StatusDisable
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (u *FirewallService) updatePingStatus(enable string) error {
|
||||
var targetPath string
|
||||
var applyCmd string
|
||||
|
||||
if _, err := os.Stat(confPath); os.IsNotExist(err) {
|
||||
// Debian 13
|
||||
targetPath = panelSysctlPath
|
||||
applyCmd = fmt.Sprintf("%s sysctl --system", cmd.SudoHandleCmd())
|
||||
if err := cmd.RunDefaultBashCf("%s mkdir -p /etc/sysctl.d", cmd.SudoHandleCmd()); err != nil {
|
||||
return fmt.Errorf("failed to create directory /etc/sysctl.d: %v", err)
|
||||
}
|
||||
} else {
|
||||
targetPath = confPath
|
||||
applyCmd = fmt.Sprintf("%s sysctl -p", cmd.SudoHandleCmd())
|
||||
}
|
||||
|
||||
lineBytes, err := os.ReadFile(targetPath)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return fmt.Errorf("failed to read %s: %v", targetPath, err)
|
||||
}
|
||||
|
||||
if err := cmd.RunDefaultBashCf("echo %s | %s tee /proc/sys/net/ipv4/icmp_echo_ignore_all > /dev/null", enable, cmd.SudoHandleCmd()); err != nil {
|
||||
return fmt.Errorf("failed to apply ipv4 ping status temporarily: %v", err)
|
||||
}
|
||||
|
||||
var hasIpv6 bool
|
||||
if _, err := os.Stat("/proc/sys/net/ipv6/icmp/echo_ignore_all"); err == nil {
|
||||
hasIpv6 = true
|
||||
if err := cmd.RunDefaultBashCf("echo %s | %s tee /proc/sys/net/ipv6/icmp/echo_ignore_all > /dev/null", enable, cmd.SudoHandleCmd()); err != nil {
|
||||
global.LOG.Warnf("failed to apply ipv6 ping status temporarily: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
var files []string
|
||||
if err == nil {
|
||||
files = strings.Split(string(lineBytes), "\n")
|
||||
}
|
||||
|
||||
var newFiles []string
|
||||
hasIPv4Line, hasIPv6Line := false, false
|
||||
|
||||
for _, line := range files {
|
||||
if strings.HasPrefix(strings.TrimSpace(line), "net.ipv4.icmp_echo_ignore_all") {
|
||||
newFiles = append(newFiles, "net.ipv4.icmp_echo_ignore_all="+enable)
|
||||
hasIPv4Line = true
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(strings.TrimSpace(line), "net.ipv6.icmp.echo_ignore_all") {
|
||||
newFiles = append(newFiles, "net.ipv6.icmp.echo_ignore_all="+enable)
|
||||
hasIPv6Line = true
|
||||
continue
|
||||
}
|
||||
newFiles = append(newFiles, line)
|
||||
}
|
||||
|
||||
if !hasIPv4Line {
|
||||
newFiles = append(newFiles, "net.ipv4.icmp_echo_ignore_all="+enable)
|
||||
}
|
||||
if hasIpv6 && !hasIPv6Line {
|
||||
newFiles = append(newFiles, "net.ipv6.icmp.echo_ignore_all="+enable)
|
||||
}
|
||||
|
||||
file, err := os.OpenFile(targetPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, constant.FilePerm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open %s: %v", targetPath, err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
if _, err = file.WriteString(strings.Join(newFiles, "\n")); err != nil {
|
||||
return fmt.Errorf("failed to write to %s: %v", targetPath, err)
|
||||
}
|
||||
|
||||
if err := cmd.RunDefaultBashC(applyCmd); err != nil {
|
||||
global.LOG.Warnf("failed to apply persistent config with '%s': %v", applyCmd, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *FirewallService) addPortsBeforeStart(client firewall.FirewallClient) error {
|
||||
if !global.IsMaster {
|
||||
if err := client.Port(fireClient.FireInfo{Port: global.CONF.Base.Port, Protocol: "tcp", Strategy: "accept"}, "add"); err != nil {
|
||||
@@ -711,6 +615,9 @@ func (u *FirewallService) addPortsBeforeStart(client firewall.FirewallClient) er
|
||||
if err := client.Port(fireClient.FireInfo{Port: "443", Protocol: "tcp", Strategy: "accept"}, "add"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := client.Port(fireClient.FireInfo{Port: "443", Protocol: "udp", Strategy: "accept"}, "add"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return client.Reload()
|
||||
}
|
||||
|
||||
@@ -263,7 +263,15 @@ func stopBeforeUpdateRepo() error {
|
||||
if err := validateDockerConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := controller.HandleRestart("docker"); err != nil {
|
||||
dockerService, _ := controller.LoadServiceName("docker")
|
||||
if len(dockerService) == 0 {
|
||||
return errors.New("docker service not found")
|
||||
}
|
||||
client, err := controller.New()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := client.Operate("restart", dockerService); err != nil {
|
||||
return fmt.Errorf("failed to restart Docker: %v", err)
|
||||
}
|
||||
ticker := time.NewTicker(3 * time.Second)
|
||||
@@ -276,8 +284,8 @@ func stopBeforeUpdateRepo() error {
|
||||
cancel()
|
||||
return errors.New("the docker service cannot be restarted")
|
||||
default:
|
||||
active, err := controller.CheckActive("docker")
|
||||
if active && err != nil {
|
||||
active, _ := client.IsActive(dockerService)
|
||||
if active {
|
||||
global.LOG.Info("docker restart with new conf successful!")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -363,6 +363,9 @@ func initPreRules() error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicAfter, "-p udp -m udp --dport 443 -j ACCEPT"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := iptables.AddRule(iptables.FilterTab, iptables.Chain1PanelBasicAfter, iptables.DropAllTcp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -137,16 +137,45 @@ func (m *MonitorService) LoadGPUOptions() dto.MonitorGPUOptions {
|
||||
return gpuInfo.GPUs[i].Index < gpuInfo.GPUs[j].Index
|
||||
})
|
||||
for _, item := range gpuInfo.GPUs {
|
||||
var chartHide dto.GPUChartHide
|
||||
chartHide.ProductName = fmt.Sprintf("%d - %s", item.Index, item.ProductName)
|
||||
chartHide.GPU = item.GPUUtil == "" || item.GPUUtil == "N/A"
|
||||
if (item.MemTotal == "" || item.MemTotal == "N/A") && (item.MemUsed == "" || item.MemUsed == "N/A") {
|
||||
chartHide.Memory = true
|
||||
}
|
||||
if (item.MaxPowerLimit == "" || item.MaxPowerLimit == "N/A") && (item.PowerDraw == "" || item.PowerDraw == "N/A") {
|
||||
chartHide.Power = true
|
||||
}
|
||||
chartHide.Temperature = item.Temperature == "" || item.Temperature == "N/A"
|
||||
chartHide.Speed = item.FanSpeed == "" || item.FanSpeed == "N/A"
|
||||
data.ChartHide = append(data.ChartHide, chartHide)
|
||||
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 {
|
||||
xpu, err := xpuClient.LoadGpuInfo()
|
||||
if err != nil || len(xpu.Xpu) == 0 {
|
||||
global.LOG.Error("Load XPU info failed or no XPU found, err: ", err)
|
||||
}
|
||||
sort.Slice(xpu.Xpu, func(i, j int) bool {
|
||||
return xpu.Xpu[i].Basic.DeviceID < xpu.Xpu[j].Basic.DeviceID
|
||||
})
|
||||
for _, item := range xpu.Xpu {
|
||||
var chartHide dto.GPUChartHide
|
||||
chartHide.GPU = true
|
||||
chartHide.Speed = true
|
||||
chartHide.ProductName = fmt.Sprintf("%d - %s", item.Basic.DeviceID, item.Basic.DeviceName)
|
||||
if (item.Stats.MemoryUsed == "" || item.Stats.MemoryUsed == "N/A") && (item.Basic.Memory == "" || item.Basic.FreeMemory == "N/A") {
|
||||
chartHide.Memory = true
|
||||
}
|
||||
if item.Stats.Power == "" || item.Stats.Power == "N/A" {
|
||||
chartHide.Power = true
|
||||
}
|
||||
chartHide.Temperature = item.Stats.Temperature == "" || item.Stats.Temperature == "N/A"
|
||||
data.ChartHide = append(data.ChartHide, chartHide)
|
||||
data.Options = append(data.Options, fmt.Sprintf("%d - %s", item.Basic.DeviceID, item.Basic.DeviceName))
|
||||
}
|
||||
return data
|
||||
}
|
||||
}
|
||||
@@ -182,8 +211,10 @@ func (m *MonitorService) LoadGPUMonitorData(req dto.MonitorGPUSearch) (dto.Monit
|
||||
}
|
||||
var process []dto.GPUProcess
|
||||
if err := json.Unmarshal([]byte(gpu.Processes), &process); err == nil {
|
||||
data.ProcessCount = append(data.ProcessCount, len(process))
|
||||
data.GPUProcesses = append(data.GPUProcesses, process)
|
||||
} else {
|
||||
data.ProcessCount = append(data.ProcessCount, 0)
|
||||
data.GPUProcesses = append(data.GPUProcesses, []dto.GPUProcess{})
|
||||
}
|
||||
data.SpeedValue = append(data.SpeedValue, gpu.FanSpeed)
|
||||
@@ -383,9 +414,7 @@ func (m *MonitorService) saveIODataToDB(ctx context.Context, interval float64) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := monitorRepo.BatchCreateMonitorIO(ioList); err != nil {
|
||||
global.LOG.Errorf("Insert io monitoring data failed, err: %v", err)
|
||||
}
|
||||
_ = monitorRepo.BatchCreateMonitorIO(ioList)
|
||||
m.DiskIO <- ioStat2
|
||||
}
|
||||
}
|
||||
@@ -422,9 +451,7 @@ func (m *MonitorService) saveNetDataToDB(ctx context.Context, interval float64)
|
||||
}
|
||||
}
|
||||
|
||||
if err := monitorRepo.BatchCreateMonitorNet(netList); err != nil {
|
||||
global.LOG.Errorf("Insert network monitoring data failed, err: %v", err)
|
||||
}
|
||||
_ = monitorRepo.BatchCreateMonitorNet(netList)
|
||||
m.NetIO <- netStat2
|
||||
}
|
||||
}
|
||||
@@ -458,15 +485,15 @@ func loadTopCPU() []dto.Process {
|
||||
}
|
||||
name, err := p.Name()
|
||||
if err != nil {
|
||||
name = "undifine"
|
||||
name = "undefined"
|
||||
}
|
||||
cmd, err := p.Cmdline()
|
||||
if err != nil {
|
||||
cmd = "undifine"
|
||||
cmd = "undefined"
|
||||
}
|
||||
user, err := p.Username()
|
||||
if err != nil {
|
||||
user = "undifine"
|
||||
user = "undefined"
|
||||
}
|
||||
if len(top5) == 5 {
|
||||
top5[minIndex] = dto.Process{Percent: percent, Pid: p.Pid, User: user, Name: name, Cmd: cmd}
|
||||
@@ -509,15 +536,15 @@ func loadTopMem() []dto.Process {
|
||||
}
|
||||
name, err := p.Name()
|
||||
if err != nil {
|
||||
name = "undifine"
|
||||
name = "undefined"
|
||||
}
|
||||
cmd, err := p.Cmdline()
|
||||
if err != nil {
|
||||
cmd = "undifine"
|
||||
cmd = "undefined"
|
||||
}
|
||||
user, err := p.Username()
|
||||
if err != nil {
|
||||
user = "undifine"
|
||||
user = "undefined"
|
||||
}
|
||||
percent, _ := p.MemoryPercent()
|
||||
if len(top5) == 5 {
|
||||
|
||||
@@ -51,7 +51,7 @@ func getNginxFull(website *model.Website) (dto.NginxFull, error) {
|
||||
if website != nil {
|
||||
nginxFull.Website = *website
|
||||
var siteNginxConfig dto.NginxConfig
|
||||
siteConfigPath := GetSitePath(*website, SiteConf)
|
||||
siteConfigPath := GetWebsiteConfigPath(*website)
|
||||
siteNginxConfig.FilePath = siteConfigPath
|
||||
siteNginxContent, err := os.ReadFile(siteConfigPath)
|
||||
if err != nil {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"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/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/encrypt"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/ssh"
|
||||
"github.com/jinzhu/copier"
|
||||
@@ -22,6 +23,7 @@ type ISettingService interface {
|
||||
|
||||
TestConnByInfo(req dto.SSHConnData) bool
|
||||
SaveConnInfo(req dto.SSHConnData) error
|
||||
SetDefaultIsConn(req dto.SSHDefaultConn) error
|
||||
GetSystemProxy() (*dto.SystemProxy, error)
|
||||
GetLocalConn() dto.SSHConnData
|
||||
GetSettingByKey(key string) string
|
||||
@@ -125,6 +127,15 @@ func (u *SettingService) SaveConnInfo(req dto.SSHConnData) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *SettingService) SetDefaultIsConn(req dto.SSHDefaultConn) error {
|
||||
if req.DefaultConn == constant.StatusDisable && req.WithReset {
|
||||
if err := settingRepo.Update("LocalSSHConn", ""); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return settingRepo.Update("LocalSSHConnShow", req.DefaultConn)
|
||||
}
|
||||
|
||||
func (u *SettingService) GetSystemProxy() (*dto.SystemProxy, error) {
|
||||
systemProxy := dto.SystemProxy{}
|
||||
systemProxy.Type, _ = settingRepo.GetValueByKey("ProxyType")
|
||||
@@ -138,6 +149,7 @@ func (u *SettingService) GetSystemProxy() (*dto.SystemProxy, error) {
|
||||
|
||||
func (u *SettingService) GetLocalConn() dto.SSHConnData {
|
||||
var data dto.SSHConnData
|
||||
data.LocalSSHConnShow, _ = settingRepo.GetValueByKey("LocalSSHConnShow")
|
||||
connItem, _ := settingRepo.GetValueByKey("LocalSSHConn")
|
||||
if len(connItem) == 0 {
|
||||
return data
|
||||
|
||||
@@ -224,12 +224,16 @@ func loadApps(fileOp fileUtils.FileOp) ([]dto.DataTree, error) {
|
||||
appTreeMap := make(map[string]dto.DataTree)
|
||||
for _, app := range apps {
|
||||
itemApp := dto.DataTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: fmt.Sprintf("%s - %s", app.App.Name, app.Name),
|
||||
Key: app.App.Key,
|
||||
Name: app.Name,
|
||||
ID: uuid.NewString(),
|
||||
Label: fmt.Sprintf("%s - %s", app.App.Name, app.Name),
|
||||
Key: app.App.Key,
|
||||
Name: app.Name,
|
||||
IsLocal: app.App.Resource == "local",
|
||||
}
|
||||
appPath := path.Join(global.Dir.DataDir, "apps", app.App.Key, app.Name)
|
||||
if itemApp.IsLocal {
|
||||
appPath = path.Join(global.Dir.AppDir, "local", strings.TrimPrefix(app.App.Key, "local"), app.Name)
|
||||
}
|
||||
itemAppData := dto.DataTree{ID: uuid.NewString(), Label: "appData", Key: app.App.Key, Name: app.Name, IsCheck: true, Path: appPath}
|
||||
if app.App.Key == constant.AppOpenresty && len(websites) != 0 {
|
||||
itemAppData.IsDisable = true
|
||||
@@ -295,7 +299,11 @@ func loadAppImage(list []dto.DataTree) []dto.DataTree {
|
||||
|
||||
for i := 0; i < len(list); i++ {
|
||||
itemAppImage := dto.DataTree{ID: uuid.NewString(), Label: "appImage"}
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashCf("cat %s | grep image: ", path.Join(global.Dir.AppDir, list[i].Key, list[i].Name, "docker-compose.yml"))
|
||||
appPath := path.Join(global.Dir.DataDir, "apps", list[i].Key, list[i].Name)
|
||||
if list[i].IsLocal {
|
||||
appPath = path.Join(global.Dir.AppDir, "local", strings.TrimPrefix(list[i].Key, "local"), list[i].Name)
|
||||
}
|
||||
stdout, err := cmd.RunDefaultWithStdoutBashCf("cat %s | grep image: ", path.Join(appPath, "docker-compose.yml"))
|
||||
if err != nil {
|
||||
list[i].Children = append(list[i].Children, itemAppImage)
|
||||
continue
|
||||
@@ -328,11 +336,26 @@ func loadPanelFile(fileOp fileUtils.FileOp) ([]dto.DataTree, error) {
|
||||
Path: path.Join(global.Dir.DataDir, fileItem.Name()),
|
||||
}
|
||||
switch itemData.Label {
|
||||
case "agent", "runtime", "docker", "task", "geo", "secret", "uploads":
|
||||
case "runtime", "docker", "task", "geo", "secret", "uploads":
|
||||
itemData.IsDisable = true
|
||||
case "clamav", "download":
|
||||
panelPath := path.Join(global.Dir.DataDir, itemData.Label)
|
||||
itemData.Children, _ = loadFile(panelPath, 3, fileOp)
|
||||
case "agent":
|
||||
panelPath := path.Join(global.Dir.DataDir, itemData.Label)
|
||||
itemData.Children, _ = loadFile(panelPath, 2, fileOp)
|
||||
itemData.IsCheck = false
|
||||
for i := 0; i < len(itemData.Children); i++ {
|
||||
if itemData.Children[i].Label != "package" {
|
||||
itemData.Children[i].IsDisable = true
|
||||
} else {
|
||||
itemData.Size = -itemData.Children[i].Size
|
||||
itemData.Children[i].IsCheck = false
|
||||
for j := 0; j < len(itemData.Children[i].Children); j++ {
|
||||
itemData.Children[i].Children[j].IsCheck = false
|
||||
}
|
||||
}
|
||||
}
|
||||
case "apps", "backup", "log", "db", "tmp":
|
||||
continue
|
||||
}
|
||||
@@ -341,7 +364,7 @@ func loadPanelFile(fileOp fileUtils.FileOp) ([]dto.DataTree, error) {
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
itemData.Size = uint64(sizeItem)
|
||||
itemData.Size = uint64(int64(sizeItem) + int64(itemData.Size))
|
||||
} else {
|
||||
fileInfo, err := fileItem.Info()
|
||||
if err != nil {
|
||||
|
||||
@@ -405,7 +405,7 @@ func snapAppImage(snap snapHelper, req dto.SnapshotCreate, targetDir string) err
|
||||
if len(imageList) != 0 {
|
||||
snap.Task.Log(strings.Join(imageList, " "))
|
||||
snap.Task.Logf("docker save %s | gzip -c > %s", strings.Join(imageList, " "), path.Join(targetDir, "images.tar.gz"))
|
||||
if err := cmd.NewCommandMgr(cmd.WithTimeout(10*time.Minute)).RunBashCf("docker save %s | gzip -c > %s", strings.Join(imageList, " "), path.Join(targetDir, "images.tar.gz")); err != nil {
|
||||
if err := cmd.RunDefaultBashCf("docker save %s | gzip -c > %s", strings.Join(imageList, " "), path.Join(targetDir, "images.tar.gz")); err != nil {
|
||||
snap.Task.LogFailedWithErr(i18n.GetMsgByKey("SnapDockerSave"), err)
|
||||
return err
|
||||
}
|
||||
|
||||
+222
-1362
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,312 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/response"
|
||||
"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/cmd/server/nginx_conf"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/files"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/nginx"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/nginx/components"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/nginx/parser"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (w WebsiteService) GetAuthBasics(req request.NginxAuthReq) (res response.NginxAuthRes, err error) {
|
||||
var (
|
||||
website model.Website
|
||||
authContent []byte
|
||||
nginxParams []response.NginxParam
|
||||
)
|
||||
website, err = websiteRepo.GetFirst(repo.WithByID(req.WebsiteID))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
absoluteAuthPath := GetSitePath(website, SiteRootAuthBasicPath)
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(absoluteAuthPath) {
|
||||
return
|
||||
}
|
||||
nginxParams, err = getNginxParamsByKeys(constant.NginxScopeServer, []string{"auth_basic"}, &website)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
res.Enable = len(nginxParams[0].Params) > 0
|
||||
authContent, err = fileOp.GetContent(absoluteAuthPath)
|
||||
authArray := strings.Split(string(authContent), "\n")
|
||||
for _, line := range authArray {
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
params := strings.Split(line, ":")
|
||||
auth := dto.NginxAuth{
|
||||
Username: params[0],
|
||||
}
|
||||
if len(params) == 3 {
|
||||
auth.Remark = params[2]
|
||||
}
|
||||
res.Items = append(res.Items, auth)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (w WebsiteService) UpdateAuthBasic(req request.NginxAuthUpdate) (err error) {
|
||||
var (
|
||||
website model.Website
|
||||
params []dto.NginxParam
|
||||
authContent []byte
|
||||
authArray []string
|
||||
)
|
||||
website, err = websiteRepo.GetFirst(repo.WithByID(req.WebsiteID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
authPath := fmt.Sprintf("/www/sites/%s/auth_basic/auth.pass", website.Alias)
|
||||
absoluteAuthPath := GetSitePath(website, SiteRootAuthBasicPath)
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(path.Dir(absoluteAuthPath)) {
|
||||
_ = fileOp.CreateDir(path.Dir(absoluteAuthPath), constant.DirPerm)
|
||||
}
|
||||
if !fileOp.Stat(absoluteAuthPath) {
|
||||
_ = fileOp.CreateFile(absoluteAuthPath)
|
||||
}
|
||||
|
||||
params = append(params, dto.NginxParam{Name: "auth_basic", Params: []string{`"Authentication"`}})
|
||||
params = append(params, dto.NginxParam{Name: "auth_basic_user_file", Params: []string{authPath}})
|
||||
authContent, err = fileOp.GetContent(absoluteAuthPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(authContent) > 0 {
|
||||
authArray = strings.Split(string(authContent), "\n")
|
||||
}
|
||||
switch req.Operate {
|
||||
case "disable":
|
||||
return deleteNginxConfig(constant.NginxScopeServer, params, &website)
|
||||
case "enable":
|
||||
return updateNginxConfig(constant.NginxScopeServer, params, &website)
|
||||
case "create":
|
||||
for _, line := range authArray {
|
||||
authParams := strings.Split(line, ":")
|
||||
username := authParams[0]
|
||||
if username == req.Username {
|
||||
err = buserr.New("ErrUsernameIsExist")
|
||||
return
|
||||
}
|
||||
}
|
||||
var passwdHash []byte
|
||||
passwdHash, err = bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
line := fmt.Sprintf("%s:%s\n", req.Username, passwdHash)
|
||||
if req.Remark != "" {
|
||||
line = fmt.Sprintf("%s:%s:%s\n", req.Username, passwdHash, req.Remark)
|
||||
}
|
||||
authArray = append(authArray, line)
|
||||
case "edit":
|
||||
userExist := false
|
||||
for index, line := range authArray {
|
||||
authParams := strings.Split(line, ":")
|
||||
username := authParams[0]
|
||||
if username == req.Username {
|
||||
userExist = true
|
||||
var passwdHash []byte
|
||||
passwdHash, err = bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
userPasswd := fmt.Sprintf("%s:%s\n", req.Username, passwdHash)
|
||||
if req.Remark != "" {
|
||||
userPasswd = fmt.Sprintf("%s:%s:%s\n", req.Username, passwdHash, req.Remark)
|
||||
}
|
||||
authArray[index] = userPasswd
|
||||
}
|
||||
}
|
||||
if !userExist {
|
||||
err = buserr.New("ErrUsernameIsNotExist")
|
||||
return
|
||||
}
|
||||
case "delete":
|
||||
deleteIndex := -1
|
||||
for index, line := range authArray {
|
||||
authParams := strings.Split(line, ":")
|
||||
username := authParams[0]
|
||||
if username == req.Username {
|
||||
deleteIndex = index
|
||||
}
|
||||
}
|
||||
if deleteIndex < 0 {
|
||||
return
|
||||
}
|
||||
authArray = append(authArray[:deleteIndex], authArray[deleteIndex+1:]...)
|
||||
}
|
||||
|
||||
var passFile *os.File
|
||||
passFile, err = os.Create(absoluteAuthPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer passFile.Close()
|
||||
writer := bufio.NewWriter(passFile)
|
||||
for _, line := range authArray {
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
_, err = writer.WriteString(line + "\n")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
err = writer.Flush()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
authContent, err = fileOp.GetContent(absoluteAuthPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(authContent) == 0 {
|
||||
if err = deleteNginxConfig(constant.NginxScopeServer, params, &website); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (w WebsiteService) GetPathAuthBasics(req request.NginxAuthReq) (res []response.NginxPathAuthRes, err error) {
|
||||
var (
|
||||
website model.Website
|
||||
authContent []byte
|
||||
)
|
||||
website, err = websiteRepo.GetFirst(repo.WithByID(req.WebsiteID))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fileOp := files.NewFileOp()
|
||||
absoluteAuthDir := GetSitePath(website, SitePathAuthBasicDir)
|
||||
passDir := path.Join(absoluteAuthDir, "pass")
|
||||
if !fileOp.Stat(absoluteAuthDir) || !fileOp.Stat(passDir) {
|
||||
return
|
||||
}
|
||||
|
||||
entries, err := os.ReadDir(absoluteAuthDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
if !entry.IsDir() {
|
||||
name := strings.TrimSuffix(entry.Name(), ".conf")
|
||||
pathAuth := dto.NginxPathAuth{
|
||||
Name: name,
|
||||
}
|
||||
configPath := path.Join(absoluteAuthDir, entry.Name())
|
||||
content, err := fileOp.GetContent(configPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config, err := parser.NewStringParser(string(content)).Parse()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
directives := config.Directives
|
||||
location, _ := directives[0].(*components.Location)
|
||||
pathAuth.Path = strings.TrimPrefix(location.Match, "^")
|
||||
passPath := path.Join(passDir, fmt.Sprintf("%s.pass", name))
|
||||
authContent, err = fileOp.GetContent(passPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authArray := strings.Split(string(authContent), "\n")
|
||||
for _, line := range authArray {
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
params := strings.Split(line, ":")
|
||||
pathAuth.Username = params[0]
|
||||
if len(params) == 3 {
|
||||
pathAuth.Remark = params[2]
|
||||
}
|
||||
}
|
||||
res = append(res, response.NginxPathAuthRes{
|
||||
NginxPathAuth: pathAuth,
|
||||
})
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (w WebsiteService) UpdatePathAuthBasic(req request.NginxPathAuthUpdate) error {
|
||||
website, err := websiteRepo.GetFirst(repo.WithByID(req.WebsiteID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fileOp := files.NewFileOp()
|
||||
authDir := GetSitePath(website, SitePathAuthBasicDir)
|
||||
if !fileOp.Stat(authDir) {
|
||||
_ = fileOp.CreateDir(authDir, constant.DirPerm)
|
||||
}
|
||||
passDir := path.Join(authDir, "pass")
|
||||
if !fileOp.Stat(passDir) {
|
||||
_ = fileOp.CreateDir(passDir, constant.DirPerm)
|
||||
}
|
||||
confPath := path.Join(authDir, fmt.Sprintf("%s.conf", req.Name))
|
||||
passPath := path.Join(passDir, fmt.Sprintf("%s.pass", req.Name))
|
||||
var config *components.Config
|
||||
switch req.Operate {
|
||||
case "delete":
|
||||
_ = fileOp.DeleteFile(confPath)
|
||||
_ = fileOp.DeleteFile(passPath)
|
||||
return updateNginxConfig(constant.NginxScopeServer, nil, &website)
|
||||
case "create":
|
||||
config, err = parser.NewStringParser(string(nginx_conf.PathAuth)).Parse()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if fileOp.Stat(confPath) || fileOp.Stat(passPath) {
|
||||
return buserr.New("ErrNameIsExist")
|
||||
}
|
||||
case "edit":
|
||||
par, err := parser.NewParser(confPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
config, err = par.Parse()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
config.FilePath = confPath
|
||||
directives := config.Directives
|
||||
location, _ := directives[0].(*components.Location)
|
||||
location.UpdateDirective("auth_basic_user_file", []string{fmt.Sprintf("/www/sites/%s/path_auth/pass/%s", website.Alias, fmt.Sprintf("%s.pass", req.Name))})
|
||||
location.ChangePath("~*", fmt.Sprintf("^%s", req.Path))
|
||||
var passwdHash []byte
|
||||
passwdHash, err = bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
line := fmt.Sprintf("%s:%s\n", req.Username, passwdHash)
|
||||
if req.Remark != "" {
|
||||
line = fmt.Sprintf("%s:%s:%s\n", req.Username, passwdHash, req.Remark)
|
||||
}
|
||||
_ = fileOp.SaveFile(passPath, line, constant.DirPerm)
|
||||
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
||||
return buserr.WithErr("ErrUpdateBuWebsite", err)
|
||||
}
|
||||
nginxInclude := fmt.Sprintf("/www/sites/%s/path_auth/*.conf", website.Alias)
|
||||
if err = updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{{Name: "include", Params: []string{nginxInclude}}}, &website); err != nil {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/files"
|
||||
"path"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func (w WebsiteService) CreateWebsiteDomain(create request.WebsiteDomainCreate) ([]model.WebsiteDomain, error) {
|
||||
var (
|
||||
domainModels []model.WebsiteDomain
|
||||
addPorts []int
|
||||
)
|
||||
httpPort, httpsPort, err := getAppInstallPort(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
website, err := websiteRepo.GetFirst(repo.WithByID(create.WebsiteID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
domainModels, addPorts, _, err = getWebsiteDomains(create.Domains, httpPort, httpsPort, create.WebsiteID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
go func() {
|
||||
_ = OperateFirewallPort(nil, addPorts)
|
||||
}()
|
||||
|
||||
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
wafDataPath := path.Join(nginxInstall.GetPath(), "1pwaf", "data")
|
||||
fileOp := files.NewFileOp()
|
||||
if fileOp.Stat(wafDataPath) {
|
||||
websitesConfigPath := path.Join(wafDataPath, "conf", "sites.json")
|
||||
content, err := fileOp.GetContent(websitesConfigPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var websitesArray []request.WafWebsite
|
||||
if content != nil {
|
||||
if err := json.Unmarshal(content, &websitesArray); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
for index, wafWebsite := range websitesArray {
|
||||
if wafWebsite.Key == website.Alias {
|
||||
wafSite := request.WafWebsite{
|
||||
Key: website.Alias,
|
||||
Domains: wafWebsite.Domains,
|
||||
Host: wafWebsite.Host,
|
||||
}
|
||||
for _, domain := range domainModels {
|
||||
wafSite.Domains = append(wafSite.Domains, domain.Domain)
|
||||
wafSite.Host = append(wafSite.Host, domain.Domain+":"+strconv.Itoa(domain.Port))
|
||||
}
|
||||
if len(wafSite.Host) == 0 {
|
||||
wafSite.Host = []string{}
|
||||
}
|
||||
websitesArray[index] = wafSite
|
||||
break
|
||||
}
|
||||
}
|
||||
websitesContent, err := json.Marshal(websitesArray)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := fileOp.SaveFileWithByte(websitesConfigPath, websitesContent, constant.DirPerm); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err = addListenAndServerName(website, domainModels); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return domainModels, websiteDomainRepo.BatchCreate(context.TODO(), domainModels)
|
||||
}
|
||||
|
||||
func (w WebsiteService) GetWebsiteDomain(websiteId uint) ([]model.WebsiteDomain, error) {
|
||||
return websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(websiteId))
|
||||
}
|
||||
|
||||
func (w WebsiteService) DeleteWebsiteDomain(domainId uint) error {
|
||||
webSiteDomain, err := websiteDomainRepo.GetFirst(repo.WithByID(domainId))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if websiteDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(webSiteDomain.WebsiteID)); len(websiteDomains) == 1 {
|
||||
return fmt.Errorf("can not delete last domain")
|
||||
}
|
||||
website, err := websiteRepo.GetFirst(repo.WithByID(webSiteDomain.WebsiteID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var ports []int
|
||||
if oldDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(webSiteDomain.WebsiteID), websiteDomainRepo.WithPort(webSiteDomain.Port)); len(oldDomains) == 1 {
|
||||
ports = append(ports, webSiteDomain.Port)
|
||||
}
|
||||
|
||||
var domains []string
|
||||
if oldDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(webSiteDomain.WebsiteID), websiteDomainRepo.WithDomain(webSiteDomain.Domain)); len(oldDomains) == 1 {
|
||||
domains = append(domains, webSiteDomain.Domain)
|
||||
}
|
||||
|
||||
if len(ports) > 0 || len(domains) > 0 {
|
||||
stringBinds := make([]string, len(ports))
|
||||
for i := 0; i < len(ports); i++ {
|
||||
stringBinds[i] = strconv.Itoa(ports[i])
|
||||
}
|
||||
if err := deleteListenAndServerName(website, stringBinds, domains); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
wafDataPath := path.Join(nginxInstall.GetPath(), "1pwaf", "data")
|
||||
fileOp := files.NewFileOp()
|
||||
if fileOp.Stat(wafDataPath) {
|
||||
websitesConfigPath := path.Join(wafDataPath, "conf", "sites.json")
|
||||
content, err := fileOp.GetContent(websitesConfigPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var websitesArray []request.WafWebsite
|
||||
var newWebsitesArray []request.WafWebsite
|
||||
if content != nil {
|
||||
if err := json.Unmarshal(content, &websitesArray); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, wafWebsite := range websitesArray {
|
||||
if wafWebsite.Key == website.Alias {
|
||||
wafSite := wafWebsite
|
||||
oldDomains := wafSite.Domains
|
||||
var newDomains []string
|
||||
for _, domain := range oldDomains {
|
||||
if domain == webSiteDomain.Domain {
|
||||
continue
|
||||
}
|
||||
newDomains = append(newDomains, domain)
|
||||
}
|
||||
wafSite.Domains = newDomains
|
||||
oldHostArray := wafSite.Host
|
||||
var newHostArray []string
|
||||
for _, host := range oldHostArray {
|
||||
if host == webSiteDomain.Domain+":"+strconv.Itoa(webSiteDomain.Port) {
|
||||
continue
|
||||
}
|
||||
newHostArray = append(newHostArray, host)
|
||||
}
|
||||
wafSite.Host = newHostArray
|
||||
if len(wafSite.Host) == 0 {
|
||||
wafSite.Host = []string{}
|
||||
}
|
||||
newWebsitesArray = append(newWebsitesArray, wafSite)
|
||||
} else {
|
||||
newWebsitesArray = append(newWebsitesArray, wafWebsite)
|
||||
}
|
||||
}
|
||||
websitesContent, err := json.Marshal(newWebsitesArray)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = fileOp.SaveFileWithByte(websitesConfigPath, websitesContent, constant.DirPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return websiteDomainRepo.DeleteBy(context.TODO(), repo.WithByID(domainId))
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
"github.com/1Panel-dev/1Panel/agent/cmd/server/nginx_conf"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/files"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/nginx"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/nginx/components"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/nginx/parser"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (w WebsiteService) GetLoadBalances(id uint) ([]dto.NginxUpstream, error) {
|
||||
website, err := websiteRepo.GetFirst(repo.WithByID(id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
includeDir := GetSitePath(website, SiteUpstreamDir)
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(includeDir) {
|
||||
return nil, nil
|
||||
}
|
||||
entries, err := os.ReadDir(includeDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var res []dto.NginxUpstream
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
name := entry.Name()
|
||||
if !strings.HasSuffix(name, ".conf") {
|
||||
continue
|
||||
}
|
||||
upstreamName := strings.TrimSuffix(name, ".conf")
|
||||
upstream := dto.NginxUpstream{
|
||||
Name: upstreamName,
|
||||
}
|
||||
upstreamPath := path.Join(includeDir, name)
|
||||
content, err := fileOp.GetContent(upstreamPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
upstream.Content = string(content)
|
||||
nginxParser, err := parser.NewParser(upstreamPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config, err := nginxParser.Parse()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
upstreams := config.FindUpstreams()
|
||||
for _, up := range upstreams {
|
||||
if up.UpstreamName == upstreamName {
|
||||
directives := up.GetDirectives()
|
||||
for _, d := range directives {
|
||||
dName := d.GetName()
|
||||
if _, ok := dto.LBAlgorithms[dName]; ok {
|
||||
upstream.Algorithm = dName
|
||||
}
|
||||
}
|
||||
upstream.Servers = getNginxUpstreamServers(up.UpstreamServers)
|
||||
}
|
||||
}
|
||||
res = append(res, upstream)
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (w WebsiteService) CreateLoadBalance(req request.WebsiteLBCreate) error {
|
||||
website, err := websiteRepo.GetFirst(repo.WithByID(req.WebsiteID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
includeDir := GetSitePath(website, SiteUpstreamDir)
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(includeDir) {
|
||||
_ = fileOp.CreateDir(includeDir, constant.DirPerm)
|
||||
}
|
||||
filePath := path.Join(includeDir, fmt.Sprintf("%s.conf", req.Name))
|
||||
if fileOp.Stat(filePath) {
|
||||
return buserr.New("ErrNameIsExist")
|
||||
}
|
||||
config, err := parser.NewStringParser(string(nginx_conf.Upstream)).Parse()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
config.Block = &components.Block{}
|
||||
config.FilePath = filePath
|
||||
upstream := components.Upstream{
|
||||
UpstreamName: req.Name,
|
||||
}
|
||||
if req.Algorithm != "default" {
|
||||
upstream.UpdateDirective(req.Algorithm, []string{})
|
||||
}
|
||||
upstream.UpstreamServers = parseUpstreamServers(req.Servers)
|
||||
config.Block.Directives = append(config.Block.Directives, &upstream)
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
_ = fileOp.DeleteFile(filePath)
|
||||
}
|
||||
}()
|
||||
|
||||
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
||||
return buserr.WithErr("ErrUpdateBuWebsite", err)
|
||||
}
|
||||
nginxInclude := fmt.Sprintf("/www/sites/%s/upstream/*.conf", website.Alias)
|
||||
if err = updateNginxConfig("", []dto.NginxParam{{Name: "include", Params: []string{nginxInclude}}}, &website); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w WebsiteService) UpdateLoadBalance(req request.WebsiteLBUpdate) error {
|
||||
website, err := websiteRepo.GetFirst(repo.WithByID(req.WebsiteID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
includeDir := GetSitePath(website, SiteUpstreamDir)
|
||||
fileOp := files.NewFileOp()
|
||||
filePath := path.Join(includeDir, fmt.Sprintf("%s.conf", req.Name))
|
||||
if !fileOp.Stat(filePath) {
|
||||
return nil
|
||||
}
|
||||
oldContent, err := fileOp.GetContent(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
parser, err := parser.NewParser(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
config, err := parser.Parse()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
upstreams := config.FindUpstreams()
|
||||
for _, up := range upstreams {
|
||||
if up.UpstreamName == req.Name {
|
||||
directives := up.GetDirectives()
|
||||
for _, d := range directives {
|
||||
dName := d.GetName()
|
||||
if _, ok := dto.LBAlgorithms[dName]; ok {
|
||||
up.RemoveDirective(dName, nil)
|
||||
}
|
||||
}
|
||||
if req.Algorithm != "default" {
|
||||
up.UpdateDirective(req.Algorithm, []string{})
|
||||
}
|
||||
up.UpstreamServers = parseUpstreamServers(req.Servers)
|
||||
}
|
||||
}
|
||||
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
||||
return buserr.WithErr("ErrUpdateBuWebsite", err)
|
||||
}
|
||||
return nginxCheckAndReload(string(oldContent), filePath, nginxInstall.ContainerName)
|
||||
}
|
||||
|
||||
func (w WebsiteService) DeleteLoadBalance(req request.WebsiteLBDelete) error {
|
||||
website, err := websiteRepo.GetFirst(repo.WithByID(req.WebsiteID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
proxies, _ := w.GetProxies(website.ID)
|
||||
if len(proxies) > 0 {
|
||||
for _, proxy := range proxies {
|
||||
if strings.HasSuffix(proxy.ProxyPass, fmt.Sprintf("://%s", req.Name)) {
|
||||
return buserr.New("ErrProxyIsUsed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
includeDir := GetSitePath(website, SiteUpstreamDir)
|
||||
fileOp := files.NewFileOp()
|
||||
filePath := path.Join(includeDir, fmt.Sprintf("%s.conf", req.Name))
|
||||
if !fileOp.Stat(filePath) {
|
||||
return nil
|
||||
}
|
||||
if err = fileOp.DeleteFile(filePath); err != nil {
|
||||
return err
|
||||
}
|
||||
return opNginx(nginxInstall.ContainerName, constant.NginxReload)
|
||||
}
|
||||
|
||||
func (w WebsiteService) UpdateLoadBalanceFile(req request.WebsiteLBUpdateFile) error {
|
||||
website, err := websiteRepo.GetFirst(repo.WithByID(req.WebsiteID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
includeDir := GetSitePath(website, SiteUpstreamDir)
|
||||
filePath := path.Join(includeDir, fmt.Sprintf("%s.conf", req.Name))
|
||||
fileOp := files.NewFileOp()
|
||||
oldContent, err := fileOp.GetContent(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = fileOp.WriteFile(filePath, strings.NewReader(req.Content), constant.DirPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
_ = fileOp.WriteFile(filePath, bytes.NewReader(oldContent), constant.DirPerm)
|
||||
}
|
||||
}()
|
||||
return opNginx(nginxInstall.ContainerName, constant.NginxReload)
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/task"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/i18n"
|
||||
"sort"
|
||||
)
|
||||
|
||||
func (w WebsiteService) BatchOpWebsite(req request.BatchWebsiteOp) error {
|
||||
websites, _ := websiteRepo.List(repo.WithByIDs(req.IDs))
|
||||
opTask, err := task.NewTaskWithOps(i18n.GetMsgByKey("Status"), task.TaskBatch, task.TaskScopeWebsite, req.TaskID, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sort.SliceStable(websites, func(i, j int) bool {
|
||||
if websites[i].Type == constant.Subsite && websites[j].Type != constant.Subsite {
|
||||
return true
|
||||
}
|
||||
if websites[i].Type != constant.Subsite && websites[j].Type == constant.Subsite {
|
||||
return false
|
||||
}
|
||||
return false
|
||||
})
|
||||
opWebsiteTask := func(t *task.Task) error {
|
||||
for _, web := range websites {
|
||||
msg := fmt.Sprintf("%s %s", i18n.GetMsgByKey(req.Operate), web.PrimaryDomain)
|
||||
switch req.Operate {
|
||||
case constant.StopWeb, constant.StartWeb:
|
||||
if err := opWebsite(&web, req.Operate); err != nil {
|
||||
t.LogFailedWithErr(msg, err)
|
||||
continue
|
||||
}
|
||||
_ = websiteRepo.Save(context.Background(), &web)
|
||||
case "delete":
|
||||
if err := w.DeleteWebsite(request.WebsiteDelete{
|
||||
ID: web.ID,
|
||||
}); err != nil {
|
||||
t.LogFailedWithErr(msg, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
t.LogSuccess(msg)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
opTask.AddSubTask("", opWebsiteTask, nil)
|
||||
|
||||
go func() {
|
||||
_ = opTask.Execute()
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w WebsiteService) BatchSetGroup(req request.BatchWebsiteGroup) error {
|
||||
websites, _ := websiteRepo.List(repo.WithByIDs(req.IDs))
|
||||
for _, web := range websites {
|
||||
web.WebsiteGroupID = req.GroupID
|
||||
if err := websiteRepo.Save(context.Background(), &web); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w WebsiteService) BatchSetHttps(ctx context.Context, req request.BatchWebsiteHttps) error {
|
||||
websites, _ := websiteRepo.List(repo.WithByIDs(req.IDs))
|
||||
opTask, err := task.NewTaskWithOps(i18n.GetMsgByKey("SSL"), task.TaskBatch, task.TaskScopeWebsite, req.TaskID, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
websiteHttpsOp := request.WebsiteHTTPSOp{
|
||||
Enable: true,
|
||||
WebsiteSSLID: req.WebsiteSSLID,
|
||||
Type: req.Type,
|
||||
PrivateKey: req.PrivateKey,
|
||||
Certificate: req.Certificate,
|
||||
PrivateKeyPath: req.PrivateKeyPath,
|
||||
CertificatePath: req.CertificatePath,
|
||||
ImportType: req.ImportType,
|
||||
HttpConfig: req.HttpConfig,
|
||||
SSLProtocol: req.SSLProtocol,
|
||||
Algorithm: req.Algorithm,
|
||||
Hsts: req.Hsts,
|
||||
HstsIncludeSubDomains: req.HstsIncludeSubDomains,
|
||||
HttpsPorts: req.HttpsPorts,
|
||||
Http3: req.Http3,
|
||||
}
|
||||
if req.Type == constant.SSLManual {
|
||||
websiteSSL, err := getManualWebsiteSSL(websiteHttpsOp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = websiteSSLRepo.Create(ctx, &websiteSSL); err != nil {
|
||||
return err
|
||||
}
|
||||
websiteHttpsOp.Type = constant.SSLExisted
|
||||
websiteHttpsOp.WebsiteSSLID = websiteSSL.ID
|
||||
}
|
||||
opWebsiteTask := func(t *task.Task) error {
|
||||
for _, web := range websites {
|
||||
if web.Type == constant.Stream {
|
||||
continue
|
||||
}
|
||||
websiteHttpsOp.WebsiteID = web.ID
|
||||
msg := fmt.Sprintf("%s [%s] %s", i18n.GetMsgByKey("Set"), web.PrimaryDomain, i18n.GetMsgByKey("SSL"))
|
||||
if _, err := w.OpWebsiteHTTPS(ctx, websiteHttpsOp); err != nil {
|
||||
t.LogFailedWithErr(msg, err)
|
||||
continue
|
||||
}
|
||||
t.LogSuccess(msg)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
opTask.AddSubTask("", opWebsiteTask, nil)
|
||||
go func() {
|
||||
_ = opTask.Execute()
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,408 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/response"
|
||||
"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/cmd/server/nginx_conf"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/files"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/nginx"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/nginx/components"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/nginx/parser"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/re"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error) {
|
||||
var (
|
||||
website model.Website
|
||||
par *parser.Parser
|
||||
oldContent []byte
|
||||
)
|
||||
|
||||
website, err = websiteRepo.GetFirst(repo.WithByID(req.ID))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fileOp := files.NewFileOp()
|
||||
includeDir := GetSitePath(website, SiteProxyDir)
|
||||
if !fileOp.Stat(includeDir) {
|
||||
_ = fileOp.CreateDir(includeDir, constant.DirPerm)
|
||||
}
|
||||
fileName := fmt.Sprintf("%s.conf", req.Name)
|
||||
includePath := path.Join(includeDir, fileName)
|
||||
backName := fmt.Sprintf("%s.bak", req.Name)
|
||||
backPath := path.Join(includeDir, backName)
|
||||
|
||||
if req.Operate == "create" && (fileOp.Stat(includePath) || fileOp.Stat(backPath)) {
|
||||
err = buserr.New("ErrNameIsExist")
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
switch req.Operate {
|
||||
case "create":
|
||||
_ = fileOp.DeleteFile(includePath)
|
||||
case "edit":
|
||||
_ = fileOp.WriteFile(includePath, bytes.NewReader(oldContent), constant.DirPerm)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
var config *components.Config
|
||||
|
||||
switch req.Operate {
|
||||
case "create":
|
||||
config, err = parser.NewStringParser(string(nginx_conf.GetWebsiteFile("proxy.conf"))).Parse()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
case "edit":
|
||||
par, err = parser.NewParser(includePath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
config, err = par.Parse()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
oldContent, err = fileOp.GetContent(includePath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
case "delete":
|
||||
_ = fileOp.DeleteFile(includePath)
|
||||
_ = fileOp.DeleteFile(backPath)
|
||||
return updateNginxConfig(constant.NginxScopeServer, nil, &website)
|
||||
case "disable":
|
||||
_ = fileOp.Rename(includePath, backPath)
|
||||
return updateNginxConfig(constant.NginxScopeServer, nil, &website)
|
||||
case "enable":
|
||||
_ = fileOp.Rename(backPath, includePath)
|
||||
return updateNginxConfig(constant.NginxScopeServer, nil, &website)
|
||||
}
|
||||
|
||||
config.FilePath = includePath
|
||||
directives := config.Directives
|
||||
|
||||
var location *components.Location
|
||||
for _, directive := range directives {
|
||||
if loc, ok := directive.(*components.Location); ok {
|
||||
location = loc
|
||||
break
|
||||
}
|
||||
}
|
||||
if location == nil {
|
||||
err = errors.New("invalid proxy config, no location found")
|
||||
return
|
||||
}
|
||||
location.UpdateDirective("proxy_pass", []string{req.ProxyPass})
|
||||
location.UpdateDirective("proxy_set_header", []string{"Host", req.ProxyHost})
|
||||
location.ChangePath(req.Modifier, req.Match)
|
||||
// Server Cache Settings
|
||||
if req.Cache {
|
||||
if err = openProxyCache(website); err != nil {
|
||||
return
|
||||
}
|
||||
location.AddServerCache(fmt.Sprintf("proxy_cache_zone_of_%s", website.Alias), req.ServerCacheTime, req.ServerCacheUnit)
|
||||
} else {
|
||||
location.RemoveServerCache(fmt.Sprintf("proxy_cache_zone_of_%s", website.Alias))
|
||||
}
|
||||
// Browser Cache Settings
|
||||
if req.CacheTime != 0 {
|
||||
location.AddBrowserCache(req.CacheTime, req.CacheUnit)
|
||||
} else {
|
||||
location.RemoveBrowserCache()
|
||||
}
|
||||
// Content Replace Settings
|
||||
if len(req.Replaces) > 0 {
|
||||
location.AddSubFilter(req.Replaces)
|
||||
} else {
|
||||
location.RemoveSubFilter()
|
||||
}
|
||||
// SSL Settings
|
||||
if req.SNI {
|
||||
location.UpdateDirective("proxy_ssl_server_name", []string{"on"})
|
||||
if req.ProxySSLName != "" {
|
||||
location.UpdateDirective("proxy_ssl_name", []string{req.ProxySSLName})
|
||||
}
|
||||
} else {
|
||||
location.UpdateDirective("proxy_ssl_server_name", []string{"off"})
|
||||
}
|
||||
// CORS Settings
|
||||
if req.Cors {
|
||||
location.UpdateDirective("add_header", []string{"Access-Control-Allow-Origin", req.AllowOrigins, "always"})
|
||||
if req.AllowMethods != "" {
|
||||
location.UpdateDirective("add_header", []string{"Access-Control-Allow-Methods", req.AllowMethods, "always"})
|
||||
} else {
|
||||
location.RemoveDirective("add_header", []string{"Access-Control-Allow-Methods"})
|
||||
}
|
||||
if req.AllowHeaders != "" {
|
||||
location.UpdateDirective("add_header", []string{"Access-Control-Allow-Headers", req.AllowHeaders, "always"})
|
||||
} else {
|
||||
location.RemoveDirective("add_header", []string{"Access-Control-Allow-Headers"})
|
||||
}
|
||||
if req.AllowCredentials {
|
||||
location.UpdateDirective("add_header", []string{"Access-Control-Allow-Credentials", "true", "always"})
|
||||
} else {
|
||||
location.RemoveDirective("add_header", []string{"Access-Control-Allow-Credentials"})
|
||||
}
|
||||
if req.Preflight {
|
||||
location.AddCorsOption()
|
||||
} else {
|
||||
location.RemoveCorsOption()
|
||||
}
|
||||
} else {
|
||||
location.RemoveDirective("add_header", []string{"Access-Control-Allow-Origin"})
|
||||
location.RemoveDirective("add_header", []string{"Access-Control-Allow-Methods"})
|
||||
location.RemoveDirective("add_header", []string{"Access-Control-Allow-Headers"})
|
||||
location.RemoveDirective("add_header", []string{"Access-Control-Allow-Credentials"})
|
||||
location.RemoveDirectiveByFullParams("if", []string{"(", "$request_method", "=", "'OPTIONS'", ")"})
|
||||
}
|
||||
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
||||
return buserr.WithErr("ErrUpdateBuWebsite", err)
|
||||
}
|
||||
nginxInclude := fmt.Sprintf("/www/sites/%s/proxy/*.conf", website.Alias)
|
||||
return updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{{Name: "include", Params: []string{nginxInclude}}}, &website)
|
||||
}
|
||||
|
||||
func (w WebsiteService) UpdateProxyCache(req request.NginxProxyCacheUpdate) (err error) {
|
||||
website, err := websiteRepo.GetFirst(repo.WithByID(req.WebsiteID))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cacheDir := GetSitePath(website, SiteCacheDir)
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(cacheDir) {
|
||||
_ = fileOp.CreateDir(cacheDir, constant.DirPerm)
|
||||
}
|
||||
if req.Open {
|
||||
proxyCachePath := fmt.Sprintf("/www/sites/%s/cache levels=1:2 keys_zone=proxy_cache_zone_of_%s:%d%s max_size=%d%s inactive=%d%s", website.Alias, website.Alias, req.ShareCache, req.ShareCacheUnit, req.CacheLimit, req.CacheLimitUnit, req.CacheExpire, req.CacheExpireUnit)
|
||||
return updateNginxConfig("", []dto.NginxParam{{Name: "proxy_cache_path", Params: []string{proxyCachePath}}}, &website)
|
||||
}
|
||||
return deleteNginxConfig("", []dto.NginxParam{{Name: "proxy_cache_path"}}, &website)
|
||||
}
|
||||
|
||||
func (w WebsiteService) GetProxyCache(id uint) (res response.NginxProxyCache, err error) {
|
||||
var (
|
||||
website model.Website
|
||||
)
|
||||
website, err = websiteRepo.GetFirst(repo.WithByID(id))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
parser, err := parser.NewParser(GetSitePath(website, SiteConf))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
config, err := parser.Parse()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var params []string
|
||||
for _, d := range config.GetDirectives() {
|
||||
if d.GetName() == "proxy_cache_path" {
|
||||
params = d.GetParameters()
|
||||
}
|
||||
}
|
||||
if len(params) == 0 {
|
||||
return
|
||||
}
|
||||
for _, param := range params {
|
||||
if re.GetRegex(re.ProxyCacheZonePattern).MatchString(param) {
|
||||
matches := re.GetRegex(re.ProxyCacheZonePattern).FindStringSubmatch(param)
|
||||
if len(matches) > 0 {
|
||||
res.ShareCache, _ = strconv.Atoi(matches[1])
|
||||
res.ShareCacheUnit = matches[2]
|
||||
}
|
||||
}
|
||||
|
||||
if re.GetRegex(re.ProxyCacheMaxSizeValidationPattern).MatchString(param) {
|
||||
matches := re.GetRegex(re.ProxyCacheMaxSizePattern).FindStringSubmatch(param)
|
||||
if len(matches) > 0 {
|
||||
res.CacheLimit, _ = strconv.ParseFloat(matches[1], 64)
|
||||
res.CacheLimitUnit = matches[2]
|
||||
}
|
||||
}
|
||||
if re.GetRegex(re.ProxyCacheInactivePattern).MatchString(param) {
|
||||
matches := re.GetRegex(re.ProxyCacheInactivePattern).FindStringSubmatch(param)
|
||||
if len(matches) > 0 {
|
||||
res.CacheExpire, _ = strconv.Atoi(matches[1])
|
||||
res.CacheExpireUnit = matches[2]
|
||||
}
|
||||
}
|
||||
}
|
||||
res.Open = true
|
||||
return
|
||||
}
|
||||
|
||||
func (w WebsiteService) GetProxies(id uint) (res []request.WebsiteProxyConfig, err error) {
|
||||
var (
|
||||
website model.Website
|
||||
fileList response.FileInfo
|
||||
)
|
||||
website, err = websiteRepo.GetFirst(repo.WithByID(id))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
includeDir := GetSitePath(website, SiteProxyDir)
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(includeDir) {
|
||||
return
|
||||
}
|
||||
fileList, err = NewIFileService().GetFileList(request.FileOption{FileOption: files.FileOption{Path: includeDir, Expand: true, Page: 1, PageSize: 100}})
|
||||
if len(fileList.Items) == 0 {
|
||||
return
|
||||
}
|
||||
var (
|
||||
content []byte
|
||||
config *components.Config
|
||||
)
|
||||
for _, configFile := range fileList.Items {
|
||||
proxyConfig := request.WebsiteProxyConfig{
|
||||
ID: website.ID,
|
||||
}
|
||||
parts := strings.Split(configFile.Name, ".")
|
||||
proxyConfig.Name = parts[0]
|
||||
if parts[1] == "conf" {
|
||||
proxyConfig.Enable = true
|
||||
} else {
|
||||
proxyConfig.Enable = false
|
||||
}
|
||||
proxyConfig.FilePath = configFile.Path
|
||||
content, err = fileOp.GetContent(configFile.Path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
proxyConfig.Content = string(content)
|
||||
config, err = parser.NewStringParser(string(content)).Parse()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
directives := config.GetDirectives()
|
||||
|
||||
var location *components.Location
|
||||
for _, directive := range directives {
|
||||
if loc, ok := directive.(*components.Location); ok {
|
||||
location = loc
|
||||
break
|
||||
}
|
||||
}
|
||||
if location == nil {
|
||||
err = errors.New("invalid proxy config, no location found")
|
||||
return
|
||||
}
|
||||
proxyConfig.ProxyPass = location.ProxyPass
|
||||
proxyConfig.Cache = location.Cache
|
||||
if location.CacheTime > 0 {
|
||||
proxyConfig.CacheTime = location.CacheTime
|
||||
proxyConfig.CacheUnit = location.CacheUint
|
||||
}
|
||||
if location.ServerCacheTime > 0 {
|
||||
proxyConfig.ServerCacheTime = location.ServerCacheTime
|
||||
proxyConfig.ServerCacheUnit = location.ServerCacheUint
|
||||
}
|
||||
proxyConfig.Match = location.Match
|
||||
proxyConfig.Modifier = location.Modifier
|
||||
proxyConfig.ProxyHost = location.Host
|
||||
proxyConfig.Replaces = location.Replaces
|
||||
for _, directive := range location.Directives {
|
||||
if directive.GetName() == "proxy_ssl_server_name" {
|
||||
proxyConfig.SNI = directive.GetParameters()[0] == "on"
|
||||
}
|
||||
if directive.GetName() == "proxy_ssl_name" && len(directive.GetParameters()) > 0 {
|
||||
proxyConfig.ProxySSLName = directive.GetParameters()[0]
|
||||
}
|
||||
}
|
||||
proxyConfig.Cors = location.Cors
|
||||
proxyConfig.AllowCredentials = location.AllowCredentials
|
||||
proxyConfig.AllowHeaders = location.AllowHeaders
|
||||
proxyConfig.AllowOrigins = location.AllowOrigins
|
||||
proxyConfig.AllowMethods = location.AllowMethods
|
||||
proxyConfig.Preflight = location.Preflight
|
||||
res = append(res, proxyConfig)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (w WebsiteService) UpdateProxyFile(req request.NginxProxyUpdate) (err error) {
|
||||
var (
|
||||
website model.Website
|
||||
oldRewriteContent []byte
|
||||
)
|
||||
website, err = websiteRepo.GetFirst(repo.WithByID(req.WebsiteID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
absolutePath := fmt.Sprintf("%s/%s.conf", GetSitePath(website, SiteProxyDir), req.Name)
|
||||
fileOp := files.NewFileOp()
|
||||
oldRewriteContent, err = fileOp.GetContent(absolutePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = fileOp.WriteFile(absolutePath, strings.NewReader(req.Content), constant.DirPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
_ = fileOp.WriteFile(absolutePath, bytes.NewReader(oldRewriteContent), constant.DirPerm)
|
||||
}
|
||||
}()
|
||||
return updateNginxConfig(constant.NginxScopeServer, nil, &website)
|
||||
}
|
||||
|
||||
func (w WebsiteService) ClearProxyCache(req request.NginxCommonReq) error {
|
||||
website, err := websiteRepo.GetFirst(repo.WithByID(req.WebsiteID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cacheDir := GetSitePath(website, SiteCacheDir)
|
||||
fileOp := files.NewFileOp()
|
||||
if fileOp.Stat(cacheDir) {
|
||||
if err = fileOp.CleanDir(cacheDir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = opNginx(nginxInstall.ContainerName, constant.NginxReload); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w WebsiteService) DeleteProxy(req request.WebsiteProxyDel) (err error) {
|
||||
fileOp := files.NewFileOp()
|
||||
website, err := websiteRepo.GetFirst(repo.WithByID(req.ID))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
includeDir := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "proxy")
|
||||
if !fileOp.Stat(includeDir) {
|
||||
_ = fileOp.CreateDir(includeDir, 0755)
|
||||
}
|
||||
fileName := fmt.Sprintf("%s.conf", req.Name)
|
||||
includePath := path.Join(includeDir, fileName)
|
||||
backName := fmt.Sprintf("%s.bak", req.Name)
|
||||
backPath := path.Join(includeDir, backName)
|
||||
_ = fileOp.DeleteFile(includePath)
|
||||
_ = fileOp.DeleteFile(backPath)
|
||||
return updateNginxConfig(constant.NginxScopeServer, nil, &website)
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/response"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
"github.com/1Panel-dev/1Panel/agent/cmd/server/nginx_conf"
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/files"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (w WebsiteService) UpdateRewriteConfig(req request.NginxRewriteUpdate) error {
|
||||
website, err := websiteRepo.GetFirst(repo.WithByID(req.WebsiteID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
includePath := fmt.Sprintf("/www/sites/%s/rewrite/%s.conf", website.Alias, website.Alias)
|
||||
absolutePath := GetSitePath(website, SiteReWritePath)
|
||||
fileOp := files.NewFileOp()
|
||||
var oldRewriteContent []byte
|
||||
if !fileOp.Stat(path.Dir(absolutePath)) {
|
||||
if err := fileOp.CreateDir(path.Dir(absolutePath), constant.DirPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if !fileOp.Stat(absolutePath) {
|
||||
if err := fileOp.CreateFile(absolutePath); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
oldRewriteContent, err = fileOp.GetContent(absolutePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := fileOp.WriteFile(absolutePath, strings.NewReader(req.Content), constant.DirPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{{Name: "include", Params: []string{includePath}}}, &website); err != nil {
|
||||
_ = fileOp.WriteFile(absolutePath, bytes.NewReader(oldRewriteContent), constant.DirPerm)
|
||||
return err
|
||||
}
|
||||
website.Rewrite = req.Name
|
||||
return websiteRepo.Save(context.Background(), &website)
|
||||
}
|
||||
|
||||
func (w WebsiteService) GetRewriteConfig(req request.NginxRewriteReq) (*response.NginxRewriteRes, error) {
|
||||
website, err := websiteRepo.GetFirst(repo.WithByID(req.WebsiteID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var contentByte []byte
|
||||
if req.Name == "current" {
|
||||
rewriteConfPath := GetSitePath(website, SiteReWritePath)
|
||||
fileOp := files.NewFileOp()
|
||||
if fileOp.Stat(rewriteConfPath) {
|
||||
contentByte, err = fileOp.GetContent(rewriteConfPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rewriteFile := fmt.Sprintf("rewrite/%s.conf", strings.ToLower(req.Name))
|
||||
contentByte, _ = nginx_conf.Rewrites.ReadFile(rewriteFile)
|
||||
if contentByte == nil {
|
||||
customRewriteDir := GetOpenrestyDir(DefaultRewriteDir)
|
||||
customRewriteFile := path.Join(customRewriteDir, fmt.Sprintf("%s.conf", strings.ToLower(req.Name)))
|
||||
contentByte, err = files.NewFileOp().GetContent(customRewriteFile)
|
||||
}
|
||||
}
|
||||
return &response.NginxRewriteRes{
|
||||
Content: string(contentByte),
|
||||
}, err
|
||||
}
|
||||
|
||||
func (w WebsiteService) OperateCustomRewrite(req request.CustomRewriteOperate) error {
|
||||
rewriteDir := GetOpenrestyDir(DefaultRewriteDir)
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(rewriteDir) {
|
||||
if err := fileOp.CreateDir(rewriteDir, constant.DirPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
rewriteFile := path.Join(rewriteDir, fmt.Sprintf("%s.conf", req.Name))
|
||||
switch req.Operate {
|
||||
case "create":
|
||||
if fileOp.Stat(rewriteFile) {
|
||||
return buserr.New("ErrNameIsExist")
|
||||
}
|
||||
return fileOp.WriteFile(rewriteFile, strings.NewReader(req.Content), constant.DirPerm)
|
||||
case "delete":
|
||||
return fileOp.DeleteFile(rewriteFile)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w WebsiteService) ListCustomRewrite() ([]string, error) {
|
||||
rewriteDir := GetOpenrestyDir(DefaultRewriteDir)
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(rewriteDir) {
|
||||
return nil, nil
|
||||
}
|
||||
entries, err := os.ReadDir(rewriteDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var res []string
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
res = append(res, strings.TrimSuffix(entry.Name(), ".conf"))
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
@@ -141,6 +141,7 @@ func (w WebsiteSSLService) Create(create request.WebsiteSSLCreate) (request.Webs
|
||||
SkipDNS: create.SkipDNS,
|
||||
DisableCNAME: create.DisableCNAME,
|
||||
ExecShell: create.ExecShell,
|
||||
IsIp: create.IsIp,
|
||||
}
|
||||
if create.ExecShell {
|
||||
websiteSSL.Shell = create.Shell
|
||||
@@ -322,7 +323,11 @@ func (w WebsiteSSLService) ObtainSSL(apply request.WebsiteSSLApply) error {
|
||||
handleError(websiteSSL, err)
|
||||
return
|
||||
}
|
||||
resource, err = client.ObtainSSL(domains, privateKey)
|
||||
if websiteSSL.IsIp {
|
||||
resource, err = client.ObtainIPSSL(domains[0], privateKey)
|
||||
} else {
|
||||
resource, err = client.ObtainSSL(domains, privateKey)
|
||||
}
|
||||
if err != nil {
|
||||
handleError(websiteSSL, err)
|
||||
return
|
||||
|
||||
+283
-120
@@ -2,7 +2,9 @@ package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
@@ -14,10 +16,10 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
@@ -129,7 +131,7 @@ func createProxyFile(website *model.Website) error {
|
||||
}
|
||||
|
||||
func createWebsiteFolder(website *model.Website, runtime *model.Runtime) error {
|
||||
siteFolder := GteSiteDir(website.Alias)
|
||||
siteFolder := GetSiteDir(website.Alias)
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(siteFolder) {
|
||||
if err := fileOp.CreateDir(siteFolder, constant.DirPerm); err != nil {
|
||||
@@ -144,11 +146,13 @@ func createWebsiteFolder(website *model.Website, runtime *model.Runtime) error {
|
||||
if err := fileOp.CreateFile(path.Join(siteFolder, "log", "error.log")); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := fileOp.CreateDir(path.Join(siteFolder, "index"), constant.DirPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := fileOp.CreateDir(path.Join(siteFolder, "ssl"), constant.DirPerm); err != nil {
|
||||
return err
|
||||
if website.Type != constant.Stream {
|
||||
if err := fileOp.CreateDir(path.Join(siteFolder, "index"), constant.DirPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := fileOp.CreateDir(path.Join(siteFolder, "ssl"), constant.DirPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if website.Type == constant.Runtime {
|
||||
if runtime.Type == constant.RuntimePHP && runtime.Resource == constant.ResourceLocal {
|
||||
@@ -175,7 +179,7 @@ func createWebsiteFolder(website *model.Website, runtime *model.Runtime) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, appInstall *model.AppInstall, runtime *model.Runtime) error {
|
||||
func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, appInstall *model.AppInstall, runtime *model.Runtime, streamConfig request.StreamConfig) error {
|
||||
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -183,72 +187,90 @@ func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, a
|
||||
if err = createWebsiteFolder(website, runtime); err != nil {
|
||||
return err
|
||||
}
|
||||
configPath := GetSitePath(*website, SiteConf)
|
||||
nginxContent := nginx_conf.GetWebsiteFile("website_default.conf")
|
||||
config, err := parser.NewStringParser(string(nginxContent)).Parse()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
servers := config.FindServers()
|
||||
if len(servers) == 0 {
|
||||
return errors.New("nginx config is not valid")
|
||||
}
|
||||
server := servers[0]
|
||||
server.DeleteListen("80")
|
||||
var serverNames []string
|
||||
for _, domain := range domains {
|
||||
serverNames = append(serverNames, domain.Domain)
|
||||
setListen(server, strconv.Itoa(domain.Port), website.IPV6, false, website.DefaultServer, false)
|
||||
}
|
||||
server.UpdateServerName(serverNames)
|
||||
|
||||
siteFolder := path.Join("/www", "sites", website.Alias)
|
||||
server.UpdateDirective("access_log", []string{path.Join(siteFolder, "log", "access.log"), "main"})
|
||||
server.UpdateDirective("error_log", []string{path.Join(siteFolder, "log", "error.log")})
|
||||
|
||||
rootIndex := path.Join("/www/sites", website.Alias, "index")
|
||||
switch website.Type {
|
||||
case constant.Deployment:
|
||||
proxy := fmt.Sprintf("http://127.0.0.1:%d", appInstall.HttpPort)
|
||||
server.UpdateRootProxy([]string{proxy})
|
||||
case constant.Static:
|
||||
server.UpdateRoot(rootIndex)
|
||||
server.UpdateDirective("error_page", []string{"404", "/404.html"})
|
||||
case constant.Proxy:
|
||||
nginxInclude := fmt.Sprintf("/www/sites/%s/proxy/*.conf", website.Alias)
|
||||
server.UpdateDirective("include", []string{nginxInclude})
|
||||
server.UpdateRoot(rootIndex)
|
||||
case constant.Runtime:
|
||||
switch runtime.Type {
|
||||
case constant.RuntimePHP:
|
||||
server.UpdateDirective("error_page", []string{"404", "/404.html"})
|
||||
if runtime.Resource == constant.ResourceLocal {
|
||||
server.UpdateRoot(rootIndex)
|
||||
localPath := path.Join(rootIndex, "index.php")
|
||||
server.UpdatePHPProxy([]string{website.Proxy}, localPath)
|
||||
} else {
|
||||
server.UpdateRoot(rootIndex)
|
||||
server.UpdatePHPProxy([]string{website.Proxy}, "")
|
||||
}
|
||||
case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo, constant.RuntimePython, constant.RuntimeDotNet:
|
||||
server.UpdateRootProxy([]string{fmt.Sprintf("http://%s", website.Proxy)})
|
||||
var (
|
||||
configPath string
|
||||
config *components.Config
|
||||
)
|
||||
if website.Type == constant.Stream {
|
||||
if streamConfig.StreamPorts == "" {
|
||||
return buserr.New("ErrTypePortRange")
|
||||
}
|
||||
case constant.Subsite:
|
||||
parentWebsite, err := websiteRepo.GetFirst(repo.WithByID(website.ParentWebsiteID))
|
||||
nginxContent := nginx_conf.GetWebsiteFile("stream_default.conf")
|
||||
config, err = parser.NewStringParser(string(nginxContent)).Parse()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
website.Proxy = parentWebsite.Proxy
|
||||
rootIndex = path.Join("/www/sites", parentWebsite.Alias, "index", website.SiteDir)
|
||||
server.UpdateDirective("error_page", []string{"404", "/404.html"})
|
||||
if parentWebsite.Type == constant.Runtime {
|
||||
parentRuntime, err := runtimeRepo.GetFirst(context.Background(), repo.WithByID(parentWebsite.RuntimeID))
|
||||
if err != nil {
|
||||
return err
|
||||
servers := config.FindServers()
|
||||
if len(servers) == 0 {
|
||||
return errors.New("nginx config is not valid")
|
||||
}
|
||||
server := servers[0]
|
||||
ports := strings.Split(streamConfig.StreamPorts, ",")
|
||||
var params []string
|
||||
if streamConfig.UDP {
|
||||
params = []string{"udp"}
|
||||
}
|
||||
for _, port := range ports {
|
||||
server.UpdateListen(port, false, params...)
|
||||
if website.IPV6 {
|
||||
server.UpdateListen("[::]:"+port, false, params...)
|
||||
}
|
||||
website.RuntimeID = parentRuntime.ID
|
||||
if parentRuntime.Type == constant.RuntimePHP {
|
||||
if parentRuntime.Resource == constant.ResourceLocal {
|
||||
}
|
||||
siteFolder := path.Join("/www", "sites", website.Alias)
|
||||
server.UpdateDirective("access_log", []string{path.Join(siteFolder, "log", "access.log"), "streamlog"})
|
||||
server.UpdateDirective("error_log", []string{path.Join(siteFolder, "log", "error.log")})
|
||||
server.UpdateDirective("proxy_pass", []string{website.Alias})
|
||||
|
||||
upstream := components.Upstream{
|
||||
UpstreamName: website.Alias,
|
||||
}
|
||||
if streamConfig.Algorithm != "default" {
|
||||
upstream.UpdateDirective(streamConfig.Algorithm, []string{})
|
||||
}
|
||||
upstream.UpstreamServers = parseUpstreamServers(streamConfig.Servers)
|
||||
config.Block.Directives = append(config.Block.Directives, &upstream)
|
||||
configPath = GetSitePath(*website, StreamConf)
|
||||
} else {
|
||||
configPath = GetSitePath(*website, SiteConf)
|
||||
nginxContent := nginx_conf.GetWebsiteFile("website_default.conf")
|
||||
config, err = parser.NewStringParser(string(nginxContent)).Parse()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
servers := config.FindServers()
|
||||
if len(servers) == 0 {
|
||||
return errors.New("nginx config is not valid")
|
||||
}
|
||||
server := servers[0]
|
||||
server.DeleteListen("80")
|
||||
var serverNames []string
|
||||
for _, domain := range domains {
|
||||
serverNames = append(serverNames, domain.Domain)
|
||||
setListen(server, strconv.Itoa(domain.Port), website.IPV6, false, website.DefaultServer, false)
|
||||
}
|
||||
server.UpdateServerName(serverNames)
|
||||
|
||||
siteFolder := path.Join("/www", "sites", website.Alias)
|
||||
server.UpdateDirective("access_log", []string{path.Join(siteFolder, "log", "access.log"), "main"})
|
||||
server.UpdateDirective("error_log", []string{path.Join(siteFolder, "log", "error.log")})
|
||||
|
||||
rootIndex := path.Join("/www/sites", website.Alias, "index")
|
||||
switch website.Type {
|
||||
case constant.Deployment:
|
||||
proxy := fmt.Sprintf("http://127.0.0.1:%d", appInstall.HttpPort)
|
||||
server.UpdateRootProxy([]string{proxy})
|
||||
case constant.Static:
|
||||
server.UpdateRoot(rootIndex)
|
||||
server.UpdateDirective("error_page", []string{"404", "/404.html"})
|
||||
case constant.Proxy:
|
||||
nginxInclude := fmt.Sprintf("/www/sites/%s/proxy/*.conf", website.Alias)
|
||||
server.UpdateDirective("include", []string{nginxInclude})
|
||||
server.UpdateRoot(rootIndex)
|
||||
case constant.Runtime:
|
||||
switch runtime.Type {
|
||||
case constant.RuntimePHP:
|
||||
server.UpdateDirective("error_page", []string{"404", "/404.html"})
|
||||
if runtime.Resource == constant.ResourceLocal {
|
||||
server.UpdateRoot(rootIndex)
|
||||
localPath := path.Join(rootIndex, "index.php")
|
||||
server.UpdatePHPProxy([]string{website.Proxy}, localPath)
|
||||
@@ -256,13 +278,39 @@ func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, a
|
||||
server.UpdateRoot(rootIndex)
|
||||
server.UpdatePHPProxy([]string{website.Proxy}, "")
|
||||
}
|
||||
case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo, constant.RuntimePython, constant.RuntimeDotNet:
|
||||
server.UpdateRootProxy([]string{fmt.Sprintf("http://%s", website.Proxy)})
|
||||
}
|
||||
case constant.Subsite:
|
||||
parentWebsite, err := websiteRepo.GetFirst(repo.WithByID(website.ParentWebsiteID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
website.Proxy = parentWebsite.Proxy
|
||||
rootIndex = path.Join("/www/sites", parentWebsite.Alias, "index", website.SiteDir)
|
||||
server.UpdateDirective("error_page", []string{"404", "/404.html"})
|
||||
if parentWebsite.Type == constant.Runtime {
|
||||
parentRuntime, err := runtimeRepo.GetFirst(context.Background(), repo.WithByID(parentWebsite.RuntimeID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
website.RuntimeID = parentRuntime.ID
|
||||
if parentRuntime.Type == constant.RuntimePHP {
|
||||
if parentRuntime.Resource == constant.ResourceLocal {
|
||||
server.UpdateRoot(rootIndex)
|
||||
localPath := path.Join(rootIndex, "index.php")
|
||||
server.UpdatePHPProxy([]string{website.Proxy}, localPath)
|
||||
} else {
|
||||
server.UpdateRoot(rootIndex)
|
||||
server.UpdatePHPProxy([]string{website.Proxy}, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
if parentWebsite.Type == constant.Static {
|
||||
server.UpdateRoot(rootIndex)
|
||||
}
|
||||
}
|
||||
if parentWebsite.Type == constant.Static {
|
||||
server.UpdateRoot(rootIndex)
|
||||
}
|
||||
}
|
||||
|
||||
config.FilePath = configPath
|
||||
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
||||
return err
|
||||
@@ -432,16 +480,22 @@ func createWafConfig(website *model.Website, domains []model.WebsiteDomain) erro
|
||||
}
|
||||
|
||||
func delNginxConfig(website model.Website, force bool) error {
|
||||
configPath := GetSitePath(website, SiteConf)
|
||||
fileOp := files.NewFileOp()
|
||||
var (
|
||||
configPath string
|
||||
)
|
||||
if website.Type == constant.Stream {
|
||||
configPath = GetSitePath(website, StreamConf)
|
||||
|
||||
if !fileOp.Stat(configPath) {
|
||||
return nil
|
||||
} else {
|
||||
configPath = GetSitePath(website, SiteConf)
|
||||
}
|
||||
if err := fileOp.DeleteFile(configPath); err != nil {
|
||||
return err
|
||||
if fileOp.Stat(configPath) {
|
||||
if err := fileOp.DeleteFile(configPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
sitePath := GteSiteDir(website.Alias)
|
||||
sitePath := GetSiteDir(website.Alias)
|
||||
if fileOp.Stat(sitePath) {
|
||||
xpack.RemoveTamper(website.Alias)
|
||||
_ = fileOp.DeleteDir(sitePath)
|
||||
@@ -694,6 +748,7 @@ func applySSL(website *model.Website, websiteSSL model.WebsiteSSL, req request.W
|
||||
}
|
||||
httpPorts := make(map[int]struct{})
|
||||
httpsPorts := make(map[int]struct{})
|
||||
sslPort := 0
|
||||
|
||||
hasDefaultPort := false
|
||||
for _, domain := range domains {
|
||||
@@ -721,6 +776,7 @@ func applySSL(website *model.Website, websiteSSL model.WebsiteSSL, req request.W
|
||||
defaultHttpPortIPV6 := "[::]:" + defaultHttpPort
|
||||
|
||||
for port := range httpsPorts {
|
||||
sslPort = port
|
||||
portStr := strconv.Itoa(port)
|
||||
server.RemoveListenByBind(portStr)
|
||||
server.RemoveListenByBind("[::]:" + portStr)
|
||||
@@ -741,7 +797,7 @@ func applySSL(website *model.Website, websiteSSL model.WebsiteSSL, req request.W
|
||||
server.UpdateListen(defaultHttpPortIPV6, website.DefaultServer)
|
||||
}
|
||||
}
|
||||
server.AddHTTP2HTTPS()
|
||||
server.AddHTTP2HTTPS(sslPort)
|
||||
case constant.HTTPAlso:
|
||||
if hasDefaultPort {
|
||||
server.UpdateListen(defaultHttpPort, website.DefaultServer)
|
||||
@@ -880,9 +936,16 @@ func deleteWebsiteFolder(website *model.Website) error {
|
||||
if fileOp.Stat(siteFolder) {
|
||||
_ = fileOp.DeleteDir(siteFolder)
|
||||
}
|
||||
nginxFilePath := GetSitePath(*website, SiteConf)
|
||||
if fileOp.Stat(nginxFilePath) {
|
||||
_ = fileOp.DeleteFile(nginxFilePath)
|
||||
if website.Type == constant.Stream {
|
||||
steamFilePath := GetSitePath(*website, StreamConf)
|
||||
if fileOp.Stat(steamFilePath) {
|
||||
_ = fileOp.DeleteFile(steamFilePath)
|
||||
}
|
||||
} else {
|
||||
nginxFilePath := GetSitePath(*website, SiteConf)
|
||||
if fileOp.Stat(nginxFilePath) {
|
||||
_ = fileOp.DeleteFile(nginxFilePath)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1052,7 +1115,7 @@ func getWebsiteDomains(domains []request.WebsiteDomain, defaultHTTPPort, default
|
||||
if domain.Domain == "" {
|
||||
continue
|
||||
}
|
||||
if !common.IsValidDomain(domain.Domain) {
|
||||
if !common.IsValidNginxServerName(domain.Domain) {
|
||||
err = buserr.WithName("ErrDomainFormat", domain.Domain)
|
||||
return
|
||||
}
|
||||
@@ -1089,27 +1152,8 @@ func getWebsiteDomains(domains []request.WebsiteDomain, defaultHTTPPort, default
|
||||
addPorts = append(addPorts, port)
|
||||
continue
|
||||
}
|
||||
if existPorts, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithPort(port)); len(existPorts) == 0 {
|
||||
errMap := make(map[string]interface{})
|
||||
errMap["port"] = port
|
||||
appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithPort(port))
|
||||
if appInstall.ID > 0 {
|
||||
errMap["type"] = i18n.GetMsgByKey("TYPE_APP")
|
||||
errMap["name"] = appInstall.Name
|
||||
err = buserr.WithMap("ErrPortExist", errMap, nil)
|
||||
return
|
||||
}
|
||||
runtime, _ := runtimeRepo.GetFirst(context.Background(), runtimeRepo.WithPort(port))
|
||||
if runtime != nil {
|
||||
errMap["type"] = i18n.GetMsgByKey("TYPE_RUNTIME")
|
||||
errMap["name"] = runtime.Name
|
||||
err = buserr.WithMap("ErrPortExist", errMap, nil)
|
||||
return
|
||||
}
|
||||
if port != defaultHTTPsPort && common.ScanPort(port) {
|
||||
err = buserr.WithDetail("ErrPortInUsed", port, nil)
|
||||
return
|
||||
}
|
||||
if err = checkWebsitePort(defaultHTTPsPort, port, ""); err != nil {
|
||||
return
|
||||
}
|
||||
if existPorts, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(websiteID), websiteDomainRepo.WithPort(port)); len(existPorts) == 0 {
|
||||
addPorts = append(addPorts, port)
|
||||
@@ -1119,6 +1163,43 @@ func getWebsiteDomains(domains []request.WebsiteDomain, defaultHTTPPort, default
|
||||
return
|
||||
}
|
||||
|
||||
func checkWebsitePort(defaultHTTPsPort, port int, websiteType string) error {
|
||||
if existPorts, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithPort(port)); len(existPorts) > 0 {
|
||||
return nil
|
||||
}
|
||||
if websiteType == constant.Stream {
|
||||
websites, _ := websiteRepo.List(websiteRepo.WithType(constant.Stream))
|
||||
for _, website := range websites {
|
||||
ports := strings.Split(website.StreamPorts, ",")
|
||||
for _, p := range ports {
|
||||
pInt, _ := strconv.Atoi(p)
|
||||
if pInt == port {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
errMap := make(map[string]interface{})
|
||||
errMap["port"] = port
|
||||
appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithPort(port))
|
||||
if appInstall.ID > 0 {
|
||||
errMap["type"] = i18n.GetMsgByKey("TYPE_APP")
|
||||
errMap["name"] = appInstall.Name
|
||||
return buserr.WithMap("ErrPortExist", errMap, nil)
|
||||
}
|
||||
runtime, _ := runtimeRepo.GetFirst(context.Background(), runtimeRepo.WithPort(port))
|
||||
if runtime != nil {
|
||||
errMap["type"] = i18n.GetMsgByKey("TYPE_RUNTIME")
|
||||
errMap["name"] = runtime.Name
|
||||
return buserr.WithMap("ErrPortExist", errMap, nil)
|
||||
}
|
||||
if port != defaultHTTPsPort && common.ScanPort(port) {
|
||||
return buserr.WithDetail("ErrPortInUsed", port, nil)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func saveCertificateFile(websiteSSL *model.WebsiteSSL, logger *log.Logger) {
|
||||
if websiteSSL.PushDir {
|
||||
fileOp := files.NewFileOp()
|
||||
@@ -1280,7 +1361,7 @@ func GetWebSiteRootDir() string {
|
||||
return dir
|
||||
}
|
||||
|
||||
func GteSiteDir(alias string) string {
|
||||
func GetSiteDir(alias string) string {
|
||||
return path.Join(GetWebSiteRootDir(), "sites", alias)
|
||||
}
|
||||
|
||||
@@ -1304,48 +1385,68 @@ const (
|
||||
SitePathAuthBasicDir = "SitePathAuthBasicDir"
|
||||
SiteUpstreamDir = "SiteUpstreamDir"
|
||||
SiteCorsPath = "SiteCorsPath"
|
||||
StreamDir = "StreamDir"
|
||||
StreamConf = "StreamConf"
|
||||
)
|
||||
|
||||
func GetWebsiteConfigPath(website model.Website) string {
|
||||
if website.Type != constant.Stream {
|
||||
return GetSitePath(website, SiteConf)
|
||||
}
|
||||
return GetSitePath(website, StreamConf)
|
||||
}
|
||||
|
||||
func GetSitePath(website model.Website, confType string) string {
|
||||
switch confType {
|
||||
case SiteConf:
|
||||
return path.Join(GetWebSiteRootDir(), "conf.d", website.Alias+".conf")
|
||||
case StreamConf:
|
||||
return path.Join(GetWebSiteRootDir(), "stream.d", website.Alias+".conf")
|
||||
case SiteAccessLog:
|
||||
return path.Join(GteSiteDir(website.Alias), "log", "access.log")
|
||||
return path.Join(GetSiteDir(website.Alias), "log", "access.log")
|
||||
case SiteErrorLog:
|
||||
return path.Join(GteSiteDir(website.Alias), "log", "error.log")
|
||||
return path.Join(GetSiteDir(website.Alias), "log", "error.log")
|
||||
case SiteDir:
|
||||
return GteSiteDir(website.Alias)
|
||||
return GetSiteDir(website.Alias)
|
||||
case SiteIndexDir:
|
||||
return path.Join(GteSiteDir(website.Alias), "index")
|
||||
return path.Join(GetSiteDir(website.Alias), "index")
|
||||
case SiteCacheDir:
|
||||
return path.Join(GteSiteDir(website.Alias), "cache")
|
||||
return path.Join(GetSiteDir(website.Alias), "cache")
|
||||
case SiteProxyDir:
|
||||
return path.Join(GteSiteDir(website.Alias), "proxy")
|
||||
return path.Join(GetSiteDir(website.Alias), "proxy")
|
||||
case SiteSSLDir:
|
||||
return path.Join(GteSiteDir(website.Alias), "ssl")
|
||||
return path.Join(GetSiteDir(website.Alias), "ssl")
|
||||
case SiteReWritePath:
|
||||
return path.Join(GteSiteDir(website.Alias), "rewrite", website.Alias+".conf")
|
||||
return path.Join(GetSiteDir(website.Alias), "rewrite", website.Alias+".conf")
|
||||
case SiteRedirectDir:
|
||||
return path.Join(GteSiteDir(website.Alias), "redirect")
|
||||
return path.Join(GetSiteDir(website.Alias), "redirect")
|
||||
case SiteRootAuthBasicPath:
|
||||
return path.Join(GteSiteDir(website.Alias), "auth_basic", "auth.pass")
|
||||
return path.Join(GetSiteDir(website.Alias), "auth_basic", "auth.pass")
|
||||
case SitePathAuthBasicDir:
|
||||
return path.Join(GteSiteDir(website.Alias), "path_auth")
|
||||
return path.Join(GetSiteDir(website.Alias), "path_auth")
|
||||
case SiteUpstreamDir:
|
||||
return path.Join(GteSiteDir(website.Alias), "upstream")
|
||||
return path.Join(GetSiteDir(website.Alias), "upstream")
|
||||
case SiteCorsPath:
|
||||
return path.Join(GteSiteDir(website.Alias), "cors", "cors.conf")
|
||||
return path.Join(GetSiteDir(website.Alias), "cors", "cors.conf")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func GetConfDir(website model.Website) string {
|
||||
if website.Type != constant.Stream {
|
||||
return GetOpenrestyDir(SiteConf)
|
||||
}
|
||||
return GetOpenrestyDir(StreamDir)
|
||||
}
|
||||
|
||||
func GetOpenrestyDir(confType string) string {
|
||||
switch confType {
|
||||
case WebsiteRootDir:
|
||||
return GetWebSiteRootDir()
|
||||
case SiteConfDir:
|
||||
return path.Join(GetWebSiteRootDir(), "conf.d")
|
||||
case StreamDir:
|
||||
return path.Join(GetWebSiteRootDir(), "stream.d")
|
||||
case SitesRootDir:
|
||||
return path.Join(GetWebSiteRootDir(), "sites")
|
||||
case DefaultDir:
|
||||
@@ -1619,3 +1720,65 @@ func getNginxUpstreamServers(upstreamServers []*components.UpstreamServer) []dto
|
||||
}
|
||||
return servers
|
||||
}
|
||||
|
||||
func getManualWebsiteSSL(req request.WebsiteHTTPSOp) (model.WebsiteSSL, error) {
|
||||
var websiteSSL model.WebsiteSSL
|
||||
var (
|
||||
certificate string
|
||||
privateKey string
|
||||
)
|
||||
switch req.ImportType {
|
||||
case "paste":
|
||||
certificate = req.Certificate
|
||||
privateKey = req.PrivateKey
|
||||
case "local":
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(req.PrivateKeyPath) {
|
||||
return websiteSSL, buserr.New("ErrSSLKeyNotFound")
|
||||
}
|
||||
if !fileOp.Stat(req.CertificatePath) {
|
||||
return websiteSSL, buserr.New("ErrSSLCertificateNotFound")
|
||||
}
|
||||
if content, err := fileOp.GetContent(req.PrivateKeyPath); err != nil {
|
||||
return websiteSSL, err
|
||||
} else {
|
||||
privateKey = string(content)
|
||||
}
|
||||
if content, err := fileOp.GetContent(req.CertificatePath); err != nil {
|
||||
return websiteSSL, err
|
||||
} else {
|
||||
certificate = string(content)
|
||||
}
|
||||
}
|
||||
|
||||
privateKeyCertBlock, _ := pem.Decode([]byte(privateKey))
|
||||
if privateKeyCertBlock == nil {
|
||||
return websiteSSL, buserr.New("ErrSSLKeyFormat")
|
||||
}
|
||||
|
||||
certBlock, _ := pem.Decode([]byte(certificate))
|
||||
if certBlock == nil {
|
||||
return websiteSSL, buserr.New("ErrSSLCertificateFormat")
|
||||
}
|
||||
cert, err := x509.ParseCertificate(certBlock.Bytes)
|
||||
if err != nil {
|
||||
return websiteSSL, err
|
||||
}
|
||||
websiteSSL.ExpireDate = cert.NotAfter
|
||||
websiteSSL.StartDate = cert.NotBefore
|
||||
websiteSSL.Type = cert.Issuer.CommonName
|
||||
if len(cert.Issuer.Organization) > 0 {
|
||||
websiteSSL.Organization = cert.Issuer.Organization[0]
|
||||
} else {
|
||||
websiteSSL.Organization = cert.Issuer.CommonName
|
||||
}
|
||||
if len(cert.DNSNames) > 0 {
|
||||
websiteSSL.PrimaryDomain = cert.DNSNames[0]
|
||||
websiteSSL.Domains = strings.Join(cert.DNSNames, ",")
|
||||
}
|
||||
websiteSSL.Provider = constant.Manual
|
||||
websiteSSL.PrivateKey = privateKey
|
||||
websiteSSL.Pem = certificate
|
||||
websiteSSL.Status = constant.SSLReady
|
||||
return websiteSSL, nil
|
||||
}
|
||||
|
||||
+29
-16
@@ -1,11 +1,9 @@
|
||||
package task
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
@@ -13,6 +11,7 @@ import (
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/buserr"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/repo"
|
||||
@@ -29,8 +28,7 @@ type Task struct {
|
||||
|
||||
Name string
|
||||
TaskID string
|
||||
Logger *log.Logger
|
||||
Writer *bufio.Writer
|
||||
Logger *logrus.Logger
|
||||
SubTasks []*SubTask
|
||||
Rollbacks []RollbackFunc
|
||||
logFile *os.File
|
||||
@@ -98,6 +96,7 @@ const (
|
||||
TaskScopeCustomAppstore = "CustomAppstore"
|
||||
TaskScopeTamper = "Tamper"
|
||||
TaskScopeFileConvert = "Convert"
|
||||
TaskScopeTask = "Task"
|
||||
)
|
||||
|
||||
func GetTaskName(resourceName, operate, scope string) string {
|
||||
@@ -138,12 +137,13 @@ func NewTask(name, operate, taskScope, taskID string, resourceID uint) (*Task, e
|
||||
}
|
||||
}
|
||||
logPath := path.Join(global.Dir.TaskDir, taskScope, taskID+".log")
|
||||
file, err := os.OpenFile(logPath, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, constant.FilePerm)
|
||||
logger := logrus.New()
|
||||
logger.SetFormatter(&SimpleFormatter{})
|
||||
logFile, err := os.OpenFile(logPath, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, constant.FilePerm)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open log file: %w", err)
|
||||
}
|
||||
writer := bufio.NewWriter(file)
|
||||
logger := log.New(file, "", log.LstdFlags)
|
||||
logger.SetOutput(logFile)
|
||||
taskModel := &model.Task{
|
||||
ID: taskID,
|
||||
Name: name,
|
||||
@@ -154,9 +154,9 @@ func NewTask(name, operate, taskScope, taskID string, resourceID uint) (*Task, e
|
||||
Operate: operate,
|
||||
}
|
||||
taskRepo := repo.NewITaskRepo()
|
||||
ctx, cancle := context.WithCancel(context.Background())
|
||||
global.TaskCtxMap[taskID] = cancle
|
||||
task := &Task{TaskCtx: ctx, Name: name, logFile: file, Logger: logger, taskRepo: taskRepo, Task: taskModel, Writer: writer}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
global.TaskCtxMap[taskID] = cancel
|
||||
task := &Task{TaskCtx: ctx, Name: name, logFile: logFile, Logger: logger, taskRepo: taskRepo, Task: taskModel}
|
||||
return task, nil
|
||||
}
|
||||
|
||||
@@ -175,16 +175,18 @@ func ReNewTask(name, operate, taskScope, taskID string, resourceID uint) (*Task,
|
||||
return nil, fmt.Errorf("failed to create log directory: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
logPath := path.Join(global.Dir.TaskDir, taskScope, taskID+".log")
|
||||
file, err := os.OpenFile(logPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, constant.FilePerm)
|
||||
logger := logrus.New()
|
||||
logger.SetFormatter(&SimpleFormatter{})
|
||||
logFile, err := os.OpenFile(logPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, constant.FilePerm)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open log file: %w", err)
|
||||
}
|
||||
writer := bufio.NewWriter(file)
|
||||
logger := log.New(file, "", log.LstdFlags)
|
||||
logger.SetOutput(logFile)
|
||||
logger.Print("\n --------------------------------------------------- \n")
|
||||
taskItem.Status = constant.StatusExecuting
|
||||
task := &Task{Name: name, logFile: file, Logger: logger, taskRepo: taskRepo, Task: &taskItem, Writer: writer}
|
||||
task := &Task{Name: name, logFile: logFile, Logger: logger, taskRepo: taskRepo, Task: &taskItem}
|
||||
task.updateTask(&taskItem)
|
||||
return task, nil
|
||||
}
|
||||
@@ -226,6 +228,9 @@ func (s *SubTask) Execute() error {
|
||||
s.RootTask.Log(i18n.GetWithName("TaskRetry", strconv.Itoa(i)))
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), s.Timeout)
|
||||
if s.Timeout == 0 {
|
||||
ctx, cancel = context.WithCancel(context.Background())
|
||||
}
|
||||
defer cancel()
|
||||
|
||||
done := make(chan error)
|
||||
@@ -325,7 +330,7 @@ func (t *Task) LogFailed(msg string) {
|
||||
}
|
||||
|
||||
func (t *Task) LogFailedWithErr(msg string, err error) {
|
||||
t.Logger.Printf("%s %s : %s\n", msg, i18n.GetMsgByKey("Failed"), err.Error())
|
||||
t.Logger.Printf("%s %s : %s", msg, i18n.GetMsgByKey("Failed"), err.Error())
|
||||
}
|
||||
|
||||
func (t *Task) LogSuccess(msg string) {
|
||||
@@ -336,7 +341,7 @@ func (t *Task) LogSuccessF(format string, v ...any) {
|
||||
}
|
||||
|
||||
func (t *Task) LogStart(msg string) {
|
||||
t.Logger.Printf("%s%s\n", i18n.GetMsgByKey("Start"), msg)
|
||||
t.Logger.Printf("%s%s", i18n.GetMsgByKey("Start"), msg)
|
||||
}
|
||||
|
||||
func (t *Task) LogWithOps(operate, msg string) {
|
||||
@@ -350,3 +355,11 @@ func (t *Task) LogSuccessWithOps(operate, msg string) {
|
||||
func (t *Task) LogFailedWithOps(operate, msg string, err error) {
|
||||
t.Logger.Printf("%s%s%s : %s ", i18n.GetMsgByKey(operate), msg, i18n.GetMsgByKey("Failed"), err.Error())
|
||||
}
|
||||
|
||||
type SimpleFormatter struct{}
|
||||
|
||||
func (f *SimpleFormatter) Format(entry *logrus.Entry) ([]byte, error) {
|
||||
timestamp := entry.Time.Format("2006/01/02 15:04:05")
|
||||
message := fmt.Sprintf("%s %s\n", timestamp, entry.Message)
|
||||
return []byte(message), nil
|
||||
}
|
||||
|
||||
@@ -3,21 +3,21 @@
|
||||
"name": "amqp",
|
||||
"check": "amqp",
|
||||
"file": "amqp.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "apcu",
|
||||
"check": "apcu",
|
||||
"file": "apcu.so",
|
||||
"versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "bcmath",
|
||||
"check": "bcmath",
|
||||
"file": "bcmath.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
@@ -31,7 +31,7 @@
|
||||
"name": "opcache",
|
||||
"check": "Zend OPcache",
|
||||
"file": "opcache.so",
|
||||
"versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
@@ -45,21 +45,21 @@
|
||||
"name": "memcached",
|
||||
"check": "memcached",
|
||||
"file": "memcached.so",
|
||||
"versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "redis",
|
||||
"check": "redis",
|
||||
"file": "redis.so",
|
||||
"versions": [ "56", "70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": [ "56", "70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "mcrypt",
|
||||
"check": "mcrypt",
|
||||
"file": "mcrypt.so",
|
||||
"versions": ["70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
|
||||
@@ -67,35 +67,35 @@
|
||||
"name": "imagick",
|
||||
"check": "imagick",
|
||||
"file": "imagick.so",
|
||||
"versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82","83","84"],
|
||||
"versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82","83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "xdebug",
|
||||
"check": "xdebug",
|
||||
"file": "xdebug.so",
|
||||
"versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "imap",
|
||||
"check": "imap",
|
||||
"file": "imap.so",
|
||||
"versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "exif",
|
||||
"check": "exif",
|
||||
"file": "exif.so",
|
||||
"versions": [ "56", "70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": [ "56", "70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "intl",
|
||||
"check": "intl",
|
||||
"file": "intl.so",
|
||||
"versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
@@ -109,42 +109,42 @@
|
||||
"name": "swoole",
|
||||
"check": "swoole",
|
||||
"file": "swoole.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "zstd",
|
||||
"check": "zstd",
|
||||
"file": "zstd.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "xlswriter",
|
||||
"check": "xlswriter",
|
||||
"file": "xlswriter.so",
|
||||
"versions": ["70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "oci8",
|
||||
"check": "oci8",
|
||||
"file": "oci8.so",
|
||||
"versions": ["70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "pdo_oci",
|
||||
"check": "pdo_oci",
|
||||
"file": "pdo_oci.so",
|
||||
"versions": ["70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "pdo_sqlsrv",
|
||||
"check": "pdo_sqlsrv",
|
||||
"file": "pdo_sqlsrv.so",
|
||||
"versions": ["70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
@@ -158,77 +158,77 @@
|
||||
"name": "yaf",
|
||||
"check": "yaf",
|
||||
"file": "yaf.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "mongodb",
|
||||
"check": "mongodb",
|
||||
"file": "mongodb.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "yac",
|
||||
"check": "yac",
|
||||
"file": "yac.so",
|
||||
"versions": ["70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "pgsql",
|
||||
"check": "pgsql",
|
||||
"file": "pgsql.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "ssh2",
|
||||
"check": "ssh2",
|
||||
"file": "ssh2.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "grpc",
|
||||
"check": "grpc",
|
||||
"file": "grpc.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "xhprof",
|
||||
"check": "xhprof",
|
||||
"file": "xhprof.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "protobuf",
|
||||
"check": "protobuf",
|
||||
"file": "protobuf.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "pdo_pgsql",
|
||||
"check": "pdo_pgsql",
|
||||
"file": "pdo_pgsql.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "snmp",
|
||||
"check": "snmp",
|
||||
"file": "snmp.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "ldap",
|
||||
"check": "ldap",
|
||||
"file": "ldap.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
@@ -242,42 +242,42 @@
|
||||
"name": "enchant",
|
||||
"check": "enchant",
|
||||
"file": "enchant.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "pspell",
|
||||
"check": "pspell",
|
||||
"file": "pspell.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "bz2",
|
||||
"check": "bz2",
|
||||
"file": "bz2.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "sysvshm",
|
||||
"check": "sysvshm",
|
||||
"file": "sysvshm.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "calendar",
|
||||
"check": "calendar",
|
||||
"file": "calendar.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "gmp",
|
||||
"check": "gmp",
|
||||
"file": "gmp.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
@@ -291,91 +291,91 @@
|
||||
"name": "sysvmsg",
|
||||
"check": "sysvmsg",
|
||||
"file": "sysvmsg.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "igbinary",
|
||||
"check": "igbinary",
|
||||
"file": "igbinary.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "zmq",
|
||||
"check": "zmq",
|
||||
"file": "zmq.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "smbclient",
|
||||
"check": "smbclient",
|
||||
"file": "smbclient.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "event",
|
||||
"check": "event",
|
||||
"file": "event.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "mailparse",
|
||||
"check": "mailparse",
|
||||
"file": "mailparse.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "yaml",
|
||||
"check": "yaml",
|
||||
"file": "yaml.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "sg16",
|
||||
"check": "SourceGuardian",
|
||||
"file": "sourceguardian.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "mysqli",
|
||||
"check": "mysqli",
|
||||
"file": "mysqli.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "pdo_mysql",
|
||||
"check": "pdo_mysql",
|
||||
"file": "pdo_mysql.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "zip",
|
||||
"check": "zip",
|
||||
"file": "zip.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "shmop",
|
||||
"check": "shmop",
|
||||
"file": "shmop.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "gd",
|
||||
"check": "gd",
|
||||
"file": "gd.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
|
||||
@@ -383,49 +383,56 @@
|
||||
"name": "pcntl",
|
||||
"check": "pcntl",
|
||||
"file": "pcntl.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "sodium",
|
||||
"check": "sodium",
|
||||
"file": "sodium.so",
|
||||
"versions": ["70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "gettext",
|
||||
"check": "gettext",
|
||||
"file": "gettext.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "soap",
|
||||
"check": "soap",
|
||||
"file": "soap.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "sysvsem",
|
||||
"check": "sysvsem",
|
||||
"file": "sysvsem.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "sockets",
|
||||
"check": "sockets",
|
||||
"file": "sockets.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "xmlrpc",
|
||||
"check": "xmlrpc",
|
||||
"file": "xmlrpc.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
},
|
||||
{
|
||||
"name": "lz4",
|
||||
"check": "lz4",
|
||||
"file": "lz4.so",
|
||||
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84","85"],
|
||||
"installed": false
|
||||
}
|
||||
]
|
||||
|
||||
@@ -11,7 +11,6 @@ location ^~ /test {
|
||||
proxy_http_version 1.1;
|
||||
|
||||
add_header X-Cache $upstream_cache_status;
|
||||
add_header Cache-Control no-cache;
|
||||
proxy_ssl_server_name off;
|
||||
proxy_ssl_name $proxy_host;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
server {
|
||||
proxy_pass mysql_cluster;
|
||||
access_log /www/sites/domain/log/access.log streamlog;
|
||||
error_log /www/sites/domain/log/error.log;
|
||||
}
|
||||
@@ -4,8 +4,9 @@ const (
|
||||
WebRunning = "Running"
|
||||
WebStopped = "Stopped"
|
||||
|
||||
ProtocolHTTP = "HTTP"
|
||||
ProtocolHTTPS = "HTTPS"
|
||||
ProtocolHTTP = "HTTP"
|
||||
ProtocolHTTPS = "HTTPS"
|
||||
ProtocolStream = "TCP/UDP"
|
||||
|
||||
NewApp = "new"
|
||||
InstalledApp = "installed"
|
||||
@@ -15,6 +16,7 @@ const (
|
||||
Proxy = "proxy"
|
||||
Runtime = "runtime"
|
||||
Subsite = "subsite"
|
||||
Stream = "stream"
|
||||
|
||||
SSLExisted = "existed"
|
||||
SSLAuto = "auto"
|
||||
@@ -29,6 +31,7 @@ const (
|
||||
|
||||
StartWeb = "start"
|
||||
StopWeb = "stop"
|
||||
SetHttps = "setHttps"
|
||||
|
||||
HTTPSOnly = "HTTPSOnly"
|
||||
HTTPAlso = "HTTPAlso"
|
||||
|
||||
@@ -31,7 +31,7 @@ func (ssl *ssl) Run() {
|
||||
}
|
||||
expireDate := s.ExpireDate.In(nyc)
|
||||
sub := expireDate.Sub(now)
|
||||
if sub.Hours() < 720 {
|
||||
if s.IsIp && sub.Hours() < 72 || !s.IsIp && sub.Hours() < 720 {
|
||||
global.LOG.Infof("Update the SSL certificate for the [%s] domain", s.PrimaryDomain)
|
||||
if s.Provider == constant.SelfSigned {
|
||||
caService := service.NewIWebsiteCAService()
|
||||
|
||||
+49
-53
@@ -4,12 +4,7 @@ go 1.24.9
|
||||
|
||||
require (
|
||||
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
|
||||
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/aws/aws-sdk-go v1.55.0
|
||||
github.com/compose-spec/compose-go/v2 v2.9.0
|
||||
github.com/creack/pty v1.1.24
|
||||
github.com/docker/compose/v2 v2.40.2
|
||||
@@ -18,13 +13,12 @@ require (
|
||||
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.29.0
|
||||
github.com/go-acme/lego/v4 v4.30.1
|
||||
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-resty/resty/v2 v2.17.0
|
||||
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
|
||||
@@ -34,6 +28,7 @@ require (
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/klauspost/compress v1.18.1
|
||||
github.com/mholt/archiver/v4 v4.0.0-alpha.8
|
||||
github.com/miekg/dns v1.1.69
|
||||
github.com/minio/minio-go/v7 v7.0.74
|
||||
github.com/nicksnyder/go-i18n/v2 v2.4.0
|
||||
github.com/opencontainers/image-spec v1.1.1
|
||||
@@ -43,7 +38,7 @@ require (
|
||||
github.com/pkg/sftp v1.13.6
|
||||
github.com/qiniu/go-sdk/v7 v7.21.1
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/shirou/gopsutil/v4 v4.25.7
|
||||
github.com/shirou/gopsutil/v4 v4.25.11
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/spf13/afero v1.11.0
|
||||
github.com/spf13/cobra v1.10.1
|
||||
@@ -52,11 +47,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.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
|
||||
golang.org/x/crypto v0.46.0
|
||||
golang.org/x/net v0.48.0
|
||||
golang.org/x/oauth2 v0.34.0
|
||||
golang.org/x/sys v0.39.0
|
||||
golang.org/x/text v0.32.0
|
||||
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38
|
||||
gopkg.in/ini.v1 v1.67.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
@@ -72,26 +67,26 @@ require (
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect
|
||||
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.13 // indirect
|
||||
github.com/alibabacloud-go/debug v1.0.1 // indirect
|
||||
github.com/alibabacloud-go/tea v1.3.13 // indirect
|
||||
github.com/alibabacloud-go/tea v1.3.14 // indirect
|
||||
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/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 v1.41.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.16 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.16 // 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/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.16 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.62.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.0.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.30.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.41.5 // indirect
|
||||
github.com/aws/smithy-go v1.24.0 // indirect
|
||||
github.com/baidubce/bce-sdk-go v0.9.254 // 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
|
||||
@@ -122,7 +117,7 @@ require (
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/dsnet/compress v0.0.1 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/ebitengine/purego v0.8.4 // indirect
|
||||
github.com/ebitengine/purego v0.9.1 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fvbommel/sortorder v1.1.0 // indirect
|
||||
@@ -130,7 +125,7 @@ require (
|
||||
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.7.0 // indirect
|
||||
github.com/go-acme/esa-20240910/v2 v2.40.1 // indirect
|
||||
github.com/go-acme/esa-20240910/v2 v2.40.3 // 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
|
||||
@@ -141,6 +136,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.13.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
@@ -152,9 +148,9 @@ require (
|
||||
github.com/h2non/filetype v1.1.1 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-version v1.7.0 // indirect
|
||||
github.com/hashicorp/go-version v1.8.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.178 // indirect
|
||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.180 // 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
|
||||
@@ -162,6 +158,7 @@ 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
|
||||
@@ -174,7 +171,6 @@ require (
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/mattn/go-shellwords v1.0.12 // indirect
|
||||
github.com/miekg/dns v1.1.68 // indirect
|
||||
github.com/minio/md5-simd v1.1.2 // indirect
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
@@ -206,7 +202,7 @@ require (
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.15 // indirect
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/rs/xid v1.5.0 // indirect
|
||||
@@ -218,11 +214,11 @@ 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.3.3 // indirect
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.12 // 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
|
||||
github.com/tklauser/numcpus v0.10.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.16 // indirect
|
||||
github.com/tklauser/numcpus v0.11.0 // indirect
|
||||
github.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323 // indirect
|
||||
github.com/tonistiigi/fsutil v0.0.0-20250605211040-586307ad452f // indirect
|
||||
github.com/tonistiigi/go-csvvalue v0.0.0-20240814133006-030d3b2625d0 // indirect
|
||||
@@ -231,36 +227,36 @@ 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.229 // indirect
|
||||
github.com/volcengine/volc-sdk-golang v1.0.230 // 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
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
||||
go.opentelemetry.io/otel v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
go4.org v0.0.0-20200411211856-f5505b9728dd // indirect
|
||||
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.18.0 // indirect
|
||||
golang.org/x/mod v0.30.0 // indirect
|
||||
golang.org/x/sync v0.19.0 // indirect
|
||||
golang.org/x/time v0.14.0 // indirect
|
||||
golang.org/x/tools v0.38.0 // indirect
|
||||
golang.org/x/tools v0.39.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-20251103181224-f26f9409b101 // indirect
|
||||
google.golang.org/grpc v1.76.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251124214823-79d6a2a48846 // indirect
|
||||
google.golang.org/grpc v1.77.0 // indirect
|
||||
google.golang.org/protobuf v1.36.10 // indirect
|
||||
modernc.org/libc v1.66.1 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
|
||||
+100
-107
@@ -100,8 +100,9 @@ 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.13 h1:WhGy6LIXaMbBM6VBYcsDCz6K/TPsT1Ri2hPmmZffZ94=
|
||||
github.com/alibabacloud-go/tea v1.3.13/go.mod h1:A560v/JTQ1n5zklt2BEpurJzZTI8TUT+Psg2drWlxRg=
|
||||
github.com/alibabacloud-go/tea v1.3.14 h1:/Uzj5ZCFPpbPR+Bs7jfzsyXkYIVsi5TOIuQNOWwc/9c=
|
||||
github.com/alibabacloud-go/tea v1.3.14/go.mod h1:A560v/JTQ1n5zklt2BEpurJzZTI8TUT+Psg2drWlxRg=
|
||||
github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE=
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.5/go.mod h1:dL6vbUT35E4F4bFTHL845eUloqaerYBYPsdWR2/jhe4=
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.7 h1:WDx5qW3Xa5ZgJ1c8NfqJkF6w+AU5wB8835UdhPr6Ax0=
|
||||
@@ -127,53 +128,43 @@ 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 v1.41.0 h1:tNvqh1s+v0vFYdA1xq0aOJH+Y5cRyZ5upu6roPgPKd4=
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.0/go.mod h1:MayyLB8y+buD9hZqkCW3kX1AKq07Y5pXxtgB+rRFhz0=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.5 h1:pz3duhAfUgnxbtVhIK39PGF/AHYyrzGEyRD9Og0QrE8=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.5/go.mod h1:xmDjzSUs/d0BB7ClzYPAZMmgQdrodNjPPhd6bGASwoE=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.5 h1:xMo63RlqP3ZZydpJDMBsH9uJ10hgHYfQFIk1cHDXrR4=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.5/go.mod h1:hhbH6oRcou+LpXfA/0vPElh/e0M3aFeOblE1sssAAEk=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16 h1:80+uETIWS1BqjnN9uJ0dBUaETh+P1XwFy5vwHwK5r9k=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16/go.mod h1:wOOsYuxYuB/7FlnVtzeBYRcjSRtQpAW0hCP7tIULMwo=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.16 h1:rgGwPzb82iBYSvHMHXc8h9mRoOUBZIGFgKb9qniaZZc=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.16/go.mod h1:L/UxsGeKpGoIj6DxfhOWHWQ/kGKcd4I1VncE4++IyKA=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.16 h1:1jtGzuV7c82xnqOVfx2F0xmJcOw5374L7N6juGW6x6U=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.16/go.mod h1:M2E5OQf+XLe+SZGmmpaI2yy+J326aFf6/+54PoxSANc=
|
||||
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/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 h1:0ryTNEdJbzUCEWkVXEXoqlXV72J5keC1GvILMOuD00E=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4/go.mod h1:HQ4qwNZh32C3CBeO6iJLQlgtMzqeG17ziAA/3KDJFow=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.16 h1:oHjJHeUy0ImIV0bsrX0X91GkV5nJAyv1l1CC9lnO0TI=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.16/go.mod h1:iRSNGgOYmiYwSCXxXaKb9HfOEj40+oTKn8pTxMlYkRM=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.62.0 h1:80pDB3Tpmb2RCSZORrK9/3iQxsd+w6vSzVqpT1FGiwE=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.62.0/go.mod h1:6EZUGGNLPLh5Unt30uEoA+KQcByERfXIkax9qrc80nA=
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.0.4 h1:HpI7aMmJ+mm1wkSHIA2t5EaFFv5EFYXePW30p1EIrbQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.0.4/go.mod h1:C5RdGMYGlfM0gYq/tifqgn4EbyX99V15P2V3R+VHbQU=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.30.7 h1:eYnlt6QxnFINKzwxP5/Ucs1vkG7VT3Iezmvfgc2waUw=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.30.7/go.mod h1:+fWt2UHSb4kS7Pu8y+BMBvJF0EWx+4H0hzNwtDNRTrg=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12 h1:AHDr0DaHIAo8c9t1emrzAlVDFp+iMMKnPdYy6XO4MCE=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12/go.mod h1:GQ73XawFFiWxyWXMHWfhiomvP3tXtdNar/fi8z18sx0=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.41.5 h1:SciGFVNZ4mHdm7gpD1dgZYnCuVdX1s+lFTg4+4DOy70=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.41.5/go.mod h1:iW40X4QBmUxdP+fZNOpfmkdMZqsovezbAeO+Ubiv2pk=
|
||||
github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
|
||||
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/aws/smithy-go v1.24.0 h1:LpilSUItNPFr1eY85RYgTIg5eIEPtvFbskaFcmmIUnk=
|
||||
github.com/aws/smithy-go v1.24.0/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0=
|
||||
github.com/baidubce/bce-sdk-go v0.9.254 h1:A7GtBOt7z2lnV7fqlZPZefhcBFg7z6iliUAhEOiIhoE=
|
||||
github.com/baidubce/bce-sdk-go v0.9.254/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=
|
||||
@@ -308,8 +299,8 @@ github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5m
|
||||
github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw=
|
||||
github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||
github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A=
|
||||
github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
@@ -354,10 +345,10 @@ github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GM
|
||||
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
|
||||
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/esa-20240910/v2 v2.40.3 h1:xXOMRex148wKEHbv7Izn73/HdAxSmz5GOaF4HdnqN+M=
|
||||
github.com/go-acme/esa-20240910/v2 v2.40.3/go.mod h1:ZYdN9EN9ikn26SNapxCVjZ65pHT/1qm4fzuJ7QGVX6g=
|
||||
github.com/go-acme/lego/v4 v4.30.1 h1:tmb6U0lvy8Mc3lQbqKwTat7oAhE8FUYNJ3D0gSg6pJU=
|
||||
github.com/go-acme/lego/v4 v4.30.1/go.mod h1:V7m/Ip+EeFkjOe028+zeH+SwWtESxw1LHelwMIfAjm4=
|
||||
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=
|
||||
@@ -402,8 +393,8 @@ github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc
|
||||
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
||||
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
|
||||
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||
github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM=
|
||||
github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA=
|
||||
github.com/go-resty/resty/v2 v2.17.0 h1:pW9DeXcaL4Rrym4EZ8v7L19zZiIlWPg5YXAcVmt+gN0=
|
||||
github.com/go-resty/resty/v2 v2.17.0/go.mod h1:kCKZ3wWmwJaNc7S29BRtUhJwy7iqmn+2mLtQrOyQlVA=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
@@ -551,8 +542,8 @@ github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdv
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
|
||||
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4=
|
||||
github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
@@ -563,8 +554,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.178 h1:eNVkjzdPMgM2qih9aECiFUI8S9zgpOwXxeBPAwQqtvU=
|
||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.178/go.mod h1:M+yna96Fx9o5GbIUnF3OvVvQGjgfVSyeJbV9Yb1z/wI=
|
||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.180 h1:uia+R3K1izQRGpxTV+bS4q3/ueMW7ProAMWqM6OlqOU=
|
||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.180/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=
|
||||
@@ -598,7 +589,9 @@ 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=
|
||||
@@ -687,8 +680,8 @@ github.com/mholt/archiver/v4 v4.0.0-alpha.8/go.mod h1:5f7FUYGXdJWUjESffJaYR4R60V
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
|
||||
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
|
||||
github.com/miekg/dns v1.1.68 h1:jsSRkNozw7G/mnmXULynzMNIsgY2dHC8LO6U6Ij2JEA=
|
||||
github.com/miekg/dns v1.1.68/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps=
|
||||
github.com/miekg/dns v1.1.69 h1:Kb7Y/1Jo+SG+a2GtfoFUfDkG//csdRPwRLkCsxDG9Sc=
|
||||
github.com/miekg/dns v1.1.69/go.mod h1:7OyjD9nEba5OkqQ/hB4fy3PIoxafSZJtducccIelz3g=
|
||||
github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
|
||||
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
||||
github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
|
||||
@@ -829,8 +822,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
|
||||
@@ -875,8 +868,8 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
@@ -894,8 +887,8 @@ github.com/secure-systems-lab/go-securesystemslib v0.6.0 h1:T65atpAVCJQK14UA57LM
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.6.0/go.mod h1:8Mtpo9JKks/qhPG4HGZ2LGMvrPbzuxwfz/f/zLfEWkk=
|
||||
github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI=
|
||||
github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE=
|
||||
github.com/shirou/gopsutil/v4 v4.25.7 h1:bNb2JuqKuAu3tRlPv5piSmBZyMfecwQ+t/ILq+1JqVM=
|
||||
github.com/shirou/gopsutil/v4 v4.25.7/go.mod h1:XV/egmwJtd3ZQjBpJVY5kndsiOO4IRqy9TQnmm6VP7U=
|
||||
github.com/shirou/gopsutil/v4 v4.25.11 h1:X53gB7muL9Gnwwo2evPSE+SfOrltMoR6V3xJAXZILTY=
|
||||
github.com/shirou/gopsutil/v4 v4.25.11/go.mod h1:EivAfP5x2EhLp2ovdpKSozecVXn1TmuG7SMzs/Wh4PU=
|
||||
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
@@ -948,8 +941,8 @@ 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.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/common v1.3.12 h1:/ABtv4x4FSGxGW0d6Sc88iQn6Up2LalWKwt/Tj7Dtz8=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.12/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=
|
||||
@@ -960,10 +953,10 @@ github.com/theupdateframework/notary v0.7.0/go.mod h1:c9DRxcmhHmVLDay4/2fUYdISnH
|
||||
github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
|
||||
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
|
||||
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
|
||||
github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4=
|
||||
github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4=
|
||||
github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso=
|
||||
github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ=
|
||||
github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA=
|
||||
github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI=
|
||||
github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw=
|
||||
github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ=
|
||||
github.com/tomasen/fcgi_client v0.0.0-20180423082037-2bb3d819fd19 h1:ZCmSnT6CLGhfoQ2lPEhL4nsJstKDCw1F1RfN8/smTCU=
|
||||
github.com/tomasen/fcgi_client v0.0.0-20180423082037-2bb3d819fd19/go.mod h1:SXTY+QvI+KTTKXQdg0zZ7nx0u94QWh8ZAwBQYsW9cqk=
|
||||
github.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323 h1:r0p7fK56l8WPequOaR3i9LBqfPtEdXIQbUTzT55iqT4=
|
||||
@@ -989,8 +982,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.229 h1:gOkDltTS6Fta8OyfYrbeY9bqCHHyiJuGYNJpR5MR+Fo=
|
||||
github.com/volcengine/volc-sdk-golang v1.0.229/go.mod h1:zHJlaqiMbIB+0mcrsZPTwOb3FB7S/0MCfqlnO8R7hlM=
|
||||
github.com/volcengine/volc-sdk-golang v1.0.230 h1:84/MOF0zUPtAHt3e1+MsFq5qrnQRC+e3XzTUwIOzZxw=
|
||||
github.com/volcengine/volc-sdk-golang v1.0.230/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=
|
||||
@@ -1022,16 +1015,16 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0 h1:0tY123n7CdWMem7MOVdKOt0YfshufLCwfE5Bob+hQuM=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0/go.mod h1:CosX/aS4eHnG9D7nESYpV753l4j9q5j3SL/PUYd2lR8=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
|
||||
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
|
||||
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
|
||||
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
|
||||
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 h1:QcFwRrZLc82r8wODjvyCbP7Ifp3UANaBSmhDSFjnqSc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0/go.mod h1:CXIWhUomyWBG/oY2/r/kLp6K/cmx9e/7DLpBuuGdLCA=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw=
|
||||
@@ -1040,14 +1033,14 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk=
|
||||
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
|
||||
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
|
||||
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
|
||||
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
|
||||
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
|
||||
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
|
||||
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
|
||||
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
|
||||
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
|
||||
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
|
||||
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
|
||||
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
|
||||
@@ -1102,8 +1095,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.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
|
||||
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
|
||||
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
|
||||
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
|
||||
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=
|
||||
@@ -1147,8 +1140,8 @@ 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.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
||||
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
||||
golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
|
||||
golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -1205,8 +1198,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.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||
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=
|
||||
@@ -1214,8 +1207,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.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
|
||||
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
|
||||
golang.org/x/oauth2 v0.34.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=
|
||||
@@ -1232,8 +1225,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.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
|
||||
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
golang.org/x/sync v0.19.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=
|
||||
@@ -1313,8 +1306,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.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
||||
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||
golang.org/x/sys v0.39.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=
|
||||
@@ -1329,8 +1322,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.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
|
||||
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
|
||||
golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
|
||||
golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
|
||||
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=
|
||||
@@ -1348,8 +1341,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.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
|
||||
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
|
||||
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
|
||||
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
|
||||
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=
|
||||
@@ -1411,8 +1404,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.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
|
||||
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
|
||||
golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ=
|
||||
golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
|
||||
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=
|
||||
@@ -1481,10 +1474,10 @@ google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxH
|
||||
google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 h1:Q3nlH8iSQSRUwOskjbcSMcF2jiYMNiQYZ0c2KEJLKKU=
|
||||
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-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/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 h1:mepRgnBZa07I4TRuomDE4sTIYieg/osKmzIf4USdWS4=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8/go.mod h1:fDMmzKV90WSg1NbozdqrE64fkuTv6mlq2zxo9ad+3yo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251124214823-79d6a2a48846 h1:Wgl1rcDNThT+Zn47YyCXOXyX/COgMTIdhJ717F0l4xk=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251124214823-79d6a2a48846/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=
|
||||
@@ -1502,8 +1495,8 @@ 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.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=
|
||||
google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c=
|
||||
google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM=
|
||||
google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
||||
@@ -154,6 +154,8 @@ unpause: 'Resume'
|
||||
remove: 'Delete'
|
||||
delete: 'Delete'
|
||||
ErrDefaultWebsite: 'Default website has been set, please cancel it before setting!'
|
||||
SSL: 'Certificate'
|
||||
Set: 'Settings'
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: 'The {{ .name }} certificate is being used by a website and cannot be deleted'
|
||||
@@ -204,9 +206,9 @@ RemoteRecover: "To restore the remote database, the local container database ser
|
||||
ErrTypeOfRedis: 'The recovery file type does not match the current persistence method, please modify it and try again'
|
||||
|
||||
#container
|
||||
ErrInUsed: '{{ .detail }} is in use and cannot be deleted'
|
||||
ErrObjectInUsed: 'The object is in use and cannot be deleted'
|
||||
ErrObjectBeDependent: 'This image depends on other images and cannot be deleted'
|
||||
ErrInUsed: "{{ .detail }} is in use and cannot be deleted!"
|
||||
ErrObjectInUsed: "This object is in use and cannot be deleted!"
|
||||
ErrObjectBeDependent: "This image is depended on by other images and cannot be deleted!"
|
||||
ErrPortRules: 'Port number does not match, please re-enter!'
|
||||
ErrPgImagePull: 'Image pull timed out, please configure image acceleration or manually pull the {{ .name }} image and try again'
|
||||
PruneHelper: "This cleanup removed {{ .name }} {{ .count }} items, freeing {{ .size }} disk space"
|
||||
@@ -256,6 +258,7 @@ InExecuting: "The current task is being executed, please do not repeat the execu
|
||||
NoSuchResource: "No backup content found in the database, skipping..."
|
||||
CleanLog: "Clean Log"
|
||||
CleanLogByName: "Clean {{.name}} Log"
|
||||
WafIpGroupNotFound: "WAF IP group not found. Please go to [Advanced Features - WAF - Black/White List - IP Group] to add an IP group via remote download method."
|
||||
|
||||
#toolbox
|
||||
ErrNotExistUser: 'The current user does not exist, please modify and try again!'
|
||||
|
||||
@@ -153,6 +153,8 @@ unpause: 'Reanudar'
|
||||
remove: 'Eliminar'
|
||||
delete: 'Eliminar'
|
||||
ErrDefaultWebsite: 'El sitio web predeterminado ya está configurado, ¡cancélelo antes de configurar!'
|
||||
SSL: 'Certificado'
|
||||
Set: 'Configuración'
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: 'El certificado {{ .name }} está siendo utilizado por un sitio web y no puede eliminarse'
|
||||
@@ -203,9 +205,9 @@ RemoteRecover: "Para restaurar la base de datos remota, primero debe iniciarse e
|
||||
ErrTypeOfRedis: 'El tipo de archivo de recuperación no coincide con el método de persistencia actual, modifíquelo e intente'
|
||||
|
||||
#container
|
||||
ErrInUsed: '{{ .detail }} está en uso y no puede eliminarse'
|
||||
ErrObjectInUsed: 'El objeto está en uso y no puede eliminarse'
|
||||
ErrObjectBeDependent: 'Esta imagen depende de otras imágenes y no puede eliminarse'
|
||||
ErrInUsed: "{{ .detail }} está en uso y no se puede eliminar!"
|
||||
ErrObjectInUsed: "Este objeto está en uso y no se puede eliminar!"
|
||||
ErrObjectBeDependent: "Esta imagen es dependida por otras imágenes y no se puede eliminar!"
|
||||
ErrPortRules: 'El número de puerto no coincide, ingrese de nuevo'
|
||||
ErrPgImagePull: 'Tiempo de espera al descargar la imagen, configure la aceleración o descárguela manualmente ({{ .name }}) e intente de nuevo'
|
||||
PruneHelper: "Esta limpieza eliminó {{ .name }} {{ .count }} elementos, liberando {{ .size }} de espacio en disco"
|
||||
@@ -255,6 +257,7 @@ InExecuting: "La tarea actual se está ejecutando, por favor no la repita"
|
||||
NoSuchResource: "No se encontraron contenidos de respaldo en la base de datos, omitiendo..."
|
||||
CleanLog: "Limpiar registro"
|
||||
CleanLogByName: "Limpiar registro de {{.name}}"
|
||||
WafIpGroupNotFound: "Grupo de IP de WAF no encontrado. Por favor, vaya a [Funciones Avanzadas - WAF - Lista Blanca/Negra - Grupo de IP] para agregar un grupo de IP mediante el método de descarga remota."
|
||||
|
||||
#toolbox
|
||||
ErrNotExistUser: 'El usuario actual no existe, modifíquelo e intente de nuevo'
|
||||
|
||||
@@ -153,6 +153,8 @@ unpause: '再開'
|
||||
remove: '削除'
|
||||
delete: '削除'
|
||||
ErrDefaultWebsite: 'デフォルト Web サイトが既に設定されています。設定する前にキャンセルしてください!'
|
||||
SSL: '証明書'
|
||||
Set: '設定'
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: '{{ .name }} 証明書は Web サイトで使用されているため、削除できません'
|
||||
@@ -203,9 +205,9 @@ RemoteRecover: "リモートデータベースを復元するには、まずイ
|
||||
ErrTypeOfRedis: 'リカバリ ファイルの種類が現在の永続化方法と一致しません。変更して再試行してください'
|
||||
|
||||
#container
|
||||
ErrInUsed: '{{ .detail }} は使用中のため削除できません'
|
||||
ErrObjectInUsed: 'オブジェクトは使用中のため削除できません'
|
||||
ErrObjectBeDependent: 'このイメージは他のイメージに依存しているため、削除できません'
|
||||
ErrInUsed: "{{ .detail }} は使用中であり、削除できません!"
|
||||
ErrObjectInUsed: "このオブジェクトは使用中であり、削除できません!"
|
||||
ErrObjectBeDependent: "このイメージは他のイメージに依存されているため、削除できません!"
|
||||
ErrPortRules: 'ポート番号が一致しません。再入力してください。'
|
||||
ErrPgImagePull: 'イメージのプルがタイムアウトしました。イメージのアクセラレーションを設定するか、{{ .name }} イメージを手動でプルして再試行してください'
|
||||
PruneHelper: "今回のクリーンアップで{{ .name }} {{ .count }}個を削除し、{{ .size }}のディスク領域を解放しました"
|
||||
@@ -255,6 +257,7 @@ InExecuting: "現在のタスクは実行中です。重複して実行しない
|
||||
NoSuchResource: "データベースにバックアップ内容が見つかりませんでした。スキップします..."
|
||||
CleanLog: "ログをクリーン"
|
||||
CleanLogByName: "{{.name}} のログをクリーン"
|
||||
WafIpGroupNotFound: "WAF IPグループが見つかりません。[高度な機能 - WAF - ブラックリスト/ホワイトリスト - IPグループ]に移動し、リモートダウンロード方式でIPグループを追加してください。"
|
||||
|
||||
#toolbox
|
||||
ErrNotExistUser: '現在のユーザーは存在しません。変更してもう一度お試しください。'
|
||||
|
||||
@@ -154,6 +154,8 @@ unpause: '재개'
|
||||
remove: '삭제'
|
||||
delete: '삭제'
|
||||
ErrDefaultWebsite: '기본 웹사이트가 이미 설정되었습니다. 설정하기 전에 취소하세요!'
|
||||
SSL: '인증서'
|
||||
Set: '설정'
|
||||
|
||||
#SSL인증
|
||||
ErrSSLCannotDelete: '{{ .name }} 인증서는 웹사이트에서 사용 중이므로 삭제할 수 없습니다.'
|
||||
@@ -204,9 +206,9 @@ RemoteRecover: "원격 데이터베이스를 복원하려면 먼저 이미지 {{
|
||||
ErrTypeOfRedis: '복구 파일 유형이 현재 지속성 방법과 일치하지 않습니다. 수정하고 다시 시도하세요'
|
||||
|
||||
#컨테이너
|
||||
ErrInUsed: '{{ .detail }}이 사용 중이므로 삭제할 수 없습니다'
|
||||
ErrObjectInUsed: '개체가 사용 중이므로 삭제할 수 없습니다'
|
||||
ErrObjectBeDependent: '이 이미지는 다른 이미지에 의존하므로 삭제할 수 없습니다'
|
||||
ErrInUsed: "{{ .detail }}(이)가 사용 중이어서 삭제할 수 없습니다!"
|
||||
ErrObjectInUsed: "이 객체는 사용 중이어서 삭제할 수 없습니다!"
|
||||
ErrObjectBeDependent: "이 이미지는 다른 이미지에 의존되어 있어 삭제할 수 없습니다!"
|
||||
ErrPortRules: '포트 번호가 일치하지 않습니다. 다시 입력하세요!'
|
||||
ErrPgImagePull: '이미지 풀링 시간이 초과되었습니다. 이미지 가속을 구성하거나 {{ .name }} 이미지를 수동으로 풀링한 다음 다시 시도하세요.'
|
||||
PruneHelper: "이번 정리에서 {{ .name }} {{ .count }}개를 제거하여 {{ .size }} 디스크 공간을 확보했습니다"
|
||||
@@ -256,6 +258,7 @@ InExecuting: "현재 작업이 실행 중입니다. 중복 실행하지 마세
|
||||
NoSuchResource: "데이터베이스에서 백업 내용을 찾을 수 없어 건너뜁니다..."
|
||||
CleanLog: "로그 정리"
|
||||
CleanLogByName: "{{.name}} 로그 정리"
|
||||
WafIpGroupNotFound: "WAF IP 그룹을 찾을 수 없습니다. [고급 기능 - WAF - 블랙/화이트 목록 - IP 그룹]으로 이동하여 원격 다운로드 방식으로 IP 그룹을 추가하십시오."
|
||||
|
||||
#도구상자
|
||||
ErrNotExistUser: '현재 사용자가 존재하지 않습니다. 수정한 후 다시 시도하세요!'
|
||||
|
||||
@@ -157,6 +157,8 @@ unpause: 'Sambung Semula'
|
||||
remove: 'Padam'
|
||||
delete: 'Padam'
|
||||
ErrDefaultWebsite: 'Laman web lalai telah ditetapkan, sila batalkan sebelum menetapkan!'
|
||||
SSL: 'Sijil'
|
||||
Set: 'Tetapan'
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: 'Sijil {{ .name }} sedang digunakan oleh tapak web dan tidak boleh dipadamkan'
|
||||
@@ -204,9 +206,9 @@ RemoteRecover: "Untuk memulihkan pangkalan data jauh, perkhidmatan pangkalan dat
|
||||
ErrTypeOfRedis: 'Jenis fail pemulihan tidak sepadan dengan kaedah kegigihan semasa, sila ubah suai dan cuba lagi'
|
||||
|
||||
#bekas
|
||||
ErrInUsed: '{{ .detail }} sedang digunakan dan tidak boleh dipadamkan'
|
||||
ErrObjectInUsed: 'Objek sedang digunakan dan tidak boleh dipadamkan'
|
||||
ErrObjectBeDependent: 'Imej ini bergantung pada imej lain dan tidak boleh dipadamkan'
|
||||
ErrInUsed: "{{ .detail }} sedang digunakan dan tidak boleh dipadam!"
|
||||
ErrObjectInUsed: "Objek ini sedang digunakan dan tidak boleh dipadam!"
|
||||
ErrObjectBeDependent: "Imej ini digantungkan oleh imej lain dan tidak boleh dipadam!"
|
||||
ErrPortRules: 'Nombor port tidak sepadan, sila masukkan semula!'
|
||||
ErrPgImagePull: 'Tarikh imej tamat masa, sila konfigurasikan pecutan imej atau tarik imej {{ .name }} secara manual dan cuba lagi'
|
||||
PruneHelper: "Pembersihan ini membuang {{ .name }} {{ .count }} item, membebaskan {{ .size }} ruang cakera"
|
||||
@@ -256,6 +258,7 @@ InExecuting: "Tugas semasa sedang dilaksanakan, jangan ulangi pelaksanaan!"
|
||||
NoSuchResource: "Tiada kandungan sandaran ditemui dalam pangkalan data, dilangkau..."
|
||||
CleanLog: "Bersihkan log"
|
||||
CleanLogByName: "Bersihkan log {{.name}}"
|
||||
WafIpGroupNotFound: "Kumpulan IP WAF tidak ditemui. Sila pergi ke [Ciri Lanjutan - WAF - Senarai Hitam/Putih - Kumpulan IP] untuk menambah kumpulan IP melalui kaedah muat turun jauh."
|
||||
|
||||
#kotak alat
|
||||
ErrNotExistUser: 'Pengguna semasa tidak wujud, sila ubah suai dan cuba lagi!'
|
||||
|
||||
@@ -157,6 +157,8 @@ unpause: 'Retomar'
|
||||
remove: 'Excluir'
|
||||
delete: 'Excluir'
|
||||
ErrDefaultWebsite: 'O site padrão já foi definido, cancele-o antes de definir!'
|
||||
SSL: 'Certificado'
|
||||
Set: 'Configurações'
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: 'O certificado {{ .name }} está sendo usado por um site e não pode ser excluído'
|
||||
@@ -204,9 +206,9 @@ RemoteRecover: "Para restaurar o banco de dados remoto, o serviço de banco de d
|
||||
ErrTypeOfRedis: 'O tipo de arquivo de recuperação não corresponde ao método de persistência atual, modifique-o e tente novamente'
|
||||
|
||||
#recipiente
|
||||
ErrInUsed: '{{ .detail }} está em uso e não pode ser excluído'
|
||||
ErrObjectInUsed: 'O objeto está em uso e não pode ser excluído'
|
||||
ErrObjectBeDependent: 'Esta imagem depende de outras imagens e não pode ser excluída'
|
||||
ErrInUsed: "{{ .detail }} está em uso e não pode ser excluído!"
|
||||
ErrObjectInUsed: "Este objeto está em uso e não pode ser excluído!"
|
||||
ErrObjectBeDependent: "Esta imagem é dependida por outras imagens e não pode ser excluída!"
|
||||
ErrPortRules: 'O número da porta não corresponde, digite novamente!'
|
||||
ErrPgImagePull: 'Tempo limite para extração de imagem. Configure a aceleração de imagem ou extraia manualmente a imagem {{ .name }} e tente novamente'
|
||||
PruneHelper: "Esta limpeza removeu {{ .name }} {{ .count }} itens, liberando {{ .size }} de espaço em disco"
|
||||
@@ -256,6 +258,7 @@ InExecuting: "A tarefa atual está sendo executada, não repita a execução!"
|
||||
NoSuchResource: "Nenhum conteúdo de backup encontrado no banco de dados, ignorando..."
|
||||
CleanLog: "Limpar log"
|
||||
CleanLogByName: "Limpar log de {{.name}}"
|
||||
WafIpGroupNotFound: "Grupo de IP do WAF não encontrado. Por favor, vá para [Recursos Avançados - WAF - Lista Branca/Preta - Grupo de IP] para adicionar um grupo de IP via método de download remoto."
|
||||
|
||||
#caixa de ferramentas
|
||||
ErrNotExistUser: 'O usuário atual não existe, modifique e tente novamente!'
|
||||
|
||||
@@ -157,6 +157,8 @@ unpause: 'Возобновить'
|
||||
remove: 'Удалить'
|
||||
delete: 'Удалить'
|
||||
ErrDefaultWebsite: 'Веб-сайт по умолчанию уже установлен, отмените его перед настройкой!'
|
||||
SSL: 'Сертификат'
|
||||
Set: 'Настройки'
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: 'Сертификат {{ .name }} используется веб-сайтом и не может быть удален'
|
||||
@@ -204,9 +206,9 @@ RemoteRecover: "Для восстановления удаленной базы
|
||||
ErrTypeOfRedis: 'Тип файла восстановления не соответствует текущему методу сохранения. Измените его и повторите попытку'
|
||||
|
||||
#контейнер
|
||||
ErrInUsed: '{{ .detail }} используется и не может быть удален'
|
||||
ErrObjectInUsed: 'Объект используется и не может быть удален'
|
||||
ErrObjectBeDependent: 'Это изображение зависит от других изображений и не может быть удалено'
|
||||
ErrInUsed: "{{ .detail }} используется и не может быть удалено!"
|
||||
ErrObjectInUsed: "Этот объект используется и не может быть удален!"
|
||||
ErrObjectBeDependent: "Этот образ зависит от других образов и не может быть удален!"
|
||||
ErrPortRules: 'Номер порта не совпадает, введите заново!'
|
||||
ErrPgImagePull: 'Время извлечения изображения истекло. Настройте ускорение изображения или вручную извлеките изображение {{ .name }} и повторите попытку'
|
||||
PruneHelper: "Очистка удалила {{ .name }} в количестве {{ .count }}, освободив {{ .size }} дискового пространства"
|
||||
@@ -256,6 +258,7 @@ InExecuting: "Текущая задача выполняется, не повт
|
||||
NoSuchResource: "В базе данных не найдено содержимое резервной копии, пропускаем..."
|
||||
CleanLog: "Очистить журнал"
|
||||
CleanLogByName: "Очистить журнал {{.name}}"
|
||||
WafIpGroupNotFound: "Группа IP WAF не найдена. Пожалуйста, перейдите в [Расширенные функции - WAF - Черный/Белый список - Группа IP], чтобы добавить группу IP с помощью метода удаленной загрузки."
|
||||
|
||||
#ящик для инструментов
|
||||
ErrNotExistUser: 'Текущий пользователь не существует, измените его и повторите попытку!'
|
||||
|
||||
@@ -158,6 +158,8 @@ unpause: 'Devam Et'
|
||||
remove: 'Sil'
|
||||
delete: 'Sil'
|
||||
ErrDefaultWebsite: "Varsayılan bir web sitesi zaten ayarlanmış. Yeni bir tane ayarlamadan önce lütfen iptal edin!"
|
||||
SSL: 'Sertifika'
|
||||
Set: 'Ayarlar'
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: '{{ .name }} sertifikası bir web sitesi tarafından kullanılıyor ve silinemez'
|
||||
@@ -205,9 +207,9 @@ RemoteRecover: "Uzak veritabanını geri yüklemek için önce {{ .name }} gör
|
||||
ErrTypeOfRedis: 'Kurtarma dosyası türü mevcut kalıcılık yöntemiyle eşleşmiyor, lütfen değiştirin ve tekrar deneyin'
|
||||
|
||||
#container
|
||||
ErrInUsed: '{{ .detail }} kullanımda ve silinemez'
|
||||
ErrObjectInUsed: 'Nesne kullanımda ve silinemez'
|
||||
ErrObjectBeDependent: 'Bu image diğer imagelere bağlı ve silinemez'
|
||||
ErrInUsed: "{{ .detail }} kullanımda ve silinemez!"
|
||||
ErrObjectInUsed: "Bu nesne kullanımda ve silinemez!"
|
||||
ErrObjectBeDependent: "Bu görüntü diğer görüntüler tarafından bağımlıdır ve silinemez!"
|
||||
ErrPortRules: 'Port numarası eşleşmiyor, lütfen yeniden girin!'
|
||||
ErrPgImagePull: 'Image çekme zaman aşımı, lütfen image hızlandırma yapılandırın veya manuel olarak {{ .name }} imageını çekin ve tekrar deneyin'
|
||||
PruneHelper: "Bu temizleme {{ .name }} {{ .count }} öğe kaldırdı, {{ .size }} disk alanı boşalttı"
|
||||
@@ -257,6 +259,7 @@ InExecuting: "Mevcut görev yürütülüyor, lütfen tekrar yürütmeyin!"
|
||||
NoSuchResource: "Veritabanında yedek içeriği bulunamadı, atlanıyor..."
|
||||
CleanLog: "Günlüğü temizle"
|
||||
CleanLogByName: "{{.name}} günlüğünü temizle"
|
||||
WafIpGroupNotFound: "WAF IP grubu bulunamadı. Lütfen [Gelişmiş Özellikler - WAF - Kara/Beyaz Liste - IP Grubu] bölümüne giderek uzaktan indirme yöntemiyle bir IP grubu ekleyin."
|
||||
|
||||
#toolbox
|
||||
ErrNotExistUser: 'Mevcut kullanıcı mevcut değil, lütfen değiştirin ve tekrar deneyin!'
|
||||
|
||||
@@ -153,6 +153,8 @@ unpause: '恢復'
|
||||
remove: '刪除'
|
||||
delete: '刪除'
|
||||
ErrDefaultWebsite: '已經設置默認網站,請取消後再設置!'
|
||||
SSL: '憑證'
|
||||
Set: '設定'
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: '{{ .name }} 憑證正在被網站使用,無法刪除'
|
||||
@@ -203,9 +205,9 @@ RemoteRecover: "恢復遠端資料庫需要先使用映像 {{ .name }} 啟動本
|
||||
ErrTypeOfRedis: '復原檔案類型與目前持久化方式不符,請修改後重試'
|
||||
|
||||
#container
|
||||
ErrInUsed: '{{ .detail }} 正被使用,無法刪除'
|
||||
ErrObjectInUsed: '該物件正被使用,無法刪除'
|
||||
ErrObjectBeDependent: '此鏡像依賴其他鏡像,無法刪除'
|
||||
ErrInUsed: "{{ .detail }} 正被使用,無法刪除!"
|
||||
ErrObjectInUsed: "該對象正被使用,無法刪除!"
|
||||
ErrObjectBeDependent: "該映像正被其他映像所依賴,無法刪除!"
|
||||
ErrPortRules: '連接埠數目不匹配,請重新輸入!'
|
||||
ErrPgImagePull: '鏡像拉取逾時,請配置鏡像加速或手動拉取{{ .name }} 鏡像後重試'
|
||||
PruneHelper: "本次清理 {{ .name }} {{ .count }} 個,釋放磁碟空間 {{ .size }}"
|
||||
@@ -255,6 +257,7 @@ InExecuting: "目前任務正在執行中,請勿重複執行!"
|
||||
NoSuchResource: "資料庫中未能查詢到備份內容,跳過..."
|
||||
CleanLog: "清理日誌"
|
||||
CleanLogByName: "清理 {{.name}} 日誌"
|
||||
WafIpGroupNotFound: "WAF IP 群組未找到,請先到【進階功能-WAF-黑白名單-IP群組】添加遠端下載方式的IP群組"
|
||||
|
||||
#toolbox
|
||||
ErrNotExistUser: '目前使用者不存在,請修改後重試!'
|
||||
|
||||
@@ -154,6 +154,8 @@ unpause: '恢复'
|
||||
remove: '删除'
|
||||
delete: '删除'
|
||||
ErrDefaultWebsite: "已经设置默认网站,请取消后再设置!"
|
||||
SSL: '证书'
|
||||
Set: '设置'
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: "{{ .name }} 证书正在被网站使用,无法删除"
|
||||
@@ -204,9 +206,9 @@ RemoteRecover: "恢复远程数据库需要先使用镜像 {{ .name }} 启动本
|
||||
ErrTypeOfRedis: "恢复文件类型与当前持久化方式不符,请修改后重试"
|
||||
|
||||
#container
|
||||
ErrInUsed: "{{ .detail }} 正被使用,无法删除"
|
||||
ErrObjectInUsed: "该对象正被使用,无法删除"
|
||||
ErrObjectBeDependent: "该镜像依赖于其他镜像,无法删除"
|
||||
ErrInUsed: "{{ .detail }} 正被使用,无法删除!"
|
||||
ErrObjectInUsed: "该对象正被使用,无法删除!"
|
||||
ErrObjectBeDependent: "该镜像正被其他镜像所依赖,无法删除!"
|
||||
ErrPortRules: "端口数目不匹配,请重新输入!"
|
||||
ErrPgImagePull: "镜像拉取超时,请配置镜像加速或手动拉取 {{ .name }} 镜像后重试"
|
||||
PruneHelper: "本次清理 {{ .name }} {{ .count }} 个,释放磁盘空间 {{ .size }}"
|
||||
@@ -256,6 +258,7 @@ InExecuting: "当前任务正在执行中,请勿重复执行!"
|
||||
NoSuchResource: "数据库中未能查询到备份内容,跳过..."
|
||||
CleanLog: "清理日志"
|
||||
CleanLogByName: "清理 {{.name}} 日志"
|
||||
WafIpGroupNotFound: "WAF IP组未找到,请先到【高级功能-WAF-黑白名单-IP组】添加远程下载方式的IP组"
|
||||
|
||||
#toolbox
|
||||
ErrNotExistUser: "当前用户不存在,请修改后重试!"
|
||||
|
||||
@@ -78,13 +78,13 @@ func initAcmeAccount() {
|
||||
}
|
||||
|
||||
func checkDockerCompose() {
|
||||
dockerComposCmd := common.GetDockerComposeCommand()
|
||||
if dockerComposCmd == "" {
|
||||
dockerComposeCmd := common.GetDockerComposeCommand()
|
||||
if dockerComposeCmd == "" {
|
||||
global.LOG.Errorf("Docker Compose command not found, please install Docker Compose Plugin")
|
||||
return
|
||||
}
|
||||
global.CONF.DockerConfig.Command = dockerComposCmd
|
||||
if err := service.NewISettingService().Update("DockerComposeCommand", dockerComposCmd); err != nil {
|
||||
global.CONF.DockerConfig.Command = dockerComposeCmd
|
||||
if err := service.NewISettingService().Update("DockerComposeCommand", dockerComposeCmd); err != nil {
|
||||
global.LOG.Errorf("update docker compose command error: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ func Init() {
|
||||
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 _, err := os.Stat("/usr/bin/1panel-core"); err == nil {
|
||||
if _, err := os.Stat(path.Join(global.Dir.DbDir, "core.db")); err == nil {
|
||||
global.CoreDB = common.LoadDBConnByPath(path.Join(global.Dir.DbDir, "core.db"), "core")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ func Init() {
|
||||
if !needInit() {
|
||||
return
|
||||
}
|
||||
InitPingStatus()
|
||||
global.LOG.Info("initializing firewall settings...")
|
||||
client, err := firewall.NewFirewallClient()
|
||||
if err != nil {
|
||||
@@ -122,3 +123,20 @@ func needInit() bool {
|
||||
fmt.Fprintf(file, "Boot Mark for 1panel\n")
|
||||
return true
|
||||
}
|
||||
|
||||
func InitPingStatus() {
|
||||
global.LOG.Info("initializing ban ping status from settings...")
|
||||
status := firewall.LoadPingStatus()
|
||||
statusInDB, _ := repo.NewISettingRepo().GetValueByKey("BanPing")
|
||||
if statusInDB == status {
|
||||
return
|
||||
}
|
||||
|
||||
enable := "1"
|
||||
if statusInDB == constant.StatusDisable {
|
||||
enable = "0"
|
||||
}
|
||||
if err := firewall.UpdatePingStatus(enable); err != nil {
|
||||
global.LOG.Errorf("initialize ping status failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ func initGlobalData() {
|
||||
if len(node.Version) != 0 {
|
||||
_ = settingRepo.Update("SystemVersion", node.Version)
|
||||
}
|
||||
global.CONF.Base.Version = node.Version
|
||||
global.CONF.Base.EncryptKey, _ = settingRepo.GetValueByKey("EncryptKey")
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,10 @@ func InitAgentDB() {
|
||||
migrations.AddGPUMonitor,
|
||||
migrations.UpdateDatabaseMysql,
|
||||
migrations.InitIptablesStatus,
|
||||
migrations.UpdateWebsite,
|
||||
migrations.AddisIPtoWebsiteSSL,
|
||||
migrations.InitPingStatus,
|
||||
migrations.UpdateApp,
|
||||
})
|
||||
if err := m.Migrate(); err != nil {
|
||||
global.LOG.Error(err)
|
||||
|
||||
@@ -775,3 +775,35 @@ var InitIptablesStatus = &gormigrate.Migration{
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var UpdateWebsite = &gormigrate.Migration{
|
||||
ID: "20251203-update-website",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
return tx.AutoMigrate(&model.Website{})
|
||||
},
|
||||
}
|
||||
|
||||
var AddisIPtoWebsiteSSL = &gormigrate.Migration{
|
||||
ID: "20251223-update-website-ssl",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
return tx.AutoMigrate(&model.WebsiteSSL{})
|
||||
},
|
||||
}
|
||||
|
||||
var InitPingStatus = &gormigrate.Migration{
|
||||
ID: "20251201-init-ping-status",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
status := firewall.LoadPingStatus()
|
||||
if err := tx.Create(&model.Setting{Key: "BanPing", Value: status}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var UpdateApp = &gormigrate.Migration{
|
||||
ID: "20251228-update-app",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
return tx.AutoMigrate(&model.App{})
|
||||
},
|
||||
}
|
||||
|
||||
@@ -19,12 +19,13 @@ func (s *BackupRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
backupRouter.POST("/refresh/token", baseApi.RefreshToken)
|
||||
backupRouter.POST("/buckets", baseApi.ListBuckets)
|
||||
backupRouter.POST("", baseApi.CreateBackup)
|
||||
backupRouter.POST("/conn/check", baseApi.CheckBackup)
|
||||
backupRouter.POST("/del", baseApi.DeleteBackup)
|
||||
backupRouter.POST("/update", baseApi.UpdateBackup)
|
||||
backupRouter.POST("/upload", baseApi.UploadForRecover)
|
||||
|
||||
backupRouter.POST("/backup", baseApi.Backup)
|
||||
backupRouter.POST("/recover", baseApi.Recover)
|
||||
backupRouter.POST("/upload", baseApi.UploadForRecover)
|
||||
backupRouter.POST("/recover/byupload", baseApi.RecoverByUpload)
|
||||
backupRouter.POST("/search/files", baseApi.LoadFilesFromBackup)
|
||||
backupRouter.POST("/record/search", baseApi.SearchBackupRecords)
|
||||
|
||||
@@ -19,6 +19,7 @@ func (a *AppRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
appRouter.POST("/search", baseApi.SearchApp)
|
||||
appRouter.GET("/:key", baseApi.GetApp)
|
||||
appRouter.GET("/detail/:appId/:version/:type", baseApi.GetAppDetail)
|
||||
appRouter.GET("/detail/node/:appKey/:version", baseApi.GetAppDetailForNode)
|
||||
appRouter.GET("/details/:id", baseApi.GetAppDetailByID)
|
||||
appRouter.POST("/install", baseApi.InstallApp)
|
||||
appRouter.GET("/tags", baseApi.GetAppTags)
|
||||
|
||||
@@ -23,6 +23,7 @@ func (f *FileRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
fileRouter.POST("/compress", baseApi.CompressFile)
|
||||
fileRouter.POST("/decompress", baseApi.DeCompressFile)
|
||||
fileRouter.POST("/content", baseApi.GetContent)
|
||||
fileRouter.POST("/preview", baseApi.PreviewContent)
|
||||
fileRouter.POST("/save", baseApi.SaveContent)
|
||||
fileRouter.POST("/check", baseApi.CheckFile)
|
||||
fileRouter.POST("/batch/check", baseApi.BatchCheckFiles)
|
||||
|
||||
@@ -32,6 +32,7 @@ func (s *SettingRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
|
||||
settingRouter.POST("/ssh/check", baseApi.CheckLocalConn)
|
||||
settingRouter.GET("/ssh/conn", baseApi.LoadLocalConn)
|
||||
settingRouter.POST("/ssh/default", baseApi.SetDefaultIsConn)
|
||||
settingRouter.POST("/ssh", baseApi.SaveLocalConn)
|
||||
settingRouter.POST("/ssh/check/info", baseApi.CheckLocalConnByInfo)
|
||||
}
|
||||
|
||||
@@ -25,8 +25,10 @@ func (a *WebsiteRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
websiteRouter.POST("/del", baseApi.DeleteWebsite)
|
||||
websiteRouter.POST("/default/server", baseApi.ChangeDefaultServer)
|
||||
websiteRouter.POST("/group/change", baseApi.ChangeWebsiteGroup)
|
||||
|
||||
websiteRouter.POST("/batch/operate", baseApi.BatchOpWebsites)
|
||||
websiteRouter.POST("/batch/group", baseApi.BatchSetWebsiteGroup)
|
||||
websiteRouter.POST("/batch/ssl", baseApi.BatchSetHttps)
|
||||
|
||||
websiteRouter.GET("/domains/:websiteId", baseApi.GetWebDomains)
|
||||
websiteRouter.POST("/domains/del", baseApi.DeleteWebDomain)
|
||||
@@ -93,5 +95,6 @@ func (a *WebsiteRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
websiteRouter.POST("/crosssite", baseApi.OperateCrossSiteAccess)
|
||||
|
||||
websiteRouter.POST("/exec/composer", baseApi.ExecComposer)
|
||||
websiteRouter.POST("/stream/update", baseApi.UpdateStreamConfig)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,23 +120,6 @@ 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")
|
||||
|
||||
@@ -1,25 +1,20 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
"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"
|
||||
)
|
||||
|
||||
type s3Client struct {
|
||||
scType string
|
||||
bucket string
|
||||
client *s3.Client
|
||||
Sess session.Session
|
||||
}
|
||||
|
||||
func NewS3Client(vars map[string]interface{}) (*s3Client, error) {
|
||||
@@ -36,26 +31,22 @@ func NewS3Client(vars map[string]interface{}) (*s3Client, error) {
|
||||
if len(mode) == 0 {
|
||||
mode = "virtual hosted"
|
||||
}
|
||||
cfg, err := config.LoadDefaultConfig(context.Background(),
|
||||
config.WithRegion(region),
|
||||
config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(accessKey, secretKey, "")),
|
||||
)
|
||||
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"),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
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
|
||||
return &s3Client{scType: scType, bucket: bucket, Sess: *sess}, nil
|
||||
}
|
||||
|
||||
func (s *s3Client) ListBuckets() ([]interface{}, error) {
|
||||
func (s s3Client) ListBuckets() ([]interface{}, error) {
|
||||
var result []interface{}
|
||||
res, err := s.client.ListBuckets(context.Background(), &s3.ListBucketsInput{})
|
||||
svc := s3.New(&s.Sess)
|
||||
res, err := svc.ListBuckets(nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -65,54 +56,50 @@ func (s *s3Client) ListBuckets() ([]interface{}, error) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
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":
|
||||
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 {
|
||||
return false, nil
|
||||
}
|
||||
} else {
|
||||
return false, aerr
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (s *s3Client) Size(path string) (int64, error) {
|
||||
file, err := s.client.GetObject(context.Background(), &s3.GetObjectInput{
|
||||
Bucket: aws.String(s.bucket),
|
||||
Key: aws.String(path),
|
||||
svc := s3.New(&s.Sess)
|
||||
file, err := svc.GetObject(&s3.GetObjectInput{
|
||||
Bucket: &s.bucket,
|
||||
Key: &path,
|
||||
})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer file.Body.Close()
|
||||
return aws.ToInt64(file.ContentLength), nil
|
||||
return *file.ContentLength, nil
|
||||
}
|
||||
|
||||
func (s *s3Client) Delete(path string) (bool, error) {
|
||||
if _, err := s.client.DeleteObject(context.Background(), &s3.DeleteObjectInput{
|
||||
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{
|
||||
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
|
||||
@@ -123,23 +110,22 @@ func (s *s3Client) Upload(src, target string) (bool, error) {
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
uploader := manager.NewUploader(s.client)
|
||||
maxUploadSize := int64(manager.MaxUploadParts) * manager.DefaultUploadPartSize
|
||||
if fileInfo.Size() > maxUploadSize {
|
||||
uploader.PartSize = fileInfo.Size() / (int64(manager.MaxUploadParts) - 1)
|
||||
uploader := s3manager.NewUploader(&s.Sess)
|
||||
if fileInfo.Size() > s3manager.MaxUploadParts*s3manager.DefaultUploadPartSize {
|
||||
uploader.PartSize = fileInfo.Size() / (s3manager.MaxUploadParts - 1)
|
||||
}
|
||||
if _, err := uploader.Upload(context.Background(), &s3.PutObjectInput{
|
||||
if _, err := uploader.Upload(&s3manager.UploadInput{
|
||||
Bucket: aws.String(s.bucket),
|
||||
Key: aws.String(target),
|
||||
Body: file,
|
||||
StorageClass: types.StorageClass(s.scType),
|
||||
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)
|
||||
}
|
||||
@@ -148,8 +134,8 @@ func (s *s3Client) Download(src, target string) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
defer file.Close()
|
||||
downloader := manager.NewDownloader(s.client)
|
||||
if _, err = downloader.Download(context.Background(), file, &s3.GetObjectInput{
|
||||
downloader := s3manager.NewDownloader(&s.Sess)
|
||||
if _, err = downloader.Download(file, &s3.GetObjectInput{
|
||||
Bucket: aws.String(s.bucket),
|
||||
Key: aws.String(src),
|
||||
}); err != nil {
|
||||
@@ -160,23 +146,17 @@ 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 := s.client.ListObjectsV2(context.Background(), &s3.ListObjectsV2Input{
|
||||
Bucket: aws.String(s.bucket),
|
||||
Prefix: aws.String(prefix),
|
||||
outputs, err := svc.ListObjects(&s3.ListObjectsInput{
|
||||
Bucket: &s.bucket,
|
||||
Prefix: &prefix,
|
||||
})
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
for _, item := range outputs.Contents {
|
||||
result = append(result, aws.ToString(item.Key))
|
||||
result = append(result, *item.Key)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func normalizeEndpoint(endpoint string) string {
|
||||
if strings.HasPrefix(endpoint, "http://") || strings.HasPrefix(endpoint, "https://") {
|
||||
return endpoint
|
||||
}
|
||||
return "http://" + endpoint
|
||||
}
|
||||
|
||||
+32
-11
@@ -108,12 +108,16 @@ func (c *CommandHelper) run(name string, arg ...string) (string, error) {
|
||||
cmd = exec.CommandContext(newContext, name, arg...)
|
||||
} else {
|
||||
if c.context == nil {
|
||||
newContext = context.Background()
|
||||
cmd = exec.Command(name, arg...)
|
||||
} else {
|
||||
newContext = c.context
|
||||
cmd = exec.CommandContext(c.context, name, arg...)
|
||||
}
|
||||
}
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
Setpgid: true,
|
||||
}
|
||||
|
||||
customWriter := &CustomWriter{taskItem: c.taskItem}
|
||||
var stdout, stderr bytes.Buffer
|
||||
@@ -145,22 +149,39 @@ func (c *CommandHelper) run(name string, arg ...string) (string, error) {
|
||||
cmd.Dir = c.workDir
|
||||
}
|
||||
|
||||
err := cmd.Run()
|
||||
if err := cmd.Start(); err != nil {
|
||||
return "", fmt.Errorf("cmd.Start() failed with '%s'\n", err)
|
||||
}
|
||||
if c.taskItem != nil {
|
||||
customWriter.Flush()
|
||||
defer customWriter.Flush()
|
||||
}
|
||||
if c.timeout != 0 {
|
||||
if newContext != nil && errors.Is(newContext.Err(), context.DeadlineExceeded) {
|
||||
return "", buserr.New("ErrCmdTimeout")
|
||||
|
||||
done := make(chan error, 1)
|
||||
go func() {
|
||||
done <- cmd.Wait()
|
||||
}()
|
||||
select {
|
||||
case err := <-done:
|
||||
if err != nil {
|
||||
return handleErr(stdout, stderr, c.IgnoreExist1, err)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
if err.Error() == "signal: killed" {
|
||||
return "", buserr.New("ErrShutDown")
|
||||
return stdout.String(), nil
|
||||
case <-newContext.Done():
|
||||
if cmd.Process != nil && cmd.Process.Pid > 0 {
|
||||
syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
|
||||
}
|
||||
return handleErr(stdout, stderr, c.IgnoreExist1, err)
|
||||
var err error
|
||||
switch newContext.Err() {
|
||||
case context.DeadlineExceeded:
|
||||
err = buserr.New("ErrCmdTimeout")
|
||||
case context.Canceled:
|
||||
err = buserr.New("ErrShutDown")
|
||||
default:
|
||||
err = newContext.Err()
|
||||
}
|
||||
<-done
|
||||
return "", err
|
||||
}
|
||||
return stdout.String(), nil
|
||||
}
|
||||
|
||||
func WithContext(ctx context.Context) Option {
|
||||
|
||||
@@ -306,6 +306,10 @@ func IsValidDomain(domain string) bool {
|
||||
return re.GetRegex(re.DomainPattern).MatchString(domain)
|
||||
}
|
||||
|
||||
func IsValidNginxServerName(serverName string) bool {
|
||||
return re.GetRegex(re.NginxServerNamePattern).MatchString(serverName)
|
||||
}
|
||||
|
||||
func ContainsChinese(text string) bool {
|
||||
for _, char := range text {
|
||||
if unicode.Is(unicode.Han, char) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
@@ -67,6 +68,9 @@ func GetDBWithPath(dbPath string) (*gorm.DB, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if strings.HasSuffix(dbPath, "core.db") || strings.HasSuffix(dbPath, "agent.db") {
|
||||
initializeTxWatch(db)
|
||||
}
|
||||
sqlDB, dbError := db.DB()
|
||||
if dbError != nil {
|
||||
return nil, dbError
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type contextKey string
|
||||
|
||||
func initializeTxWatch(db *gorm.DB) {
|
||||
_ = db.Callback().Create().Before("gorm:begin_transaction").Register(
|
||||
"my_plugin:before_begin",
|
||||
func(db *gorm.DB) {
|
||||
var caller []string
|
||||
for i := 0; ; i++ {
|
||||
pc, file, line, ok := runtime.Caller(i)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
funcName := runtime.FuncForPC(pc).Name()
|
||||
if !strings.HasPrefix(funcName, "github.com/1Panel-dev/1Panel") {
|
||||
continue
|
||||
}
|
||||
fileParts := strings.Split(file, "/")
|
||||
fileName := fileParts[len(fileParts)-1]
|
||||
caller = append(caller, fmt.Sprintf("%s/%s:%d", funcName, fileName, line))
|
||||
}
|
||||
txID := generateTransactionID()
|
||||
db.Statement.Context = context.WithValue(
|
||||
db.Statement.Context,
|
||||
contextKey("tx_id"), txID,
|
||||
)
|
||||
db.Statement.Context = context.WithValue(
|
||||
db.Statement.Context,
|
||||
contextKey("tx_start"), time.Now(),
|
||||
)
|
||||
global.LOG.Debugf("[%s] tx start \n%s", txID, strings.Join(caller, "\n"))
|
||||
},
|
||||
)
|
||||
|
||||
_ = db.Callback().Create().After("gorm:commit_or_rollback_transaction").Register(
|
||||
"my_plugin:after_commit_or_rollback",
|
||||
func(db *gorm.DB) {
|
||||
ctx := db.Statement.Context
|
||||
txID, _ := ctx.Value(contextKey("tx_id")).(string)
|
||||
startTime, _ := ctx.Value(contextKey("tx_start")).(time.Time)
|
||||
if txID != "" {
|
||||
duration := time.Since(startTime)
|
||||
if db.Error != nil {
|
||||
global.LOG.Debugf("[%s] tx rollback! time: %v, err: %v", txID, duration, db.Error)
|
||||
} else {
|
||||
global.LOG.Debugf("[%s] tx commit! time: %v", txID, duration)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func generateTransactionID() string {
|
||||
return fmt.Sprintf("tx_%d", time.Now().UnixNano())
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user