Compare commits

...
77 Commits
Author SHA1 Message Date
ssongliu 3f26412585 fix: Modify OneDrive default connection settings (#9403) 2025-07-04 09:03:41 +00:00
ssongliu ac99d77fbb fix: Fix snap docker startup failure due to empty configuration (#9402) 2025-07-04 07:21:40 +00:00
ssongliu 4f6f7632f5 fix: Fix the problem of re-logging during the snapshot recovery process (#9401) 2025-07-04 03:59:40 +00:00
CityFun f74248f0d7 fix: Fixed issue with open app log failed with docker-compose (#9400) 2025-07-04 10:23:02 +08:00
ssongliu bb8a15ca56 fix: Fix system load spike during disk mount failures (#9399)
Refs #8827
2025-07-04 02:19:39 +00:00
ssongliu 52432002c7 fix: Fix port acquisition exception issue (#9398) 2025-07-03 16:31:34 +08:00
ssongliu 3fade48f8f fix: Add error ignore functionality to cronjob backups (#9396) 2025-07-03 16:31:25 +08:00
ssongliu fc81801c4c fix: Fix user settings loading failure after reinstallation (#9395) 2025-07-03 14:52:04 +08:00
ssongliu c23c5b2859 style: Add more pagination options to table (#9392)
Refs #5621
2025-07-03 05:55:38 +00:00
ssongliu ccec57e32d fix: Fix user settings loading failure after reinstallation (#9391) 2025-07-03 02:49:37 +00:00
CityFun 56ae5fbf70 fix: Fixed issue with build core failed (#9387) 2025-07-02 23:32:26 +08:00
CityFun 735b44856e style: Fix the problem where dropdown text is too long to display properly. (#9378) 2025-07-02 10:49:34 +00:00
ssongliu 1f6ea9f494 fix: Support docker configuration modifications for snap installations (#9377) 2025-07-02 09:43:35 +00:00
ssongliu afa643519f fix: Modify default values for recommended apps on dashboard (#9375) 2025-07-02 09:41:36 +00:00
ssongliu 1767b84026 fix: Fix overview page data loading/closing exception (#9373) 2025-07-02 09:39:35 +00:00
ssongliu e855e7692e fix: Fix permission errors when running script library as non-root User (#9370) 2025-07-02 04:25:34 +00:00
CityFun 94d37eb68a fix: Resolve the php runtime start failed (#9369) 2025-07-02 04:23:35 +00:00
CityFun e10b19bcde fix: Fixed issue with the mounted directory configuration cannot be displayed in runtime (#9368)
Refs https://github.com/1Panel-dev/1Panel/issues/9293
2025-07-02 04:21:35 +00:00
ssongliu e9192e75ea fix: Fix file existence check when deleting node upgrade records (#9365) 2025-07-01 14:29:33 +00:00
ssongliu 2fa4f68b1e fix: Update backup account documentation links (#9364) 2025-07-01 10:13:32 +00:00
ssongliu 08f53a4a37 fix: Support configurable docker config file snapshotting (#9363) 2025-07-01 07:49:32 +00:00
CityFun c522295c56 fix: Resolve the issue of database uninstallation failure (#9361) 2025-07-01 15:46:21 +08:00
BugKing 7a45548387 feat: add terminal icon for installed App (#9331)
* feat: add terminal icon for installed App

* refactor: 应用卡片打开容器终端,适配多个容器情况
2025-07-01 15:45:57 +08:00
ssongliu 810ea9c421 style: Handle overflow for node names with ellipsis truncation (#9360) 2025-07-01 07:45:32 +00:00
CityFun ba6a4fe6d7 fix: Resolve the issue of lost GPU configuration after upgrade ollama (#9359) 2025-07-01 07:43:32 +00:00
ssongliu 4d144f7a8e fix: Optimize backup account switching logic (#9358) 2025-07-01 06:31:32 +00:00
ssongliu 45c41184c1 fix: Optimize 1pctl restore command output (#9355) 2025-07-01 03:51:33 +00:00
ssongliu 5c29c5e7dd fix: Implement chunked upload for google drive file transfers (#9354) 2025-07-01 03:49:32 +00:00
蘭 4da9a84363 fix: Disable button when clearing cache and selecting size 0B (#9349) 2025-06-30 14:29:31 +00:00
蘭 22d8fb7867 fix: Fix the display error of the sub node website icon (#9348) 2025-06-30 11:11:31 +00:00
ssongliu c7058cb3e6 fix: Optimize container image repo restart detection logic (#9347)
Refs #8978
2025-06-30 11:09:30 +00:00
ssongliu e6092b2658 fix: Fix the compilation exception problem caused by dependencies (#9345) 2025-06-30 08:49:30 +00:00
ssongliu ae19b72e61 feat: Add root/sudo password-free access check for ssh (#9344) 2025-06-30 08:21:30 +00:00
dependabot[bot] da117582d6 build(deps): bump github.com/go-viper/mapstructure/v2 in /agent (#9343)
Bumps [github.com/go-viper/mapstructure/v2](https://github.com/go-viper/mapstructure) from 2.2.1 to 2.3.0.
- [Release notes](https://github.com/go-viper/mapstructure/releases)
- [Changelog](https://github.com/go-viper/mapstructure/blob/main/CHANGELOG.md)
- [Commits](https://github.com/go-viper/mapstructure/compare/v2.2.1...v2.3.0)

---
updated-dependencies:
- dependency-name: github.com/go-viper/mapstructure/v2
  dependency-version: 2.3.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-30 12:00:18 +08:00
CityFun c7ca1ccbd7 core: Remove unused code (#9342) 2025-06-30 03:55:30 +00:00
ssongliu 911b5c406d style: Optimize cronjob report page styling (#9341) 2025-06-30 03:53:30 +00:00
wanghe-fit2cloud 71ed4b946a feat: Adjust the logo’s aspect ratio to prevent it from appearing stretched 2025-06-29 23:19:55 +08:00
蘭 4ef9fcde59 fix: Default display of hidden files (#9327)
#9325 
#9324
2025-06-27 10:23:24 +00:00
ssongliu 7889b5ad69 fix: Optimize script-type cronjob execution output (#9326) 2025-06-27 17:57:40 +08:00
ssongliu be6d3ea337 fix: Update compression backup exclusion rules (#9323) 2025-06-27 09:25:23 +00:00
CityFun 64fd715973 perf: optimization php config (#9321) 2025-06-27 16:56:13 +08:00
ssongliu 315f99a03a feat: Add application exclusion for cronjob snapshots (#9320)
Refs #8914
2025-06-27 08:47:26 +00:00
ssongliu 7e1351c543 fix: resolve code warnings and improve code quality (#9322) 2025-06-27 16:47:01 +08:00
CityFun bd3c829653 fix: translate the requestTimeout msg for frontend (#9316)
Refs https://github.com/1Panel-dev/1Panel/issues/9308
2025-06-27 05:49:24 +00:00
蘭 4f6dde02d2 fix: Fix the issue of missing line breaks in copied log content (#9314)
#9099
2025-06-27 05:47:25 +00:00
蘭 8cc7d1f67f fix: Fix the issue of multiple selection moving folder errors (#9317) 2025-06-27 05:45:23 +00:00
ssongliu 2bbba9d755 style: Adjust node option popup interaction (#9312)
Refs #9290
2025-06-27 02:23:23 +00:00
CityFun e9e4755348 Revert "fix: Fix missing line breaks in copied logs on the log page (… (#9311) 2025-06-27 02:19:26 +00:00
CityFun 9fbb63df95 fix: Resolve command execution failures in the PHP runtime environmen… (#9299)
Refs https://github.com/1Panel-dev/1Panel/issues/9286
2025-06-26 08:31:23 +00:00
ssongliu 5b5a649589 fix: resolve Google Drive token refresh failure (#9298)
Refs #9223
2025-06-26 07:37:22 +00:00
蘭 79556affbd fix: Fix the preview image error of child nodes (#9296)
#9245
2025-06-26 06:43:22 +00:00
蘭 9cba19d4db fix: Fix the process status error issue (#9285) 2025-06-25 22:05:29 +08:00
蘭 4f377c04b8 fix: Fix missing line breaks in copied logs on the log page (#9283) 2025-06-25 22:05:12 +08:00
ssongliu 763df5606b fix: Fix snapshot restoration missing website backup detection (#9282) 2025-06-25 22:04:53 +08:00
ssongliu e1d20e3ec9 fix: Optimize snapshot and snapshot recovery mechanism (#9279) 2025-06-25 16:29:15 +08:00
CityFun 215c082a04 perf: add some config for website_default.conf (#9278)
Refs https://github.com/1Panel-dev/1Panel/issues/8837
2025-06-25 08:23:21 +00:00
ssongliu 984985e650 fix: Fix snapshot restoration for container configuration errors (#9277)
Refs #9216
2025-06-25 08:21:21 +00:00
蘭 249b3c3245 fix: Fixed logging errors for uploaded files (#9273) 2025-06-25 08:19:20 +00:00
Swt242 725786d6aa fix: Fixed logging errors for uploaded files (#9204) 2025-06-25 11:46:27 +08:00
蘭 2edddaf487 feat: Specify the interpretation code based on the file content (#9267) 2025-06-24 14:17:14 +00:00
ssongliu 49cbab08c1 fix: Modify snapshot synchronization and import name restrictions (#9266) 2025-06-24 18:43:56 +08:00
ssongliu a75df66151 fix: Rollback snapshot code (#9263) 2025-06-24 10:41:14 +00:00
CityFun 43e9c13c5e perf: Optimize and Edit PHP Runtime Environment Version Switching (#9265) 2025-06-24 18:40:53 +08:00
CityFun 5ad06f121b fix: fix issue with subsite dir error (#9259) 2025-06-24 10:39:14 +00:00
wanghe-fit2cloud 0eaaf7aacb feat: Adjust the logo’s aspect ratio to prevent it from appearing stretched 2025-06-24 17:29:15 +08:00
CityFun dd44fdd1f2 fix: Fixed issue with tar file failed with exist 1 (#9261) 2025-06-24 16:57:27 +08:00
CityFun 669855de70 fix: Fixed the issue that caused the error (bufio.Scanner: token too long) when viewing container log (#9256)
Refs https://github.com/1Panel-dev/1Panel/issues/9241
2025-06-24 05:53:13 +00:00
CityFun 193ae2b7d6 fix: fix issue with enable website ssl with ipv6 failed (#9255) 2025-06-24 13:44:17 +08:00
Alan af4b23e0e0 fix: fixed dashboard operating system platform Version (#9247) 2025-06-24 09:31:14 +08:00
蘭 c35991315d fix: Fix page loading issue with no data status (#9248) 2025-06-23 22:14:48 +08:00
ssongliu 9aa852370c fix: Split snapshot application backup (#9244) 2025-06-23 10:40:13 +00:00
CityFun 8f18497551 feat: add remark for runtime (#9242) 2025-06-23 18:37:37 +08:00
CityFun 4c59951e8c style: change dnsAccount select option style in create ssl page (#9239) 2025-06-23 06:48:12 +00:00
CityFun eb2a80d216 style: hightlight ipv6 address in task log (#9238)
Refs https://github.com/1Panel-dev/1Panel/issues/9118
2025-06-23 06:46:13 +00:00
CityFun 41d0175a6d style: change show diff button style for upgrade app (#9237)
Refs https://github.com/1Panel-dev/1Panel/issues/9207
2025-06-23 06:44:11 +00:00
igophper 2f6aa0f45b fix: Fix docker status flicker issue (#9218) 2025-06-23 13:46:03 +08:00
igophper 17c685bc4c fix: Fix the apps store docker status error (#9217) 2025-06-23 13:44:09 +08:00
158 changed files with 2465 additions and 1387 deletions
+1 -1
View File
@@ -296,7 +296,7 @@ func (b *BaseApi) SaveContent(c *gin.Context) {
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Security Timestamp // @Security Timestamp
// @Router /files/upload [post] // @Router /files/upload [post]
// @x-panel-log {"bodyKeys":["path"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"上传文件 [path]","formatEN":"Upload file [path]"} // @x-panel-log {"bodyKeys":["path", "file"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"上传文件 [path]/[file]","formatEN":"Upload file [path]/[file]"}
func (b *BaseApi) UploadFiles(c *gin.Context) { func (b *BaseApi) UploadFiles(c *gin.Context) {
form, err := c.MultipartForm() form, err := c.MultipartForm()
if err != nil { if err != nil {
+4 -4
View File
@@ -98,20 +98,20 @@ func (b *BaseApi) CreateRepo(c *gin.Context) {
// @Tags Container Image-repo // @Tags Container Image-repo
// @Summary Delete image repo // @Summary Delete image repo
// @Accept json // @Accept json
// @Param request body dto.ImageRepoDelete true "request" // @Param request body dto.OperateByID true "request"
// @Produce json // @Produce json
// @Success 200 // @Success 200
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Security Timestamp // @Security Timestamp
// @Router /containers/repo/del [post] // @Router /containers/repo/del [post]
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"image_repos","output_column":"name","output_value":"names"}],"formatZH":"删除镜像仓库 [names]","formatEN":"delete image repo [names]"} // @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"image_repos","output_column":"name","output_value":"name"}],"formatZH":"删除镜像仓库 [name]","formatEN":"delete image repo [name]"}
func (b *BaseApi) DeleteRepo(c *gin.Context) { func (b *BaseApi) DeleteRepo(c *gin.Context) {
var req dto.ImageRepoDelete var req dto.OperateByID
if err := helper.CheckBindAndValidate(&req, c); err != nil { if err := helper.CheckBindAndValidate(&req, c); err != nil {
return return
} }
if err := imageRepoService.BatchDelete(req); err != nil { if err := imageRepoService.Delete(req); err != nil {
helper.InternalServer(c, err) helper.InternalServer(c, err)
return return
} }
+20
View File
@@ -535,3 +535,23 @@ func (b *BaseApi) GetPHPContainerConfig(c *gin.Context) {
} }
helper.SuccessWithData(c, data) helper.SuccessWithData(c, data)
} }
// @Tags Runtime
// @Summary Update runtime remark
// @Accept json
// @Param request body request.RuntimeRemarkUpdate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /runtimes/remark [post]
func (b *BaseApi) UpdateRuntimeRemark(c *gin.Context) {
var req request.RuntimeRemark
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := runtimeService.UpdateRemark(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
+30 -21
View File
@@ -29,27 +29,34 @@ type CronjobOperate struct {
ContainerName string `json:"containerName"` ContainerName string `json:"containerName"`
User string `json:"user"` User string `json:"user"`
ScriptID uint `json:"scriptID"` ScriptID uint `json:"scriptID"`
AppID string `json:"appID"` AppID string `json:"appID"`
Website string `json:"website"` Website string `json:"website"`
ExclusionRules string `json:"exclusionRules"` ExclusionRules string `json:"exclusionRules"`
DBType string `json:"dbType"` DBType string `json:"dbType"`
DBName string `json:"dbName"` DBName string `json:"dbName"`
URL string `json:"url"` URL string `json:"url"`
IsDir bool `json:"isDir"` IsDir bool `json:"isDir"`
SourceDir string `json:"sourceDir"` SourceDir string `json:"sourceDir"`
SnapshotRule SnapshotRule `json:"snapshotRule"`
SourceAccountIDs string `json:"sourceAccountIDs"` SourceAccountIDs string `json:"sourceAccountIDs"`
DownloadAccountID uint `json:"downloadAccountID"` DownloadAccountID uint `json:"downloadAccountID"`
RetainCopies int `json:"retainCopies" validate:"number,min=1"` RetainCopies int `json:"retainCopies" validate:"number,min=1"`
RetryTimes int `json:"retryTimes" validate:"number,min=0"` RetryTimes int `json:"retryTimes" validate:"number,min=0"`
Timeout uint `json:"timeout" validate:"number,min=1"` Timeout uint `json:"timeout" validate:"number,min=1"`
IgnoreErr bool `json:"ignoreErr"`
Secret string `json:"secret"` Secret string `json:"secret"`
AlertCount uint `json:"alertCount"` AlertCount uint `json:"alertCount"`
AlertTitle string `json:"alertTitle"` AlertTitle string `json:"alertTitle"`
} }
type SnapshotRule struct {
WithImage bool `json:"withImage"`
IgnoreAppIDs []uint `json:"ignoreAppIDs"`
}
type CronjobUpdateStatus struct { type CronjobUpdateStatus struct {
ID uint `json:"id" validate:"required"` ID uint `json:"id" validate:"required"`
Status string `json:"status" validate:"required"` Status string `json:"status" validate:"required"`
@@ -87,18 +94,20 @@ type CronjobInfo struct {
ContainerName string `json:"containerName"` ContainerName string `json:"containerName"`
User string `json:"user"` User string `json:"user"`
ScriptID uint `json:"scriptID"` ScriptID uint `json:"scriptID"`
AppID string `json:"appID"` AppID string `json:"appID"`
Website string `json:"website"` Website string `json:"website"`
ExclusionRules string `json:"exclusionRules"` ExclusionRules string `json:"exclusionRules"`
DBType string `json:"dbType"` DBType string `json:"dbType"`
DBName string `json:"dbName"` DBName string `json:"dbName"`
URL string `json:"url"` URL string `json:"url"`
IsDir bool `json:"isDir"` IsDir bool `json:"isDir"`
SourceDir string `json:"sourceDir"` SourceDir string `json:"sourceDir"`
RetainCopies int `json:"retainCopies"` RetainCopies int `json:"retainCopies"`
RetryTimes int `json:"retryTimes"` RetryTimes int `json:"retryTimes"`
Timeout uint `json:"timeout"` Timeout uint `json:"timeout"`
IgnoreErr bool `json:"ignoreErr"`
SnapshotRule SnapshotRule `json:"snapshotRule"`
SourceAccounts []string `json:"sourceAccounts"` SourceAccounts []string `json:"sourceAccounts"`
DownloadAccount string `json:"downloadAccount"` DownloadAccount string `json:"downloadAccount"`
+4 -4
View File
@@ -6,8 +6,8 @@ type ImageRepoCreate struct {
Name string `json:"name" validate:"required"` Name string `json:"name" validate:"required"`
DownloadUrl string `json:"downloadUrl"` DownloadUrl string `json:"downloadUrl"`
Protocol string `json:"protocol"` Protocol string `json:"protocol"`
Username string `json:"username" validate:"max=256"` Username string `json:"username"`
Password string `json:"password" validate:"max=256"` Password string `json:"password"`
Auth bool `json:"auth"` Auth bool `json:"auth"`
} }
@@ -15,8 +15,8 @@ type ImageRepoUpdate struct {
ID uint `json:"id"` ID uint `json:"id"`
DownloadUrl string `json:"downloadUrl"` DownloadUrl string `json:"downloadUrl"`
Protocol string `json:"protocol"` Protocol string `json:"protocol"`
Username string `json:"username" validate:"max=256"` Username string `json:"username"`
Password string `json:"password" validate:"max=256"` Password string `json:"password"`
Auth bool `json:"auth"` Auth bool `json:"auth"`
} }
+6 -5
View File
@@ -92,11 +92,12 @@ type FileWget struct {
} }
type FileMove struct { type FileMove struct {
Type string `json:"type" validate:"required"` Type string `json:"type" validate:"required"`
OldPaths []string `json:"oldPaths" validate:"required"` OldPaths []string `json:"oldPaths" validate:"required"`
NewPath string `json:"newPath" validate:"required"` NewPath string `json:"newPath" validate:"required"`
Name string `json:"name"` Name string `json:"name"`
Cover bool `json:"cover"` Cover bool `json:"cover"`
CoverPaths []string `json:"coverPaths"`
} }
type FileDownload struct { type FileDownload struct {
+26 -17
View File
@@ -12,15 +12,17 @@ type RuntimeSearch struct {
} }
type RuntimeCreate struct { type RuntimeCreate struct {
AppDetailID uint `json:"appDetailId"` AppDetailID uint `json:"appDetailId"`
Name string `json:"name"` Name string `json:"name"`
Params map[string]interface{} `json:"params"` Resource string `json:"resource"`
Resource string `json:"resource"` Image string `json:"image"`
Image string `json:"image"` Type string `json:"type"`
Type string `json:"type"` Version string `json:"version"`
Version string `json:"version"` Source string `json:"source"`
Source string `json:"source"` CodeDir string `json:"codeDir"`
CodeDir string `json:"codeDir"` Remark string `json:"remark"`
Params map[string]interface{} `json:"params"`
NodeConfig NodeConfig
} }
@@ -53,14 +55,16 @@ type RuntimeDelete struct {
} }
type RuntimeUpdate struct { type RuntimeUpdate struct {
Name string `json:"name"` Name string `json:"name"`
ID uint `json:"id"` ID uint `json:"id"`
Params map[string]interface{} `json:"params"` Image string `json:"image"`
Image string `json:"image"` Version string `json:"version"`
Version string `json:"version"` Rebuild bool `json:"rebuild"`
Rebuild bool `json:"rebuild"` Source string `json:"source"`
Source string `json:"source"` CodeDir string `json:"codeDir"`
CodeDir string `json:"codeDir"` Remark string `json:"remark"`
Params map[string]interface{} `json:"params"`
NodeConfig NodeConfig
} }
@@ -131,3 +135,8 @@ type PHPContainerConfig struct {
Environments []Environment `json:"environments"` Environments []Environment `json:"environments"`
Volumes []Volume `json:"volumes"` Volumes []Volume `json:"volumes"`
} }
type RuntimeRemark struct {
ID uint `json:"id" validate:"required"`
Remark string `json:"remark"`
}
+2
View File
@@ -32,6 +32,8 @@ type WebsiteCreate struct {
TaskID string `json:"taskID"` TaskID string `json:"taskID"`
ParentWebsiteID uint `json:"parentWebsiteID"` ParentWebsiteID uint `json:"parentWebsiteID"`
SiteDir string `json:"siteDir"`
RuntimeConfig RuntimeConfig
FtpConfig FtpConfig
DataBaseConfig DataBaseConfig
+1
View File
@@ -53,6 +53,7 @@ type ExistFileInfo struct {
Path string `json:"path"` Path string `json:"path"`
Size int64 `json:"size"` Size int64 `json:"size"`
ModTime time.Time `json:"modTime"` ModTime time.Time `json:"modTime"`
IsDir bool `json:"isDir"`
} }
type UserInfo struct { type UserInfo struct {
+2
View File
@@ -30,6 +30,7 @@ type RuntimeDTO struct {
Volumes []request.Volume `json:"volumes"` Volumes []request.Volume `json:"volumes"`
ContainerStatus string `json:"containerStatus"` ContainerStatus string `json:"containerStatus"`
Container string `json:"container"` Container string `json:"container"`
Remark string `json:"remark"`
} }
type PackageScripts struct { type PackageScripts struct {
@@ -53,6 +54,7 @@ func NewRuntimeDTO(runtime model.Runtime) RuntimeDTO {
Port: runtime.Port, Port: runtime.Port,
Path: runtime.GetPath(), Path: runtime.GetPath(),
Container: runtime.ContainerName, Container: runtime.ContainerName,
Remark: runtime.Remark,
} }
} }
-2
View File
@@ -23,8 +23,6 @@ type SettingInfo struct {
AppStoreSyncStatus string `json:"appStoreSyncStatus"` AppStoreSyncStatus string `json:"appStoreSyncStatus"`
FileRecycleBin string `json:"fileRecycleBin"` FileRecycleBin string `json:"fileRecycleBin"`
SnapshotIgnore string `json:"snapshotIgnore"`
} }
type SettingUpdate struct { type SettingUpdate struct {
+10 -5
View File
@@ -23,11 +23,14 @@ type SnapshotCreate struct {
BackupData []DataTree `json:"backupData"` BackupData []DataTree `json:"backupData"`
PanelData []DataTree `json:"panelData"` PanelData []DataTree `json:"panelData"`
WithDockerConf bool `json:"withDockerConf"`
WithMonitorData bool `json:"withMonitorData"` WithMonitorData bool `json:"withMonitorData"`
WithLoginLog bool `json:"withLoginLog"` WithLoginLog bool `json:"withLoginLog"`
WithOperationLog bool `json:"withOperationLog"` WithOperationLog bool `json:"withOperationLog"`
WithSystemLog bool `json:"withSystemLog"` WithSystemLog bool `json:"withSystemLog"`
WithTaskLog bool `json:"withTaskLog"` WithTaskLog bool `json:"withTaskLog"`
IgnoreFiles []string `json:"ignoreFiles"`
} }
type SnapshotData struct { type SnapshotData struct {
@@ -35,11 +38,13 @@ type SnapshotData struct {
BackupData []DataTree `json:"backupData"` BackupData []DataTree `json:"backupData"`
PanelData []DataTree `json:"panelData"` PanelData []DataTree `json:"panelData"`
WithMonitorData bool `json:"withMonitorData"` WithDockerConf bool `json:"withDockerConf"`
WithLoginLog bool `json:"withLoginLog"` WithMonitorData bool `json:"withMonitorData"`
WithOperationLog bool `json:"withOperationLog"` WithLoginLog bool `json:"withLoginLog"`
WithSystemLog bool `json:"withSystemLog"` WithOperationLog bool `json:"withOperationLog"`
WithTaskLog bool `json:"withTaskLog"` WithSystemLog bool `json:"withSystemLog"`
WithTaskLog bool `json:"withTaskLog"`
IgnoreFiles []string `json:"ignoreFiles"`
} }
type DataTree struct { type DataTree struct {
ID string `json:"id"` ID string `json:"id"`
+2
View File
@@ -29,12 +29,14 @@ type Cronjob struct {
URL string `json:"url"` URL string `json:"url"`
IsDir bool `json:"isDir"` IsDir bool `json:"isDir"`
SourceDir string `json:"sourceDir"` SourceDir string `json:"sourceDir"`
SnapshotRule string `json:"snapshotRule"`
ExclusionRules string `json:"exclusionRules"` ExclusionRules string `json:"exclusionRules"`
SourceAccountIDs string `json:"sourceAccountIDs"` SourceAccountIDs string `json:"sourceAccountIDs"`
DownloadAccountID uint `json:"downloadAccountID"` DownloadAccountID uint `json:"downloadAccountID"`
RetryTimes uint `json:"retryTimes"` RetryTimes uint `json:"retryTimes"`
Timeout uint `json:"timeout"` Timeout uint `json:"timeout"`
IgnoreErr bool `json:"ignoreErr"`
RetainCopies uint64 `json:"retainCopies"` RetainCopies uint64 `json:"retainCopies"`
Status string `json:"status"` Status string `json:"status"`
+1
View File
@@ -23,6 +23,7 @@ type Runtime struct {
Message string `json:"message"` Message string `json:"message"`
CodeDir string `json:"codeDir"` CodeDir string `json:"codeDir"`
ContainerName string `json:"containerName"` ContainerName string `json:"containerName"`
Remark string `json:"remark"`
} }
func (r *Runtime) GetComposePath() string { func (r *Runtime) GetComposePath() string {
+6 -3
View File
@@ -15,14 +15,17 @@ type Snapshot struct {
TaskRecoverID string `json:"taskRecoverID"` TaskRecoverID string `json:"taskRecoverID"`
TaskRollbackID string `json:"taskRollbackID"` TaskRollbackID string `json:"taskRollbackID"`
AppData string `json:"appData"` AppData string `json:"appData"`
PanelData string `json:"panelData"` PanelData string `json:"panelData"`
BackupData string `json:"backupData"` BackupData string `json:"backupData"`
WithDockerConf bool `json:"withDockerConf"`
WithMonitorData bool `json:"withMonitorData"` WithMonitorData bool `json:"withMonitorData"`
WithLoginLog bool `json:"withLoginLog"` WithLoginLog bool `json:"withLoginLog"`
WithOperationLog bool `json:"withOperationLog"` WithOperationLog bool `json:"withOperationLog"`
WithSystemLog bool `json:"withSystemLog"` WithSystemLog bool `json:"withSystemLog"`
WithTaskLog bool `json:"withTaskLog"` WithTaskLog bool `json:"withTaskLog"`
IgnoreFiles string `json:"ignoreFiles"`
InterruptStep string `json:"interruptStep"` InterruptStep string `json:"interruptStep"`
RecoverStatus string `json:"recoverStatus"` RecoverStatus string `json:"recoverStatus"`
+19 -19
View File
@@ -4,7 +4,6 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/docker/docker/api/types/container"
"math" "math"
"net/http" "net/http"
"os" "os"
@@ -15,28 +14,25 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/1Panel-dev/1Panel/agent/utils/files" "github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/utils/req_helper"
"gopkg.in/yaml.v3"
"github.com/1Panel-dev/1Panel/agent/utils/env"
"github.com/1Panel-dev/1Panel/agent/utils/nginx"
"github.com/joho/godotenv"
"github.com/1Panel-dev/1Panel/agent/app/dto/request" "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/dto/response"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/model" "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/constant"
"github.com/1Panel-dev/1Panel/agent/global" "github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/common" "github.com/1Panel-dev/1Panel/agent/utils/common"
"github.com/1Panel-dev/1Panel/agent/utils/compose" "github.com/1Panel-dev/1Panel/agent/utils/compose"
"github.com/1Panel-dev/1Panel/agent/utils/docker" "github.com/1Panel-dev/1Panel/agent/utils/docker"
"github.com/1Panel-dev/1Panel/agent/utils/env"
"github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/1Panel-dev/1Panel/agent/utils/nginx"
"github.com/1Panel-dev/1Panel/agent/utils/req_helper"
"github.com/docker/docker/api/types/container"
"github.com/joho/godotenv"
"github.com/pkg/errors" "github.com/pkg/errors"
"gopkg.in/yaml.v3"
) )
type AppInstallService struct { type AppInstallService struct {
@@ -124,7 +120,7 @@ func (a *AppInstallService) Page(req request.AppInstalledSearch) (int64, []respo
} }
} }
installDTOs, err := handleInstalled(installs, req.Update, req.Sync) installDTOs, _ := handleInstalled(installs, req.Update, req.Sync)
if req.Update { if req.Update {
total = int64(len(installDTOs)) total = int64(len(installDTOs))
} }
@@ -635,10 +631,14 @@ func (a *AppInstallService) DeleteCheck(installID uint) ([]dto.AppResource, erro
resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithLinkId(appInstall.ID), repo.WithByFrom(constant.AppResourceLocal)) resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithLinkId(appInstall.ID), repo.WithByFrom(constant.AppResourceLocal))
for _, resource := range resources { for _, resource := range resources {
linkInstall, _ := appInstallRepo.GetFirst(repo.WithByID(resource.AppInstallId)) linkInstall, _ := appInstallRepo.GetFirst(repo.WithByID(resource.AppInstallId))
res = append(res, dto.AppResource{ if linkInstall.ID > 0 {
Type: "app", res = append(res, dto.AppResource{
Name: linkInstall.Name, Type: "app",
}) Name: linkInstall.Name,
})
} else {
_ = appInstallResourceRepo.DeleteBy(context.Background(), appInstallResourceRepo.WithAppInstallId(resource.AppInstallId))
}
} }
return res, nil return res, nil
} }
+66 -104
View File
@@ -5,7 +5,6 @@ import (
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/compose-spec/compose-go/v2/types"
"log" "log"
"math" "math"
"net/http" "net/http"
@@ -19,39 +18,33 @@ import (
"strings" "strings"
"time" "time"
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/utils/nginx"
"github.com/1Panel-dev/1Panel/agent/utils/nginx/parser"
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
"github.com/1Panel-dev/1Panel/agent/app/task"
"github.com/1Panel-dev/1Panel/agent/utils/req_helper"
"github.com/docker/docker/api/types/container"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper" "github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/subosito/gotenv"
"gopkg.in/yaml.v3"
"github.com/1Panel-dev/1Panel/agent/utils/env"
"github.com/1Panel-dev/1Panel/agent/app/dto/response"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/app/dto" "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/model"
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/app/task"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/constant" "github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global" "github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/common" "github.com/1Panel-dev/1Panel/agent/utils/common"
"github.com/1Panel-dev/1Panel/agent/utils/compose" "github.com/1Panel-dev/1Panel/agent/utils/compose"
"github.com/1Panel-dev/1Panel/agent/utils/docker" "github.com/1Panel-dev/1Panel/agent/utils/docker"
composeV2 "github.com/1Panel-dev/1Panel/agent/utils/docker" composeV2 "github.com/1Panel-dev/1Panel/agent/utils/docker"
"github.com/1Panel-dev/1Panel/agent/utils/env"
"github.com/1Panel-dev/1Panel/agent/utils/files" "github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/1Panel-dev/1Panel/agent/utils/nginx"
"github.com/1Panel-dev/1Panel/agent/utils/nginx/parser"
"github.com/1Panel-dev/1Panel/agent/utils/req_helper"
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
"github.com/compose-spec/compose-go/v2/types"
"github.com/docker/docker/api/types/container"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/subosito/gotenv"
"gopkg.in/yaml.v3"
) )
type DatabaseOp string type DatabaseOp string
@@ -386,21 +379,25 @@ func deleteAppInstall(deleteReq request.AppInstallDelete) error {
} }
resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(install.ID)) resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(install.ID))
if deleteReq.DeleteDB && len(resources) > 0 { if len(resources) > 0 {
del := dto.DelAppLink{ if deleteReq.DeleteDB {
Ctx: ctx, del := dto.DelAppLink{
Install: &install, Ctx: ctx,
ForceDelete: deleteReq.ForceDelete, Install: &install,
Task: uninstallTask, ForceDelete: deleteReq.ForceDelete,
} Task: uninstallTask,
t.LogWithOps(task.TaskDelete, i18n.GetMsgByKey("Database"))
if err = deleteLink(del); err != nil {
t.LogFailedWithOps(task.TaskDelete, i18n.GetMsgByKey("Database"), err)
if !deleteReq.ForceDelete {
return err
} }
t.LogWithOps(task.TaskDelete, i18n.GetMsgByKey("Database"))
if err = deleteLink(del); err != nil {
t.LogFailedWithOps(task.TaskDelete, i18n.GetMsgByKey("Database"), err)
if !deleteReq.ForceDelete {
return err
}
}
t.LogSuccessWithOps(task.TaskDelete, i18n.GetMsgByKey("Database"))
} else {
_ = appInstallResourceRepo.DeleteBy(ctx, appInstallResourceRepo.WithAppInstallId(install.ID))
} }
t.LogSuccessWithOps(task.TaskDelete, i18n.GetMsgByKey("Database"))
} }
if DatabaseKeys[install.App.Key] > 0 { if DatabaseKeys[install.App.Key] > 0 {
@@ -489,17 +486,14 @@ func deleteLink(del dto.DelAppLink) error {
return appInstallResourceRepo.DeleteBy(del.Ctx, appInstallResourceRepo.WithAppInstallId(install.ID)) return appInstallResourceRepo.DeleteBy(del.Ctx, appInstallResourceRepo.WithAppInstallId(install.ID))
} }
func getUpgradeCompose(install model.AppInstall, detail model.AppDetail) (string, error) { func handleUpgradeCompose(install model.AppInstall, detail model.AppDetail) (map[string]interface{}, error) {
if detail.DockerCompose == "" {
return "", nil
}
composeMap := make(map[string]interface{}) composeMap := make(map[string]interface{})
if err := yaml.Unmarshal([]byte(detail.DockerCompose), &composeMap); err != nil { if err := yaml.Unmarshal([]byte(detail.DockerCompose), &composeMap); err != nil {
return "", err return nil, err
} }
value, ok := composeMap["services"] value, ok := composeMap["services"]
if !ok || value == nil { if !ok || value == nil {
return "", buserr.New("ErrFileParse") return nil, buserr.New("ErrFileParse")
} }
servicesMap := value.(map[string]interface{}) servicesMap := value.(map[string]interface{})
if len(servicesMap) == 1 { if len(servicesMap) == 1 {
@@ -517,6 +511,34 @@ func getUpgradeCompose(install model.AppInstall, detail model.AppDetail) (string
delete(servicesMap, oldServiceName) delete(servicesMap, oldServiceName)
} }
} }
serviceValue := servicesMap[install.ServiceName].(map[string]interface{})
oldComposeMap := make(map[string]interface{})
if err := yaml.Unmarshal([]byte(install.DockerCompose), &oldComposeMap); err != nil {
return nil, err
}
oldValue, ok := oldComposeMap["services"]
if !ok || oldValue == nil {
return nil, buserr.New("ErrFileParse")
}
oldValueMap := oldValue.(map[string]interface{})
oldServiceValue := oldValueMap[install.ServiceName].(map[string]interface{})
if oldServiceValue["deploy"] != nil {
serviceValue["deploy"] = oldServiceValue["deploy"]
}
servicesMap[install.ServiceName] = serviceValue
composeMap["services"] = servicesMap
return composeMap, nil
}
func getUpgradeCompose(install model.AppInstall, detail model.AppDetail) (string, error) {
if detail.DockerCompose == "" {
return "", nil
}
composeMap, err := handleUpgradeCompose(install, detail)
if err != nil {
return "", err
}
envs := make(map[string]interface{}) envs := make(map[string]interface{})
if err := json.Unmarshal([]byte(install.Env), &envs); err != nil { if err := json.Unmarshal([]byte(install.Env), &envs); err != nil {
return "", err return "", err
@@ -617,7 +639,7 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
if err != nil { if err != nil {
return err return err
} }
dockerCLi, err := docker.NewClient() dockerCLi, _ := docker.NewClient()
if req.PullImage { if req.PullImage {
images, err := composeV2.GetDockerComposeImagesV2(content, []byte(detail.DockerCompose)) images, err := composeV2.GetDockerComposeImagesV2(content, []byte(detail.DockerCompose))
if err != nil { if err != nil {
@@ -674,63 +696,6 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
} }
envParams := make(map[string]string, len(envs)) envParams := make(map[string]string, len(envs))
handleMap(envs, envParams) handleMap(envs, envParams)
if install.App.Key == "openresty" && install.App.Resource == "remote" && !common.CompareVersion(install.Version, "1.25.3.2-0-1") {
t.Log(i18n.GetMsgByKey("MoveSiteDir"))
siteDir := path.Join(global.Dir.DataDir, "www")
envParams["WEBSITE_DIR"] = siteDir
oldSiteDir := path.Join(install.GetPath(), "www")
t.Log(i18n.GetWithName("MoveSiteToDir", siteDir))
if err := fileOp.CopyDir(oldSiteDir, global.Dir.DataDir); err != nil {
t.Log(i18n.GetMsgByKey("ErrMoveSiteDir"))
return err
}
newConfDir := path.Join(global.Dir.DataDir, "www", "conf.d")
_ = fileOp.CreateDir(newConfDir, constant.DirPerm)
oldConfDir := path.Join(install.GetPath(), "conf/conf.d")
items, err := os.ReadDir(oldConfDir)
if err != nil {
return err
}
for _, item := range items {
itemPath := path.Join(oldConfDir, item.Name())
if item.IsDir() {
_ = fileOp.Mv(itemPath, newConfDir)
}
if item.Name() != "default.conf" && item.Name() != "00.default.conf" {
_ = fileOp.Mv(itemPath, newConfDir)
}
}
nginxConfPath := path.Join(install.GetPath(), "conf", "nginx.conf")
parse, err := parser.NewParser(nginxConfPath)
if err != nil {
return err
}
config, err := parse.Parse()
if err != nil {
return err
}
config.FilePath = nginxConfPath
httpDirective := config.FindHttp()
httpDirective.UpdateDirective("include", []string{"/usr/local/openresty/nginx/conf/default/*.conf"})
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
return buserr.WithErr("ErrUpdateBuWebsite", err)
}
t.Log(i18n.GetMsgByKey("DeleteRuntimePHP"))
_ = fileOp.DeleteDir(path.Join(global.Dir.RuntimeDir, "php"))
websites, _ := websiteRepo.List(repo.WithByType("runtime"))
for _, website := range websites {
runtime, _ := runtimeRepo.GetFirst(context.Background(), repo.WithByID(website.RuntimeID))
if runtime != nil && runtime.Type == "php" {
website.Type = constant.Static
website.RuntimeID = 0
_ = websiteRepo.SaveWithoutCtx(&website)
}
}
_ = runtimeRepo.DeleteBy(repo.WithByType("php"))
t.Log(i18n.GetMsgByKey("MoveSiteDirSuccess"))
}
if err = env.Write(envParams, install.GetEnvPath()); err != nil { if err = env.Write(envParams, install.GetEnvPath()); err != nil {
return err return err
} }
@@ -1802,10 +1767,7 @@ func ignoreUpdate(installed model.AppInstall) bool {
return true return true
} }
ignores, _ := appIgnoreUpgradeRepo.List(appDetailRepo.WithAppId(installed.AppId), appIgnoreUpgradeRepo.WithScope("all")) ignores, _ := appIgnoreUpgradeRepo.List(appDetailRepo.WithAppId(installed.AppId), appIgnoreUpgradeRepo.WithScope("all"))
if len(ignores) > 0 { return len(ignores) > 0
return true
}
return false
} }
func RequestDownloadCallBack(downloadCallBackUrl string) { func RequestDownloadCallBack(downloadCallBackUrl string) {
-2
View File
@@ -290,8 +290,6 @@ func (u *BackupService) RefreshToken(req dto.OperateByID) error {
switch backup.Type { switch backup.Type {
case constant.OneDrive: case constant.OneDrive:
refreshToken, err = client.RefreshToken("refresh_token", "refreshToken", varMap) refreshToken, err = client.RefreshToken("refresh_token", "refreshToken", varMap)
case constant.GoogleDrive:
refreshToken, err = client.RefreshGoogleToken("refresh_token", "refreshToken", varMap)
case constant.ALIYUN: case constant.ALIYUN:
refreshToken, err = client.RefreshALIToken(varMap) refreshToken, err = client.RefreshALIToken(varMap)
} }
+1 -2
View File
@@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"os" "os"
"path" "path"
"strings"
"sync" "sync"
"github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/dto"
@@ -194,7 +193,7 @@ func (u *BackupRecordService) ListFiles(req dto.OperateByID) []string {
var datas []string var datas []string
for _, file := range files { for _, file := range files {
fileName := path.Base(file) fileName := path.Base(file)
if len(file) != 0 && (strings.HasPrefix(fileName, "1panel-v2.") || strings.HasPrefix(fileName, "snapshot-1panel-v2.")) { if len(file) != 0 && checkSnapshotIsOk(fileName) {
datas = append(datas, path.Base(file)) datas = append(datas, path.Base(file))
} }
} }
+1 -4
View File
@@ -639,10 +639,7 @@ func handleAlert(stdout, clamName string, clamId uint) {
EntryID: clamId, EntryID: clamId,
Param: strconv.Itoa(infectedFiles), Param: strconv.Itoa(infectedFiles),
} }
err := xpack.PushAlert(pushAlert) _ = xpack.PushAlert(pushAlert)
if err != nil {
global.LOG.Errorf("clamdscan push failed, err: %v", err)
}
break break
} }
} }
+53 -32
View File
@@ -33,7 +33,7 @@ import (
"github.com/1Panel-dev/1Panel/agent/utils/cmd" "github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/common" "github.com/1Panel-dev/1Panel/agent/utils/common"
"github.com/1Panel-dev/1Panel/agent/utils/docker" "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/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/image" "github.com/docker/docker/api/types/image"
@@ -94,8 +94,8 @@ func NewIContainerService() IContainerService {
func (u *ContainerService) Page(req dto.PageContainer) (int64, interface{}, error) { func (u *ContainerService) Page(req dto.PageContainer) (int64, interface{}, error) {
var ( var (
records []types.Container records []container.Summary
list []types.Container list []container.Summary
) )
client, err := docker.NewDockerClient() client, err := docker.NewDockerClient()
if err != nil { if err != nil {
@@ -165,7 +165,7 @@ func (u *ContainerService) Page(req dto.PageContainer) (int64, interface{}, erro
total, start, end := len(list), (req.Page-1)*req.PageSize, req.Page*req.PageSize total, start, end := len(list), (req.Page-1)*req.PageSize, req.Page*req.PageSize
if start > total { if start > total {
records = make([]types.Container, 0) records = make([]container.Summary, 0)
} else { } else {
if end >= total { if end >= total {
end = total end = total
@@ -307,7 +307,7 @@ func (u *ContainerService) ContainerListStats() ([]dto.ContainerListStats, error
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(len(list)) wg.Add(len(list))
for i := 0; i < len(list); i++ { for i := 0; i < len(list); i++ {
go func(item types.Container) { go func(item container.Summary) {
datas = append(datas, loadCpuAndMem(client, item.ID)) datas = append(datas, loadCpuAndMem(client, item.ID))
wg.Done() wg.Done()
}(list[i]) }(list[i])
@@ -466,7 +466,7 @@ func (u *ContainerService) Prune(req dto.ContainerPrune) (dto.ContainerPruneRepo
report.DeletedNumber = len(rep.VolumesDeleted) report.DeletedNumber = len(rep.VolumesDeleted)
report.SpaceReclaimed = int(rep.SpaceReclaimed) report.SpaceReclaimed = int(rep.SpaceReclaimed)
case "buildcache": case "buildcache":
opts := types.BuildCachePruneOptions{} opts := build.CachePruneOptions{}
opts.All = true opts.All = true
rep, err := client.BuildCachePrune(context.Background(), opts) rep, err := client.BuildCachePrune(context.Background(), opts)
if err != nil { if err != nil {
@@ -915,9 +915,6 @@ func collectLogs(done <-chan struct{}, params dto.StreamLog, messageChan chan<-
defer close(messageChan) defer close(messageChan)
defer close(errorChan) defer close(errorChan)
var cmdArgs []string var cmdArgs []string
if params.Type == "compose" {
cmdArgs = []string{"compose", "-f", params.Compose}
}
cmdArgs = append(cmdArgs, "logs") cmdArgs = append(cmdArgs, "logs")
if params.Follow { if params.Follow {
cmdArgs = append(cmdArgs, "-f") cmdArgs = append(cmdArgs, "-f")
@@ -932,7 +929,20 @@ func collectLogs(done <-chan struct{}, params dto.StreamLog, messageChan chan<-
cmdArgs = append(cmdArgs, params.Container) cmdArgs = append(cmdArgs, params.Container)
} }
dockerCmd := exec.Command("docker", cmdArgs...) 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...)
} else {
newCmdArgs := append([]string{"compose", "-f", params.Compose}, cmdArgs...)
dockerCmd = exec.Command("docker", newCmdArgs...)
}
} else {
dockerCmd = exec.Command("docker", cmdArgs...)
}
dockerCmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} dockerCmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
stdout, err := dockerCmd.StdoutPipe() stdout, err := dockerCmd.StdoutPipe()
@@ -958,7 +968,7 @@ func collectLogs(done <-chan struct{}, params dto.StreamLog, messageChan chan<-
} }
}() }()
scanner := bufio.NewScanner(stdout) reader := bufio.NewReader(stdout)
processKilled := false processKilled := false
go func() { go func() {
@@ -972,19 +982,30 @@ func collectLogs(done <-chan struct{}, params dto.StreamLog, messageChan chan<-
} }
}() }()
for scanner.Scan() { for {
message := scanner.Text() line, err := reader.ReadString('\n')
if err != nil {
if err == io.EOF {
if len(line) > 0 {
line = strings.TrimSuffix(line, "\n")
select {
case messageChan <- line:
case <-done:
return
}
}
break
}
errorChan <- fmt.Errorf("reader error: %v", err)
return
}
line = strings.TrimSuffix(line, "\n")
select { select {
case messageChan <- message: case messageChan <- line:
case <-done: case <-done:
return return
} }
} }
if err = scanner.Err(); err != nil && err != io.EOF {
errorChan <- fmt.Errorf("scanner error: %v", err)
}
_ = dockerCmd.Wait() _ = dockerCmd.Wait()
} }
@@ -1300,7 +1321,7 @@ func checkPortStats(ports []dto.PortHelper) (nat.PortMap, error) {
return portMap, nil return portMap, nil
} }
func loadConfigInfo(isCreate bool, req dto.ContainerOperate, oldContainer *types.ContainerJSON) (*container.Config, *container.HostConfig, *network.NetworkingConfig, error) { func loadConfigInfo(isCreate bool, req dto.ContainerOperate, oldContainer *container.InspectResponse) (*container.Config, *container.HostConfig, *network.NetworkingConfig, error) {
var config container.Config var config container.Config
var hostConf container.HostConfig var hostConf container.HostConfig
if !isCreate { if !isCreate {
@@ -1383,7 +1404,7 @@ func loadConfigInfo(isCreate bool, req dto.ContainerOperate, oldContainer *types
return &config, &hostConf, &networkConf, nil return &config, &hostConf, &networkConf, nil
} }
func reCreateAfterUpdate(name string, client *client.Client, config *container.Config, hostConf *container.HostConfig, networkConf *types.NetworkSettings) { func reCreateAfterUpdate(name string, client *client.Client, config *container.Config, hostConf *container.HostConfig, networkConf *container.NetworkSettings) {
ctx := context.Background() ctx := context.Background()
var oldNetworkConf network.NetworkingConfig var oldNetworkConf network.NetworkingConfig
@@ -1405,7 +1426,7 @@ func reCreateAfterUpdate(name string, client *client.Client, config *container.C
global.LOG.Info("recreate after container update successful") global.LOG.Info("recreate after container update successful")
} }
func loadVolumeBinds(binds []types.MountPoint) []dto.VolumeHelper { func loadVolumeBinds(binds []container.MountPoint) []dto.VolumeHelper {
var datas []dto.VolumeHelper var datas []dto.VolumeHelper
for _, bind := range binds { for _, bind := range binds {
var volumeItem dto.VolumeHelper var volumeItem dto.VolumeHelper
@@ -1425,13 +1446,13 @@ func loadVolumeBinds(binds []types.MountPoint) []dto.VolumeHelper {
return datas return datas
} }
func loadPortByInspect(id string, client *client.Client) ([]types.Port, error) { func loadPortByInspect(id string, client *client.Client) ([]container.Port, error) {
container, err := client.ContainerInspect(context.Background(), id) containerItem, err := client.ContainerInspect(context.Background(), id)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var itemPorts []types.Port var itemPorts []container.Port
for key, val := range container.ContainerJSONBase.HostConfig.PortBindings { for key, val := range containerItem.ContainerJSONBase.HostConfig.PortBindings {
if !strings.Contains(string(key), "/") { if !strings.Contains(string(key), "/") {
continue continue
} }
@@ -1440,15 +1461,15 @@ func loadPortByInspect(id string, client *client.Client) ([]types.Port, error) {
for _, itemVal := range val { for _, itemVal := range val {
publicPort, _ := strconv.ParseUint(itemVal.HostPort, 10, 16) publicPort, _ := strconv.ParseUint(itemVal.HostPort, 10, 16)
itemPorts = append(itemPorts, types.Port{PrivatePort: uint16(itemPort), Type: item[1], PublicPort: uint16(publicPort), IP: itemVal.HostIP}) itemPorts = append(itemPorts, container.Port{PrivatePort: uint16(itemPort), Type: item[1], PublicPort: uint16(publicPort), IP: itemVal.HostIP})
} }
} }
return itemPorts, nil return itemPorts, nil
} }
func transPortToStr(ports []types.Port) []string { func transPortToStr(ports []container.Port) []string {
var ( var (
ipv4Ports []types.Port ipv4Ports []container.Port
ipv6Ports []types.Port ipv6Ports []container.Port
) )
for _, port := range ports { for _, port := range ports {
if strings.Contains(port.IP, ":") { if strings.Contains(port.IP, ":") {
@@ -1461,7 +1482,7 @@ func transPortToStr(ports []types.Port) []string {
list2 := simplifyPort(ipv6Ports) list2 := simplifyPort(ipv6Ports)
return append(list1, list2...) return append(list1, list2...)
} }
func simplifyPort(ports []types.Port) []string { func simplifyPort(ports []container.Port) []string {
var datas []string var datas []string
if len(ports) == 0 { if len(ports) == 0 {
return datas return datas
@@ -1557,7 +1578,7 @@ func loadComposeCount(client *client.Client) int {
return len(composeMap) return len(composeMap)
} }
func loadContainerPortForInfo(itemPorts []types.Port) []dto.PortHelper { func loadContainerPortForInfo(itemPorts []container.Port) []dto.PortHelper {
var exposedPorts []dto.PortHelper var exposedPorts []dto.PortHelper
samePortMap := make(map[string]dto.PortHelper) samePortMap := make(map[string]dto.PortHelper)
ports := transPortToStr(itemPorts) ports := transPortToStr(itemPorts)
+22
View File
@@ -73,6 +73,9 @@ func (u *CronjobService) SearchWithPage(search dto.PageCronjob) (int64, interfac
} else { } else {
item.AlertCount = 0 item.AlertCount = 0
} }
if cronjob.Type == "snapshot" && len(cronjob.SnapshotRule) != 0 {
_ = json.Unmarshal([]byte(cronjob.SnapshotRule), &item.SnapshotRule)
}
dtoCronjobs = append(dtoCronjobs, item) dtoCronjobs = append(dtoCronjobs, item)
} }
return total, dtoCronjobs, err return total, dtoCronjobs, err
@@ -94,6 +97,9 @@ func (u *CronjobService) LoadInfo(req dto.OperateByID) (*dto.CronjobOperate, err
} else { } else {
item.AlertCount = 0 item.AlertCount = 0
} }
if cronjob.Type == "snapshot" && len(cronjob.SnapshotRule) != 0 {
_ = json.Unmarshal([]byte(cronjob.SnapshotRule), &item.SnapshotRule)
}
return &item, err return &item, err
} }
@@ -279,6 +285,13 @@ func (u *CronjobService) Create(req dto.CronjobOperate) error {
if err := copier.Copy(&cronjob, &req); err != nil { if err := copier.Copy(&cronjob, &req); err != nil {
return buserr.WithDetail("ErrStructTransform", err.Error(), nil) return buserr.WithDetail("ErrStructTransform", err.Error(), nil)
} }
if cronjob.Type == "snapshot" {
rule, err := json.Marshal(req.SnapshotRule)
if err != nil {
return err
}
cronjob.SnapshotRule = string(rule)
}
if cronjob.Type == "cutWebsiteLog" { if cronjob.Type == "cutWebsiteLog" {
backupAccount, err := backupRepo.Get(repo.WithByType(constant.Local)) backupAccount, err := backupRepo.Get(repo.WithByType(constant.Local))
if backupAccount.ID == 0 { if backupAccount.ID == 0 {
@@ -372,6 +385,13 @@ func (u *CronjobService) Update(id uint, req dto.CronjobOperate) error {
if err := copier.Copy(&cronjob, &req); err != nil { if err := copier.Copy(&cronjob, &req); err != nil {
return buserr.WithDetail("ErrStructTransform", err.Error(), nil) return buserr.WithDetail("ErrStructTransform", err.Error(), nil)
} }
if req.Type == "snapshot" {
itemRule, err := json.Marshal(req.SnapshotRule)
if err != nil {
return err
}
cronjob.SnapshotRule = string(itemRule)
}
cronModel, err := cronjobRepo.Get(repo.WithByID(id)) cronModel, err := cronjobRepo.Get(repo.WithByID(id))
if err != nil { if err != nil {
return buserr.New("ErrRecordNotFound") return buserr.New("ErrRecordNotFound")
@@ -412,12 +432,14 @@ func (u *CronjobService) Update(id uint, req dto.CronjobOperate) error {
upMap["db_name"] = req.DBName upMap["db_name"] = req.DBName
upMap["url"] = req.URL upMap["url"] = req.URL
upMap["source_dir"] = req.SourceDir upMap["source_dir"] = req.SourceDir
upMap["snapshot_rule"] = cronjob.SnapshotRule
upMap["source_account_ids"] = req.SourceAccountIDs upMap["source_account_ids"] = req.SourceAccountIDs
upMap["download_account_id"] = req.DownloadAccountID upMap["download_account_id"] = req.DownloadAccountID
upMap["retain_copies"] = req.RetainCopies upMap["retain_copies"] = req.RetainCopies
upMap["retry_times"] = req.RetryTimes upMap["retry_times"] = req.RetryTimes
upMap["timeout"] = req.Timeout upMap["timeout"] = req.Timeout
upMap["ignore_err"] = req.IgnoreErr
upMap["secret"] = req.Secret upMap["secret"] = req.Secret
err = cronjobRepo.Update(id, upMap) err = cronjobRepo.Update(id, upMap)
if err != nil { if err != nil {
+106 -11
View File
@@ -2,6 +2,7 @@ package service
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"os" "os"
"path" "path"
@@ -47,6 +48,7 @@ func (u *CronjobService) handleApp(cronjob model.Cronjob, startTime time.Time, t
return err return err
} }
for _, app := range apps { for _, app := range apps {
retry := 0
taskItem.AddSubTaskWithOps(task.GetTaskName(app.Name, task.TaskBackup, task.TaskScopeCronjob), func(task *task.Task) error { taskItem.AddSubTaskWithOps(task.GetTaskName(app.Name, task.TaskBackup, task.TaskScopeCronjob), func(task *task.Task) error {
var record model.BackupRecord var record model.BackupRecord
record.From = "cronjob" record.From = "cronjob"
@@ -58,11 +60,22 @@ func (u *CronjobService) handleApp(cronjob model.Cronjob, startTime time.Time, t
backupDir := path.Join(global.Dir.TmpDir, fmt.Sprintf("app/%s/%s", app.App.Key, app.Name)) backupDir := path.Join(global.Dir.TmpDir, fmt.Sprintf("app/%s/%s", app.App.Key, app.Name))
record.FileName = fmt.Sprintf("app_%s_%s.tar.gz", app.Name, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5)) record.FileName = fmt.Sprintf("app_%s_%s.tar.gz", app.Name, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5))
if err := doAppBackup(&app, task, backupDir, record.FileName, cronjob.ExclusionRules, cronjob.Secret); err != nil { if err := doAppBackup(&app, task, backupDir, record.FileName, cronjob.ExclusionRules, cronjob.Secret); err != nil {
return err if retry < int(cronjob.RetryTimes) || !cronjob.IgnoreErr {
retry++
return err
} else {
task.Log(i18n.GetMsgWithDetail("IgnoreBackupErr", err.Error()))
return nil
}
} }
downloadPath, err := u.uploadCronjobBackFile(cronjob, task, accountMap, path.Join(backupDir, record.FileName)) downloadPath, err := u.uploadCronjobBackFile(cronjob, task, accountMap, path.Join(backupDir, record.FileName))
if err != nil { if err != nil {
return err if retry < int(cronjob.RetryTimes) || !cronjob.IgnoreErr {
retry++
return err
}
task.Log(i18n.GetMsgWithDetail("IgnoreUploadErr", err.Error()))
return nil
} }
record.FileDir = path.Dir(downloadPath) record.FileDir = path.Dir(downloadPath)
if err := backupRepo.CreateRecord(&record); err != nil { if err := backupRepo.CreateRecord(&record); err != nil {
@@ -86,6 +99,7 @@ func (u *CronjobService) handleWebsite(cronjob model.Cronjob, startTime time.Tim
return err return err
} }
for _, web := range webs { for _, web := range webs {
retry := 0
taskItem.AddSubTaskWithOps(task.GetTaskName(web.Alias, task.TaskBackup, task.TaskScopeCronjob), func(task *task.Task) error { taskItem.AddSubTaskWithOps(task.GetTaskName(web.Alias, task.TaskBackup, task.TaskScopeCronjob), func(task *task.Task) error {
var record model.BackupRecord var record model.BackupRecord
record.From = "cronjob" record.From = "cronjob"
@@ -98,12 +112,23 @@ func (u *CronjobService) handleWebsite(cronjob model.Cronjob, startTime time.Tim
record.FileName = fmt.Sprintf("website_%s_%s.tar.gz", web.Alias, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5)) record.FileName = fmt.Sprintf("website_%s_%s.tar.gz", web.Alias, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5))
if err := doWebsiteBackup(&web, taskItem, backupDir, record.FileName, cronjob.ExclusionRules, cronjob.Secret); err != nil { if err := doWebsiteBackup(&web, taskItem, backupDir, record.FileName, cronjob.ExclusionRules, cronjob.Secret); err != nil {
return err if retry < int(cronjob.RetryTimes) || !cronjob.IgnoreErr {
retry++
return err
} else {
task.Log(i18n.GetMsgWithDetail("IgnoreBackupErr", err.Error()))
return nil
}
} }
downloadPath, err := u.uploadCronjobBackFile(cronjob, task, accountMap, path.Join(backupDir, record.FileName)) downloadPath, err := u.uploadCronjobBackFile(cronjob, task, accountMap, path.Join(backupDir, record.FileName))
if err != nil { if err != nil {
return err if retry < int(cronjob.RetryTimes) || !cronjob.IgnoreErr {
retry++
return err
}
task.Log(i18n.GetMsgWithDetail("IgnoreUploadErr", err.Error()))
return nil
} }
record.FileDir = path.Dir(downloadPath) record.FileDir = path.Dir(downloadPath)
if err := backupRepo.CreateRecord(&record); err != nil { if err := backupRepo.CreateRecord(&record); err != nil {
@@ -127,6 +152,7 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Ti
return err return err
} }
for _, dbInfo := range dbs { for _, dbInfo := range dbs {
retry := 0
itemName := fmt.Sprintf("%s[%s] - %s", dbInfo.Database, dbInfo.DBType, dbInfo.Name) itemName := fmt.Sprintf("%s[%s] - %s", dbInfo.Database, dbInfo.DBType, dbInfo.Name)
taskItem.AddSubTaskWithOps(task.GetTaskName(itemName, task.TaskBackup, task.TaskScopeCronjob), func(task *task.Task) error { taskItem.AddSubTaskWithOps(task.GetTaskName(itemName, task.TaskBackup, task.TaskScopeCronjob), func(task *task.Task) error {
var record model.BackupRecord var record model.BackupRecord
@@ -141,17 +167,34 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Ti
record.FileName = fmt.Sprintf("db_%s_%s.sql.gz", dbInfo.Name, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5)) record.FileName = fmt.Sprintf("db_%s_%s.sql.gz", dbInfo.Name, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5))
if cronjob.DBType == "mysql" || cronjob.DBType == "mariadb" { if cronjob.DBType == "mysql" || cronjob.DBType == "mariadb" {
if err := doMysqlBackup(dbInfo, backupDir, record.FileName); err != nil { if err := doMysqlBackup(dbInfo, backupDir, record.FileName); err != nil {
return err if retry < int(cronjob.RetryTimes) || !cronjob.IgnoreErr {
retry++
return err
} else {
task.Log(i18n.GetMsgWithDetail("IgnoreBackupErr", err.Error()))
return nil
}
} }
} else { } else {
if err := doPostgresqlgBackup(dbInfo, backupDir, record.FileName); err != nil { if err := doPostgresqlgBackup(dbInfo, backupDir, record.FileName); err != nil {
return err if retry < int(cronjob.RetryTimes) || !cronjob.IgnoreErr {
retry++
return err
} else {
task.Log(i18n.GetMsgWithDetail("IgnoreBackupErr", err.Error()))
return nil
}
} }
} }
downloadPath, err := u.uploadCronjobBackFile(cronjob, task, accountMap, path.Join(backupDir, record.FileName)) downloadPath, err := u.uploadCronjobBackFile(cronjob, task, accountMap, path.Join(backupDir, record.FileName))
if err != nil { if err != nil {
return err if retry < int(cronjob.RetryTimes) || !cronjob.IgnoreErr {
retry++
return err
}
task.Log(i18n.GetMsgWithDetail("IgnoreUploadErr", err.Error()))
return nil
} }
record.FileDir = path.Dir(downloadPath) record.FileDir = path.Dir(downloadPath)
if err := backupRepo.CreateRecord(&record); err != nil { if err := backupRepo.CreateRecord(&record); err != nil {
@@ -250,10 +293,6 @@ func (u *CronjobService) handleSnapshot(cronjob model.Cronjob, jobRecord model.J
if err != nil { if err != nil {
return err return err
} }
itemData, err := NewISnapshotService().LoadSnapshotData()
if err != nil {
return err
}
var record model.BackupRecord var record model.BackupRecord
record.From = "cronjob" record.From = "cronjob"
@@ -268,6 +307,11 @@ func (u *CronjobService) handleSnapshot(cronjob model.Cronjob, jobRecord model.J
if !global.IsMaster { if !global.IsMaster {
scope = "agent" scope = "agent"
} }
itemData, err := loadSnapWithRule(cronjob)
if err != nil {
return err
}
req := dto.SnapshotCreate{ req := dto.SnapshotCreate{
Name: fmt.Sprintf("snapshot-1panel-%s-%s-linux-%s-%s", scope, versionItem.Value, loadOs(), jobRecord.StartTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5)), Name: fmt.Sprintf("snapshot-1panel-%s-%s-linux-%s-%s", scope, versionItem.Value, loadOs(), jobRecord.StartTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5)),
Secret: cronjob.Secret, Secret: cronjob.Secret,
@@ -278,11 +322,13 @@ func (u *CronjobService) handleSnapshot(cronjob model.Cronjob, jobRecord model.J
AppData: itemData.AppData, AppData: itemData.AppData,
PanelData: itemData.PanelData, PanelData: itemData.PanelData,
BackupData: itemData.BackupData, BackupData: itemData.BackupData,
WithDockerConf: true,
WithMonitorData: true, WithMonitorData: true,
WithLoginLog: true, WithLoginLog: true,
WithOperationLog: true, WithOperationLog: true,
WithSystemLog: true, WithSystemLog: true,
WithTaskLog: true, WithTaskLog: true,
IgnoreFiles: strings.Split(cronjob.ExclusionRules, ","),
} }
if err := NewISnapshotService().SnapshotCreate(taskItem, req, jobRecord.ID, cronjob.RetryTimes, cronjob.Timeout); err != nil { if err := NewISnapshotService().SnapshotCreate(taskItem, req, jobRecord.ID, cronjob.RetryTimes, cronjob.Timeout); err != nil {
@@ -451,3 +497,52 @@ func handleBackupLogs(taskItem *task.Task, targetDir, fileName string, secret st
}() }()
return nil return nil
} }
func loadSnapWithRule(cronjob model.Cronjob) (dto.SnapshotData, error) {
itemData, err := NewISnapshotService().LoadSnapshotData()
if err != nil {
return itemData, err
}
if len(cronjob.SnapshotRule) == 0 {
return itemData, nil
}
var snapRule dto.SnapshotRule
if err := json.Unmarshal([]byte(cronjob.SnapshotRule), &snapRule); err != nil {
return itemData, err
}
if len(snapRule.IgnoreAppIDs) == 0 && !snapRule.WithImage {
return itemData, nil
}
var ignoreApps []model.AppInstall
if len(snapRule.IgnoreAppIDs) != 0 {
ignoreApps, _ = appInstallRepo.ListBy(context.Background(), repo.WithByIDs(snapRule.IgnoreAppIDs))
}
if len(ignoreApps) == 0 && !snapRule.WithImage {
return itemData, nil
}
for i := 0; i < len(itemData.AppData); i++ {
isIgnore := false
for _, ignore := range ignoreApps {
if ignore.App.Key == itemData.AppData[i].Key && ignore.Name == itemData.AppData[i].Name {
isIgnore = true
itemData.AppData[i].IsCheck = false
for j := 0; j < len(itemData.AppData[i].Children); j++ {
if itemData.AppData[i].Children[j].Label == "appData" {
itemData.AppData[i].Children[j].IsCheck = false
}
}
break
}
}
if snapRule.WithImage && !isIgnore {
for j := 0; j < len(itemData.AppData[i].Children); j++ {
if itemData.AppData[i].Children[j].Label == "appImage" {
itemData.AppData[i].Children[j].IsCheck = true
}
}
}
}
return itemData, nil
}
+5 -5
View File
@@ -271,6 +271,10 @@ func (u *CronjobService) uploadCronjobBackFile(cronjob model.Cronjob, task *task
cloudSrc := strings.TrimPrefix(file, global.Dir.TmpDir+"/") cloudSrc := strings.TrimPrefix(file, global.Dir.TmpDir+"/")
for _, account := range accounts { for _, account := range accounts {
if len(account) != 0 { if len(account) != 0 {
task.LogStart(i18n.GetMsgWithMap("UploadFile", map[string]interface{}{
"file": pathUtils.Join(accountMap[account].backupPath, cloudSrc),
"backup": accountMap[account].name,
}))
_, err := accountMap[account].client.Upload(file, pathUtils.Join(accountMap[account].backupPath, cloudSrc)) _, err := accountMap[account].client.Upload(file, pathUtils.Join(accountMap[account].backupPath, cloudSrc))
task.LogWithStatus( task.LogWithStatus(
i18n.GetMsgWithMap("UploadFile", map[string]interface{}{ i18n.GetMsgWithMap("UploadFile", map[string]interface{}{
@@ -355,9 +359,5 @@ func handleCronJobAlert(cronjob *model.Cronjob) {
EntryID: cronjob.ID, EntryID: cronjob.ID,
Param: cronjob.Type, Param: cronjob.Type,
} }
err := xpack.PushAlert(pushAlert) _ = xpack.PushAlert(pushAlert)
if err != nil {
global.LOG.Errorf("cronjob alert push failed, err: %v", err)
return
}
} }
+2 -2
View File
@@ -390,10 +390,10 @@ type diskInfo struct {
func loadDiskInfo() []dto.DiskInfo { func loadDiskInfo() []dto.DiskInfo {
var datas []dto.DiskInfo var datas []dto.DiskInfo
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(2 * time.Second)) cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(2 * time.Second))
stdout, err := cmdMgr.RunWithStdoutBashC("df -hT -P|grep '/'|grep -v tmpfs|grep -v 'snap/core'|grep -v udev") stdout, err := cmdMgr.RunWithStdoutBashC("timeout 2 df -hT -P | awk 'NR>1 && !/tmpfs|snap\\/core|udev/ {print}'")
if err != nil { if err != nil {
cmdMgr2 := cmd.NewCommandMgr(cmd.WithTimeout(1 * time.Second)) cmdMgr2 := cmd.NewCommandMgr(cmd.WithTimeout(1 * time.Second))
stdout, err = cmdMgr2.RunWithStdoutBashC("df -lhT -P|grep '/'|grep -v tmpfs|grep -v 'snap/core'|grep -v udev") stdout, err = cmdMgr2.RunWithStdoutBashC("timeout 1 df -lhT -P | awk 'NR>1 && !/tmpfs|snap\\/core|udev/ {print}'")
if err != nil { if err != nil {
return datas return datas
} }
+2 -1
View File
@@ -13,6 +13,7 @@ import (
"github.com/1Panel-dev/1Panel/agent/constant" "github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/utils/docker" "github.com/1Panel-dev/1Panel/agent/utils/docker"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/build"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
"github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/dto"
@@ -663,7 +664,7 @@ func dropBuildCache() {
if err != nil { if err != nil {
global.LOG.Errorf("do not get docker client") global.LOG.Errorf("do not get docker client")
} }
opts := types.BuildCachePruneOptions{} opts := build.CachePruneOptions{}
opts.All = true opts.All = true
_, err = client.BuildCachePrune(context.Background(), opts) _, err = client.BuildCachePrune(context.Background(), opts)
if err != nil { if err != nil {
-27
View File
@@ -220,16 +220,6 @@ func (u *DockerService) UpdateConf(req dto.SettingUpdate, withRestart bool) erro
daemonMap["proxies"] = proxies daemonMap["proxies"] = proxies
} }
} }
if len(daemonMap) == 0 {
if len(file) == 0 {
return nil
}
_ = os.Remove(constant.DaemonJsonPath)
if withRestart {
return restartDocker()
}
return nil
}
newJson, err := json.MarshalIndent(daemonMap, "", "\t") newJson, err := json.MarshalIndent(daemonMap, "", "\t")
if err != nil { if err != nil {
return err return err
@@ -277,11 +267,6 @@ func (u *DockerService) UpdateLogOption(req dto.LogOption) error {
_ = json.Unmarshal(file, &daemonMap) _ = json.Unmarshal(file, &daemonMap)
changeLogOption(daemonMap, req.LogMaxFile, req.LogMaxSize) changeLogOption(daemonMap, req.LogMaxFile, req.LogMaxSize)
if len(daemonMap) == 0 {
_ = os.Remove(constant.DaemonJsonPath)
_ = restartDocker()
return nil
}
newJson, err := json.MarshalIndent(daemonMap, "", "\t") newJson, err := json.MarshalIndent(daemonMap, "", "\t")
if err != nil { if err != nil {
return err return err
@@ -321,11 +306,6 @@ func (u *DockerService) UpdateIpv6Option(req dto.Ipv6Option) error {
if req.Experimental { if req.Experimental {
daemonMap["experimental"] = req.Experimental daemonMap["experimental"] = req.Experimental
} }
if len(daemonMap) == 0 {
_ = os.Remove(constant.DaemonJsonPath)
_ = restartDocker()
return nil
}
newJson, err := json.MarshalIndent(daemonMap, "", "\t") newJson, err := json.MarshalIndent(daemonMap, "", "\t")
if err != nil { if err != nil {
return err return err
@@ -345,13 +325,6 @@ func (u *DockerService) UpdateIpv6Option(req dto.Ipv6Option) error {
} }
func (u *DockerService) UpdateConfByFile(req dto.DaemonJsonUpdateByFile) error { func (u *DockerService) UpdateConfByFile(req dto.DaemonJsonUpdateByFile) error {
if len(req.File) == 0 {
_ = os.Remove(constant.DaemonJsonPath)
if err := restartDocker(); err != nil {
return err
}
return nil
}
err := createIfNotExistDaemonJsonFile() err := createIfNotExistDaemonJsonFile()
if err != nil { if err != nil {
return err return err
+28 -15
View File
@@ -4,7 +4,10 @@ import (
"bufio" "bufio"
"context" "context"
"fmt" "fmt"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/jinzhu/copier" "github.com/jinzhu/copier"
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/simplifiedchinese"
"io" "io"
"io/fs" "io/fs"
"os" "os"
@@ -15,9 +18,6 @@ import (
"strconv" "strconv"
"strings" "strings"
"time" "time"
"unicode/utf8"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/repo" "github.com/1Panel-dev/1Panel/agent/app/repo"
@@ -27,7 +27,6 @@ import (
"github.com/1Panel-dev/1Panel/agent/constant" "github.com/1Panel-dev/1Panel/agent/constant"
"golang.org/x/net/html/charset" "golang.org/x/net/html/charset"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform" "golang.org/x/text/transform"
"github.com/1Panel-dev/1Panel/agent/global" "github.com/1Panel-dev/1Panel/agent/global"
@@ -335,17 +334,22 @@ func (f *FileService) GetContent(op request.FileContentReq) (response.FileInfo,
if len(content) > 1024 { if len(content) > 1024 {
content = content[:1024] content = content[:1024]
} }
if !utf8.Valid(content) { _, decodeName, _ := charset.DetermineEncoding(content, "")
_, decodeName, _ := charset.DetermineEncoding(content, "") decoder := files.GetDecoderByName(decodeName)
if decodeName == "windows-1252" || strings.ToLower(decodeName) == "gbk" { if decoder != nil {
reader := strings.NewReader(info.Content) reader := strings.NewReader(info.Content)
item := transform.NewReader(reader, simplifiedchinese.GBK.NewDecoder()) var dec *encoding.Decoder
contents, err := io.ReadAll(item) if decodeName == "windows-1252" {
if err != nil { dec = simplifiedchinese.GBK.NewDecoder()
return response.FileInfo{}, err } else {
} dec = decoder.NewDecoder()
info.Content = string(contents)
} }
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 return response.FileInfo{FileInfo: *info}, nil
} }
@@ -390,10 +394,18 @@ func (f *FileService) MvFile(m request.FileMove) error {
return buserr.New("ErrMovePathFailed") return buserr.New("ErrMovePathFailed")
} }
} }
var errs []error
if m.Type == "cut" { if m.Type == "cut" {
if len(m.CoverPaths) > 0 {
for _, src := range m.CoverPaths {
if err := fo.CopyAndReName(src, m.NewPath, "", true); err != nil {
errs = append(errs, err)
global.LOG.Errorf("cut copy file [%s] to [%s] failed, err: %s", src, m.NewPath, err.Error())
}
}
}
return fo.Cut(m.OldPaths, m.NewPath, m.Name, m.Cover) return fo.Cut(m.OldPaths, m.NewPath, m.Name, m.Cover)
} }
var errs []error
if m.Type == "copy" { if m.Type == "copy" {
for _, src := range m.OldPaths { for _, src := range m.OldPaths {
if err := fo.CopyAndReName(src, m.NewPath, m.Name, m.Cover); err != nil { if err := fo.CopyAndReName(src, m.NewPath, m.Name, m.Cover); err != nil {
@@ -565,6 +577,7 @@ func (f *FileService) BatchCheckFiles(req request.FilePathsCheck) []response.Exi
Name: info.Name(), Name: info.Name(),
Path: filePath, Path: filePath,
ModTime: info.ModTime(), ModTime: info.ModTime(),
IsDir: info.IsDir(),
}) })
} }
} }
+1 -1
View File
@@ -602,7 +602,7 @@ func getProcessStatus(config *response.SupervisorProcessConfig, containerName st
out, err = exec.Command("supervisorctl", processNames...).Output() out, err = exec.Command("supervisorctl", processNames...).Output()
output = string(out) output = string(out)
} }
if containerName == "" && err != nil { if output == "" && err != nil {
return err return err
} }
lines := strings.Split(output, "\n") lines := strings.Split(output, "\n")
+3 -3
View File
@@ -22,7 +22,7 @@ import (
"github.com/1Panel-dev/1Panel/agent/global" "github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/i18n" "github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/utils/docker" "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/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/image" "github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/registry" "github.com/docker/docker/api/types/registry"
@@ -189,7 +189,7 @@ func (u *ImageService) ImageBuild(req dto.ImageBuild) error {
return err return err
} }
opts := types.ImageBuildOptions{ opts := build.ImageBuildOptions{
Dockerfile: fileName, Dockerfile: fileName,
Tags: []string{req.Name}, Tags: []string{req.Name},
Remove: true, Remove: true,
@@ -432,7 +432,7 @@ func formatFileSize(fileSize int64) (size string) {
} }
} }
func checkUsed(imageID string, containers []types.Container) bool { func checkUsed(imageID string, containers []container.Summary) bool {
for _, container := range containers { for _, container := range containers {
if container.ImageID == imageID { if container.ImageID == imageID {
return true return true
+69 -43
View File
@@ -28,7 +28,7 @@ type IImageRepoService interface {
Login(req dto.OperateByID) error Login(req dto.OperateByID) error
Create(req dto.ImageRepoCreate) error Create(req dto.ImageRepoCreate) error
Update(req dto.ImageRepoUpdate) error Update(req dto.ImageRepoUpdate) error
BatchDelete(req dto.ImageRepoDelete) error Delete(req dto.OperateByID) error
} }
func NewIImageRepoService() IImageRepoService { func NewIImageRepoService() IImageRepoService {
@@ -91,28 +91,7 @@ func (u *ImageRepoService) Create(req dto.ImageRepoCreate) error {
if err := u.handleRegistries(req.DownloadUrl, "", "create"); err != nil { if err := u.handleRegistries(req.DownloadUrl, "", "create"); err != nil {
return fmt.Errorf("create registry %s failed, err: %v", req.DownloadUrl, err) return fmt.Errorf("create registry %s failed, err: %v", req.DownloadUrl, err)
} }
if err := restartDocker(); err != nil { if err := stopBeforeUpdateRepo(); err != nil {
return err
}
ticker := time.NewTicker(3 * time.Second)
defer ticker.Stop()
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
if err := func() error {
for range ticker.C {
select {
case <-ctx.Done():
cancel()
return errors.New("the docker service cannot be restarted")
default:
stdout, err := cmd.RunDefaultWithStdoutBashC("systemctl is-active docker")
if string(stdout) == "active\n" && err == nil {
global.LOG.Info("docker restart with new conf successful!")
return nil
}
}
}
return nil
}(); err != nil {
return err return err
} }
} }
@@ -131,15 +110,32 @@ func (u *ImageRepoService) Create(req dto.ImageRepoCreate) error {
return imageRepoRepo.Create(&imageRepo) return imageRepoRepo.Create(&imageRepo)
} }
func (u *ImageRepoService) BatchDelete(req dto.ImageRepoDelete) error { func (u *ImageRepoService) Delete(req dto.OperateByID) error {
for _, id := range req.Ids { if req.ID == 1 {
if id == 1 { return errors.New("The default value cannot be edit !")
return errors.New("The default value cannot be edit !")
}
} }
if err := imageRepoRepo.Delete(repo.WithByIDs(req.Ids)); err != nil { itemRepo, _ := imageRepoRepo.Get(repo.WithByID(req.ID))
if itemRepo.ID == 0 {
return buserr.New("ErrRecordNotFound")
}
if itemRepo.Auth {
_, _ = cmd.NewCommandMgr().RunWithStdout("docker", "logout", "-i", itemRepo.DownloadUrl)
}
if itemRepo.Protocol == "https" {
return imageRepoRepo.Delete(repo.WithByID(req.ID))
}
if err := u.handleRegistries("", itemRepo.DownloadUrl, "delete"); err != nil {
return fmt.Errorf("delete registry %s failed, err: %v", itemRepo.DownloadUrl, err)
}
if err := validateDockerConfig(); err != nil {
return err return err
} }
if err := imageRepoRepo.Delete(repo.WithByID(req.ID)); err != nil {
return err
}
go func() {
_ = restartDocker()
}()
return nil return nil
} }
@@ -154,38 +150,37 @@ func (u *ImageRepoService) Update(req dto.ImageRepoUpdate) error {
if err != nil { if err != nil {
return err return err
} }
needRestart := false
if repo.Protocol == "http" && req.Protocol == "https" { if repo.Protocol == "http" && req.Protocol == "https" {
if err := u.handleRegistries("", repo.DownloadUrl, "delete"); err != nil { if err := u.handleRegistries("", repo.DownloadUrl, "delete"); err != nil {
return fmt.Errorf("delete registry %s failed, err: %v", repo.DownloadUrl, err) return fmt.Errorf("delete registry %s failed, err: %v", repo.DownloadUrl, err)
} }
needRestart = true
} }
if repo.Protocol == "http" && req.Protocol == "http" { if repo.Protocol == "http" && req.Protocol == "http" {
if err := u.handleRegistries(req.DownloadUrl, repo.DownloadUrl, "update"); err != nil { if err := u.handleRegistries(req.DownloadUrl, repo.DownloadUrl, "update"); err != nil {
return fmt.Errorf("update registry %s => %s failed, err: %v", repo.DownloadUrl, req.DownloadUrl, err) return fmt.Errorf("update registry %s => %s failed, err: %v", repo.DownloadUrl, req.DownloadUrl, err)
} }
needRestart = repo.DownloadUrl == req.DownloadUrl
} }
if repo.Protocol == "https" && req.Protocol == "http" { if repo.Protocol == "https" && req.Protocol == "http" {
if err := u.handleRegistries(req.DownloadUrl, "", "create"); err != nil { if err := u.handleRegistries(req.DownloadUrl, "", "create"); err != nil {
return fmt.Errorf("create registry %s failed, err: %v", req.DownloadUrl, err) return fmt.Errorf("create registry %s failed, err: %v", req.DownloadUrl, err)
} }
needRestart = true
} }
if repo.Auth != req.Auth || repo.DownloadUrl != req.DownloadUrl { if needRestart {
if repo.Auth { if err := stopBeforeUpdateRepo(); err != nil {
cmdMgr := cmd.NewCommandMgr() return err
_, _ = cmdMgr.RunWithStdout("docker", "logout", "-i", repo.DownloadUrl)
}
if req.Auth {
if err := u.CheckConn(req.DownloadUrl, req.Username, req.Password); err != nil {
return err
}
} }
} }
if repo.Auth {
if err := validateDockerConfig(); err != nil { _, _ = cmd.NewCommandMgr().RunWithStdout("docker", "logout", "-i", repo.DownloadUrl)
return err
} }
if err := restartDocker(); err != nil { if req.Auth {
return err if err := u.CheckConn(req.DownloadUrl, req.Username, req.Password); err != nil {
return err
}
} }
upMap := make(map[string]interface{}) upMap := make(map[string]interface{})
@@ -260,3 +255,34 @@ func (u *ImageRepoService) handleRegistries(newHost, delHost, handle string) err
} }
return nil return nil
} }
func stopBeforeUpdateRepo() error {
if err := validateDockerConfig(); err != nil {
return err
}
if err := restartDocker(); err != nil {
return err
}
ticker := time.NewTicker(3 * time.Second)
defer ticker.Stop()
ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
if err := func() error {
for range ticker.C {
select {
case <-ctx.Done():
cancel()
return errors.New("the docker service cannot be restarted")
default:
stdout, err := cmd.RunDefaultWithStdoutBashC("systemctl is-active docker")
if string(stdout) == "active\n" && err == nil {
global.LOG.Info("docker restart with new conf successful!")
return nil
}
}
}
return nil
}(); err != nil {
return err
}
return nil
}
+32 -17
View File
@@ -52,6 +52,7 @@ type IRuntimeService interface {
SyncForRestart() error SyncForRestart() error
SyncRuntimeStatus() error SyncRuntimeStatus() error
DeleteCheck(installID uint) ([]dto.AppResource, error) DeleteCheck(installID uint) ([]dto.AppResource, error)
UpdateRemark(req request.RuntimeRemark) error
GetPHPExtensions(runtimeID uint) (response.PHPExtensionRes, error) GetPHPExtensions(runtimeID uint) (response.PHPExtensionRes, error)
InstallPHPExtension(req request.PHPExtensionInstallReq) error InstallPHPExtension(req request.PHPExtensionInstallReq) error
@@ -108,6 +109,7 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (*model.Runtime, e
Type: create.Type, Type: create.Type,
Version: create.Version, Version: create.Version,
Status: constant.StatusNormal, Status: constant.StatusNormal,
Remark: create.Remark,
} }
return nil, runtimeRepo.Create(context.Background(), runtime) return nil, runtimeRepo.Create(context.Background(), runtime)
} }
@@ -168,6 +170,7 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (*model.Runtime, e
Version: create.Version, Version: create.Version,
ContainerName: containerName.(string), ContainerName: containerName.(string),
Port: strings.Join(hostPorts, ","), Port: strings.Join(hostPorts, ","),
Remark: create.Remark,
} }
switch create.Type { switch create.Type {
@@ -454,6 +457,7 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error {
Params: req.Params, Params: req.Params,
CodeDir: req.CodeDir, CodeDir: req.CodeDir,
Version: req.Version, Version: req.Version,
Remark: req.Remark,
NodeConfig: request.NodeConfig{ NodeConfig: request.NodeConfig{
Install: true, Install: true,
ExposedPorts: req.ExposedPorts, ExposedPorts: req.ExposedPorts,
@@ -465,6 +469,7 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error {
if err != nil { if err != nil {
return err return err
} }
runtime.Remark = req.Remark
runtime.Env = string(envContent) runtime.Env = string(envContent)
runtime.DockerCompose = string(composeContent) runtime.DockerCompose = string(composeContent)
@@ -719,25 +724,27 @@ func (r *RuntimeService) InstallPHPExtension(req request.PHPExtensionInstallReq)
return err return err
} }
client, err := docker.NewClient() client, err := docker.NewClient()
if err != nil {
return err
}
defer client.Close() defer client.Close()
if err == nil { oldImageID, err := client.GetImageIDByName(runtime.Image)
oldImageID, err := client.GetImageIDByName(runtime.Image) if err != nil {
if err != nil { return err
return err }
} err = cmdMgr.RunBashCf("docker commit %s %s", runtime.ContainerName, runtime.Image)
err = cmdMgr.RunBashCf("docker commit %s %s", runtime.ContainerName, runtime.Image) if err != nil {
if err != nil { return err
return err }
} newImageID, err := client.GetImageIDByName(runtime.Image)
newImageID, err := client.GetImageIDByName(runtime.Image) if err == nil && newImageID != oldImageID {
if err == nil && newImageID != oldImageID { if err := client.DeleteImage(oldImageID); err != nil {
if err := client.DeleteImage(oldImageID); err != nil { t.Log(fmt.Sprintf("delete old image error %v", err))
t.Log(fmt.Sprintf("delete old image error %v", err)) } else {
} else { t.Log("delete old image success")
t.Log("delete old image success")
}
} }
} }
handlePHPDir(*runtime)
if err = restartRuntime(runtime); err != nil { if err = restartRuntime(runtime); err != nil {
return err return err
} }
@@ -887,7 +894,6 @@ func (r *RuntimeService) UpdatePHPConfig(req request.PHPConfigUpdate) (err error
pattern := "^" + regexp.QuoteMeta("disable_functions") + "\\s*=\\s*.*$" pattern := "^" + regexp.QuoteMeta("disable_functions") + "\\s*=\\s*.*$"
if matched, _ := regexp.MatchString(pattern, line); matched { if matched, _ := regexp.MatchString(pattern, line); matched {
lines[i] = "disable_functions" + " = " + strings.Join(req.DisableFunctions, ",") lines[i] = "disable_functions" + " = " + strings.Join(req.DisableFunctions, ",")
break
} }
case "upload_max_filesize": case "upload_max_filesize":
pattern := "^" + regexp.QuoteMeta("post_max_size") + "\\s*=\\s*.*$" pattern := "^" + regexp.QuoteMeta("post_max_size") + "\\s*=\\s*.*$"
@@ -1143,3 +1149,12 @@ func (r *RuntimeService) OperateSupervisorProcessFile(req request.PHPSupervisorP
logFile := path.Join(supervisorDir, "log", fmt.Sprintf("%s.out.log", req.SupervisorProcessFileReq.Name)) logFile := path.Join(supervisorDir, "log", fmt.Sprintf("%s.out.log", req.SupervisorProcessFileReq.Name))
return handleSupervisorFile(req.SupervisorProcessFileReq, configDir, runtime.ContainerName, logFile) return handleSupervisorFile(req.SupervisorProcessFileReq, configDir, runtime.ContainerName, logFile)
} }
func (r *RuntimeService) UpdateRemark(req request.RuntimeRemark) error {
runtime, err := runtimeRepo.GetFirst(context.Background(), repo.WithByID(req.ID))
if err != nil {
return err
}
runtime.Remark = req.Remark
return runtimeRepo.Save(runtime)
}
+80 -10
View File
@@ -6,7 +6,6 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
cmd2 "github.com/1Panel-dev/1Panel/agent/utils/cmd"
"io" "io"
"os" "os"
"os/exec" "os/exec"
@@ -17,6 +16,8 @@ import (
"strings" "strings"
"time" "time"
cmd2 "github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/i18n" "github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/utils/common" "github.com/1Panel-dev/1Panel/agent/utils/common"
@@ -89,7 +90,7 @@ func handlePHP(create request.RuntimeCreate, runtime *model.Runtime, fileOp file
version, ok := create.Params["PHP_VERSION"] version, ok := create.Params["PHP_VERSION"]
if ok { if ok {
extensionsDir := path.Join(projectDir, "extensions", getExtensionDir(version.(string))) extensionsDir := path.Join(projectDir, "extensions", getExtensionDir(version.(string)))
_ = fileOp.CreateDir(extensionsDir, 0644) _ = fileOp.CreateDir(extensionsDir, 0755)
} }
composeContent, envContent, forms, err := handleParams(create, projectDir) composeContent, envContent, forms, err := handleParams(create, projectDir)
@@ -141,11 +142,27 @@ func reCreateRuntime(runtime *model.Runtime) {
} }
} }
func runComposeCmdWithLog(operate string, composePath string, logPath string) error { func getComposeCmd(composePath, operate string) *exec.Cmd {
cmd := exec.Command("docker", "compose", "-f", composePath, operate) dockerCommand := global.CONF.DockerConfig.Command
if operate == "up" { var cmd *exec.Cmd
cmd = exec.Command("docker", "compose", "-f", composePath, operate, "-d") if dockerCommand == "docker-compose" {
if operate == "up" {
cmd = exec.Command("docker-compose", "-f", composePath, operate, "-d")
} else {
cmd = exec.Command("docker-compose", "-f", composePath, operate)
}
} else {
if operate == "up" {
cmd = exec.Command("docker", "compose", "-f", composePath, operate, "-d")
} else {
cmd = exec.Command("docker", "compose", "-f", composePath, operate)
}
} }
return cmd
}
func runComposeCmdWithLog(operate string, composePath string, logPath string) error {
cmd := getComposeCmd(composePath, operate)
logFile, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, constant.FilePerm) logFile, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, constant.FilePerm)
if err != nil { if err != nil {
global.LOG.Errorf("Failed to open log file: %v", err) global.LOG.Errorf("Failed to open log file: %v", err)
@@ -287,10 +304,22 @@ func buildRuntime(runtime *model.Runtime, oldImageID string, oldEnv string, rebu
_ = logFile.Close() _ = logFile.Close()
}() }()
newPHPVersion := getRuntimeEnv(runtime.Env, "PHP_VERSION")
oldPHPVersion := getRuntimeEnv(oldEnv, "PHP_VERSION")
if newPHPVersion != oldPHPVersion {
_ = os.Rename(path.Join(runtimePath, "extensions", getExtensionDir(oldPHPVersion)), path.Join(runtimePath, "extensions", getExtensionDir(newPHPVersion)))
}
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Hour) ctx, cancel := context.WithTimeout(context.Background(), 1*time.Hour)
defer cancel() defer cancel()
cmd := exec.CommandContext(ctx, "docker", "compose", "-f", composePath, "build") dockerCommand := global.CONF.DockerConfig.Command
var cmd *exec.Cmd
if dockerCommand == "docker-compose" {
cmd = exec.CommandContext(ctx, "docker-compose", "-f", composePath, "build")
} else {
cmd = exec.CommandContext(ctx, "docker", "compose", "-f", composePath, "build")
}
cmd.Stdout = logFile cmd.Stdout = logFile
var stderrBuf bytes.Buffer var stderrBuf bytes.Buffer
multiWriterStderr := io.MultiWriter(&stderrBuf, logFile) multiWriterStderr := io.MultiWriter(&stderrBuf, logFile)
@@ -373,6 +402,7 @@ func buildRuntime(runtime *model.Runtime, oldImageID string, oldEnv string, rebu
if deleteImageID != "" { if deleteImageID != "" {
deleteImageByID(deleteImageID, runtime.Image, client) deleteImageByID(deleteImageID, runtime.Image, client)
} }
handlePHPDir(*runtime)
if out, err := compose.DownAndUp(composePath); err != nil { if out, err := compose.DownAndUp(composePath); err != nil {
runtime.Status = constant.StatusStartErr runtime.Status = constant.StatusStartErr
runtime.Message = out runtime.Message = out
@@ -553,7 +583,7 @@ func handleCompose(env gotenv.Env, composeContent []byte, create request.Runtime
serviceName = name serviceName = name
serviceValue = service.(map[string]interface{}) serviceValue = service.(map[string]interface{})
delete(serviceValue, "ports") delete(serviceValue, "ports")
if create.ExposedPorts != nil && len(create.ExposedPorts) > 0 { if len(create.ExposedPorts) > 0 {
var ports []interface{} var ports []interface{}
for i, port := range create.ExposedPorts { for i, port := range create.ExposedPorts {
containerPortStr := fmt.Sprintf("CONTAINER_PORT_%d", i) containerPortStr := fmt.Sprintf("CONTAINER_PORT_%d", i)
@@ -567,12 +597,12 @@ func handleCompose(env gotenv.Env, composeContent []byte, create request.Runtime
create.Params[hostIPStr] = port.HostIP create.Params[hostIPStr] = port.HostIP
} }
if create.Type == constant.RuntimePHP { if create.Type == constant.RuntimePHP {
ports = append(ports, fmt.Sprintf("127.0.0.1:${PANEL_APP_PORT_HTTP}:9000")) ports = append(ports, "127.0.0.1:${PANEL_APP_PORT_HTTP}:9000")
} }
serviceValue["ports"] = ports serviceValue["ports"] = ports
} else { } else {
if create.Type == constant.RuntimePHP { if create.Type == constant.RuntimePHP {
serviceValue["ports"] = []interface{}{fmt.Sprintf("127.0.0.1:${PANEL_APP_PORT_HTTP}:9000")} serviceValue["ports"] = []interface{}{"127.0.0.1:${PANEL_APP_PORT_HTTP}:9000"}
} }
} }
var environments []interface{} var environments []interface{}
@@ -959,3 +989,43 @@ func handleRuntimeDTO(res *response.RuntimeDTO, runtime model.Runtime) error {
} }
return nil return nil
} }
func handlePHPDir(runtime model.Runtime) {
fileOp := files.NewFileOp()
dirs := []string{
path.Join(runtime.GetPath(), "conf"),
path.Join(runtime.GetPath(), "extensions"),
path.Join(runtime.GetPath(), "composer"),
path.Join(runtime.GetPath(), "log"),
}
for _, dir := range dirs {
_ = fileOp.ChmodR(dir, 0755, true)
_ = fileOp.ChownR(dir, strconv.Itoa(1000), strconv.Itoa(1000), true)
}
}
func HandleOldPHPRuntime() {
runtimes, _ := runtimeRepo.List(repo.WithByType(constant.RuntimePHP))
if len(runtimes) == 0 {
return
}
fileOp := files.NewFileOp()
for _, runtime := range runtimes {
composePtah := runtime.GetComposePath()
composeBytes, _ := fileOp.GetContent(composePtah)
composeContent := strings.ReplaceAll(string(composeBytes), "./conf:/usr/local/etc/php", "./conf/php.ini:/usr/local/etc/php/php.ini")
composeContent = strings.ReplaceAll(composeContent, "./conf/php-fpm.conf:/usr/local/etc/php-fpm.d/www.conf", "./conf/php-fpm.conf:/usr/local/etc/php-fpm.conf")
composeContent = strings.ReplaceAll(composeContent, "./extensions:${EXTENSION_DIR}", "./extensions:/usr/local/lib/php/extensions")
_ = fileOp.WriteFile(composePtah, strings.NewReader(composeContent), constant.DirPerm)
_ = fileOp.WriteFile(runtime.GetFPMPath(), bytes.NewReader(nginx_conf.GetWebsiteFile("php-fpm.conf")), constant.DirPerm)
supervisorConfigPath := path.Join(runtime.GetPath(), "supervisor", "supervisor.d", "php-fpm.ini")
supervisorConfigBytes, _ := fileOp.GetContent(supervisorConfigPath)
if !strings.Contains(string(supervisorConfigBytes), "nodaemonize") {
newConfigContent := strings.ReplaceAll(string(supervisorConfigBytes), "command=php-fpm", "command=php-fpm --nodaemonize")
_ = fileOp.WriteFile(supervisorConfigPath, bytes.NewReader([]byte(newConfigContent)), constant.DirPerm)
}
go func() {
_ = restartRuntime(&runtime)
}()
}
}
+18 -7
View File
@@ -68,7 +68,7 @@ func (u *SnapshotService) SnapshotImport(req dto.SnapshotImport) error {
} }
for _, snapName := range req.Names { for _, snapName := range req.Names {
if !strings.HasPrefix(snapName, "1panel-v2.") && !strings.HasPrefix(snapName, "snapshot-1panel-v2.") { if !checkSnapshotIsOk(snapName) {
return fmt.Errorf("incorrect snapshot name format of %s", snapName) return fmt.Errorf("incorrect snapshot name format of %s", snapName)
} }
snap, _ := snapshotRepo.Get(repo.WithByName(strings.ReplaceAll(snapName, ".tar.gz", ""))) snap, _ := snapshotRepo.Get(repo.WithByName(strings.ReplaceAll(snapName, ".tar.gz", "")))
@@ -77,11 +77,11 @@ func (u *SnapshotService) SnapshotImport(req dto.SnapshotImport) error {
} }
} }
for _, snap := range req.Names { for _, snap := range req.Names {
shortName := strings.TrimPrefix(snap, "snapshot_") shortName := strings.ReplaceAll(snap, "snapshot-", "")
nameItems := strings.Split(shortName, "-") shortName = strings.ReplaceAll(shortName, "1panel-", "")
if !strings.HasPrefix(shortName, "1panel-v") || !strings.HasSuffix(shortName, ".tar.gz") || len(nameItems) < 3 { shortName = strings.ReplaceAll(shortName, "core-", "")
return fmt.Errorf("incorrect snapshot name format of %s", shortName) shortName = strings.ReplaceAll(shortName, "agent-", "")
} nameItems := strings.Split(shortName, "-linux")
if strings.HasSuffix(snap, ".tar.gz") { if strings.HasSuffix(snap, ".tar.gz") {
snap = strings.ReplaceAll(snap, ".tar.gz", "") snap = strings.ReplaceAll(snap, ".tar.gz", "")
} }
@@ -89,7 +89,7 @@ func (u *SnapshotService) SnapshotImport(req dto.SnapshotImport) error {
Name: snap, Name: snap,
SourceAccountIDs: fmt.Sprintf("%v", req.BackupAccountID), SourceAccountIDs: fmt.Sprintf("%v", req.BackupAccountID),
DownloadAccountID: req.BackupAccountID, DownloadAccountID: req.BackupAccountID,
Version: nameItems[1], Version: nameItems[0],
Description: req.Description, Description: req.Description,
Status: constant.StatusSuccess, Status: constant.StatusSuccess,
} }
@@ -110,6 +110,7 @@ func (u *SnapshotService) LoadSnapshotData() (dto.SnapshotData, error) {
if err != nil { if err != nil {
return data, err return data, err
} }
data.WithDockerConf = true
data.PanelData, err = loadPanelFile(fileOp) data.PanelData, err = loadPanelFile(fileOp)
if err != nil { if err != nil {
return data, err return data, err
@@ -403,3 +404,13 @@ func loadFile(pathItem string, index int, fileOp fileUtils.FileOp) ([]dto.DataTr
} }
return data, nil return data, nil
} }
func checkSnapshotIsOk(name string) bool {
names := []string{"1panel-core-v2.", "1panel-agent-v2.", "1panel-v2.", "snapshot-1panel-core-v2.", "snapshot-1panel-agent-v2."}
for _, item := range names {
if strings.HasPrefix(name, item) {
return true
}
}
return false
}
+33 -25
View File
@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"os" "os"
"path" "path"
"path/filepath"
"strings" "strings"
"sync" "sync"
"time" "time"
@@ -34,7 +35,7 @@ func (u *SnapshotService) SnapshotCreate(parentTask *task.Task, req dto.Snapshot
scope = "agent" scope = "agent"
} }
if jobID == 0 { if jobID == 0 {
req.Name = fmt.Sprintf("1panel-%s-%s-linux-%s-%s", versionItem.Value, scope, loadOs(), time.Now().Format(constant.DateTimeSlimLayout)) req.Name = fmt.Sprintf("1panel-%s-%s-linux-%s-%s", scope, versionItem.Value, loadOs(), time.Now().Format(constant.DateTimeSlimLayout))
} }
appItem, _ := json.Marshal(req.AppData) appItem, _ := json.Marshal(req.AppData)
panelItem, _ := json.Marshal(req.PanelData) panelItem, _ := json.Marshal(req.PanelData)
@@ -50,11 +51,13 @@ func (u *SnapshotService) SnapshotCreate(parentTask *task.Task, req dto.Snapshot
AppData: string(appItem), AppData: string(appItem),
PanelData: string(panelItem), PanelData: string(panelItem),
BackupData: string(backupItem), BackupData: string(backupItem),
WithDockerConf: req.WithDockerConf,
WithMonitorData: req.WithMonitorData, WithMonitorData: req.WithMonitorData,
WithLoginLog: req.WithLoginLog, WithLoginLog: req.WithLoginLog,
WithOperationLog: req.WithOperationLog, WithOperationLog: req.WithOperationLog,
WithTaskLog: req.WithTaskLog, WithTaskLog: req.WithTaskLog,
WithSystemLog: req.WithSystemLog, WithSystemLog: req.WithSystemLog,
IgnoreFiles: strings.Join(req.IgnoreFiles, ","),
Version: versionItem.Value, Version: versionItem.Value,
Status: constant.StatusWaiting, Status: constant.StatusWaiting,
@@ -106,13 +109,14 @@ func (u *SnapshotService) SnapshotReCreate(id uint) error {
return err return err
} }
req.TaskID = taskModel.ID req.TaskID = taskModel.ID
taskItem, err := task.NewTaskWithOps(req.Name, task.TaskCreate, task.TaskScopeSnapshot, req.TaskID, req.ID) taskItem, err := task.ReNewTaskWithOps(req.Name, task.TaskCreate, task.TaskScopeSnapshot, req.TaskID, req.ID)
if err != nil { if err != nil {
global.LOG.Errorf("new task for create snapshot failed, err: %v", err) global.LOG.Errorf("new task for create snapshot failed, err: %v", err)
return err return err
} }
_ = snapshotRepo.Update(req.ID, map[string]interface{}{"status": constant.StatusWaiting, "message": ""})
go func() { go func() {
_ = handleSnapshot(req, taskItem, 0, 0, 0) _ = handleSnapshot(req, taskItem, 0, 3, 0)
}() }()
return nil return nil
@@ -145,7 +149,7 @@ func handleSnapshot(req dto.SnapshotCreate, taskItem *task.Task, jobID, retry, t
if len(req.InterruptStep) == 0 || req.InterruptStep == "SnapBaseInfo" { if len(req.InterruptStep) == 0 || req.InterruptStep == "SnapBaseInfo" {
taskItem.AddSubTaskWithAliasAndOps( taskItem.AddSubTaskWithAliasAndOps(
"SnapBaseInfo", "SnapBaseInfo",
func(t *task.Task) error { return snapBaseData(itemHelper, baseDir) }, func(t *task.Task) error { return snapBaseData(itemHelper, baseDir, req.WithDockerConf) },
nil, int(retry), time.Duration(timeout)*time.Second, nil, int(retry), time.Duration(timeout)*time.Second,
) )
req.InterruptStep = "" req.InterruptStep = ""
@@ -233,6 +237,7 @@ func loadDbConn(snap *snapHelper, targetDir string, req dto.SnapshotCreate) erro
if err != nil { if err != nil {
return err return err
} }
_ = os.Remove(path.Join(targetDir, "db/session.db"))
agentDb, err := common.LoadDBConnByPathWithErr(path.Join(targetDir, "db/agent.db"), "agent.db") agentDb, err := common.LoadDBConnByPathWithErr(path.Join(targetDir, "db/agent.db"), "agent.db")
snap.Task.LogWithStatus(i18n.GetWithName("SnapNewDB", "agent"), err) snap.Task.LogWithStatus(i18n.GetWithName("SnapNewDB", "agent"), err)
@@ -284,7 +289,7 @@ func loadDbConn(snap *snapHelper, targetDir string, req dto.SnapshotCreate) erro
return nil return nil
} }
func snapBaseData(snap snapHelper, targetDir string) error { func snapBaseData(snap snapHelper, targetDir string, withDockerConf bool) error {
snap.Task.Log("---------------------- 2 / 8 ----------------------") snap.Task.Log("---------------------- 2 / 8 ----------------------")
snap.Task.LogStart(i18n.GetMsgByKey("SnapBaseInfo")) snap.Task.LogStart(i18n.GetMsgByKey("SnapBaseInfo"))
@@ -321,11 +326,13 @@ func snapBaseData(snap snapHelper, targetDir string) error {
return err return err
} }
if snap.FileOp.Stat("/etc/docker/daemon.json") { if withDockerConf {
err = snap.FileOp.CopyFile("/etc/docker/daemon.json", targetDir) if snap.FileOp.Stat(constant.DaemonJsonPath) {
snap.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/etc/docker/daemon.json"), err) err = snap.FileOp.CopyFile(constant.DaemonJsonPath, targetDir)
if err != nil { snap.Task.LogWithStatus(i18n.GetWithName("SnapCopy", constant.DaemonJsonPath), err)
return err if err != nil {
return err
}
} }
} }
@@ -377,8 +384,8 @@ func snapAppImage(snap snapHelper, req dto.SnapshotCreate, targetDir string) err
} }
} }
snap.Task.Log(strings.Join(imageList, " "))
if len(imageList) != 0 { 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")) snap.Task.Logf("docker save %s | gzip -c > %s", strings.Join(imageList, " "), path.Join(targetDir, "images.tar.gz"))
std, err := cmd.NewCommandMgr(cmd.WithTimeout(10*time.Minute)).RunWithStdoutBashCf("docker save %s | gzip -c > %s", strings.Join(imageList, " "), path.Join(targetDir, "images.tar.gz")) std, err := cmd.NewCommandMgr(cmd.WithTimeout(10*time.Minute)).RunWithStdoutBashCf("docker save %s | gzip -c > %s", strings.Join(imageList, " "), path.Join(targetDir, "images.tar.gz"))
if err != nil { if err != nil {
@@ -386,6 +393,8 @@ func snapAppImage(snap snapHelper, req dto.SnapshotCreate, targetDir string) err
return errors.New(std) return errors.New(std)
} }
snap.Task.LogSuccess(i18n.GetMsgByKey("SnapDockerSave")) snap.Task.LogSuccess(i18n.GetMsgByKey("SnapDockerSave"))
} else {
snap.Task.Log(i18n.GetMsgByKey("SnapInstallAppImageEmpty"))
} }
return nil return nil
} }
@@ -395,6 +404,7 @@ func snapBackupData(snap snapHelper, req dto.SnapshotCreate, targetDir string) e
snap.Task.LogStart(i18n.GetMsgByKey("SnapLocalBackup")) snap.Task.LogStart(i18n.GetMsgByKey("SnapLocalBackup"))
excludes := loadBackupExcludes(snap, req.BackupData) excludes := loadBackupExcludes(snap, req.BackupData)
excludes = append(excludes, req.IgnoreFiles...)
excludes = append(excludes, "./system_snapshot") excludes = append(excludes, "./system_snapshot")
for _, item := range req.AppData { for _, item := range req.AppData {
for _, itemApp := range item.Children { for _, itemApp := range item.Children {
@@ -418,7 +428,8 @@ func loadBackupExcludes(snap snapHelper, req []dto.DataTree) []string {
if err := snap.snapAgentDB.Where("file_dir = ? AND file_name = ?", strings.TrimPrefix(path.Dir(item.Path), global.Dir.LocalBackupDir+"/"), path.Base(item.Path)).Delete(&model.BackupRecord{}).Error; err != nil { if err := snap.snapAgentDB.Where("file_dir = ? AND file_name = ?", strings.TrimPrefix(path.Dir(item.Path), global.Dir.LocalBackupDir+"/"), path.Base(item.Path)).Delete(&model.BackupRecord{}).Error; err != nil {
snap.Task.LogWithStatus("delete backup file from database", err) snap.Task.LogWithStatus("delete backup file from database", err)
} }
excludes = append(excludes, "."+strings.TrimPrefix(item.Path, global.Dir.LocalBackupDir)) itemDir, _ := filepath.Rel(item.Path, global.Dir.LocalBackupDir)
excludes = append(excludes, itemDir)
} else { } else {
excludes = append(excludes, loadBackupExcludes(snap, item.Children)...) excludes = append(excludes, loadBackupExcludes(snap, item.Children)...)
} }
@@ -430,7 +441,8 @@ func loadAppBackupExcludes(req []dto.DataTree) []string {
for _, item := range req { for _, item := range req {
if len(item.Children) == 0 { if len(item.Children) == 0 {
if !item.IsCheck { if !item.IsCheck {
excludes = append(excludes, "."+strings.TrimPrefix(item.Path, path.Join(global.Dir.LocalBackupDir))) itemDir, _ := filepath.Rel(item.Path, global.Dir.LocalBackupDir)
excludes = append(excludes, itemDir)
} }
} else { } else {
excludes = append(excludes, loadAppBackupExcludes(item.Children)...) excludes = append(excludes, loadAppBackupExcludes(item.Children)...)
@@ -463,26 +475,21 @@ func snapPanelData(snap snapHelper, req dto.SnapshotCreate, targetDir string) er
rootDir := global.Dir.DataDir rootDir := global.Dir.DataDir
if strings.Contains(global.Dir.LocalBackupDir, rootDir) { if strings.Contains(global.Dir.LocalBackupDir, rootDir) {
excludes = append(excludes, "."+strings.ReplaceAll(global.Dir.LocalBackupDir, rootDir, "")) itemDir, _ := filepath.Rel(rootDir, global.Dir.LocalBackupDir)
excludes = append(excludes, itemDir)
} }
if len(snap.OpenrestyDir) != 0 && strings.Contains(snap.OpenrestyDir, rootDir) { if len(snap.OpenrestyDir) != 0 && strings.Contains(snap.OpenrestyDir, rootDir) {
excludes = append(excludes, "."+strings.ReplaceAll(snap.OpenrestyDir, rootDir, "")) itemDir, _ := filepath.Rel(rootDir, snap.OpenrestyDir)
} excludes = append(excludes, itemDir)
ignoreVal, _ := settingRepo.Get(settingRepo.WithByKey("SnapshotIgnore"))
rules := strings.Split(ignoreVal.Value, ",")
for _, ignore := range rules {
if len(ignore) == 0 || cmd.CheckIllegal(ignore) {
continue
}
excludes = append(excludes, "."+strings.ReplaceAll(ignore, rootDir, ""))
} }
excludes = append(excludes, req.IgnoreFiles...)
err := snap.FileOp.TarGzCompressPro(false, rootDir, path.Join(targetDir, "1panel_data.tar.gz"), "", strings.Join(excludes, ",")) err := snap.FileOp.TarGzCompressPro(false, rootDir, path.Join(targetDir, "1panel_data.tar.gz"), "", strings.Join(excludes, ","))
snap.Task.LogWithStatus(i18n.GetMsgByKey("SnapCompressPanel"), err) snap.Task.LogWithStatus(i18n.GetMsgByKey("SnapCompressPanel"), err)
if err != nil { if err != nil {
return err return err
} }
if len(snap.OpenrestyDir) != 0 { if len(snap.OpenrestyDir) != 0 {
err := snap.FileOp.TarGzCompressPro(false, snap.OpenrestyDir, path.Join(targetDir, "website.tar.gz"), "", "") err := snap.FileOp.TarGzCompressPro(false, snap.OpenrestyDir, path.Join(targetDir, "website.tar.gz"), "", strings.Join(req.IgnoreFiles, ","))
snap.Task.LogWithStatus(i18n.GetMsgByKey("SnapWebsite"), err) snap.Task.LogWithStatus(i18n.GetMsgByKey("SnapWebsite"), err)
if err != nil { if err != nil {
return err return err
@@ -496,7 +503,8 @@ func loadPanelExcludes(req []dto.DataTree) []string {
for _, item := range req { for _, item := range req {
if len(item.Children) == 0 { if len(item.Children) == 0 {
if !item.IsCheck { if !item.IsCheck {
excludes = append(excludes, "."+strings.TrimPrefix(item.Path, path.Join(global.Dir.BaseDir, "1panel"))) itemDir, _ := filepath.Rel(item.Path, path.Join(global.Dir.BaseDir, "1panel"))
excludes = append(excludes, itemDir)
} }
} else { } else {
excludes = append(excludes, loadPanelExcludes(item.Children)...) excludes = append(excludes, loadPanelExcludes(item.Children)...)
+53 -21
View File
@@ -38,6 +38,18 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
_ = snapshotRepo.Update(snap.ID, map[string]interface{}{"recover_status": constant.StatusFailed, "recover_message": errInfo}) _ = snapshotRepo.Update(snap.ID, map[string]interface{}{"recover_status": constant.StatusFailed, "recover_message": errInfo})
return errors.New(errInfo) return errors.New(errInfo)
} }
if !strings.Contains(snap.Name, "-v2.") {
return errors.New("snapshots are currently not supported for recovery across major versions")
}
if !strings.Contains(snap.Name, "-core") && !strings.Contains(snap.Name, "-agent") {
return errors.New("the name of the snapshot file does not conform to the format")
}
if strings.Contains(snap.Name, "-core") && !global.IsMaster {
return errors.New("the snapshot of the master node cannot be restored on the agent nodes")
}
if strings.Contains(snap.Name, "-agent") && global.IsMaster {
return errors.New("the snapshot of the agent node cannot be restored on the master node")
}
if len(snap.RollbackStatus) != 0 && snap.RollbackStatus != constant.StatusSuccess { if len(snap.RollbackStatus) != 0 && snap.RollbackStatus != constant.StatusSuccess {
req.IsNew = true req.IsNew = true
} }
@@ -55,7 +67,13 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
} else { } else {
_ = snapshotRepo.Update(snap.ID, map[string]interface{}{"task_recover_id": req.TaskID}) _ = snapshotRepo.Update(snap.ID, map[string]interface{}{"task_recover_id": req.TaskID})
} }
taskItem, err := task.NewTaskWithOps(snap.Name, task.TaskRecover, task.TaskScopeSnapshot, req.TaskID, snap.ID)
var taskItem *task.Task
if req.IsNew {
taskItem, err = task.NewTaskWithOps(snap.Name, task.TaskRecover, task.TaskScopeSnapshot, req.TaskID, snap.ID)
} else {
taskItem, err = task.ReNewTaskWithOps(snap.Name, task.TaskRecover, task.TaskScopeSnapshot, req.TaskID, snap.ID)
}
if err != nil { if err != nil {
global.LOG.Errorf("new task for create snapshot failed, err: %v", err) global.LOG.Errorf("new task for create snapshot failed, err: %v", err)
return err return err
@@ -84,7 +102,7 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
taskItem.AddSubTaskWithAlias( taskItem.AddSubTaskWithAlias(
"RecoverDecompress", "RecoverDecompress",
func(t *task.Task) error { func(t *task.Task) error {
itemHelper.Task.Log("---------------------- 2 / 10 ----------------------") itemHelper.Task.Log("---------------------- 2 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetWithName("RecoverDecompress", snap.Name)) itemHelper.Task.LogStart(i18n.GetWithName("RecoverDecompress", snap.Name))
err := itemHelper.FileOp.TarGzExtractPro(fmt.Sprintf("%s/%s.tar.gz", rootDir, snap.Name), rootDir, req.Secret) err := itemHelper.FileOp.TarGzExtractPro(fmt.Sprintf("%s/%s.tar.gz", rootDir, snap.Name), rootDir, req.Secret)
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("Decompress"), err) itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("Decompress"), err)
@@ -140,7 +158,7 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
taskItem.AddSubTaskWithAlias( taskItem.AddSubTaskWithAlias(
"RecoverBackups", "RecoverBackups",
func(t *task.Task) error { func(t *task.Task) error {
itemHelper.Task.Log("---------------------- 8 / 10 ----------------------") itemHelper.Task.Log("---------------------- 8 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetWithName("RecoverBackups", snap.Name)) itemHelper.Task.LogStart(i18n.GetWithName("RecoverBackups", snap.Name))
err := itemHelper.FileOp.TarGzExtractPro(path.Join(rootDir, snap.Name, "/1panel_backup.tar.gz"), snapJson.BackupDataDir, "") err := itemHelper.FileOp.TarGzExtractPro(path.Join(rootDir, snap.Name, "/1panel_backup.tar.gz"), snapJson.BackupDataDir, "")
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("Decompress"), err) itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("Decompress"), err)
@@ -150,11 +168,29 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
) )
req.IsNew = true req.IsNew = true
} }
if req.IsNew || snap.InterruptStep == "RecoverWebsite" {
taskItem.AddSubTaskWithAlias(
"RecoverWebsite",
func(t *task.Task) error {
itemHelper.Task.Log("---------------------- 9 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetWithName("RecoverWebsite", snap.Name))
webFile := path.Join(rootDir, snap.Name, "/website.tar.gz")
var err error
if itemHelper.FileOp.Stat(webFile) {
err = itemHelper.FileOp.TarGzExtractPro(webFile, snapJson.OperestyDir, "")
}
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("Decompress"), err)
return err
},
nil,
)
req.IsNew = true
}
if req.IsNew || snap.InterruptStep == "RecoverPanelData" { if req.IsNew || snap.InterruptStep == "RecoverPanelData" {
taskItem.AddSubTaskWithAlias( taskItem.AddSubTaskWithAlias(
"RecoverPanelData", "RecoverPanelData",
func(t *task.Task) error { func(t *task.Task) error {
itemHelper.Task.Log("---------------------- 9 / 10 ----------------------") itemHelper.Task.Log("---------------------- 10 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetWithName("RecoverPanelData", snap.Name)) itemHelper.Task.LogStart(i18n.GetWithName("RecoverPanelData", snap.Name))
err := itemHelper.FileOp.TarGzExtractPro(path.Join(rootDir, snap.Name, "/1panel_data.tar.gz"), path.Join(snapJson.BaseDir, "1panel"), "") err := itemHelper.FileOp.TarGzExtractPro(path.Join(rootDir, snap.Name, "/1panel_data.tar.gz"), path.Join(snapJson.BaseDir, "1panel"), "")
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("Decompress"), err) itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("Decompress"), err)
@@ -195,7 +231,7 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
} }
func handleDownloadSnapshot(itemHelper *snapRecoverHelper, snap model.Snapshot, targetDir string) error { func handleDownloadSnapshot(itemHelper *snapRecoverHelper, snap model.Snapshot, targetDir string) error {
itemHelper.Task.Log("---------------------- 1 / 10 ----------------------") itemHelper.Task.Log("---------------------- 1 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetMsgByKey("RecoverDownload")) itemHelper.Task.LogStart(i18n.GetMsgByKey("RecoverDownload"))
account, client, err := NewBackupClientWithID(snap.DownloadAccountID) account, client, err := NewBackupClientWithID(snap.DownloadAccountID)
@@ -214,7 +250,7 @@ func handleDownloadSnapshot(itemHelper *snapRecoverHelper, snap model.Snapshot,
} }
func backupBeforeRecover(name string, itemHelper *snapRecoverHelper) error { func backupBeforeRecover(name string, itemHelper *snapRecoverHelper) error {
itemHelper.Task.Log("---------------------- 3 / 10 ----------------------") itemHelper.Task.Log("---------------------- 3 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetMsgByKey("BackupBeforeRecover")) itemHelper.Task.LogStart(i18n.GetMsgByKey("BackupBeforeRecover"))
rootDir := fmt.Sprintf("%s/1panel_original/original_%s", global.Dir.BaseDir, name) rootDir := fmt.Sprintf("%s/1panel_original/original_%s", global.Dir.BaseDir, name)
@@ -273,9 +309,9 @@ func backupBeforeRecover(name string, itemHelper *snapRecoverHelper) error {
if err != nil { if err != nil {
return err return err
} }
if itemHelper.FileOp.Stat("/etc/docker/daemon.json") { if itemHelper.FileOp.Stat(constant.DaemonJsonPath) {
err = itemHelper.FileOp.CopyFile("/etc/docker/daemon.json", baseDir) err = itemHelper.FileOp.CopyFile(constant.DaemonJsonPath, baseDir)
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/etc/docker/daemon.json"), err) itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", constant.DaemonJsonPath), err)
if err != nil { if err != nil {
return err return err
} }
@@ -284,7 +320,7 @@ func backupBeforeRecover(name string, itemHelper *snapRecoverHelper) error {
} }
func readFromJson(rootDir string, itemHelper *snapRecoverHelper) (SnapshotJson, error) { func readFromJson(rootDir string, itemHelper *snapRecoverHelper) (SnapshotJson, error) {
itemHelper.Task.Log("---------------------- 4 / 10 ----------------------") itemHelper.Task.Log("---------------------- 4 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetMsgByKey("Readjson")) itemHelper.Task.LogStart(i18n.GetMsgByKey("Readjson"))
snapJsonPath := path.Join(rootDir, "base/snapshot.json") snapJsonPath := path.Join(rootDir, "base/snapshot.json")
@@ -308,7 +344,7 @@ func readFromJson(rootDir string, itemHelper *snapRecoverHelper) (SnapshotJson,
} }
func recoverAppData(src string, itemHelper *snapRecoverHelper) error { func recoverAppData(src string, itemHelper *snapRecoverHelper) error {
itemHelper.Task.Log("---------------------- 5 / 10 ----------------------") itemHelper.Task.Log("---------------------- 5 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetMsgByKey("RecoverApp")) itemHelper.Task.LogStart(i18n.GetMsgByKey("RecoverApp"))
if _, err := os.Stat(path.Join(src, "images.tar.gz")); err != nil { if _, err := os.Stat(path.Join(src, "images.tar.gz")); err != nil {
@@ -325,7 +361,7 @@ func recoverAppData(src string, itemHelper *snapRecoverHelper) error {
} }
func recoverBaseData(src string, itemHelper *snapRecoverHelper) error { func recoverBaseData(src string, itemHelper *snapRecoverHelper) error {
itemHelper.Task.Log("---------------------- 6 / 10 ----------------------") itemHelper.Task.Log("---------------------- 6 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetMsgByKey("SnapBaseInfo")) itemHelper.Task.LogStart(i18n.GetMsgByKey("SnapBaseInfo"))
if global.IsMaster { if global.IsMaster {
@@ -356,15 +392,11 @@ func recoverBaseData(src string, itemHelper *snapRecoverHelper) error {
return err return err
} }
daemonJsonPath := "/etc/docker/daemon.json" if !itemHelper.FileOp.Stat(path.Join(src, "daemon.json")) {
_, errSrc := os.Stat(path.Join(src, "docker/daemon.json"))
_, errPath := os.Stat(daemonJsonPath)
if os.IsNotExist(errSrc) && os.IsNotExist(errPath) {
itemHelper.Task.Log(i18n.GetMsgByKey("RecoverDaemonJsonEmpty")) itemHelper.Task.Log(i18n.GetMsgByKey("RecoverDaemonJsonEmpty"))
return nil return nil
} } else {
if errSrc == nil { err = itemHelper.FileOp.CopyFile(path.Join(src, "daemon.json"), path.Dir(constant.DaemonJsonPath))
err = itemHelper.FileOp.CopyFile(path.Join(src, "docker/daemon.json"), "/etc/docker")
itemHelper.Task.Log(i18n.GetMsgByKey("RecoverDaemonJson")) itemHelper.Task.Log(i18n.GetMsgByKey("RecoverDaemonJson"))
if err != nil { if err != nil {
return fmt.Errorf("recover docker daemon.json failed, err: %v", err) return fmt.Errorf("recover docker daemon.json failed, err: %v", err)
@@ -378,7 +410,7 @@ func recoverBaseData(src string, itemHelper *snapRecoverHelper) error {
} }
func recoverDBData(src string, itemHelper *snapRecoverHelper) error { func recoverDBData(src string, itemHelper *snapRecoverHelper) error {
itemHelper.Task.Log("---------------------- 7 / 10 ----------------------") itemHelper.Task.Log("---------------------- 7 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetMsgByKey("RecoverDBData")) itemHelper.Task.LogStart(i18n.GetMsgByKey("RecoverDBData"))
err := itemHelper.FileOp.CopyDirWithExclude(src, global.Dir.DataDir, nil) err := itemHelper.FileOp.CopyDirWithExclude(src, global.Dir.DataDir, nil)
@@ -387,7 +419,7 @@ func recoverDBData(src string, itemHelper *snapRecoverHelper) error {
} }
func restartCompose(composePath string, itemHelper *snapRecoverHelper) error { func restartCompose(composePath string, itemHelper *snapRecoverHelper) error {
itemHelper.Task.Log("---------------------- 10 / 10 ----------------------") itemHelper.Task.Log("---------------------- 11 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetMsgByKey("RecoverCompose")) itemHelper.Task.LogStart(i18n.GetMsgByKey("RecoverCompose"))
composes, err := composeRepo.ListRecord() composes, err := composeRepo.ListRecord()
+5 -2
View File
@@ -76,9 +76,12 @@ func (u *SnapshotService) SnapshotRollback(req dto.SnapshotRecover) error {
nil, nil,
) )
taskItem.AddSubTask( taskItem.AddSubTask(
i18n.GetWithName("SnapCopy", "/etc/docker/daemon.json"), i18n.GetWithName("SnapCopy", constant.DaemonJsonPath),
func(t *task.Task) error { func(t *task.Task) error {
return FileOp.CopyFile(path.Join(baseDir, "daemon.json"), "/etc/docker") if FileOp.Stat(path.Join(baseDir, "daemon.json")) {
return FileOp.CopyFile(path.Join(baseDir, "daemon.json"), path.Dir(constant.DaemonJsonPath))
}
return nil
}, },
nil, nil,
) )
+20 -26
View File
@@ -415,6 +415,7 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error)
return err return err
} }
website.ParentWebsiteID = parentWebsite.ID website.ParentWebsiteID = parentWebsite.ID
website.SiteDir = create.SiteDir
} }
configNginx := func(t *task.Task) error { configNginx := func(t *task.Task) error {
@@ -922,18 +923,12 @@ func (w WebsiteService) GetWebsiteHTTPS(websiteId uint) (response.WebsiteHTTPS,
res response.WebsiteHTTPS res response.WebsiteHTTPS
httpsPorts []string httpsPorts []string
) )
websiteDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(websiteId))
for _, domain := range websiteDomains { httpsPortsMap := getHttpsPort(websiteId)
if domain.SSL { for port := range httpsPortsMap {
httpsPorts = append(httpsPorts, strconv.Itoa(domain.Port)) httpsPorts = append(httpsPorts, strconv.Itoa(port))
}
}
if len(httpsPorts) == 0 {
nginxInstall, _ := getAppInstallByKey(constant.AppOpenresty)
res.HttpsPort = strconv.Itoa(nginxInstall.HttpsPort)
} else {
res.HttpsPort = strings.Join(httpsPorts, ",")
} }
res.HttpsPort = strings.Join(httpsPorts, ",")
if website.WebsiteSSLID == 0 { if website.WebsiteSSLID == 0 {
res.Enable = false res.Enable = false
return res, nil return res, nil
@@ -981,10 +976,6 @@ func (w WebsiteService) OpWebsiteHTTPS(ctx context.Context, req request.WebsiteH
res response.WebsiteHTTPS res response.WebsiteHTTPS
websiteSSL model.WebsiteSSL websiteSSL model.WebsiteSSL
) )
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
if err != nil {
return nil, err
}
if err = ChangeHSTSConfig(req.Hsts, req.Http3, website); err != nil { if err = ChangeHSTSConfig(req.Hsts, req.Http3, website); err != nil {
return nil, err return nil, err
} }
@@ -995,24 +986,27 @@ func (w WebsiteService) OpWebsiteHTTPS(ctx context.Context, req request.WebsiteH
website.Protocol = constant.ProtocolHTTP website.Protocol = constant.ProtocolHTTP
website.WebsiteSSLID = 0 website.WebsiteSSLID = 0
httpsPorts, err := getHttpsPort(&website) websiteDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(website.ID))
ports := make(map[int]struct{})
for _, domain := range websiteDomains {
ports[domain.Port] = struct{}{}
}
for port := range ports {
if err = removeSSLListen(website, []string{strconv.Itoa(port)}); err != nil {
return nil, err
}
}
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if len(httpsPorts) == 1 && httpsPorts[0] == nginxInstall.HttpsPort { if _, ok := ports[nginxInstall.HttpsPort]; !ok {
httpsPortStr := strconv.Itoa(httpsPorts[0]) httpsPortStr := strconv.Itoa(nginxInstall.HttpsPort)
if err = deleteListenAndServerName(website, []string{httpsPortStr, "[::]:" + httpsPortStr}, []string{}); err != nil { if err = deleteListenAndServerName(website, []string{httpsPortStr, "[::]:" + httpsPortStr}, []string{}); err != nil {
return nil, err return nil, err
} }
} else {
for _, port := range httpsPorts {
httpsPortStr := strconv.Itoa(port)
if err = removeSSLListen(website, []string{httpsPortStr}); err != nil {
return nil, err
}
}
} }
nginxParams := getNginxParamsFromStaticFile(dto.SSL, nil) nginxParams := getNginxParamsFromStaticFile(dto.SSL, nil)
nginxParams = append(nginxParams, nginxParams = append(nginxParams,
dto.NginxParam{ dto.NginxParam{
+61 -43
View File
@@ -182,8 +182,8 @@ func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, a
return err return err
} }
configPath := GetSitePath(*website, SiteConf) configPath := GetSitePath(*website, SiteConf)
nginxContent := string(nginx_conf.WebsiteDefault) nginxContent := nginx_conf.GetWebsiteFile("website_default.conf")
config, err := parser.NewStringParser(nginxContent).Parse() config, err := parser.NewStringParser(string(nginxContent)).Parse()
if err != nil { if err != nil {
return err return err
} }
@@ -651,22 +651,33 @@ func createPemFile(website model.Website, websiteSSL model.WebsiteSSL) error {
return nil return nil
} }
func getHttpsPort(website *model.Website) ([]int, error) { func getHttpsPort(websiteID uint) map[int]struct{} {
websiteDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(website.ID)) domains, err := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(websiteID))
var httpsPorts []int if err != nil {
for _, domain := range websiteDomains { return nil
if domain.SSL { }
httpsPorts = append(httpsPorts, domain.Port) httpsPorts := make(map[int]struct{})
nginxInstall, _ := getAppInstallByKey(constant.AppOpenresty)
hasDefaultPort := false
for _, domain := range domains {
if domain.Port == nginxInstall.HttpPort {
hasDefaultPort = true
} }
if domain.SSL {
httpsPorts[domain.Port] = struct{}{}
}
}
if hasDefaultPort {
httpsPorts[nginxInstall.HttpsPort] = struct{}{}
} }
if len(httpsPorts) == 0 { if len(httpsPorts) == 0 {
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) for _, domain := range domains {
if err != nil { if !domain.SSL {
return nil, err httpsPorts[domain.Port] = struct{}{}
}
} }
httpsPorts = append(httpsPorts, nginxInstall.HttpsPort)
} }
return httpsPorts, nil return httpsPorts
} }
func applySSL(website *model.Website, websiteSSL model.WebsiteSSL, req request.WebsiteHTTPSOp) error { func applySSL(website *model.Website, websiteSSL model.WebsiteSSL, req request.WebsiteHTTPSOp) error {
@@ -678,63 +689,71 @@ func applySSL(website *model.Website, websiteSSL model.WebsiteSSL, req request.W
if err != nil { if err != nil {
return nil return nil
} }
noDefaultPort := true
httpPorts := make(map[int]struct{}) httpPorts := make(map[int]struct{})
httpsPorts := make(map[int]struct{})
hasDefaultPort := false
for _, domain := range domains { for _, domain := range domains {
if domain.Port == 80 { if domain.Port == nginxFull.Install.HttpPort {
noDefaultPort = false hasDefaultPort = true
} }
if domain.Port != 80 && !domain.SSL { if domain.SSL {
httpsPorts[domain.Port] = struct{}{}
} else {
httpPorts[domain.Port] = struct{}{} httpPorts[domain.Port] = struct{}{}
} }
} }
if hasDefaultPort {
httpsPorts[nginxFull.Install.HttpsPort] = struct{}{}
}
if len(httpsPorts) == 0 {
for port := range httpPorts {
httpsPorts[port] = struct{}{}
}
}
config := nginxFull.SiteConfig.Config config := nginxFull.SiteConfig.Config
server := config.FindServers()[0] server := config.FindServers()[0]
httpPort := strconv.Itoa(nginxFull.Install.HttpPort) defaultHttpPort := strconv.Itoa(nginxFull.Install.HttpPort)
httpsPort, err := getHttpsPort(website) defaultHttpPortIPV6 := "[::]:" + defaultHttpPort
if err != nil {
return err
}
httpPortIPV6 := "[::]:" + httpPort
for _, port := range httpsPort { for port := range httpsPorts {
if _, ok := httpPorts[port]; !ok { portStr := strconv.Itoa(port)
server.DeleteListen(strconv.Itoa(port)) server.RemoveListenByBind(portStr)
} server.RemoveListenByBind("[::]:" + portStr)
setListen(server, strconv.Itoa(port), website.IPV6, req.Http3, website.DefaultServer, true) setListen(server, portStr, website.IPV6, req.Http3, website.DefaultServer, true)
} }
server.UpdateDirective("http2", []string{"on"}) server.UpdateDirective("http2", []string{"on"})
switch req.HttpConfig { switch req.HttpConfig {
case constant.HTTPSOnly: case constant.HTTPSOnly:
server.RemoveListenByBind(httpPort) server.RemoveListenByBind(defaultHttpPort)
server.RemoveListenByBind(httpPortIPV6) server.RemoveListenByBind(defaultHttpPortIPV6)
server.RemoveDirective("if", []string{"($scheme"}) server.RemoveDirective("if", []string{"($scheme"})
case constant.HTTPToHTTPS: case constant.HTTPToHTTPS:
if !noDefaultPort { if hasDefaultPort {
server.UpdateListen(httpPort, website.DefaultServer) server.UpdateListen(defaultHttpPort, website.DefaultServer)
} if website.IPV6 {
if website.IPV6 { server.UpdateListen(defaultHttpPortIPV6, website.DefaultServer)
server.UpdateListen(httpPortIPV6, website.DefaultServer) }
} }
server.AddHTTP2HTTPS() server.AddHTTP2HTTPS()
case constant.HTTPAlso: case constant.HTTPAlso:
if !noDefaultPort { if hasDefaultPort {
server.UpdateListen(httpPort, website.DefaultServer) server.UpdateListen(defaultHttpPort, website.DefaultServer)
if website.IPV6 {
server.UpdateListen(defaultHttpPortIPV6, website.DefaultServer)
}
} }
server.RemoveDirective("if", []string{"($scheme"}) server.RemoveDirective("if", []string{"($scheme"})
if website.IPV6 {
server.UpdateListen(httpPortIPV6, website.DefaultServer)
}
} }
if !req.Hsts { if !req.Hsts {
server.RemoveDirective("add_header", []string{"Strict-Transport-Security", "\"max-age=31536000\""}) server.RemoveDirective("add_header", []string{"Strict-Transport-Security", "\"max-age=31536000\""})
} }
if !req.Http3 { if !req.Http3 {
for _, port := range httpsPort { for port := range httpsPorts {
server.RemoveListen(strconv.Itoa(port), "quic") server.RemoveListen(strconv.Itoa(port), "quic")
if website.IPV6 { if website.IPV6 {
httpsPortIPV6 := "[::]:" + strconv.Itoa(port) httpsPortIPV6 := "[::]:" + strconv.Itoa(port)
@@ -1078,7 +1097,7 @@ func getWebsiteDomains(domains []request.WebsiteDomain, defaultPort int, website
err = buserr.WithMap("ErrPortExist", errMap, nil) err = buserr.WithMap("ErrPortExist", errMap, nil)
return return
} }
if common.ScanPort(port) { if port != 443 && common.ScanPort(port) {
err = buserr.WithDetail("ErrPortInUsed", port, nil) err = buserr.WithDetail("ErrPortInUsed", port, nil)
return return
} }
@@ -1117,7 +1136,6 @@ func saveCertificateFile(websiteSSL *model.WebsiteSSL, logger *log.Logger) {
func GetSystemSSL() (bool, uint) { func GetSystemSSL() (bool, uint) {
sslSetting, err := settingRepo.Get(settingRepo.WithByKey("SSL")) sslSetting, err := settingRepo.Get(settingRepo.WithByKey("SSL"))
if err != nil { if err != nil {
global.LOG.Errorf("load service ssl from setting failed, err: %v", err)
return false, 0 return false, 0
} }
if sslSetting.Value == "enable" { if sslSetting.Value == "enable" {
+35 -1
View File
@@ -142,6 +142,40 @@ func NewTask(name, operate, taskScope, taskID string, resourceID uint) (*Task, e
return task, nil return task, nil
} }
func ReNewTaskWithOps(resourceName, operate, scope, taskID string, resourceID uint) (*Task, error) {
return ReNewTask(GetTaskName(resourceName, operate, scope), operate, scope, taskID, resourceID)
}
func ReNewTask(name, operate, taskScope, taskID string, resourceID uint) (*Task, error) {
if taskID == "" {
return NewTask(name, operate, taskScope, taskID, resourceID)
}
logDir := path.Join(global.Dir.TaskDir, taskScope)
if _, err := os.Stat(logDir); err != nil {
if err = os.MkdirAll(logDir, constant.DirPerm); err != nil {
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)
if err != nil {
return nil, fmt.Errorf("failed to open log file: %w", err)
}
writer := bufio.NewWriter(file)
logger := log.New(file, "", log.LstdFlags)
taskModel := &model.Task{
ID: taskID,
Name: name,
Type: taskScope,
LogFile: logPath,
Status: constant.StatusExecuting,
ResourceID: resourceID,
Operate: operate,
}
taskRepo := repo.NewITaskRepo()
task := &Task{Name: name, logFile: file, Logger: logger, taskRepo: taskRepo, Task: taskModel, Writer: writer}
return task, nil
}
func (t *Task) AddSubTask(name string, action ActionFunc, rollback RollbackFunc) { func (t *Task) AddSubTask(name string, action ActionFunc, rollback RollbackFunc) {
subTask := &SubTask{RootTask: t, Name: name, Retry: 0, Timeout: 30 * time.Minute, Action: action, Rollback: rollback} subTask := &SubTask{RootTask: t, Name: name, Retry: 0, Timeout: 30 * time.Minute, Action: action, Rollback: rollback}
t.SubTasks = append(t.SubTasks, subTask) t.SubTasks = append(t.SubTasks, subTask)
@@ -158,7 +192,7 @@ func (t *Task) AddSubTaskWithOps(name string, action ActionFunc, rollback Rollba
} }
func (t *Task) AddSubTaskWithAliasAndOps(key string, action ActionFunc, rollback RollbackFunc, retry int, timeout time.Duration) { func (t *Task) AddSubTaskWithAliasAndOps(key string, action ActionFunc, rollback RollbackFunc, retry int, timeout time.Duration) {
subTask := &SubTask{RootTask: t, Name: i18n.GetMsgByKey(key), Retry: retry, Timeout: timeout, Action: action, Rollback: rollback} subTask := &SubTask{RootTask: t, Name: i18n.GetMsgByKey(key), StepAlias: key, Retry: retry, Timeout: timeout, Action: action, Rollback: rollback}
t.SubTasks = append(t.SubTasks, subTask) t.SubTasks = append(t.SubTasks, subTask)
} }
+1 -4
View File
@@ -9,9 +9,6 @@ import (
//go:embed ssl.conf //go:embed ssl.conf
var SSL []byte var SSL []byte
//go:embed website_default.conf
var WebsiteDefault []byte
//go:embed index.html //go:embed index.html
var Index []byte var Index []byte
@@ -48,7 +45,7 @@ var Upstream []byte
//go:embed sse.conf //go:embed sse.conf
var SSE []byte var SSE []byte
//go:embed *.json //go:embed *.json *.conf
var websitesFiles embed.FS var websitesFiles embed.FS
func GetWebsiteFile(filename string) []byte { func GetWebsiteFile(filename string) []byte {
+16
View File
@@ -0,0 +1,16 @@
[global]
error_log = /var/log/php/fpm.error.log
log_level = notice
[www]
user = www-data
group = www-data
listen = 0.0.0.0:9000
pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.status_path = /status
slowlog = /var/log/php/fpm.slow.log
request_slowlog_timeout = 3
catch_workers_output = yes
@@ -15,9 +15,16 @@ server {
access_log /www/sites/domain/log/access.log main; access_log /www/sites/domain/log/access.log main;
error_log /www/sites/domain/log/error.log; error_log /www/sites/domain/log/error.log;
location ~ ^/(\.user.ini|\.htaccess|\.git|\.env|\.svn|\.project|LICENSE|README.md){
return 404;
}
location ^~ /.well-known{ location ^~ /.well-known{
allow all; allow all;
root /usr/share/nginx/html; root /usr/share/nginx/html;
} }
if ( $uri ~ "^/\.well-known/.*\.(php|jsp|py|js|css|lua|ts|go|zip|tar\.gz|rar|7z|sql|bak)$" ) {
return 403;
}
} }
+2 -2
View File
@@ -13,6 +13,6 @@ const (
ComposeOpStop = "stop" ComposeOpStop = "stop"
ComposeOpRestart = "restart" ComposeOpRestart = "restart"
ComposeOpRemove = "remove" ComposeOpRemove = "remove"
DaemonJsonPath = "/etc/docker/daemon.json"
) )
var DaemonJsonPath = "/etc/docker/daemon.json"
+3 -3
View File
@@ -41,11 +41,11 @@ var RuntimeDefaultVolumes = map[string]string{
var PHPDefaultVolumes = map[string]string{ var PHPDefaultVolumes = map[string]string{
"${PANEL_WEBSITE_DIR}": "/www/", "${PANEL_WEBSITE_DIR}": "/www/",
"./conf": "/usr/local/etc/php", "./conf/php.ini": "/usr/local/etc/php/php.ini",
"./conf/conf.d": "/usr/local/etc/php/conf.d", "./conf/conf.d": "/usr/local/etc/php/conf.d",
"./conf/php-fpm.conf": "/usr/local/etc/php-fpm.d/www.conf", "./conf/php-fpm.conf": "/usr/local/etc/php-fpm.conf",
"./log": "/var/log/php", "./log": "/var/log/php",
"./extensions": "${EXTENSION_DIR}", "./extensions": "/usr/local/lib/php/extensions",
"./supervisor/supervisord.conf": "/etc/supervisord.conf", "./supervisor/supervisord.conf": "/etc/supervisord.conf",
"./supervisor/supervisor.d/php-fpm.ini": "/etc/supervisor.d/php-fpm.ini", "./supervisor/supervisor.d/php-fpm.ini": "/etc/supervisor.d/php-fpm.ini",
"./supervisor/supervisor.d": "/etc/supervisor.d", "./supervisor/supervisor.d": "/etc/supervisor.d",
+1 -3
View File
@@ -18,7 +18,7 @@ func NewBackupJob() *backup {
func (b *backup) Run() { func (b *backup) Run() {
var backups []model.BackupAccount var backups []model.BackupAccount
_ = global.DB.Where("`type` in (?) AND is_public = 0", []string{constant.OneDrive, constant.ALIYUN, constant.GoogleDrive}).Find(&backups) _ = global.DB.Where("`type` in (?) AND is_public = 0", []string{constant.OneDrive, constant.ALIYUN}).Find(&backups)
if len(backups) == 0 { if len(backups) == 0 {
return return
} }
@@ -39,8 +39,6 @@ func (b *backup) Run() {
switch backupItem.Type { switch backupItem.Type {
case constant.OneDrive: case constant.OneDrive:
refreshToken, err = client.RefreshToken("refresh_token", "refreshToken", varMap) refreshToken, err = client.RefreshToken("refresh_token", "refreshToken", varMap)
case constant.GoogleDrive:
refreshToken, err = client.RefreshGoogleToken("refresh_token", "refreshToken", varMap)
case constant.ALIYUN: case constant.ALIYUN:
refreshToken, err = client.RefreshALIToken(varMap) refreshToken, err = client.RefreshALIToken(varMap)
} }
+11 -11
View File
@@ -40,6 +40,7 @@ require (
github.com/shirou/gopsutil/v3 v3.24.5 github.com/shirou/gopsutil/v3 v3.24.5
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3
github.com/spf13/afero v1.11.0 github.com/spf13/afero v1.11.0
github.com/spf13/cobra v1.9.1
github.com/spf13/viper v1.19.0 github.com/spf13/viper v1.19.0
github.com/studio-b12/gowebdav v0.9.0 github.com/studio-b12/gowebdav v0.9.0
github.com/subosito/gotenv v1.6.0 github.com/subosito/gotenv v1.6.0
@@ -53,7 +54,7 @@ require (
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38
gopkg.in/ini.v1 v1.67.0 gopkg.in/ini.v1 v1.67.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
gorm.io/gorm v1.25.11 gorm.io/gorm v1.30.0
) )
require ( require (
@@ -98,7 +99,7 @@ require (
github.com/fvbommel/sortorder v1.1.0 // indirect github.com/fvbommel/sortorder v1.1.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.8 // indirect github.com/gabriel-vasile/mimetype v1.4.8 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect
github.com/glebarez/go-sqlite v1.21.2 // indirect github.com/glebarez/go-sqlite v1.22.0 // indirect
github.com/go-ini/ini v1.67.0 // indirect github.com/go-ini/ini v1.67.0 // indirect
github.com/go-jose/go-jose/v4 v4.0.5 // indirect github.com/go-jose/go-jose/v4 v4.0.5 // indirect
github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/logr v1.4.2 // indirect
@@ -106,7 +107,7 @@ require (
github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/go-viper/mapstructure/v2 v2.3.0 // indirect
github.com/goccy/go-json v0.10.5 // indirect github.com/goccy/go-json v0.10.5 // indirect
github.com/gofrs/flock v0.12.1 // indirect github.com/gofrs/flock v0.12.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
@@ -114,7 +115,6 @@ require (
github.com/golang/snappy v0.0.4 // indirect github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-querystring v1.1.0 // indirect
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect
github.com/h2non/filetype v1.1.1 // indirect github.com/h2non/filetype v1.1.1 // indirect
@@ -162,6 +162,7 @@ require (
github.com/morikuni/aec v1.0.0 // indirect github.com/morikuni/aec v1.0.0 // indirect
github.com/mozillazg/go-httpheader v0.2.1 // indirect github.com/mozillazg/go-httpheader v0.2.1 // indirect
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 // indirect github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/nrdcg/dnspod-go v0.4.0 // indirect github.com/nrdcg/dnspod-go v0.4.0 // indirect
github.com/nrdcg/freemyip v0.3.0 // indirect github.com/nrdcg/freemyip v0.3.0 // indirect
github.com/nrdcg/mailinabox v0.2.0 // indirect github.com/nrdcg/mailinabox v0.2.0 // indirect
@@ -184,7 +185,6 @@ require (
github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/cast v1.6.0 // indirect github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/cobra v1.9.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect github.com/spf13/pflag v1.0.6 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1128 // indirect github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1128 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1128 // indirect github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1128 // indirect
@@ -224,17 +224,17 @@ require (
go.uber.org/multierr v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect
go4.org v0.0.0-20200411211856-f5505b9728dd // indirect go4.org v0.0.0-20200411211856-f5505b9728dd // indirect
golang.org/x/arch v0.8.0 // indirect golang.org/x/arch v0.8.0 // indirect
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
golang.org/x/mod v0.25.0 // indirect golang.org/x/mod v0.25.0 // indirect
golang.org/x/sync v0.15.0 // indirect golang.org/x/sync v0.15.0 // indirect
golang.org/x/time v0.11.0 // indirect golang.org/x/time v0.11.0 // indirect
golang.org/x/tools v0.33.0 // indirect golang.org/x/tools v0.34.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect
google.golang.org/grpc v1.72.2 // indirect google.golang.org/grpc v1.72.2 // indirect
google.golang.org/protobuf v1.36.6 // indirect google.golang.org/protobuf v1.36.6 // indirect
modernc.org/libc v1.22.5 // indirect modernc.org/libc v1.66.1 // indirect
modernc.org/mathutil v1.5.0 // indirect modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.5.0 // indirect modernc.org/memory v1.11.0 // indirect
modernc.org/sqlite v1.23.1 // indirect modernc.org/sqlite v1.38.0 // indirect
) )
+41 -23
View File
@@ -257,8 +257,8 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo= github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ=
github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k= github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc=
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw= github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ= github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
github.com/go-acme/lego/v4 v4.23.1 h1:lZ5fGtGESA2L9FB8dNTvrQUq3/X4QOb8ExkKyY7LSV4= github.com/go-acme/lego/v4 v4.23.1 h1:lZ5fGtGESA2L9FB8dNTvrQUq3/X4QOb8ExkKyY7LSV4=
@@ -311,8 +311,8 @@ github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpv
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk=
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-viper/mapstructure/v2 v2.3.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
@@ -396,8 +396,8 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
@@ -571,9 +571,8 @@ github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6T
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA=
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mholt/archiver/v4 v4.0.0-alpha.8 h1:tRGQuDVPh66WCOelqe6LIGh0gwmfwxUrSSDunscGsRM= github.com/mholt/archiver/v4 v4.0.0-alpha.8 h1:tRGQuDVPh66WCOelqe6LIGh0gwmfwxUrSSDunscGsRM=
github.com/mholt/archiver/v4 v4.0.0-alpha.8/go.mod h1:5f7FUYGXdJWUjESffJaYR4R60VhnHxb2X3T1teMyv5A= github.com/mholt/archiver/v4 v4.0.0-alpha.8/go.mod h1:5f7FUYGXdJWUjESffJaYR4R60VhnHxb2X3T1teMyv5A=
@@ -650,6 +649,8 @@ github.com/nats-io/nats.go v1.12.1/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/
github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s=
github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4= github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM= github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM=
github.com/nicksnyder/go-i18n/v2 v2.4.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4= github.com/nicksnyder/go-i18n/v2 v2.4.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
@@ -755,7 +756,6 @@ github.com/qiniu/go-sdk/v7 v7.21.1/go.mod h1:8EM2awITynlem2VML2dXGHkMYP2UyECsGLO
github.com/qiniu/x v1.10.5/go.mod h1:03Ni9tj+N2h2aKnAz+6N0Xfl8FwMEDRC2PAlxekASDs= github.com/qiniu/x v1.10.5/go.mod h1:03Ni9tj+N2h2aKnAz+6N0Xfl8FwMEDRC2PAlxekASDs=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
@@ -1004,8 +1004,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@@ -1261,8 +1261,8 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 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.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1396,8 +1396,8 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/gorm v1.25.11 h1:/Wfyg1B/je1hnDx3sMkX+gAlxrlZpn6X0BXRlwXlvHg= gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
gorm.io/gorm v1.25.11/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@@ -1407,14 +1407,32 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE= modernc.org/cc/v4 v4.26.1 h1:+X5NtzVBn0KgsBCBe+xkDC7twLb/jNVj9FPgiwSQO3s=
modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY= modernc.org/cc/v4 v4.26.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU=
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE=
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds= modernc.org/fileutil v1.3.3 h1:3qaU+7f7xxTUmvU1pJTZiDLAIoJVdUSSauJNHg9yXoA=
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= modernc.org/fileutil v1.3.3/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM= modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk= modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/goabi0 v0.0.3 h1:y81b9r3asCh6Xtse6Nz85aYGB0cG3M3U6222yap1KWI=
modernc.org/goabi0 v0.0.3/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
modernc.org/libc v1.66.1 h1:4uQsntXbVyAgrV+j6NhKvDiUypoJL48BWQx6sy9y8ok=
modernc.org/libc v1.66.1/go.mod h1:AiZxInURfEJx516LqEaFcrC+X38rt9G7+8ojIXQKHbo=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.38.0 h1:+4OrfPQ8pxHKuWG4md1JpR/EYAh3Md7TdejuuzE7EUI=
modernc.org/sqlite v1.38.0/go.mod h1:1Bj+yES4SVvBZ4cBOpVZ6QgesMCKpJZDq0nxYzOpmNE=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
+3
View File
@@ -205,6 +205,8 @@ SystemLog: 'System Log'
CutWebsiteLog: 'Rotate Website Log' CutWebsiteLog: 'Rotate Website Log'
FileOrDir: 'Directory / File' FileOrDir: 'Directory / File'
UploadFile: 'Uploading backup file {{ .file }} to {{ .backup }}' UploadFile: 'Uploading backup file {{ .file }} to {{ .backup }}'
IgnoreBackupErr: 'Backup failed, error: {{ .detail }}, ignoring this error...'
IgnoreUploadErr: 'Upload failed, error: {{ .detail }}, ignoring this error...'
#toolbox #toolbox
ErrNotExistUser: 'The current user does not exist, please modify and try again!' ErrNotExistUser: 'The current user does not exist, please modify and try again!'
@@ -333,6 +335,7 @@ SnapDeleteLoginLog: 'Delete access log'
SnapDeleteMonitor: 'Delete monitoring data' SnapDeleteMonitor: 'Delete monitoring data'
SnapRemoveSystemIP: 'Remove system IP' SnapRemoveSystemIP: 'Remove system IP'
SnapBaseInfo: 'Write 1Panel basic information' SnapBaseInfo: 'Write 1Panel basic information'
SnapInstallAppImageEmpty: 'No application images selected, skipping...'
SnapInstallApp: 'Backup 1Panel installed applications' SnapInstallApp: 'Backup 1Panel installed applications'
SnapDockerSave: 'Compress installed applications' SnapDockerSave: 'Compress installed applications'
SnapLocalBackup: 'Backup 1Panel local backup directory' SnapLocalBackup: 'Backup 1Panel local backup directory'
+4 -1
View File
@@ -205,6 +205,8 @@ SystemLog: 'システムログ'
CutWebsiteLog: 'ウェブサイトログのローテーション' CutWebsiteLog: 'ウェブサイトログのローテーション'
FileOrDir: 'ディレクトリ / ファイル' FileOrDir: 'ディレクトリ / ファイル'
UploadFile: 'バックアップファイル {{ .file }} を {{ .backup }} にアップロード中' UploadFile: 'バックアップファイル {{ .file }} を {{ .backup }} にアップロード中'
IgnoreBackupErr: 'バックアップ失敗、エラー:{{ .detail }}、このエラーを無視します...'
IgnoreUploadErr: 'アップロード失敗、エラー:{{ .detail }}、このエラーを無視します...'
#toolbox #toolbox
ErrNotExistUser: '現在のユーザーは存在しません。変更してもう一度お試しください。' ErrNotExistUser: '現在のユーザーは存在しません。変更してもう一度お試しください。'
@@ -333,7 +335,8 @@ SnapDeleteLoginLog: 'アクセスログを削除する'
SnapDeleteMonitor: '監視データを削除する' SnapDeleteMonitor: '監視データを削除する'
SnapRemoveSystemIP: 'システム IP を削除します' SnapRemoveSystemIP: 'システム IP を削除します'
SnapBaseInfo: '1Panel の基本情報を書き込む' SnapBaseInfo: '1Panel の基本情報を書き込む'
SnapInstallApp: '1Panel にインストールされたアプリケーションをバックアップする' SnapInstallAppImageEmpty: 'アプリケーションイメージが選択されていないため、スキップします...'
SnapInstallApp: '1Panelインストール済みアプリケーションのバックアップ'
SnapDockerSave: 'インストールされたアプリケーションを圧縮する' SnapDockerSave: 'インストールされたアプリケーションを圧縮する'
SnapLocalBackup: '1Panel ローカル バックアップ ディレクトリをバックアップします' SnapLocalBackup: '1Panel ローカル バックアップ ディレクトリをバックアップします'
SnapCompressBackup: 'ローカル バックアップ ディレクトリを圧縮する' SnapCompressBackup: 'ローカル バックアップ ディレクトリを圧縮する'
+3
View File
@@ -205,6 +205,8 @@ SystemLog: '시스템 로그'
CutWebsiteLog: '웹사이트 로그 회전' CutWebsiteLog: '웹사이트 로그 회전'
FileOrDir: '디렉터리 / 파일' FileOrDir: '디렉터리 / 파일'
UploadFile: '백업 파일 {{ .file }} 을(를) {{ .backup }}(으)로 업로드 중' UploadFile: '백업 파일 {{ .file }} 을(를) {{ .backup }}(으)로 업로드 중'
IgnoreBackupErr: 'Sandaran gagal, ralat: {{ .detail }}, abaikan ralat ini...'
IgnoreUploadErr: 'Muat naik gagal, ralat: {{ .detail }}, abaikan ralat ini...'
#도구상자 #도구상자
ErrNotExistUser: '현재 사용자가 존재하지 않습니다. 수정한 후 다시 시도하세요!' ErrNotExistUser: '현재 사용자가 존재하지 않습니다. 수정한 후 다시 시도하세요!'
@@ -333,6 +335,7 @@ SnapDeleteLoginLog: '액세스 로그 삭제'
SnapDeleteMonitor: '모니터링 데이터 삭제' SnapDeleteMonitor: '모니터링 데이터 삭제'
SnapRemoveSystemIP: '시스템 IP 제거' SnapRemoveSystemIP: '시스템 IP 제거'
SnapBaseInfo: '1패널 기본 정보 쓰기' SnapBaseInfo: '1패널 기본 정보 쓰기'
SnapInstallAppImageEmpty: '애플리케이션 이미지가 선택되지 않아 건너뜁니다...'
SnapInstallApp: '1Panel 설치된 애플리케이션 백업' SnapInstallApp: '1Panel 설치된 애플리케이션 백업'
SnapDockerSave: '설치된 애플리케이션 압축' SnapDockerSave: '설치된 애플리케이션 압축'
SnapLocalBackup: '1Panel 로컬 백업 디렉토리 백업' SnapLocalBackup: '1Panel 로컬 백업 디렉토리 백업'
+4 -1
View File
@@ -204,6 +204,8 @@ SystemLog: 'Log Sistem'
CutWebsiteLog: 'Putar Log Laman Web' CutWebsiteLog: 'Putar Log Laman Web'
FileOrDir: 'Direktori / Fail' FileOrDir: 'Direktori / Fail'
UploadFile: 'Muat naik fail sandaran {{ .file }} ke {{ .backup }}' UploadFile: 'Muat naik fail sandaran {{ .file }} ke {{ .backup }}'
IgnoreBackupErr: 'Sandaran gagal, ralat: {{ .detail }}, abaikan ralat ini...'
IgnoreUploadErr: 'Muat naik gagal, ralat: {{ .detail }}, abaikan ralat ini...'
#kotak alat #kotak alat
ErrNotExistUser: 'Pengguna semasa tidak wujud, sila ubah suai dan cuba lagi!' ErrNotExistUser: 'Pengguna semasa tidak wujud, sila ubah suai dan cuba lagi!'
@@ -332,7 +334,8 @@ SnapDeleteLoginLog: 'Padam log akses'
SnapDeleteMonitor: 'Padamkan data pemantauan' SnapDeleteMonitor: 'Padamkan data pemantauan'
SnapRemoveSystemIP: 'Alih keluar IP sistem' SnapRemoveSystemIP: 'Alih keluar IP sistem'
SnapBaseInfo: 'Tulis maklumat asas 1Panel' SnapBaseInfo: 'Tulis maklumat asas 1Panel'
SnapInstallApp: 'Aplikasi yang dipasang sandaran 1Panel' SnapInstallAppImageEmpty: 'Tiada imej aplikasi dipilih, dilangkau...'
SnapInstallApp: 'Sandaran aplikasi terpasang 1Panel'
SnapDockerSave: 'Mampatkan aplikasi yang dipasang' SnapDockerSave: 'Mampatkan aplikasi yang dipasang'
SnapLocalBackup: 'Sandaran 1Panel direktori sandaran tempatan' SnapLocalBackup: 'Sandaran 1Panel direktori sandaran tempatan'
SnapCompressBackup: 'Mampatkan direktori sandaran tempatan' SnapCompressBackup: 'Mampatkan direktori sandaran tempatan'
+4 -1
View File
@@ -205,6 +205,8 @@ SystemLog: 'Log do Sistema'
CutWebsiteLog: 'Rotacionar Log do Website' CutWebsiteLog: 'Rotacionar Log do Website'
FileOrDir: 'Diretório / Arquivo' FileOrDir: 'Diretório / Arquivo'
UploadFile: 'Enviando arquivo de backup {{ .file }} para {{ .backup }}' UploadFile: 'Enviando arquivo de backup {{ .file }} para {{ .backup }}'
IgnoreBackupErr: 'Backup falhou, erro: {{ .detail }}, ignorando este erro...'
IgnoreUploadErr: 'Upload falhou, erro: {{ .detail }}, ignorando este erro...'
#caixa de ferramentas #caixa de ferramentas
ErrNotExistUser: 'O usuário atual não existe, modifique e tente novamente!' ErrNotExistUser: 'O usuário atual não existe, modifique e tente novamente!'
@@ -333,7 +335,8 @@ SnapDeleteLoginLog: 'Excluir log de acesso'
SnapDeleteMonitor: 'Excluir dados de monitoramento' SnapDeleteMonitor: 'Excluir dados de monitoramento'
SnapRemoveSystemIP: 'Remover IP do sistema' SnapRemoveSystemIP: 'Remover IP do sistema'
SnapBaseInfo: 'Escreva informações básicas do 1Panel' SnapBaseInfo: 'Escreva informações básicas do 1Panel'
SnapInstallApp: 'Fazer backup dos aplicativos instalados do 1Panel' SnapInstallAppImageEmpty: 'Nenhuma imagem de aplicativo selecionada, pulando...'
SnapInstallApp: 'Backup dos aplicativos instalados do 1Panel'
SnapDockerSave: 'Compactar aplicativos instalados' SnapDockerSave: 'Compactar aplicativos instalados'
SnapLocalBackup: 'Backup do diretório de backup local do 1Panel' SnapLocalBackup: 'Backup do diretório de backup local do 1Panel'
SnapCompressBackup: 'Compactar diretório de backup local' SnapCompressBackup: 'Compactar diretório de backup local'
+4 -1
View File
@@ -205,6 +205,8 @@ SystemLog: 'Системный лог'
CutWebsiteLog: 'Ротация логов сайта' CutWebsiteLog: 'Ротация логов сайта'
FileOrDir: 'Каталог / Файл' FileOrDir: 'Каталог / Файл'
UploadFile: 'Загрузка файла резервной копии {{ .file }} в {{ .backup }}' UploadFile: 'Загрузка файла резервной копии {{ .file }} в {{ .backup }}'
IgnoreBackupErr: 'Ошибка резервного копирования: {{ .detail }}, игнорируем эту ошибку...'
IgnoreUploadErr: 'Ошибка загрузки: {{ .detail }}, игнорируем эту ошибку...'
#ящик для инструментов #ящик для инструментов
ErrNotExistUser: 'Текущий пользователь не существует, измените его и повторите попытку!' ErrNotExistUser: 'Текущий пользователь не существует, измените его и повторите попытку!'
@@ -333,7 +335,8 @@ SnapDeleteLoginLog: 'Удалить журнал доступа'
SnapDeleteMonitor: 'Удалить данные мониторинга' SnapDeleteMonitor: 'Удалить данные мониторинга'
SnapRemoveSystemIP: 'Удалить системный IP' SnapRemoveSystemIP: 'Удалить системный IP'
SnapBaseInfo: 'Записать основную информацию 1Panel' SnapBaseInfo: 'Записать основную информацию 1Panel'
SnapInstallApp: 'Резервное копирование установленных приложений 1Panel' SnapInstallAppImageEmpty: 'Образы приложений не выбраны, пропускаем...'
SnapInstallApp: 'Резервное копирование приложений, установленных в 1Panel'
SnapDockerSave: 'Сжать установленные приложения' SnapDockerSave: 'Сжать установленные приложения'
SnapLocalBackup: 'Резервное копирование локального каталога резервных копий 1Panel' SnapLocalBackup: 'Резервное копирование локального каталога резервных копий 1Panel'
SnapCompressBackup: 'Сжать локальный каталог резервных копий' SnapCompressBackup: 'Сжать локальный каталог резервных копий'
+4 -1
View File
@@ -204,6 +204,8 @@ SystemLog: '系統日誌'
CutWebsiteLog: '切割網站日誌' CutWebsiteLog: '切割網站日誌'
FileOrDir: '目錄 / 檔案' FileOrDir: '目錄 / 檔案'
UploadFile: '上傳備份文件 {{ .file }} 到 {{ .backup }}' UploadFile: '上傳備份文件 {{ .file }} 到 {{ .backup }}'
IgnoreBackupErr: '備份失敗,錯誤:{{ .detail }},忽略本次錯誤...'
IgnoreUploadErr: '上傳失敗,錯誤:{{ .detail }},忽略本次錯誤...'
#toolbox #toolbox
ErrNotExistUser: '目前使用者不存在,請修改後重試!' ErrNotExistUser: '目前使用者不存在,請修改後重試!'
@@ -332,7 +334,8 @@ SnapDeleteLoginLog: '刪除存取日誌'
SnapDeleteMonitor: '刪除監控資料' SnapDeleteMonitor: '刪除監控資料'
SnapRemoveSystemIP: '移除系統IP' SnapRemoveSystemIP: '移除系統IP'
SnapBaseInfo: '寫入1Panel 基本資料' SnapBaseInfo: '寫入1Panel 基本資料'
SnapInstallApp: '備份1Panel 已安裝應用程式' SnapInstallAppImageEmpty: '當前未勾選應用鏡像,跳過...'
SnapInstallApp: '備份 1Panel 已安裝應用'
SnapDockerSave: '壓縮已安裝應用' SnapDockerSave: '壓縮已安裝應用'
SnapLocalBackup: '備份1Panel 本機備份目錄' SnapLocalBackup: '備份1Panel 本機備份目錄'
SnapCompressBackup: '壓縮本機備份目錄' SnapCompressBackup: '壓縮本機備份目錄'
+3
View File
@@ -204,6 +204,8 @@ SystemLog: "系统日志"
CutWebsiteLog: "切割网站日志" CutWebsiteLog: "切割网站日志"
FileOrDir: "目录 / 文件" FileOrDir: "目录 / 文件"
UploadFile: "上传备份文件 {{ .file }} 到 {{ .backup }}" UploadFile: "上传备份文件 {{ .file }} 到 {{ .backup }}"
IgnoreBackupErr: "备份失败,错误:{{ .detail }},忽略本次错误..."
IgnoreUploadErr: "上传失败,错误:{{ .detail }},忽略本次错误..."
#toolbox #toolbox
ErrNotExistUser: "当前用户不存在,请修改后重试!" ErrNotExistUser: "当前用户不存在,请修改后重试!"
@@ -332,6 +334,7 @@ SnapDeleteLoginLog: "删除访问日志"
SnapDeleteMonitor: "删除监控数据" SnapDeleteMonitor: "删除监控数据"
SnapRemoveSystemIP: "移除系统 IP" SnapRemoveSystemIP: "移除系统 IP"
SnapBaseInfo: "写入 1Panel 基本信息" SnapBaseInfo: "写入 1Panel 基本信息"
SnapInstallAppImageEmpty: "当前未勾选应用镜像,跳过..."
SnapInstallApp: "备份 1Panel 已安装应用" SnapInstallApp: "备份 1Panel 已安装应用"
SnapDockerSave: "压缩已安装应用" SnapDockerSave: "压缩已安装应用"
SnapLocalBackup: "备份 1Panel 本地备份目录" SnapLocalBackup: "备份 1Panel 本地备份目录"
+16 -5
View File
@@ -2,12 +2,14 @@ package hook
import ( import (
"os" "os"
"strings"
"github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/model" "github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/app/repo" "github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/constant" "github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global" "github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/xpack" "github.com/1Panel-dev/1Panel/agent/utils/xpack"
) )
@@ -18,6 +20,8 @@ func Init() {
handleOllamaModelStatus() handleOllamaModelStatus()
loadLocalDir() loadLocalDir()
initDockerConf()
} }
func initGlobalData() { func initGlobalData() {
@@ -92,11 +96,7 @@ func handleCronJobAlert(cronjob *model.Cronjob) {
EntryID: cronjob.ID, EntryID: cronjob.ID,
Param: cronjob.Type, Param: cronjob.Type,
} }
err := xpack.PushAlert(pushAlert) _ = xpack.PushAlert(pushAlert)
if err != nil {
global.LOG.Errorf("cronjob alert push failed, err: %v", err)
return
}
} }
func loadLocalDir() { func loadLocalDir() {
@@ -113,3 +113,14 @@ func loadLocalDir() {
} }
} }
} }
func initDockerConf() {
stdout, err := cmd.RunDefaultWithStdoutBashC("which docker")
if err != nil {
return
}
dockerPath := stdout
if strings.Contains(dockerPath, "snap") {
constant.DaemonJsonPath = "/var/snap/docker/current/config/daemon.json"
}
}
+5
View File
@@ -24,6 +24,11 @@ func InitAgentDB() {
migrations.InitBackup, migrations.InitBackup,
migrations.InitDefault, migrations.InitDefault,
migrations.UpdateWebsiteExpireDate, migrations.UpdateWebsiteExpireDate,
migrations.UpdateRuntime,
migrations.AddSnapshotRule,
migrations.UpdatePHPRuntime,
migrations.AddSnapshotIgnore,
migrations.InitAppLauncher,
}) })
if err := m.Migrate(); err != nil { if err := m.Migrate(); err != nil {
global.LOG.Error(err) global.LOG.Error(err)
+49 -3
View File
@@ -185,9 +185,6 @@ var InitSetting = &gormigrate.Migration{
if err := tx.Create(&model.Setting{Key: "FileRecycleBin", Value: constant.StatusEnable}).Error; err != nil { if err := tx.Create(&model.Setting{Key: "FileRecycleBin", Value: constant.StatusEnable}).Error; err != nil {
return err return err
} }
if err := tx.Create(&model.Setting{Key: "SnapshotIgnore", Value: "*.sock"}).Error; err != nil {
return err
}
if err := tx.Create(&model.Setting{Key: "LocalSSHConn", Value: ""}).Error; err != nil { if err := tx.Create(&model.Setting{Key: "LocalSSHConn", Value: ""}).Error; err != nil {
return err return err
@@ -314,3 +311,52 @@ var UpdateWebsiteExpireDate = &gormigrate.Migration{
return nil return nil
}, },
} }
var UpdateRuntime = &gormigrate.Migration{
ID: "20250624-update-runtime",
Migrate: func(tx *gorm.DB) error {
return tx.AutoMigrate(
&model.Runtime{},
)
},
}
var AddSnapshotRule = &gormigrate.Migration{
ID: "20250703-add-snapshot-rule",
Migrate: func(tx *gorm.DB) error {
return tx.AutoMigrate(
&model.Cronjob{},
)
},
}
var UpdatePHPRuntime = &gormigrate.Migration{
ID: "20250702-update-php-runtime",
Migrate: func(tx *gorm.DB) error {
service.HandleOldPHPRuntime()
return nil
},
}
var AddSnapshotIgnore = &gormigrate.Migration{
ID: "20250628-add-snapshot-ignore",
Migrate: func(tx *gorm.DB) error {
return tx.AutoMigrate(
&model.Snapshot{},
)
},
}
var InitAppLauncher = &gormigrate.Migration{
ID: "20250702-init-app-launcher",
Migrate: func(tx *gorm.DB) error {
launchers := []string{"openresty", "mysql", "halo", "redis", "maxkb", "wordpress"}
for _, val := range launchers {
var item model.AppLauncher
_ = tx.Model(&model.AppLauncher{}).Where("key = ?", val).First(&item).Error
if item.ID == 0 {
item.Key = val
_ = tx.Create(&item).Error
}
}
return nil
},
}
+2
View File
@@ -48,5 +48,7 @@ func (r *RuntimeRouter) InitRouter(Router *gin.RouterGroup) {
groupRouter.GET("/supervisor/process/:id", baseApi.GetSupervisorProcess) groupRouter.GET("/supervisor/process/:id", baseApi.GetSupervisorProcess)
groupRouter.POST("/supervisor/process", baseApi.OperateSupervisorProcess) groupRouter.POST("/supervisor/process", baseApi.OperateSupervisorProcess)
groupRouter.POST("/supervisor/process/file", baseApi.OperateSupervisorProcessFile) groupRouter.POST("/supervisor/process/file", baseApi.OperateSupervisorProcessFile)
groupRouter.POST("/remark", baseApi.UpdateRuntimeRemark)
} }
} }
@@ -57,11 +57,9 @@ func (g *googleDriveClient) Delete(pathItem string) (bool, error) {
if len(fileInfo.ID) == 0 { if len(fileInfo.ID) == 0 {
return false, fmt.Errorf("no such file %s", pathItem) return false, fmt.Errorf("no such file %s", pathItem)
} }
res, err := g.googleRequest("https://www.googleapis.com/drive/v3/files/"+fileInfo.ID, http.MethodDelete, nil, nil) if _, err = g.googleRequest("https://www.googleapis.com/drive/v3/files/"+fileInfo.ID, http.MethodDelete, nil, nil); err != nil {
if err != nil {
return false, err return false, err
} }
fmt.Println(string(res))
return true, nil return true, nil
} }
@@ -99,14 +97,51 @@ func (g *googleDriveClient) Upload(src, target string) (bool, error) {
return false, err return false, err
} }
uploadUrl := resp.Header().Get("location") uploadUrl := resp.Header().Get("location")
if _, err := g.googleRequest(uploadUrl, http.MethodPut, func(req *resty.Request) {
req.SetHeader("Content-Length", strconv.FormatInt(fileInfo.Size(), 10)).SetBody(file) buf := make([]byte, 5*1024*1024)
}, nil); err != nil { var offset int64 = 0
return false, err for {
n, err := file.Read(buf)
if err != nil && err != io.EOF {
return false, fmt.Errorf("read file failed, err: %v", err)
}
if n == 0 {
break
}
chunk := buf[:n]
start := offset
end := offset + int64(n) - 1
if err = uploadChunk(client, uploadUrl, chunk, start, end, fileInfo.Size()); err != nil {
return false, err
}
offset += int64(n)
if err == io.EOF {
break
}
} }
return true, nil return true, nil
} }
func uploadChunk(client *resty.Client, uploadURL string, chunk []byte, start, end, total int64) error {
contentRange := fmt.Sprintf("bytes %d-%d/%d", start, end, total)
resp, err := client.R().
SetHeader("Content-Length", strconv.Itoa(len(chunk))).
SetHeader("Content-Range", contentRange).
SetBody(chunk).
Put(uploadURL)
if err != nil {
return fmt.Errorf("new request for upload chunk failed: %v", err)
}
if resp.StatusCode() != 200 && resp.StatusCode() != 308 {
return fmt.Errorf("upload chunk failed: %s, %s", resp.Status(), string(resp.Body()))
}
return nil
}
func (g *googleDriveClient) Download(src, target string) (bool, error) { func (g *googleDriveClient) Download(src, target string) (bool, error) {
src = path.Join("/root", src) src = path.Join("/root", src)
fileInfo, err := g.loadFileWithName(src) fileInfo, err := g.loadFileWithName(src)
+28 -18
View File
@@ -9,6 +9,7 @@ import (
"os" "os"
"os/exec" "os/exec"
"strings" "strings"
"syscall"
"time" "time"
"github.com/1Panel-dev/1Panel/agent/app/task" "github.com/1Panel-dev/1Panel/agent/app/task"
@@ -17,12 +18,13 @@ import (
) )
type CommandHelper struct { type CommandHelper struct {
workDir string workDir string
outputFile string outputFile string
scriptPath string scriptPath string
timeout time.Duration timeout time.Duration
taskItem *task.Task taskItem *task.Task
logger *log.Logger logger *log.Logger
IgnoreExist1 bool
} }
type Option func(*CommandHelper) type Option func(*CommandHelper)
@@ -65,6 +67,7 @@ func (c *CommandHelper) RunBashCWithArgs(arg ...string) error {
_, err := c.run("bash", arg...) _, err := c.run("bash", arg...)
return err return err
} }
func (c *CommandHelper) RunBashC(command string) error { func (c *CommandHelper) RunBashC(command string) error {
std, err := c.run("bash", "-c", command) std, err := c.run("bash", "-c", command)
if err != nil { if err != nil {
@@ -133,23 +136,17 @@ func (c *CommandHelper) run(name string, arg ...string) (string, error) {
cmd.Dir = c.workDir cmd.Dir = c.workDir
} }
err := cmd.Run()
if c.taskItem != nil {
customWriter.Flush()
}
if c.timeout != 0 { if c.timeout != 0 {
err := cmd.Run()
if c.taskItem != nil {
customWriter.Flush()
}
if ctx != nil && errors.Is(ctx.Err(), context.DeadlineExceeded) { if ctx != nil && errors.Is(ctx.Err(), context.DeadlineExceeded) {
return "", buserr.New("ErrCmdTimeout") return "", buserr.New("ErrCmdTimeout")
} }
if err != nil {
return handleErr(stdout, stderr, err)
}
return stdout.String(), nil
} }
err := cmd.Run()
if err != nil { if err != nil {
return handleErr(stdout, stderr, err) return handleErr(stdout, stderr, c.IgnoreExist1, err)
} }
return stdout.String(), nil return stdout.String(), nil
} }
@@ -184,6 +181,11 @@ func WithScriptPath(scriptPath string) Option {
s.scriptPath = scriptPath s.scriptPath = scriptPath
} }
} }
func WithIgnoreExist1() Option {
return func(s *CommandHelper) {
s.IgnoreExist1 = true
}
}
type CustomWriter struct { type CustomWriter struct {
taskItem *task.Task taskItem *task.Task
@@ -209,7 +211,15 @@ func (cw *CustomWriter) Flush() {
} }
} }
func handleErr(stdout, stderr bytes.Buffer, err error) (string, error) { func handleErr(stdout, stderr bytes.Buffer, ignoreExist1 bool, err error) (string, error) {
var exitError *exec.ExitError
if ignoreExist1 && errors.As(err, &exitError) {
if status, ok := exitError.Sys().(syscall.WaitStatus); ok {
if status.ExitStatus() == 1 {
return "", nil
}
}
}
errMsg := "" errMsg := ""
if len(stderr.String()) != 0 { if len(stderr.String()) != 0 {
errMsg = fmt.Sprintf("stderr: %s", stderr.String()) errMsg = fmt.Sprintf("stderr: %s", stderr.String())
+31 -27
View File
@@ -329,25 +329,30 @@ func (f FileOp) DownloadFile(url, dst string) error {
} }
func (f FileOp) Cut(oldPaths []string, dst, name string, cover bool) error { func (f FileOp) Cut(oldPaths []string, dst, name string, cover bool) error {
for _, p := range oldPaths { if len(oldPaths) == 0 {
var dstPath string return nil
if name != "" { }
dstPath = filepath.Join(dst, name) var dstPath string
if f.Stat(dstPath) { coverFlag := ""
dstPath = dst if name != "" {
} dstPath = filepath.Join(dst, name)
} else { if f.Stat(dstPath) {
base := filepath.Base(p) dstPath = dst
dstPath = filepath.Join(dst, base)
} }
coverFlag := ""
if cover { if cover {
coverFlag = "-f" coverFlag = "-f"
} }
} else {
if err := cmd.RunDefaultBashCf(`mv %s '%s' '%s'`, coverFlag, p, dstPath); err != nil { dstPath = dst
return err coverFlag = "-f"
} }
var quotedPaths []string
for _, p := range oldPaths {
quotedPaths = append(quotedPaths, fmt.Sprintf("'%s'", p))
}
mvCommand := fmt.Sprintf("mv %s %s '%s'", coverFlag, strings.Join(quotedPaths, " "), dstPath)
if err := cmd.RunDefaultBashCf(mvCommand); err != nil {
return err
} }
return nil return nil
} }
@@ -810,6 +815,9 @@ func (f FileOp) TarGzCompressPro(withDir bool, src, dst, secret, exclusionRules
if len(exclude) == 0 { if len(exclude) == 0 {
continue continue
} }
if strings.HasPrefix(exclude, "/") {
exclude, _ = filepath.Rel(src, exclude)
}
if _, ok := exMap[exclude]; ok { if _, ok := exMap[exclude]; ok {
continue continue
} }
@@ -817,19 +825,14 @@ func (f FileOp) TarGzCompressPro(withDir bool, src, dst, secret, exclusionRules
exMap[exclude] = struct{}{} exMap[exclude] = struct{}{}
} }
itemPrefix := filepath.Base(src)
if itemPrefix == "/" {
itemPrefix = ""
}
if len(secret) != 0 { if len(secret) != 0 {
commands = fmt.Sprintf("tar --warning=no-file-changed --ignore-failed-read %s --exclude-from=<(find %s -type s -printf '%s' | sed 's|^|%s/|') -zcf - %s | openssl enc -aes-256-cbc -salt -k '%s' -out %s", exStr, src, "%P\n", itemPrefix, srcItem, secret, dst) commands = fmt.Sprintf("tar %s -zcf - %s | openssl enc -aes-256-cbc -salt -k '%s' -out %s", exStr, srcItem, secret, dst)
global.LOG.Debug(strings.ReplaceAll(commands, fmt.Sprintf(" %s ", secret), "******")) global.LOG.Debug(strings.ReplaceAll(commands, fmt.Sprintf(" %s ", secret), "******"))
} else { } else {
commands = fmt.Sprintf("tar --warning=no-file-changed --ignore-failed-read --exclude-from=<(find %s -type s -printf '%s' | sed 's|^|%s/|') -zcf %s %s %s", src, "%P\n", itemPrefix, dst, exStr, srcItem) commands = fmt.Sprintf("tar -zcf %s %s %s", dst, exStr, srcItem)
global.LOG.Debug(commands) global.LOG.Debug(commands)
} }
cmdMgr := cmd.NewCommandMgr(cmd.WithWorkDir(workdir), cmd.WithIgnoreExist1())
cmdMgr := cmd.NewCommandMgr(cmd.WithWorkDir(workdir))
return cmdMgr.RunBashC(commands) return cmdMgr.RunBashC(commands)
} }
@@ -846,13 +849,14 @@ func (f FileOp) TarGzFilesWithCompressPro(list []string, dst, secret string) err
} }
commands := "" commands := ""
if len(secret) != 0 { if len(secret) != 0 {
commands = fmt.Sprintf("tar --warning=no-file-changed --ignore-failed-read -zcf - %s | openssl enc -aes-256-cbc -salt -k '%s' -out %s", strings.Join(filelist, " "), secret, dst) commands = fmt.Sprintf("tar -zcf - %s | openssl enc -aes-256-cbc -salt -k '%s' -out %s", strings.Join(filelist, " "), secret, dst)
global.LOG.Debug(strings.ReplaceAll(commands, fmt.Sprintf(" %s ", secret), "******")) global.LOG.Debug(strings.ReplaceAll(commands, fmt.Sprintf(" %s ", secret), "******"))
} else { } else {
commands = fmt.Sprintf("tar --warning=no-file-changed --ignore-failed-read -zcf %s %s", dst, strings.Join(filelist, " ")) commands = fmt.Sprintf("tar -zcf %s %s", dst, strings.Join(filelist, " "))
global.LOG.Debug(commands) global.LOG.Debug(commands)
} }
return cmd.RunDefaultBashC(commands) cmdMgr := cmd.NewCommandMgr(cmd.WithIgnoreExist1())
return cmdMgr.RunBashC(commands)
} }
func (f FileOp) TarGzExtractPro(src, dst string, secret string) error { func (f FileOp) TarGzExtractPro(src, dst string, secret string) error {
@@ -870,7 +874,7 @@ func (f FileOp) TarGzExtractPro(src, dst string, secret string) error {
commands = fmt.Sprintf("tar zxvf %s", src) commands = fmt.Sprintf("tar zxvf %s", src)
global.LOG.Debug(commands) global.LOG.Debug(commands)
} }
cmdMgr := cmd.NewCommandMgr(cmd.WithWorkDir(dst)) cmdMgr := cmd.NewCommandMgr(cmd.WithWorkDir(dst), cmd.WithIgnoreExist1())
return cmdMgr.RunBashC(commands) return cmdMgr.RunBashC(commands)
} }
func CopyCustomAppFile(srcPath, dstPath string) error { func CopyCustomAppFile(srcPath, dstPath string) error {
+72
View File
@@ -7,6 +7,13 @@ import (
"github.com/1Panel-dev/1Panel/agent/buserr" "github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/constant" "github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/utils/req_helper" "github.com/1Panel-dev/1Panel/agent/utils/req_helper"
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/charmap"
"golang.org/x/text/encoding/japanese"
"golang.org/x/text/encoding/korean"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/encoding/traditionalchinese"
"golang.org/x/text/encoding/unicode"
"io" "io"
"net/http" "net/http"
"os" "os"
@@ -201,3 +208,68 @@ func DownloadFileWithProxy(url, dst string) error {
} }
return nil return nil
} }
func GetDecoderByName(name string) encoding.Encoding {
switch strings.ToLower(name) {
case "gbk":
return simplifiedchinese.GBK
case "gb18030":
return simplifiedchinese.GB18030
case "big5":
return traditionalchinese.Big5
case "euc-jp":
return japanese.EUCJP
case "iso-2022-jp":
return japanese.ISO2022JP
case "shift_jis":
return japanese.ShiftJIS
case "euc-kr":
return korean.EUCKR
case "utf-16be":
return unicode.UTF16(unicode.BigEndian, unicode.ExpectBOM)
case "utf-16le":
return unicode.UTF16(unicode.LittleEndian, unicode.ExpectBOM)
case "windows-1250":
return charmap.Windows1250
case "windows-1251":
return charmap.Windows1251
case "windows-1252":
return charmap.Windows1252
case "windows-1253":
return charmap.Windows1253
case "windows-1254":
return charmap.Windows1254
case "windows-1255":
return charmap.Windows1255
case "windows-1256":
return charmap.Windows1256
case "windows-1257":
return charmap.Windows1257
case "windows-1258":
return charmap.Windows1258
case "iso-8859-1":
return charmap.ISO8859_1
case "iso-8859-2":
return charmap.ISO8859_2
case "iso-8859-3":
return charmap.ISO8859_3
case "iso-8859-4":
return charmap.ISO8859_4
case "iso-8859-5":
return charmap.ISO8859_5
case "iso-8859-6":
return charmap.ISO8859_6
case "iso-8859-7":
return charmap.ISO8859_7
case "iso-8859-8":
return charmap.ISO8859_8
case "iso-8859-9":
return charmap.ISO8859_9
case "iso-8859-13":
return charmap.ISO8859_13
case "iso-8859-15":
return charmap.ISO8859_15
default:
return encoding.Nop
}
}
+14 -8
View File
@@ -3,7 +3,6 @@ package v2
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"path"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@@ -185,26 +184,33 @@ func (b *BaseApi) RunScript(c *gin.Context) {
tty.Start(quitChan) tty.Start(quitChan)
go slave.Wait(quitChan) go slave.Wait(quitChan)
} else { } else {
connInfo, installDir, err := xpack.LoadNodeInfo(currentNode) connInfo, _, err := xpack.LoadNodeInfo(currentNode)
if wshandleError(wsConn, errors.WithMessage(err, "invalid param rows in request")) { if wshandleError(wsConn, errors.WithMessage(err, "invalid param rows in request")) {
return return
} }
fileDir := path.Join(installDir, "1panel/tmp/script")
fileName := "" fileName := ""
var translations = make(map[string]string) var translations = make(map[string]string)
_ = json.Unmarshal([]byte(scriptItem.Name), &translations) _ = json.Unmarshal([]byte(scriptItem.Name), &translations)
if name, ok := translations["en"]; ok { if name, ok := translations["en"]; ok {
fileName = path.Join(fileDir, strings.ReplaceAll(name, " ", "_")) fileName = strings.ReplaceAll(name, " ", "_")
} else { } else {
fileName = path.Join(fileDir, strings.ReplaceAll(scriptItem.Name, " ", "_")) fileName = strings.ReplaceAll(scriptItem.Name, " ", "_")
} }
initCmd := fmt.Sprintf("mkdir -p %s && cat > %s <<'MYMARKER'\n%s\nMYMARKER\n bash %s", fileDir, fileName, scriptItem.Script, fileName)
client, err := ssh.NewClient(*connInfo) client, err := ssh.NewClient(*connInfo)
if wshandleError(wsConn, errors.WithMessage(err, "failed to set up the connection. Please check the host information")) { if wshandleError(wsConn, errors.WithMessage(err, "set up the connection failed. Please check the host information")) {
return return
} }
defer client.Close() sudoItem := client.SudoHandleCmd()
defer func() {
_, _ = client.Runf("%s rm -rf %s", sudoItem, fileName)
client.Close()
}()
std, err := client.Runf("%s touch %s && %s chmod 777 %s && %s cat > %s <<'MYMARKER'\n%s\nMYMARKER\n", sudoItem, fileName, sudoItem, fileName, sudoItem, fileName, scriptItem.Script)
if wshandleError(wsConn, errors.WithMessage(err, fmt.Sprintf("touch script file failed, err: %s. Please check and retry", std))) {
return
}
initCmd := fmt.Sprintf("%s bash %s", sudoItem, fileName)
sws, err := terminal.NewLogicSshWsSession(cols, rows, client.Client, wsConn, initCmd) sws, err := terminal.NewLogicSshWsSession(cols, rows, client.Client, wsConn, initCmd)
if wshandleError(wsConn, err) { if wshandleError(wsConn, err) {
+7
View File
@@ -16,6 +16,7 @@ type IUpgradeLogRepo interface {
Delete(opts ...global.DBOption) error Delete(opts ...global.DBOption) error
WithByNodeID(nodeID uint) global.DBOption WithByNodeID(nodeID uint) global.DBOption
WithByUpgradeVersion(oldVersion, newVersion string) global.DBOption
} }
func NewIUpgradeLogRepo() IUpgradeLogRepo { func NewIUpgradeLogRepo() IUpgradeLogRepo {
@@ -79,3 +80,9 @@ func (c *UpgradeLogRepo) WithByNodeID(nodeID uint) global.DBOption {
return g.Where("node_id = ?", nodeID) return g.Where("node_id = ?", nodeID)
} }
} }
func (c *UpgradeLogRepo) WithByUpgradeVersion(oldVersion, newVersion string) global.DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("old_version = ? AND new_version = ?", oldVersion, newVersion)
}
}
-2
View File
@@ -268,8 +268,6 @@ func (u *BackupService) RefreshToken(req dto.OperateByName) error {
switch backup.Type { switch backup.Type {
case constant.OneDrive: case constant.OneDrive:
refreshToken, err = client.RefreshToken("refresh_token", "refreshToken", varMap) refreshToken, err = client.RefreshToken("refresh_token", "refreshToken", varMap)
case constant.GoogleDrive:
refreshToken, err = client.RefreshGoogleToken("refresh_token", "refreshToken", varMap)
case constant.ALIYUN: case constant.ALIYUN:
refreshToken, err = client.RefreshALIToken(varMap) refreshToken, err = client.RefreshALIToken(varMap)
} }
+6
View File
@@ -87,6 +87,12 @@ var restoreCmd = &cobra.Command{
fmt.Println(i18n.GetMsgByKeyForCmd("RestoreStep5")) fmt.Println(i18n.GetMsgByKeyForCmd("RestoreStep5"))
fmt.Println(i18n.GetMsgByKeyForCmd("RestoreSuccessful")) fmt.Println(i18n.GetMsgByKeyForCmd("RestoreSuccessful"))
_, _ = cmdUtils.RunDefaultWithStdoutBashC("systemctl daemon-reload")
std, err := cmdUtils.RunDefaultWithStdoutBashC("1pctl restart all")
if err != nil {
fmt.Println(std)
}
return nil return nil
}, },
} }
+142 -94
View File
@@ -97,6 +97,13 @@
"formatZH": "同步Ollama模型列表", "formatZH": "同步Ollama模型列表",
"formatEN": "syncOllamamodellist" "formatEN": "syncOllamamodellist"
}, },
"/apps/ignored/cancel": {
"bodyKeys": [],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "取消忽略应用升级",
"formatEN": "Cancelignoreapplicationupgrade"
},
"/apps/install": { "/apps/install": {
"bodyKeys": [ "bodyKeys": [
"name" "name"
@@ -117,13 +124,11 @@
"formatEN": "Applicationconfigupdate[installID]" "formatEN": "Applicationconfigupdate[installID]"
}, },
"/apps/installed/ignore": { "/apps/installed/ignore": {
"bodyKeys": [ "bodyKeys": [],
"installId"
],
"paramKeys": [], "paramKeys": [],
"beforeFunctions": [], "beforeFunctions": [],
"formatZH": "忽略应用[installId]版本升级", "formatZH": "忽略应用升级",
"formatEN": "Applicationparamupdate[installId]" "formatEN": "Ignoreapplicationupgrade"
}, },
"/apps/installed/op": { "/apps/installed/op": {
"bodyKeys": [ "bodyKeys": [
@@ -649,16 +654,6 @@
"formatZH": "删除容器存储卷[names]", "formatZH": "删除容器存储卷[names]",
"formatEN": "deletecontainervolume[names]" "formatEN": "deletecontainervolume[names]"
}, },
"/core/app/launcher/show": {
"bodyKeys": [
"key",
"value"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "首页应用[key]=\u003e显示:[value]",
"formatEN": "applauncher[key]=\u003eshow:[value]"
},
"/core/backups": { "/core/backups": {
"bodyKeys": [ "bodyKeys": [
"type" "type"
@@ -840,6 +835,13 @@
"formatZH": "绑定许可证", "formatZH": "绑定许可证",
"formatEN": "bindlicense" "formatEN": "bindlicense"
}, },
"/core/licenses/bind/free": {
"bodyKeys": [],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "修改许可证免费节点绑定",
"formatEN": "changebindoffreenodeforlicense"
},
"/core/licenses/del": { "/core/licenses/del": {
"bodyKeys": [], "bodyKeys": [],
"paramKeys": [], "paramKeys": [],
@@ -1232,6 +1234,16 @@
"formatZH": "更新计划任务[name]", "formatZH": "更新计划任务[name]",
"formatEN": "updatecronjob[name]" "formatEN": "updatecronjob[name]"
}, },
"/dashboard/app/launcher/show": {
"bodyKeys": [
"key",
"value"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "首页应用[key]=\u003e显示:[value]",
"formatEN": "applauncher[key]=\u003eshow:[value]"
},
"/databases": { "/databases": {
"bodyKeys": [ "bodyKeys": [
"name" "name"
@@ -1568,6 +1580,15 @@
"formatZH": "删除文件/文件夹[path]", "formatZH": "删除文件/文件夹[path]",
"formatEN": "Deletedirorfile[path]" "formatEN": "Deletedirorfile[path]"
}, },
"/files/depth/size": {
"bodyKeys": [
"path"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "获取目录及其第一层子目录文件夹大小[path]",
"formatEN": "Multifilesize[path]"
},
"/files/favorite": { "/files/favorite": {
"bodyKeys": [ "bodyKeys": [
"path" "path"
@@ -1672,12 +1693,13 @@
}, },
"/files/upload": { "/files/upload": {
"bodyKeys": [ "bodyKeys": [
"path" "path",
"file"
], ],
"paramKeys": [], "paramKeys": [],
"beforeFunctions": [], "beforeFunctions": [],
"formatZH": "上传文件[path]", "formatZH": "上传文件[path]/[file]",
"formatEN": "Uploadfile[path]" "formatEN": "Uploadfile[path]/[file]"
}, },
"/files/wget": { "/files/wget": {
"bodyKeys": [ "bodyKeys": [
@@ -1690,85 +1712,13 @@
"formatZH": "下载url=\u003e[path]/[name]", "formatZH": "下载url=\u003e[path]/[name]",
"formatEN": "Downloadurl=\u003e[path]/[name]" "formatEN": "Downloadurl=\u003e[path]/[name]"
}, },
"/host/conffile/update": { "/hosts/conffile/update": {
"bodyKeys": [], "bodyKeys": [],
"paramKeys": [], "paramKeys": [],
"beforeFunctions": [], "beforeFunctions": [],
"formatZH": "修改SSH配置文件", "formatZH": "修改SSH配置文件",
"formatEN": "updateSSHconf" "formatEN": "updateSSHconf"
}, },
"/host/ssh/generate": {
"bodyKeys": [],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "生成SSH密钥",
"formatEN": "generateSSHsecret"
},
"/host/ssh/operate": {
"bodyKeys": [
"operation"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "[operation]SSH",
"formatEN": "[operation]SSH"
},
"/host/ssh/update": {
"bodyKeys": [
"key",
"value"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "修改SSH配置[key]=\u003e[value]",
"formatEN": "updateSSHsetting[key]=\u003e[value]"
},
"/host/tool/config": {
"bodyKeys": [
"operate"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "[operate]主机工具配置文件",
"formatEN": "[operate]toolconfig"
},
"/host/tool/create": {
"bodyKeys": [
"type"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "创建[type]配置",
"formatEN": "create[type]config"
},
"/host/tool/operate": {
"bodyKeys": [
"operate",
"type"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "[operate][type]",
"formatEN": "[operate][type]"
},
"/host/tool/supervisor/process": {
"bodyKeys": [
"operate"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "[operate]守护进程",
"formatEN": "[operate]process"
},
"/host/tool/supervisor/process/file": {
"bodyKeys": [
"operate"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "[operate]Supervisor进程文件",
"formatEN": "[operate]SupervisorProcessConfigfile"
},
"/hosts/firewall/forward": { "/hosts/firewall/forward": {
"bodyKeys": [ "bodyKeys": [
"source_port" "source_port"
@@ -1824,6 +1774,78 @@
"formatZH": "修改默认监控网卡[name]-[value]", "formatZH": "修改默认监控网卡[name]-[value]",
"formatEN": "updatedefaultmonitor[name]-[value]" "formatEN": "updatedefaultmonitor[name]-[value]"
}, },
"/hosts/ssh/generate": {
"bodyKeys": [],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "生成SSH密钥",
"formatEN": "generateSSHsecret"
},
"/hosts/ssh/operate": {
"bodyKeys": [
"operation"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "[operation]SSH",
"formatEN": "[operation]SSH"
},
"/hosts/ssh/update": {
"bodyKeys": [
"key",
"value"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "修改SSH配置[key]=\u003e[value]",
"formatEN": "updateSSHsetting[key]=\u003e[value]"
},
"/hosts/tool/config": {
"bodyKeys": [
"operate"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "[operate]主机工具配置文件",
"formatEN": "[operate]toolconfig"
},
"/hosts/tool/create": {
"bodyKeys": [
"type"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "创建[type]配置",
"formatEN": "create[type]config"
},
"/hosts/tool/operate": {
"bodyKeys": [
"operate",
"type"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "[operate][type]",
"formatEN": "[operate][type]"
},
"/hosts/tool/supervisor/process": {
"bodyKeys": [
"operate"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "[operate]守护进程",
"formatEN": "[operate]process"
},
"/hosts/tool/supervisor/process/file": {
"bodyKeys": [
"operate"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "[operate]Supervisor进程文件",
"formatEN": "[operate]SupervisorProcessConfigfile"
},
"/openresty/build": { "/openresty/build": {
"bodyKeys": [], "bodyKeys": [],
"paramKeys": [], "paramKeys": [],
@@ -1989,6 +2011,13 @@
"formatZH": "删除脚本库脚本[names]", "formatZH": "删除脚本库脚本[names]",
"formatEN": "deletescript[names]" "formatEN": "deletescript[names]"
}, },
"/script/sync": {
"bodyKeys": [],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "同步脚本库脚本",
"formatEN": "syncscripts"
},
"/script/update": { "/script/update": {
"bodyKeys": [ "bodyKeys": [
"id" "id"
@@ -2417,6 +2446,24 @@
"formatZH": "删除网站acme[email]", "formatZH": "删除网站acme[email]",
"formatEN": "Deletewebsiteacme[email]" "formatEN": "Deletewebsiteacme[email]"
}, },
"/websites/acme/update": {
"bodyKeys": [
"id"
],
"paramKeys": [],
"beforeFunctions": [
{
"input_column": "id",
"input_value": "id",
"isList": false,
"db": "website_acme_accounts",
"output_column": "email",
"output_value": "email"
}
],
"formatZH": "更新acme[email]",
"formatEN": "Updateacme[email]"
},
"/websites/ca": { "/websites/ca": {
"bodyKeys": [ "bodyKeys": [
"name" "name"
@@ -3019,12 +3066,13 @@
"/xpack/tampers/update": { "/xpack/tampers/update": {
"bodyKeys": [ "bodyKeys": [
"website", "website",
"status" "status",
"path"
], ],
"paramKeys": [], "paramKeys": [],
"beforeFunctions": [], "beforeFunctions": [],
"formatZH": "更新防篡改信息[website]=\u003e[status]", "formatZH": "更新防篡改信息[website][path]=\u003e[status]",
"formatEN": "updatetamperinfo[website]=\u003e[status]" "formatEN": "updatetamperinfo[website][path]=\u003e[status]"
}, },
"/xpack/waf/acl/create": { "/xpack/waf/acl/create": {
"bodyKeys": [ "bodyKeys": [
Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

+6 -6
View File
@@ -33,8 +33,6 @@ const (
OneDriveRedirectURI = "http://localhost/login/authorized" OneDriveRedirectURI = "http://localhost/login/authorized"
GoogleRedirectURI = "https://localhost:8080" GoogleRedirectURI = "https://localhost:8080"
DaemonJsonPath = "/etc/docker/daemon.json"
) )
const ( const (
@@ -76,10 +74,10 @@ var WebUrlMap = map[string]struct{}{
"/containers/setting": {}, "/containers/setting": {},
"/containers/dashboard": {}, "/containers/dashboard": {},
"/cronjobs": {}, "/cronjobs": {},
"/cronjobs/cronjob": {}, "/cronjobs/cronjob": {},
"/cronjobs/library": {}, "/cronjobs/library": {},
"/cronjobs/operate": {}, "/cronjobs/cronjob/operate": {},
"/databases": {}, "/databases": {},
"/databases/mysql": {}, "/databases/mysql": {},
@@ -176,3 +174,5 @@ var DynamicRoutes = []string{
} }
var CertStore atomic.Value var CertStore atomic.Value
var DaemonJsonPath = "/etc/docker/daemon.json"
+9 -8
View File
@@ -48,7 +48,7 @@ require (
golang.org/x/text v0.26.0 golang.org/x/text v0.26.0
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
gorm.io/gorm v1.25.11 gorm.io/gorm v1.30.0
) )
require ( require (
@@ -65,7 +65,7 @@ require (
github.com/dustin/go-humanize v1.0.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect
github.com/glebarez/go-sqlite v1.21.2 // indirect github.com/glebarez/go-sqlite v1.22.0 // indirect
github.com/go-ini/ini v1.67.0 // indirect github.com/go-ini/ini v1.67.0 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.6 // indirect github.com/go-openapi/jsonreference v0.19.6 // indirect
@@ -99,6 +99,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mozillazg/go-httpheader v0.2.1 // indirect github.com/mozillazg/go-httpheader v0.2.1 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rs/xid v1.5.0 // indirect github.com/rs/xid v1.5.0 // indirect
@@ -114,17 +115,17 @@ require (
go.uber.org/atomic v1.9.0 // indirect go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect
golang.org/x/arch v0.8.0 // indirect golang.org/x/arch v0.8.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
golang.org/x/image v0.28.0 // indirect golang.org/x/image v0.28.0 // indirect
golang.org/x/sync v0.15.0 // indirect golang.org/x/sync v0.15.0 // indirect
golang.org/x/time v0.6.0 // indirect golang.org/x/time v0.6.0 // indirect
golang.org/x/tools v0.33.0 // indirect golang.org/x/tools v0.34.0 // indirect
google.golang.org/appengine v1.6.8 // indirect google.golang.org/appengine v1.6.8 // indirect
google.golang.org/protobuf v1.34.1 // indirect google.golang.org/protobuf v1.34.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect
gorm.io/driver/sqlite v1.4.4 // indirect gorm.io/driver/sqlite v1.4.4 // indirect
modernc.org/libc v1.22.5 // indirect modernc.org/libc v1.66.1 // indirect
modernc.org/mathutil v1.5.0 // indirect modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.5.0 // indirect modernc.org/memory v1.11.0 // indirect
modernc.org/sqlite v1.23.1 // indirect modernc.org/sqlite v1.38.0 // indirect
) )
+39 -21
View File
@@ -97,8 +97,8 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo= github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ=
github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k= github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc=
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw= github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ= github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
@@ -202,8 +202,8 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
@@ -338,9 +338,8 @@ github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
github.com/minio/minio-go/v7 v7.0.74 h1:fTo/XlPBTSpo3BAMshlwKL5RspXRv9us5UeHEGYCFe0= github.com/minio/minio-go/v7 v7.0.74 h1:fTo/XlPBTSpo3BAMshlwKL5RspXRv9us5UeHEGYCFe0=
@@ -357,6 +356,8 @@ github.com/mojocn/base64Captcha v1.3.6 h1:gZEKu1nsKpttuIAQgWHO+4Mhhls8cAKyiV2Ew0
github.com/mojocn/base64Captcha v1.3.6/go.mod h1:i5CtHvm+oMbj1UzEPXaA8IH/xHFZ3DGY3Wh3dBpZ28E= github.com/mojocn/base64Captcha v1.3.6/go.mod h1:i5CtHvm+oMbj1UzEPXaA8IH/xHFZ3DGY3Wh3dBpZ28E=
github.com/mozillazg/go-httpheader v0.2.1 h1:geV7TrjbL8KXSyvghnFm+NyTux/hxwueTSrwhe88TQQ= github.com/mozillazg/go-httpheader v0.2.1 h1:geV7TrjbL8KXSyvghnFm+NyTux/hxwueTSrwhe88TQQ=
github.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60= github.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM= github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM=
github.com/nicksnyder/go-i18n/v2 v2.4.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4= github.com/nicksnyder/go-i18n/v2 v2.4.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
@@ -380,7 +381,6 @@ github.com/qiniu/dyn v1.3.0/go.mod h1:E8oERcm8TtwJiZvkQPbcAh0RL8jO1G0VXJMW3FAWdk
github.com/qiniu/go-sdk/v7 v7.21.1 h1:D/IjVOlg5pTw0jeDjqTo6H5QM73Obb1AYfPOHmIFN+Q= github.com/qiniu/go-sdk/v7 v7.21.1 h1:D/IjVOlg5pTw0jeDjqTo6H5QM73Obb1AYfPOHmIFN+Q=
github.com/qiniu/go-sdk/v7 v7.21.1/go.mod h1:8EM2awITynlem2VML2dXGHkMYP2UyECsGLOdp6yMpco= github.com/qiniu/go-sdk/v7 v7.21.1/go.mod h1:8EM2awITynlem2VML2dXGHkMYP2UyECsGLOdp6yMpco=
github.com/qiniu/x v1.10.5/go.mod h1:03Ni9tj+N2h2aKnAz+6N0Xfl8FwMEDRC2PAlxekASDs= github.com/qiniu/x v1.10.5/go.mod h1:03Ni9tj+N2h2aKnAz+6N0Xfl8FwMEDRC2PAlxekASDs=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
@@ -516,8 +516,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk= golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk=
@@ -720,8 +720,8 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 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.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -836,8 +836,8 @@ gorm.io/gorm v1.23.7/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
gorm.io/gorm v1.23.10/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= gorm.io/gorm v1.23.10/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
gorm.io/gorm v1.25.11 h1:/Wfyg1B/je1hnDx3sMkX+gAlxrlZpn6X0BXRlwXlvHg= gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
gorm.io/gorm v1.25.11/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@@ -845,14 +845,32 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE= modernc.org/cc/v4 v4.26.1 h1:+X5NtzVBn0KgsBCBe+xkDC7twLb/jNVj9FPgiwSQO3s=
modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY= modernc.org/cc/v4 v4.26.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU=
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE=
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds= modernc.org/fileutil v1.3.3 h1:3qaU+7f7xxTUmvU1pJTZiDLAIoJVdUSSauJNHg9yXoA=
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= modernc.org/fileutil v1.3.3/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM= modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk= modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/goabi0 v0.0.3 h1:y81b9r3asCh6Xtse6Nz85aYGB0cG3M3U6222yap1KWI=
modernc.org/goabi0 v0.0.3/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
modernc.org/libc v1.66.1 h1:4uQsntXbVyAgrV+j6NhKvDiUypoJL48BWQx6sy9y8ok=
modernc.org/libc v1.66.1/go.mod h1:AiZxInURfEJx516LqEaFcrC+X38rt9G7+8ojIXQKHbo=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.38.0 h1:+4OrfPQ8pxHKuWG4md1JpR/EYAh3Md7TdejuuzE7EUI=
modernc.org/sqlite v1.38.0/go.mod h1:1Bj+yES4SVvBZ4cBOpVZ6QgesMCKpJZDq0nxYzOpmNE=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
-2
View File
@@ -40,8 +40,6 @@ func (b *backup) Run() {
switch backupItem.Type { switch backupItem.Type {
case constant.OneDrive: case constant.OneDrive:
refreshToken, err = client.RefreshToken("refresh_token", "refreshToken", varMap) refreshToken, err = client.RefreshToken("refresh_token", "refreshToken", varMap)
case constant.GoogleDrive:
refreshToken, err = client.RefreshGoogleToken("refresh_token", "refreshToken", varMap)
case constant.ALIYUN: case constant.ALIYUN:
refreshToken, err = client.RefreshALIToken(varMap) refreshToken, err = client.RefreshALIToken(varMap)
} }
+40 -20
View File
@@ -32,43 +32,52 @@ func Init() {
handleUserInfo(global.CONF.Base.ChangeUserInfo, settingRepo) handleUserInfo(global.CONF.Base.ChangeUserInfo, settingRepo)
generateKey() generateKey()
initDockerConf()
} }
func handleUserInfo(tags string, settingRepo repo.ISettingRepo) { func handleUserInfo(tags string, settingRepo repo.ISettingRepo) {
if len(tags) == 0 { if len(tags) == 0 {
return return
} }
settingMap := make(map[string]string)
if tags == "use_existing" {
settingMap["ServerPort"] = common.LoadParams("ORIGINAL_PORT")
global.CONF.Conn.Port = settingMap["ServerPort"]
settingMap["UserName"] = global.CONF.Base.Username
settingMap["Password"] = global.CONF.Base.Password
settingMap["SecurityEntrance"] = global.CONF.Conn.Entrance
settingMap["SystemVersion"] = common.LoadParams("ORIGINAL_VERSION")
global.CONF.Base.Version = settingMap["SystemVersion"]
settingMap["Language"] = global.CONF.Base.Language
}
if tags == "all" { if tags == "all" {
if err := settingRepo.Update("UserName", common.RandStrAndNum(10)); err != nil { settingMap["UserName"] = common.RandStrAndNum(10)
global.LOG.Fatalf("init username before start failed, err: %v", err) settingMap["Password"] = common.RandStrAndNum(10)
} settingMap["SecurityEntrance"] = common.RandStrAndNum(10)
pass, _ := encrypt.StringEncrypt(common.RandStrAndNum(10))
if err := settingRepo.Update("Password", pass); err != nil {
global.LOG.Fatalf("init password before start failed, err: %v", err)
}
if err := settingRepo.Update("SecurityEntrance", common.RandStrAndNum(10)); err != nil {
global.LOG.Fatalf("init entrance before start failed, err: %v", err)
}
return
} }
if strings.Contains(global.CONF.Base.ChangeUserInfo, "username") { if strings.Contains(global.CONF.Base.ChangeUserInfo, "username") {
if err := settingRepo.Update("UserName", common.RandStrAndNum(10)); err != nil { settingMap["UserName"] = common.RandStrAndNum(10)
global.LOG.Fatalf("init username before start failed, err: %v", err)
}
} }
if strings.Contains(global.CONF.Base.ChangeUserInfo, "password") { if strings.Contains(global.CONF.Base.ChangeUserInfo, "password") {
pass, _ := encrypt.StringEncrypt(common.RandStrAndNum(10)) settingMap["Password"] = common.RandStrAndNum(10)
if err := settingRepo.Update("Password", pass); err != nil {
global.LOG.Fatalf("init password before start failed, err: %v", err)
}
} }
if strings.Contains(global.CONF.Base.ChangeUserInfo, "entrance") { if strings.Contains(global.CONF.Base.ChangeUserInfo, "entrance") {
if err := settingRepo.Update("SecurityEntrance", common.RandStrAndNum(10)); err != nil { settingMap["SecurityEntrance"] = common.RandStrAndNum(10)
global.LOG.Fatalf("init entrance before start failed, err: %v", err) }
for key, val := range settingMap {
if len(val) == 0 {
continue
}
if key == "Password" {
val, _ = encrypt.StringEncrypt(val)
}
if err := settingRepo.Update(key, val); err != nil {
global.LOG.Errorf("update %s before start failed, err: %v", key, err)
} }
} }
_, _ = cmd.RunDefaultWithStdoutBashCf("%s sed -i '/CHANGE_USER_INFO=%v/d' /usr/local/bin/1pctl", cmd.SudoHandleCmd(), global.CONF.Base.ChangeUserInfo) _, _ = cmd.RunDefaultWithStdoutBashCf("%s sed -i '/CHANGE_USER_INFO=%v/d' /usr/local/bin/1pctl", cmd.SudoHandleCmd(), global.CONF.Base.ChangeUserInfo)
_, _ = cmd.RunDefaultWithStdoutBashCf("%s sed -i -e 's#ORIGINAL_PASSWORD=.*#ORIGINAL_PASSWORD=**********#g' /usr/local/bin/1pctl", cmd.SudoHandleCmd())
} }
func generateKey() { func generateKey() {
@@ -76,3 +85,14 @@ func generateKey() {
global.LOG.Errorf("generate rsa key error : %s", err.Error()) global.LOG.Errorf("generate rsa key error : %s", err.Error())
} }
} }
func initDockerConf() {
stdout, err := cmd.RunDefaultWithStdoutBashC("which docker")
if err != nil {
return
}
dockerPath := stdout
if strings.Contains(dockerPath, "snap") {
constant.DaemonJsonPath = "/var/snap/docker/current/config/daemon.json"
}
}
+1
View File
@@ -19,6 +19,7 @@ func Init() {
migrations.AddXpackHideMenu, migrations.AddXpackHideMenu,
migrations.UpdateGoogle, migrations.UpdateGoogle,
migrations.UpdateXpackHideMenu, migrations.UpdateXpackHideMenu,
migrations.UpdateOnedrive,
}) })
if err := m.Migrate(); err != nil { if err := m.Migrate(); err != nil {
global.LOG.Error(err) global.LOG.Error(err)
+19
View File
@@ -13,6 +13,7 @@ import (
"github.com/1Panel-dev/1Panel/core/constant" "github.com/1Panel-dev/1Panel/core/constant"
"github.com/1Panel-dev/1Panel/core/global" "github.com/1Panel-dev/1Panel/core/global"
"github.com/1Panel-dev/1Panel/core/init/migration/helper" "github.com/1Panel-dev/1Panel/core/init/migration/helper"
"github.com/1Panel-dev/1Panel/core/utils/cmd"
"github.com/1Panel-dev/1Panel/core/utils/common" "github.com/1Panel-dev/1Panel/core/utils/common"
"github.com/1Panel-dev/1Panel/core/utils/encrypt" "github.com/1Panel-dev/1Panel/core/utils/encrypt"
"github.com/go-gormigrate/gormigrate/v2" "github.com/go-gormigrate/gormigrate/v2"
@@ -52,6 +53,7 @@ var InitSetting = &gormigrate.Migration{
if err := tx.Create(&model.Setting{Key: "Password", Value: pass}).Error; err != nil { if err := tx.Create(&model.Setting{Key: "Password", Value: pass}).Error; err != nil {
return err return err
} }
_, _ = cmd.RunDefaultWithStdoutBashCf("%s sed -i -e 's#ORIGINAL_PASSWORD=.*#ORIGINAL_PASSWORD=**********#g' /usr/local/bin/1pctl", cmd.SudoHandleCmd())
if err := tx.Create(&model.Setting{Key: "Theme", Value: "light"}).Error; err != nil { if err := tx.Create(&model.Setting{Key: "Theme", Value: "light"}).Error; err != nil {
return err return err
} }
@@ -470,3 +472,20 @@ var UpdateGoogle = &gormigrate.Migration{
return nil return nil
}, },
} }
var UpdateOnedrive = &gormigrate.Migration{
ID: "20250704-update-onedrive",
Migrate: func(tx *gorm.DB) error {
if err := tx.Model(&model.Setting{}).
Where("key = ?", "OneDriveID").
Update("value", "NTQ0NmNmZTMtNGM3OS00N2EwLWFlMjUtZmM2NDU0NzhlMmQ5").Error; err != nil {
return err
}
if err := tx.Model(&model.Setting{}).
Where("key = ?", "OneDriveSc").
Update("value", "bGRlOFF+WEVrR1M0b25Vb1VsRWpMYzE2MW9rTXZEM25KdnZ1MGN6MA==").Error; err != nil {
return err
}
return nil
},
}
+8 -19
View File
@@ -10,6 +10,7 @@ import (
"github.com/1Panel-dev/1Panel/core/cmd/server/conf" "github.com/1Panel-dev/1Panel/core/cmd/server/conf"
"github.com/1Panel-dev/1Panel/core/global" "github.com/1Panel-dev/1Panel/core/global"
"github.com/1Panel-dev/1Panel/core/utils/cmd" "github.com/1Panel-dev/1Panel/core/utils/cmd"
"github.com/1Panel-dev/1Panel/core/utils/common"
"github.com/fsnotify/fsnotify" "github.com/fsnotify/fsnotify"
"github.com/spf13/viper" "github.com/spf13/viper"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
@@ -39,13 +40,13 @@ func Init() {
panic(fmt.Errorf("Fatal error config file: %s \n", err)) panic(fmt.Errorf("Fatal error config file: %s \n", err))
} }
} else { } else {
baseDir = loadParams("BASE_DIR") baseDir = common.LoadParams("BASE_DIR")
port = loadParams("ORIGINAL_PORT") port = common.LoadParams("ORIGINAL_PORT")
version = loadParams("ORIGINAL_VERSION") version = common.LoadParams("ORIGINAL_VERSION")
username = loadParams("ORIGINAL_USERNAME") username = common.LoadParams("ORIGINAL_USERNAME")
password = loadParams("ORIGINAL_PASSWORD") password = common.LoadParams("ORIGINAL_PASSWORD")
entrance = loadParams("ORIGINAL_ENTRANCE") entrance = common.LoadParams("ORIGINAL_ENTRANCE")
language = loadParams("LANGUAGE") language = common.LoadParams("LANGUAGE")
reader := bytes.NewReader(conf.AppYaml) reader := bytes.NewReader(conf.AppYaml)
if err := v.ReadConfig(reader); err != nil { if err := v.ReadConfig(reader); err != nil {
@@ -100,18 +101,6 @@ func Init() {
global.Viper = v global.Viper = v
} }
func loadParams(param string) string {
stdout, err := cmd.RunDefaultWithStdoutBashCf("grep '^%s=' /usr/local/bin/1pctl | cut -d'=' -f2", param)
if err != nil {
panic(err)
}
info := strings.ReplaceAll(stdout, "\n", "")
if len(info) == 0 || info == `""` {
panic(fmt.Sprintf("error `%s` find in /usr/local/bin/1pctl", param))
}
return info
}
func loadChangeInfo() string { func loadChangeInfo() string {
stdout, err := cmd.RunDefaultWithStdoutBashC("grep '^CHANGE_USER_INFO=' /usr/local/bin/1pctl | cut -d'=' -f2") stdout, err := cmd.RunDefaultWithStdoutBashC("grep '^CHANGE_USER_INFO=' /usr/local/bin/1pctl | cut -d'=' -f2")
if err != nil { if err != nil {
+37 -1
View File
@@ -6,6 +6,8 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
"mime"
"mime/multipart"
"net/http" "net/http"
"net/url" "net/url"
"path" "path"
@@ -65,7 +67,11 @@ func OperationLog() gin.HandlerFunc {
c.Request.Body = io.NopCloser(bytes.NewBuffer(body)) c.Request.Body = io.NopCloser(bytes.NewBuffer(body))
} }
bodyMap := make(map[string]interface{}) bodyMap := make(map[string]interface{})
_ = json.Unmarshal(body, &bodyMap) if strings.Contains(c.Request.Header.Get("Content-Type"), "multipart/form-data") {
bodyMap, _ = parseMultipart(body, c.Request.Header.Get("Content-Type"))
} else {
_ = json.Unmarshal(body, &bodyMap)
}
for _, key := range operationDic.BodyKeys { for _, key := range operationDic.BodyKeys {
if _, ok := bodyMap[key]; ok { if _, ok := bodyMap[key]; ok {
formatMap[key] = bodyMap[key] formatMap[key] = bodyMap[key]
@@ -247,3 +253,33 @@ func replaceStr(val string, rep ...string) string {
} }
return val return val
} }
func parseMultipart(formData []byte, contentType string) (map[string]interface{}, error) {
d, params, err := mime.ParseMediaType(contentType)
if err != nil || d != "multipart/form-data" {
return nil, http.ErrNotMultipart
}
boundary, ok := params["boundary"]
if !ok {
return nil, http.ErrMissingBoundary
}
reader := multipart.NewReader(bytes.NewReader(formData), boundary)
ret := make(map[string]interface{})
f, err := reader.ReadForm(32 << 20)
if err != nil {
return nil, err
}
for k, v := range f.Value {
if len(v) > 0 {
ret[k] = v[0]
}
}
for k, v := range f.File {
if len(v) > 0 {
ret[k] = v[0].Filename
}
}
return ret, nil
}
+24 -9
View File
@@ -9,6 +9,7 @@ import (
"os" "os"
"os/exec" "os/exec"
"strings" "strings"
"syscall"
"time" "time"
"github.com/1Panel-dev/1Panel/core/app/task" "github.com/1Panel-dev/1Panel/core/app/task"
@@ -17,12 +18,13 @@ import (
) )
type CommandHelper struct { type CommandHelper struct {
workDir string workDir string
outputFile string outputFile string
scriptPath string scriptPath string
timeout time.Duration timeout time.Duration
taskItem *task.Task taskItem *task.Task
logger *log.Logger logger *log.Logger
IgnoreExist1 bool
} }
type Option func(*CommandHelper) type Option func(*CommandHelper)
@@ -132,14 +134,14 @@ func (c *CommandHelper) run(name string, arg ...string) (string, error) {
return "", buserr.New("ErrCmdTimeout") return "", buserr.New("ErrCmdTimeout")
} }
if err != nil { if err != nil {
return handleErr(stdout, stderr, err) return handleErr(stdout, stderr, c.IgnoreExist1, err)
} }
return stdout.String(), nil return stdout.String(), nil
} }
err := cmd.Run() err := cmd.Run()
if err != nil { if err != nil {
return handleErr(stdout, stderr, err) return handleErr(stdout, stderr, c.IgnoreExist1, err)
} }
return stdout.String(), nil return stdout.String(), nil
} }
@@ -174,6 +176,11 @@ func WithScriptPath(scriptPath string) Option {
s.scriptPath = scriptPath s.scriptPath = scriptPath
} }
} }
func WithIgnoreExist1() Option {
return func(s *CommandHelper) {
s.IgnoreExist1 = true
}
}
type CustomWriter struct { type CustomWriter struct {
taskItem *task.Task taskItem *task.Task
@@ -199,7 +206,15 @@ func (cw *CustomWriter) Flush() {
} }
} }
func handleErr(stdout, stderr bytes.Buffer, err error) (string, error) { func handleErr(stdout, stderr bytes.Buffer, ignoreExist1 bool, err error) (string, error) {
var exitError *exec.ExitError
if ignoreExist1 && errors.As(err, &exitError) {
if status, ok := exitError.Sys().(syscall.WaitStatus); ok {
if status.ExitStatus() == 1 {
return "", nil
}
}
}
errMsg := "" errMsg := ""
if len(stderr.String()) != 0 { if len(stderr.String()) != 0 {
errMsg = fmt.Sprintf("stderr: %s", stderr.String()) errMsg = fmt.Sprintf("stderr: %s", stderr.String())
+9 -10
View File
@@ -4,14 +4,12 @@ import (
"fmt" "fmt"
mathRand "math/rand" mathRand "math/rand"
"net" "net"
"net/http"
"os" "os"
"path" "path"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"github.com/1Panel-dev/1Panel/core/constant"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/1Panel-dev/1Panel/core/global" "github.com/1Panel-dev/1Panel/core/global"
@@ -225,13 +223,14 @@ func HandleIPList(content string) ([]string, error) {
return res, nil return res, nil
} }
func deleteCookie(w http.ResponseWriter) { func LoadParams(param string) string {
cookie := &http.Cookie{ stdout, err := cmd.RunDefaultWithStdoutBashCf("grep '^%s=' /usr/local/bin/1pctl | cut -d'=' -f2", param)
Name: constant.SessionName, if err != nil {
Value: "", panic(err)
Path: "/",
Expires: time.Unix(0, 0),
MaxAge: -1,
} }
http.SetCookie(w, cookie) info := strings.ReplaceAll(stdout, "\n", "")
if len(info) == 0 || info == `""` {
panic(fmt.Sprintf("error `%s` find in /usr/local/bin/1pctl", param))
}
return info
} }
+3 -4
View File
@@ -83,7 +83,6 @@ func HandleTar(sourceDir, targetDir, name, exclusionRules string, secret string)
exMap := make(map[string]struct{}) exMap := make(map[string]struct{})
excludes := strings.Split(exclusionRules, ",") excludes := strings.Split(exclusionRules, ",")
excludeRules := "" excludeRules := ""
excludes = append(excludes, "*.sock")
for _, exclude := range excludes { for _, exclude := range excludes {
if len(exclude) == 0 { if len(exclude) == 0 {
continue continue
@@ -110,13 +109,13 @@ func HandleTar(sourceDir, targetDir, name, exclusionRules string, secret string)
if len(secret) != 0 { if len(secret) != 0 {
extraCmd := "| openssl enc -aes-256-cbc -salt -k '" + secret + "' -out" extraCmd := "| openssl enc -aes-256-cbc -salt -k '" + secret + "' -out"
commands = fmt.Sprintf("tar --warning=no-file-changed --ignore-failed-read -zcf %s %s %s %s", " -"+excludeRules, path, extraCmd, targetDir+"/"+name) commands = fmt.Sprintf("tar -zcf %s %s %s %s", " -"+excludeRules, path, extraCmd, targetDir+"/"+name)
global.LOG.Debug(strings.ReplaceAll(commands, fmt.Sprintf(" %s ", secret), "******")) global.LOG.Debug(strings.ReplaceAll(commands, fmt.Sprintf(" %s ", secret), "******"))
} else { } else {
commands = fmt.Sprintf("tar --warning=no-file-changed --ignore-failed-read -zcf %s %s %s", targetDir+"/"+name, excludeRules, path) commands = fmt.Sprintf("tar -zcf %s %s %s", targetDir+"/"+name, excludeRules, path)
global.LOG.Debug(commands) global.LOG.Debug(commands)
} }
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(24 * time.Hour)) cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(24*time.Hour), cmd.WithIgnoreExist1())
stdout, err := cmdMgr.RunWithStdoutBashC(commands) stdout, err := cmdMgr.RunWithStdoutBashC(commands)
if err != nil { if err != nil {
if len(stdout) != 0 { if len(stdout) != 0 {
+8
View File
@@ -75,6 +75,14 @@ func (c *SSHClient) SudoHandleCmd() string {
return "" return ""
} }
func (c *SSHClient) IsRoot(user string) bool {
if user == "root" {
return true
}
_, err := c.Run("sudo -n true")
return err == nil
}
func (c *SSHClient) Runf(shell string, args ...interface{}) (string, error) { func (c *SSHClient) Runf(shell string, args ...interface{}) (string, error) {
session, err := c.Client.NewSession() session, err := c.Client.NewSession()
if err != nil { if err != nil {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

+2 -8
View File
@@ -47,7 +47,6 @@ class RequestHttp {
this.service.interceptors.response.use( this.service.interceptors.response.use(
(response: AxiosResponse) => { (response: AxiosResponse) => {
globalStore.errStatus = '';
const { data } = response; const { data } = response;
if (data.code == ResultEnum.OVERDUE || data.code == ResultEnum.FORBIDDEN) { if (data.code == ResultEnum.OVERDUE || data.code == ResultEnum.FORBIDDEN) {
globalStore.setLogStatus(false); globalStore.setLogStatus(false);
@@ -94,9 +93,9 @@ class RequestHttp {
return data; return data;
}, },
async (error: AxiosError) => { async (error: AxiosError) => {
globalStore.errStatus = '';
const { response } = error; const { response } = error;
if (error.message.indexOf('timeout') !== -1) MsgError('请求超时!请您稍后重试');
if (error.message.indexOf('timeout') !== -1) MsgError(i18n.global.t('commons.msg.requestTimeout'));
if (response) { if (response) {
switch (response.status) { switch (response.status) {
case 313: case 313:
@@ -110,11 +109,6 @@ class RequestHttp {
); );
return Promise.reject(error); return Promise.reject(error);
default: default:
globalStore.errStatus = 'code-' + response.status;
router.push({
name: 'entrance',
params: { code: globalStore.entrance },
});
return; return;
} }
} }
-3
View File
@@ -246,9 +246,6 @@ export namespace Container {
password: string; password: string;
auth: boolean; auth: boolean;
} }
export interface RepoDelete {
ids: Array<number>;
}
export interface RepoInfo { export interface RepoInfo {
id: number; id: number;
createdAt: Date; createdAt: Date;
+11
View File
@@ -23,12 +23,16 @@ export namespace Cronjob {
appID: string; appID: string;
website: string; website: string;
exclusionRules: string; exclusionRules: string;
ignoreFiles: Array<string>;
dbType: string; dbType: string;
dbName: string; dbName: string;
url: string; url: string;
isDir: boolean; isDir: boolean;
files: Array<Item>; files: Array<Item>;
sourceDir: string; sourceDir: string;
snapshotRule: snapshotRule;
ignoreAppIDs: Array<Number>;
withImage: boolean;
websiteList: Array<string>; websiteList: Array<string>;
appIdList: Array<string>; appIdList: Array<string>;
@@ -41,6 +45,7 @@ export namespace Cronjob {
sourceAccountItems: Array<number>; sourceAccountItems: Array<number>;
retainCopies: number; retainCopies: number;
ignoreErr: boolean;
retryTimes: number; retryTimes: number;
timeout: number; timeout: number;
timeoutItem: number; timeoutItem: number;
@@ -72,6 +77,7 @@ export namespace Cronjob {
url: string; url: string;
isDir: boolean; isDir: boolean;
sourceDir: string; sourceDir: string;
snapshotRule: snapshotRule;
//shell //shell
executor: string; executor: string;
@@ -86,11 +92,16 @@ export namespace Cronjob {
retainCopies: number; retainCopies: number;
retryTimes: number; retryTimes: number;
timeout: number; timeout: number;
ignoreErr: boolean;
secret: string; secret: string;
alertCount: number; alertCount: number;
alertTitle: string; alertTitle: string;
} }
export interface snapshotRule {
withImage: boolean;
ignoreAppIDs: Array<Number>;
}
export interface SpecObj { export interface SpecObj {
specType: string; specType: string;
week: number; week: number;
+1
View File
@@ -168,6 +168,7 @@ export namespace File {
size: number; size: number;
uploadSize: number; uploadSize: number;
modTime: string; modTime: string;
isDir: boolean;
} }
export interface RecycleBin { export interface RecycleBin {
+7
View File
@@ -16,6 +16,7 @@ export namespace Runtime {
codeDir: string; codeDir: string;
port: string; port: string;
appID: number; appID: number;
remark: string;
} }
export interface RuntimeReq extends ReqPage { export interface RuntimeReq extends ReqPage {
@@ -61,6 +62,7 @@ export namespace Runtime {
exposedPorts?: ExposedPort[]; exposedPorts?: ExposedPort[];
environments?: Environment[]; environments?: Environment[];
volumes?: Volume[]; volumes?: Volume[];
remark?: string;
} }
export interface ExposedPort { export interface ExposedPort {
@@ -218,4 +220,9 @@ export namespace Runtime {
environments: Environment[]; environments: Environment[];
volumes: Volume[]; volumes: Volume[];
} }
export interface RemarkUpdate {
id: number;
remark: string;
}
} }
+2 -2
View File
@@ -141,8 +141,8 @@ export const createImageRepo = (params: Container.RepoCreate) => {
export const updateImageRepo = (params: Container.RepoUpdate) => { export const updateImageRepo = (params: Container.RepoUpdate) => {
return http.post(`/containers/repo/update`, params, TimeoutEnum.T_40S); return http.post(`/containers/repo/update`, params, TimeoutEnum.T_40S);
}; };
export const deleteImageRepo = (params: Container.RepoDelete) => { export const deleteImageRepo = (id: Number) => {
return http.post(`/containers/repo/del`, params, TimeoutEnum.T_40S); return http.post(`/containers/repo/del`, { id: id }, TimeoutEnum.T_40S);
}; };
// composeTemplate // composeTemplate
+4
View File
@@ -129,3 +129,7 @@ export const getPHPContainerConfig = (id: number) => {
export const updatePHPContainerConfig = (req: Runtime.PHPContainerConfig) => { export const updatePHPContainerConfig = (req: Runtime.PHPContainerConfig) => {
return http.post<any>(`/runtimes/php/container/update`, req); return http.post<any>(`/runtimes/php/container/update`, req);
}; };
export const updateRemark = (req: Runtime.RemarkUpdate) => {
return http.post(`/runtimes/remark`, req);
};
@@ -2,12 +2,15 @@
<div> <div>
<el-card :style="{ height: height }" class="home-card"> <el-card :style="{ height: height }" class="home-card">
<div class="header"> <div class="header">
<span class="header-span">{{ header }}</span> <div class="header-left">
<slot name="header-l" /> <span class="header-span">{{ header }}</span>
<slot name="header-r" /> <slot name="header-l" />
</div>
<div class="header-right">
<slot name="header-r" />
</div>
</div> </div>
<div class="body-content">
<div>
<slot name="body" /> <slot name="body" />
</div> </div>
</el-card> </el-card>
@@ -25,27 +28,44 @@ defineProps({
<style scoped lang="scss"> <style scoped lang="scss">
.home-card { .home-card {
.header { .header {
.header-span { display: flex;
position: relative; justify-content: space-between;
font-size: 16px; align-items: center;
font-weight: 500;
margin-left: 18px; .header-left {
display: flex; display: flex;
&::before { align-items: center;
position: absolute; gap: 12px;
top: 50%;
transform: translateY(-50%); .header-span {
left: -13px; position: relative;
width: 4px; font-size: 16px;
height: 14px; font-weight: 500;
content: ''; margin-left: 18px;
background: $primary-color; display: flex;
border-radius: 10px; align-items: center;
&::before {
position: absolute;
top: 50%;
transform: translateY(-50%);
left: -13px;
width: 4px;
height: 14px;
content: '';
background: $primary-color;
border-radius: 10px;
}
} }
} }
.header-right {
display: flex;
align-items: center;
}
} }
div:nth-child(2) { .body-content {
margin-top: 20px; margin-top: 20px;
} }
} }
@@ -32,7 +32,7 @@
v-model:current-page="paginationConfig.currentPage" v-model:current-page="paginationConfig.currentPage"
v-model:page-size="paginationConfig.pageSize" v-model:page-size="paginationConfig.pageSize"
:total="paginationConfig.total" :total="paginationConfig.total"
:page-sizes="[5, 10, 20, 50, 100]" :page-sizes="[5, 10, 20, 50, 100, 200, 500]"
@size-change="sizeChange" @size-change="sizeChange"
@current-change="currentChange" @current-change="currentChange"
:size="mobile || paginationConfig.small ? 'small' : 'default'" :size="mobile || paginationConfig.small ? 'small' : 'default'"
@@ -1,6 +1,5 @@
<template> <template>
<DrawerPro v-model="drawerVisible" :header="$t('setting.ignoreRule')" @close="handleClose" size="small"> <div>
<el-alert :closable="false" type="warning">{{ $t('setting.ignoreHelper') }}</el-alert>
<el-form ref="formRef" :model="form" :rules="rules" v-loading="loading" class="mt-2"> <el-form ref="formRef" :model="form" :rules="rules" v-loading="loading" class="mt-2">
<el-form-item prop="tmpRule"> <el-form-item prop="tmpRule">
<div class="w-full"> <div class="w-full">
@@ -13,6 +12,7 @@
/> />
<FileList @choose="loadDir" :path="baseDir" :isAll="true"></FileList> <FileList @choose="loadDir" :path="baseDir" :isAll="true"></FileList>
</div> </div>
<span class="input-help">{{ $t('cronjob.exclusionRulesHelper') }}</span>
</el-form-item> </el-form-item>
</el-form> </el-form>
@@ -30,26 +30,26 @@
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<template #footer> </div>
<el-button @click="drawerVisible = false">{{ $t('commons.button.cancel') }}</el-button>
<el-button :disabled="loading" type="primary" @click="onSave()">
{{ $t('commons.button.save') }}
</el-button>
</template>
</DrawerPro>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, ref } from 'vue'; import { reactive, ref } from 'vue';
import i18n from '@/lang'; import i18n from '@/lang';
import { MsgSuccess } from '@/utils/message';
import FileList from '@/components/file-list/index.vue'; import FileList from '@/components/file-list/index.vue';
import { FormInstance } from 'element-plus'; import { FormInstance } from 'element-plus';
import { getAgentSettingInfo, loadBaseDir, updateAgentSetting } from '@/api/modules/setting'; import { loadBaseDir } from '@/api/modules/setting';
const loading = ref(); const loading = ref();
const baseDir = ref(); const baseDir = ref();
const drawerVisible = ref(false);
const tableList = ref(); const tableList = ref();
const em = defineEmits(['update:files']);
const props = defineProps({
files: {
type: Array<String>,
default: [],
},
});
const form = reactive({ const form = reactive({
tmpRule: '', tmpRule: '',
@@ -76,17 +76,6 @@ function checkData(rule: any, value: any, callback: any) {
callback(); callback();
} }
const acceptParams = async (): Promise<void> => {
loadPath();
const res = await getAgentSettingInfo();
tableList.value = [];
let items = res.data.snapshotIgnore.split(',');
for (const item of items) {
tableList.value.push({ value: item });
}
drawerVisible.value = true;
};
const loadPath = async () => { const loadPath = async () => {
const pathRes = await loadBaseDir(); const pathRes = await loadBaseDir();
baseDir.value = pathRes.data; baseDir.value = pathRes.data;
@@ -106,35 +95,25 @@ const handleAdd = (formEl: FormInstance | undefined) => {
tableList.value.push({ value: item }); tableList.value.push({ value: item });
} }
} }
em(
'update:files',
tableList.value.map((item) => item.value),
);
form.tmpRule = ''; form.tmpRule = '';
}); });
}; };
const handleDelete = (index: number) => { const handleDelete = (index: number) => {
tableList.value.splice(index, 1); tableList.value.splice(index, 1);
em(
'update:files',
tableList.value.map((item) => item.value),
);
}; };
const onSave = async () => { onMounted(() => {
let list = []; loadPath();
for (const item of tableList.value) { tableList.value = props.files.map((item) => {
list.push(item.value); return { value: item };
} });
await updateAgentSetting({ key: 'SnapshotIgnore', value: list.join(',') })
.then(async () => {
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
loading.value = false;
drawerVisible.value = false;
return;
})
.catch(() => {
loading.value = false;
});
};
const handleClose = () => {
drawerVisible.value = false;
};
defineExpose({
acceptParams,
}); });
</script> </script>
@@ -1,7 +1,7 @@
<template> <template>
<span v-for="(token, index) in tokens" :key="index" :class="['token', token.type]" :style="{ color: token.color }"> <span v-for="(token, index) in tokens" :key="index" :class="['token', token.type]" :style="{ color: token.color }">
<span v-if="token.type != 'html'">{{ token.text }}</span> <span v-if="token.type != 'html'" class="whitespace-pre">{{ token.text }}</span>
<span v-else v-html="token.text"></span> <span v-else v-html="token.text" class="whitespace-pre"></span>
</span> </span>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -111,6 +111,11 @@ const defaultRules: TokenRule[] = [
pattern: /\b(?<!\[)\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b(?!\])/g, pattern: /\b(?<!\[)\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b(?!\])/g,
color: '#4A90E2', color: '#4A90E2',
}, },
{
type: 'ipv6',
pattern: /\b(?:[A-Fa-f0-9]{1,4}:){7}[A-Fa-f0-9]{1,4}\b/g,
color: '#4A90E2',
},
{ {
type: 'server-host', type: 'server-host',
pattern: /(?:server|host):\s*[^,\s]+/g, pattern: /(?:server|host):\s*[^,\s]+/g,
@@ -189,8 +194,9 @@ function tokenizeLog(log: string): Token[] {
}); });
if (lastIndex < log.length) { if (lastIndex < log.length) {
const rest = log.substring(lastIndex).replace(/\n?$/, '\n');
tokens.push({ tokens.push({
text: log.substring(lastIndex), text: rest,
type: 'plain', type: 'plain',
color: '#666666', color: '#666666',
}); });
+12 -5
View File
@@ -886,6 +886,7 @@ const message = {
repo: 'Container registry | Container registries', repo: 'Container registry | Container registries',
createRepo: 'Add', createRepo: 'Add',
httpRepoHelper: 'Operating an HTTP-type repository requires restarting the Docker service.',
httpRepo: 'Choosing HTTP protocol requires restarting the Docker service to add it into insecure registries.', httpRepo: 'Choosing HTTP protocol requires restarting the Docker service to add it into insecure registries.',
delInsecure: 'Deletion of credit', delInsecure: 'Deletion of credit',
delInsecureHelper: delInsecureHelper:
@@ -1028,9 +1029,14 @@ const message = {
saveLocal: 'Retain local backups (the same as the number of cloud storage copies)', saveLocal: 'Retain local backups (the same as the number of cloud storage copies)',
url: 'URL Address', url: 'URL Address',
targetHelper: 'Backup accounts are maintained in panel settings.', targetHelper: 'Backup accounts are maintained in panel settings.',
withImageHelper: 'Backup app store images, but this will increase the snapshot file size.',
ignoreApp: 'Exclude apps',
withImage: 'Backup all app images',
retainCopies: 'Retain records', retainCopies: 'Retain records',
retryTimes: 'Retry Attempts', retryTimes: 'Retry Attempts',
timeout: 'Timeout', timeout: 'Timeout',
ignoreErr: 'Ignore errors',
ignoreErrHelper: 'Ignore errors during backup to ensure all backup tasks complete',
retryTimesHelper: '0 means no retry after failure', retryTimesHelper: '0 means no retry after failure',
retainCopiesHelper: 'Number of copies to retain for execution records and logs', retainCopiesHelper: 'Number of copies to retain for execution records and logs',
retainCopiesHelper1: 'Number of copies to retain for backup files', retainCopiesHelper1: 'Number of copies to retain for backup files',
@@ -1467,7 +1473,8 @@ const message = {
existFileTitle: 'Same name file prompt', existFileTitle: 'Same name file prompt',
existFileHelper: 'The uploaded file contains a file with the same name, do you want to overwrite it?', existFileHelper: 'The uploaded file contains a file with the same name, do you want to overwrite it?',
existFileSize: 'File size (new -> old)', existFileSize: 'File size (new -> old)',
existFileDirHelper: 'The selected file/folder has a duplicate name. Please proceed with caution!', existFileDirHelper: 'The selected file/folder has a duplicate name. Please proceed with caution! \n',
coverDirHelper: 'The selected folders to be replaced will be copied to the destination path!',
noSuchFile: 'The file or directory was not found. Please check and try again.', noSuchFile: 'The file or directory was not found. Please check and try again.',
setting: 'Setting', setting: 'Setting',
showHide: 'Show hidden files', showHide: 'Show hidden files',
@@ -1823,6 +1830,7 @@ const message = {
systemLog: 'Retain System Log', systemLog: 'Retain System Log',
taskLog: 'Retain Task Log', taskLog: 'Retain Task Log',
monitorData: 'Retain Monitoring Data', monitorData: 'Retain Monitoring Data',
dockerConf: 'Retain Docker Configuration',
selectAllImage: 'Backup All Application Images', selectAllImage: 'Backup All Application Images',
logLabel: 'Log', logLabel: 'Log',
agentLabel: 'Node Configuration', agentLabel: 'Node Configuration',
@@ -2088,8 +2096,6 @@ const message = {
takeDown: 'TakeDown', takeDown: 'TakeDown',
allReadyInstalled: 'Installed', allReadyInstalled: 'Installed',
installHelper: 'If you have image pull issues, configure image acceleration.', installHelper: 'If you have image pull issues, configure image acceleration.',
upgradeHelper:
'Bring abnormal applications back to normal status before upgrading. If the upgrade fails, go to "Logs > System Logs" to check the failure reason.',
installWarn: `The external access isn't checked, and it will make the application unable to access through external network. Do you want to continue?`, installWarn: `The external access isn't checked, and it will make the application unable to access through external network. Do you want to continue?`,
showIgnore: 'View ignored applications', showIgnore: 'View ignored applications',
cancelIgnore: 'Cancel ignore', cancelIgnore: 'Cancel ignore',
@@ -2416,8 +2422,6 @@ const message = {
enableSSLHelper: 'Failure to enable will not affect the creation of the website', enableSSLHelper: 'Failure to enable will not affect the creation of the website',
batchAdd: 'Batch Add Domains', batchAdd: 'Batch Add Domains',
generateDomain: 'Generate', generateDomain: 'Generate',
domainSSLHelper:
'Enabling SSL on a non-443 port will cause the 443 port to stop listening. If you need the 443 port to continue listening, please add the domain:443',
global: 'Global', global: 'Global',
subsite: 'Subsite', subsite: 'Subsite',
subsiteHelper: 'A subsite can select an existing PHP or static website directory as the main directory.', subsiteHelper: 'A subsite can select an existing PHP or static website directory as the main directory.',
@@ -3111,6 +3115,7 @@ const message = {
belongToIpGroup: 'Belongs to IP Group', belongToIpGroup: 'Belongs to IP Group',
notBelongToIpGroup: 'Does not belong to IP Group', notBelongToIpGroup: 'Does not belong to IP Group',
unknownWebsiteKey: 'Unknown Domain', unknownWebsiteKey: 'Unknown Domain',
special: 'Special',
}, },
monitor: { monitor: {
name: 'Website Monitoring', name: 'Website Monitoring',
@@ -3381,6 +3386,8 @@ const message = {
nodeCheck: 'Availability check', nodeCheck: 'Availability check',
checkSSH: 'Check node SSH connection', checkSSH: 'Check node SSH connection',
checkUserPermission: 'Check node user permissions',
isNotRoot: 'Detected that password-less sudo is not supported on this node and current user is non-root',
checkLicense: 'Check node license status', checkLicense: 'Check node license status',
checkService: 'Check existing service information on node', checkService: 'Check existing service information on node',
checkPort: 'Check node port reachability', checkPort: 'Check node port reachability',
+13 -4
View File
@@ -861,6 +861,7 @@ const message = {
repo: 'レジストリ', repo: 'レジストリ',
createRepo: '追加', createRepo: '追加',
httpRepoHelper: 'HTTPタイプのリポジトリを操作するにはDockerサービスの再起動が必要です。',
httpRepo: httpRepo:
'HTTPプロトコルを選択するには、Dockerサービスを再起動して不安定なレジストリに追加する必要があります。', 'HTTPプロトコルを選択するには、Dockerサービスを再起動して不安定なレジストリに追加する必要があります。',
delInsecure: 'クレジットの削除', delInsecure: 'クレジットの削除',
@@ -996,9 +997,15 @@ const message = {
saveLocal: 'ローカルバックアップを保持します(クラウドストレージコピーの数と同じ)', saveLocal: 'ローカルバックアップを保持します(クラウドストレージコピーの数と同じ)',
url: 'URLアドレス', url: 'URLアドレス',
targetHelper: 'バックアップアカウントは、パネル設定で維持されます。', targetHelper: 'バックアップアカウントは、パネル設定で維持されます。',
withImageHelper:
'アプリストアのイメージをバックアップしますが、スナップショットファイルのサイズが大きくなります。',
ignoreApp: 'アプリを除外',
withImage: 'すべてのアプリイメージをバックアップ',
retainCopies: '記録を保持します', retainCopies: '記録を保持します',
retryTimes: 'リトライ回数', retryTimes: 'リトライ回数',
timeout: 'タイムアウト', timeout: 'タイムアウト',
ignoreErr: 'エラーを無視',
ignoreErrHelper: 'バックアップ中のエラーを無視し、全てのバックアップタスクを確実に実行します',
retryTimesHelper: '0は失敗後リトライしないことを意味します', retryTimesHelper: '0は失敗後リトライしないことを意味します',
retainCopiesHelper: '実行記録とログのために保持するコピーの数', retainCopiesHelper: '実行記録とログのために保持するコピーの数',
retainCopiesHelper1: 'バックアップファイル用に保持するコピーの数', retainCopiesHelper1: 'バックアップファイル用に保持するコピーの数',
@@ -1411,6 +1418,7 @@ const message = {
existFileHelper: 'アップロードしたファイルに同じ名前のファイルが含まれています。上書きしますか?', existFileHelper: 'アップロードしたファイルに同じ名前のファイルが含まれています。上書きしますか?',
existFileSize: 'ファイルサイズ(新しい -> 古い)', existFileSize: 'ファイルサイズ(新しい -> 古い)',
existFileDirHelper: '選択したファイル/フォルダーには同じ名前のものが既に存在します。慎重に操作してください!', existFileDirHelper: '選択したファイル/フォルダーには同じ名前のものが既に存在します。慎重に操作してください!',
coverDirHelper: '上書きするフォルダを選択すると、対象パスにコピーされます!',
noSuchFile: 'ファイルまたはディレクトリが見つかりませんでした。確認して再試行してください。', noSuchFile: 'ファイルまたはディレクトリが見つかりませんでした。確認して再試行してください。',
setting: '設定', setting: '設定',
showHide: '隠しファイルを表示', showHide: '隠しファイルを表示',
@@ -1743,6 +1751,7 @@ const message = {
systemLog: 'システムログを保持', systemLog: 'システムログを保持',
taskLog: 'タスクログを保持', taskLog: 'タスクログを保持',
monitorData: '監視データを保持', monitorData: '監視データを保持',
dockerConf: 'Docker設定保持',
selectAllImage: 'すべてのアプリイメージをバックアップ', selectAllImage: 'すべてのアプリイメージをバックアップ',
logLabel: 'ログ', logLabel: 'ログ',
agentLabel: 'ノード設定', agentLabel: 'ノード設定',
@@ -2000,8 +2009,6 @@ const message = {
takeDown: '降ろす', takeDown: '降ろす',
allReadyInstalled: 'インストール', allReadyInstalled: 'インストール',
installHelper: '画像プルの問題がある場合は、画像アクセラレーションを構成します。', installHelper: '画像プルの問題がある場合は、画像アクセラレーションを構成します。',
upgradeHelper:
'アップグレードする前に、異常なアプリケーションを通常のステータスに戻します。アップグレードが失敗した場合は、「ログ>システムログ」に移動して、障害の理由を確認します。',
installWarn: `外部アクセスは有効になっていないため、アプリケーションが外部ネットワークを介してアクセスできるようになります。続けたいですか?`, installWarn: `外部アクセスは有効になっていないため、アプリケーションが外部ネットワークを介してアクセスできるようになります。続けたいですか?`,
showIgnore: '無視されたアプリケーションを表示します', showIgnore: '無視されたアプリケーションを表示します',
cancelIgnore: 'キャンセルは無視します', cancelIgnore: 'キャンセルは無視します',
@@ -2331,8 +2338,6 @@ const message = {
enableSSLHelper: 'SSLの有効化に失敗しても、ウェブサイトの作成には影響しません。', enableSSLHelper: 'SSLの有効化に失敗しても、ウェブサイトの作成には影響しません。',
batchAdd: 'ドメインを一括追加', batchAdd: 'ドメインを一括追加',
generateDomain: '生成', generateDomain: '生成',
domainSSLHelper:
'443以外のポートでSSLを有効にすると、443ポートのリスナーが削除されます。443ポートを引き続きリスニングするには、ドメイン:443を追加してください。',
global: 'グローバル', global: 'グローバル',
subsite: 'サブサイト', subsite: 'サブサイト',
subsiteHelper: subsiteHelper:
@@ -2982,6 +2987,7 @@ const message = {
belongToIpGroup: 'IP グループに属しています', belongToIpGroup: 'IP グループに属しています',
notBelongToIpGroup: 'IP グループに属していません', notBelongToIpGroup: 'IP グループに属していません',
unknownWebsiteKey: '未知のドメイン', unknownWebsiteKey: '未知のドメイン',
special: '特別な文字は使用できません',
}, },
monitor: { monitor: {
name: 'ウェブサイトモニタリング', name: 'ウェブサイトモニタリング',
@@ -3249,6 +3255,9 @@ const message = {
nodeCheck: '可用性チェック', nodeCheck: '可用性チェック',
checkSSH: 'ノードSSH接続を確認', checkSSH: 'ノードSSH接続を確認',
checkUserPermission: 'ノードユーザー権限を確認',
isNotRoot:
'このノードではパスワードなしsudoがサポートされておらず、現在のユーザーがrootではないことが検出されました',
checkLicense: 'ノードライセンス状態を確認', checkLicense: 'ノードライセンス状態を確認',
checkService: 'ノードの既存サービス情報を確認', checkService: 'ノードの既存サービス情報を確認',
checkPort: 'ノードポート到達性を確認', checkPort: 'ノードポート到達性を確認',
+12 -4
View File
@@ -852,6 +852,7 @@ const message = {
repo: '레지스트리', repo: '레지스트리',
createRepo: '추가', createRepo: '추가',
httpRepoHelper: 'HTTP 타입 저장소 작업 시 Docker 서비스 재시작이 필요합니다.',
httpRepo: 'HTTP 프로토콜을 선택하면 Docker 서비스를 재시작하여 불안정한 레지스트리에 추가해야 합니다.', httpRepo: 'HTTP 프로토콜을 선택하면 Docker 서비스를 재시작하여 불안정한 레지스트리에 추가해야 합니다.',
delInsecure: '신뢰할 수 없는 항목 삭제', delInsecure: '신뢰할 수 없는 항목 삭제',
delInsecureHelper: delInsecureHelper:
@@ -984,9 +985,14 @@ const message = {
saveLocal: '로컬 백업 보관 (클라우드 저장소 복사본 수와 동일)', saveLocal: '로컬 백업 보관 (클라우드 저장소 복사본 수와 동일)',
url: 'URL 주소', url: 'URL 주소',
targetHelper: '백업 계정은 패널 설정에서 관리됩니다.', targetHelper: '백업 계정은 패널 설정에서 관리됩니다.',
withImageHelper: '앱 스토어 이미지를 백업하지만 스냅샷 파일 크기가 증가합니다.',
ignoreApp: '앱 제외',
withImage: '모든 앱 이미지 백업',
retainCopies: '기록 보관', retainCopies: '기록 보관',
retryTimes: '재시도 횟수', retryTimes: '재시도 횟수',
timeout: '타임아웃', timeout: '타임아웃',
ignoreErr: '오류 무시',
ignoreErrHelper: '백업 과정에서 발생하는 오류를 무시하여 모든 백업 작업이 실행되도록 합니다',
retryTimesHelper: '0은 실패 후 재시도 안 함을 의미합니다', retryTimesHelper: '0은 실패 후 재시도 안 함을 의미합니다',
retainCopiesHelper: '실행 기록과 로그에 대해 보관할 복사본 수', retainCopiesHelper: '실행 기록과 로그에 대해 보관할 복사본 수',
retainCopiesHelper1: '백업 파일에 대해 보관할 복사본 수', retainCopiesHelper1: '백업 파일에 대해 보관할 복사본 수',
@@ -1397,6 +1403,7 @@ const message = {
existFileHelper: '업로드한 파일에 동일한 이름의 파일이 포함되어 있습니다. 덮어쓰시겠습니까?', existFileHelper: '업로드한 파일에 동일한 이름의 파일이 포함되어 있습니다. 덮어쓰시겠습니까?',
existFileSize: '파일 크기 (새로운 -> 오래된)', existFileSize: '파일 크기 (새로운 -> 오래된)',
existFileDirHelper: '선택한 파일/폴더에 동일한 이름이 이미 존재합니다. 신중하게 작업하세요!', existFileDirHelper: '선택한 파일/폴더에 동일한 이름이 이미 존재합니다. 신중하게 작업하세요!',
coverDirHelper: '덮어쓸 폴더를 선택하면 대상 경로로 복사됩니다!',
noSuchFile: '파일 또는 디렉터리를 찾을 수 없습니다. 확인 후 다시 시도하세요.', noSuchFile: '파일 또는 디렉터리를 찾을 수 없습니다. 확인 후 다시 시도하세요.',
setting: '설정', setting: '설정',
showHide: '숨김 파일 표시', showHide: '숨김 파일 표시',
@@ -1717,6 +1724,7 @@ const message = {
systemLog: '시스템 로그 유지', systemLog: '시스템 로그 유지',
taskLog: '작업 로그 유지', taskLog: '작업 로그 유지',
monitorData: '모니터링 데이터 유지', monitorData: '모니터링 데이터 유지',
dockerConf: 'Docker 설정',
selectAllImage: '모든 앱 이미지를 백업', selectAllImage: '모든 앱 이미지를 백업',
logLabel: '로그', logLabel: '로그',
agentLabel: '노드 설정', agentLabel: '노드 설정',
@@ -1967,8 +1975,6 @@ const message = {
takeDown: '내리기', takeDown: '내리기',
allReadyInstalled: '설치됨', allReadyInstalled: '설치됨',
installHelper: '이미지 풀 문제 시 이미지 가속을 구성하세요.', installHelper: '이미지 풀 문제 시 이미지 가속을 구성하세요.',
upgradeHelper:
'업그레이드 전에 비정상적인 애플리케이션을 정상 상태로 복원하세요. 업그레이드 실패 시 "로그 > 시스템 로그"에서 실패 원인을 확인하세요.',
installWarn: installWarn:
'외부 접근이 활성화되지 않아 애플리케이션이 외부 네트워크에서 접근할 수 없습니다. 계속 하시겠습니까?', '외부 접근이 활성화되지 않아 애플리케이션이 외부 네트워크에서 접근할 수 없습니다. 계속 하시겠습니까?',
showIgnore: '무시된 애플리케이션 보기', showIgnore: '무시된 애플리케이션 보기',
@@ -2291,8 +2297,6 @@ const message = {
enableSSLHelper: 'SSL 활성화 실패는 웹사이트 생성에 영향을 미치지 않습니다.', enableSSLHelper: 'SSL 활성화 실패는 웹사이트 생성에 영향을 미치지 않습니다.',
batchAdd: '도메인 일괄 추가', batchAdd: '도메인 일괄 추가',
generateDomain: '생성', generateDomain: '생성',
domainSSLHelper:
'443이 아닌 포트에서 SSL을 활성화하면 443 포트 리스너가 제거됩니다. 443 포트를 계속 리스닝하려면 도메인:443을 추가하세요.',
global: '글로벌', global: '글로벌',
subsite: '하위 사이트', subsite: '하위 사이트',
subsiteHelper: '하위 사이트는 기존 PHP 또는 정적 웹사이트의 디렉토리를 루트 디렉토리로 선택할 수 있습니다.', subsiteHelper: '하위 사이트는 기존 PHP 또는 정적 웹사이트의 디렉토리를 루트 디렉토리로 선택할 수 있습니다.',
@@ -2932,6 +2936,7 @@ const message = {
belongToIpGroup: 'IP 그룹에 속함', belongToIpGroup: 'IP 그룹에 속함',
notBelongToIpGroup: 'IP 그룹에 속하지 않음', notBelongToIpGroup: 'IP 그룹에 속하지 않음',
unknownWebsiteKey: '알 수 없는 도메인', unknownWebsiteKey: '알 수 없는 도메인',
special: '특수 문자',
}, },
monitor: { monitor: {
name: '웹사이트 모니터링', name: '웹사이트 모니터링',
@@ -3192,6 +3197,9 @@ const message = {
nodeCheck: '가용성 확인', nodeCheck: '가용성 확인',
checkSSH: '노드 SSH 연결 확인', checkSSH: '노드 SSH 연결 확인',
checkUserPermission: '노드 사용자 권한 확인',
isNotRoot:
'이 노드에서 비밀번호 없이 sudo를 사용할 수 없으며 현재 사용자가 root가 아닌 것으로 감지되었습니다',
checkLicense: '노드 라이선스 상태 확인', checkLicense: '노드 라이선스 상태 확인',
checkService: '노드의 기존 서비스 정보 확인', checkService: '노드의 기존 서비스 정보 확인',
checkPort: '노드 포트 접근 가능 여부 확인', checkPort: '노드 포트 접근 가능 여부 확인',
+12 -4
View File
@@ -878,6 +878,7 @@ const message = {
repo: 'Pendaftaran', repo: 'Pendaftaran',
createRepo: 'Tambah', createRepo: 'Tambah',
httpRepoHelper: 'Mengoperasikan repositori jenis HTTP memerlukan mulakan semula perkhidmatan Docker.',
httpRepo: httpRepo:
'Memilih protokol HTTP memerlukan memulakan semula perkhidmatan Docker untuk menambahkannya ke pendaftaran tidak selamat.', 'Memilih protokol HTTP memerlukan memulakan semula perkhidmatan Docker untuk menambahkannya ke pendaftaran tidak selamat.',
delInsecure: 'Padamkan pendaftaran tidak selamat', delInsecure: 'Padamkan pendaftaran tidak selamat',
@@ -1018,9 +1019,14 @@ const message = {
saveLocal: 'Simpan sandaran tempatan (sama seperti bilangan salinan storan awan)', saveLocal: 'Simpan sandaran tempatan (sama seperti bilangan salinan storan awan)',
url: 'Alamat URL', url: 'Alamat URL',
targetHelper: 'Akaun sandaran diselenggara dalam tetapan panel.', targetHelper: 'Akaun sandaran diselenggara dalam tetapan panel.',
withImageHelper: 'Sandarkan imej kedai aplikasi, tetapi ini akan meningkatkan saiz fail snapshot.',
ignoreApp: 'Kecualikan aplikasi',
withImage: 'Sandarkan semua imej aplikasi',
retainCopies: 'Simpan salinan', retainCopies: 'Simpan salinan',
retryTimes: 'Bilangan Cubaan Semula', retryTimes: 'Bilangan Cubaan Semula',
timeout: 'Masa Tamat', timeout: 'Masa Tamat',
ignoreErr: 'Abaikan ralat',
ignoreErrHelper: 'Abaikan ralat semasa sandaran untuk memastikan semua tugas sandaran dilaksanakan',
retryTimesHelper: '0 bermaksud tiada cubaan semula selepas gagal', retryTimesHelper: '0 bermaksud tiada cubaan semula selepas gagal',
retainCopiesHelper: 'Bilangan salinan untuk menyimpan rekod pelaksanaan dan log', retainCopiesHelper: 'Bilangan salinan untuk menyimpan rekod pelaksanaan dan log',
retainCopiesHelper1: 'Bilangan salinan untuk menyimpan fail sandaran', retainCopiesHelper1: 'Bilangan salinan untuk menyimpan fail sandaran',
@@ -1453,7 +1459,8 @@ const message = {
existFileTitle: 'Amaran fail dengan nama yang sama', existFileTitle: 'Amaran fail dengan nama yang sama',
existFileHelper: 'Fail yang dimuat naik mengandungi fail dengan nama yang sama. Adakah anda mahu menimpanya?', existFileHelper: 'Fail yang dimuat naik mengandungi fail dengan nama yang sama. Adakah anda mahu menimpanya?',
existFileSize: 'Saiz fail (baru -> lama)', existFileSize: 'Saiz fail (baru -> lama)',
existFileDirHelper: 'Fail/folder yang dipilih mempunyai nama yang sama. Sila berhati-hati!', existFileDirHelper: 'Fail/folder yang dipilih mempunyai nama yang sama. Sila berhati-hati!\n',
coverDirHelper: 'Folder yang dipilih untuk ditimpa akan disalin ke laluan destinasi!',
noSuchFile: 'Fail atau direktori tidak ditemui. Sila periksa dan cuba lagi.', noSuchFile: 'Fail atau direktori tidak ditemui. Sila periksa dan cuba lagi.',
setting: 'tetapan', setting: 'tetapan',
showHide: 'Tunjukkan fail tersembunyi', showHide: 'Tunjukkan fail tersembunyi',
@@ -1800,6 +1807,7 @@ const message = {
systemLog: 'Simpan log sistem', systemLog: 'Simpan log sistem',
taskLog: 'Simpan log tugas', taskLog: 'Simpan log tugas',
monitorData: 'Simpan data pemantauan', monitorData: 'Simpan data pemantauan',
dockerConf: 'Simpan Konfigurasi Docker',
selectAllImage: 'Simpan semua imej aplikasi', selectAllImage: 'Simpan semua imej aplikasi',
logLabel: 'Log', logLabel: 'Log',
agentLabel: 'Konfigurasi Nod', agentLabel: 'Konfigurasi Nod',
@@ -2058,7 +2066,6 @@ const message = {
takeDown: 'Henti Operasi', takeDown: 'Henti Operasi',
allReadyInstalled: 'Telah Dipasang', allReadyInstalled: 'Telah Dipasang',
installHelper: 'Jika terdapat isu tarikan imej, konfigurasikan pecutan imej.', installHelper: 'Jika terdapat isu tarikan imej, konfigurasikan pecutan imej.',
upgradeHelper: 'Bawa aplikasi yang tidak normal kembali ke status normal sebelum meningkatkan.',
installWarn: installWarn:
'Akses luaran tidak diaktifkan, yang menghalang aplikasi daripada diakses melalui rangkaian luaran. Adakah anda mahu meneruskan?', 'Akses luaran tidak diaktifkan, yang menghalang aplikasi daripada diakses melalui rangkaian luaran. Adakah anda mahu meneruskan?',
showIgnore: 'Lihat aplikasi yang diabaikan', showIgnore: 'Lihat aplikasi yang diabaikan',
@@ -2384,8 +2391,6 @@ const message = {
enableSSLHelper: 'Kegagalan mengaktifkan SSL tidak akan menjejaskan penciptaan laman web.', enableSSLHelper: 'Kegagalan mengaktifkan SSL tidak akan menjejaskan penciptaan laman web.',
batchAdd: 'Tambah Domain Secara Batch', batchAdd: 'Tambah Domain Secara Batch',
generateDomain: 'Hasilkan', generateDomain: 'Hasilkan',
domainSSLHelper:
'Mengaktifkan SSL pada port selain 443 akan menghapus pendengar port 443. Untuk terus mendengar port 443, sila tambah domain:443.',
global: 'Global', global: 'Global',
subsite: 'Sublaman', subsite: 'Sublaman',
subsiteHelper: subsiteHelper:
@@ -3047,6 +3052,7 @@ const message = {
belongToIpGroup: 'Tergolong dalam Kumpulan IP', belongToIpGroup: 'Tergolong dalam Kumpulan IP',
notBelongToIpGroup: 'Tidak tergolong dalam Kumpulan IP', notBelongToIpGroup: 'Tidak tergolong dalam Kumpulan IP',
unknownWebsiteKey: 'Domain Tidak Diketahui', unknownWebsiteKey: 'Domain Tidak Diketahui',
special: 'Peraturan Khas',
}, },
monitor: { monitor: {
name: 'Pemantauan Laman Web', name: 'Pemantauan Laman Web',
@@ -3320,6 +3326,8 @@ const message = {
nodeCheck: 'Semakan ketersediaan', nodeCheck: 'Semakan ketersediaan',
checkSSH: 'Periksa sambungan SSH nod', checkSSH: 'Periksa sambungan SSH nod',
checkUserPermission: 'Semak kebenaran pengguna nod',
isNotRoot: 'Dikesan sudo tanpa kata laluan tidak disokong pada nod ini dan pengguna semasa bukan root',
checkLicense: 'Periksa status lesen nod', checkLicense: 'Periksa status lesen nod',
checkService: 'Periksa maklumat perkhidmatan sedia ada pada nod', checkService: 'Periksa maklumat perkhidmatan sedia ada pada nod',
checkPort: 'Periksa kebolehcapaian port nod', checkPort: 'Periksa kebolehcapaian port nod',
+13 -3
View File
@@ -872,6 +872,7 @@ const message = {
repo: 'Registries', repo: 'Registries',
createRepo: 'Adicionar', createRepo: 'Adicionar',
httpRepoHelper: 'Operar um repositório do tipo HTTP requer reinicialização do serviço Docker.',
httpRepo: httpRepo:
'Escolher o protocolo HTTP requer reiniciar o serviço Docker para adicioná-lo a registries inseguros.', 'Escolher o protocolo HTTP requer reiniciar o serviço Docker para adicioná-lo a registries inseguros.',
delInsecure: 'Remover da lista de segurança', delInsecure: 'Remover da lista de segurança',
@@ -1013,9 +1014,15 @@ const message = {
saveLocal: 'Manter backups locais (o mesmo número de cópias na nuvem)', saveLocal: 'Manter backups locais (o mesmo número de cópias na nuvem)',
url: 'Endereço URL', url: 'Endereço URL',
targetHelper: 'As contas de backup são mantidas nas configurações do painel.', targetHelper: 'As contas de backup são mantidas nas configurações do painel.',
withImageHelper:
'Fazer backup das imagens da loja de aplicativos, mas isso aumentará o tamanho do arquivo de snapshot.',
ignoreApp: 'Excluir aplicativos',
withImage: 'Fazer backup de todas as imagens de aplicativos',
retainCopies: 'Manter cópias', retainCopies: 'Manter cópias',
retryTimes: 'Tentativas de Repetição', retryTimes: 'Tentativas de Repetição',
timeout: 'Tempo Limite', timeout: 'Tempo Limite',
ignoreErr: 'Ignorar erros',
ignoreErrHelper: 'Ignorar erros durante o backup para garantir a execução de todas as tarefas de backup',
retryTimesHelper: '0 significa não repetir após falha', retryTimesHelper: '0 significa não repetir após falha',
retainCopiesHelper: 'Número de cópias a serem mantidas para registros de execução e logs', retainCopiesHelper: 'Número de cópias a serem mantidas para registros de execução e logs',
retainCopiesHelper1: 'Número de cópias a serem mantidas para arquivos de backup', retainCopiesHelper1: 'Número de cópias a serem mantidas para arquivos de backup',
@@ -1439,7 +1446,8 @@ const message = {
existFileTitle: 'Aviso de arquivo com o mesmo nome', existFileTitle: 'Aviso de arquivo com o mesmo nome',
existFileHelper: 'O arquivo enviado contém um arquivo com o mesmo nome. Deseja substituí-lo?', existFileHelper: 'O arquivo enviado contém um arquivo com o mesmo nome. Deseja substituí-lo?',
existFileSize: 'Tamanho do arquivo (novo -> antigo)', existFileSize: 'Tamanho do arquivo (novo -> antigo)',
existFileDirHelper: 'O arquivo/pasta selecionado tem um nome duplicado. Por favor, prossiga com cautela!', existFileDirHelper: 'O arquivo/pasta selecionado tem um nome duplicado. Por favor, prossiga com cautela!\n',
coverDirHelper: 'As pastas selecionadas para substituição serão copiadas para o caminho de destino!',
noSuchFile: 'O arquivo ou diretório não foi encontrado. Por favor, verifique e tente novamente.', noSuchFile: 'O arquivo ou diretório não foi encontrado. Por favor, verifique e tente novamente.',
setting: 'configuração', setting: 'configuração',
showHide: 'Mostrar arquivos ocultos', showHide: 'Mostrar arquivos ocultos',
@@ -1784,6 +1792,7 @@ const message = {
systemLog: 'Manter logs do sistema', systemLog: 'Manter logs do sistema',
taskLog: 'Manter logs de tarefas', taskLog: 'Manter logs de tarefas',
monitorData: 'Manter dados de monitoramento', monitorData: 'Manter dados de monitoramento',
dockerConf: 'Manter Configuração do Docker',
selectAllImage: 'Fazer backup de todas as imagens de aplicativos', selectAllImage: 'Fazer backup de todas as imagens de aplicativos',
logLabel: 'Log', logLabel: 'Log',
agentLabel: 'Configuração do Nó', agentLabel: 'Configuração do Nó',
@@ -2381,8 +2390,6 @@ const message = {
enableSSLHelper: 'A falha ao ativar o SSL não afetará a criação do site.', enableSSLHelper: 'A falha ao ativar o SSL não afetará a criação do site.',
batchAdd: 'Adicionar Domínios em Lote', batchAdd: 'Adicionar Domínios em Lote',
generateDomain: 'Gerar', generateDomain: 'Gerar',
domainSSLHelper:
'Ativar o SSL em portas que não sejam a 443 removerá o ouvinte da porta 443. Para manter a porta 443 ouvindo, adicione o domínio:443.',
global: 'Global', global: 'Global',
subsite: 'Subsite', subsite: 'Subsite',
subsiteHelper: subsiteHelper:
@@ -3050,6 +3057,7 @@ const message = {
belongToIpGroup: 'Pertence ao Grupo de IP', belongToIpGroup: 'Pertence ao Grupo de IP',
notBelongToIpGroup: 'Não pertence ao Grupo de IP', notBelongToIpGroup: 'Não pertence ao Grupo de IP',
unknownWebsiteKey: 'Domínio Desconhecido', unknownWebsiteKey: 'Domínio Desconhecido',
special: 'Domínio Especial',
}, },
monitor: { monitor: {
name: 'Monitoramento de Websites', name: 'Monitoramento de Websites',
@@ -3327,6 +3335,8 @@ const message = {
nodeCheck: 'Verificação de disponibilidade', nodeCheck: 'Verificação de disponibilidade',
checkSSH: 'Verificar conexão SSH do nó', checkSSH: 'Verificar conexão SSH do nó',
checkUserPermission: 'Verificar permissões de usuário do nó',
isNotRoot: 'Detectado que sudo sem senha não é suportado neste nó e o usuário atual não é root',
checkLicense: 'Verificar status da licença do nó', checkLicense: 'Verificar status da licença do nó',
checkService: 'Verificar informações de serviço existentes no nó', checkService: 'Verificar informações de serviço existentes no nó',
checkPort: 'Verificar acessibilidade da porta do nó', checkPort: 'Verificar acessibilidade da porta do nó',

Some files were not shown because too many files have changed in this diff Show More