Compare commits

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

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

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

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

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