Compare commits

..
86 Commits
Author SHA1 Message Date
CityFun 0128cd3138 Fix: fix issue with element-plus tab style wrong (#9441) 2025-07-07 18:34:00 +08:00
ssongliu 157d3093f8 fix: Update license validation error messages (#9438) 2025-07-07 08:17:50 +00:00
ssongliu 4ca188973e fix: Add rule validation for FTP account creation (#9437) 2025-07-07 06:25:49 +00:00
wanghe-fit2cloud f387d89a45 docs: Optimize README 2025-07-07 12:09:52 +08:00
CityFun 54567db22f Fix: Resolved issue where domain binding failed in MCP due to OpenResty not using 80 port (#9435)
Refs https://github.com/1Panel-dev/1Panel/issues/9431
2025-07-07 04:07:50 +00:00
ssongliu 2bee68dd40 fix: Fix timezone modification reboot exception (#9432)
Refs #9422
2025-07-07 04:05:50 +00:00
CityFun e2b6ea5253 Fix: Resolved unInstall app failed due to run compose down timeout (#9436) 2025-07-07 04:03:49 +00:00
CityFun 9974c5fa20 feat: add DownloadCallBack for install php runtime (#9430) 2025-07-07 03:05:50 +00:00
ssongliu 997b706d8a fix: Fix dashboard refresh exception issue (#9429) 2025-07-07 03:03:49 +00:00
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
176 changed files with 2613 additions and 1416 deletions
+1 -1
View File
@@ -1,3 +1,3 @@
{
"ansible.python.interpreterPath": "/opt/homebrew/bin/python3"
}
}
+1 -1
View File
@@ -125,4 +125,4 @@ enforcement ladder](https://github.com/mozilla/diversity).
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
https://www.contributor-covenant.org/translations.
+1 -1
View File
@@ -296,7 +296,7 @@ func (b *BaseApi) SaveContent(c *gin.Context) {
// @Security ApiKeyAuth
// @Security Timestamp
// @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) {
form, err := c.MultipartForm()
if err != nil {
+4 -4
View File
@@ -98,20 +98,20 @@ func (b *BaseApi) CreateRepo(c *gin.Context) {
// @Tags Container Image-repo
// @Summary Delete image repo
// @Accept json
// @Param request body dto.ImageRepoDelete true "request"
// @Param request body dto.OperateByID true "request"
// @Produce json
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @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) {
var req dto.ImageRepoDelete
var req dto.OperateByID
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := imageRepoService.BatchDelete(req); err != nil {
if err := imageRepoService.Delete(req); err != nil {
helper.InternalServer(c, err)
return
}
+20
View File
@@ -535,3 +535,23 @@ func (b *BaseApi) GetPHPContainerConfig(c *gin.Context) {
}
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"`
User string `json:"user"`
ScriptID uint `json:"scriptID"`
AppID string `json:"appID"`
Website string `json:"website"`
ExclusionRules string `json:"exclusionRules"`
DBType string `json:"dbType"`
DBName string `json:"dbName"`
URL string `json:"url"`
IsDir bool `json:"isDir"`
SourceDir string `json:"sourceDir"`
ScriptID uint `json:"scriptID"`
AppID string `json:"appID"`
Website string `json:"website"`
ExclusionRules string `json:"exclusionRules"`
DBType string `json:"dbType"`
DBName string `json:"dbName"`
URL string `json:"url"`
IsDir bool `json:"isDir"`
SourceDir string `json:"sourceDir"`
SnapshotRule SnapshotRule `json:"snapshotRule"`
SourceAccountIDs string `json:"sourceAccountIDs"`
DownloadAccountID uint `json:"downloadAccountID"`
RetainCopies int `json:"retainCopies" validate:"number,min=1"`
RetryTimes int `json:"retryTimes" validate:"number,min=0"`
Timeout uint `json:"timeout" validate:"number,min=1"`
IgnoreErr bool `json:"ignoreErr"`
Secret string `json:"secret"`
AlertCount uint `json:"alertCount"`
AlertTitle string `json:"alertTitle"`
}
type SnapshotRule struct {
WithImage bool `json:"withImage"`
IgnoreAppIDs []uint `json:"ignoreAppIDs"`
}
type CronjobUpdateStatus struct {
ID uint `json:"id" validate:"required"`
Status string `json:"status" validate:"required"`
@@ -87,18 +94,20 @@ type CronjobInfo struct {
ContainerName string `json:"containerName"`
User string `json:"user"`
ScriptID uint `json:"scriptID"`
AppID string `json:"appID"`
Website string `json:"website"`
ExclusionRules string `json:"exclusionRules"`
DBType string `json:"dbType"`
DBName string `json:"dbName"`
URL string `json:"url"`
IsDir bool `json:"isDir"`
SourceDir string `json:"sourceDir"`
RetainCopies int `json:"retainCopies"`
RetryTimes int `json:"retryTimes"`
Timeout uint `json:"timeout"`
ScriptID uint `json:"scriptID"`
AppID string `json:"appID"`
Website string `json:"website"`
ExclusionRules string `json:"exclusionRules"`
DBType string `json:"dbType"`
DBName string `json:"dbName"`
URL string `json:"url"`
IsDir bool `json:"isDir"`
SourceDir string `json:"sourceDir"`
RetainCopies int `json:"retainCopies"`
RetryTimes int `json:"retryTimes"`
Timeout uint `json:"timeout"`
IgnoreErr bool `json:"ignoreErr"`
SnapshotRule SnapshotRule `json:"snapshotRule"`
SourceAccounts []string `json:"sourceAccounts"`
DownloadAccount string `json:"downloadAccount"`
+4 -4
View File
@@ -6,8 +6,8 @@ type ImageRepoCreate struct {
Name string `json:"name" validate:"required"`
DownloadUrl string `json:"downloadUrl"`
Protocol string `json:"protocol"`
Username string `json:"username" validate:"max=256"`
Password string `json:"password" validate:"max=256"`
Username string `json:"username"`
Password string `json:"password"`
Auth bool `json:"auth"`
}
@@ -15,8 +15,8 @@ type ImageRepoUpdate struct {
ID uint `json:"id"`
DownloadUrl string `json:"downloadUrl"`
Protocol string `json:"protocol"`
Username string `json:"username" validate:"max=256"`
Password string `json:"password" validate:"max=256"`
Username string `json:"username"`
Password string `json:"password"`
Auth bool `json:"auth"`
}
+6 -5
View File
@@ -92,11 +92,12 @@ type FileWget struct {
}
type FileMove struct {
Type string `json:"type" validate:"required"`
OldPaths []string `json:"oldPaths" validate:"required"`
NewPath string `json:"newPath" validate:"required"`
Name string `json:"name"`
Cover bool `json:"cover"`
Type string `json:"type" validate:"required"`
OldPaths []string `json:"oldPaths" validate:"required"`
NewPath string `json:"newPath" validate:"required"`
Name string `json:"name"`
Cover bool `json:"cover"`
CoverPaths []string `json:"coverPaths"`
}
type FileDownload struct {
+26 -17
View File
@@ -12,15 +12,17 @@ type RuntimeSearch struct {
}
type RuntimeCreate struct {
AppDetailID uint `json:"appDetailId"`
Name string `json:"name"`
Params map[string]interface{} `json:"params"`
Resource string `json:"resource"`
Image string `json:"image"`
Type string `json:"type"`
Version string `json:"version"`
Source string `json:"source"`
CodeDir string `json:"codeDir"`
AppDetailID uint `json:"appDetailId"`
Name string `json:"name"`
Resource string `json:"resource"`
Image string `json:"image"`
Type string `json:"type"`
Version string `json:"version"`
Source string `json:"source"`
CodeDir string `json:"codeDir"`
Remark string `json:"remark"`
Params map[string]interface{} `json:"params"`
NodeConfig
}
@@ -53,14 +55,16 @@ type RuntimeDelete struct {
}
type RuntimeUpdate struct {
Name string `json:"name"`
ID uint `json:"id"`
Params map[string]interface{} `json:"params"`
Image string `json:"image"`
Version string `json:"version"`
Rebuild bool `json:"rebuild"`
Source string `json:"source"`
CodeDir string `json:"codeDir"`
Name string `json:"name"`
ID uint `json:"id"`
Image string `json:"image"`
Version string `json:"version"`
Rebuild bool `json:"rebuild"`
Source string `json:"source"`
CodeDir string `json:"codeDir"`
Remark string `json:"remark"`
Params map[string]interface{} `json:"params"`
NodeConfig
}
@@ -131,3 +135,8 @@ type PHPContainerConfig struct {
Environments []Environment `json:"environments"`
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"`
ParentWebsiteID uint `json:"parentWebsiteID"`
SiteDir string `json:"siteDir"`
RuntimeConfig
FtpConfig
DataBaseConfig
+1
View File
@@ -53,6 +53,7 @@ type ExistFileInfo struct {
Path string `json:"path"`
Size int64 `json:"size"`
ModTime time.Time `json:"modTime"`
IsDir bool `json:"isDir"`
}
type UserInfo struct {
+2
View File
@@ -30,6 +30,7 @@ type RuntimeDTO struct {
Volumes []request.Volume `json:"volumes"`
ContainerStatus string `json:"containerStatus"`
Container string `json:"container"`
Remark string `json:"remark"`
}
type PackageScripts struct {
@@ -53,6 +54,7 @@ func NewRuntimeDTO(runtime model.Runtime) RuntimeDTO {
Port: runtime.Port,
Path: runtime.GetPath(),
Container: runtime.ContainerName,
Remark: runtime.Remark,
}
}
-2
View File
@@ -23,8 +23,6 @@ type SettingInfo struct {
AppStoreSyncStatus string `json:"appStoreSyncStatus"`
FileRecycleBin string `json:"fileRecycleBin"`
SnapshotIgnore string `json:"snapshotIgnore"`
}
type SettingUpdate struct {
+10 -5
View File
@@ -23,11 +23,14 @@ type SnapshotCreate struct {
BackupData []DataTree `json:"backupData"`
PanelData []DataTree `json:"panelData"`
WithDockerConf bool `json:"withDockerConf"`
WithMonitorData bool `json:"withMonitorData"`
WithLoginLog bool `json:"withLoginLog"`
WithOperationLog bool `json:"withOperationLog"`
WithSystemLog bool `json:"withSystemLog"`
WithTaskLog bool `json:"withTaskLog"`
IgnoreFiles []string `json:"ignoreFiles"`
}
type SnapshotData struct {
@@ -35,11 +38,13 @@ type SnapshotData struct {
BackupData []DataTree `json:"backupData"`
PanelData []DataTree `json:"panelData"`
WithMonitorData bool `json:"withMonitorData"`
WithLoginLog bool `json:"withLoginLog"`
WithOperationLog bool `json:"withOperationLog"`
WithSystemLog bool `json:"withSystemLog"`
WithTaskLog bool `json:"withTaskLog"`
WithDockerConf bool `json:"withDockerConf"`
WithMonitorData bool `json:"withMonitorData"`
WithLoginLog bool `json:"withLoginLog"`
WithOperationLog bool `json:"withOperationLog"`
WithSystemLog bool `json:"withSystemLog"`
WithTaskLog bool `json:"withTaskLog"`
IgnoreFiles []string `json:"ignoreFiles"`
}
type DataTree struct {
ID string `json:"id"`
+2
View File
@@ -29,12 +29,14 @@ type Cronjob struct {
URL string `json:"url"`
IsDir bool `json:"isDir"`
SourceDir string `json:"sourceDir"`
SnapshotRule string `json:"snapshotRule"`
ExclusionRules string `json:"exclusionRules"`
SourceAccountIDs string `json:"sourceAccountIDs"`
DownloadAccountID uint `json:"downloadAccountID"`
RetryTimes uint `json:"retryTimes"`
Timeout uint `json:"timeout"`
IgnoreErr bool `json:"ignoreErr"`
RetainCopies uint64 `json:"retainCopies"`
Status string `json:"status"`
+1
View File
@@ -23,6 +23,7 @@ type Runtime struct {
Message string `json:"message"`
CodeDir string `json:"codeDir"`
ContainerName string `json:"containerName"`
Remark string `json:"remark"`
}
func (r *Runtime) GetComposePath() string {
+6 -3
View File
@@ -15,14 +15,17 @@ type Snapshot struct {
TaskRecoverID string `json:"taskRecoverID"`
TaskRollbackID string `json:"taskRollbackID"`
AppData string `json:"appData"`
PanelData string `json:"panelData"`
BackupData string `json:"backupData"`
AppData string `json:"appData"`
PanelData string `json:"panelData"`
BackupData string `json:"backupData"`
WithDockerConf bool `json:"withDockerConf"`
WithMonitorData bool `json:"withMonitorData"`
WithLoginLog bool `json:"withLoginLog"`
WithOperationLog bool `json:"withOperationLog"`
WithSystemLog bool `json:"withSystemLog"`
WithTaskLog bool `json:"withTaskLog"`
IgnoreFiles string `json:"ignoreFiles"`
InterruptStep string `json:"interruptStep"`
RecoverStatus string `json:"recoverStatus"`
+19 -19
View File
@@ -4,7 +4,6 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/docker/docker/api/types/container"
"math"
"net/http"
"os"
@@ -15,28 +14,25 @@ import (
"strconv"
"strings"
"github.com/1Panel-dev/1Panel/agent/utils/files"
"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"
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
"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/repo"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/common"
"github.com/1Panel-dev/1Panel/agent/utils/compose"
"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"
"gopkg.in/yaml.v3"
)
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 {
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))
for _, resource := range resources {
linkInstall, _ := appInstallRepo.GetFirst(repo.WithByID(resource.AppInstallId))
res = append(res, dto.AppResource{
Type: "app",
Name: linkInstall.Name,
})
if linkInstall.ID > 0 {
res = append(res, dto.AppResource{
Type: "app",
Name: linkInstall.Name,
})
} else {
_ = appInstallResourceRepo.DeleteBy(context.Background(), appInstallResourceRepo.WithAppInstallId(resource.AppInstallId))
}
}
return res, nil
}
+66 -104
View File
@@ -5,7 +5,6 @@ import (
"encoding/base64"
"encoding/json"
"fmt"
"github.com/compose-spec/compose-go/v2/types"
"log"
"math"
"net/http"
@@ -19,39 +18,33 @@ import (
"strings"
"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/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/request"
"github.com/1Panel-dev/1Panel/agent/app/dto/response"
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/app/task"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/common"
"github.com/1Panel-dev/1Panel/agent/utils/compose"
"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/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/subosito/gotenv"
"gopkg.in/yaml.v3"
)
type DatabaseOp string
@@ -386,21 +379,25 @@ func deleteAppInstall(deleteReq request.AppInstallDelete) error {
}
resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(install.ID))
if deleteReq.DeleteDB && len(resources) > 0 {
del := dto.DelAppLink{
Ctx: ctx,
Install: &install,
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
if len(resources) > 0 {
if deleteReq.DeleteDB {
del := dto.DelAppLink{
Ctx: ctx,
Install: &install,
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.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 {
@@ -489,17 +486,14 @@ func deleteLink(del dto.DelAppLink) error {
return appInstallResourceRepo.DeleteBy(del.Ctx, appInstallResourceRepo.WithAppInstallId(install.ID))
}
func getUpgradeCompose(install model.AppInstall, detail model.AppDetail) (string, error) {
if detail.DockerCompose == "" {
return "", nil
}
func handleUpgradeCompose(install model.AppInstall, detail model.AppDetail) (map[string]interface{}, error) {
composeMap := make(map[string]interface{})
if err := yaml.Unmarshal([]byte(detail.DockerCompose), &composeMap); err != nil {
return "", err
return nil, err
}
value, ok := composeMap["services"]
if !ok || value == nil {
return "", buserr.New("ErrFileParse")
return nil, buserr.New("ErrFileParse")
}
servicesMap := value.(map[string]interface{})
if len(servicesMap) == 1 {
@@ -517,6 +511,34 @@ func getUpgradeCompose(install model.AppInstall, detail model.AppDetail) (string
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{})
if err := json.Unmarshal([]byte(install.Env), &envs); err != nil {
return "", err
@@ -617,7 +639,7 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
if err != nil {
return err
}
dockerCLi, err := docker.NewClient()
dockerCLi, _ := docker.NewClient()
if req.PullImage {
images, err := composeV2.GetDockerComposeImagesV2(content, []byte(detail.DockerCompose))
if err != nil {
@@ -674,63 +696,6 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
}
envParams := make(map[string]string, len(envs))
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 {
return err
}
@@ -1802,10 +1767,7 @@ func ignoreUpdate(installed model.AppInstall) bool {
return true
}
ignores, _ := appIgnoreUpgradeRepo.List(appDetailRepo.WithAppId(installed.AppId), appIgnoreUpgradeRepo.WithScope("all"))
if len(ignores) > 0 {
return true
}
return false
return len(ignores) > 0
}
func RequestDownloadCallBack(downloadCallBackUrl string) {
-2
View File
@@ -290,8 +290,6 @@ func (u *BackupService) RefreshToken(req dto.OperateByID) error {
switch backup.Type {
case constant.OneDrive:
refreshToken, err = client.RefreshToken("refresh_token", "refreshToken", varMap)
case constant.GoogleDrive:
refreshToken, err = client.RefreshGoogleToken("refresh_token", "refreshToken", varMap)
case constant.ALIYUN:
refreshToken, err = client.RefreshALIToken(varMap)
}
+1 -2
View File
@@ -5,7 +5,6 @@ import (
"fmt"
"os"
"path"
"strings"
"sync"
"github.com/1Panel-dev/1Panel/agent/app/dto"
@@ -194,7 +193,7 @@ func (u *BackupRecordService) ListFiles(req dto.OperateByID) []string {
var datas []string
for _, file := range files {
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))
}
}
+1 -4
View File
@@ -639,10 +639,7 @@ func handleAlert(stdout, clamName string, clamId uint) {
EntryID: clamId,
Param: strconv.Itoa(infectedFiles),
}
err := xpack.PushAlert(pushAlert)
if err != nil {
global.LOG.Errorf("clamdscan push failed, err: %v", err)
}
_ = xpack.PushAlert(pushAlert)
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/common"
"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/filters"
"github.com/docker/docker/api/types/image"
@@ -94,8 +94,8 @@ func NewIContainerService() IContainerService {
func (u *ContainerService) Page(req dto.PageContainer) (int64, interface{}, error) {
var (
records []types.Container
list []types.Container
records []container.Summary
list []container.Summary
)
client, err := docker.NewDockerClient()
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
if start > total {
records = make([]types.Container, 0)
records = make([]container.Summary, 0)
} else {
if end >= total {
end = total
@@ -307,7 +307,7 @@ func (u *ContainerService) ContainerListStats() ([]dto.ContainerListStats, error
var wg sync.WaitGroup
wg.Add(len(list))
for i := 0; i < len(list); i++ {
go func(item types.Container) {
go func(item container.Summary) {
datas = append(datas, loadCpuAndMem(client, item.ID))
wg.Done()
}(list[i])
@@ -466,7 +466,7 @@ func (u *ContainerService) Prune(req dto.ContainerPrune) (dto.ContainerPruneRepo
report.DeletedNumber = len(rep.VolumesDeleted)
report.SpaceReclaimed = int(rep.SpaceReclaimed)
case "buildcache":
opts := types.BuildCachePruneOptions{}
opts := build.CachePruneOptions{}
opts.All = true
rep, err := client.BuildCachePrune(context.Background(), opts)
if err != nil {
@@ -915,9 +915,6 @@ func collectLogs(done <-chan struct{}, params dto.StreamLog, messageChan chan<-
defer close(messageChan)
defer close(errorChan)
var cmdArgs []string
if params.Type == "compose" {
cmdArgs = []string{"compose", "-f", params.Compose}
}
cmdArgs = append(cmdArgs, "logs")
if params.Follow {
cmdArgs = append(cmdArgs, "-f")
@@ -932,7 +929,20 @@ func collectLogs(done <-chan struct{}, params dto.StreamLog, messageChan chan<-
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}
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
go func() {
@@ -972,19 +982,30 @@ func collectLogs(done <-chan struct{}, params dto.StreamLog, messageChan chan<-
}
}()
for scanner.Scan() {
message := scanner.Text()
for {
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 {
case messageChan <- message:
case messageChan <- line:
case <-done:
return
}
}
if err = scanner.Err(); err != nil && err != io.EOF {
errorChan <- fmt.Errorf("scanner error: %v", err)
}
_ = dockerCmd.Wait()
}
@@ -1300,7 +1321,7 @@ func checkPortStats(ports []dto.PortHelper) (nat.PortMap, error) {
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 hostConf container.HostConfig
if !isCreate {
@@ -1383,7 +1404,7 @@ func loadConfigInfo(isCreate bool, req dto.ContainerOperate, oldContainer *types
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()
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")
}
func loadVolumeBinds(binds []types.MountPoint) []dto.VolumeHelper {
func loadVolumeBinds(binds []container.MountPoint) []dto.VolumeHelper {
var datas []dto.VolumeHelper
for _, bind := range binds {
var volumeItem dto.VolumeHelper
@@ -1425,13 +1446,13 @@ func loadVolumeBinds(binds []types.MountPoint) []dto.VolumeHelper {
return datas
}
func loadPortByInspect(id string, client *client.Client) ([]types.Port, error) {
container, err := client.ContainerInspect(context.Background(), id)
func loadPortByInspect(id string, client *client.Client) ([]container.Port, error) {
containerItem, err := client.ContainerInspect(context.Background(), id)
if err != nil {
return nil, err
}
var itemPorts []types.Port
for key, val := range container.ContainerJSONBase.HostConfig.PortBindings {
var itemPorts []container.Port
for key, val := range containerItem.ContainerJSONBase.HostConfig.PortBindings {
if !strings.Contains(string(key), "/") {
continue
}
@@ -1440,15 +1461,15 @@ func loadPortByInspect(id string, client *client.Client) ([]types.Port, error) {
for _, itemVal := range val {
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
}
func transPortToStr(ports []types.Port) []string {
func transPortToStr(ports []container.Port) []string {
var (
ipv4Ports []types.Port
ipv6Ports []types.Port
ipv4Ports []container.Port
ipv6Ports []container.Port
)
for _, port := range ports {
if strings.Contains(port.IP, ":") {
@@ -1461,7 +1482,7 @@ func transPortToStr(ports []types.Port) []string {
list2 := simplifyPort(ipv6Ports)
return append(list1, list2...)
}
func simplifyPort(ports []types.Port) []string {
func simplifyPort(ports []container.Port) []string {
var datas []string
if len(ports) == 0 {
return datas
@@ -1557,7 +1578,7 @@ func loadComposeCount(client *client.Client) int {
return len(composeMap)
}
func loadContainerPortForInfo(itemPorts []types.Port) []dto.PortHelper {
func loadContainerPortForInfo(itemPorts []container.Port) []dto.PortHelper {
var exposedPorts []dto.PortHelper
samePortMap := make(map[string]dto.PortHelper)
ports := transPortToStr(itemPorts)
+22
View File
@@ -73,6 +73,9 @@ func (u *CronjobService) SearchWithPage(search dto.PageCronjob) (int64, interfac
} else {
item.AlertCount = 0
}
if cronjob.Type == "snapshot" && len(cronjob.SnapshotRule) != 0 {
_ = json.Unmarshal([]byte(cronjob.SnapshotRule), &item.SnapshotRule)
}
dtoCronjobs = append(dtoCronjobs, item)
}
return total, dtoCronjobs, err
@@ -94,6 +97,9 @@ func (u *CronjobService) LoadInfo(req dto.OperateByID) (*dto.CronjobOperate, err
} else {
item.AlertCount = 0
}
if cronjob.Type == "snapshot" && len(cronjob.SnapshotRule) != 0 {
_ = json.Unmarshal([]byte(cronjob.SnapshotRule), &item.SnapshotRule)
}
return &item, err
}
@@ -279,6 +285,13 @@ func (u *CronjobService) Create(req dto.CronjobOperate) error {
if err := copier.Copy(&cronjob, &req); err != 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" {
backupAccount, err := backupRepo.Get(repo.WithByType(constant.Local))
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 {
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))
if err != nil {
return buserr.New("ErrRecordNotFound")
@@ -412,12 +432,14 @@ func (u *CronjobService) Update(id uint, req dto.CronjobOperate) error {
upMap["db_name"] = req.DBName
upMap["url"] = req.URL
upMap["source_dir"] = req.SourceDir
upMap["snapshot_rule"] = cronjob.SnapshotRule
upMap["source_account_ids"] = req.SourceAccountIDs
upMap["download_account_id"] = req.DownloadAccountID
upMap["retain_copies"] = req.RetainCopies
upMap["retry_times"] = req.RetryTimes
upMap["timeout"] = req.Timeout
upMap["ignore_err"] = req.IgnoreErr
upMap["secret"] = req.Secret
err = cronjobRepo.Update(id, upMap)
if err != nil {
+106 -11
View File
@@ -2,6 +2,7 @@ package service
import (
"context"
"encoding/json"
"fmt"
"os"
"path"
@@ -47,6 +48,7 @@ func (u *CronjobService) handleApp(cronjob model.Cronjob, startTime time.Time, t
return err
}
for _, app := range apps {
retry := 0
taskItem.AddSubTaskWithOps(task.GetTaskName(app.Name, task.TaskBackup, task.TaskScopeCronjob), func(task *task.Task) error {
var record model.BackupRecord
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))
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 {
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))
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)
if err := backupRepo.CreateRecord(&record); err != nil {
@@ -86,6 +99,7 @@ func (u *CronjobService) handleWebsite(cronjob model.Cronjob, startTime time.Tim
return err
}
for _, web := range webs {
retry := 0
taskItem.AddSubTaskWithOps(task.GetTaskName(web.Alias, task.TaskBackup, task.TaskScopeCronjob), func(task *task.Task) error {
var record model.BackupRecord
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))
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))
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)
if err := backupRepo.CreateRecord(&record); err != nil {
@@ -127,6 +152,7 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Ti
return err
}
for _, dbInfo := range dbs {
retry := 0
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 {
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))
if cronjob.DBType == "mysql" || cronjob.DBType == "mariadb" {
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 {
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))
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)
if err := backupRepo.CreateRecord(&record); err != nil {
@@ -250,10 +293,6 @@ func (u *CronjobService) handleSnapshot(cronjob model.Cronjob, jobRecord model.J
if err != nil {
return err
}
itemData, err := NewISnapshotService().LoadSnapshotData()
if err != nil {
return err
}
var record model.BackupRecord
record.From = "cronjob"
@@ -268,6 +307,11 @@ func (u *CronjobService) handleSnapshot(cronjob model.Cronjob, jobRecord model.J
if !global.IsMaster {
scope = "agent"
}
itemData, err := loadSnapWithRule(cronjob)
if err != nil {
return err
}
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)),
Secret: cronjob.Secret,
@@ -278,11 +322,13 @@ func (u *CronjobService) handleSnapshot(cronjob model.Cronjob, jobRecord model.J
AppData: itemData.AppData,
PanelData: itemData.PanelData,
BackupData: itemData.BackupData,
WithDockerConf: true,
WithMonitorData: true,
WithLoginLog: true,
WithOperationLog: true,
WithSystemLog: true,
WithTaskLog: true,
IgnoreFiles: strings.Split(cronjob.ExclusionRules, ","),
}
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
}
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+"/")
for _, account := range accounts {
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))
task.LogWithStatus(
i18n.GetMsgWithMap("UploadFile", map[string]interface{}{
@@ -355,9 +359,5 @@ func handleCronJobAlert(cronjob *model.Cronjob) {
EntryID: cronjob.ID,
Param: cronjob.Type,
}
err := xpack.PushAlert(pushAlert)
if err != nil {
global.LOG.Errorf("cronjob alert push failed, err: %v", err)
return
}
_ = xpack.PushAlert(pushAlert)
}
+2 -2
View File
@@ -390,10 +390,10 @@ type diskInfo struct {
func loadDiskInfo() []dto.DiskInfo {
var datas []dto.DiskInfo
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 {
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 {
return datas
}
+1 -1
View File
@@ -120,7 +120,7 @@ func (u *DeviceService) Update(key, value string) error {
if err := ntp.UpdateSystemTimeZone(value); err != nil {
return err
}
go common.RestartService(true, true, false)
go common.RestartService(global.IsMaster, true, false)
case "DNS":
if err := updateDNS(strings.Split(value, ",")); err != nil {
return err
+2 -1
View File
@@ -13,6 +13,7 @@ import (
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/utils/docker"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/build"
"github.com/docker/docker/api/types/filters"
"github.com/1Panel-dev/1Panel/agent/app/dto"
@@ -663,7 +664,7 @@ func dropBuildCache() {
if err != nil {
global.LOG.Errorf("do not get docker client")
}
opts := types.BuildCachePruneOptions{}
opts := build.CachePruneOptions{}
opts.All = true
_, err = client.BuildCachePrune(context.Background(), opts)
if err != nil {
-27
View File
@@ -220,16 +220,6 @@ func (u *DockerService) UpdateConf(req dto.SettingUpdate, withRestart bool) erro
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")
if err != nil {
return err
@@ -277,11 +267,6 @@ func (u *DockerService) UpdateLogOption(req dto.LogOption) error {
_ = json.Unmarshal(file, &daemonMap)
changeLogOption(daemonMap, req.LogMaxFile, req.LogMaxSize)
if len(daemonMap) == 0 {
_ = os.Remove(constant.DaemonJsonPath)
_ = restartDocker()
return nil
}
newJson, err := json.MarshalIndent(daemonMap, "", "\t")
if err != nil {
return err
@@ -321,11 +306,6 @@ func (u *DockerService) UpdateIpv6Option(req dto.Ipv6Option) error {
if req.Experimental {
daemonMap["experimental"] = req.Experimental
}
if len(daemonMap) == 0 {
_ = os.Remove(constant.DaemonJsonPath)
_ = restartDocker()
return nil
}
newJson, err := json.MarshalIndent(daemonMap, "", "\t")
if err != nil {
return err
@@ -345,13 +325,6 @@ func (u *DockerService) UpdateIpv6Option(req dto.Ipv6Option) 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()
if err != nil {
return err
+28 -15
View File
@@ -4,7 +4,10 @@ import (
"bufio"
"context"
"fmt"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/jinzhu/copier"
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/simplifiedchinese"
"io"
"io/fs"
"os"
@@ -15,9 +18,6 @@ import (
"strconv"
"strings"
"time"
"unicode/utf8"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/repo"
@@ -27,7 +27,6 @@ import (
"github.com/1Panel-dev/1Panel/agent/constant"
"golang.org/x/net/html/charset"
"golang.org/x/sys/unix"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
"github.com/1Panel-dev/1Panel/agent/global"
@@ -335,17 +334,22 @@ func (f *FileService) GetContent(op request.FileContentReq) (response.FileInfo,
if len(content) > 1024 {
content = content[:1024]
}
if !utf8.Valid(content) {
_, decodeName, _ := charset.DetermineEncoding(content, "")
if decodeName == "windows-1252" || strings.ToLower(decodeName) == "gbk" {
reader := strings.NewReader(info.Content)
item := transform.NewReader(reader, simplifiedchinese.GBK.NewDecoder())
contents, err := io.ReadAll(item)
if err != nil {
return response.FileInfo{}, err
}
info.Content = string(contents)
_, decodeName, _ := charset.DetermineEncoding(content, "")
decoder := files.GetDecoderByName(decodeName)
if decoder != nil {
reader := strings.NewReader(info.Content)
var dec *encoding.Decoder
if decodeName == "windows-1252" {
dec = simplifiedchinese.GBK.NewDecoder()
} else {
dec = decoder.NewDecoder()
}
decodedReader := transform.NewReader(reader, dec)
contents, err := io.ReadAll(decodedReader)
if err != nil {
return response.FileInfo{}, err
}
info.Content = string(contents)
}
return response.FileInfo{FileInfo: *info}, nil
}
@@ -390,10 +394,18 @@ func (f *FileService) MvFile(m request.FileMove) error {
return buserr.New("ErrMovePathFailed")
}
}
var errs []error
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)
}
var errs []error
if m.Type == "copy" {
for _, src := range m.OldPaths {
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(),
Path: filePath,
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()
output = string(out)
}
if containerName == "" && err != nil {
if output == "" && err != nil {
return err
}
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/i18n"
"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/image"
"github.com/docker/docker/api/types/registry"
@@ -189,7 +189,7 @@ func (u *ImageService) ImageBuild(req dto.ImageBuild) error {
return err
}
opts := types.ImageBuildOptions{
opts := build.ImageBuildOptions{
Dockerfile: fileName,
Tags: []string{req.Name},
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 {
if container.ImageID == imageID {
return true
+69 -43
View File
@@ -28,7 +28,7 @@ type IImageRepoService interface {
Login(req dto.OperateByID) error
Create(req dto.ImageRepoCreate) error
Update(req dto.ImageRepoUpdate) error
BatchDelete(req dto.ImageRepoDelete) error
Delete(req dto.OperateByID) error
}
func NewIImageRepoService() IImageRepoService {
@@ -91,28 +91,7 @@ func (u *ImageRepoService) Create(req dto.ImageRepoCreate) error {
if err := u.handleRegistries(req.DownloadUrl, "", "create"); err != nil {
return fmt.Errorf("create registry %s failed, err: %v", req.DownloadUrl, 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*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 {
if err := stopBeforeUpdateRepo(); err != nil {
return err
}
}
@@ -131,15 +110,32 @@ func (u *ImageRepoService) Create(req dto.ImageRepoCreate) error {
return imageRepoRepo.Create(&imageRepo)
}
func (u *ImageRepoService) BatchDelete(req dto.ImageRepoDelete) error {
for _, id := range req.Ids {
if id == 1 {
return errors.New("The default value cannot be edit !")
}
func (u *ImageRepoService) Delete(req dto.OperateByID) error {
if req.ID == 1 {
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
}
if err := imageRepoRepo.Delete(repo.WithByID(req.ID)); err != nil {
return err
}
go func() {
_ = restartDocker()
}()
return nil
}
@@ -154,38 +150,37 @@ func (u *ImageRepoService) Update(req dto.ImageRepoUpdate) error {
if err != nil {
return err
}
needRestart := false
if repo.Protocol == "http" && req.Protocol == "https" {
if err := u.handleRegistries("", repo.DownloadUrl, "delete"); err != nil {
return fmt.Errorf("delete registry %s failed, err: %v", repo.DownloadUrl, err)
}
needRestart = true
}
if repo.Protocol == "http" && req.Protocol == "http" {
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)
}
needRestart = repo.DownloadUrl == req.DownloadUrl
}
if repo.Protocol == "https" && req.Protocol == "http" {
if err := u.handleRegistries(req.DownloadUrl, "", "create"); err != nil {
return fmt.Errorf("create registry %s failed, err: %v", req.DownloadUrl, err)
}
needRestart = true
}
if repo.Auth != req.Auth || repo.DownloadUrl != req.DownloadUrl {
if repo.Auth {
cmdMgr := cmd.NewCommandMgr()
_, _ = 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 needRestart {
if err := stopBeforeUpdateRepo(); err != nil {
return err
}
}
if err := validateDockerConfig(); err != nil {
return err
if repo.Auth {
_, _ = cmd.NewCommandMgr().RunWithStdout("docker", "logout", "-i", repo.DownloadUrl)
}
if err := restartDocker(); err != nil {
return err
if req.Auth {
if err := u.CheckConn(req.DownloadUrl, req.Username, req.Password); err != nil {
return err
}
}
upMap := make(map[string]interface{})
@@ -260,3 +255,34 @@ func (u *ImageRepoService) handleRegistries(newHost, delHost, handle string) err
}
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
}
+10 -2
View File
@@ -283,11 +283,19 @@ func (m McpServerService) BindDomain(req request.McpBindDomain) error {
}
}
group, _ := groupRepo.Get(groupRepo.WithByWebsiteDefault())
domain, err := ParseDomain(req.Domain)
if err != nil {
return err
}
if domain.Port == 0 {
domain.Port = nginxInstall.HttpPort
}
createWebsiteReq := request.WebsiteCreate{
Domains: []request.WebsiteDomain{
{
Domain: req.Domain,
Port: 80,
Domain: domain.Domain,
Port: domain.Port,
},
},
Alias: strings.ToLower(req.Domain),
+32 -17
View File
@@ -52,6 +52,7 @@ type IRuntimeService interface {
SyncForRestart() error
SyncRuntimeStatus() error
DeleteCheck(installID uint) ([]dto.AppResource, error)
UpdateRemark(req request.RuntimeRemark) error
GetPHPExtensions(runtimeID uint) (response.PHPExtensionRes, error)
InstallPHPExtension(req request.PHPExtensionInstallReq) error
@@ -108,6 +109,7 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (*model.Runtime, e
Type: create.Type,
Version: create.Version,
Status: constant.StatusNormal,
Remark: create.Remark,
}
return nil, runtimeRepo.Create(context.Background(), runtime)
}
@@ -168,6 +170,7 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (*model.Runtime, e
Version: create.Version,
ContainerName: containerName.(string),
Port: strings.Join(hostPorts, ","),
Remark: create.Remark,
}
switch create.Type {
@@ -454,6 +457,7 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error {
Params: req.Params,
CodeDir: req.CodeDir,
Version: req.Version,
Remark: req.Remark,
NodeConfig: request.NodeConfig{
Install: true,
ExposedPorts: req.ExposedPorts,
@@ -465,6 +469,7 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error {
if err != nil {
return err
}
runtime.Remark = req.Remark
runtime.Env = string(envContent)
runtime.DockerCompose = string(composeContent)
@@ -719,25 +724,27 @@ func (r *RuntimeService) InstallPHPExtension(req request.PHPExtensionInstallReq)
return err
}
client, err := docker.NewClient()
if err != nil {
return err
}
defer client.Close()
if err == nil {
oldImageID, err := client.GetImageIDByName(runtime.Image)
if err != nil {
return err
}
err = cmdMgr.RunBashCf("docker commit %s %s", runtime.ContainerName, runtime.Image)
if err != nil {
return err
}
newImageID, err := client.GetImageIDByName(runtime.Image)
if err == nil && newImageID != oldImageID {
if err := client.DeleteImage(oldImageID); err != nil {
t.Log(fmt.Sprintf("delete old image error %v", err))
} else {
t.Log("delete old image success")
}
oldImageID, err := client.GetImageIDByName(runtime.Image)
if err != nil {
return err
}
err = cmdMgr.RunBashCf("docker commit %s %s", runtime.ContainerName, runtime.Image)
if err != nil {
return err
}
newImageID, err := client.GetImageIDByName(runtime.Image)
if err == nil && newImageID != oldImageID {
if err := client.DeleteImage(oldImageID); err != nil {
t.Log(fmt.Sprintf("delete old image error %v", err))
} else {
t.Log("delete old image success")
}
}
handlePHPDir(*runtime)
if err = restartRuntime(runtime); err != nil {
return err
}
@@ -887,7 +894,6 @@ func (r *RuntimeService) UpdatePHPConfig(req request.PHPConfigUpdate) (err error
pattern := "^" + regexp.QuoteMeta("disable_functions") + "\\s*=\\s*.*$"
if matched, _ := regexp.MatchString(pattern, line); matched {
lines[i] = "disable_functions" + " = " + strings.Join(req.DisableFunctions, ",")
break
}
case "upload_max_filesize":
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))
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)
}
+87 -10
View File
@@ -6,7 +6,6 @@ import (
"context"
"encoding/json"
"fmt"
cmd2 "github.com/1Panel-dev/1Panel/agent/utils/cmd"
"io"
"os"
"os/exec"
@@ -17,6 +16,8 @@ import (
"strings"
"time"
cmd2 "github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/i18n"
"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"]
if ok {
extensionsDir := path.Join(projectDir, "extensions", getExtensionDir(version.(string)))
_ = fileOp.CreateDir(extensionsDir, 0644)
_ = fileOp.CreateDir(extensionsDir, 0755)
}
composeContent, envContent, forms, err := handleParams(create, projectDir)
@@ -101,6 +102,13 @@ func handlePHP(create request.RuntimeCreate, runtime *model.Runtime, fileOp file
runtime.Params = string(forms)
runtime.Status = constant.StatusBuilding
go func() {
appDetail, err := appDetailRepo.GetFirst(repo.WithByID(runtime.AppDetailID))
if err == nil {
RequestDownloadCallBack(appDetail.DownloadCallBackUrl)
}
}()
go buildRuntime(runtime, "", "", false)
return
}
@@ -141,11 +149,27 @@ func reCreateRuntime(runtime *model.Runtime) {
}
}
func runComposeCmdWithLog(operate string, composePath string, logPath string) error {
cmd := exec.Command("docker", "compose", "-f", composePath, operate)
if operate == "up" {
cmd = exec.Command("docker", "compose", "-f", composePath, operate, "-d")
func getComposeCmd(composePath, operate string) *exec.Cmd {
dockerCommand := global.CONF.DockerConfig.Command
var cmd *exec.Cmd
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)
if err != nil {
global.LOG.Errorf("Failed to open log file: %v", err)
@@ -287,10 +311,22 @@ func buildRuntime(runtime *model.Runtime, oldImageID string, oldEnv string, rebu
_ = 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)
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
var stderrBuf bytes.Buffer
multiWriterStderr := io.MultiWriter(&stderrBuf, logFile)
@@ -373,6 +409,7 @@ func buildRuntime(runtime *model.Runtime, oldImageID string, oldEnv string, rebu
if deleteImageID != "" {
deleteImageByID(deleteImageID, runtime.Image, client)
}
handlePHPDir(*runtime)
if out, err := compose.DownAndUp(composePath); err != nil {
runtime.Status = constant.StatusStartErr
runtime.Message = out
@@ -553,7 +590,7 @@ func handleCompose(env gotenv.Env, composeContent []byte, create request.Runtime
serviceName = name
serviceValue = service.(map[string]interface{})
delete(serviceValue, "ports")
if create.ExposedPorts != nil && len(create.ExposedPorts) > 0 {
if len(create.ExposedPorts) > 0 {
var ports []interface{}
for i, port := range create.ExposedPorts {
containerPortStr := fmt.Sprintf("CONTAINER_PORT_%d", i)
@@ -567,12 +604,12 @@ func handleCompose(env gotenv.Env, composeContent []byte, create request.Runtime
create.Params[hostIPStr] = port.HostIP
}
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
} else {
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{}
@@ -959,3 +996,43 @@ func handleRuntimeDTO(res *response.RuntimeDTO, runtime model.Runtime) error {
}
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 {
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)
}
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 {
shortName := strings.TrimPrefix(snap, "snapshot_")
nameItems := strings.Split(shortName, "-")
if !strings.HasPrefix(shortName, "1panel-v") || !strings.HasSuffix(shortName, ".tar.gz") || len(nameItems) < 3 {
return fmt.Errorf("incorrect snapshot name format of %s", shortName)
}
shortName := strings.ReplaceAll(snap, "snapshot-", "")
shortName = strings.ReplaceAll(shortName, "1panel-", "")
shortName = strings.ReplaceAll(shortName, "core-", "")
shortName = strings.ReplaceAll(shortName, "agent-", "")
nameItems := strings.Split(shortName, "-linux")
if strings.HasSuffix(snap, ".tar.gz") {
snap = strings.ReplaceAll(snap, ".tar.gz", "")
}
@@ -89,7 +89,7 @@ func (u *SnapshotService) SnapshotImport(req dto.SnapshotImport) error {
Name: snap,
SourceAccountIDs: fmt.Sprintf("%v", req.BackupAccountID),
DownloadAccountID: req.BackupAccountID,
Version: nameItems[1],
Version: nameItems[0],
Description: req.Description,
Status: constant.StatusSuccess,
}
@@ -110,6 +110,7 @@ func (u *SnapshotService) LoadSnapshotData() (dto.SnapshotData, error) {
if err != nil {
return data, err
}
data.WithDockerConf = true
data.PanelData, err = loadPanelFile(fileOp)
if err != nil {
return data, err
@@ -403,3 +404,13 @@ func loadFile(pathItem string, index int, fileOp fileUtils.FileOp) ([]dto.DataTr
}
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"
"os"
"path"
"path/filepath"
"strings"
"sync"
"time"
@@ -34,7 +35,7 @@ func (u *SnapshotService) SnapshotCreate(parentTask *task.Task, req dto.Snapshot
scope = "agent"
}
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)
panelItem, _ := json.Marshal(req.PanelData)
@@ -50,11 +51,13 @@ func (u *SnapshotService) SnapshotCreate(parentTask *task.Task, req dto.Snapshot
AppData: string(appItem),
PanelData: string(panelItem),
BackupData: string(backupItem),
WithDockerConf: req.WithDockerConf,
WithMonitorData: req.WithMonitorData,
WithLoginLog: req.WithLoginLog,
WithOperationLog: req.WithOperationLog,
WithTaskLog: req.WithTaskLog,
WithSystemLog: req.WithSystemLog,
IgnoreFiles: strings.Join(req.IgnoreFiles, ","),
Version: versionItem.Value,
Status: constant.StatusWaiting,
@@ -106,13 +109,14 @@ func (u *SnapshotService) SnapshotReCreate(id uint) error {
return err
}
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 {
global.LOG.Errorf("new task for create snapshot failed, err: %v", err)
return err
}
_ = snapshotRepo.Update(req.ID, map[string]interface{}{"status": constant.StatusWaiting, "message": ""})
go func() {
_ = handleSnapshot(req, taskItem, 0, 0, 0)
_ = handleSnapshot(req, taskItem, 0, 3, 0)
}()
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" {
taskItem.AddSubTaskWithAliasAndOps(
"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,
)
req.InterruptStep = ""
@@ -233,6 +237,7 @@ func loadDbConn(snap *snapHelper, targetDir string, req dto.SnapshotCreate) erro
if err != nil {
return err
}
_ = os.Remove(path.Join(targetDir, "db/session.db"))
agentDb, err := common.LoadDBConnByPathWithErr(path.Join(targetDir, "db/agent.db"), "agent.db")
snap.Task.LogWithStatus(i18n.GetWithName("SnapNewDB", "agent"), err)
@@ -284,7 +289,7 @@ func loadDbConn(snap *snapHelper, targetDir string, req dto.SnapshotCreate) erro
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.LogStart(i18n.GetMsgByKey("SnapBaseInfo"))
@@ -321,11 +326,13 @@ func snapBaseData(snap snapHelper, targetDir string) error {
return err
}
if snap.FileOp.Stat("/etc/docker/daemon.json") {
err = snap.FileOp.CopyFile("/etc/docker/daemon.json", targetDir)
snap.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/etc/docker/daemon.json"), err)
if err != nil {
return err
if withDockerConf {
if snap.FileOp.Stat(constant.DaemonJsonPath) {
err = snap.FileOp.CopyFile(constant.DaemonJsonPath, targetDir)
snap.Task.LogWithStatus(i18n.GetWithName("SnapCopy", constant.DaemonJsonPath), 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 {
snap.Task.Log(strings.Join(imageList, " "))
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"))
if err != nil {
@@ -386,6 +393,8 @@ func snapAppImage(snap snapHelper, req dto.SnapshotCreate, targetDir string) err
return errors.New(std)
}
snap.Task.LogSuccess(i18n.GetMsgByKey("SnapDockerSave"))
} else {
snap.Task.Log(i18n.GetMsgByKey("SnapInstallAppImageEmpty"))
}
return nil
}
@@ -395,6 +404,7 @@ func snapBackupData(snap snapHelper, req dto.SnapshotCreate, targetDir string) e
snap.Task.LogStart(i18n.GetMsgByKey("SnapLocalBackup"))
excludes := loadBackupExcludes(snap, req.BackupData)
excludes = append(excludes, req.IgnoreFiles...)
excludes = append(excludes, "./system_snapshot")
for _, item := range req.AppData {
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 {
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 {
excludes = append(excludes, loadBackupExcludes(snap, item.Children)...)
}
@@ -430,7 +441,8 @@ func loadAppBackupExcludes(req []dto.DataTree) []string {
for _, item := range req {
if len(item.Children) == 0 {
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 {
excludes = append(excludes, loadAppBackupExcludes(item.Children)...)
@@ -463,26 +475,21 @@ func snapPanelData(snap snapHelper, req dto.SnapshotCreate, targetDir string) er
rootDir := global.Dir.DataDir
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) {
excludes = append(excludes, "."+strings.ReplaceAll(snap.OpenrestyDir, rootDir, ""))
}
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, ""))
itemDir, _ := filepath.Rel(rootDir, snap.OpenrestyDir)
excludes = append(excludes, itemDir)
}
excludes = append(excludes, req.IgnoreFiles...)
err := snap.FileOp.TarGzCompressPro(false, rootDir, path.Join(targetDir, "1panel_data.tar.gz"), "", strings.Join(excludes, ","))
snap.Task.LogWithStatus(i18n.GetMsgByKey("SnapCompressPanel"), err)
if err != nil {
return err
}
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)
if err != nil {
return err
@@ -496,7 +503,8 @@ func loadPanelExcludes(req []dto.DataTree) []string {
for _, item := range req {
if len(item.Children) == 0 {
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 {
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})
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 {
req.IsNew = true
}
@@ -55,7 +67,13 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
} else {
_ = 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 {
global.LOG.Errorf("new task for create snapshot failed, err: %v", err)
return err
@@ -84,7 +102,7 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
taskItem.AddSubTaskWithAlias(
"RecoverDecompress",
func(t *task.Task) error {
itemHelper.Task.Log("---------------------- 2 / 10 ----------------------")
itemHelper.Task.Log("---------------------- 2 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetWithName("RecoverDecompress", snap.Name))
err := itemHelper.FileOp.TarGzExtractPro(fmt.Sprintf("%s/%s.tar.gz", rootDir, snap.Name), rootDir, req.Secret)
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("Decompress"), err)
@@ -140,7 +158,7 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
taskItem.AddSubTaskWithAlias(
"RecoverBackups",
func(t *task.Task) error {
itemHelper.Task.Log("---------------------- 8 / 10 ----------------------")
itemHelper.Task.Log("---------------------- 8 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetWithName("RecoverBackups", snap.Name))
err := itemHelper.FileOp.TarGzExtractPro(path.Join(rootDir, snap.Name, "/1panel_backup.tar.gz"), snapJson.BackupDataDir, "")
itemHelper.Task.LogWithStatus(i18n.GetMsgByKey("Decompress"), err)
@@ -150,11 +168,29 @@ func (u *SnapshotService) SnapshotRecover(req dto.SnapshotRecover) error {
)
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" {
taskItem.AddSubTaskWithAlias(
"RecoverPanelData",
func(t *task.Task) error {
itemHelper.Task.Log("---------------------- 9 / 10 ----------------------")
itemHelper.Task.Log("---------------------- 10 / 11 ----------------------")
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"), "")
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 {
itemHelper.Task.Log("---------------------- 1 / 10 ----------------------")
itemHelper.Task.Log("---------------------- 1 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetMsgByKey("RecoverDownload"))
account, client, err := NewBackupClientWithID(snap.DownloadAccountID)
@@ -214,7 +250,7 @@ func handleDownloadSnapshot(itemHelper *snapRecoverHelper, snap model.Snapshot,
}
func backupBeforeRecover(name string, itemHelper *snapRecoverHelper) error {
itemHelper.Task.Log("---------------------- 3 / 10 ----------------------")
itemHelper.Task.Log("---------------------- 3 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetMsgByKey("BackupBeforeRecover"))
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 {
return err
}
if itemHelper.FileOp.Stat("/etc/docker/daemon.json") {
err = itemHelper.FileOp.CopyFile("/etc/docker/daemon.json", baseDir)
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", "/etc/docker/daemon.json"), err)
if itemHelper.FileOp.Stat(constant.DaemonJsonPath) {
err = itemHelper.FileOp.CopyFile(constant.DaemonJsonPath, baseDir)
itemHelper.Task.LogWithStatus(i18n.GetWithName("SnapCopy", constant.DaemonJsonPath), err)
if err != nil {
return err
}
@@ -284,7 +320,7 @@ func backupBeforeRecover(name string, itemHelper *snapRecoverHelper) 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"))
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 {
itemHelper.Task.Log("---------------------- 5 / 10 ----------------------")
itemHelper.Task.Log("---------------------- 5 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetMsgByKey("RecoverApp"))
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 {
itemHelper.Task.Log("---------------------- 6 / 10 ----------------------")
itemHelper.Task.Log("---------------------- 6 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetMsgByKey("SnapBaseInfo"))
if global.IsMaster {
@@ -356,15 +392,11 @@ func recoverBaseData(src string, itemHelper *snapRecoverHelper) error {
return err
}
daemonJsonPath := "/etc/docker/daemon.json"
_, errSrc := os.Stat(path.Join(src, "docker/daemon.json"))
_, errPath := os.Stat(daemonJsonPath)
if os.IsNotExist(errSrc) && os.IsNotExist(errPath) {
if !itemHelper.FileOp.Stat(path.Join(src, "daemon.json")) {
itemHelper.Task.Log(i18n.GetMsgByKey("RecoverDaemonJsonEmpty"))
return nil
}
if errSrc == nil {
err = itemHelper.FileOp.CopyFile(path.Join(src, "docker/daemon.json"), "/etc/docker")
} else {
err = itemHelper.FileOp.CopyFile(path.Join(src, "daemon.json"), path.Dir(constant.DaemonJsonPath))
itemHelper.Task.Log(i18n.GetMsgByKey("RecoverDaemonJson"))
if err != nil {
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 {
itemHelper.Task.Log("---------------------- 7 / 10 ----------------------")
itemHelper.Task.Log("---------------------- 7 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetMsgByKey("RecoverDBData"))
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 {
itemHelper.Task.Log("---------------------- 10 / 10 ----------------------")
itemHelper.Task.Log("---------------------- 11 / 11 ----------------------")
itemHelper.Task.LogStart(i18n.GetMsgByKey("RecoverCompose"))
composes, err := composeRepo.ListRecord()
+5 -2
View File
@@ -76,9 +76,12 @@ func (u *SnapshotService) SnapshotRollback(req dto.SnapshotRecover) error {
nil,
)
taskItem.AddSubTask(
i18n.GetWithName("SnapCopy", "/etc/docker/daemon.json"),
i18n.GetWithName("SnapCopy", constant.DaemonJsonPath),
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,
)
+20 -26
View File
@@ -415,6 +415,7 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error)
return err
}
website.ParentWebsiteID = parentWebsite.ID
website.SiteDir = create.SiteDir
}
configNginx := func(t *task.Task) error {
@@ -922,18 +923,12 @@ func (w WebsiteService) GetWebsiteHTTPS(websiteId uint) (response.WebsiteHTTPS,
res response.WebsiteHTTPS
httpsPorts []string
)
websiteDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(websiteId))
for _, domain := range websiteDomains {
if domain.SSL {
httpsPorts = append(httpsPorts, strconv.Itoa(domain.Port))
}
}
if len(httpsPorts) == 0 {
nginxInstall, _ := getAppInstallByKey(constant.AppOpenresty)
res.HttpsPort = strconv.Itoa(nginxInstall.HttpsPort)
} else {
res.HttpsPort = strings.Join(httpsPorts, ",")
httpsPortsMap := getHttpsPort(websiteId)
for port := range httpsPortsMap {
httpsPorts = append(httpsPorts, strconv.Itoa(port))
}
res.HttpsPort = strings.Join(httpsPorts, ",")
if website.WebsiteSSLID == 0 {
res.Enable = false
return res, nil
@@ -981,10 +976,6 @@ func (w WebsiteService) OpWebsiteHTTPS(ctx context.Context, req request.WebsiteH
res response.WebsiteHTTPS
websiteSSL model.WebsiteSSL
)
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
if err != nil {
return nil, err
}
if err = ChangeHSTSConfig(req.Hsts, req.Http3, website); err != nil {
return nil, err
}
@@ -995,24 +986,27 @@ func (w WebsiteService) OpWebsiteHTTPS(ctx context.Context, req request.WebsiteH
website.Protocol = constant.ProtocolHTTP
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 {
return nil, err
}
if len(httpsPorts) == 1 && httpsPorts[0] == nginxInstall.HttpsPort {
httpsPortStr := strconv.Itoa(httpsPorts[0])
if _, ok := ports[nginxInstall.HttpsPort]; !ok {
httpsPortStr := strconv.Itoa(nginxInstall.HttpsPort)
if err = deleteListenAndServerName(website, []string{httpsPortStr, "[::]:" + httpsPortStr}, []string{}); err != nil {
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 = append(nginxParams,
dto.NginxParam{
+81 -43
View File
@@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"log"
"net"
"os"
"path"
"path/filepath"
@@ -182,8 +183,8 @@ func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, a
return err
}
configPath := GetSitePath(*website, SiteConf)
nginxContent := string(nginx_conf.WebsiteDefault)
config, err := parser.NewStringParser(nginxContent).Parse()
nginxContent := nginx_conf.GetWebsiteFile("website_default.conf")
config, err := parser.NewStringParser(string(nginxContent)).Parse()
if err != nil {
return err
}
@@ -651,22 +652,33 @@ func createPemFile(website model.Website, websiteSSL model.WebsiteSSL) error {
return nil
}
func getHttpsPort(website *model.Website) ([]int, error) {
websiteDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(website.ID))
var httpsPorts []int
for _, domain := range websiteDomains {
if domain.SSL {
httpsPorts = append(httpsPorts, domain.Port)
func getHttpsPort(websiteID uint) map[int]struct{} {
domains, err := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(websiteID))
if err != nil {
return nil
}
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 {
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
if err != nil {
return nil, err
for _, domain := range domains {
if !domain.SSL {
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 {
@@ -678,63 +690,71 @@ func applySSL(website *model.Website, websiteSSL model.WebsiteSSL, req request.W
if err != nil {
return nil
}
noDefaultPort := true
httpPorts := make(map[int]struct{})
httpsPorts := make(map[int]struct{})
hasDefaultPort := false
for _, domain := range domains {
if domain.Port == 80 {
noDefaultPort = false
if domain.Port == nginxFull.Install.HttpPort {
hasDefaultPort = true
}
if domain.Port != 80 && !domain.SSL {
if domain.SSL {
httpsPorts[domain.Port] = struct{}{}
} else {
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
server := config.FindServers()[0]
httpPort := strconv.Itoa(nginxFull.Install.HttpPort)
httpsPort, err := getHttpsPort(website)
if err != nil {
return err
}
httpPortIPV6 := "[::]:" + httpPort
defaultHttpPort := strconv.Itoa(nginxFull.Install.HttpPort)
defaultHttpPortIPV6 := "[::]:" + defaultHttpPort
for _, port := range httpsPort {
if _, ok := httpPorts[port]; !ok {
server.DeleteListen(strconv.Itoa(port))
}
setListen(server, strconv.Itoa(port), website.IPV6, req.Http3, website.DefaultServer, true)
for port := range httpsPorts {
portStr := strconv.Itoa(port)
server.RemoveListenByBind(portStr)
server.RemoveListenByBind("[::]:" + portStr)
setListen(server, portStr, website.IPV6, req.Http3, website.DefaultServer, true)
}
server.UpdateDirective("http2", []string{"on"})
switch req.HttpConfig {
case constant.HTTPSOnly:
server.RemoveListenByBind(httpPort)
server.RemoveListenByBind(httpPortIPV6)
server.RemoveListenByBind(defaultHttpPort)
server.RemoveListenByBind(defaultHttpPortIPV6)
server.RemoveDirective("if", []string{"($scheme"})
case constant.HTTPToHTTPS:
if !noDefaultPort {
server.UpdateListen(httpPort, website.DefaultServer)
}
if website.IPV6 {
server.UpdateListen(httpPortIPV6, website.DefaultServer)
if hasDefaultPort {
server.UpdateListen(defaultHttpPort, website.DefaultServer)
if website.IPV6 {
server.UpdateListen(defaultHttpPortIPV6, website.DefaultServer)
}
}
server.AddHTTP2HTTPS()
case constant.HTTPAlso:
if !noDefaultPort {
server.UpdateListen(httpPort, website.DefaultServer)
if hasDefaultPort {
server.UpdateListen(defaultHttpPort, website.DefaultServer)
if website.IPV6 {
server.UpdateListen(defaultHttpPortIPV6, website.DefaultServer)
}
}
server.RemoveDirective("if", []string{"($scheme"})
if website.IPV6 {
server.UpdateListen(httpPortIPV6, website.DefaultServer)
}
}
if !req.Hsts {
server.RemoveDirective("add_header", []string{"Strict-Transport-Security", "\"max-age=31536000\""})
}
if !req.Http3 {
for _, port := range httpsPort {
for port := range httpsPorts {
server.RemoveListen(strconv.Itoa(port), "quic")
if website.IPV6 {
httpsPortIPV6 := "[::]:" + strconv.Itoa(port)
@@ -1078,7 +1098,7 @@ func getWebsiteDomains(domains []request.WebsiteDomain, defaultPort int, website
err = buserr.WithMap("ErrPortExist", errMap, nil)
return
}
if common.ScanPort(port) {
if port != 443 && common.ScanPort(port) {
err = buserr.WithDetail("ErrPortInUsed", port, nil)
return
}
@@ -1117,7 +1137,6 @@ func saveCertificateFile(websiteSSL *model.WebsiteSSL, logger *log.Logger) {
func GetSystemSSL() (bool, uint) {
sslSetting, err := settingRepo.Get(settingRepo.WithByKey("SSL"))
if err != nil {
global.LOG.Errorf("load service ssl from setting failed, err: %v", err)
return false, 0
}
if sslSetting.Value == "enable" {
@@ -1425,3 +1444,22 @@ func hasDefaultServer(params []string) bool {
}
return false
}
func ParseDomain(domain string) (*model.WebsiteDomain, error) {
host, portStr, err := net.SplitHostPort(domain)
if err != nil {
return &model.WebsiteDomain{
Domain: domain,
Port: 0,
}, nil
}
port, err := strconv.Atoi(portStr)
if err != nil {
return nil, fmt.Errorf("invalid port in domain %s: %v", domain, err)
}
return &model.WebsiteDomain{
Domain: host,
Port: port,
}, nil
}
+35 -1
View File
@@ -142,6 +142,40 @@ func NewTask(name, operate, taskScope, taskID string, resourceID uint) (*Task, e
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) {
subTask := &SubTask{RootTask: t, Name: name, Retry: 0, Timeout: 30 * time.Minute, Action: action, Rollback: rollback}
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) {
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)
}
+1 -4
View File
@@ -9,9 +9,6 @@ import (
//go:embed ssl.conf
var SSL []byte
//go:embed website_default.conf
var WebsiteDefault []byte
//go:embed index.html
var Index []byte
@@ -48,7 +45,7 @@ var Upstream []byte
//go:embed sse.conf
var SSE []byte
//go:embed *.json
//go:embed *.json *.conf
var websitesFiles embed.FS
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;
error_log /www/sites/domain/log/error.log;
location ~ ^/(\.user.ini|\.htaccess|\.git|\.env|\.svn|\.project|LICENSE|README.md){
return 404;
}
location ^~ /.well-known{
allow all;
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"
ComposeOpRestart = "restart"
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{
"${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/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",
"./extensions": "${EXTENSION_DIR}",
"./extensions": "/usr/local/lib/php/extensions",
"./supervisor/supervisord.conf": "/etc/supervisord.conf",
"./supervisor/supervisor.d/php-fpm.ini": "/etc/supervisor.d/php-fpm.ini",
"./supervisor/supervisor.d": "/etc/supervisor.d",
+1 -3
View File
@@ -18,7 +18,7 @@ func NewBackupJob() *backup {
func (b *backup) Run() {
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 {
return
}
@@ -39,8 +39,6 @@ func (b *backup) Run() {
switch backupItem.Type {
case constant.OneDrive:
refreshToken, err = client.RefreshToken("refresh_token", "refreshToken", varMap)
case constant.GoogleDrive:
refreshToken, err = client.RefreshGoogleToken("refresh_token", "refreshToken", varMap)
case constant.ALIYUN:
refreshToken, err = client.RefreshALIToken(varMap)
}
+11 -11
View File
@@ -40,6 +40,7 @@ require (
github.com/shirou/gopsutil/v3 v3.24.5
github.com/sirupsen/logrus v1.9.3
github.com/spf13/afero v1.11.0
github.com/spf13/cobra v1.9.1
github.com/spf13/viper v1.19.0
github.com/studio-b12/gowebdav v0.9.0
github.com/subosito/gotenv v1.6.0
@@ -53,7 +54,7 @@ require (
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38
gopkg.in/ini.v1 v1.67.0
gopkg.in/yaml.v3 v3.0.1
gorm.io/gorm v1.25.11
gorm.io/gorm v1.30.0
)
require (
@@ -98,7 +99,7 @@ require (
github.com/fvbommel/sortorder v1.1.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.8 // 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-jose/go-jose/v4 v4.0.5 // 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-playground/locales v0.14.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/gofrs/flock v0.12.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
@@ -114,7 +115,6 @@ require (
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-cmp v0.7.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/grpc-ecosystem/grpc-gateway/v2 v2.26.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/mozillazg/go-httpheader v0.2.1 // 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/freemyip v0.3.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/sourcegraph/conc v0.3.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/tencentcloud/tencentcloud-sdk-go/tencentcloud/common 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
go4.org v0.0.0-20200411211856-f5505b9728dd // 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/sync v0.15.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/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect
google.golang.org/grpc v1.72.2 // indirect
google.golang.org/protobuf v1.36.6 // indirect
modernc.org/libc v1.22.5 // indirect
modernc.org/mathutil v1.5.0 // indirect
modernc.org/memory v1.5.0 // indirect
modernc.org/sqlite v1.23.1 // indirect
modernc.org/libc v1.66.1 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // 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-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
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.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ=
github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc=
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
github.com/go-acme/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-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-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk=
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/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
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-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-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM=
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
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/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
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-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
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.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/mholt/archiver/v4 v4.0.0-alpha.8 h1:tRGQuDVPh66WCOelqe6LIGh0gwmfwxUrSSDunscGsRM=
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.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
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/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4=
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/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/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/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
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-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-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
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-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
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.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.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
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-20191011141410-1b5146add898/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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
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.25.11/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
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/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
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-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=
modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=
modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY=
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM=
modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk=
modernc.org/cc/v4 v4.26.1 h1:+X5NtzVBn0KgsBCBe+xkDC7twLb/jNVj9FPgiwSQO3s=
modernc.org/cc/v4 v4.26.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU=
modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE=
modernc.org/fileutil v1.3.3 h1:3qaU+7f7xxTUmvU1pJTZiDLAIoJVdUSSauJNHg9yXoA=
modernc.org/fileutil v1.3.3/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
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=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
+3
View File
@@ -205,6 +205,8 @@ SystemLog: 'System Log'
CutWebsiteLog: 'Rotate Website Log'
FileOrDir: 'Directory / File'
UploadFile: 'Uploading backup file {{ .file }} to {{ .backup }}'
IgnoreBackupErr: 'Backup failed, error: {{ .detail }}, ignoring this error...'
IgnoreUploadErr: 'Upload failed, error: {{ .detail }}, ignoring this error...'
#toolbox
ErrNotExistUser: 'The current user does not exist, please modify and try again!'
@@ -333,6 +335,7 @@ SnapDeleteLoginLog: 'Delete access log'
SnapDeleteMonitor: 'Delete monitoring data'
SnapRemoveSystemIP: 'Remove system IP'
SnapBaseInfo: 'Write 1Panel basic information'
SnapInstallAppImageEmpty: 'No application images selected, skipping...'
SnapInstallApp: 'Backup 1Panel installed applications'
SnapDockerSave: 'Compress installed applications'
SnapLocalBackup: 'Backup 1Panel local backup directory'
+4 -1
View File
@@ -205,6 +205,8 @@ SystemLog: 'システムログ'
CutWebsiteLog: 'ウェブサイトログのローテーション'
FileOrDir: 'ディレクトリ / ファイル'
UploadFile: 'バックアップファイル {{ .file }} を {{ .backup }} にアップロード中'
IgnoreBackupErr: 'バックアップ失敗、エラー:{{ .detail }}、このエラーを無視します...'
IgnoreUploadErr: 'アップロード失敗、エラー:{{ .detail }}、このエラーを無視します...'
#toolbox
ErrNotExistUser: '現在のユーザーは存在しません。変更してもう一度お試しください。'
@@ -333,7 +335,8 @@ SnapDeleteLoginLog: 'アクセスログを削除する'
SnapDeleteMonitor: '監視データを削除する'
SnapRemoveSystemIP: 'システム IP を削除します'
SnapBaseInfo: '1Panel の基本情報を書き込む'
SnapInstallApp: '1Panel にインストールされたアプリケーションをバックアップする'
SnapInstallAppImageEmpty: 'アプリケーションイメージが選択されていないため、スキップします...'
SnapInstallApp: '1Panelインストール済みアプリケーションのバックアップ'
SnapDockerSave: 'インストールされたアプリケーションを圧縮する'
SnapLocalBackup: '1Panel ローカル バックアップ ディレクトリをバックアップします'
SnapCompressBackup: 'ローカル バックアップ ディレクトリを圧縮する'
+3
View File
@@ -205,6 +205,8 @@ SystemLog: '시스템 로그'
CutWebsiteLog: '웹사이트 로그 회전'
FileOrDir: '디렉터리 / 파일'
UploadFile: '백업 파일 {{ .file }} 을(를) {{ .backup }}(으)로 업로드 중'
IgnoreBackupErr: 'Sandaran gagal, ralat: {{ .detail }}, abaikan ralat ini...'
IgnoreUploadErr: 'Muat naik gagal, ralat: {{ .detail }}, abaikan ralat ini...'
#도구상자
ErrNotExistUser: '현재 사용자가 존재하지 않습니다. 수정한 후 다시 시도하세요!'
@@ -333,6 +335,7 @@ SnapDeleteLoginLog: '액세스 로그 삭제'
SnapDeleteMonitor: '모니터링 데이터 삭제'
SnapRemoveSystemIP: '시스템 IP 제거'
SnapBaseInfo: '1패널 기본 정보 쓰기'
SnapInstallAppImageEmpty: '애플리케이션 이미지가 선택되지 않아 건너뜁니다...'
SnapInstallApp: '1Panel 설치된 애플리케이션 백업'
SnapDockerSave: '설치된 애플리케이션 압축'
SnapLocalBackup: '1Panel 로컬 백업 디렉토리 백업'
+4 -1
View File
@@ -204,6 +204,8 @@ SystemLog: 'Log Sistem'
CutWebsiteLog: 'Putar Log Laman Web'
FileOrDir: 'Direktori / Fail'
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
ErrNotExistUser: 'Pengguna semasa tidak wujud, sila ubah suai dan cuba lagi!'
@@ -332,7 +334,8 @@ SnapDeleteLoginLog: 'Padam log akses'
SnapDeleteMonitor: 'Padamkan data pemantauan'
SnapRemoveSystemIP: 'Alih keluar IP sistem'
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'
SnapLocalBackup: 'Sandaran 1Panel 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'
FileOrDir: 'Diretório / Arquivo'
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
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'
SnapRemoveSystemIP: 'Remover IP do sistema'
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'
SnapLocalBackup: 'Backup do diretório de backup local do 1Panel'
SnapCompressBackup: 'Compactar diretório de backup local'
+4 -1
View File
@@ -205,6 +205,8 @@ SystemLog: 'Системный лог'
CutWebsiteLog: 'Ротация логов сайта'
FileOrDir: 'Каталог / Файл'
UploadFile: 'Загрузка файла резервной копии {{ .file }} в {{ .backup }}'
IgnoreBackupErr: 'Ошибка резервного копирования: {{ .detail }}, игнорируем эту ошибку...'
IgnoreUploadErr: 'Ошибка загрузки: {{ .detail }}, игнорируем эту ошибку...'
#ящик для инструментов
ErrNotExistUser: 'Текущий пользователь не существует, измените его и повторите попытку!'
@@ -333,7 +335,8 @@ SnapDeleteLoginLog: 'Удалить журнал доступа'
SnapDeleteMonitor: 'Удалить данные мониторинга'
SnapRemoveSystemIP: 'Удалить системный IP'
SnapBaseInfo: 'Записать основную информацию 1Panel'
SnapInstallApp: 'Резервное копирование установленных приложений 1Panel'
SnapInstallAppImageEmpty: 'Образы приложений не выбраны, пропускаем...'
SnapInstallApp: 'Резервное копирование приложений, установленных в 1Panel'
SnapDockerSave: 'Сжать установленные приложения'
SnapLocalBackup: 'Резервное копирование локального каталога резервных копий 1Panel'
SnapCompressBackup: 'Сжать локальный каталог резервных копий'
+4 -1
View File
@@ -204,6 +204,8 @@ SystemLog: '系統日誌'
CutWebsiteLog: '切割網站日誌'
FileOrDir: '目錄 / 檔案'
UploadFile: '上傳備份文件 {{ .file }} 到 {{ .backup }}'
IgnoreBackupErr: '備份失敗,錯誤:{{ .detail }},忽略本次錯誤...'
IgnoreUploadErr: '上傳失敗,錯誤:{{ .detail }},忽略本次錯誤...'
#toolbox
ErrNotExistUser: '目前使用者不存在,請修改後重試!'
@@ -332,7 +334,8 @@ SnapDeleteLoginLog: '刪除存取日誌'
SnapDeleteMonitor: '刪除監控資料'
SnapRemoveSystemIP: '移除系統IP'
SnapBaseInfo: '寫入1Panel 基本資料'
SnapInstallApp: '備份1Panel 已安裝應用程式'
SnapInstallAppImageEmpty: '當前未勾選應用鏡像,跳過...'
SnapInstallApp: '備份 1Panel 已安裝應用'
SnapDockerSave: '壓縮已安裝應用'
SnapLocalBackup: '備份1Panel 本機備份目錄'
SnapCompressBackup: '壓縮本機備份目錄'
+3
View File
@@ -204,6 +204,8 @@ SystemLog: "系统日志"
CutWebsiteLog: "切割网站日志"
FileOrDir: "目录 / 文件"
UploadFile: "上传备份文件 {{ .file }} 到 {{ .backup }}"
IgnoreBackupErr: "备份失败,错误:{{ .detail }},忽略本次错误..."
IgnoreUploadErr: "上传失败,错误:{{ .detail }},忽略本次错误..."
#toolbox
ErrNotExistUser: "当前用户不存在,请修改后重试!"
@@ -332,6 +334,7 @@ SnapDeleteLoginLog: "删除访问日志"
SnapDeleteMonitor: "删除监控数据"
SnapRemoveSystemIP: "移除系统 IP"
SnapBaseInfo: "写入 1Panel 基本信息"
SnapInstallAppImageEmpty: "当前未勾选应用镜像,跳过..."
SnapInstallApp: "备份 1Panel 已安装应用"
SnapDockerSave: "压缩已安装应用"
SnapLocalBackup: "备份 1Panel 本地备份目录"
+16 -5
View File
@@ -2,12 +2,14 @@ package hook
import (
"os"
"strings"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
)
@@ -18,6 +20,8 @@ func Init() {
handleOllamaModelStatus()
loadLocalDir()
initDockerConf()
}
func initGlobalData() {
@@ -92,11 +96,7 @@ func handleCronJobAlert(cronjob *model.Cronjob) {
EntryID: cronjob.ID,
Param: cronjob.Type,
}
err := xpack.PushAlert(pushAlert)
if err != nil {
global.LOG.Errorf("cronjob alert push failed, err: %v", err)
return
}
_ = xpack.PushAlert(pushAlert)
}
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.InitDefault,
migrations.UpdateWebsiteExpireDate,
migrations.UpdateRuntime,
migrations.AddSnapshotRule,
migrations.UpdatePHPRuntime,
migrations.AddSnapshotIgnore,
migrations.InitAppLauncher,
})
if err := m.Migrate(); err != nil {
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 {
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 {
return err
@@ -314,3 +311,52 @@ var UpdateWebsiteExpireDate = &gormigrate.Migration{
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.POST("/supervisor/process", baseApi.OperateSupervisorProcess)
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 {
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 != nil {
if _, err = g.googleRequest("https://www.googleapis.com/drive/v3/files/"+fileInfo.ID, http.MethodDelete, nil, nil); err != nil {
return false, err
}
fmt.Println(string(res))
return true, nil
}
@@ -99,14 +97,51 @@ func (g *googleDriveClient) Upload(src, target string) (bool, error) {
return false, err
}
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)
}, nil); err != nil {
return false, err
buf := make([]byte, 5*1024*1024)
var offset int64 = 0
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
}
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) {
src = path.Join("/root", src)
fileInfo, err := g.loadFileWithName(src)
+28 -18
View File
@@ -9,6 +9,7 @@ import (
"os"
"os/exec"
"strings"
"syscall"
"time"
"github.com/1Panel-dev/1Panel/agent/app/task"
@@ -17,12 +18,13 @@ import (
)
type CommandHelper struct {
workDir string
outputFile string
scriptPath string
timeout time.Duration
taskItem *task.Task
logger *log.Logger
workDir string
outputFile string
scriptPath string
timeout time.Duration
taskItem *task.Task
logger *log.Logger
IgnoreExist1 bool
}
type Option func(*CommandHelper)
@@ -65,6 +67,7 @@ func (c *CommandHelper) RunBashCWithArgs(arg ...string) error {
_, err := c.run("bash", arg...)
return err
}
func (c *CommandHelper) RunBashC(command string) error {
std, err := c.run("bash", "-c", command)
if err != nil {
@@ -133,23 +136,17 @@ func (c *CommandHelper) run(name string, arg ...string) (string, error) {
cmd.Dir = c.workDir
}
err := cmd.Run()
if c.taskItem != nil {
customWriter.Flush()
}
if c.timeout != 0 {
err := cmd.Run()
if c.taskItem != nil {
customWriter.Flush()
}
if ctx != nil && errors.Is(ctx.Err(), context.DeadlineExceeded) {
return "", buserr.New("ErrCmdTimeout")
}
if err != nil {
return handleErr(stdout, stderr, err)
}
return stdout.String(), nil
}
err := cmd.Run()
if err != nil {
return handleErr(stdout, stderr, err)
return handleErr(stdout, stderr, c.IgnoreExist1, err)
}
return stdout.String(), nil
}
@@ -184,6 +181,11 @@ func WithScriptPath(scriptPath string) Option {
s.scriptPath = scriptPath
}
}
func WithIgnoreExist1() Option {
return func(s *CommandHelper) {
s.IgnoreExist1 = true
}
}
type CustomWriter struct {
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 := ""
if len(stderr.String()) != 0 {
errMsg = fmt.Sprintf("stderr: %s", stderr.String())
+1 -1
View File
@@ -31,7 +31,7 @@ func Down(filePath string) (string, error) {
if err := checkCmd(); err != nil {
return "", err
}
stdout, err := cmd.RunDefaultWithStdoutBashCf(global.CONF.DockerConfig.Command+" -f %s down --remove-orphans", filePath)
stdout, err := cmd.RunDefaultWithStdoutBashCfAndTimeOut(global.CONF.DockerConfig.Command+" -f %s down --remove-orphans", 20*time.Minute, filePath)
return stdout, err
}
+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 {
for _, p := range oldPaths {
var dstPath string
if name != "" {
dstPath = filepath.Join(dst, name)
if f.Stat(dstPath) {
dstPath = dst
}
} else {
base := filepath.Base(p)
dstPath = filepath.Join(dst, base)
if len(oldPaths) == 0 {
return nil
}
var dstPath string
coverFlag := ""
if name != "" {
dstPath = filepath.Join(dst, name)
if f.Stat(dstPath) {
dstPath = dst
}
coverFlag := ""
if cover {
coverFlag = "-f"
}
if err := cmd.RunDefaultBashCf(`mv %s '%s' '%s'`, coverFlag, p, dstPath); err != nil {
return err
}
} else {
dstPath = dst
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
}
@@ -810,6 +815,9 @@ func (f FileOp) TarGzCompressPro(withDir bool, src, dst, secret, exclusionRules
if len(exclude) == 0 {
continue
}
if strings.HasPrefix(exclude, "/") {
exclude, _ = filepath.Rel(src, exclude)
}
if _, ok := exMap[exclude]; ok {
continue
}
@@ -817,19 +825,14 @@ func (f FileOp) TarGzCompressPro(withDir bool, src, dst, secret, exclusionRules
exMap[exclude] = struct{}{}
}
itemPrefix := filepath.Base(src)
if itemPrefix == "/" {
itemPrefix = ""
}
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), "******"))
} 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)
}
cmdMgr := cmd.NewCommandMgr(cmd.WithWorkDir(workdir))
cmdMgr := cmd.NewCommandMgr(cmd.WithWorkDir(workdir), cmd.WithIgnoreExist1())
return cmdMgr.RunBashC(commands)
}
@@ -846,13 +849,14 @@ func (f FileOp) TarGzFilesWithCompressPro(list []string, dst, secret string) err
}
commands := ""
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), "******"))
} 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)
}
return cmd.RunDefaultBashC(commands)
cmdMgr := cmd.NewCommandMgr(cmd.WithIgnoreExist1())
return cmdMgr.RunBashC(commands)
}
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)
global.LOG.Debug(commands)
}
cmdMgr := cmd.NewCommandMgr(cmd.WithWorkDir(dst))
cmdMgr := cmd.NewCommandMgr(cmd.WithWorkDir(dst), cmd.WithIgnoreExist1())
return cmdMgr.RunBashC(commands)
}
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/constant"
"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"
"net/http"
"os"
@@ -201,3 +208,68 @@ func DownloadFileWithProxy(url, dst string) error {
}
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 (
"encoding/json"
"fmt"
"path"
"strconv"
"strings"
"time"
@@ -185,26 +184,33 @@ func (b *BaseApi) RunScript(c *gin.Context) {
tty.Start(quitChan)
go slave.Wait(quitChan)
} else {
connInfo, installDir, err := xpack.LoadNodeInfo(currentNode)
connInfo, _, err := xpack.LoadNodeInfo(currentNode)
if wshandleError(wsConn, errors.WithMessage(err, "invalid param rows in request")) {
return
}
fileDir := path.Join(installDir, "1panel/tmp/script")
fileName := ""
var translations = make(map[string]string)
_ = json.Unmarshal([]byte(scriptItem.Name), &translations)
if name, ok := translations["en"]; ok {
fileName = path.Join(fileDir, strings.ReplaceAll(name, " ", "_"))
fileName = strings.ReplaceAll(name, " ", "_")
} 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)
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
}
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)
if wshandleError(wsConn, err) {
+7
View File
@@ -16,6 +16,7 @@ type IUpgradeLogRepo interface {
Delete(opts ...global.DBOption) error
WithByNodeID(nodeID uint) global.DBOption
WithByUpgradeVersion(oldVersion, newVersion string) global.DBOption
}
func NewIUpgradeLogRepo() IUpgradeLogRepo {
@@ -79,3 +80,9 @@ func (c *UpgradeLogRepo) WithByNodeID(nodeID uint) global.DBOption {
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 {
case constant.OneDrive:
refreshToken, err = client.RefreshToken("refresh_token", "refreshToken", varMap)
case constant.GoogleDrive:
refreshToken, err = client.RefreshGoogleToken("refresh_token", "refreshToken", varMap)
case constant.ALIYUN:
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("RestoreSuccessful"))
_, _ = cmdUtils.RunDefaultWithStdoutBashC("systemctl daemon-reload")
std, err := cmdUtils.RunDefaultWithStdoutBashC("1pctl restart all")
if err != nil {
fmt.Println(std)
}
return nil
},
}
+142 -94
View File
@@ -97,6 +97,13 @@
"formatZH": "同步Ollama模型列表",
"formatEN": "syncOllamamodellist"
},
"/apps/ignored/cancel": {
"bodyKeys": [],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "取消忽略应用升级",
"formatEN": "Cancelignoreapplicationupgrade"
},
"/apps/install": {
"bodyKeys": [
"name"
@@ -117,13 +124,11 @@
"formatEN": "Applicationconfigupdate[installID]"
},
"/apps/installed/ignore": {
"bodyKeys": [
"installId"
],
"bodyKeys": [],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "忽略应用[installId]版本升级",
"formatEN": "Applicationparamupdate[installId]"
"formatZH": "忽略应用升级",
"formatEN": "Ignoreapplicationupgrade"
},
"/apps/installed/op": {
"bodyKeys": [
@@ -649,16 +654,6 @@
"formatZH": "删除容器存储卷[names]",
"formatEN": "deletecontainervolume[names]"
},
"/core/app/launcher/show": {
"bodyKeys": [
"key",
"value"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "首页应用[key]=\u003e显示:[value]",
"formatEN": "applauncher[key]=\u003eshow:[value]"
},
"/core/backups": {
"bodyKeys": [
"type"
@@ -840,6 +835,13 @@
"formatZH": "绑定许可证",
"formatEN": "bindlicense"
},
"/core/licenses/bind/free": {
"bodyKeys": [],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "修改许可证免费节点绑定",
"formatEN": "changebindoffreenodeforlicense"
},
"/core/licenses/del": {
"bodyKeys": [],
"paramKeys": [],
@@ -1232,6 +1234,16 @@
"formatZH": "更新计划任务[name]",
"formatEN": "updatecronjob[name]"
},
"/dashboard/app/launcher/show": {
"bodyKeys": [
"key",
"value"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "首页应用[key]=\u003e显示:[value]",
"formatEN": "applauncher[key]=\u003eshow:[value]"
},
"/databases": {
"bodyKeys": [
"name"
@@ -1568,6 +1580,15 @@
"formatZH": "删除文件/文件夹[path]",
"formatEN": "Deletedirorfile[path]"
},
"/files/depth/size": {
"bodyKeys": [
"path"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "获取目录及其第一层子目录文件夹大小[path]",
"formatEN": "Multifilesize[path]"
},
"/files/favorite": {
"bodyKeys": [
"path"
@@ -1672,12 +1693,13 @@
},
"/files/upload": {
"bodyKeys": [
"path"
"path",
"file"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "上传文件[path]",
"formatEN": "Uploadfile[path]"
"formatZH": "上传文件[path]/[file]",
"formatEN": "Uploadfile[path]/[file]"
},
"/files/wget": {
"bodyKeys": [
@@ -1690,85 +1712,13 @@
"formatZH": "下载url=\u003e[path]/[name]",
"formatEN": "Downloadurl=\u003e[path]/[name]"
},
"/host/conffile/update": {
"/hosts/conffile/update": {
"bodyKeys": [],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "修改SSH配置文件",
"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": {
"bodyKeys": [
"source_port"
@@ -1824,6 +1774,78 @@
"formatZH": "修改默认监控网卡[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": {
"bodyKeys": [],
"paramKeys": [],
@@ -1989,6 +2011,13 @@
"formatZH": "删除脚本库脚本[names]",
"formatEN": "deletescript[names]"
},
"/script/sync": {
"bodyKeys": [],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "同步脚本库脚本",
"formatEN": "syncscripts"
},
"/script/update": {
"bodyKeys": [
"id"
@@ -2417,6 +2446,24 @@
"formatZH": "删除网站acme[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": {
"bodyKeys": [
"name"
@@ -3019,12 +3066,13 @@
"/xpack/tampers/update": {
"bodyKeys": [
"website",
"status"
"status",
"path"
],
"paramKeys": [],
"beforeFunctions": [],
"formatZH": "更新防篡改信息[website]=\u003e[status]",
"formatEN": "updatetamperinfo[website]=\u003e[status]"
"formatZH": "更新防篡改信息[website][path]=\u003e[status]",
"formatEN": "updatetamperinfo[website][path]=\u003e[status]"
},
"/xpack/waf/acl/create": {
"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"
GoogleRedirectURI = "https://localhost:8080"
DaemonJsonPath = "/etc/docker/daemon.json"
)
const (
@@ -76,10 +74,10 @@ var WebUrlMap = map[string]struct{}{
"/containers/setting": {},
"/containers/dashboard": {},
"/cronjobs": {},
"/cronjobs/cronjob": {},
"/cronjobs/library": {},
"/cronjobs/operate": {},
"/cronjobs": {},
"/cronjobs/cronjob": {},
"/cronjobs/library": {},
"/cronjobs/cronjob/operate": {},
"/databases": {},
"/databases/mysql": {},
@@ -176,3 +174,5 @@ var DynamicRoutes = []string{
}
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
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
gorm.io/gorm v1.25.11
gorm.io/gorm v1.30.0
)
require (
@@ -65,7 +65,7 @@ require (
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // 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-openapi/jsonpointer v0.19.5 // 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/reflect2 v1.0.2 // 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/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // 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/multierr v1.9.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/sync v0.15.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/protobuf v1.34.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gorm.io/driver/sqlite v1.4.4 // indirect
modernc.org/libc v1.22.5 // indirect
modernc.org/mathutil v1.5.0 // indirect
modernc.org/memory v1.5.0 // indirect
modernc.org/sqlite v1.23.1 // indirect
modernc.org/libc v1.66.1 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // 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-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
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.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ=
github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc=
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
github.com/go-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-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-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
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/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
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.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
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.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/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
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/mozillazg/go-httpheader v0.2.1 h1:geV7TrjbL8KXSyvghnFm+NyTux/hxwueTSrwhe88TQQ=
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/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4=
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/go.mod h1:8EM2awITynlem2VML2dXGHkMYP2UyECsGLOdp6yMpco=
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/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
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-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-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
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-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
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.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.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
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-20190513163551-3ee3066db522/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.10/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.25.11/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
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-20190106161140-3f1c8253044a/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-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=
modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=
modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY=
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM=
modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk=
modernc.org/cc/v4 v4.26.1 h1:+X5NtzVBn0KgsBCBe+xkDC7twLb/jNVj9FPgiwSQO3s=
modernc.org/cc/v4 v4.26.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU=
modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE=
modernc.org/fileutil v1.3.3 h1:3qaU+7f7xxTUmvU1pJTZiDLAIoJVdUSSauJNHg9yXoA=
modernc.org/fileutil v1.3.3/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
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=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
+1
View File
@@ -58,6 +58,7 @@ ErrXpackExceptional: "This section is for professional edition, please sync lice
ErrXpackOutOfDate: "Current license has expired, please import the license again in Panel Settings - License"
ErrXpackLost: "License has reached the maximum retry count, please go to the [Panel Settings] [License] page and click the sync button manually to ensure the professional features work correctly"
ErrDeviceLost: "Required files for license verification are missing, please check and try again!"
ErrDeviceErr: "The current environment does not match the license import environment. Please edit the license and re-import!"
ErrXpackTimeout: "Request timeout, network connection might be unstable, please try again later!"
ErrUnbindMaster: "Detected nodes in node management, unable to unbind the current license, please remove nodes first and retry!"
ErrFreeNodeLimit: "Community version node limit reached, please go to www.lxware.cn/1panel to purchase and retry!"
+1
View File
@@ -59,6 +59,7 @@ ErrXpackExceptional: "この部分はプロフェッショナル版機能です
ErrXpackOutOfDate: "現在のライセンスは期限切れです、再度「パネル設定-ライセンス」画面でライセンスをインポートしてください"
ErrXpackLost: "ライセンスの最大試行回数に達しました、「パネル設定」「ライセンス」ページに移動し、手動で同期ボタンをクリックして、プロフェッショナル版機能が正常に使用できることを確認してください"
ErrDeviceLost: "ライセンス検証に必要なファイルが失われました。確認して再試行してください!"
ErrDeviceErr: "現在の環境とライセンスのインポート環境が一致しません。ライセンスを編集して再度インポートしてください!"
ErrXpackTimeout: "リクエストタイムアウト、ネットワーク接続が不安定な可能性があります。後で再試行してください!"
ErrUnbindMaster: "ノード管理にノードが存在するため、現在のライセンスを解除できません。ノードを削除してから再試行してください!"
ErrFreeNodeLimit: "コミュニティ版のノード数が無料上限に達しました、www.lxware.cn/1panel で購入して再試行してください!"
+1
View File
@@ -58,6 +58,7 @@ ErrXpackExceptional: "이 섹션은 프로페셔널 에디션 기능입니다.
ErrXpackOutOfDate: "현재 라이선스가 만료되었습니다. 다시 [패널 설정]-[라이선스] 인터페이스에서 라이선스를 가져오세요."
ErrXpackLost: "라이선스가 최대 재시도 횟수에 도달했습니다. [패널 설정][라이선스] 페이지로 이동하여 수동으로 동기화 버튼을 클릭하여 프로페셔널 기능을 정상적으로 사용할 수 있도록 하세요."
ErrDeviceLost: "라이센스 검증에 필요한 파일이 누락되었습니다. 확인 후 다시 시도해 주세요!"
ErrDeviceErr: "현재 환경이 라이선스 가져오기 환경과 일치하지 않습니다. 라이선스를 편집하고 다시 가져오십시오!"
ErrXpackTimeout: "요청 시간 초과, 네트워크 연결이 불안정할 수 있습니다. 나중에 다시 시도해 주세요!"
ErrUnbindMaster: "노드 관리 내에 노드가 존재함을 감지하였습니다. 현재 라이선스를 해제할 수 없습니다. 먼저 제거 후 다시 시도해 주세요!"
ErrFreeNodeLimit: "커뮤니티 에디션 노드 수가 무료 한도에 도달하였습니다. www.lxware.cn/1panel 에서 구매 후 다시 시도해 주세요!"
+1
View File
@@ -58,6 +58,7 @@ ErrXpackExceptional: "Bahagian ini adalah fungsi profesional, sila selaraskan le
ErrXpackOutOfDate: "Lesen semasa telah tamat tempoh, sila muatkan lesen baru di Tetapan Papan Pemuka."
ErrXpackLost: "Lesen telah mencapai bilangan percubaan maksimum, sila ke [Tetapan Papan Pemuka][Lesen] dan klik butang penyelarasan secara manual."
ErrDeviceLost: "Fail yang diperlukan untuk pengesahan lesen hilang, sila semak dan cuba lagi!"
ErrDeviceErr: "Persekitaran semasa tidak sepadan dengan persekitaran import lesen. Sila edit lesen dan import semula!"
ErrXpackTimeout: "Permintaan tamat masa, sambungan rangkaian mungkin tidak stabil, sila cuba lagi kemudian!"
ErrUnbindMaster: "Terdapat nod dalam pengurusan nod, sila keluarkan dahulu dan cuba lagi!"
ErrFreeNodeLimit: "Jumlah nod versi komuniti telah mencapai had percuma, sila lawati www.lxware.cn/1panel untuk pembelian!"
+1
View File
@@ -58,6 +58,7 @@ ErrXpackExceptional: "Esta parte é uma funcionalidade profissional, por favor s
ErrXpackOutOfDate: "A licença atual expirou, por favor importe uma nova em Configurações do Painel - Licença."
ErrXpackLost: "A licença atingiu o número máximo de tentativas, acesse [Configurações do Painel][Licença] e clique no botão de sincronização manual."
ErrDeviceLost: "Arquivos necessários para a verificação da licença estão faltando, por favor verifique e tente novamente!"
ErrDeviceErr: "O ambiente atual não corresponde ao ambiente de importação da licença. Por favor, edite a licença e reimporte!"
ErrXpackTimeout: "Requisição expirou, a conexão de rede pode estar instável, por favor tente novamente mais tarde!"
ErrUnbindMaster: "Foram encontrados nós na gestão de nós, remova-os primeiro e tente novamente!"
ErrFreeNodeLimit: "O número de nós da versão comunitária atingiu o limite gratuito, por favor acesse www.lxware.cn/1panel para comprar!"
+1
View File
@@ -58,6 +58,7 @@ ErrXpackExceptional: "Эта часть доступна только в про
ErrXpackOutOfDate: "Текущая лицензия истекла, повторно импортируйте лицензию в разделе Настройки панели - Лицензия."
ErrXpackLost: "Лицензия достигла максимального количества попыток, перейдите в [Настройки панели][Лицензия] и нажмите кнопку синхронизации вручную."
ErrDeviceLost: "Необходимые файлы для проверки лицензии отсутствуют, пожалуйста, проверьте и попробуйте снова!"
ErrDeviceErr: "Текущая среда не соответствует среде импорта лицензии. Отредактируйте лицензию и повторите импорт!"
ErrXpackTimeout: "Время ожидания запроса истекло, возможно нестабильное сетевое соединение, повторите попытку позже!"
ErrUnbindMaster: "В управлении узлами обнаружены узлы, сначала удалите их и повторите попытку!"
ErrFreeNodeLimit: "Количество узлов в версии сообщества достигло бесплатного лимита, посетите www.lxware.cn/1panel для покупки!"
+1
View File
@@ -58,6 +58,7 @@ ErrXpackExceptional: "該部分為專業版功能,請先在 面板設定-許
ErrXpackOutOfDate: "目前許可證已過期,請重新在 面板設定-許可證 介面匯入許可證"
ErrXpackLost: "許可證已達到最大重試次數,請進入【面板設定】【許可證】頁面手動點擊同步按鈕,以確保專業版功能正常使用"
ErrDeviceLost: "許可證校驗必要檔案遺失,請檢查後重試!"
ErrDeviceErr: "當前環境與許可證導入環境不一致,請編輯許可證重新導入!"
ErrXpackTimeout: "請求超時,網路連接可能不穩定,請稍後再試!"
ErrUnbindMaster: "檢測到節點管理內存在節點,無法解綁目前許可證,請先移除後重試!"
ErrFreeNodeLimit: "社區版節點數量已達免費上限,請前往 www.lxware.cn/1panel 購買後重試!"
+1
View File
@@ -58,6 +58,7 @@ ErrXpackExceptional: "该部分为专业版功能,请先在 面板设置-许
ErrXpackOutOfDate: "当前许可证已过期,请重新在 面板设置-许可证 界面导入许可证"
ErrXpackLost: "许可证已达到最大重试次数,请进入【面板设置】【许可证】页面手动点击同步按钮,以确保专业版功能正常使用"
ErrDeviceLost: "许可证校验必要文件丢失,请检查后重试!"
ErrDeviceErr: "当前环境与许可证导入环境不一致,请编辑许可证重新导入!"
ErrXpackTimeout: "请求超时,网络连接可能不稳定,请稍后再试!"
ErrUnbindMaster: "检测到节点管理内存在专业版节点,无法解绑当前许可证,请先移除或解绑后重试!"
ErrFreeNodeLimit: "社区版节点数量已达到免费上限,请前往 www.lxware.cn/1panel 购买后重试!"
-2
View File
@@ -40,8 +40,6 @@ func (b *backup) Run() {
switch backupItem.Type {
case constant.OneDrive:
refreshToken, err = client.RefreshToken("refresh_token", "refreshToken", varMap)
case constant.GoogleDrive:
refreshToken, err = client.RefreshGoogleToken("refresh_token", "refreshToken", varMap)
case constant.ALIYUN:
refreshToken, err = client.RefreshALIToken(varMap)
}
+40 -20
View File
@@ -32,43 +32,52 @@ func Init() {
handleUserInfo(global.CONF.Base.ChangeUserInfo, settingRepo)
generateKey()
initDockerConf()
}
func handleUserInfo(tags string, settingRepo repo.ISettingRepo) {
if len(tags) == 0 {
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 err := settingRepo.Update("UserName", common.RandStrAndNum(10)); err != nil {
global.LOG.Fatalf("init username before start failed, err: %v", err)
}
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
settingMap["UserName"] = common.RandStrAndNum(10)
settingMap["Password"] = common.RandStrAndNum(10)
settingMap["SecurityEntrance"] = common.RandStrAndNum(10)
}
if strings.Contains(global.CONF.Base.ChangeUserInfo, "username") {
if err := settingRepo.Update("UserName", common.RandStrAndNum(10)); err != nil {
global.LOG.Fatalf("init username before start failed, err: %v", err)
}
settingMap["UserName"] = common.RandStrAndNum(10)
}
if strings.Contains(global.CONF.Base.ChangeUserInfo, "password") {
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)
}
settingMap["Password"] = common.RandStrAndNum(10)
}
if strings.Contains(global.CONF.Base.ChangeUserInfo, "entrance") {
if err := settingRepo.Update("SecurityEntrance", common.RandStrAndNum(10)); err != nil {
global.LOG.Fatalf("init entrance before start failed, err: %v", err)
settingMap["SecurityEntrance"] = common.RandStrAndNum(10)
}
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 -e 's#ORIGINAL_PASSWORD=.*#ORIGINAL_PASSWORD=**********#g' /usr/local/bin/1pctl", cmd.SudoHandleCmd())
}
func generateKey() {
@@ -76,3 +85,14 @@ func generateKey() {
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.UpdateGoogle,
migrations.UpdateXpackHideMenu,
migrations.UpdateOnedrive,
})
if err := m.Migrate(); err != nil {
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/global"
"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/encrypt"
"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 {
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 {
return err
}
@@ -470,3 +472,20 @@ var UpdateGoogle = &gormigrate.Migration{
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/global"
"github.com/1Panel-dev/1Panel/core/utils/cmd"
"github.com/1Panel-dev/1Panel/core/utils/common"
"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
"gopkg.in/yaml.v3"
@@ -39,13 +40,13 @@ func Init() {
panic(fmt.Errorf("Fatal error config file: %s \n", err))
}
} else {
baseDir = loadParams("BASE_DIR")
port = loadParams("ORIGINAL_PORT")
version = loadParams("ORIGINAL_VERSION")
username = loadParams("ORIGINAL_USERNAME")
password = loadParams("ORIGINAL_PASSWORD")
entrance = loadParams("ORIGINAL_ENTRANCE")
language = loadParams("LANGUAGE")
baseDir = common.LoadParams("BASE_DIR")
port = common.LoadParams("ORIGINAL_PORT")
version = common.LoadParams("ORIGINAL_VERSION")
username = common.LoadParams("ORIGINAL_USERNAME")
password = common.LoadParams("ORIGINAL_PASSWORD")
entrance = common.LoadParams("ORIGINAL_ENTRANCE")
language = common.LoadParams("LANGUAGE")
reader := bytes.NewReader(conf.AppYaml)
if err := v.ReadConfig(reader); err != nil {
@@ -100,18 +101,6 @@ func Init() {
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 {
stdout, err := cmd.RunDefaultWithStdoutBashC("grep '^CHANGE_USER_INFO=' /usr/local/bin/1pctl | cut -d'=' -f2")
if err != nil {
+37 -1
View File
@@ -6,6 +6,8 @@ import (
"encoding/json"
"fmt"
"io"
"mime"
"mime/multipart"
"net/http"
"net/url"
"path"
@@ -65,7 +67,11 @@ func OperationLog() gin.HandlerFunc {
c.Request.Body = io.NopCloser(bytes.NewBuffer(body))
}
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 {
if _, ok := bodyMap[key]; ok {
formatMap[key] = bodyMap[key]
@@ -247,3 +253,33 @@ func replaceStr(val string, rep ...string) string {
}
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/exec"
"strings"
"syscall"
"time"
"github.com/1Panel-dev/1Panel/core/app/task"
@@ -17,12 +18,13 @@ import (
)
type CommandHelper struct {
workDir string
outputFile string
scriptPath string
timeout time.Duration
taskItem *task.Task
logger *log.Logger
workDir string
outputFile string
scriptPath string
timeout time.Duration
taskItem *task.Task
logger *log.Logger
IgnoreExist1 bool
}
type Option func(*CommandHelper)
@@ -132,14 +134,14 @@ func (c *CommandHelper) run(name string, arg ...string) (string, error) {
return "", buserr.New("ErrCmdTimeout")
}
if err != nil {
return handleErr(stdout, stderr, err)
return handleErr(stdout, stderr, c.IgnoreExist1, err)
}
return stdout.String(), nil
}
err := cmd.Run()
if err != nil {
return handleErr(stdout, stderr, err)
return handleErr(stdout, stderr, c.IgnoreExist1, err)
}
return stdout.String(), nil
}
@@ -174,6 +176,11 @@ func WithScriptPath(scriptPath string) Option {
s.scriptPath = scriptPath
}
}
func WithIgnoreExist1() Option {
return func(s *CommandHelper) {
s.IgnoreExist1 = true
}
}
type CustomWriter struct {
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 := ""
if len(stderr.String()) != 0 {
errMsg = fmt.Sprintf("stderr: %s", stderr.String())
+9 -10
View File
@@ -4,14 +4,12 @@ import (
"fmt"
mathRand "math/rand"
"net"
"net/http"
"os"
"path"
"strconv"
"strings"
"time"
"github.com/1Panel-dev/1Panel/core/constant"
"github.com/gin-gonic/gin"
"github.com/1Panel-dev/1Panel/core/global"
@@ -225,13 +223,14 @@ func HandleIPList(content string) ([]string, error) {
return res, nil
}
func deleteCookie(w http.ResponseWriter) {
cookie := &http.Cookie{
Name: constant.SessionName,
Value: "",
Path: "/",
Expires: time.Unix(0, 0),
MaxAge: -1,
func LoadParams(param string) string {
stdout, err := cmd.RunDefaultWithStdoutBashCf("grep '^%s=' /usr/local/bin/1pctl | cut -d'=' -f2", param)
if err != nil {
panic(err)
}
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{})
excludes := strings.Split(exclusionRules, ",")
excludeRules := ""
excludes = append(excludes, "*.sock")
for _, exclude := range excludes {
if len(exclude) == 0 {
continue
@@ -110,13 +109,13 @@ func HandleTar(sourceDir, targetDir, name, exclusionRules string, secret string)
if len(secret) != 0 {
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), "******"))
} 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)
}
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(24 * time.Hour))
cmdMgr := cmd.NewCommandMgr(cmd.WithTimeout(24*time.Hour), cmd.WithIgnoreExist1())
stdout, err := cmdMgr.RunWithStdoutBashC(commands)
if err != nil {
if len(stdout) != 0 {
+8
View File
@@ -75,6 +75,14 @@ func (c *SSHClient) SudoHandleCmd() string {
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) {
session, err := c.Client.NewSession()
if err != nil {
+2 -2
View File
@@ -4,14 +4,14 @@
<p align="center">
<a href="https://trendshift.io/repositories/2462" target="_blank"><img src="https://trendshift.io/api/badge/repositories/2462" alt="1Panel-dev%2F1Panel | Trendshift" style="width: 180px; height: auto;" /></a>
<a href="https://hellogithub.com/repository/71791baf930149ac9b84e1acf186573f" target="_blank"><img src="https://api.hellogithub.com/v1/widgets/recommend.svg?rid=71791baf930149ac9b84e1acf186573f&claim_uid=p8vB3kP5CMrthiL&theme=dark&theme=neutral" alt="Featured|HelloGitHub" style="width: 180px; height: auto;" /></a>
<a href="https://market.aliyun.com/products/53690006/cmjj00062740.html?userCode=kmemb8jp" target="_blank"><img src="https://img.alicdn.com/imgextra/i2/O1CN01H5JIwY1rZ0OobDjnJ_!!6000000005644-2-tps-1000-216.png" alt="1Panel-dev%2F1Panel | Aliyun" style="width: 180px; height: auto;" /></a>
</p>
<p align="center">
<a href="https://www.gnu.org/licenses/gpl-3.0.html"><img src="https://shields.io/github/license/1Panel-dev/1Panel?color=%231890FF" alt="License: GPL v3"></a>
<a href="https://app.codacy.com/gh/1Panel-dev/1Panel?utm_source=github.com&utm_medium=referral&utm_content=1Panel-dev/1Panel&utm_campaign=Badge_Grade_Dashboard"><img src="https://app.codacy.com/project/badge/Grade/da67574fd82b473992781d1386b937ef" alt="Codacy"></a>
<a href="https://github.com/1Panel-dev/1Panel/releases"><img src="https://img.shields.io/github/v/release/1Panel-dev/1Panel" alt="GitHub release"></a>
<a href="https://github.com/1Panel-dev/1Panel"><img src="https://img.shields.io/github/stars/1Panel-dev/1Panel?color=%231890FF&style=flat-square" alt="GitHub Stars"></a>
<a href="https://gitee.com/fit2cloud-feizhiyun/1Panel"><img src="https://gitee.com/fit2cloud-feizhiyun/1Panel/badge/star.svg?theme=gvp" alt="Gitee Stars"></a><br>
<a href="https://gitee.com/fit2cloud-feizhiyun/1Panel"><img src="https://gitee.com/fit2cloud-feizhiyun/1Panel/badge/star.svg?theme=gvp" alt="Gitee Stars"></a>
<a href="https://gitcode.com/feizhiyun/1Panel"><img src="https://gitcode.com/feizhiyun/1Panel/star/badge.svg" alt="GitCode Stars"></a><br>
</p>
<p align="center">
<a href="/README.md"><img alt="English" src="https://img.shields.io/badge/English-d9d9d9"></a>
+1 -1
View File
@@ -38,7 +38,7 @@
"codemirror": "^6.0.1",
"crypto-js": "^4.2.0",
"echarts": "^5.5.0",
"element-plus": "^2.9.9",
"element-plus": "2.9.8",
"fit2cloud-ui-plus": "^1.2.2",
"highlight.js": "^11.9.0",
"js-base64": "^3.7.7",
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(
(response: AxiosResponse) => {
globalStore.errStatus = '';
const { data } = response;
if (data.code == ResultEnum.OVERDUE || data.code == ResultEnum.FORBIDDEN) {
globalStore.setLogStatus(false);
@@ -94,9 +93,9 @@ class RequestHttp {
return data;
},
async (error: AxiosError) => {
globalStore.errStatus = '';
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) {
switch (response.status) {
case 313:
@@ -110,11 +109,6 @@ class RequestHttp {
);
return Promise.reject(error);
default:
globalStore.errStatus = 'code-' + response.status;
router.push({
name: 'entrance',
params: { code: globalStore.entrance },
});
return;
}
}

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