Compare commits

..
365 changed files with 4538 additions and 17651 deletions
-22
View File
@@ -226,28 +226,6 @@ func (b *BaseApi) CleanRecord(c *gin.Context) {
helper.Success(c)
}
// @Tags Cronjob
// @Summary Handle stop job
// @Accept json
// @Param request body dto.OperateByID true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /cronjobs/stop [post]
func (b *BaseApi) StopCronJob(c *gin.Context) {
var req dto.OperateByID
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := cronjobService.HandleStop(req.ID); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Cronjob
// @Summary Delete cronjob
// @Accept json
+2 -3
View File
@@ -17,9 +17,8 @@ var (
appInstallService = service.NewIAppInstalledService()
appIgnoreUpgradeService = service.NewIAppIgnoreUpgradeService()
aiToolService = service.NewIAIToolService()
mcpServerService = service.NewIMcpServerService()
tensorrtLLMService = service.NewITensorRTLLMService()
aiToolService = service.NewIAIToolService()
mcpServerService = service.NewIMcpServerService()
containerService = service.NewIContainerService()
composeTemplateService = service.NewIComposeTemplateService()
-41
View File
@@ -901,44 +901,3 @@ func (b *BaseApi) GetUsersAndGroups(c *gin.Context) {
}
helper.SuccessWithData(c, res)
}
// @Tags File
// @Summary Convert file
// @Accept json
// @Param request body request.FileConvert true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /files/convert [post]
func (b *BaseApi) ConvertFile(c *gin.Context) {
var req request.FileConvertRequest
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
fileService.Convert(req)
helper.SuccessWithData(c, nil)
}
// @Tags File
// @Summary Convert file
// @Accept json
// @Param request body dto.PageInfo true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /files/convert/log [post]
func (b *BaseApi) ConvertLog(c *gin.Context) {
var req dto.PageInfo
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
total, logs, err := fileService.ConvertLog(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, dto.PageResult{
Items: logs,
Total: total,
})
}
+22
View File
@@ -95,6 +95,28 @@ func (b *BaseApi) OperateToolConfig(c *gin.Context) {
helper.SuccessWithData(c, config)
}
// @Tags Host tool
// @Summary Get tool logs
// @Accept json
// @Param request body request.HostToolLogReq true "request"
// @Success 200 {string} logContent
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/tool/log [post]
func (b *BaseApi) GetToolLog(c *gin.Context) {
var req request.HostToolLogReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
logContent, err := hostToolService.GetToolLog(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, logContent)
}
// @Tags Host tool
// @Summary Create Supervisor process
// @Accept json
+21 -1
View File
@@ -1,6 +1,7 @@
package v2
import (
"encoding/base64"
"encoding/json"
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
@@ -76,7 +77,26 @@ func (b *BaseApi) LoadBaseDir(c *gin.Context) {
// @Security Timestamp
// @Router /settings/ssh/conn [get]
func (b *BaseApi) LoadLocalConn(c *gin.Context) {
helper.SuccessWithData(c, settingService.GetLocalConn())
connInfoInDB := settingService.GetSettingByKey("LocalSSHConn")
if len(connInfoInDB) == 0 {
helper.Success(c)
return
}
var data dto.SSHConnData
if err := json.Unmarshal([]byte(connInfoInDB), &data); err != nil {
helper.Success(c)
return
}
if len(data.Password) != 0 {
data.Password = base64.StdEncoding.EncodeToString([]byte(data.Password))
}
if len(data.PrivateKey) != 0 {
data.PrivateKey = base64.StdEncoding.EncodeToString([]byte(data.PrivateKey))
}
if len(data.PassPhrase) != 0 {
data.PassPhrase = base64.StdEncoding.EncodeToString([]byte(data.PassPhrase))
}
helper.SuccessWithData(c, data)
}
func (b *BaseApi) CheckLocalConn(c *gin.Context) {
+41 -75
View File
@@ -68,23 +68,21 @@ func (b *BaseApi) UpdateSSH(c *gin.Context) {
}
// @Tags SSH
// @Summary Generate host SSH secret
// @Summary Update host SSH setting by file
// @Accept json
// @Param request body dto.RootCertOperate true "request"
// @Param request body dto.SSHConf true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/ssh/cert [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"生成 SSH 密钥 ","formatEN":"generate SSH secret"}
func (b *BaseApi) CreateRootCert(c *gin.Context) {
var req dto.RootCertOperate
// @Router /hosts/ssh/conffile/update [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改 SSH 配置文件","formatEN":"update SSH conf"}
func (b *BaseApi) UpdateSSHByfile(c *gin.Context) {
var req dto.SSHConf
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := loadCertAfterDecrypt(&req); err != nil {
helper.BadRequest(c, err)
}
if err := sshService.CreateRootCert(req); err != nil {
if err := sshService.UpdateByFile(req.File); err != nil {
helper.InternalServer(c, err)
return
}
@@ -92,23 +90,45 @@ func (b *BaseApi) CreateRootCert(c *gin.Context) {
}
// @Tags SSH
// @Summary Update host SSH secret
// @Summary Generate host SSH secret
// @Accept json
// @Param request body dto.RootCertOperate true "request"
// @Param request body dto.CreateRootCert true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/ssh/cert/update [post]
// @Router /hosts/ssh/cert [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"生成 SSH 密钥 ","formatEN":"generate SSH secret"}
func (b *BaseApi) EditRootCert(c *gin.Context) {
var req dto.RootCertOperate
func (b *BaseApi) CreateRootCert(c *gin.Context) {
var req dto.CreateRootCert
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := loadCertAfterDecrypt(&req); err != nil {
helper.BadRequest(c, err)
if len(req.PassPhrase) != 0 {
passPhrase, err := base64.StdEncoding.DecodeString(req.PassPhrase)
if err != nil {
helper.BadRequest(c, err)
return
}
req.PassPhrase = string(passPhrase)
}
if err := sshService.EditRootCert(req); err != nil {
if len(req.PrivateKey) != 0 {
privateKey, err := base64.StdEncoding.DecodeString(req.PrivateKey)
if err != nil {
helper.BadRequest(c, err)
return
}
req.PrivateKey = string(privateKey)
}
if len(req.PublicKey) != 0 {
publicKey, err := base64.StdEncoding.DecodeString(req.PublicKey)
if err != nil {
helper.BadRequest(c, err)
return
}
req.PublicKey = string(publicKey)
}
if err := sshService.CreateRootCert(req); err != nil {
helper.InternalServer(c, err)
return
}
@@ -226,69 +246,15 @@ func (b *BaseApi) ExportSSHLogs(c *gin.Context) {
// @Tags SSH
// @Summary Load host SSH conf
// @Accept json
// @Param request body dto.OperationWithName true "request"
// @Success 200 {string} conf
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/ssh/file [post]
func (b *BaseApi) LoadSSHFile(c *gin.Context) {
var req dto.OperationWithName
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := sshService.LoadSSHFile(req.Name)
// @Router /hosts/ssh/conf [get]
func (b *BaseApi) LoadSSHConf(c *gin.Context) {
data, err := sshService.LoadSSHConf()
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags SSH
// @Summary Update host SSH setting by file
// @Accept json
// @Param request body dto.SSHConf true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/ssh/file/update [post]
// @x-panel-log {"bodyKeys":["key"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改 SSH 配置文件 [key]","formatEN":"update SSH conf [key]"}
func (b *BaseApi) UpdateSSHByFile(c *gin.Context) {
var req dto.SettingUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := sshService.UpdateByFile(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
func loadCertAfterDecrypt(req *dto.RootCertOperate) error {
if len(req.PassPhrase) != 0 {
passPhrase, err := base64.StdEncoding.DecodeString(req.PassPhrase)
if err != nil {
return err
}
req.PassPhrase = string(passPhrase)
}
if len(req.PrivateKey) != 0 {
privateKey, err := base64.StdEncoding.DecodeString(req.PrivateKey)
if err != nil {
return err
}
req.PrivateKey = string(privateKey)
}
if len(req.PublicKey) != 0 {
publicKey, err := base64.StdEncoding.DecodeString(req.PublicKey)
if err != nil {
return err
}
req.PublicKey = string(publicKey)
}
return nil
}
-68
View File
@@ -1,68 +0,0 @@
package v2
import (
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
"github.com/gin-gonic/gin"
)
func (b *BaseApi) PageTensorRTLLMs(c *gin.Context) {
var req request.TensorRTLLMSearch
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
list := tensorrtLLMService.Page(req)
helper.SuccessWithData(c, list)
}
func (b *BaseApi) CreateTensorRTLLM(c *gin.Context) {
var req request.TensorRTLLMCreate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := tensorrtLLMService.Create(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
func (b *BaseApi) UpdateTensorRTLLM(c *gin.Context) {
var req request.TensorRTLLMUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := tensorrtLLMService.Update(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
func (b *BaseApi) DeleteTensorRTLLM(c *gin.Context) {
var req request.TensorRTLLMDelete
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := tensorrtLLMService.Delete(req.ID)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
func (b *BaseApi) OperateTensorRTLLM(c *gin.Context) {
var req request.TensorRTLLMOperate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
err := tensorrtLLMService.Operate(req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
+55 -40
View File
@@ -6,6 +6,7 @@ import (
"fmt"
"net/http"
"strconv"
"strings"
"time"
"github.com/1Panel-dev/1Panel/agent/app/dto"
@@ -85,16 +86,15 @@ func (b *BaseApi) ContainerWsSSH(c *gin.Context) {
return
}
source := c.Query("source")
var containerID string
var initCmd []string
switch source {
case "redis", "redis-cluster":
initCmd, err = loadRedisInitCmd(c, source)
containerID, initCmd, err = loadRedisInitCmd(c, source)
case "ollama":
initCmd, err = loadOllamaInitCmd(c)
containerID, initCmd, err = loadOllamaInitCmd(c)
case "container":
initCmd, err = loadContainerInitCmd(c)
case "database":
initCmd, err = loadDatabaseInitCmd(c)
containerID, initCmd, err = loadContainerInitCmd(c)
default:
if wshandleError(wsConn, fmt.Errorf("not support such source %s", source)) {
return
@@ -103,10 +103,12 @@ func (b *BaseApi) ContainerWsSSH(c *gin.Context) {
if wshandleError(wsConn, err) {
return
}
pidMap := loadMapFromDockerTop(containerID)
slave, err := terminal.NewCommand("docker", initCmd...)
if wshandleError(wsConn, err) {
return
}
defer killBash(containerID, strings.ReplaceAll(strings.Join(initCmd, " "), fmt.Sprintf("exec -it %s ", containerID), ""), pidMap)
defer slave.Close()
tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, false)
@@ -125,18 +127,18 @@ func (b *BaseApi) ContainerWsSSH(c *gin.Context) {
_ = wsConn.WriteControl(websocket.CloseMessage, nil, dt)
}
func loadRedisInitCmd(c *gin.Context, redisType string) ([]string, error) {
func loadRedisInitCmd(c *gin.Context, redisType string) (string, []string, error) {
name := c.Query("name")
from := c.Query("from")
commands := []string{"exec", "-it"}
database, err := databaseService.Get(name)
if err != nil {
return nil, fmt.Errorf("no such database in db, err: %v", err)
return "", nil, fmt.Errorf("no such database in db, err: %v", err)
}
if from == "local" {
redisInfo, err := appInstallService.LoadConnInfo(dto.OperationWithNameAndType{Name: name, Type: redisType})
if err != nil {
return nil, fmt.Errorf("no such app in db, err: %v", err)
return "", nil, fmt.Errorf("no such app in db, err: %v", err)
}
name = redisInfo.ContainerName
commands = append(commands, []string{name, "redis-cli"}...)
@@ -150,61 +152,38 @@ func loadRedisInitCmd(c *gin.Context, redisType string) ([]string, error) {
commands = append(commands, []string{"-a", database.Password, "--no-auth-warning"}...)
}
}
return commands, nil
return name, commands, nil
}
func loadOllamaInitCmd(c *gin.Context) ([]string, error) {
func loadOllamaInitCmd(c *gin.Context) (string, []string, error) {
name := c.Query("name")
if cmd.CheckIllegal(name) {
return nil, fmt.Errorf("ollama model %s contains illegal characters", name)
return "", nil, fmt.Errorf("ollama model %s contains illegal characters", name)
}
ollamaInfo, err := appInstallService.LoadConnInfo(dto.OperationWithNameAndType{Name: "", Type: "ollama"})
if err != nil {
return nil, fmt.Errorf("no such app in db, err: %v", err)
return "", nil, fmt.Errorf("no such app in db, err: %v", err)
}
containerName := ollamaInfo.ContainerName
return []string{"exec", "-it", containerName, "ollama", "run", name}, nil
return containerName, []string{"exec", "-it", containerName, "ollama", "run", name}, nil
}
func loadContainerInitCmd(c *gin.Context) ([]string, error) {
func loadContainerInitCmd(c *gin.Context) (string, []string, error) {
containerID := c.Query("containerid")
command := c.Query("command")
user := c.Query("user")
if cmd.CheckIllegal(user, containerID, command) {
return nil, fmt.Errorf("the command contains illegal characters. command: %s, user: %s, containerID: %s", command, user, containerID)
return "", nil, fmt.Errorf("the command contains illegal characters. command: %s, user: %s, containerID: %s", command, user, containerID)
}
if len(command) == 0 || len(containerID) == 0 {
return nil, fmt.Errorf("error param of command: %s or containerID: %s", command, containerID)
return "", nil, fmt.Errorf("error param of command: %s or containerID: %s", command, containerID)
}
commands := []string{"exec", "-it", containerID, command}
if len(user) != 0 {
commands = []string{"exec", "-it", "-u", user, containerID, command}
}
return commands, nil
}
func loadDatabaseInitCmd(c *gin.Context) ([]string, error) {
database := c.Query("database")
databaseType := c.Query("databaseType")
if len(database) == 0 || len(databaseType) == 0 {
return nil, fmt.Errorf("error param of database: %s or database type: %s", database, databaseType)
}
databaseConn, err := appInstallService.LoadConnInfo(dto.OperationWithNameAndType{Type: databaseType, Name: database})
if err != nil {
return nil, fmt.Errorf("no such database in db, err: %v", err)
}
commands := []string{"exec", "-it", databaseConn.ContainerName}
switch databaseType {
case "mysql", "mysql-cluster":
commands = append(commands, []string{"mysql", "-uroot", "-p" + databaseConn.Password}...)
case "mariadb":
commands = append(commands, []string{"mariadb", "-uroot", "-p" + databaseConn.Password}...)
case "postgresql", "postgresql-cluster":
commands = []string{"exec", "-e", fmt.Sprintf("PGPASSWORD=%s", databaseConn.Password), "-it", databaseConn.ContainerName, "psql", "-t", "-U", databaseConn.Username}
}
return commands, nil
return containerID, commands, nil
}
func wshandleError(ws *websocket.Conn, err error) bool {
@@ -227,6 +206,42 @@ func wshandleError(ws *websocket.Conn, err error) bool {
return false
}
func loadMapFromDockerTop(containerID string) map[string]string {
pidMap := make(map[string]string)
sudo := cmd.SudoHandleCmd()
stdout, err := cmd.RunDefaultWithStdoutBashCf("%s docker top %s -eo pid,command ", sudo, containerID)
if err != nil {
return pidMap
}
lines := strings.Split(stdout, "\n")
for _, line := range lines {
parts := strings.Fields(line)
if len(parts) < 2 {
continue
}
pidMap[parts[0]] = strings.Join(parts[1:], " ")
}
return pidMap
}
func killBash(containerID, comm string, pidMap map[string]string) {
sudo := cmd.SudoHandleCmd()
newPidMap := loadMapFromDockerTop(containerID)
for pid, command := range newPidMap {
isOld := false
for pid2 := range pidMap {
if pid == pid2 {
isOld = true
break
}
}
if !isOld && command == comm {
_, _ = cmd.RunDefaultWithStdoutBashCf("%s kill -9 %s", sudo, pid)
}
}
}
var upGrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024 * 1024 * 10,
-62
View File
@@ -1141,65 +1141,3 @@ func (b *BaseApi) ExecComposer(c *gin.Context) {
}
helper.Success(c)
}
// @Tags Website
// @Summary Batch operate websites
// @Accept json
// @Param request body request.BatchOpWebsite true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/batch/operate [post]
func (b *BaseApi) BatchOpWebsites(c *gin.Context) {
var req request.BatchWebsiteOp
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.BatchOpWebsite(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
// @Tags Website
// @Summary Get CORS Config
// @Accept json
// @Param id path int true "id"
// @Success 200 {object} request.CorsConfig
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/cors/{id} [get]
func (b *BaseApi) GetCORSConfig(c *gin.Context) {
id, err := helper.GetParamID(c)
if err != nil {
helper.BadRequest(c, err)
return
}
res, err := websiteService.GetCors(id)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, res)
}
// @Tags Website
// @Summary Update CORS Config
// @Accept json
// @Param request body request.CorsConfigReq true "request"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/cors/update [post]
func (b *BaseApi) UpdateCORSConfig(c *gin.Context) {
var req request.CorsConfigReq
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.UpdateCors(req); err != nil {
helper.InternalServer(c, err)
return
}
helper.Success(c)
}
-75
View File
@@ -2,8 +2,6 @@ package v2
import (
"github.com/1Panel-dev/1Panel/agent/app/model"
"io"
"mime/multipart"
"net/http"
"net/url"
"reflect"
@@ -219,79 +217,6 @@ func (b *BaseApi) UploadWebsiteSSL(c *gin.Context) {
helper.Success(c)
}
// @Tags Website SSL
// @Summary Upload SSL file
// @Accept multipart/form-data
// @Param type formData string true "type"
// @Param description formData string false "description"
// @Param sslID formData string false "sslID"
// @Param privateKeyFile formData file true "privateKeyFile"
// @Param certificateFile formData file true "certificateFile"
// @Success 200
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /websites/ssl/upload/file [post]
// @x-panel-log {"bodyKeys":["type"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"上传 ssl 文件 [type]","formatEN":"Upload ssl file [type]"}
func (b *BaseApi) UploadSSLFile(c *gin.Context) {
var req request.WebsiteSSLFileUpload
req.Type = c.PostForm("type")
req.Description = c.PostForm("description")
sslID := c.PostForm("sslID")
if sslID != "" {
req.SSLID, _ = strconv.ParseUint(sslID, 10, 64)
}
privateKeyFile, err := c.FormFile("privateKeyFile")
if err != nil {
helper.InternalServer(c, err)
return
}
certificateFile, err := c.FormFile("certificateFile")
if err != nil {
helper.InternalServer(c, err)
return
}
privateKeyContent, err := readUploadedFile(privateKeyFile)
if err != nil {
helper.InternalServer(c, err)
return
}
certificateContent, err := readUploadedFile(certificateFile)
if err != nil {
helper.InternalServer(c, err)
return
}
uploadReq := request.WebsiteSSLUpload{
Type: "paste",
PrivateKey: string(privateKeyContent),
Certificate: string(certificateContent),
Description: req.Description,
SSLID: uint(req.SSLID),
}
if err := websiteSSLService.Upload(uploadReq); err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, nil)
}
func readUploadedFile(fileHeader *multipart.FileHeader) ([]byte, error) {
file, err := fileHeader.Open()
if err != nil {
return nil, err
}
defer file.Close()
return io.ReadAll(file)
}
// @Tags Website SSL
// @Summary Download SSL file
// @Accept json
-2
View File
@@ -292,7 +292,6 @@ type AlertConfigTest struct {
Host string `json:"host"`
Port int `json:"port"`
Sender string `json:"sender"`
UserName string `json:"userName"`
Password string `json:"password"`
DisplayName string `json:"displayName"`
Encryption string `json:"encryption"` // "ssl" / "tls" / "none"
@@ -324,7 +323,6 @@ type AlertEmailConfig struct {
Host string `json:"host"`
Port int `json:"port"`
Sender string `json:"sender"`
UserName string `json:"userName"`
Password string `json:"password"`
DisplayName string `json:"displayName"`
Encryption string `json:"encryption"` // "ssl" / "tls" / "none"
-1
View File
@@ -128,7 +128,6 @@ type Locale struct {
Zh string `json:"zh"`
Ko string `json:"ko"`
Tr string `json:"tr"`
Es string `json:"es-es" yaml:"es-es"`
}
type AppForm struct {
-3
View File
@@ -99,9 +99,6 @@ type BackupRecords struct {
DownloadAccountID uint `json:"downloadAccountID"`
FileDir string `json:"fileDir"`
FileName string `json:"fileName"`
TaskID string `json:"taskID"`
Status string `json:"status"`
Message string `json:"message"`
Description string `json:"description"`
}
-3
View File
@@ -33,7 +33,6 @@ type ClamInfo struct {
LastRecordStatus string `json:"lastRecordStatus"`
LastRecordTime string `json:"lastRecordTime"`
Spec string `json:"spec"`
Timeout uint `json:"timeout"`
Description string `json:"description"`
AlertCount uint `json:"alertCount"`
AlertMethod string `json:"alertMethod"`
@@ -78,7 +77,6 @@ type ClamCreate struct {
InfectedStrategy string `json:"infectedStrategy"`
InfectedDir string `json:"infectedDir"`
Spec string `json:"spec"`
Timeout uint `json:"timeout"`
Description string `json:"description"`
AlertCount uint `json:"alertCount"`
AlertTitle string `json:"alertTitle"`
@@ -93,7 +91,6 @@ type ClamUpdate struct {
InfectedStrategy string `json:"infectedStrategy"`
InfectedDir string `json:"infectedDir"`
Spec string `json:"spec"`
Timeout uint `json:"timeout"`
Description string `json:"description"`
AlertCount uint `json:"alertCount"`
AlertTitle string `json:"alertTitle"`
+1 -1
View File
@@ -71,6 +71,7 @@ type ResourceLimit struct {
type ContainerOperate struct {
TaskID string `json:"taskID"`
ContainerID string `json:"containerID"`
ForcePull bool `json:"forcePull"`
Name string `json:"name" validate:"required"`
Image string `json:"image" validate:"required"`
@@ -143,7 +144,6 @@ type VolumeHelper struct {
SourceDir string `json:"sourceDir"`
ContainerDir string `json:"containerDir"`
Mode string `json:"mode"`
Shared string `json:"shared"`
}
type PortHelper struct {
HostIP string `json:"hostIP"`
-1
View File
@@ -34,7 +34,6 @@ type ChangeQuicks struct {
type QuickJump struct {
ID uint `json:"id"`
Name string `json:"name"`
Alias string `json:"alias"`
Title string `json:"title"`
Detail string `json:"detail"`
Recommend int `json:"recommend"`
+1 -2
View File
@@ -27,8 +27,7 @@ type SwapHelper struct {
Size uint64 `json:"size"`
Used string `json:"used"`
IsNew bool `json:"isNew"`
TaskID string `json:"taskID"`
IsNew bool `json:"isNew"`
}
type TimeZoneOptions struct {
-1
View File
@@ -37,7 +37,6 @@ type ForwardRuleOperate struct {
Operation string `json:"operation" validate:"required,oneof=add remove"`
Num string `json:"num"`
Protocol string `json:"protocol" validate:"required,oneof=tcp udp tcp/udp"`
Interface string `json:"interface"`
Port string `json:"port" validate:"required"`
TargetIP string `json:"targetIP"`
TargetPort string `json:"targetPort" validate:"required"`
+5 -5
View File
@@ -30,14 +30,14 @@ type ImageBuild struct {
}
type ImagePull struct {
TaskID string `json:"taskID"`
RepoID uint `json:"repoID"`
ImageName []string `json:"imageName" validate:"required"`
TaskID string `json:"taskID"`
RepoID uint `json:"repoID"`
ImageName string `json:"imageName" validate:"required"`
}
type ImageTag struct {
SourceID string `json:"sourceID" validate:"required"`
Tags []string `json:"tags" validate:"required"`
SourceID string `json:"sourceID" validate:"required"`
TargetName string `json:"targetName" validate:"required"`
}
type ImagePush struct {
-16
View File
@@ -148,19 +148,3 @@ type FileExistReq struct {
Name string `json:"name" validate:"required"`
Dir string `json:"dir" validate:"required"`
}
type FileConvert struct {
Path string `json:"path" validate:"required"`
Type string `json:"type" validate:"required"`
InputFile string `json:"inputFile" validate:"required"`
Extension string `json:"extension" validate:"required"`
OutputFormat string `json:"outputFormat" validate:"required"`
Status string `json:"status"`
}
type FileConvertRequest struct {
Files []FileConvert `json:"files" validate:"required"`
OutputPath string `json:"outputPath" validate:"required"`
DeleteSource bool `json:"deleteSource"`
TaskID string `json:"taskID"`
}
-1
View File
@@ -34,7 +34,6 @@ type SupervisorProcessConfig struct {
Numprocs string `json:"numprocs"`
AutoRestart string `json:"autoRestart"`
AutoStart string `json:"autoStart"`
Environment string `json:"environment"`
}
type SupervisorProcessFileReq struct {
-1
View File
@@ -100,7 +100,6 @@ type PHPConfigUpdate struct {
Scope string `json:"scope" validate:"required"`
DisableFunctions []string `json:"disableFunctions"`
UploadMaxSize string `json:"uploadMaxSize"`
MaxExecutionTime string `json:"maxExecutionTime"`
}
type PHPFileUpdate struct {
-40
View File
@@ -1,40 +0,0 @@
package request
import "github.com/1Panel-dev/1Panel/agent/app/dto"
type TensorRTLLMSearch struct {
dto.PageInfo
Name string `json:"name"`
}
type TensorRTLLMCreate struct {
Name string `json:"name" validate:"required"`
ContainerName string `json:"containerName" validate:"required"`
Version string `json:"version" validate:"required"`
ModelDir string `json:"modelDir" validate:"required"`
Image string `json:"image" validate:"required"`
Command string `json:"command" validate:"required"`
ModelType string `json:"modelType"`
ModelSpeedup bool `json:"modelSpeedup"`
DockerConfig
}
type TensorRTLLMUpdate struct {
ID uint `json:"id" validate:"required"`
TensorRTLLMCreate
}
type TensorRTLLMDelete struct {
ID uint `json:"id" validate:"required"`
}
type TensorRTLLMOperate struct {
ID uint `json:"id" validate:"required"`
Operate string `json:"operate" validate:"required"`
}
type DockerConfig struct {
ExposedPorts []ExposedPort `json:"exposedPorts"`
Environments []Environment `json:"environments"`
Volumes []Volume `json:"volumes"`
}
-22
View File
@@ -95,7 +95,6 @@ type WebsiteDelete struct {
DeleteApp bool `json:"deleteApp"`
DeleteBackup bool `json:"deleteBackup"`
ForceDelete bool `json:"forceDelete"`
DeleteDB bool `json:"deleteDB"`
}
type WebsiteOp struct {
@@ -103,12 +102,6 @@ type WebsiteOp struct {
Operate string `json:"operate"`
}
type BatchWebsiteOp struct {
IDs []uint `json:"ids" validate:"required"`
Operate string `json:"operate" validate:"required"`
TaskID string `json:"taskID" validate:"required"`
}
type WebsiteRedirectUpdate struct {
WebsiteID uint `json:"websiteId" validate:"required"`
Key string `json:"key" validate:"required"`
@@ -229,21 +222,6 @@ type WebsiteProxyConfig struct {
Replaces map[string]string `json:"replaces"`
SNI bool `json:"sni"`
ProxySSLName string `json:"proxySSLName"`
CorsConfig
}
type CorsConfig struct {
Cors bool `json:"cors"`
AllowOrigins string `json:"allowOrigins"`
AllowMethods string `json:"allowMethods"`
AllowHeaders string `json:"allowHeaders"`
AllowCredentials bool `json:"allowCredentials"`
Preflight bool `json:"preflight"`
}
type CorsConfigReq struct {
WebsiteID uint `json:"websiteID" validate:"required"`
CorsConfig
}
type WebsiteProxyReq struct {
-6
View File
@@ -157,9 +157,3 @@ type WebsiteCAObtain struct {
type WebsiteCARenew struct {
SSLID uint `json:"SSLID" validate:"required"`
}
type WebsiteSSLFileUpload struct {
Type string `json:"type"`
Description string `json:"description"`
SSLID uint64 `json:"sslID"`
}
-8
View File
@@ -73,11 +73,3 @@ type DepthDirSizeRes struct {
Path string `json:"path"`
Size int64 `json:"size"`
}
type FileConvertLog struct {
Date string `json:"date"`
Type string `json:"type"`
Log string `json:"log"`
Status string `json:"status"`
Message string `json:"message"`
}
-1
View File
@@ -32,7 +32,6 @@ type SupervisorProcessConfig struct {
Status []ProcessStatus `json:"status"`
AutoRestart string `json:"autoRestart"`
AutoStart string `json:"autoStart"`
Environment string `json:"environment"`
}
type ProcessStatus struct {
-25
View File
@@ -1,25 +0,0 @@
package response
import (
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
"github.com/1Panel-dev/1Panel/agent/app/model"
)
type TensorRTLLMsRes struct {
Items []TensorRTLLMDTO `json:"items"`
Total int64 `json:"total"`
}
type TensorRTLLMDTO struct {
model.TensorRTLLM
Version string `json:"version"`
Model string `json:"model"`
Dir string `json:"dir"`
ModelDir string `json:"modelDir"`
Image string `json:"image"`
Command string `json:"command"`
ExposedPorts []request.ExposedPort `json:"exposedPorts"`
Environments []request.Environment `json:"environments"`
Volumes []request.Volume `json:"volumes"`
}
+10 -11
View File
@@ -59,16 +59,16 @@ type WebsiteNginxConfig struct {
}
type WebsiteHTTPS struct {
Enable bool `json:"enable"`
HttpConfig string `json:"httpConfig"`
SSL model.WebsiteSSL `json:"SSL"`
SSLProtocol []string `json:"SSLProtocol"`
Algorithm string `json:"algorithm"`
Hsts bool `json:"hsts"`
HstsIncludeSubDomains bool `json:"hstsIncludeSubDomains"`
HttpsPorts []int `json:"httpsPorts"`
HttpsPort string `json:"httpsPort"`
Http3 bool `json:"http3"`
Enable bool `json:"enable"`
HttpConfig string `json:"httpConfig"`
SSL model.WebsiteSSL `json:"SSL"`
SSLProtocol []string `json:"SSLProtocol"`
Algorithm string `json:"algorithm"`
Hsts bool `json:"hsts"`
HstsIncludeSubDomains bool `json:"hstsIncludeSubDomains"`
HttpsPorts []int `json:"httpsPorts"`
HttpsPort string `json:"httpsPort"`
Http3 bool `json:"http3"`
}
type WebsiteLog struct {
@@ -82,7 +82,6 @@ type PHPConfig struct {
Params map[string]string `json:"params"`
DisableFunctions []string `json:"disableFunctions"`
UploadMaxSize string `json:"uploadMaxSize"`
MaxExecutionTime string `json:"maxExecutionTime"`
}
type NginxRewriteRes struct {
-2
View File
@@ -69,8 +69,6 @@ type SSHConnData struct {
Password string `json:"password"`
PrivateKey string `json:"privateKey"`
PassPhrase string `json:"passPhrase"`
LocalSSHConnShow string `json:"localSSHConnShow"`
}
type SystemProxy struct {
+1 -2
View File
@@ -22,8 +22,7 @@ type SSHInfo struct {
CurrentUser string `json:"currentUser"`
}
type RootCertOperate struct {
ID uint `json:"id"`
type CreateRootCert struct {
Name string `json:"name"`
Mode string `json:"mode"`
EncryptionMode string `json:"encryptionMode" validate:"required,oneof=rsa ed25519 ecdsa dsa"`
+1 -7
View File
@@ -43,17 +43,11 @@ type App struct {
func (i *App) IsLocalApp() bool {
return i.Resource == constant.ResourceLocal
}
func (i *App) IsCustomApp() bool {
return i.Resource == constant.AppResourceCustom
}
func (i *App) GetAppResourcePath() string {
if i.IsLocalApp() {
//这里要去掉本地应用的local前缀
return filepath.Join(global.Dir.LocalAppResourceDir, strings.TrimPrefix(i.Key, "local"))
}
if i.IsCustomApp() {
return filepath.Join(global.Dir.CustomAppResourceDir, i.Key)
}
return filepath.Join(global.Dir.RemoteAppResourceDir, i.Key)
}
-1
View File
@@ -8,7 +8,6 @@ type AppLauncher struct {
type QuickJump struct {
BaseModel
Name string `json:"name"`
Alias string `json:"alias"`
Title string `json:"title"`
Detail string `json:"detail"`
Recommend int `json:"recommend"`
-3
View File
@@ -27,8 +27,5 @@ type BackupRecord struct {
FileDir string `json:"fileDir"`
FileName string `json:"fileName"`
TaskID string `json:"taskID"`
Status string `json:"status"`
Message string `json:"message"`
Description string `json:"description"`
}
-2
View File
@@ -10,8 +10,6 @@ type Clam struct {
InfectedStrategy string `json:"infectedStrategy"`
InfectedDir string `json:"infectedDir"`
Spec string `json:"spec"`
RetryTimes uint `json:"retryTimes"`
Timeout uint `json:"timeout"`
EntryID int `json:"entryID"`
Description string `json:"description"`
-2
View File
@@ -43,8 +43,6 @@ type Cronjob struct {
EntryIDs string `json:"entryIDs"`
Records []JobRecords `json:"records"`
Secret string `json:"secret"`
Config string `json:"config"`
}
type JobRecords struct {
-1
View File
@@ -18,5 +18,4 @@ type Forward struct {
Port string `gorm:"not null" json:"port"`
TargetIP string `gorm:"not null" json:"targetIP"`
TargetPort string `gorm:"not null" json:"targetPort"`
Interface string `json:"interface"`
}
+3 -7
View File
@@ -2,18 +2,14 @@ package model
type MonitorBase struct {
BaseModel
Cpu float64 `json:"cpu"`
TopCPU string `json:"topCPU"`
TopCPUItems interface{} `gorm:"-" json:"topCPUItems"`
Memory float64 `json:"memory"`
TopMem string `json:"topMem"`
TopMemItems interface{} `gorm:"-" json:"topMemItems"`
Cpu float64 `json:"cpu"`
LoadUsage float64 `json:"loadUsage"`
CpuLoad1 float64 `json:"cpuLoad1"`
CpuLoad5 float64 `json:"cpuLoad5"`
CpuLoad15 float64 `json:"cpuLoad15"`
Memory float64 `json:"memory"`
}
type MonitorIO struct {
-4
View File
@@ -49,7 +49,3 @@ func (r *Runtime) GetPHPPath() string {
func (r *Runtime) GetLogPath() string {
return path.Join(r.GetPath(), "build.log")
}
func (r *Runtime) GetSlowLogPath() string {
return path.Join(r.GetPath(), "log", "fpm.slow.log")
}
-14
View File
@@ -1,14 +0,0 @@
package model
type TensorRTLLM struct {
BaseModel
Name string `json:"name"`
DockerCompose string `json:"dockerCompose"`
ContainerName string `json:"containerName"`
Message string `json:"message"`
Status string `json:"status"`
Env string `json:"env"`
TaskID string `json:"taskID"`
ModelType string `json:"modelType"`
ModelSpeedup bool `json:"modelSpeedup"`
}
+29 -31
View File
@@ -10,37 +10,35 @@ import (
type WebsiteSSL struct {
BaseModel
PrimaryDomain string `json:"primaryDomain"`
PrivateKey string `json:"privateKey"`
Pem string `json:"pem"`
Domains string `json:"domains"`
CertURL string `json:"certURL"`
Type string `json:"type"`
Provider string `json:"provider"`
Organization string `json:"organization"`
DnsAccountID uint `json:"dnsAccountId"`
AcmeAccountID uint `gorm:"column:acme_account_id" json:"acmeAccountId" `
CaID uint `json:"caId"`
AutoRenew bool `json:"autoRenew"`
ExpireDate time.Time `json:"expireDate"`
StartDate time.Time `json:"startDate"`
Status string `json:"status"`
Message string `json:"message"`
KeyType string `json:"keyType"`
PushDir bool `json:"pushDir"`
Dir string `json:"dir"`
Description string `json:"description"`
SkipDNS bool `json:"skipDNS"`
Nameserver1 string `json:"nameserver1"`
Nameserver2 string `json:"nameserver2"`
DisableCNAME bool `json:"disableCNAME"`
ExecShell bool `json:"execShell"`
Shell string `json:"shell"`
MasterSSLID uint `json:"masterSslId"`
Nodes string `json:"nodes"`
PushNode bool `json:"pushNode"`
PrivateKeyPath string `json:"privateKeyPath"`
CertPath string `json:"certPath"`
PrimaryDomain string `json:"primaryDomain"`
PrivateKey string `json:"privateKey"`
Pem string `json:"pem"`
Domains string `json:"domains"`
CertURL string `json:"certURL"`
Type string `json:"type"`
Provider string `json:"provider"`
Organization string `json:"organization"`
DnsAccountID uint `json:"dnsAccountId"`
AcmeAccountID uint `gorm:"column:acme_account_id" json:"acmeAccountId" `
CaID uint `json:"caId"`
AutoRenew bool `json:"autoRenew"`
ExpireDate time.Time `json:"expireDate"`
StartDate time.Time `json:"startDate"`
Status string `json:"status"`
Message string `json:"message"`
KeyType string `json:"keyType"`
PushDir bool `json:"pushDir"`
Dir string `json:"dir"`
Description string `json:"description"`
SkipDNS bool `json:"skipDNS"`
Nameserver1 string `json:"nameserver1"`
Nameserver2 string `json:"nameserver2"`
DisableCNAME bool `json:"disableCNAME"`
ExecShell bool `json:"execShell"`
Shell string `json:"shell"`
MasterSSLID uint `json:"masterSslId"`
Nodes string `json:"nodes"`
PushNode bool `json:"pushNode"`
AcmeAccount WebsiteAcmeAccount `json:"acmeAccount" gorm:"-:migration"`
DnsAccount WebsiteDnsAccount `json:"dnsAccount" gorm:"-:migration"`
-1
View File
@@ -95,7 +95,6 @@ func (u *LauncherRepo) UpdateQuicks(quicks []model.QuickJump) error {
if err := tx.Model(&model.QuickJump{}).Where("id = ?", item.ID).Updates(map[string]interface{}{
"is_show": item.IsShow,
"detail": item.Detail,
"alias": item.Alias,
}).Error; err != nil {
tx.Rollback()
return err
+3 -3
View File
@@ -19,7 +19,7 @@ type IHostRepo interface {
GetCert(opts ...DBOption) (model.RootCert, error)
PageCert(limit, offset int, opts ...DBOption) (int64, []model.RootCert, error)
ListCert(opts ...DBOption) ([]model.RootCert, error)
SaveCert(cert *model.RootCert) error
CreateCert(cert *model.RootCert) error
UpdateCert(id uint, vars map[string]interface{}) error
DeleteCert(opts ...DBOption) error
}
@@ -107,8 +107,8 @@ func (u *HostRepo) ListCert(opts ...DBOption) ([]model.RootCert, error) {
return ops, err
}
func (u *HostRepo) SaveCert(cert *model.RootCert) error {
return global.DB.Save(cert).Error
func (u *HostRepo) CreateCert(cert *model.RootCert) error {
return global.DB.Create(cert).Error
}
func (u *HostRepo) UpdateCert(id uint, vars map[string]interface{}) error {
-7
View File
@@ -24,7 +24,6 @@ type ITaskRepo interface {
DeleteAll() error
WithByID(id string) DBOption
WithByIDNotIn(ids []string) DBOption
WithResourceID(id uint) DBOption
WithOperate(taskOperate string) DBOption
WithByStatus(status string) DBOption
@@ -59,12 +58,6 @@ func (t TaskRepo) WithByID(id string) DBOption {
}
}
func (t TaskRepo) WithByIDNotIn(ids []string) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("id not in (?)", ids)
}
}
func (t TaskRepo) WithOperate(taskOperate string) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("operate = ?", taskOperate)
-56
View File
@@ -1,56 +0,0 @@
package repo
import "github.com/1Panel-dev/1Panel/agent/app/model"
type TensorRTLLMRepo struct {
}
type ITensorRTLLMRepo interface {
Page(page, size int, opts ...DBOption) (int64, []model.TensorRTLLM, error)
GetFirst(opts ...DBOption) (*model.TensorRTLLM, error)
Create(tensorrtLLM *model.TensorRTLLM) error
Save(tensorrtLLM *model.TensorRTLLM) error
DeleteBy(opts ...DBOption) error
List(opts ...DBOption) ([]model.TensorRTLLM, error)
}
func NewITensorRTLLMRepo() ITensorRTLLMRepo {
return &TensorRTLLMRepo{}
}
func (t TensorRTLLMRepo) Page(page, size int, opts ...DBOption) (int64, []model.TensorRTLLM, error) {
var servers []model.TensorRTLLM
db := getDb(opts...).Model(&model.TensorRTLLM{})
count := int64(0)
db = db.Count(&count)
err := db.Limit(size).Offset(size * (page - 1)).Find(&servers).Error
return count, servers, err
}
func (t TensorRTLLMRepo) GetFirst(opts ...DBOption) (*model.TensorRTLLM, error) {
var tensorrtLLM model.TensorRTLLM
if err := getDb(opts...).First(&tensorrtLLM).Error; err != nil {
return nil, err
}
return &tensorrtLLM, nil
}
func (t TensorRTLLMRepo) List(opts ...DBOption) ([]model.TensorRTLLM, error) {
var tensorrtLLMs []model.TensorRTLLM
if err := getDb(opts...).Find(&tensorrtLLMs).Error; err != nil {
return nil, err
}
return tensorrtLLMs, nil
}
func (t TensorRTLLMRepo) Create(tensorrtLLM *model.TensorRTLLM) error {
return getDb().Create(tensorrtLLM).Error
}
func (t TensorRTLLMRepo) Save(tensorrtLLM *model.TensorRTLLM) error {
return getDb().Save(tensorrtLLM).Error
}
func (t TensorRTLLMRepo) DeleteBy(opts ...DBOption) error {
return getDb(opts...).Delete(&model.TensorRTLLM{}).Error
}
+1 -5
View File
@@ -479,14 +479,10 @@ func (a AlertService) DeleteAlertConfig(id uint) error {
}
func (a AlertService) TestAlertConfig(req dto.AlertConfigTest) (bool, error) {
username := req.UserName
if username == "" {
username = req.Sender
}
cfg := email.SMTPConfig{
Host: req.Host,
Port: req.Port,
Username: username,
Username: req.Sender,
Password: req.Password,
From: fmt.Sprintf("%s <%s>", req.DisplayName, req.Sender),
Encryption: req.Encryption,
+2 -16
View File
@@ -7,7 +7,6 @@ import (
"fmt"
"net/http"
"os"
"path"
"path/filepath"
"reflect"
"strconv"
@@ -73,11 +72,7 @@ func (a AppService) PageApp(ctx *gin.Context, req request.AppSearch) (interface{
if err != nil {
return nil, err
}
kernelArch := info.KernelArch
if kernelArch == "aarch64" {
kernelArch = "arm64"
}
opts = append(opts, appRepo.WithArch(kernelArch))
opts = append(opts, appRepo.WithArch(info.KernelArch))
}
if len(req.Tags) != 0 {
tags, err := tagRepo.GetByKeys(req.Tags)
@@ -112,7 +107,7 @@ func (a AppService) PageApp(ctx *gin.Context, req request.AppSearch) (interface{
lang := strings.ToLower(common.GetLang(ctx))
for _, ap := range apps {
if req.Type == "php" {
if !global.CONF.Base.IsOffLine && (ap.RequiredPanelVersion == 0 || !common.CompareAppVersion(common.GetSystemVersion(info.SystemVersion), fmt.Sprintf("%f", ap.RequiredPanelVersion))) {
if ap.RequiredPanelVersion == 0 || !common.CompareAppVersion(common.GetSystemVersion(info.SystemVersion), fmt.Sprintf("%f", ap.RequiredPanelVersion)) {
continue
}
}
@@ -485,15 +480,6 @@ func (a AppService) Install(req request.AppInstallCreate) (appInstall *model.App
req.Params["RESTY_ADD_PACKAGE_BUILDDEPS"] = ""
req.Params["RESTY_CONFIG_OPTIONS_MORE"] = ""
}
if app.Key == "openresty" && (app.Resource == "remote" || app.Resource == "custom") && common.CompareVersion(appDetail.Version, "1.27") {
if dir, ok := req.Params["WEBSITE_DIR"]; ok {
siteDir := dir.(string)
if siteDir == "" || !strings.HasPrefix(siteDir, "/") {
siteDir = path.Join(global.Dir.DataDir, dir.(string))
}
req.Params["WEBSITE_DIR"] = siteDir
}
}
paramByte, err = json.Marshal(req.Params)
if err != nil {
return
+21 -25
View File
@@ -677,29 +677,29 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
backupFile string
)
backUpApp := func(t *task.Task) error {
backupService := NewIBackupService()
backupRecordService := NewIBackupRecordService()
fileName := fmt.Sprintf("upgrade_backup_%s_%s.tar.gz", install.Name, time.Now().Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5))
backupRecord, err := backupService.AppBackup(dto.CommonBackup{Name: install.App.Key, DetailName: install.Name, FileName: fileName})
if err == nil {
backups, _ := backupRecordService.ListAppRecords(install.App.Key, install.Name, "upgrade_backup")
if len(backups) > 3 {
backupsToDelete := backups[:len(backups)-3]
var deleteIDs []uint
for _, backup := range backupsToDelete {
deleteIDs = append(deleteIDs, backup.ID)
if req.Backup {
backupService := NewIBackupService()
backupRecordService := NewIBackupRecordService()
fileName := fmt.Sprintf("upgrade_backup_%s_%s.tar.gz", install.Name, time.Now().Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5))
backupRecord, err := backupService.AppBackup(dto.CommonBackup{Name: install.App.Key, DetailName: install.Name, FileName: fileName})
if err == nil {
backups, _ := backupRecordService.ListAppRecords(install.App.Key, install.Name, "upgrade_backup")
if len(backups) > 3 {
backupsToDelete := backups[:len(backups)-3]
var deleteIDs []uint
for _, backup := range backupsToDelete {
deleteIDs = append(deleteIDs, backup.ID)
}
_ = backupRecordService.BatchDeleteRecord(deleteIDs)
}
_ = backupRecordService.BatchDeleteRecord(deleteIDs)
backupFile = path.Join(global.Dir.LocalBackupDir, backupRecord.FileDir, backupRecord.FileName)
} else {
return buserr.WithNameAndErr("ErrAppBackup", install.Name, err)
}
backupFile = path.Join(global.Dir.LocalBackupDir, backupRecord.FileDir, backupRecord.FileName)
} else {
return buserr.WithNameAndErr("ErrAppBackup", install.Name, err)
}
return nil
}
if req.Backup {
upgradeTask.AddSubTask(task.GetTaskName(install.Name, task.TaskBackup, task.TaskScopeApp), backUpApp, nil)
}
upgradeTask.AddSubTask(task.GetTaskName(install.Name, task.TaskBackup, task.TaskScopeApp), backUpApp, nil)
upgradeApp := func(t *task.Task) error {
fileOp := files.NewFileOp()
@@ -946,7 +946,7 @@ func handleMap(params map[string]interface{}, envParams map[string]string) {
}
func downloadApp(app model.App, appDetail model.AppDetail, appInstall *model.AppInstall, logger *log.Logger) (err error) {
if app.IsLocalApp() || app.IsCustomApp() {
if app.IsLocalApp() {
return nil
}
appResourceDir := path.Join(global.Dir.AppResourceDir, app.Resource)
@@ -1163,11 +1163,7 @@ func upApp(task *task.Task, appInstall *model.AppInstall, pullImages bool) error
appInstall.Message = errMsg + errOur
installErr := errors.New(appInstall.Message)
task.LogFailedWithErr(i18n.GetMsgByKey("PullImage"), installErr)
if exist, _ := dockerCLi.ImageExists(image); !exist {
return installErr
} else {
task.Log(i18n.GetMsgByKey("UseExistImage"))
}
return installErr
} else {
task.Log(i18n.GetMsgByKey("PullImageSuccess"))
}
@@ -2067,7 +2063,7 @@ func handleSSLConfig(appInstall *model.AppInstall, hasDefaultWebsite bool) error
}
defaultConfig.FilePath = defaultConfigPath
defaultServer := defaultConfig.FindServers()[0]
updateDefaultServer(defaultServer, appInstall.HttpPort, appInstall.HttpsPort, !hasDefaultWebsite, true)
updateDefaultServer(defaultServer, appInstall.HttpPort, appInstall.HttpsPort, !hasDefaultWebsite)
defaultServer.UpdateDirective("include", []string{"/usr/local/openresty/nginx/conf/ssl/root_ssl.conf"})
defaultServer.UpdateDirective("http2", []string{"on"})
if err = nginx.WriteConfig(defaultConfig, nginx.IndentedStyle); err != nil {
+46 -50
View File
@@ -45,29 +45,36 @@ func (u *BackupService) AppBackup(req dto.CommonBackup) (*model.BackupRecord, er
fileName = fmt.Sprintf("%s_%s.tar.gz", req.DetailName, timeNow+common.RandStrAndNum(5))
}
record := &model.BackupRecord{
Type: "app",
Name: req.Name,
DetailName: req.DetailName,
SourceAccountIDs: "1",
DownloadAccountID: 1,
FileDir: itemDir,
FileName: fileName,
TaskID: req.TaskID,
Status: constant.StatusWaiting,
Description: req.Description,
}
if err := backupRepo.CreateRecord(record); err != nil {
global.LOG.Errorf("save backup record failed, err: %v", err)
return nil, err
backupApp := func() (*model.BackupRecord, error) {
if err = handleAppBackup(&install, nil, backupDir, fileName, "", req.Secret, req.TaskID); err != nil {
global.LOG.Errorf("backup app %s failed, err: %v", req.DetailName, err)
return nil, err
}
record := &model.BackupRecord{
Type: "app",
Name: req.Name,
DetailName: req.DetailName,
SourceAccountIDs: "1",
DownloadAccountID: 1,
FileDir: itemDir,
FileName: fileName,
Description: req.Description,
}
if err := backupRepo.CreateRecord(record); err != nil {
global.LOG.Errorf("save backup record failed, err: %v", err)
return nil, err
}
return record, nil
}
if err = handleAppBackup(&install, nil, record.ID, backupDir, fileName, "", req.Secret, req.TaskID); err != nil {
global.LOG.Errorf("backup app %s failed, err: %v", req.DetailName, err)
return nil, err
if req.TaskID != "" {
go func() {
_, _ = backupApp()
}()
} else {
return backupApp()
}
return record, nil
return nil, nil
}
func (u *BackupService) AppRecover(req dto.CommonRecover) error {
@@ -87,9 +94,11 @@ func (u *BackupService) AppRecover(req dto.CommonRecover) error {
if _, err := compose.Down(install.GetComposePath()); err != nil {
return err
}
if err := handleAppRecover(&install, nil, req.File, false, req.Secret, req.TaskID); err != nil {
global.LOG.Errorf("recover app %s failed, err: %v", req.DetailName, err)
}
go func() {
if err := handleAppRecover(&install, nil, req.File, false, req.Secret, req.TaskID); err != nil {
global.LOG.Errorf("recover app %s failed, err: %v", req.DetailName, err)
}
}()
return nil
}
@@ -102,7 +111,7 @@ func backupDatabaseWithTask(parentTask *task.Task, resourceKey, tmpDir, name str
}
parentTask.LogStart(task.GetTaskName(db.Name, task.TaskBackup, task.TaskScopeDatabase))
databaseHelper := DatabaseHelper{Database: db.MysqlName, DBType: resourceKey, Name: db.Name}
if err := handleMysqlBackup(databaseHelper, parentTask, 0, tmpDir, fmt.Sprintf("%s.sql.gz", name), ""); err != nil {
if err := handleMysqlBackup(databaseHelper, parentTask, tmpDir, fmt.Sprintf("%s.sql.gz", name), ""); err != nil {
return err
}
parentTask.LogSuccess(task.GetTaskName(db.Name, task.TaskBackup, task.TaskScopeDatabase))
@@ -113,7 +122,7 @@ func backupDatabaseWithTask(parentTask *task.Task, resourceKey, tmpDir, name str
}
parentTask.LogStart(task.GetTaskName(db.Name, task.TaskBackup, task.TaskScopeDatabase))
databaseHelper := DatabaseHelper{Database: db.PostgresqlName, DBType: resourceKey, Name: db.Name}
if err := handlePostgresqlBackup(databaseHelper, parentTask, 0, tmpDir, fmt.Sprintf("%s.sql.gz", name), ""); err != nil {
if err := handlePostgresqlBackup(databaseHelper, parentTask, tmpDir, fmt.Sprintf("%s.sql.gz", name), ""); err != nil {
return err
}
parentTask.LogSuccess(task.GetTaskName(db.Name, task.TaskBackup, task.TaskScopeDatabase))
@@ -121,34 +130,25 @@ func backupDatabaseWithTask(parentTask *task.Task, resourceKey, tmpDir, name str
return nil
}
func handleAppBackup(install *model.AppInstall, parentTask *task.Task, recordID uint, backupDir, fileName, excludes, secret, taskID string) error {
func handleAppBackup(install *model.AppInstall, parentTask *task.Task, backupDir, fileName, excludes, secret, taskID string) error {
var (
err error
backupTask *task.Task
)
backupTask = parentTask
if parentTask == nil {
backupTask, err = task.NewTaskWithOps(install.Name, task.TaskBackup, task.TaskScopeBackup, taskID, install.ID)
backupTask, err = task.NewTaskWithOps(install.Name, task.TaskBackup, task.TaskScopeApp, taskID, install.ID)
if err != nil {
return err
}
}
itemHandler := func() error { return doAppBackup(install, backupTask, backupDir, fileName, excludes, secret) }
backupTask.AddSubTask(task.GetTaskName(install.Name, task.TaskBackup, task.TaskScopeApp), func(t *task.Task) error { return itemHandler() }, nil)
if parentTask != nil {
return itemHandler()
}
backupTask.AddSubTaskWithOps(task.GetTaskName(install.Name, task.TaskBackup, task.TaskScopeBackup), func(t *task.Task) error { return itemHandler() }, nil, 3, time.Hour)
go func() {
if err := backupTask.Execute(); err != nil {
backupRepo.UpdateRecordByMap(recordID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
return
}
backupRepo.UpdateRecordByMap(recordID, map[string]interface{}{"status": constant.StatusSuccess})
}()
return nil
return backupTask.Execute()
}
func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverFile string, isRollback bool, secret, taskID string) error {
@@ -160,7 +160,7 @@ func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverF
)
recoverTask = parentTask
if parentTask == nil {
recoverTask, err = task.NewTaskWithOps(install.Name, task.TaskRecover, task.TaskScopeBackup, taskID, install.ID)
recoverTask, err = task.NewTaskWithOps(install.Name, task.TaskRecover, task.TaskScopeApp, taskID, install.ID)
if err != nil {
return err
}
@@ -170,7 +170,7 @@ func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverF
fileOp := files.NewFileOp()
if !isRollback {
rollbackFile = path.Join(global.Dir.TmpDir, fmt.Sprintf("app/%s_%s.tar.gz", install.Name, time.Now().Format(constant.DateTimeSlimLayout)))
if err := handleAppBackup(install, recoverTask, 0, path.Dir(rollbackFile), path.Base(rollbackFile), "", "", taskID); err != nil {
if err := handleAppBackup(install, recoverTask, path.Dir(rollbackFile), path.Base(rollbackFile), "", "", taskID); err != nil {
t.Log(fmt.Sprintf("backup app %s for rollback before recover failed, err: %v", install.Name, err))
}
}
@@ -308,10 +308,6 @@ func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverF
return nil
}
if parentTask != nil {
return recoverApp(parentTask)
}
rollBackApp := func(t *task.Task) {
if isRollback {
return
@@ -328,11 +324,12 @@ func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverF
_ = os.RemoveAll(rollbackFile)
}
}
recoverTask.AddSubTask(task.GetTaskName(install.Name, task.TaskRecover, task.TaskScopeBackup), recoverApp, rollBackApp)
go func() {
_ = recoverTask.Execute()
}()
return nil
recoverTask.AddSubTask(task.GetTaskName(install.Name, task.TaskRecover, task.TaskScopeApp), recoverApp, rollBackApp)
if parentTask != nil {
return recoverApp(parentTask)
}
return recoverTask.Execute()
}
func doAppBackup(install *model.AppInstall, parentTask *task.Task, backupDir, fileName, excludes, secret string) error {
@@ -354,7 +351,6 @@ func doAppBackup(install *model.AppInstall, parentTask *task.Task, backupDir, fi
}
appPath := install.GetPath()
parentTask.LogStart(i18n.GetMsgByKey("TaskBackup"))
if err := fileOp.TarGzCompressPro(true, appPath, path.Join(tmpDir, "app.tar.gz"), "", excludes); err != nil {
return err
}
+25 -28
View File
@@ -30,6 +30,11 @@ func (u *BackupService) MysqlBackup(req dto.CommonBackup) error {
targetDir := path.Join(global.Dir.LocalBackupDir, itemDir)
fileName := fmt.Sprintf("%s_%s.sql.gz", req.DetailName, timeNow+common.RandStrAndNum(5))
databaseHelper := DatabaseHelper{Database: req.Name, DBType: req.Type, Name: req.DetailName}
if err := handleMysqlBackup(databaseHelper, nil, targetDir, fileName, req.TaskID); err != nil {
return err
}
record := &model.BackupRecord{
Type: req.Type,
Name: req.Name,
@@ -38,25 +43,19 @@ func (u *BackupService) MysqlBackup(req dto.CommonBackup) error {
DownloadAccountID: 1,
FileDir: itemDir,
FileName: fileName,
TaskID: req.TaskID,
Status: constant.StatusWaiting,
Description: req.Description,
}
if err := backupRepo.CreateRecord(record); err != nil {
global.LOG.Errorf("save backup record failed, err: %v", err)
return err
}
databaseHelper := DatabaseHelper{Database: req.Name, DBType: req.Type, Name: req.DetailName}
if err := handleMysqlBackup(databaseHelper, nil, record.ID, targetDir, fileName, req.TaskID); err != nil {
backupRepo.UpdateRecordByMap(record.ID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
return err
}
return nil
}
func (u *BackupService) MysqlRecover(req dto.CommonRecover) error {
return handleMysqlRecover(req, nil, false, req.TaskID)
if err := handleMysqlRecover(req, nil, false, req.TaskID); err != nil {
return err
}
return nil
}
func (u *BackupService) MysqlRecoverByUpload(req dto.CommonRecover) error {
@@ -65,14 +64,14 @@ func (u *BackupService) MysqlRecoverByUpload(req dto.CommonRecover) error {
return err
}
req.File = recoveFile
if err := handleMysqlRecover(req, nil, false, req.TaskID); err != nil {
return err
}
global.LOG.Info("recover from uploads successful!")
return nil
}
func handleMysqlBackup(db DatabaseHelper, parentTask *task.Task, recordID uint, targetDir, fileName, taskID string) error {
func handleMysqlBackup(db DatabaseHelper, parentTask *task.Task, targetDir, fileName, taskID string) error {
var (
err error
backupTask *task.Task
@@ -84,25 +83,18 @@ func handleMysqlBackup(db DatabaseHelper, parentTask *task.Task, recordID uint,
}
itemName := fmt.Sprintf("%s[%s] - %s", db.Database, db.DBType, db.Name)
if parentTask == nil {
backupTask, err = task.NewTaskWithOps(itemName, task.TaskBackup, task.TaskScopeBackup, taskID, dbInfo.ID)
backupTask, err = task.NewTaskWithOps(itemName, task.TaskBackup, task.TaskScopeDatabase, taskID, dbInfo.ID)
if err != nil {
return err
}
}
itemHandler := func() error { return doMysqlBackup(db, targetDir, fileName) }
backupTask.AddSubTask(task.GetTaskName(itemName, task.TaskBackup, task.TaskScopeDatabase), func(t *task.Task) error { return itemHandler() }, nil)
if parentTask != nil {
return itemHandler()
}
backupTask.AddSubTaskWithOps(task.GetTaskName(itemName, task.TaskBackup, task.TaskScopeBackup), func(t *task.Task) error { return itemHandler() }, nil, 3, time.Hour)
go func() {
if err := backupTask.Execute(); err != nil {
backupRepo.UpdateRecordByMap(recordID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
return
}
backupRepo.UpdateRecordByMap(recordID, map[string]interface{}{"status": constant.StatusSuccess})
}()
return nil
return backupTask.Execute()
}
func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback bool, taskID string) error {
@@ -117,7 +109,7 @@ func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback
}
itemName := fmt.Sprintf("%s[%s] - %s", req.Name, req.Type, req.DetailName)
if parentTask == nil {
itemTask, err = task.NewTaskWithOps(itemName, task.TaskRecover, task.TaskScopeBackup, taskID, dbInfo.ID)
itemTask, err = task.NewTaskWithOps(itemName, task.TaskRecover, task.TaskScopeDatabase, taskID, dbInfo.ID)
if err != nil {
return err
}
@@ -147,6 +139,8 @@ func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback
Format: dbInfo.Format,
TargetDir: path.Dir(rollbackFile),
FileName: path.Base(rollbackFile),
Timeout: 300,
}); err != nil {
return fmt.Errorf("backup mysql db %s for rollback before recover failed, err: %v", req.DetailName, err)
}
@@ -159,6 +153,8 @@ func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback
Version: version,
Format: dbInfo.Format,
SourceFile: rollbackFile,
Timeout: 300,
}); err != nil {
global.LOG.Errorf("rollback mysql db %s from %s failed, err: %v", req.DetailName, rollbackFile, err)
} else {
@@ -176,6 +172,8 @@ func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback
Version: version,
Format: dbInfo.Format,
SourceFile: req.File,
Timeout: 300,
}); err != nil {
global.LOG.Errorf("recover mysql db %s from %s failed, err: %v", req.DetailName, req.File, err)
return err
@@ -183,15 +181,12 @@ func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback
isOk = true
return nil
}
itemTask.AddSubTask(i18n.GetMsgByKey("TaskRecover"), recoverDatabase, nil)
if parentTask != nil {
return recoverDatabase(parentTask)
}
itemTask.AddSubTaskWithOps(i18n.GetMsgByKey("TaskRecover"), recoverDatabase, nil, 3, time.Hour)
go func() {
_ = itemTask.Execute()
}()
return nil
return itemTask.Execute()
}
func doMysqlBackup(db DatabaseHelper, targetDir, fileName string) error {
@@ -210,6 +205,8 @@ func doMysqlBackup(db DatabaseHelper, targetDir, fileName string) error {
Format: dbInfo.Format,
TargetDir: targetDir,
FileName: fileName,
Timeout: 300,
}
return cli.Backup(backupInfo)
}
+12 -24
View File
@@ -29,6 +29,11 @@ func (u *BackupService) PostgresqlBackup(req dto.CommonBackup) error {
targetDir := path.Join(global.Dir.LocalBackupDir, itemDir)
fileName := fmt.Sprintf("%s_%s.sql.gz", req.DetailName, timeNow+common.RandStrAndNum(5))
databaseHelper := DatabaseHelper{Database: req.Name, DBType: req.Type, Name: req.DetailName}
if err := handlePostgresqlBackup(databaseHelper, nil, targetDir, fileName, req.TaskID); err != nil {
return err
}
record := &model.BackupRecord{
Type: req.Type,
Name: req.Name,
@@ -37,18 +42,11 @@ func (u *BackupService) PostgresqlBackup(req dto.CommonBackup) error {
DownloadAccountID: 1,
FileDir: itemDir,
FileName: fileName,
TaskID: req.TaskID,
Status: constant.StatusWaiting,
Description: req.Description,
}
if err := backupRepo.CreateRecord(record); err != nil {
global.LOG.Errorf("save backup record failed, err: %v", err)
}
databaseHelper := DatabaseHelper{Database: req.Name, DBType: req.Type, Name: req.DetailName}
if err := handlePostgresqlBackup(databaseHelper, nil, record.ID, targetDir, fileName, req.TaskID); err != nil {
return err
}
return nil
}
func (u *BackupService) PostgresqlRecover(req dto.CommonRecover) error {
@@ -71,7 +69,7 @@ func (u *BackupService) PostgresqlRecoverByUpload(req dto.CommonRecover) error {
return nil
}
func handlePostgresqlBackup(db DatabaseHelper, parentTask *task.Task, recordID uint, targetDir, fileName, taskID string) error {
func handlePostgresqlBackup(db DatabaseHelper, parentTask *task.Task, targetDir, fileName, taskID string) error {
var (
err error
backupTask *task.Task
@@ -79,25 +77,18 @@ func handlePostgresqlBackup(db DatabaseHelper, parentTask *task.Task, recordID u
backupTask = parentTask
itemName := fmt.Sprintf("%s - %s", db.Database, db.Name)
if parentTask == nil {
backupTask, err = task.NewTaskWithOps(itemName, task.TaskBackup, task.TaskScopeBackup, taskID, db.ID)
backupTask, err = task.NewTaskWithOps(itemName, task.TaskBackup, task.TaskScopeDatabase, taskID, db.ID)
if err != nil {
return err
}
}
itemHandler := func() error { return doPostgresqlgBackup(db, targetDir, fileName) }
backupTask.AddSubTask(task.GetTaskName(itemName, task.TaskBackup, task.TaskScopeDatabase), func(task *task.Task) error { return itemHandler() }, nil)
if parentTask != nil {
return itemHandler()
}
backupTask.AddSubTaskWithOps(task.GetTaskName(itemName, task.TaskBackup, task.TaskScopeBackup), func(t *task.Task) error { return itemHandler() }, nil, 3, time.Hour)
go func() {
if err := backupTask.Execute(); err != nil {
backupRepo.UpdateRecordByMap(recordID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
return
}
backupRepo.UpdateRecordByMap(recordID, map[string]interface{}{"status": constant.StatusSuccess})
}()
return nil
return backupTask.Execute()
}
func handlePostgresqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback bool) error {
@@ -111,7 +102,7 @@ func handlePostgresqlRecover(req dto.CommonRecover, parentTask *task.Task, isRol
}
itemTask = parentTask
if parentTask == nil {
itemTask, err = task.NewTaskWithOps(req.Name, task.TaskRecover, task.TaskScopeBackup, req.TaskID, dbInfo.ID)
itemTask, err = task.NewTaskWithOps(req.Name, task.TaskRecover, task.TaskScopeDatabase, req.TaskID, dbInfo.ID)
if err != nil {
return err
}
@@ -172,15 +163,12 @@ func handlePostgresqlRecover(req dto.CommonRecover, parentTask *task.Task, isRol
isOk = true
return nil
}
itemTask.AddSubTask(i18n.GetMsgByKey("TaskRecover"), recoverDatabase, nil)
if parentTask != nil {
return recoverDatabase(parentTask)
}
itemTask.AddSubTaskWithOps(i18n.GetMsgByKey("TaskRecover"), recoverDatabase, nil, 3, time.Hour)
go func() {
_ = itemTask.Execute()
}()
return nil
return itemTask.Execute()
}
func doPostgresqlgBackup(db DatabaseHelper, targetDir, fileName string) error {
-4
View File
@@ -11,7 +11,6 @@ import (
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/jinzhu/copier"
)
@@ -240,9 +239,6 @@ func (u *BackupRecordService) LoadRecordSize(req dto.SearchForSize) ([]dto.Recor
return nil, err
}
for _, item := range records {
if item.Status == constant.StatusWaiting {
continue
}
list = append(list, backupSizeHelper{ID: item.ID, DownloadID: item.DownloadAccountID, FilePath: path.Join(item.FileDir, item.FileName)})
}
}
+10 -22
View File
@@ -44,24 +44,22 @@ func (u *BackupService) RedisBackup(req dto.CommonBackup) error {
}
itemDir := fmt.Sprintf("database/redis/%s", redisInfo.Name)
backupDir := path.Join(global.Dir.LocalBackupDir, itemDir)
if err := handleRedisBackup(redisInfo, nil, backupDir, fileName, req.Secret, req.TaskID); err != nil {
return err
}
record := &model.BackupRecord{
Type: req.Type,
Type: "redis",
Name: req.Name,
SourceAccountIDs: "1",
DownloadAccountID: 1,
FileDir: itemDir,
FileName: fileName,
TaskID: req.TaskID,
Status: constant.StatusWaiting,
Description: req.Description,
}
if err := backupRepo.CreateRecord(record); err != nil {
global.LOG.Errorf("save backup record failed, err: %v", err)
}
if err := handleRedisBackup(redisInfo, nil, record.ID, backupDir, fileName, req.Secret, req.TaskID); err != nil {
return err
}
return nil
}
@@ -77,14 +75,15 @@ func (u *BackupService) RedisRecover(req dto.CommonRecover) error {
return nil
}
func handleRedisBackup(redisInfo *repo.RootInfo, parentTask *task.Task, recordID uint, backupDir, fileName, secret, taskID string) error {
func handleRedisBackup(redisInfo *repo.RootInfo, parentTask *task.Task, backupDir, fileName, secret, taskID string) error {
var (
err error
itemTask *task.Task
)
itemTask = parentTask
if parentTask == nil {
itemTask, err = task.NewTaskWithOps("Redis", task.TaskBackup, task.TaskScopeBackup, taskID, redisInfo.ID)
itemTask, err = task.NewTaskWithOps("Redis", task.TaskBackup, task.TaskScopeDatabase, taskID, redisInfo.ID)
if err != nil {
return err
}
@@ -129,14 +128,6 @@ func handleRedisBackup(redisInfo *repo.RootInfo, parentTask *task.Task, recordID
return backupDatabase(parentTask)
}
itemTask.AddSubTaskWithOps(i18n.GetMsgByKey("TaskBackup"), backupDatabase, nil, 3, time.Hour)
go func() {
if err := itemTask.Execute(); err != nil {
backupRepo.UpdateRecordByMap(recordID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
return
}
backupRepo.UpdateRecordByMap(recordID, map[string]interface{}{"status": constant.StatusSuccess})
}()
return itemTask.Execute()
}
@@ -147,7 +138,7 @@ func handleRedisRecover(redisInfo *repo.RootInfo, parentTask *task.Task, recover
)
itemTask = parentTask
if parentTask == nil {
itemTask, err = task.NewTaskWithOps("Redis", task.TaskRecover, task.TaskScopeBackup, taskID, redisInfo.ID)
itemTask, err = task.NewTaskWithOps("Redis", task.TaskRecover, task.TaskScopeDatabase, taskID, redisInfo.ID)
if err != nil {
return err
}
@@ -189,7 +180,7 @@ func handleRedisRecover(redisInfo *repo.RootInfo, parentTask *task.Task, recover
}
}
rollbackFile := path.Join(global.Dir.TmpDir, fmt.Sprintf("database/redis/%s_%s.%s", redisInfo.Name, time.Now().Format(constant.DateTimeSlimLayout), suffix))
if err := handleRedisBackup(redisInfo, nil, 0, path.Dir(rollbackFile), path.Base(rollbackFile), secret, ""); err != nil {
if err := handleRedisBackup(redisInfo, nil, path.Dir(rollbackFile), path.Base(rollbackFile), secret, ""); err != nil {
return fmt.Errorf("backup database %s for rollback before recover failed, err: %v", redisInfo.Name, err)
}
defer func() {
@@ -239,8 +230,5 @@ func handleRedisRecover(redisInfo *repo.RootInfo, parentTask *task.Task, recover
return recoverDatabase(parentTask)
}
go func() {
_ = itemTask.Execute()
}()
return nil
return itemTask.Execute()
}
+57 -79
View File
@@ -38,26 +38,26 @@ func (u *BackupService) WebsiteBackup(req dto.CommonBackup) error {
backupDir := path.Join(global.Dir.LocalBackupDir, itemDir)
fileName := fmt.Sprintf("%s_%s.tar.gz", website.Alias, timeNow+common.RandStrAndNum(5))
record := &model.BackupRecord{
Type: "website",
Name: website.Alias,
DetailName: website.Alias,
SourceAccountIDs: "1",
DownloadAccountID: 1,
FileDir: itemDir,
FileName: fileName,
TaskID: req.TaskID,
Status: constant.StatusWaiting,
Description: req.Description,
}
if err = backupRepo.CreateRecord(record); err != nil {
global.LOG.Errorf("save backup record failed, err: %v", err)
return err
}
if err = handleWebsiteBackup(&website, nil, record.ID, backupDir, fileName, "", req.Secret, req.TaskID); err != nil {
global.LOG.Errorf("backup website %s failed, err: %v", website.Alias, err)
return err
}
go func() {
if err = handleWebsiteBackup(&website, nil, backupDir, fileName, "", req.Secret, req.TaskID); err != nil {
global.LOG.Errorf("backup website %s failed, err: %v", website.Alias, err)
return
}
record := &model.BackupRecord{
Type: "website",
Name: website.Alias,
DetailName: website.Alias,
SourceAccountIDs: "1",
DownloadAccountID: 1,
FileDir: itemDir,
FileName: fileName,
Description: req.Description,
}
if err = backupRepo.CreateRecord(record); err != nil {
global.LOG.Errorf("save backup record failed, err: %v", err)
return
}
}()
return nil
}
@@ -66,34 +66,40 @@ func (u *BackupService) WebsiteRecover(req dto.CommonRecover) error {
if err != nil {
return err
}
if err := handleWebsiteRecover(&website, nil, req.File, false, req.Secret, req.TaskID); err != nil {
global.LOG.Errorf("recover website %s failed, err: %v", website.Alias, err)
}
go func() {
if err := handleWebsiteRecover(&website, req.File, false, req.Secret, req.TaskID); err != nil {
global.LOG.Errorf("recover website %s failed, err: %v", website.Alias, err)
}
}()
return nil
}
func handleWebsiteRecover(website *model.Website, parentTask *task.Task, recoverFile string, isRollback bool, secret, taskID string) error {
var (
err error
recoverTask *task.Task
isOk = false
rollbackFile string
)
recoverTask = parentTask
if parentTask == nil {
recoverTask, err = task.NewTaskWithOps(website.PrimaryDomain, task.TaskRecover, task.TaskScopeBackup, taskID, website.ID)
if err != nil {
return err
}
func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback bool, secret, taskID string) error {
recoverTask, err := task.NewTaskWithOps(website.PrimaryDomain, task.TaskRecover, task.TaskScopeWebsite, taskID, website.ID)
if err != nil {
return err
}
recoverWebsite := func(t *task.Task) error {
recoverTask.AddSubTask(task.GetTaskName(website.PrimaryDomain, task.TaskRecover, task.TaskScopeWebsite), func(t *task.Task) error {
isOk := false
if !isRollback {
rollbackFile = path.Join(global.Dir.TmpDir, fmt.Sprintf("website/%s_%s.tar.gz", website.Alias, time.Now().Format(constant.DateTimeSlimLayout)))
if err := handleWebsiteBackup(website, recoverTask, 0, path.Dir(rollbackFile), path.Base(rollbackFile), "", "", taskID); err != nil {
rollbackFile := path.Join(global.Dir.TmpDir, fmt.Sprintf("website/%s_%s.tar.gz", website.Alias, time.Now().Format(constant.DateTimeSlimLayout)))
if err := handleWebsiteBackup(website, recoverTask, path.Dir(rollbackFile), path.Base(rollbackFile), "", "", taskID); err != nil {
return fmt.Errorf("backup website %s for rollback before recover failed, err: %v", website.Alias, err)
}
defer func() {
if !isOk {
t.LogStart(i18n.GetMsgByKey("Rollback"))
if err := handleWebsiteRecover(website, rollbackFile, true, "", taskID); err != nil {
t.LogFailedWithErr(i18n.GetMsgByKey("Rollback"), err)
return
}
t.LogSuccess(i18n.GetMsgByKey("Rollback"))
_ = os.RemoveAll(rollbackFile)
} else {
_ = os.RemoveAll(rollbackFile)
}
}()
}
fileOp := files.NewFileOp()
tmpPath := strings.ReplaceAll(recoverFile, ".tar.gz", "")
t.Log(i18n.GetWithName("DeCompressFile", recoverFile))
@@ -145,10 +151,12 @@ func handleWebsiteRecover(website *model.Website, parentTask *task.Task, recover
taskName := task.GetTaskName(app.Name, task.TaskRecover, task.TaskScopeApp)
t.LogStart(taskName)
if err := handleAppRecover(&app, recoverTask, fmt.Sprintf("%s/%s.app.tar.gz", tmpPath, website.Alias), true, "", ""); err != nil {
t.LogFailedWithErr(taskName, err)
return err
}
t.LogSuccess(taskName)
if _, err = compose.DownAndUp(fmt.Sprintf("%s/%s/%s/docker-compose.yml", global.Dir.AppInstallDir, app.App.Key, app.Name)); err != nil {
t.LogFailedWithErr("Run", err)
return err
}
case constant.Runtime:
@@ -159,6 +167,7 @@ func handleWebsiteRecover(website *model.Website, parentTask *task.Task, recover
taskName := task.GetTaskName(runtime.Name, task.TaskRecover, task.TaskScopeRuntime)
t.LogStart(taskName)
if err := handleRuntimeRecover(runtime, fmt.Sprintf("%s/%s.runtime.tar.gz", tmpPath, website.Alias), true, ""); err != nil {
t.LogFailedWithErr(taskName, err)
return err
}
t.LogSuccess(taskName)
@@ -177,6 +186,7 @@ func handleWebsiteRecover(website *model.Website, parentTask *task.Task, recover
taskName := i18n.GetMsgByKey("TaskRecover") + i18n.GetMsgByKey("websiteDir")
t.Log(taskName)
if err = fileOp.TarGzExtractPro(fmt.Sprintf("%s/%s.web.tar.gz", tmpPath, website.Alias), GetOpenrestyDir(SitesRootDir), ""); err != nil {
t.LogFailedWithErr(taskName, err)
return err
}
stdout, err := cmd.RunDefaultWithStdoutBashCf("docker exec -i %s nginx -s reload", nginxInfo.ContainerName)
@@ -189,60 +199,28 @@ func handleWebsiteRecover(website *model.Website, parentTask *task.Task, recover
}
isOk = true
return nil
}
if parentTask != nil {
return recoverWebsite(parentTask)
}
rollBackWebsite := func(t *task.Task) {
if isRollback {
return
}
if !isOk {
t.Log(i18n.GetMsgByKey("RecoverFailedStartRollBack"))
if err := handleWebsiteRecover(website, t, rollbackFile, true, "", ""); err != nil {
t.LogFailedWithErr(i18n.GetMsgByKey("Rollback"), err)
return
}
t.LogSuccess(i18n.GetMsgByKey("Rollback"))
_ = os.RemoveAll(rollbackFile)
} else {
_ = os.RemoveAll(rollbackFile)
}
}
recoverTask.AddSubTask(task.GetTaskName(website.PrimaryDomain, task.TaskRecover, task.TaskScopeBackup), recoverWebsite, rollBackWebsite)
go func() {
_ = recoverTask.Execute()
}()
return nil
}, nil)
return recoverTask.Execute()
}
func handleWebsiteBackup(website *model.Website, parentTask *task.Task, recordID uint, backupDir, fileName, excludes, secret, taskID string) error {
func handleWebsiteBackup(website *model.Website, parentTask *task.Task, backupDir, fileName, excludes, secret, taskID string) error {
var (
err error
backupTask *task.Task
)
backupTask = parentTask
if parentTask == nil {
backupTask, err = task.NewTaskWithOps(website.Alias, task.TaskBackup, task.TaskScopeBackup, taskID, website.ID)
backupTask, err = task.NewTaskWithOps(website.Alias, task.TaskBackup, task.TaskScopeWebsite, taskID, website.ID)
if err != nil {
return err
}
}
itemHandler := func() error { return doWebsiteBackup(website, backupTask, backupDir, fileName, excludes, secret) }
backupTask.AddSubTask(task.GetTaskName(website.Alias, task.TaskBackup, task.TaskScopeWebsite), func(t *task.Task) error { return itemHandler() }, nil)
if parentTask != nil {
return itemHandler()
}
backupTask.AddSubTaskWithOps(task.GetTaskName(website.Alias, task.TaskBackup, task.TaskScopeBackup), func(t *task.Task) error { return itemHandler() }, nil, 3, time.Hour)
go func() {
if err := backupTask.Execute(); err != nil {
backupRepo.UpdateRecordByMap(recordID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
return
}
backupRepo.UpdateRecordByMap(recordID, map[string]interface{}{"status": constant.StatusSuccess})
}()
return nil
return backupTask.Execute()
}
func doWebsiteBackup(website *model.Website, parentTask *task.Task, backupDir, fileName, excludes, secret string) error {
@@ -274,7 +252,7 @@ func doWebsiteBackup(website *model.Website, parentTask *task.Task, backupDir, f
return err
}
parentTask.LogStart(task.GetTaskName(app.Name, task.TaskBackup, task.TaskScopeApp))
if err = handleAppBackup(&app, parentTask, 0, tmpDir, fmt.Sprintf("%s.app.tar.gz", website.Alias), excludes, "", ""); err != nil {
if err = handleAppBackup(&app, parentTask, tmpDir, fmt.Sprintf("%s.app.tar.gz", website.Alias), excludes, "", ""); err != nil {
return err
}
parentTask.LogSuccess(task.GetTaskName(app.Name, task.TaskBackup, task.TaskScopeApp))
-6
View File
@@ -8,7 +8,6 @@ import (
"path"
"strconv"
"strings"
"time"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/model"
@@ -20,7 +19,6 @@ import (
"github.com/1Panel-dev/1Panel/agent/utils/alert_push"
"github.com/1Panel-dev/1Panel/agent/utils/clam"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/common"
"github.com/1Panel-dev/1Panel/agent/utils/systemctl"
"github.com/1Panel-dev/1Panel/agent/utils/xpack"
"github.com/jinzhu/copier"
@@ -240,7 +238,6 @@ func (c *ClamService) Update(req dto.ClamUpdate) error {
upMap["infected_dir"] = req.InfectedDir
upMap["infected_strategy"] = req.InfectedStrategy
upMap["spec"] = req.Spec
upMap["timeout"] = req.Timeout
upMap["description"] = req.Description
if err := clamRepo.Update(req.ID, upMap); err != nil {
return err
@@ -342,9 +339,6 @@ func (c *ClamService) SearchRecords(req dto.ClamLogSearch) (int64, interface{},
if clam.ID == 0 {
return 0, nil, buserr.New("ErrRecordNotFound")
}
loc, _ := time.LoadLocation(common.LoadTimeZoneByCmd())
req.StartTime = req.StartTime.In(loc)
req.EndTime = req.EndTime.In(loc)
total, records, err := clamRepo.PageRecords(req.Page, req.PageSize, clamRepo.WithByClamID(req.ClamID), repo.WithByStatus(req.Status), repo.WithByCreatedAt(req.StartTime, req.EndTime))
if err != nil {
+17 -15
View File
@@ -640,6 +640,7 @@ func (u *ContainerService) ContainerInfo(req dto.OperationWithName) (*dto.Contai
}
var data dto.ContainerOperate
data.ContainerID = oldContainer.ID
data.Name = strings.ReplaceAll(oldContainer.Name, "/", "")
data.Image = oldContainer.Config.Image
if oldContainer.NetworkSettings != nil {
@@ -701,7 +702,11 @@ func (u *ContainerService) ContainerUpdate(req dto.ContainerOperate) error {
}
defer client.Close()
ctx := context.Background()
oldContainer, err := client.ContainerInspect(ctx, req.Name)
newContainer, _ := client.ContainerInspect(ctx, req.Name)
if newContainer.ContainerJSONBase != nil && newContainer.ID != req.ContainerID {
return buserr.New("ErrContainerName")
}
oldContainer, err := client.ContainerInspect(ctx, req.ContainerID)
if err != nil {
return err
}
@@ -725,7 +730,7 @@ func (u *ContainerService) ContainerUpdate(req dto.ContainerOperate) error {
}, nil)
taskItem.AddSubTask(i18n.GetWithName("ContainerCreate", req.Name), func(t *task.Task) error {
err := client.ContainerRemove(ctx, req.Name, container.RemoveOptions{Force: true})
err := client.ContainerRemove(ctx, req.ContainerID, container.RemoveOptions{Force: true})
taskItem.LogWithStatus(i18n.GetWithName("ContainerRemoveOld", req.Name), err)
if err != nil {
return err
@@ -1498,19 +1503,17 @@ func loadConfigInfo(isCreate bool, req dto.ContainerOperate, oldContainer *conta
hostConf.DNS = req.DNS
config.Volumes = make(map[string]struct{})
for _, volume := range req.Volumes {
item := mount.Mount{
Type: mount.Type(volume.Type),
Source: volume.SourceDir,
Target: volume.ContainerDir,
ReadOnly: volume.Mode == "ro",
if volume.Type == "volume" {
hostConf.Mounts = append(hostConf.Mounts, mount.Mount{
Type: mount.Type(volume.Type),
Source: volume.SourceDir,
Target: volume.ContainerDir,
ReadOnly: volume.Mode == "ro",
})
config.Volumes[volume.ContainerDir] = struct{}{}
} else {
hostConf.Binds = append(hostConf.Binds, fmt.Sprintf("%s:%s:%s", volume.SourceDir, volume.ContainerDir, volume.Mode))
}
if volume.Type == "bind" {
item.BindOptions = &mount.BindOptions{
Propagation: mount.Propagation(volume.Shared),
}
}
hostConf.Mounts = append(hostConf.Mounts, item)
config.Volumes[volume.ContainerDir] = struct{}{}
}
return &config, &hostConf, &networkConf, nil
}
@@ -1552,7 +1555,6 @@ func loadVolumeBinds(binds []container.MountPoint) []dto.VolumeHelper {
if bind.RW {
volumeItem.Mode = "rw"
}
volumeItem.Shared = string(bind.Propagation)
datas = append(datas, volumeItem)
}
return datas
+3 -18
View File
@@ -36,7 +36,6 @@ type ICronjobService interface {
Delete(req dto.CronjobBatchDelete) error
StartJob(cronjob *model.Cronjob, isUpdate bool) (string, error)
CleanRecord(req dto.CronjobClean) error
HandleStop(id uint) error
Export(req dto.OperateByIDs) (string, error)
Import(req []dto.CronjobTrans) error
@@ -500,8 +499,8 @@ func (u *CronjobService) CleanRecord(req dto.CronjobClean) error {
if hasBackup(cronjob.Type) {
accountMap := NewBackupClientMap(strings.Split(cronjob.SourceAccountIDs, ","))
if !req.CleanRemoteData {
for key, val := range accountMap {
if val.accountType != constant.Local {
for key := range accountMap {
if key != constant.Local {
delete(accountMap, key)
}
}
@@ -605,7 +604,7 @@ func (u *CronjobService) StartJob(cronjob *model.Cronjob, isUpdate bool) (string
global.Cron.Remove(cron.EntryID(idItem))
}
}
specs := strings.Split(cronjob.Spec, "&&")
specs := strings.Split(cronjob.Spec, ",")
var ids []string
for _, spec := range specs {
cronjob.Spec = spec
@@ -618,20 +617,6 @@ func (u *CronjobService) StartJob(cronjob *model.Cronjob, isUpdate bool) (string
return strings.Join(ids, ","), nil
}
func (u *CronjobService) HandleStop(id uint) error {
record, _ := cronjobRepo.GetRecord(repo.WithByID(id))
if record.ID == 0 {
return buserr.New("ErrRecordNotFound")
}
if len(record.TaskID) == 0 {
return nil
}
if cancle, ok := global.TaskCtxMap[record.TaskID]; ok {
cancle()
}
return nil
}
func (u *CronjobService) Delete(req dto.CronjobBatchDelete) error {
for _, id := range req.IDs {
cronjob, _ := cronjobRepo.Get(repo.WithByID(id))
-6
View File
@@ -38,7 +38,6 @@ func (u *CronjobService) handleApp(cronjob model.Cronjob, startTime time.Time, t
retry := 0
taskItem.AddSubTaskWithOps(task.GetTaskName(app.Name, task.TaskBackup, task.TaskScopeCronjob), func(task *task.Task) error {
var record model.BackupRecord
record.Status = constant.StatusSuccess
record.From = "cronjob"
record.Type = "app"
record.CronjobID = cronjob.ID
@@ -96,7 +95,6 @@ func (u *CronjobService) handleWebsite(cronjob model.Cronjob, startTime time.Tim
retry := 0
taskItem.AddSubTaskWithOps(task.GetTaskName(web.Alias, task.TaskBackup, task.TaskScopeCronjob), func(task *task.Task) error {
var record model.BackupRecord
record.Status = constant.StatusSuccess
record.From = "cronjob"
record.Type = "website"
record.CronjobID = cronjob.ID
@@ -156,7 +154,6 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Ti
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
record.Status = constant.StatusSuccess
record.From = "cronjob"
record.Type = dbInfo.DBType
record.CronjobID = cronjob.ID
@@ -241,7 +238,6 @@ func (u *CronjobService) handleDirectory(cronjob model.Cronjob, startTime time.T
}
}
var record model.BackupRecord
record.Status = constant.StatusSuccess
record.From = "cronjob"
record.Type = "directory"
record.CronjobID = cronjob.ID
@@ -277,7 +273,6 @@ func (u *CronjobService) handleSystemLog(cronjob model.Cronjob, startTime time.T
return err
}
var record model.BackupRecord
record.Status = constant.StatusSuccess
record.From = "cronjob"
record.Type = "log"
record.CronjobID = cronjob.ID
@@ -306,7 +301,6 @@ func (u *CronjobService) handleSnapshot(cronjob model.Cronjob, jobRecord model.J
return errors.New(i18n.GetMsgWithDetail("LoadBackupFailed", accountMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].message))
}
var record model.BackupRecord
record.Status = constant.StatusSuccess
record.From = "cronjob"
record.Type = "snapshot"
record.CronjobID = cronjob.ID
+5 -11
View File
@@ -132,8 +132,7 @@ func (u *CronjobService) loadTask(cronjob *model.Cronjob, record *model.JobRecor
}
func (u *CronjobService) handleShell(cronjob model.Cronjob, taskItem *task.Task) {
cmdMgr := cmd.NewCommandMgr(cmd.WithTask(*taskItem), cmd.WithContext(taskItem.TaskCtx))
cmdMgr := cmd.NewCommandMgr(cmd.WithTask(*taskItem))
taskItem.AddSubTaskWithOps(i18n.GetWithName("HandleShell", cronjob.Name), func(t *task.Task) error {
if len(cronjob.ContainerName) != 0 {
scriptItem := cronjob.Script
@@ -148,21 +147,17 @@ func (u *CronjobService) handleShell(cronjob model.Cronjob, taskItem *task.Task)
command = cronjob.Command
}
if len(cronjob.User) != 0 {
return cmdMgr.Run("docker", "exec", "-u", cronjob.User, cronjob.ContainerName, command, "-c", scriptItem)
return cmdMgr.Run("docker", "exec", "-u", cronjob.User, cronjob.ContainerName, command, "-c", strings.ReplaceAll(scriptItem, "\"", "\\\""))
}
return cmdMgr.Run("docker", "exec", cronjob.ContainerName, command, "-c", scriptItem)
return cmdMgr.Run("docker", "exec", cronjob.ContainerName, command, "-c", strings.ReplaceAll(scriptItem, "\"", "\\\""))
}
if len(cronjob.Executor) == 0 {
cronjob.Executor = "bash"
}
if cronjob.ScriptMode == "input" {
suffix := ".sh"
if strings.HasPrefix(cronjob.Executor, "python") {
suffix = ".py"
}
fileItem := pathUtils.Join(global.Dir.DataDir, "task", "shell", cronjob.Name, cronjob.Name+suffix)
fileItem := pathUtils.Join(global.Dir.DataDir, "task", "shell", cronjob.Name, cronjob.Name+".sh")
_ = os.MkdirAll(pathUtils.Dir(fileItem), os.ModePerm)
shellFile, err := os.OpenFile(fileItem, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, constant.DirPerm)
shellFile, err := os.OpenFile(fileItem, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, constant.FilePerm)
if err != nil {
return err
}
@@ -222,7 +217,6 @@ func (u *CronjobService) handleCutWebsiteLog(cronjob *model.Cronjob, startTime t
for _, website := range websites {
taskItem.Log(website.Alias)
var record model.BackupRecord
record.Status = constant.StatusSuccess
record.From = "cronjob"
record.Type = "cut-website-log"
record.CronjobID = cronjob.ID
+31 -51
View File
@@ -12,11 +12,9 @@ import (
"time"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"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/ntp"
@@ -233,58 +231,40 @@ func (u *DeviceService) UpdatePasswd(req dto.ChangePasswd) error {
}
func (u *DeviceService) UpdateSwap(req dto.SwapHelper) error {
taskItem, err := task.NewTaskWithOps(req.Path, task.TaskSwapSet, task.TaskScopeSystem, req.TaskID, 1)
if cmd.CheckIllegal(req.Path) {
return buserr.New("ErrCmdIllegal")
}
if !req.IsNew {
std, err := cmd.RunDefaultWithStdoutBashCf("%s swapoff %s", cmd.SudoHandleCmd(), req.Path)
if err != nil {
return fmt.Errorf("handle swapoff %s failed, err: %s", req.Path, std)
}
}
if req.Size == 0 {
if req.Path == path.Join(global.Dir.BaseDir, ".1panel_swap") {
_ = os.Remove(path.Join(global.Dir.BaseDir, ".1panel_swap"))
}
return operateSwapWithFile(true, req)
}
stdDD, err := cmd.RunDefaultWithStdoutBashCf("%s dd if=/dev/zero of=%s bs=1024 count=%d", cmd.SudoHandleCmd(), req.Path, req.Size)
if err != nil {
global.LOG.Errorf("new task for create container failed, err: %v", err)
return err
return fmt.Errorf("handle dd %s failed, std: %s, err: %s", req.Path, stdDD, err)
}
stdChmod, err := cmd.RunDefaultWithStdoutBashCf("%s chmod 0600 %s", cmd.SudoHandleCmd(), req.Path)
if err != nil {
return fmt.Errorf("handle chmod 0600 %s failed,std: %s, err: %s", req.Path, stdChmod, err)
}
stdMkswap, err := cmd.RunDefaultWithStdoutBashCf("%s mkswap -f %s", cmd.SudoHandleCmd(), req.Path)
if err != nil {
return fmt.Errorf("handle mkswap -f %s failed, std: %s, err: %s", req.Path, stdMkswap, err)
}
taskItem.AddSubTask(i18n.GetMsgWithMap("SetSwap", map[string]interface{}{"path": req.Path, "size": common.LoadSizeUnit2F(float64(req.Size * 1024))}), func(t *task.Task) error {
if cmd.CheckIllegal(req.Path) {
return buserr.New("ErrCmdIllegal")
}
cmdMgr := cmd.NewCommandMgr(cmd.WithTask(*taskItem))
if !req.IsNew {
std, err := cmdMgr.RunWithStdoutBashCf("%s swapoff %s", cmd.SudoHandleCmd(), req.Path)
if err != nil {
return fmt.Errorf("handle swapoff %s failed, err: %s", req.Path, std)
}
}
if req.Size == 0 {
if req.Path == path.Join(global.Dir.BaseDir, ".1panel_swap") {
_ = os.Remove(path.Join(global.Dir.BaseDir, ".1panel_swap"))
}
return operateSwapWithFile(true, req)
}
taskItem.LogStart(i18n.GetMsgByKey("CreateSwap"))
stdDD, err := cmdMgr.RunWithStdoutBashCf("%s dd if=/dev/zero of=%s bs=1024 count=%d", cmd.SudoHandleCmd(), req.Path, req.Size)
if err != nil {
return fmt.Errorf("handle dd %s failed, std: %s, err: %s", req.Path, stdDD, err)
}
taskItem.Log("chmod 0600 " + req.Path)
stdChmod, err := cmdMgr.RunWithStdoutBashCf("%s chmod 0600 %s", cmd.SudoHandleCmd(), req.Path)
if err != nil {
return fmt.Errorf("handle chmod 0600 %s failed,std: %s, err: %s", req.Path, stdChmod, err)
}
taskItem.LogStart(i18n.GetMsgByKey("FormatSwap"))
stdMkswap, err := cmdMgr.RunWithStdoutBashCf("%s mkswap -f %s", cmd.SudoHandleCmd(), req.Path)
if err != nil {
return fmt.Errorf("handle mkswap -f %s failed, std: %s, err: %s", req.Path, stdMkswap, err)
}
taskItem.LogStart(i18n.GetMsgByKey("EnableSwap"))
stdSwapon, err := cmdMgr.RunWithStdoutBashCf("%s swapon %s", cmd.SudoHandleCmd(), req.Path)
if err != nil {
_, _ = cmdMgr.RunWithStdoutBashCf("%s swapoff %s", cmd.SudoHandleCmd(), req.Path)
return fmt.Errorf("handle swapoff %s failed,std: %s, err: %s", req.Path, stdSwapon, err)
}
return operateSwapWithFile(false, req)
}, nil)
go func() {
_ = taskItem.Execute()
}()
return nil
stdSwapon, err := cmd.RunDefaultWithStdoutBashCf("%s swapon %s", cmd.SudoHandleCmd(), req.Path)
if err != nil {
_, _ = cmd.RunDefaultWithStdoutBashCf("%s swapoff %s", cmd.SudoHandleCmd(), req.Path)
return fmt.Errorf("handle swapoff %s failed,std: %s, err: %s", req.Path, stdSwapon, err)
}
return operateSwapWithFile(false, req)
}
func (u *DeviceService) LoadConf(name string) (string, error) {
+11 -76
View File
@@ -7,7 +7,6 @@ import (
"path"
"path/filepath"
"sort"
"strconv"
"strings"
"time"
@@ -19,7 +18,6 @@ import (
"github.com/docker/docker/api/types/filters"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/app/task"
"github.com/1Panel-dev/1Panel/agent/global"
@@ -76,21 +74,8 @@ func (u *DeviceService) Scan() dto.CleanData {
sort.Slice(upgradeTree.Children, func(i, j int) bool {
return common.CompareVersion(upgradeTree.Children[i].Label, upgradeTree.Children[j].Label)
})
if global.IsMaster {
var copiesSeeting model.Setting
_ = global.CoreDB.Where("key = ?", "UpgradeBackupCopies").First(&copiesSeeting).Error
copies, _ := strconv.Atoi(copiesSeeting.Value)
if copies == 0 || copies > len(upgradeTree.Children) {
copies = len(upgradeTree.Children)
}
for i := 0; i < copies; i++ {
upgradeTree.Children[i].IsCheck = false
upgradeTree.Children[i].IsRecommend = false
}
} else {
upgradeTree.Children[0].IsCheck = false
upgradeTree.Children[0].IsRecommend = false
}
upgradeTree.Children[0].IsCheck = false
upgradeTree.Children[0].IsRecommend = false
}
treeData = append(treeData, upgradeTree)
@@ -229,7 +214,7 @@ func (u *DeviceService) Clean(req []dto.Clean) {
}
case "task_log":
if len(item.Name) == 0 {
files, _ := os.ReadDir(global.Dir.TaskDir)
files, _ := os.ReadDir(path.Join(global.Dir.TaskDir))
if len(files) == 0 {
continue
}
@@ -237,10 +222,15 @@ func (u *DeviceService) Clean(req []dto.Clean) {
if file.Name() == "ssl" || !file.IsDir() {
continue
}
dropTaskLog(path.Join(global.Dir.TaskDir, file.Name()))
dropFileOrDir(path.Join(global.Dir.TaskDir, file.Name()))
}
_ = taskRepo.DeleteAll()
} else {
dropTaskLog(path.Join(global.Dir.TaskDir, item.Name))
pathItem := path.Join(global.Dir.TaskDir, item.Name)
dropFileOrDir(pathItem)
if len(item.Name) != 0 {
_ = taskRepo.Delete(repo.WithByType(item.Name))
}
}
case "script":
dropFileOrDir(path.Join(global.Dir.TmpDir, "script", item.Name))
@@ -540,6 +530,7 @@ func loadTreeWithAllFile(isCheck bool, originalPath, treeType, pathItem string,
}
func dropFileOrDir(itemPath string) {
global.LOG.Debugf("drop file %s", itemPath)
if err := os.RemoveAll(itemPath); err != nil {
global.LOG.Errorf("drop file %s failed, err %v", itemPath, err)
}
@@ -615,62 +606,6 @@ func dropVolumes() (int, int) {
return len(res.VolumesDeleted), int(res.SpaceReclaimed)
}
func dropTaskLog(logDir string) {
files, err := os.ReadDir(logDir)
if err != nil {
return
}
taskType := path.Base(logDir)
var usedTasks []string
switch taskType {
case "Cronjob":
_ = global.DB.Model(&model.JobRecords{}).Where("task_id != ?", "").Select("task_id").Find(&usedTasks).Error
case "Snapshot":
var (
snapIDs []string
recoverIDs []string
rollbackIDs []string
)
_ = global.DB.Model(&model.Snapshot{}).Where("task_id != ?", "").Select("task_id").Find(&snapIDs).Error
_ = global.DB.Model(&model.Snapshot{}).Where("task_recover_id != ", "").Select("task_id").Find(&recoverIDs).Error
_ = global.DB.Model(&model.Snapshot{}).Where("task_rollback_id != ?", "").Select("task_id").Find(&rollbackIDs).Error
usedTasks = append(usedTasks, snapIDs...)
usedTasks = append(usedTasks, recoverIDs...)
usedTasks = append(usedTasks, rollbackIDs...)
case "Backup":
_ = global.DB.Model(&model.BackupRecord{}).Where("task_id != ?", "").Select("task_id").Find(&usedTasks).Error
case "Clam":
_ = global.DB.Model(&model.ClamRecord{}).Where("task_id != ?", "").Select("task_id").Find(&usedTasks).Error
case "Tamper":
xpackDB, err := common.LoadDBConnByPathWithErr(path.Join(global.CONF.Base.InstallDir, "1panel/db/xpack.db"), "xpack.db")
if err == nil {
_ = xpackDB.Table("tampers").Where("task_id != ?", "").Select("task_id").Find(&usedTasks).Error
}
case "System":
xpackDB, err := common.LoadDBConnByPathWithErr(path.Join(global.CONF.Base.InstallDir, "1panel/db/xpack.db"), "xpack.db")
if err == nil {
_ = xpackDB.Model("nodes").Where("task_id != ?", "").Select("task_id").Find(&usedTasks).Error
}
default:
dropFileOrDir(logDir)
_ = taskRepo.Delete(repo.WithByType(taskType))
return
}
usedMap := make(map[string]struct{})
for _, item := range usedTasks {
if _, ok := usedMap[item]; !ok {
usedMap[item] = struct{}{}
}
}
for _, item := range files {
if _, ok := usedMap[strings.TrimSuffix(item.Name(), ".log")]; ok {
continue
}
_ = os.Remove(logDir + "/" + item.Name())
}
_ = taskRepo.Delete(repo.WithByType(taskType), taskRepo.WithByIDNotIn(usedTasks))
}
func dropWithExclude(pathToDelete string, excludeSubDirs []string, taskItem *task.Task, size *int64, count *int) {
entries, err := os.ReadDir(pathToDelete)
if err != nil {
+1 -2
View File
@@ -8,7 +8,6 @@ import (
"os"
"path"
"strings"
"time"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/constant"
@@ -458,7 +457,7 @@ func restartDocker() error {
if err != nil {
return err
}
stdout, err := cmd.NewCommandMgr(cmd.WithTimeout(3*time.Minute)).RunWithStdoutBashCf("%s restart docker", restartCmd)
stdout, err := cmd.RunDefaultWithStdoutBashCf("%s restart docker", restartCmd)
if err != nil {
return fmt.Errorf("failed to restart Docker: %s", stdout)
}
+2 -3
View File
@@ -12,9 +12,8 @@ var (
appInstallResourceRepo = repo.NewIAppInstallResourceRpo()
appIgnoreUpgradeRepo = repo.NewIAppIgnoreUpgradeRepo()
aiRepo = repo.NewIAiRepo()
mcpServerRepo = repo.NewIMcpServerRepo()
tensorrtLLMRepo = repo.NewITensorRTLLMRepo()
aiRepo = repo.NewIAiRepo()
mcpServerRepo = repo.NewIMcpServerRepo()
mysqlRepo = repo.NewIMysqlRepo()
postgresqlRepo = repo.NewIPostgresqlRepo()
-120
View File
@@ -3,12 +3,7 @@ package service
import (
"bufio"
"context"
"encoding/json"
"fmt"
"github.com/1Panel-dev/1Panel/agent/app/task"
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/utils/convert"
"github.com/1Panel-dev/1Panel/agent/utils/ini_conf"
"io"
"io/fs"
"os"
@@ -71,8 +66,6 @@ type IFileService interface {
BatchCheckFiles(req request.FilePathsCheck) []response.ExistFileInfo
GetHostMount() []dto.DiskInfo
GetUsersAndGroups() (*response.UserGroupResponse, error)
Convert(req request.FileConvertRequest)
ConvertLog(req dto.PageInfo) (int64, []response.FileConvertLog, error)
}
var filteredPaths = []string{
@@ -561,19 +554,6 @@ func (f *FileService) ReadLogByLine(req request.FileReadByLineReq) (*response.Fi
logFilePath = path.Join(global.Dir.DataDir, fmt.Sprintf("apps/mysql/%s/data/1Panel-slow.log", req.Name))
case "mariadb-slow-logs":
logFilePath = path.Join(global.Dir.DataDir, fmt.Sprintf("apps/mariadb/%s/db/data/1Panel-slow.log", req.Name))
case "php-fpm-slow-logs":
php, err := runtimeRepo.GetFirst(context.Background(), repo.WithByID(req.ID))
if err != nil {
return nil, err
}
logFilePath = php.GetSlowLogPath()
case constant.Supervisord:
configPath := "/etc/supervisord.conf"
pathSet, _ := settingRepo.Get(settingRepo.WithByKey(constant.SupervisorConfigPath))
if pathSet.ID != 0 || pathSet.Value != "" {
configPath = pathSet.Value
}
logFilePath, _ = ini_conf.GetIniValue(configPath, "supervisord", "logfile")
}
file, err := os.Open(logFilePath)
@@ -743,103 +723,3 @@ func getValidUsers(validGroups map[string]bool) ([]response.UserInfo, map[string
}
return users, groupSet, nil
}
func (f *FileService) Convert(req request.FileConvertRequest) {
convertTask, err := task.NewTaskWithOps(i18n.GetMsgByKey("FileConvert"), task.TaskExec, task.TaskScopeFileConvert, req.TaskID, 1)
if err != nil {
global.LOG.Errorf("Create convert task failed %v", err)
return
}
convertTask.AddSubTask(task.GetTaskName(i18n.GetMsgByKey("FileConvert"), task.TaskExec, task.TaskScopeFileConvert), func(t *task.Task) (err error) {
for _, file := range req.Files {
input := filepath.Join(file.Path, file.InputFile)
nameOnly := file.InputFile[0 : len(file.InputFile)-len(file.Extension)]
output := filepath.Join(req.OutputPath, nameOnly+"."+file.OutputFormat)
status, errMsg := convert.MediaFile(input, output, file.OutputFormat, req.DeleteSource)
if status == "FAILED" {
convertTask.Log(fmt.Sprintf("%s -> %s [%s]: %s\n",
input, output, status, errMsg))
} else {
convertTask.Log(fmt.Sprintf("%s -> %s [%s]: %s\n",
input, output, status, "SUCCESS"))
}
}
return nil
}, nil)
go func() {
_ = convertTask.Execute()
}()
}
func (f *FileService) ConvertLog(req dto.PageInfo) (total int64, data []response.FileConvertLog, err error) {
logFilePath := filepath.Join(global.Dir.ConvertLogDir, "convert.log")
file, err := os.Open(logFilePath)
if err != nil {
return 0, nil, err
}
defer file.Close()
const chunkSize = 64 * 1024
stat, err := file.Stat()
if err != nil {
return 0, nil, err
}
fileSize := stat.Size()
var (
buf []byte
remainder []byte
offset = fileSize
lines []string
)
pageStart := int64((req.Page - 1) * req.PageSize)
pageEnd := pageStart + int64(req.PageSize)
for offset > 0 {
readSize := chunkSize
if offset < int64(readSize) {
readSize = int(offset)
}
offset -= int64(readSize)
tmp := make([]byte, readSize)
if _, err := file.ReadAt(tmp, offset); err != nil && err != io.EOF {
return 0, nil, err
}
buf = append(tmp, remainder...)
linesSplit := strings.Split(string(buf), "\n")
if offset > 0 {
remainder = []byte(linesSplit[0])
linesSplit = linesSplit[1:]
}
for i := len(linesSplit) - 1; i >= 0; i-- {
line := strings.TrimSpace(linesSplit[i])
if line == "" {
continue
}
total++
if total > pageStart && total <= pageEnd {
lines = append(lines, line)
}
if total >= pageEnd {
break
}
}
if total >= pageEnd {
break
}
}
for _, line := range lines {
var entry response.FileConvertLog
if err := json.Unmarshal([]byte(line), &entry); err == nil {
data = append(data, entry)
}
}
return total, data, nil
}
+2 -5
View File
@@ -329,8 +329,7 @@ func (u *FirewallService) OperateForwardRule(req dto.ForwardRuleOperate) error {
if reqRule.Port == rule.Port &&
reqRule.TargetPort == rule.TargetPort &&
reqRule.TargetIP == rule.TargetIP &&
proto == rule.Protocol &&
reqRule.Interface == rule.Interface {
proto == rule.Protocol {
shouldKeep = false
break
}
@@ -354,8 +353,7 @@ func (u *FirewallService) OperateForwardRule(req dto.ForwardRuleOperate) error {
if reqRule.Port == rule.Port &&
reqRule.TargetPort == rule.TargetPort &&
reqRule.TargetIP == rule.TargetIP &&
proto == rule.Protocol &&
reqRule.Interface == rule.Interface {
proto == rule.Protocol {
return buserr.New("ErrRecordExist")
}
}
@@ -385,7 +383,6 @@ func (u *FirewallService) OperateForwardRule(req dto.ForwardRuleOperate) error {
Port: r.Port,
TargetIP: r.TargetIP,
TargetPort: r.TargetPort,
Interface: r.Interface,
}, r.Operation); err != nil {
if req.ForceDelete {
global.LOG.Error(err)
+20 -8
View File
@@ -31,6 +31,7 @@ type IHostToolService interface {
CreateToolConfig(req request.HostToolCreate) error
OperateTool(req request.HostToolReq) error
OperateToolConfig(req request.HostToolConfig) (*response.HostToolConfig, error)
GetToolLog(req request.HostToolLogReq) (string, error)
OperateSupervisorProcess(req request.SupervisorProcessConfig) error
GetSupervisorProcessConfig() ([]response.SupervisorProcessConfig, error)
OperateSupervisorProcessFile(req request.SupervisorProcessFileReq) (string, error)
@@ -260,6 +261,25 @@ func (h *HostToolService) OperateToolConfig(req request.HostToolConfig) (*respon
return res, nil
}
func (h *HostToolService) GetToolLog(req request.HostToolLogReq) (string, error) {
fileOp := files.NewFileOp()
logfilePath := ""
switch req.Type {
case constant.Supervisord:
configPath := "/etc/supervisord.conf"
pathSet, _ := settingRepo.Get(settingRepo.WithByKey(constant.SupervisorConfigPath))
if pathSet.ID != 0 || pathSet.Value != "" {
configPath = pathSet.Value
}
logfilePath, _ = ini_conf.GetIniValue(configPath, "supervisord", "logfile")
}
oldContent, err := fileOp.GetContent(logfilePath)
if err != nil {
return "", err
}
return string(oldContent), nil
}
func (h *HostToolService) OperateSupervisorProcess(req request.SupervisorProcessConfig) error {
var (
supervisordDir = path.Join(global.Dir.DataDir, "tools", "supervisord")
@@ -313,9 +333,6 @@ func handleProcess(supervisordDir string, req request.SupervisorProcessConfig, c
_, _ = section.NewKey("priority", "999")
_, _ = section.NewKey("numprocs", req.Numprocs)
_, _ = section.NewKey("process_name", "%(program_name)s_%(process_num)02d")
if req.Environment != "" {
_, _ = section.NewKey("environment", req.Environment)
}
if err = configFile.SaveTo(iniPath); err != nil {
return err
@@ -346,8 +363,6 @@ func handleProcess(supervisordDir string, req request.SupervisorProcessConfig, c
autoRestart.SetValue(req.AutoRestart)
autoStart := section.Key("autostart")
autoStart.SetValue(req.AutoStart)
environment := section.Key("environment")
environment.SetValue(req.Environment)
if err = configFile.SaveTo(iniPath); err != nil {
return err
@@ -420,9 +435,6 @@ func handleProcessConfig(configDir, containerName string) ([]response.Supervisor
if autoStart, _ := section.GetKey("autostart"); autoStart != nil {
config.AutoStart = autoStart.Value()
}
if environment, _ := section.GetKey("environment"); environment != nil {
config.Environment = environment.Value()
}
_ = getProcessStatus(&config, containerName)
result = append(result, config)
}
+8 -42
View File
@@ -256,19 +256,17 @@ func (u *ImageService) ImagePull(req dto.ImagePull) error {
return err
}
defer client.Close()
taskItem, err := task.NewTaskWithOps(strings.Join(req.ImageName, ","), task.TaskPull, task.TaskScopeImage, req.TaskID, 1)
imageItemName := strings.ReplaceAll(path.Base(req.ImageName), ":", "_")
taskItem, err := task.NewTaskWithOps(imageItemName, task.TaskPull, task.TaskScopeImage, req.TaskID, 1)
if err != nil {
return fmt.Errorf("new task for image pull failed, err: %v", err)
}
for _, item := range req.ImageName {
itemName := strings.ReplaceAll(path.Base(item), ":", "_")
taskItem.AddSubTask(i18n.GetWithName("ImagePull", itemName), func(t *task.Task) error {
taskItem.Logf("----------------- %s -----------------", itemName)
go func() {
taskItem.AddSubTask(i18n.GetWithName("ImagePull", req.ImageName), func(t *task.Task) error {
options := image.PullOptions{}
imageName := item
imageName := req.ImageName
if req.RepoID == 0 {
hasAuth, authStr := loadAuthInfo(item)
hasAuth, authStr := loadAuthInfo(req.ImageName)
if hasAuth {
options.RegistryAuth = authStr
}
@@ -290,7 +288,7 @@ func (u *ImageService) ImagePull(req dto.ImagePull) error {
authStr := base64.URLEncoding.EncodeToString(encodedJSON)
options.RegistryAuth = authStr
}
imageName = repo.DownloadUrl + "/" + item
imageName = repo.DownloadUrl + "/" + req.ImageName
}
dockerCli := docker.NewClientWithExist(client)
err = dockerCli.PullImageWithProcessAndOptions(taskItem, imageName, options)
@@ -300,8 +298,6 @@ func (u *ImageService) ImagePull(req dto.ImagePull) error {
}
return nil
}, nil)
}
go func() {
_ = taskItem.Execute()
}()
return nil
@@ -363,39 +359,9 @@ func (u *ImageService) ImageTag(req dto.ImageTag) error {
}
defer client.Close()
imageItem, err := client.ImageInspect(context.Background(), req.SourceID)
if err != nil {
if err := client.ImageTag(context.TODO(), req.SourceID, req.TargetName); err != nil {
return err
}
for _, tag := range req.Tags {
isNew := true
for _, tagOld := range imageItem.RepoTags {
if tag == tagOld {
isNew = false
break
}
}
if isNew {
if err := client.ImageTag(context.TODO(), req.SourceID, tag); err != nil {
return err
}
}
}
for _, tagOld := range imageItem.RepoTags {
isDel := true
for _, tag := range req.Tags {
if tag == tagOld {
isDel = false
break
}
}
if isDel {
if _, err := client.ImageRemove(context.TODO(), tagOld, image.RemoveOptions{}); err != nil {
return err
}
}
}
return nil
}
+2 -5
View File
@@ -10,7 +10,7 @@ import (
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/cmd/server/ai"
"github.com/1Panel-dev/1Panel/agent/cmd/server/mcp"
"github.com/1Panel-dev/1Panel/agent/cmd/server/nginx_conf"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
@@ -565,7 +565,7 @@ func handleEnv(mcpServer *model.McpServer) gotenv.Env {
func handleCreateParams(mcpServer *model.McpServer, environments []request.Environment, volumes []request.Volume) error {
var composeContent []byte
if mcpServer.ID == 0 {
composeContent = ai.DefaultMcpCompose
composeContent = mcp.DefaultMcpCompose
} else {
composeContent = []byte(mcpServer.DockerCompose)
}
@@ -680,9 +680,6 @@ func GetWebsiteID() uint {
}
func pullImage(imageType string) {
if global.CONF.Base.IsOffLine {
return
}
if imageType == "npx" {
if err := docker.PullImage("supercorp/supergateway:latest"); err != nil {
global.LOG.Errorf("docker pull mcp image error: %s", err.Error())
+6 -17
View File
@@ -119,16 +119,7 @@ func updateDefaultServerConfig(enable bool) error {
}
defaultConfig.FilePath = defaultConfigPath
defaultServer := defaultConfig.FindServers()[0]
includeSSL := false
for _, dir := range defaultServer.GetDirectives() {
if dir.GetName() == "include" && dir.GetParameters()[0] == "/usr/local/openresty/nginx/conf/ssl/root_ssl.conf" {
includeSSL = true
break
}
}
updateDefaultServer(defaultServer, nginxInstall.HttpPort, nginxInstall.HttpsPort, enable, includeSSL)
updateDefaultServer(defaultServer, nginxInstall.HttpPort, nginxInstall.HttpsPort, enable)
if err = nginx.WriteConfig(defaultConfig, nginx.IndentedStyle); err != nil {
return err
}
@@ -271,13 +262,11 @@ func nginxCheckAndReload(oldContent string, filePath string, containerName strin
return nil
}
func updateDefaultServer(server *components.Server, httpPort int, httpsPort int, defaultServer bool, ssl bool) {
func updateDefaultServer(server *components.Server, httpPort int, httpsPort int, defaultServer bool) {
server.UpdateListen(fmt.Sprintf("%d", httpPort), defaultServer)
server.UpdateListen(fmt.Sprintf("[::]:%d", httpPort), defaultServer)
if ssl {
server.UpdateListen(fmt.Sprintf("%d", httpsPort), defaultServer, "ssl")
server.UpdateListen(fmt.Sprintf("[::]:%d", httpsPort), defaultServer, "ssl")
server.UpdateListen(fmt.Sprintf("%d", httpsPort), defaultServer, "quic", "reuseport")
server.UpdateListen(fmt.Sprintf("[::]:%d", httpsPort), defaultServer, "quic", "reuseport")
}
server.UpdateListen(fmt.Sprintf("%d", httpsPort), defaultServer, "ssl")
server.UpdateListen(fmt.Sprintf("[::]:%d", httpsPort), defaultServer, "ssl")
server.UpdateListen(fmt.Sprintf("%d", httpsPort), defaultServer, "quic", "reuseport")
server.UpdateListen(fmt.Sprintf("[::]:%d", httpsPort), defaultServer, "quic", "reuseport")
}
+25 -36
View File
@@ -8,7 +8,6 @@ import (
fcgiclient "github.com/tomasen/fcgi_client"
"maps"
"os"
"os/exec"
"path"
"path/filepath"
"regexp"
@@ -232,14 +231,6 @@ func (r *RuntimeService) Page(req request.RuntimeSearch) (int64, []response.Runt
if err != nil {
return 0, nil, err
}
detail, _ := appDetailRepo.GetFirst(repo.WithByID(runtime.AppDetailID))
if detail.AppId == 0 {
appID, appDetailID := handleRuntimeDetailID(runtime)
runtimeDTO.AppDetailID = appDetailID
runtimeDTO.AppID = appID
} else {
runtimeDTO.AppID = detail.AppId
}
for k, v := range envs {
runtimeDTO.Params[k] = v
if strings.Contains(k, "CONTAINER_PORT") || strings.Contains(k, "HOST_PORT") {
@@ -390,9 +381,6 @@ func (r *RuntimeService) Get(id uint) (*response.RuntimeDTO, error) {
appParam.Value = []string{}
} else {
appParam.Value = strings.Split(v, ",")
if strSlice, ok := appParam.Value.([]string); ok && len(strSlice) > 0 && strSlice[0] == "" {
appParam.Value = strSlice[1:]
}
}
} else {
for _, fv := range form.Values {
@@ -596,7 +584,7 @@ func (r *RuntimeService) GetNodeModules(req request.NodeModuleReq) ([]response.N
nodeModulesPath := path.Join(runtime.CodeDir, "node_modules")
fileOp := files.NewFileOp()
if !fileOp.Stat(nodeModulesPath) {
return res, nil
return nil, buserr.New("ErrNodeModulesNotFound")
}
moduleDirs, err := os.ReadDir(nodeModulesPath)
if err != nil {
@@ -629,17 +617,31 @@ func (r *RuntimeService) OperateNodeModules(req request.NodeModuleOperateReq) er
if err != nil {
return err
}
operation := getOperation(req.Operate, req.PkgManager)
execScript := fmt.Sprintf("%s %s %s", req.PkgManager, operation, req.Module)
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Minute)
defer cancel()
installCmd := exec.CommandContext(ctx, "docker", "exec", "-i", containerName, "bash", "-c", execScript)
output, err := installCmd.CombinedOutput()
if err != nil {
return fmt.Errorf("failed to execute command: %s, error: %w", string(output), err)
cmd := req.PkgManager
switch req.Operate {
case constant.RuntimeInstall:
if req.PkgManager == constant.RuntimeNpm {
cmd += " install"
} else {
cmd += " add"
}
case constant.RuntimeUninstall:
if req.PkgManager == constant.RuntimeNpm {
cmd += " uninstall"
} else {
cmd += " remove"
}
case constant.RuntimeUpdate:
if req.PkgManager == constant.RuntimeNpm {
cmd += " update"
} else {
cmd += " upgrade"
}
}
return nil
cmd += " " + req.Module
cmdMgr := cmd2.NewCommandMgr(cmd2.WithTimeout(5 * time.Minute))
return cmdMgr.Run("docker", "exec", "-i", containerName, "bash", "-c", fmt.Sprintf("'%s'", cmd))
}
func (r *RuntimeService) SyncForRestart() error {
@@ -858,10 +860,6 @@ func (r *RuntimeService) GetPHPConfig(id uint) (*response.PHPConfig, error) {
if uploadMaxSize != "" {
res.UploadMaxSize = uploadMaxSize
}
timeout := phpConfig.Key("max_execution_time").Value()
if timeout != "" {
res.MaxExecutionTime = timeout
}
return res, nil
}
@@ -914,15 +912,6 @@ func (r *RuntimeService) UpdatePHPConfig(req request.PHPConfigUpdate) (err error
if matched, _ := regexp.MatchString(patternUpload, line); matched {
lines[i] = "upload_max_filesize" + " = " + req.UploadMaxSize
}
case "max_execution_time":
pattern := "^" + regexp.QuoteMeta("max_execution_time") + "\\s*=\\s*.*$"
if matched, _ := regexp.MatchString(pattern, line); matched {
lines[i] = "max_execution_time" + " = " + req.MaxExecutionTime
}
patternInput := "^" + regexp.QuoteMeta("max_input_time") + "\\s*=\\s*.*$"
if matched, _ := regexp.MatchString(patternInput, line); matched {
lines[i] = "max_input_time" + " = " + req.MaxExecutionTime
}
}
}
updatedContent := strings.Join(lines, "\n")
+6 -44
View File
@@ -689,15 +689,9 @@ func checkContainerStatus(name string) (string, error) {
return "", nil
}
func delPHPExtensions(dir, phpExtensionDir, fileName, extName string) {
fileOp := files.NewFileOp()
_ = fileOp.DeleteFile(path.Join(phpExtensionDir, fileName))
_ = fileOp.DeleteFile(path.Join(dir, "conf", "conf.d", "docker-php-ext-"+extName+".ini"))
_ = removePHPIniExt(path.Join(dir, "conf", "php.ini"), fileName)
}
func unInstallPHPExtension(runtime *model.Runtime, delExtensions []string) error {
dir := runtime.GetPath()
fileOP := files.NewFileOp()
var phpExtensions []response.SupportExtension
if err := json.Unmarshal(nginx_conf.GetWebsiteFile("php_extensions.json"), &phpExtensions); err != nil {
return err
@@ -706,20 +700,16 @@ func unInstallPHPExtension(runtime *model.Runtime, delExtensions []string) error
phpExtensionDir := path.Join(dir, "extensions", getExtensionDir(phpVersion))
delMap := make(map[string]struct{})
for _, del := range delExtensions {
exist := false
for _, ext := range phpExtensions {
for _, ext := range phpExtensions {
for _, del := range delExtensions {
if ext.Name == del {
exist = true
delMap[ext.Check] = struct{}{}
delPHPExtensions(dir, phpExtensionDir, ext.Check, ext.Name)
_ = fileOP.DeleteFile(path.Join(phpExtensionDir, ext.File))
_ = fileOP.DeleteFile(path.Join(dir, "conf", "conf.d", "docker-php-ext-"+ext.Check+".ini"))
_ = removePHPIniExt(path.Join(dir, "conf", "php.ini"), ext.File)
break
}
}
if !exist {
delMap[del] = struct{}{}
delPHPExtensions(dir, phpExtensionDir, del+".so", del)
}
}
extensions := getRuntimeEnv(runtime.Env, "PHP_EXTENSIONS")
var (
@@ -1045,31 +1035,3 @@ func HandleOldPHPRuntime() {
}()
}
}
func getOperation(operate, pkgManager string) string {
operations := map[string][2]string{
constant.RuntimeInstall: {"install", "add"},
constant.RuntimeUninstall: {"uninstall", "remove"},
constant.RuntimeUpdate: {"update", "upgrade"},
}
ops := operations[operate]
if pkgManager == constant.RuntimeNpm {
return ops[0]
}
return ops[1]
}
func handleRuntimeDetailID(runtime model.Runtime) (uint, uint) {
app, _ := appRepo.GetFirst(appRepo.WithKey(runtime.Type))
if app.ID == 0 {
return 0, 0
}
appDetail, _ := appDetailRepo.GetFirst(appDetailRepo.WithVersion(runtime.Version), appDetailRepo.WithAppId(app.ID))
if appDetail.ID == 0 {
return 0, 0
}
runtime.AppDetailID = appDetail.ID
_ = runtimeRepo.Save(&runtime)
return app.ID, appDetail.ID
}
+2 -24
View File
@@ -8,6 +8,7 @@ import (
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/utils/encrypt"
"github.com/1Panel-dev/1Panel/agent/utils/ssh"
"github.com/jinzhu/copier"
@@ -22,7 +23,6 @@ type ISettingService interface {
TestConnByInfo(req dto.SSHConnData) bool
SaveConnInfo(req dto.SSHConnData) error
GetSystemProxy() (*dto.SystemProxy, error)
GetLocalConn() dto.SSHConnData
GetSettingByKey(key string) string
}
@@ -119,6 +119,7 @@ func (u *SettingService) SaveConnInfo(req dto.SSHConnData) error {
localConn, _ := json.Marshal(&connItem)
connAfterEncrypt, _ := encrypt.StringEncrypt(string(localConn))
_ = settingRepo.Update("LocalSSHConn", connAfterEncrypt)
_ = settingRepo.Update("LocalSSHConnShow", constant.StatusEnable)
return nil
}
@@ -133,29 +134,6 @@ func (u *SettingService) GetSystemProxy() (*dto.SystemProxy, error) {
return &systemProxy, nil
}
func (u *SettingService) GetLocalConn() dto.SSHConnData {
var data dto.SSHConnData
connItem, _ := settingRepo.GetValueByKey("LocalSSHConn")
if len(connItem) == 0 {
return data
}
connInfoInDB, _ := encrypt.StringDecrypt(connItem)
data.LocalSSHConnShow, _ = settingRepo.GetValueByKey("LocalSSHConnShow")
if err := json.Unmarshal([]byte(connInfoInDB), &data); err != nil {
return data
}
if len(data.Password) != 0 {
data.Password = base64.StdEncoding.EncodeToString([]byte(data.Password))
}
if len(data.PrivateKey) != 0 {
data.PrivateKey = base64.StdEncoding.EncodeToString([]byte(data.PrivateKey))
}
if len(data.PassPhrase) != 0 {
data.PassPhrase = base64.StdEncoding.EncodeToString([]byte(data.PassPhrase))
}
return data
}
func (u *SettingService) GetSettingByKey(key string) string {
switch key {
case "LocalSSHConn":
+28 -191
View File
@@ -3,7 +3,6 @@ package service
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"os"
"os/user"
@@ -38,16 +37,15 @@ type SSHService struct{}
type ISSHService interface {
GetSSHInfo() (*dto.SSHInfo, error)
OperateSSH(operation string) error
UpdateByFile(value string) error
Update(req dto.SSHUpdate) error
LoadSSHFile(name string) (string, error)
UpdateByFile(req dto.SettingUpdate) error
LoadSSHConf() (string, error)
LoadLog(ctx *gin.Context, req dto.SearchSSHLog) (int64, []dto.SSHHistory, error)
ExportLog(ctx *gin.Context, req dto.SearchSSHLog) (string, error)
SyncRootCert() error
CreateRootCert(req dto.RootCertOperate) error
EditRootCert(req dto.RootCertOperate) error
CreateRootCert(req dto.CreateRootCert) error
SearchRootCerts(req dto.SearchWithPage) (int64, interface{}, error)
DeleteRootCerts(req dto.ForceDelete) error
}
@@ -210,20 +208,31 @@ func (u *SSHService) Update(req dto.SSHUpdate) error {
if err := NewIFirewallService().UpdatePortRule(ruleItem); err != nil {
global.LOG.Errorf("reset firewall rules %s -> %s failed, err: %v", req.OldValue, req.NewValue, err)
}
newPort, _ := strconv.Atoi(req.NewValue)
if err := updateLocalConn(uint(newPort)); err != nil {
global.LOG.Errorf("update local conn for terminal failed, err: %v", err)
}
if err := updateSSHSocketFile(req.NewValue); err != nil {
global.LOG.Errorf("update port for ssh.socket failed, err: %v", err)
}
}
_, _ = cmd.RunDefaultWithStdoutBashCf("%s systemctl restart %s", sudo, serviceName)
return nil
}
func (u *SSHService) UpdateByFile(value string) error {
serviceName, err := loadServiceName()
if err != nil {
return err
}
file, err := os.OpenFile(sshPath, os.O_WRONLY|os.O_TRUNC, constant.FilePerm)
if err != nil {
return err
}
defer file.Close()
if _, err = file.WriteString(value); err != nil {
return err
}
sudo := cmd.SudoHandleCmd()
_, _ = cmd.RunDefaultWithStdoutBashCf("%s systemctl restart %s", sudo, serviceName)
return nil
}
func (u *SSHService) SyncRootCert() error {
currentUser, err := user.Current()
if err != nil {
@@ -261,7 +270,7 @@ func (u *SSHService) SyncRootCert() error {
return hostRepo.SyncCert(rootCerts)
}
func (u *SSHService) CreateRootCert(req dto.RootCertOperate) error {
func (u *SSHService) CreateRootCert(req dto.CreateRootCert) error {
if cmd.CheckIllegal(req.EncryptionMode, req.PassPhrase) {
return buserr.New("ErrCmdIllegal")
}
@@ -281,19 +290,6 @@ func (u *SSHService) CreateRootCert(req dto.RootCertOperate) error {
publicPath := fmt.Sprintf("%s/.ssh/%s.pub", currentUser.HomeDir, req.Name)
authFilePath := currentUser.HomeDir + "/.ssh/authorized_keys"
authFileItem, _ := os.ReadFile(authFilePath)
authFile := string(authFileItem)
if authFile != "" && !strings.HasSuffix(authFile, "\n") {
file, err := os.OpenFile(authFilePath, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
return err
}
defer file.Close()
if _, err := file.WriteString("\n"); err != nil {
return err
}
}
if req.Mode == "input" || req.Mode == "import" {
if err := os.WriteFile(privatePath, []byte(req.PrivateKey), constant.FilePerm); err != nil {
return err
@@ -322,58 +318,7 @@ func (u *SSHService) CreateRootCert(req dto.RootCertOperate) error {
if len(cert.PassPhrase) != 0 {
cert.PassPhrase, _ = encrypt.StringEncrypt(cert.PassPhrase)
}
return hostRepo.SaveCert(&cert)
}
func (u *SSHService) EditRootCert(req dto.RootCertOperate) error {
currentUser, err := user.Current()
if err != nil {
return fmt.Errorf("load current user failed, err: %v", err)
}
certItem, _ := hostRepo.GetCert(repo.WithByID(req.ID))
if certItem.ID == 0 {
return buserr.New("ErrRecordNotFound")
}
oldPublicItem, err := os.ReadFile(certItem.PublicKeyPath)
if err != nil {
return err
}
var cert model.RootCert
if err := copier.Copy(&cert, req); err != nil {
return err
}
cert.PrivateKeyPath = fmt.Sprintf("%s/.ssh/%s", currentUser.HomeDir, req.Name)
cert.PublicKeyPath = fmt.Sprintf("%s/.ssh/%s.pub", currentUser.HomeDir, req.Name)
if err := os.WriteFile(cert.PrivateKeyPath, []byte(req.PrivateKey), constant.FilePerm); err != nil {
return err
}
if err := os.WriteFile(cert.PublicKeyPath, []byte(req.PublicKey), constant.FilePerm); err != nil {
return err
}
authFilePath := currentUser.HomeDir + "/.ssh/authorized_keys"
authItem, err := os.ReadFile(authFilePath)
if err != nil {
return err
}
oldPublic := strings.ReplaceAll(string(oldPublicItem), "\n", "")
newPublic := strings.ReplaceAll(string(req.PublicKey), "\n", "")
lines := strings.Split(string(authItem), "\n")
var newFiles []string
for i := 0; i < len(lines); i++ {
if len(lines[i]) != 0 && lines[i] != oldPublic && lines[i] != newPublic {
newFiles = append(newFiles, lines[i])
}
}
newFiles = append(newFiles, newPublic)
if err := os.WriteFile(authFilePath, []byte(strings.Join(newFiles, "\n")), constant.FilePerm); err != nil {
return fmt.Errorf("refresh authorized_keys failed, err: %v", err)
}
if len(cert.PassPhrase) != 0 {
cert.PassPhrase, _ = encrypt.StringEncrypt(cert.PassPhrase)
}
return hostRepo.SaveCert(&cert)
return hostRepo.CreateCert(&cert)
}
func (u *SSHService) SearchRootCerts(req dto.SearchWithPage) (int64, interface{}, error) {
@@ -546,64 +491,17 @@ func (u *SSHService) ExportLog(ctx *gin.Context, req dto.SearchSSHLog) (string,
return tmpFileName, nil
}
func (u *SSHService) LoadSSHFile(name string) (string, error) {
var fileName string
switch name {
case "authKeys":
currentUser, err := user.Current()
if err != nil {
return "", fmt.Errorf("load current user failed, err: %v", err)
}
fileName = currentUser.HomeDir + "/.ssh/authorized_keys"
case "sshdConf":
fileName = "/etc/ssh/sshd_config"
default:
return "", buserr.WithName("ErrNotSupportType", name)
func (u *SSHService) LoadSSHConf() (string, error) {
if _, err := os.Stat("/etc/ssh/sshd_config"); err != nil {
return "", buserr.New("ErrHttpReqNotFound")
}
if _, err := os.Stat(fileName); err != nil {
return "", buserr.WithErr("ErrHttpReqNotFound", err)
}
content, err := os.ReadFile(fileName)
content, err := os.ReadFile("/etc/ssh/sshd_config")
if err != nil {
return "", err
}
return string(content), nil
}
func (u *SSHService) UpdateByFile(req dto.SettingUpdate) error {
var fileName string
switch req.Key {
case "authKeys":
currentUser, err := user.Current()
if err != nil {
return fmt.Errorf("load current user failed, err: %v", err)
}
fileName = currentUser.HomeDir + "/.ssh/authorized_keys"
case "sshdConf":
fileName = "/etc/ssh/sshd_config"
default:
return buserr.WithName("ErrNotSupportType", req.Key)
}
file, err := os.OpenFile(fileName, os.O_WRONLY|os.O_TRUNC, constant.FilePerm)
if err != nil {
return err
}
defer file.Close()
if _, err = file.WriteString(req.Value); err != nil {
return err
}
if req.Key == "authKeys" {
return nil
}
serviceName, err := loadServiceName()
if err != nil {
return err
}
sudo := cmd.SudoHandleCmd()
_, _ = cmd.RunDefaultWithStdoutBashCf("%s systemctl restart %s", sudo, serviceName)
return nil
}
func sortFileList(fileNames []sshFileItem) []sshFileItem {
if len(fileNames) < 2 {
return fileNames
@@ -840,64 +738,3 @@ func loadEncryptioMode(content string) string {
}
return ""
}
func updateLocalConn(newPort uint) error {
conn, _ := settingRepo.GetValueByKey("LocalSSHConn")
if len(conn) == 0 {
return nil
}
connItem, err := encrypt.StringDecrypt(conn)
if err != nil {
return err
}
var data dto.SSHConnData
if err := json.Unmarshal([]byte(connItem), &data); err != nil {
return err
}
data.Port = newPort
connNew, err := json.Marshal(data)
if err != nil {
return err
}
connNewItem, err := encrypt.StringEncrypt(string(connNew))
if err != nil {
return err
}
return settingRepo.Update("LocalSSHConn", connNewItem)
}
func updateSSHSocketFile(newPort string) error {
active, _ := systemctl.IsActive("ssh.socket")
if !active {
return nil
}
filepath := "/usr/lib/systemd/system/ssh.socket"
file, err := os.ReadFile(filepath)
if err != nil {
return err
}
lines := strings.Split(string(file), "\n")
for i := 0; i < len(lines); i++ {
if strings.HasPrefix(lines[i], "ListenStream=") {
parts := strings.Split(lines[i], ":")
if len(parts) > 1 {
lines[i] = strings.ReplaceAll(lines[i], parts[len(parts)-1], newPort)
continue
}
parts = strings.Split(lines[i], "=")
if len(parts) > 1 {
lines[i] = strings.ReplaceAll(lines[i], parts[len(parts)-1], newPort)
}
}
}
fileItem, err := os.OpenFile(filepath, os.O_WRONLY|os.O_TRUNC, constant.FilePerm)
if err != nil {
return err
}
defer fileItem.Close()
if _, err = fileItem.WriteString(strings.Join(lines, "\n")); err != nil {
return err
}
_ = cmd.RunDefaultBashC("systemctl daemon-reload && systemctl restart ssh.socket")
return nil
}
-438
View File
@@ -1,438 +0,0 @@
package service
import (
"errors"
"fmt"
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
"github.com/1Panel-dev/1Panel/agent/app/dto/response"
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/cmd/server/ai"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"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/subosito/gotenv"
"gopkg.in/yaml.v3"
"os"
"path"
"path/filepath"
"regexp"
"strconv"
"strings"
)
type TensorRTLLMService struct{}
type ITensorRTLLMService interface {
Page(req request.TensorRTLLMSearch) response.TensorRTLLMsRes
Create(create request.TensorRTLLMCreate) error
Update(req request.TensorRTLLMUpdate) error
Delete(id uint) error
Operate(req request.TensorRTLLMOperate) error
}
func NewITensorRTLLMService() ITensorRTLLMService {
return &TensorRTLLMService{}
}
func (t TensorRTLLMService) Page(req request.TensorRTLLMSearch) response.TensorRTLLMsRes {
var (
res response.TensorRTLLMsRes
items []response.TensorRTLLMDTO
)
total, data, _ := tensorrtLLMRepo.Page(req.PageInfo.Page, req.PageInfo.PageSize)
for _, item := range data {
_ = syncTensorRTLLMContainerStatus(&item)
serverDTO := response.TensorRTLLMDTO{
TensorRTLLM: item,
}
envs, _ := gotenv.Unmarshal(item.Env)
serverDTO.Version = envs["VERSION"]
serverDTO.ModelDir = envs["MODEL_PATH"]
serverDTO.Dir = path.Join(global.Dir.TensorRTLLMDir, item.Name)
serverDTO.Image = envs["IMAGE"]
serverDTO.Command = getCommand(item.Env)
for k, v := range envs {
if strings.Contains(k, "CONTAINER_PORT") || strings.Contains(k, "HOST_PORT") {
if strings.Contains(k, "CONTAINER_PORT") {
r := regexp.MustCompile(`_(\d+)$`)
matches := r.FindStringSubmatch(k)
containerPort, err := strconv.Atoi(v)
if err != nil {
continue
}
hostPort, err := strconv.Atoi(envs[fmt.Sprintf("HOST_PORT_%s", matches[1])])
if err != nil {
continue
}
hostIP := envs[fmt.Sprintf("HOST_IP_%s", matches[1])]
if hostIP == "" {
hostIP = "0.0.0.0"
}
serverDTO.ExposedPorts = append(serverDTO.ExposedPorts, request.ExposedPort{
ContainerPort: containerPort,
HostPort: hostPort,
HostIP: hostIP,
})
}
}
}
composeByte, err := files.NewFileOp().GetContent(path.Join(global.Dir.TensorRTLLMDir, item.Name, "docker-compose.yml"))
if err == nil {
serverDTO.Environments, _ = getDockerComposeEnvironments(composeByte)
}
volumes, err := getDockerComposeVolumes(composeByte)
if err == nil {
var defaultVolumes = map[string]string{
"${MODEL_PATH}": "${MODEL_PATH}",
}
for _, volume := range volumes {
exist := false
for key, value := range defaultVolumes {
if key == volume.Source && value == volume.Target {
exist = true
break
}
}
if !exist {
serverDTO.Volumes = append(serverDTO.Volumes, volume)
}
}
}
items = append(items, serverDTO)
}
res.Total = total
res.Items = items
return res
}
func handleLLMParams(llm *model.TensorRTLLM, create request.TensorRTLLMCreate) error {
var composeContent []byte
if llm.ID == 0 {
composeContent = ai.DefaultTensorrtLLMCompose
} else {
composeContent = []byte(llm.DockerCompose)
}
composeMap := make(map[string]interface{})
if err := yaml.Unmarshal(composeContent, &composeMap); err != nil {
return err
}
services, serviceValid := composeMap["services"].(map[string]interface{})
if !serviceValid {
return buserr.New("ErrFileParse")
}
serviceName := ""
serviceValue := make(map[string]interface{})
if llm.ID > 0 {
serviceName = llm.Name
serviceValue = services[serviceName].(map[string]interface{})
} else {
for name, service := range services {
serviceName = name
serviceValue = service.(map[string]interface{})
break
}
delete(services, serviceName)
}
delete(serviceValue, "ports")
if len(create.ExposedPorts) > 0 {
var ports []interface{}
for i := range create.ExposedPorts {
containerPortStr := fmt.Sprintf("CONTAINER_PORT_%d", i)
hostPortStr := fmt.Sprintf("HOST_PORT_%d", i)
hostIPStr := fmt.Sprintf("HOST_IP_%d", i)
ports = append(ports, fmt.Sprintf("${%s}:${%s}:${%s}", hostIPStr, hostPortStr, containerPortStr))
}
serviceValue["ports"] = ports
}
delete(serviceValue, "environment")
var environments []interface{}
environments = append(environments, fmt.Sprintf("MODEL_PATH=%s", create.ModelDir))
for _, e := range create.Environments {
environments = append(environments, fmt.Sprintf("%s=%s", e.Key, e.Value))
}
serviceValue["environment"] = environments
var volumes []interface{}
var defaultVolumes = map[string]string{
"${MODEL_PATH}": "${MODEL_PATH}",
}
for k, v := range defaultVolumes {
volumes = append(volumes, fmt.Sprintf("%s:%s", k, v))
}
for _, volume := range create.Volumes {
volumes = append(volumes, fmt.Sprintf("%s:%s", volume.Source, volume.Target))
}
serviceValue["volumes"] = volumes
services[llm.Name] = serviceValue
composeByte, err := yaml.Marshal(composeMap)
if err != nil {
return err
}
llm.DockerCompose = string(composeByte)
return nil
}
func handleLLMEnv(llm *model.TensorRTLLM, create request.TensorRTLLMCreate) gotenv.Env {
envMap := make(gotenv.Env)
envMap["CONTAINER_NAME"] = create.ContainerName
envMap["MODEL_PATH"] = create.ModelDir
envMap["VERSION"] = create.Version
envMap["IMAGE"] = create.Image
envMap["COMMAND"] = create.Command
for i, port := range create.ExposedPorts {
containerPortStr := fmt.Sprintf("CONTAINER_PORT_%d", i)
hostPortStr := fmt.Sprintf("HOST_PORT_%d", i)
hostIPStr := fmt.Sprintf("HOST_IP_%d", i)
envMap[containerPortStr] = strconv.Itoa(port.ContainerPort)
envMap[hostPortStr] = strconv.Itoa(port.HostPort)
envMap[hostIPStr] = port.HostIP
}
orders := []string{"MODEL_PATH", "COMMAND"}
envStr, _ := env.MarshalWithOrder(envMap, orders)
llm.Env = envStr
return envMap
}
func (t TensorRTLLMService) Create(create request.TensorRTLLMCreate) error {
servers, _ := tensorrtLLMRepo.List()
for _, server := range servers {
if server.ContainerName == create.ContainerName {
return buserr.New("ErrContainerName")
}
if server.Name == create.Name {
return buserr.New("ErrNameIsExist")
}
}
for _, export := range create.ExposedPorts {
if err := checkPortExist(export.HostPort); err != nil {
return err
}
}
if err := checkContainerName(create.ContainerName); err != nil {
return err
}
tensorrtLLMDir := path.Join(global.Dir.TensorRTLLMDir, create.Name)
filesOp := files.NewFileOp()
if !filesOp.Stat(tensorrtLLMDir) {
_ = filesOp.CreateDir(tensorrtLLMDir, 0644)
}
if create.ModelSpeedup {
if err := handleModelArchive(create.ModelType, create.ModelDir); err != nil {
return err
}
}
tensorrtLLM := &model.TensorRTLLM{
Name: create.Name,
ContainerName: create.ContainerName,
Status: constant.StatusStarting,
ModelType: create.ModelType,
ModelSpeedup: create.ModelSpeedup,
}
if err := handleLLMParams(tensorrtLLM, create); err != nil {
return err
}
envMap := handleLLMEnv(tensorrtLLM, create)
llmDir := path.Join(global.Dir.TensorRTLLMDir, create.Name)
envPath := path.Join(llmDir, ".env")
if err := env.WriteWithOrder(envMap, envPath, []string{"MODEL_PATH", "COMMAND"}); err != nil {
return err
}
dockerComposePath := path.Join(llmDir, "docker-compose.yml")
if err := filesOp.SaveFile(dockerComposePath, tensorrtLLM.DockerCompose, 0644); err != nil {
return err
}
tensorrtLLM.Status = constant.StatusStarting
if err := tensorrtLLMRepo.Create(tensorrtLLM); err != nil {
return err
}
go startTensorRTLLM(tensorrtLLM)
return nil
}
func (t TensorRTLLMService) Update(req request.TensorRTLLMUpdate) error {
tensorrtLLM, err := tensorrtLLMRepo.GetFirst(repo.WithByID(req.ID))
if err != nil {
return err
}
if tensorrtLLM.ContainerName != req.ContainerName {
if err := checkContainerName(req.ContainerName); err != nil {
return err
}
}
tensorrtLLM.ModelType = req.ModelType
tensorrtLLM.ModelSpeedup = req.ModelSpeedup
tensorrtLLM.ContainerName = req.ContainerName
if err := handleLLMParams(tensorrtLLM, req.TensorRTLLMCreate); err != nil {
return err
}
envMap := handleLLMEnv(tensorrtLLM, req.TensorRTLLMCreate)
envStr, _ := gotenv.Marshal(envMap)
tensorrtLLM.Env = envStr
llmDir := path.Join(global.Dir.TensorRTLLMDir, tensorrtLLM.Name)
envPath := path.Join(llmDir, ".env")
if err := env.WriteWithOrder(envMap, envPath, []string{"MODEL_PATH", "COMMAND"}); err != nil {
return err
}
dockerComposePath := path.Join(llmDir, "docker-compose.yml")
if err := files.NewFileOp().SaveFile(dockerComposePath, tensorrtLLM.DockerCompose, 0644); err != nil {
return err
}
tensorrtLLM.Status = constant.StatusStarting
if err := tensorrtLLMRepo.Save(tensorrtLLM); err != nil {
return err
}
go startTensorRTLLM(tensorrtLLM)
return nil
}
func (t TensorRTLLMService) Delete(id uint) error {
tensorrtLLM, err := tensorrtLLMRepo.GetFirst(repo.WithByID(id))
if err != nil {
return err
}
composePath := path.Join(global.Dir.TensorRTLLMDir, tensorrtLLM.Name, "docker-compose.yml")
_, _ = compose.Down(composePath)
_ = files.NewFileOp().DeleteDir(path.Join(global.Dir.TensorRTLLMDir, tensorrtLLM.Name))
return tensorrtLLMRepo.DeleteBy(repo.WithByID(id))
}
func (t TensorRTLLMService) Operate(req request.TensorRTLLMOperate) error {
tensorrtLLM, err := tensorrtLLMRepo.GetFirst(repo.WithByID(req.ID))
if err != nil {
return err
}
composePath := path.Join(global.Dir.TensorRTLLMDir, tensorrtLLM.Name, "docker-compose.yml")
var out string
switch req.Operate {
case "start":
out, err = compose.Up(composePath)
tensorrtLLM.Status = constant.StatusRunning
case "stop":
out, err = compose.Down(composePath)
tensorrtLLM.Status = constant.StatusStopped
case "restart":
out, err = compose.Restart(composePath)
tensorrtLLM.Status = constant.StatusRunning
}
if err != nil {
tensorrtLLM.Status = constant.StatusError
tensorrtLLM.Message = out
}
return tensorrtLLMRepo.Save(tensorrtLLM)
}
func startTensorRTLLM(tensorrtLLM *model.TensorRTLLM) {
composePath := path.Join(global.Dir.TensorRTLLMDir, tensorrtLLM.Name, "docker-compose.yml")
if tensorrtLLM.Status != constant.StatusNormal {
_, _ = compose.Down(composePath)
}
if out, err := compose.Up(composePath); err != nil {
tensorrtLLM.Status = constant.StatusError
tensorrtLLM.Message = out
} else {
tensorrtLLM.Status = constant.StatusRunning
tensorrtLLM.Message = ""
}
_ = syncTensorRTLLMContainerStatus(tensorrtLLM)
}
func syncTensorRTLLMContainerStatus(tensorrtLLM *model.TensorRTLLM) error {
containerNames := []string{tensorrtLLM.ContainerName}
cli, err := docker.NewClient()
if err != nil {
return err
}
defer cli.Close()
containers, err := cli.ListContainersByName(containerNames)
if err != nil {
return err
}
if len(containers) == 0 {
if tensorrtLLM.Status == constant.StatusStarting {
return nil
}
tensorrtLLM.Status = constant.StatusStopped
return tensorrtLLMRepo.Save(tensorrtLLM)
}
container := containers[0]
switch container.State {
case "exited":
tensorrtLLM.Status = constant.StatusError
case "running":
tensorrtLLM.Status = constant.StatusRunning
case "paused":
tensorrtLLM.Status = constant.StatusStopped
case "restarting":
tensorrtLLM.Status = constant.StatusRestarting
default:
if tensorrtLLM.Status != constant.StatusStarting {
tensorrtLLM.Status = constant.StatusStopped
}
}
return tensorrtLLMRepo.Save(tensorrtLLM)
}
func findModelArchive(modelType string) (string, error) {
const baseDir = "/home/models"
prefix := fmt.Sprintf("FusionXplay_%s_Accelerator", modelType)
entries, err := os.ReadDir(baseDir)
if err != nil {
return "", fmt.Errorf("failed to read %s: %w", baseDir, err)
}
for _, entry := range entries {
if entry.IsDir() {
continue
}
name := entry.Name()
if strings.HasPrefix(name, prefix) && strings.HasSuffix(name, ".tar.gz") {
return filepath.Join(baseDir, name), nil
}
}
return "", errors.New(fmt.Sprintf("no FusionXplay_%s_Accelerator*.tar.gz found in /home/models", modelType))
}
func handleModelArchive(modelType string, modelDir string) error {
filePath, err := findModelArchive(modelType)
if err != nil {
return err
}
fileOp := files.NewFileOp()
if err = fileOp.TarGzExtractPro(filePath, modelDir, ""); err != nil {
return err
}
if err = fileOp.ChmodR(path.Join(modelDir, "fusionxpark_accelerator"), 0755, false); err != nil {
return err
}
return nil
}
func getCommand(envStr string) string {
lines := strings.Split(envStr, "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if strings.HasPrefix(line, "COMMAND=") {
return strings.TrimPrefix(line, "COMMAND=")
}
}
return ""
}
+5 -171
View File
@@ -60,7 +60,6 @@ type IWebsiteService interface {
UpdateWebsite(req request.WebsiteUpdate) error
DeleteWebsite(req request.WebsiteDelete) error
GetWebsite(id uint) (response.WebsiteDTO, error)
BatchOpWebsite(req request.BatchWebsiteOp) error
CreateWebsiteDomain(create request.WebsiteDomainCreate) ([]model.WebsiteDomain, error)
GetWebsiteDomain(websiteId uint) ([]model.WebsiteDomain, error)
@@ -96,9 +95,6 @@ type IWebsiteService interface {
ClearProxyCache(req request.NginxCommonReq) error
DeleteProxy(req request.WebsiteProxyDel) (err error)
UpdateCors(req request.CorsConfigReq) error
GetCors(websiteID uint) (*request.CorsConfig, error)
GetAntiLeech(id uint) (*response.NginxAntiLeechRes, error)
UpdateAntiLeech(req request.NginxAntiLeechUpdate) (err error)
@@ -521,43 +517,6 @@ func (w WebsiteService) OpWebsite(req request.WebsiteOp) error {
return websiteRepo.Save(context.Background(), &website)
}
func (w WebsiteService) BatchOpWebsite(req request.BatchWebsiteOp) error {
websites, _ := websiteRepo.List(repo.WithByIDs(req.IDs))
opTask, err := task.NewTaskWithOps(i18n.GetMsgByKey("Status"), task.TaskBatch, task.TaskScopeWebsite, req.TaskID, 0)
if err != nil {
return err
}
opWebsiteTask := func(t *task.Task) error {
for _, web := range websites {
msg := fmt.Sprintf("%s %s", i18n.GetMsgByKey(req.Operate), web.PrimaryDomain)
switch req.Operate {
case constant.StopWeb, constant.StartWeb:
if err := opWebsite(&web, req.Operate); err != nil {
t.LogFailedWithErr(msg, err)
continue
}
_ = websiteRepo.Save(context.Background(), &web)
case "delete":
if err := w.DeleteWebsite(request.WebsiteDelete{
ID: web.ID,
}); err != nil {
t.LogFailedWithErr(msg, err)
continue
}
}
t.LogSuccess(msg)
}
return nil
}
opTask.AddSubTask("", opWebsiteTask, nil)
go func() {
_ = opTask.Execute()
}()
return nil
}
func (w WebsiteService) GetWebsiteOptions(req request.WebsiteOptionReq) ([]response.WebsiteOption, error) {
var options []repo.DBOption
if len(req.Types) > 0 {
@@ -644,36 +603,6 @@ func (w WebsiteService) DeleteWebsite(req request.WebsiteDelete) error {
return buserr.WithName("ErrParentWebsite", strings.Join(names, ","))
}
}
if website.Type == constant.Runtime && req.DeleteDB && website.DbID != 0 {
switch website.DbType {
case constant.AppMysql, constant.AppMariaDB:
mysqlDB, _ := mysqlRepo.Get(repo.WithByID(website.DbID))
if mysqlDB.ID > 0 {
deleteReq := dto.MysqlDBDelete{
ID: mysqlDB.ID,
Database: mysqlDB.MysqlName,
ForceDelete: req.ForceDelete,
}
if err = NewIMysqlService().Delete(context.TODO(), deleteReq); err != nil && !req.ForceDelete {
return err
}
}
case constant.AppPostgresql, constant.AppPostgres:
pgDB, _ := postgresqlRepo.Get(repo.WithByID(website.DbID))
if pgDB.ID > 0 {
deleteReq := dto.PostgresqlDBDelete{
ID: pgDB.ID,
ForceDelete: req.ForceDelete,
Database: pgDB.PostgresqlName,
}
if err = NewIPostgresqlService().Delete(context.TODO(), deleteReq); err != nil && !req.ForceDelete {
return err
}
}
}
}
if err = delNginxConfig(website, req.ForceDelete); err != nil {
return err
}
@@ -1684,7 +1613,7 @@ func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error)
switch req.Operate {
case "create":
config, err = parser.NewStringParser(string(nginx_conf.GetWebsiteFile("proxy.conf"))).Parse()
config, err = parser.NewStringParser(string(nginx_conf.Proxy)).Parse()
if err != nil {
return
}
@@ -1751,35 +1680,6 @@ func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error)
} else {
location.UpdateDirective("proxy_ssl_server_name", []string{"off"})
}
if req.Cors {
location.UpdateDirective("add_header", []string{"Access-Control-Allow-Origin", req.AllowOrigins, "always"})
if req.AllowMethods != "" {
location.UpdateDirective("add_header", []string{"Access-Control-Allow-Methods", req.AllowMethods, "always"})
} else {
location.RemoveDirective("add_header", []string{"Access-Control-Allow-Methods"})
}
if req.AllowHeaders != "" {
location.UpdateDirective("add_header", []string{"Access-Control-Allow-Headers", req.AllowHeaders, "always"})
} else {
location.RemoveDirective("add_header", []string{"Access-Control-Allow-Headers"})
}
if req.AllowCredentials {
location.UpdateDirective("add_header", []string{"Access-Control-Allow-Credentials", "true", "always"})
} else {
location.RemoveDirective("add_header", []string{"Access-Control-Allow-Credentials"})
}
if req.Preflight {
location.AddCorsOption()
} else {
location.RemoveDirective("if", []string{"(", "$request_method", "=", "'OPTIONS'", ")"})
}
} else {
location.RemoveDirective("add_header", []string{"Access-Control-Allow-Origin"})
location.RemoveDirective("add_header", []string{"Access-Control-Allow-Methods"})
location.RemoveDirective("add_header", []string{"Access-Control-Allow-Headers"})
location.RemoveDirective("add_header", []string{"Access-Control-Allow-Credentials"})
location.RemoveDirective("if", []string{"(", "$request_method", "=", "'OPTIONS'", ")"})
}
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
return buserr.WithErr("ErrUpdateBuWebsite", err)
}
@@ -1939,12 +1839,6 @@ func (w WebsiteService) GetProxies(id uint) (res []request.WebsiteProxyConfig, e
proxyConfig.ProxySSLName = directive.GetParameters()[0]
}
}
proxyConfig.Cors = location.Cors
proxyConfig.AllowCredentials = location.AllowCredentials
proxyConfig.AllowHeaders = location.AllowHeaders
proxyConfig.AllowOrigins = location.AllowOrigins
proxyConfig.AllowMethods = location.AllowMethods
proxyConfig.Preflight = location.Preflight
res = append(res, proxyConfig)
}
return
@@ -2021,65 +1915,6 @@ func (w WebsiteService) DeleteProxy(req request.WebsiteProxyDel) (err error) {
return updateNginxConfig(constant.NginxScopeServer, nil, &website)
}
func (w WebsiteService) UpdateCors(req request.CorsConfigReq) error {
website, err := websiteRepo.GetFirst(repo.WithByID(req.WebsiteID))
if err != nil {
return err
}
params := []dto.NginxParam{
{Name: "add_header", Params: []string{"Access-Control-Allow-Origin"}},
{Name: "add_header", Params: []string{"Access-Control-Allow-Methods"}},
{Name: "add_header", Params: []string{"Access-Control-Allow-Headers"}},
{Name: "add_header", Params: []string{"Access-Control-Allow-Credentials"}},
{Name: "if", Params: []string{"(", "$request_method", "=", "'OPTIONS'", ")"}},
}
if err := deleteNginxConfig(constant.NginxScopeServer, params, &website); err != nil {
return err
}
if req.Cors {
return updateWebsiteConfig(website, func(server *components.Server) error {
server.UpdateDirective("add_header", []string{"Access-Control-Allow-Origin", req.AllowOrigins, "always"})
if req.AllowMethods != "" {
server.UpdateDirective("add_header", []string{"Access-Control-Allow-Methods", req.AllowMethods, "always"})
}
if req.AllowHeaders != "" {
server.UpdateDirective("add_header", []string{"Access-Control-Allow-Headers", req.AllowHeaders, "always"})
}
if req.AllowCredentials {
server.UpdateDirective("add_header", []string{"Access-Control-Allow-Credentials", "true", "always"})
}
if req.Preflight {
server.AddCorsOption()
}
return nil
})
}
return nil
}
func (w WebsiteService) GetCors(websiteID uint) (*request.CorsConfig, error) {
website, err := websiteRepo.GetFirst(repo.WithByID(websiteID))
if err != nil {
return nil, err
}
server, err := getServer(website)
if err != nil {
return nil, err
}
if server == nil {
return nil, nil
}
cors := &request.CorsConfig{
Cors: server.Cors,
AllowOrigins: server.AllowOrigins,
AllowMethods: server.AllowMethods,
AllowHeaders: server.AllowHeaders,
AllowCredentials: server.AllowCredentials,
Preflight: server.Preflight,
}
return cors, nil
}
func (w WebsiteService) GetAuthBasics(req request.NginxAuthReq) (res response.NginxAuthRes, err error) {
var (
website model.Website
@@ -3201,10 +3036,6 @@ func (w WebsiteService) UpdateLoadBalance(req request.WebsiteLBUpdate) error {
if !fileOp.Stat(filePath) {
return nil
}
oldContent, err := fileOp.GetContent(filePath)
if err != nil {
return err
}
parser, err := parser.NewParser(filePath)
if err != nil {
return err
@@ -3256,7 +3087,10 @@ func (w WebsiteService) UpdateLoadBalance(req request.WebsiteLBUpdate) error {
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
return buserr.WithErr("ErrUpdateBuWebsite", err)
}
return nginxCheckAndReload(string(oldContent), filePath, nginxInstall.ContainerName)
if err = opNginx(nginxInstall.ContainerName, constant.NginxReload); err != nil {
return err
}
return nil
}
func (w WebsiteService) DeleteLoadBalance(req request.WebsiteLBDelete) error {
-4
View File
@@ -626,13 +626,9 @@ func (w WebsiteSSLService) Upload(req request.WebsiteSSLUpload) error {
} else {
websiteSSL.Pem = string(content)
}
websiteSSL.CertPath = req.CertificatePath
websiteSSL.PrivateKeyPath = req.PrivateKeyPath
} else {
websiteSSL.PrivateKey = req.PrivateKey
websiteSSL.Pem = req.Certificate
websiteSSL.CertPath = ""
websiteSSL.PrivateKeyPath = ""
}
privateKeyCertBlock, _ := pem.Decode([]byte(websiteSSL.PrivateKey))
+3 -56
View File
@@ -223,7 +223,7 @@ func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, a
server.UpdateDirective("error_page", []string{"404", "/404.html"})
if runtime.Resource == constant.ResourceLocal {
server.UpdateRoot(rootIndex)
localPath := path.Join(rootIndex, "index.php")
localPath := path.Join(GetSitePath(*website, SiteIndexDir), "index.php")
server.UpdatePHPProxy([]string{website.Proxy}, localPath)
} else {
server.UpdateRoot(rootIndex)
@@ -249,7 +249,7 @@ func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, a
if parentRuntime.Type == constant.RuntimePHP {
if parentRuntime.Resource == constant.ResourceLocal {
server.UpdateRoot(rootIndex)
localPath := path.Join(rootIndex, "index.php")
localPath := path.Join(nginxInstall.GetPath(), rootIndex, "index.php")
server.UpdatePHPProxy([]string{website.Proxy}, localPath)
} else {
server.UpdateRoot(rootIndex)
@@ -959,7 +959,7 @@ func opWebsite(website *model.Website, operate string) error {
}
if runtime.Type == constant.RuntimePHP {
if website.ProxyType == constant.RuntimeProxyUnix || website.ProxyType == constant.RuntimeProxyTcp {
localPath = path.Join(rootIndex, "index.php")
localPath = path.Join(GetSitePath(*website, SiteIndexDir), "index.php")
}
server.UpdatePHPProxy([]string{website.Proxy}, localPath)
} else {
@@ -1303,7 +1303,6 @@ const (
SiteRootAuthBasicPath = "SiteRootAuthBasicPath"
SitePathAuthBasicDir = "SitePathAuthBasicDir"
SiteUpstreamDir = "SiteUpstreamDir"
SiteCorsPath = "SiteCorsPath"
)
func GetSitePath(website model.Website, confType string) string {
@@ -1334,8 +1333,6 @@ func GetSitePath(website model.Website, confType string) string {
return path.Join(GteSiteDir(website.Alias), "path_auth")
case SiteUpstreamDir:
return path.Join(GteSiteDir(website.Alias), "upstream")
case SiteCorsPath:
return path.Join(GteSiteDir(website.Alias), "cors", "cors.conf")
}
return ""
}
@@ -1484,53 +1481,3 @@ func ParseDomain(domain string) (*model.WebsiteDomain, error) {
Port: port,
}, nil
}
func updateWebsiteConfig(website model.Website, updateFunc func(server *components.Server) error) error {
configPath := GetSitePath(website, SiteConf)
nginxContent, err := files.NewFileOp().GetContent(configPath)
if err != nil {
return err
}
config, err := parser.NewStringParser(string(nginxContent)).Parse()
if err != nil {
return err
}
config.FilePath = configPath
servers := config.FindServers()
if len(servers) == 0 {
return errors.New("nginx config is not valid")
}
server := servers[0]
if err := updateFunc(server); err != nil {
return err
}
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
return err
}
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
if err != nil {
return err
}
return nginxCheckAndReload(string(nginxContent), configPath, nginxInstall.ContainerName)
}
func getServer(website model.Website) (*components.Server, error) {
configPath := GetSitePath(website, SiteConf)
nginxContent, err := files.NewFileOp().GetContent(configPath)
if err != nil {
return nil, err
}
config, err := parser.NewStringParser(string(nginxContent)).Parse()
if err != nil {
return nil, err
}
servers := config.FindServers()
if len(servers) == 0 {
return nil, errors.New("nginx config is not valid")
}
server := servers[0]
return server, nil
}
+14 -24
View File
@@ -25,8 +25,6 @@ type ActionFunc func(*Task) error
type RollbackFunc func(*Task)
type Task struct {
TaskCtx context.Context
Name string
TaskID string
Logger *log.Logger
@@ -71,10 +69,6 @@ const (
TaskHandle = "TaskHandle"
TaskScan = "TaskScan"
TaskExec = "TaskExec"
TaskBatch = "TaskBatch"
TaskProtect = "TaskProtect"
TaskConvert = "TaskConvert"
TaskSwapSet = "TaskSwapSet"
)
const (
@@ -91,11 +85,8 @@ const (
TaskScopeContainer = "Container"
TaskScopeCompose = "Compose"
TaskScopeImage = "Image"
TaskScopeBackup = "Backup"
TaskScopeRuntimeExtension = "RuntimeExtension"
TaskScopeCustomAppstore = "CustomAppstore"
TaskScopeTamper = "Tamper"
TaskScopeFileConvert = "Convert"
)
func GetTaskName(resourceName, operate, scope string) string {
@@ -152,9 +143,7 @@ func NewTask(name, operate, taskScope, taskID string, resourceID uint) (*Task, e
Operate: operate,
}
taskRepo := repo.NewITaskRepo()
ctx, cancle := context.WithCancel(context.Background())
global.TaskCtxMap[taskID] = cancle
task := &Task{TaskCtx: ctx, Name: name, logFile: file, Logger: logger, taskRepo: taskRepo, Task: taskModel, Writer: writer}
task := &Task{Name: name, logFile: file, Logger: logger, taskRepo: taskRepo, Task: taskModel, Writer: writer}
return task, nil
}
@@ -162,9 +151,7 @@ func ReNewTaskWithOps(resourceName, operate, scope, taskID string, resourceID ui
return ReNewTask(GetTaskName(resourceName, operate, scope), operate, scope, taskID, resourceID)
}
func ReNewTask(name, operate, taskScope, taskID string, resourceID uint) (*Task, error) {
taskRepo := repo.NewITaskRepo()
taskItem, _ := taskRepo.GetFirst(taskRepo.WithByID(taskID))
if taskItem.ID == "" {
if taskID == "" {
return NewTask(name, operate, taskScope, taskID, resourceID)
}
logDir := path.Join(global.Dir.TaskDir, taskScope)
@@ -180,10 +167,17 @@ func ReNewTask(name, operate, taskScope, taskID string, resourceID uint) (*Task,
}
writer := bufio.NewWriter(file)
logger := log.New(file, "", log.LstdFlags)
logger.Print("\n --------------------------------------------------- \n")
taskItem.Status = constant.StatusExecuting
task := &Task{Name: name, logFile: file, Logger: logger, taskRepo: taskRepo, Task: &taskItem, Writer: writer}
task.updateTask(&taskItem)
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
}
@@ -213,7 +207,6 @@ func (t *Task) AddSubTaskWithIgnoreErr(name string, action ActionFunc) {
}
func (s *SubTask) Execute() error {
defer delete(global.TaskCtxMap, s.RootTask.TaskID)
subTaskName := s.Name
if s.Name == "" {
subTaskName = i18n.GetMsgByKey("SubTask")
@@ -238,9 +231,6 @@ func (s *SubTask) Execute() error {
case err = <-done:
if err != nil {
s.RootTask.Log(i18n.GetWithNameAndErr("SubTaskFailed", subTaskName, err))
if err.Error() == i18n.GetMsgByKey("ErrShutDown") {
return err
}
} else {
s.RootTask.Log(i18n.GetWithName("SubTaskSuccess", subTaskName))
return nil
@@ -327,7 +317,7 @@ func (t *Task) LogFailedWithErr(msg string, err error) {
}
func (t *Task) LogSuccess(msg string) {
t.Logger.Println(msg + " " + i18n.GetMsgByKey("Success"))
t.Logger.Println(msg + i18n.GetMsgByKey("Success"))
}
func (t *Task) LogSuccessF(format string, v ...any) {
t.Logger.Println(fmt.Sprintf(format, v...) + i18n.GetMsgByKey("Success"))
-30
View File
@@ -1,30 +0,0 @@
services:
tensorrt-llm:
image: ${IMAGE}:${VERSION}
container_name: ${CONTAINER_NAME}
restart: always
runtime: nvidia
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
networks:
- 1panel-network
volumes:
- ${MODEL_PATH}:${MODEL_PATH}
ipc: host
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65535
hard: 65535
stack: 67108864
command: ${COMMAND}
networks:
1panel-network:
external: true
@@ -10,12 +10,4 @@ additionalProperties:
limit: #应用安装数量限制,0 代表无限制
website: #官网地址
github: #github 地址
description:
en:
zh: #应用中文描述,不要超过30个字
zh-Hant:
ja:
ms:
pt-br:
ru:
ko:
document: #文档地址

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

-1
View File
@@ -2,7 +2,6 @@ base:
install_dir: /opt
mode: dev
is_demo: false
is_offline: false
remote_url:
app_repo: https://apps-assets.fit2cloud.com
@@ -1,4 +1,4 @@
package ai
package mcp
import (
_ "embed"
@@ -6,6 +6,3 @@ import (
//go:embed compose.yml
var DefaultMcpCompose []byte
//go:embed llm-compose.yml
var DefaultTensorrtLLMCompose []byte
+14 -58
View File
@@ -1,25 +1,4 @@
[
{
"name": "amqp",
"check": "amqp",
"file": "amqp.so",
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
"installed": false
},
{
"name": "apcu",
"check": "apcu",
"file": "apcu.so",
"versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
"installed": false
},
{
"name": "bcmath",
"check": "bcmath",
"file": "bcmath.so",
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
"installed": false
},
{
"name": "ionCube",
"check": "ionCube Loader",
@@ -62,7 +41,13 @@
"versions": ["70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
"installed": false
},
{
"name": "apcu",
"check": "apcu",
"file": "apcu.so",
"versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
"installed": false
},
{
"name": "imagick",
"check": "imagick",
@@ -378,7 +363,13 @@
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
"installed": false
},
{
"name": "bcmath",
"check": "bcmath",
"file": "bcmath.so",
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
"installed": false
},
{
"name": "pcntl",
"check": "pcntl",
@@ -392,40 +383,5 @@
"file": "sodium.so",
"versions": ["70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
"installed": false
},
{
"name": "gettext",
"check": "gettext",
"file": "gettext.so",
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
"installed": false
},
{
"name": "soap",
"check": "soap",
"file": "soap.so",
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
"installed": false
},
{
"name": "sysvsem",
"check": "sysvsem",
"file": "sysvsem.so",
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
"installed": false
},
{
"name": "sockets",
"check": "sockets",
"file": "sockets.so",
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
"installed": false
},
{
"name": "xmlrpc",
"check": "xmlrpc",
"file": "xmlrpc.so",
"versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83","84"],
"installed": false
}
]
@@ -10,7 +10,7 @@ server {
location ~ ^/(\.user.ini|\.htaccess|\.git|\.env|\.svn|\.project|LICENSE|README.md){
return 404;
}
location ^~ /.well-known/acme-challenge {
location ^~ /.well-known{
allow all;
root /usr/share/nginx/html;
}
-2
View File
@@ -17,8 +17,6 @@ const (
TypeImagePush = "image-push"
TypeImageBuild = "image-build"
TypeComposeCreate = "compose-create"
InterruptedMsg = "the task was interrupted due to the restart of the 1panel service"
)
const (
+12 -16
View File
@@ -14,7 +14,6 @@ type Base struct {
Mode string `mapstructure:"mode"` // xpack [ Enable / Disable ]
IsDemo bool `mapstructure:"is_demo"`
InstallDir string `mapstructure:"install_dir"`
IsOffLine bool `mapstructure:"is_offline"`
}
type RemoteURL struct {
@@ -32,21 +31,18 @@ type SystemDir struct {
TmpDir string
LocalBackupDir string
AppDir string
ResourceDir string
AppResourceDir string
AppInstallDir string
LocalAppResourceDir string
LocalAppInstallDir string
RemoteAppResourceDir string
CustomAppResourceDir string
OfflineAppResourceDir string
RuntimeDir string
RecycleBinDir string
SSLLogDir string
McpDir string
ConvertLogDir string
TensorRTLLMDir string
AppDir string
ResourceDir string
AppResourceDir string
AppInstallDir string
LocalAppResourceDir string
LocalAppInstallDir string
RemoteAppResourceDir string
CustomAppResourceDir string
RuntimeDir string
RecycleBinDir string
SSLLogDir string
McpDir string
}
type LogConfig struct {
-4
View File
@@ -1,8 +1,6 @@
package global
import (
"context"
badger_db "github.com/1Panel-dev/1Panel/agent/init/cache/db"
"github.com/go-playground/validator/v10"
"github.com/nicksnyder/go-i18n/v2/i18n"
@@ -36,6 +34,4 @@ var (
AlertBaseJobID cron.EntryID
AlertResourceJobID cron.EntryID
TaskCtxMap = make(map[string]context.CancelFunc)
)
+1 -3
View File
@@ -177,12 +177,10 @@ require (
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/goacmedns v0.2.0 // indirect
github.com/nrdcg/mailinabox v0.2.0 // indirect
github.com/nrdcg/namesilo v0.2.1 // indirect
github.com/nwaples/rardecode/v2 v2.2.0 // indirect
github.com/nwaples/rardecode/v2 v2.0.0-beta.2 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/ovh/go-ovh v1.9.0 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pierrec/lz4/v4 v4.1.15 // indirect
-10
View File
@@ -532,8 +532,6 @@ github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY=
github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jarcoal/httpmock v1.3.0 h1:2RJ8GP0IIaWwcC9Fp2BmVi8Kog3v2Hn7VXM3fTd+nuc=
github.com/jarcoal/httpmock v1.3.0/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg=
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
@@ -628,8 +626,6 @@ github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lL
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/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/maxatome/go-testdeep v1.12.0 h1:Ql7Go8Tg0C1D/uMMX59LAoYK7LffeJQ6X2T04nTH68g=
github.com/maxatome/go-testdeep v1.12.0/go.mod h1:lPZc/HAcJMP92l7yI6TRz1aZN5URwUBUAfUNvrclaNM=
github.com/mholt/archiver/v4 v4.0.0-alpha.8 h1:tRGQuDVPh66WCOelqe6LIGh0gwmfwxUrSSDunscGsRM=
github.com/mholt/archiver/v4 v4.0.0-alpha.8/go.mod h1:5f7FUYGXdJWUjESffJaYR4R60VhnHxb2X3T1teMyv5A=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
@@ -714,16 +710,12 @@ github.com/nrdcg/dnspod-go v0.4.0 h1:c/jn1mLZNKF3/osJ6mz3QPxTudvPArXTjpkmYj0uK6U
github.com/nrdcg/dnspod-go v0.4.0/go.mod h1:vZSoFSFeQVm2gWLMkyX61LZ8HI3BaqtHZWgPTGKr6KQ=
github.com/nrdcg/freemyip v0.3.0 h1:0D2rXgvLwe2RRaVIjyUcQ4S26+cIS2iFwnhzDsEuuwc=
github.com/nrdcg/freemyip v0.3.0/go.mod h1:c1PscDvA0ukBF0dwelU/IwOakNKnVxetpAQ863RMJoM=
github.com/nrdcg/goacmedns v0.2.0 h1:ADMbThobzEMnr6kg2ohs4KGa3LFqmgiBA22/6jUWJR0=
github.com/nrdcg/goacmedns v0.2.0/go.mod h1:T5o6+xvSLrQpugmwHvrSNkzWht0UGAwj2ACBMhh73Cg=
github.com/nrdcg/mailinabox v0.2.0 h1:IKq8mfKiVwNW2hQii/ng1dJ4yYMMv3HAP3fMFIq2CFk=
github.com/nrdcg/mailinabox v0.2.0/go.mod h1:0yxqeYOiGyxAu7Sb94eMxHPIOsPYXAjTeA9ZhePhGnc=
github.com/nrdcg/namesilo v0.2.1 h1:kLjCjsufdW/IlC+iSfAqj0iQGgKjlbUUeDJio5Y6eMg=
github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw=
github.com/nwaples/rardecode/v2 v2.0.0-beta.2 h1:e3mzJFJs4k83GXBEiTaQ5HgSc/kOK8q0rDaRO0MPaOk=
github.com/nwaples/rardecode/v2 v2.0.0-beta.2/go.mod h1:yntwv/HfMc/Hbvtq9I19D1n58te3h6KsqCf3GxyfBGY=
github.com/nwaples/rardecode/v2 v2.2.0 h1:4ufPGHiNe1rYJxYfehALLjup4Ls3ck42CWwjKiOqu0A=
github.com/nwaples/rardecode/v2 v2.2.0/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
@@ -750,8 +742,6 @@ github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYr
github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE=
github.com/oschwald/maxminddb-golang v1.13.1 h1:G3wwjdN9JmIK2o/ermkHM+98oX5fS+k5MbwsmL4MRQE=
github.com/oschwald/maxminddb-golang v1.13.1/go.mod h1:K4pgV9N/GcK694KSTmVSDTODk4IsCNThNdTmnaBZ/F8=
github.com/ovh/go-ovh v1.9.0 h1:6K8VoL3BYjVV3In9tPJUdT7qMx9h0GExN9EXx1r2kKE=
github.com/ovh/go-ovh v1.9.0/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
-1
View File
@@ -134,7 +134,6 @@ func Init() {
_, _ = bundle.LoadMessageFileFS(fs, "lang/ms.yaml")
_, _ = bundle.LoadMessageFileFS(fs, "lang/ko.yaml")
_, _ = bundle.LoadMessageFileFS(fs, "lang/tr.yaml")
_, _ = bundle.LoadMessageFileFS(fs, "lang/es-ES.yaml")
lang := GetLanguageFromDB()
global.I18n = i18n.NewLocalizer(bundle, lang)
}
-22
View File
@@ -14,7 +14,6 @@ ErrApiConfigKeyInvalid: 'API interface key error: {{ .detail }}'
ErrApiConfigIPInvalid: 'The IP used to call the API interface is not in the whitelist: {{ .detail }}'
ErrApiConfigDisable: 'This interface prohibits the use of API interface calls: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'API interface timestamp error: {{ .detail }}'
ErrShutDown: "Command manually terminated!"
ErrMinQuickJump: "Please set at least one quick jump entry!"
ErrMaxQuickJump: "You can set up to four quick jump entries!"
@@ -95,7 +94,6 @@ ErrCustomRuntimes: 'There is an installed runtime environment, please delete it
ErrAppVersionDeprecated: "The {{ .name }} application is not compatible with the current 1Panel version, skipped"
ErrDockerFailed: "The state of Docker is abnormal, please check the service status"
ErrDockerComposeCmdNotFound: "The Docker Compose command does not exist, please install this command on the host machine first"
UseExistImage: 'Failed to pull image, using existing image'
#ssh
ExportIP: "Login IP"
@@ -124,7 +122,6 @@ ErrLogFileToLarge: "The log file exceeds 500MB and cannot be opened"
FileDropFailed: "Failed to clean up file {{ .name }}: {{ .err }}"
FileDropSuccess: "Successfully cleaned up file {{ .name }}, cleaned {{ .count }} files, freed {{ .size }} disk space"
FileDropSum: "File cleanup completed successfully, total {{ .count }} files cleaned, total {{ .size }} disk space freed"
ErrBadDecrypt: "Compressed package decryption password error, decompression failed, please check and try again!"
#website
ErrAliasIsExist: 'Alias already exists'
@@ -143,10 +140,6 @@ ErrSSLValid: 'Certificate file is abnormal, please check the certificate status!
ErrWebsiteDir: "Please select a directory within the website directory."
ErrComposerFileNotFound: "composer.json file does not exist"
ErrRuntimeNoPort: "The runtime environment is not set with a port, please edit the runtime environment first."
Status: 'Status'
start: 'Start'
stop: 'Stop'
delete: 'Delete'
#ssl
ErrSSLCannotDelete: 'The {{ .name }} certificate is being used by a website and cannot be deleted'
@@ -248,18 +241,6 @@ NoSuchResource: "No backup content found in the database, skipping..."
ErrNotExistUser: 'The current user does not exist, please modify and try again!'
ErrBanAction: 'Setting failed. The current {{ .name }} service is unavailable. Please check and try again!'
ErrClamdscanNotFound: 'The clamdscan command was not detected, please refer to the documentation to install it!'
TaskSwapSet: "Set Swap"
SetSwap: "Set Swap {{ .path }} - {{ .size }}"
CreateSwap: "Create Swap File"
FormatSwap: "Format Swap File"
EnableSwap: "Enable Swap"
#tamper
CleanTamperSetting: "Clean up historical protection settings"
SetTamperWithRules: "Start directory protection according to rules"
ProtectDir: "Protect directory {{ .name }}"
IgnoreFile: "Protect file {{ .name }}"
TamperSetSuccessful: "Protection settings completed, start monitoring the following directories:"
#waf
ErrScope: 'Modifying this configuration is not supported'
@@ -332,7 +313,6 @@ TaskDelete: 'Delete'
TaskUpgrade: 'Upgrade'
TaskUpdate: 'Update'
TaskRestart: 'Restart'
TaskProtect: "Protect"
TaskBackup: 'Backup'
TaskRecover: 'Recover'
TaskRollback: 'Rollback'
@@ -373,8 +353,6 @@ RuntimeExtension: 'Runtime Environment Extension'
TaskIsExecuting: 'Task is running'
CustomAppstore: 'Custom application warehouse'
TaskExec: 'Execute'
TaskBatch: "Batch Operation"
FileConvert: 'File Conversion'
# task - clam
Clamscan: "Scan {{ .name }}"
-509
View File
@@ -1,509 +0,0 @@
ErrInvalidParams: 'Error en los parámetros de la solicitud: {{ .detail }}'
ErrTokenParse: 'Error al generar el token: {{ .detail }}'
ErrInitialPassword: 'La contraseña original es incorrecta'
ErrInternalServer: 'Error interno del servidor: {{ .detail }}'
ErrRecordExist: 'El registro ya existe'
ErrRecordNotFound: 'Registro no encontrado'
ErrStructTransform: 'Error de conversión de tipo: {{ .err }}'
ErrNotLogin: 'Usuario no ha iniciado sesión: {{ .detail }}'
ErrPasswordExpired: 'La contraseña actual ha expirado: {{ .detail }}'
ErrNotSupportType: 'El sistema no admite el tipo actual: {{ .name }}'
ErrProxy: 'Error en la solicitud, por favor revise el estado del nodo: {{ .detail }}'
ErrApiConfigStatusInvalid: 'Se prohíbe el acceso a la interfaz API: {{ .detail }}'
ErrApiConfigKeyInvalid: 'Error en la clave de la interfaz API: {{ .detail }}'
ErrApiConfigIPInvalid: 'La IP usada para llamar a la API no está en la lista blanca: {{ .detail }}'
ErrApiConfigDisable: 'Esta interfaz prohíbe el uso de llamadas a la API: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'Error en la marca de tiempo de la interfaz API: {{ .detail }}'
ErrShutDown: "¡Comando terminado manualmente!"
ErrMinQuickJump: "¡Por favor configure al menos una entrada de acceso rápido!"
ErrMaxQuickJump: "¡Puede configurar hasta cuatro entradas de acceso rápido!"
#común
ErrUsernameIsExist: 'El nombre de usuario ya existe'
ErrNameIsExist: 'El nombre ya existe'
ErrDemoEnvironment: '¡Servidor de demostración, esta operación está prohibida!'
ErrCmdTimeout: '¡Tiempo de espera excedido en la ejecución del comando!'
ErrCmdIllegal: 'Hay caracteres ilegales en el comando, ¡modifíquelo e intente de nuevo!'
ErrPortExist: 'El puerto {{ .port }} ya está ocupado por {{ .type }} [{{ .name }}]'
TYPE_APP: 'Aplicación'
TYPE_RUNTIME: 'Entorno de ejecución'
TYPE_DOMAIN: 'Nombre de dominio'
ErrTypePort: 'El formato del puerto {{ .name }} es incorrecto'
ErrTypePortRange: 'El rango de puertos debe estar entre 1-65535'
Success: 'Éxito'
Failed: 'Error'
SystemRestart: 'La tarea fue interrumpida debido a un reinicio del sistema'
ErrGroupIsDefault: 'Grupo predeterminado, no se puede eliminar'
ErrGroupIsInWebsiteUse: 'El grupo está siendo usado por otro sitio web y no se puede eliminar.'
#backup
ErrBackupInUsed: 'La cuenta de respaldo está siendo utilizada en una tarea programada y no se puede eliminar.'
ErrBackupCheck: 'Error al probar la conexión de la cuenta de respaldo {{ .err }}'
ErrBackupLocalDelete: 'No se admite aún la eliminación de la cuenta de respaldo del servidor local'
ErrBackupLocalCreate: 'No se admite aún la creación de cuentas de respaldo del servidor local'
Localhost: "Máquina local"
#app
ErrPortInUsed: '¡El puerto {{ .detail }} ya está ocupado!'
ErrAppLimit: 'El número de aplicaciones instaladas ha superado el límite'
ErrNotInstall: 'Aplicación no instalada'
ErrPortInOtherApp: '¡El puerto {{ .port }} ya está ocupado por la aplicación {{ .apps }}!'
ErrDbUserNotValid: '¡Base de datos existente, usuario y contraseña no coinciden!'
ErrUpdateBuWebsite: 'La aplicación se actualizó correctamente, pero falló la modificación del archivo de configuración del sitio web. ¡Por favor revise la configuración!'
Err1PanelNetworkFailed: '¡Fallo la creación de la red por defecto del contenedor! {{ .detail }}'
ErrFileParse: '¡Fallo al analizar el archivo docker-compose de la aplicación!'
ErrInstallDirNotFound: 'El directorio de instalación no existe. Si desea desinstalar, seleccione Desinstalación forzada'
AppStoreIsUpToDate: 'La tienda de aplicaciones ya está en la última versión'
LocalAppVersionNull: '¡La aplicación {{ .name }} no está sincronizada a la versión! No se puede agregar a la lista de aplicaciones'
LocalAppVersionErr: '¡La sincronización de la versión {{ .version }} de {{ .name }} falló! {{ .err }}'
ErrFileNotFound: 'El archivo {{ .name }} no existe'
ErrFileParseApp: '¡El archivo {{ .name }} falló al analizarse! {{ .err }}'
ErrAppDirNull: 'La carpeta de la versión no existe'
LocalAppErr: '¡La sincronización de la aplicación {{ .name }} falló! {{ .err }}'
ErrContainerName: 'El nombre del contenedor ya existe'
ErrCreateHttpClient: 'Fallo al crear la solicitud {{ .err }}'
ErrHttpReqTimeOut: 'La solicitud superó el tiempo de espera {{ .err }}'
ErrHttpReqFailed: 'La solicitud falló {{ .err }}'
ErrNoSuchHost: 'No se pudo encontrar el servidor solicitado {{ .err }}'
ErrHttpReqNotFound: 'No se pudo encontrar el recurso solicitado {{ .err }}'
ErrContainerNotFound: 'El contenedor {{ .name }} no existe'
ErrContainerMsg: 'El contenedor {{ .name }} presenta anomalías. Revise el log en la página de contenedores para más detalles'
ErrAppBackup: 'Falló el respaldo de la aplicación {{ .name }} {{ .err }}'
ErrVersionTooLow: 'La versión actual de 1Panel es demasiado baja para actualizar la tienda de aplicaciones. Actualice primero.'
ErrAppNameExist: 'El nombre de la aplicación ya existe'
AppStoreIsSyncing: 'La tienda de aplicaciones está sincronizando, inténtelo más tarde'
ErrGetCompose: '¡Fallo al obtener el archivo docker-compose.yml! {{ .detail }}'
ErrAppWarn: 'Estado anómalo, revise el log'
ErrAppParamKey: 'El campo de parámetro {{ .name }} es anómalo'
ErrAppUpgrade: 'La actualización de la aplicación {{ .name }} falló {{ .err }}'
AppRecover: 'Revertir la aplicación {{ .name }}'
PullImageStart: 'Iniciar descarga de la imagen {{ .name }}'
PullImageSuccess: 'Descarga de imagen exitosa'
AppStoreIsLastVersion: 'La tienda de aplicaciones ya está en la última versión'
AppStoreSyncSuccess: 'Sincronización de la tienda de aplicaciones exitosa'
SyncAppDetail: 'Sincronizar configuración de la aplicación'
AppVersionNotMatch: 'La aplicación {{ .name }} requiere una versión superior de 1Panel, se omite la sincronización'
MoveSiteDir: 'La actualización actual requiere migrar el directorio del sitio web OpenResty'
MoveSiteDirSuccess: 'Migración del directorio del sitio exitosa'
DeleteRuntimePHP: 'Eliminar entorno de ejecución PHP'
CustomAppStoreFileValid: 'Los paquetes de la tienda de aplicaciones deben estar en formato .tar.gz'
PullImageTimeout: 'Tiempo de espera al descargar la imagen, intente aumentar la aceleración o use otra'
ErrAppIsDown: 'El estado de la aplicación {{ .name }} es anómalo, revise'
ErrCustomApps: 'Hay una aplicación instalada, desinstálela primero'
ErrCustomRuntimes: 'Hay un entorno de ejecución instalado, elimínelo primero'
ErrAppVersionDeprecated: "La aplicación {{ .name }} no es compatible con la versión actual de 1Panel, omitida"
ErrDockerFailed: "El estado de Docker es anómalo, revise el servicio"
ErrDockerComposeCmdNotFound: "El comando Docker Compose no existe, por favor instálelo primero en el host"
UseExistImage: 'Error al extraer la imagen, usando imagen existente'
#ssh
ExportIP: "IP de inicio de sesión"
ExportArea: "Ubicación"
ExportPort: "Puerto"
ExportAuthMode: "Método de inicio de sesión"
ExportUser: "Usuario"
ExportStatus: "Estado de inicio de sesión"
ExportDate: "Fecha y hora"
#file
ErrFileCanNotRead: 'Este archivo no soporta vista previa'
ErrFileToLarge: 'El archivo es mayor a 10M y no puede abrirse'
ErrPathNotFound: 'El directorio no existe'
ErrMovePathFailed: '¡La ruta de destino no puede contener la ruta original!'
ErrLinkPathNotFound: '¡La ruta de destino no existe!'
ErrFileIsExist: '¡El archivo o carpeta ya existe!'
ErrFileUpload: '{{ .name }} falló al subir archivo {{ .detail }}'
ErrFileDownloadDir: 'No se admite la descarga de carpetas'
ErrCmdNotFound: 'El comando {{ .name }} no existe, instálelo primero en el host'
ErrSourcePathNotFound: 'El directorio fuente no existe'
ErrFavoriteExist: 'Esta ruta ya ha sido marcada como favorita'
ErrInvalidChar: 'No se permiten caracteres ilegales'
ErrPathNotDelete: 'No se puede eliminar el directorio seleccionado'
FileDropFailed: "Error al limpiar el archivo {{ .name }}: {{ .err }}"
FileDropSuccess: "Archivo {{ .name }} limpiado correctamente, {{ .count }} archivos eliminados, {{ .size }} de espacio liberado"
FileDropSum: "Limpieza de archivos completada, total {{ .count }} archivos eliminados, {{ .size }} de espacio liberado"
ErrBadDecrypt: "Error de contraseña de descifrado del paquete comprimido, descompresión fallida, ¡compruebe e inténtelo de nuevo!"
#website
ErrAliasIsExist: 'El alias ya existe'
ErrBackupMatch: 'El archivo de respaldo no coincide con parte de los datos actuales del sitio web {{ .detail }}'
ErrBackupExist: 'Parte de los datos fuente del respaldo no existe {{ .detail }}'
ErrPHPResource: '¡El entorno local no soporta cambio!'
ErrPathPermission: 'Se detectó una carpeta con permisos distintos a 1000:1000 en el directorio index, lo cual puede causar errores de acceso denegado. Haga clic en Guardar arriba'
ErrDomainIsUsed: 'El dominio ya está en uso por el sitio web [{{ .name }}]'
ErrDomainFormat: 'El formato del dominio {{ .name }} es incorrecto'
ErrDefaultAlias: 'default es un código reservado, use otro'
ErrParentWebsite: 'Primero debe eliminar el sub-sitio {{ .name }}'
ErrBuildDirNotFound: 'El directorio de compilación no existe'
ErrImageNotExist: 'La imagen del entorno {{ .name }} no existe, edítela de nuevo'
ErrProxyIsUsed: "El balanceo de carga ya está usado por un proxy reverso, no se puede eliminar"
ErrSSLValid: 'Archivo de certificado anómalo, ¡revise el estado del certificado!'
ErrWebsiteDir: "Por favor seleccione un directorio dentro del directorio del sitio web"
ErrComposerFileNotFound: "El archivo composer.json no existe"
ErrRuntimeNoPort: "El entorno de ejecución no tiene configurado un puerto, edítelo primero"
Status: 'Estado'
start: 'Iniciar'
stop: 'Detener'
delete: 'Eliminar'
#ssl
ErrSSLCannotDelete: 'El certificado {{ .name }} está siendo utilizado por un sitio web y no puede eliminarse'
ErrAccountCannotDelete: 'La cuenta está asociada a un certificado y no puede eliminarse'
ErrSSLApply: 'Renovación del certificado exitosa, recarga de openresty fallida, ¡revise la configuración!'
ErrEmailIsExist: 'El correo ya existe'
ErrSSLKeyNotFound: 'El archivo de clave privada no existe'
ErrSSLCertificateNotFound: 'El archivo de certificado no existe'
ErrSSLKeyFormat: 'Error en la verificación del archivo de clave privada'
ErrSSLCertificateFormat: 'Formato de certificado incorrecto, use formato pem'
ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid o EabHmacKey no pueden estar en blanco'
ErrOpenrestyNotFound: 'El modo Http requiere tener Openresty instalado primero'
ApplySSLStart: 'Iniciando solicitud de certificado, dominio [{{ .domain }}] método de solicitud [{{ .type }}]'
dnsAccount: 'DNS Automático'
dnsManual: 'DNS Manual'
http: 'HTTP'
ApplySSLFailed: 'Solicitud de certificado para [{{ .domain }}] fallida, {{ .detail }}'
ApplySSLSuccess: '¡Solicitud de certificado para [{{ .domain }}] exitosa!'
DNSAccountName: 'Cuenta DNS [{{ .name }}] proveedor [{{ .type }}]'
PushDirLog: 'Certificado empujado al directorio [{{ .path }}] {{ .status }}'
ErrDeleteWithPanelSSL: 'La configuración SSL del panel utiliza este certificado y no puede eliminarse'
ErrDefaultCA: 'La autoridad por defecto no puede eliminarse'
ApplyWebSiteSSLLog: 'Iniciando renovación del certificado del sitio web {{ .name }}'
ErrUpdateWebsiteSSL: 'Actualización de certificado del sitio web {{ .name }} falló: {{ .err }}'
ApplyWebSiteSSLSuccess: 'Certificado del sitio web actualizado exitosamente'
ErrExecShell: 'Ejecución del script fallida {{ .err }}'
ExecShellStart: 'Iniciando ejecución de script'
ExecShellSuccess: 'Ejecución de script exitosa'
StartUpdateSystemSSL: 'Iniciando actualización del certificado del sistema'
UpdateSystemSSLSuccess: 'Certificado del sistema actualizado correctamente'
ErrWildcardDomain: 'No se puede solicitar certificado de dominio wildcard en modo HTTP'
ErrDeleteCAWithSSL: "La organización actual tiene un certificado emitido y no puede eliminarse."
ErrApplySSLCanNotDelete: "El certificado {{ .name }} en proceso de solicitud no puede eliminarse, inténtelo más tarde"
StartPushSSLToNode: "Iniciando envío de certificado al nodo"
PushSSLToNodeFailed: "Error al enviar el certificado al nodo: {{ .err }}"
PushSSLToNodeSuccess: "Certificado enviado correctamente al nodo"
#mysql
ErrUserIsExist: 'El usuario actual ya existe, intente con otro'
ErrDatabaseIsExist: 'La base de datos actual ya existe, intente con otro nombre'
ErrExecTimeOut: 'Tiempo de espera en la ejecución SQL, revise la base de datos'
ErrRemoteExist: 'La base de datos remota ya existe con ese nombre, modifíquelo e intente de nuevo'
ErrLocalExist: 'El nombre ya existe en la base de datos local, modifíquelo e intente de nuevo'
#redis
ErrTypeOfRedis: 'El tipo de archivo de recuperación no coincide con el método de persistencia actual, modifíquelo e intente'
#container
ErrInUsed: '{{ .detail }} está en uso y no puede eliminarse'
ErrObjectInUsed: 'El objeto está en uso y no puede eliminarse'
ErrObjectBeDependent: 'Esta imagen depende de otras imágenes y no puede eliminarse'
ErrPortRules: 'El número de puerto no coincide, ingrese de nuevo'
ErrPgImagePull: 'Tiempo de espera al descargar la imagen, configure la aceleración o descárguela manualmente ({{ .name }}) e intente de nuevo'
PruneHelper: "Esta limpieza eliminó {{ .name }} {{ .count }} elementos, liberando {{ .size }} de espacio en disco"
ImageRemoveHelper: "Imagen {{ .name }} eliminada, liberando {{ .size }} de espacio en disco"
BuildCache: "Caché de compilación"
Volume: "Volumen de almacenamiento"
Network: "Red"
#runtime
ErrFileNotExist: 'El archivo {{ .detail }} no existe, ¡verifique la integridad!'
ErrImageBuildErr: 'Fallo al construir la imagen'
ErrImageExist: "¡La imagen ya existe! Modifique el nombre de la imagen."
ErrDelWithWebsite: 'El entorno de ejecución ya está asociado a un sitio web y no puede eliminarse'
ErrRuntimeStart: 'Fallo al iniciar'
ErrPackageJsonNotFound: 'El archivo package.json no existe'
ErrScriptsNotFound: 'No se encontró la configuración de scripts en package.json'
ErrContainerNameNotFound: 'No se puede obtener el nombre del contenedor, revise el archivo .env'
ErrNodeModulesNotFound: 'La carpeta node_modules no existe, edite o espere a que inicie'
ErrContainerNameIsNull: 'El nombre del contenedor no existe'
ErrPHPPortIsDefault: "El puerto 9000 es el predeterminado, modifique e intente de nuevo"
ErrPHPRuntimePortFailed: "El puerto {{ .name }} ya está en uso por el entorno actual, modifique e intente"
#tool
ErrConfigNotFound: 'El archivo de configuración no existe'
ErrConfigParse: 'El formato del archivo de configuración es incorrecto'
ErrConfigIsNull: 'El archivo de configuración no puede estar vacío'
ErrConfigDirNotFound: 'El directorio de ejecución no existe'
ErrConfigAlreadyExist: 'Ya existe un archivo de configuración con ese nombre'
ErrUserFindErr: 'Búsqueda del usuario {{ .name }} fallida {{ .err }}'
#cronjob
CutWebsiteLogSuccess: 'Log del sitio web {{ .name }} cortado con éxito, ruta de respaldo {{ .path }}'
HandleShell: 'Ejecutar script {{ .name }}'
HandleNtpSync: 'Sincronizar hora del sistema'
HandleSystemClean: 'Limpiar caché del sistema'
SystemLog: 'Log del sistema'
CutWebsiteLog: 'Rotar log del sitio web'
FileOrDir: 'Directorio / Archivo'
UploadFile: 'Subiendo archivo de respaldo {{ .file }} a {{ .backup }}'
IgnoreBackupErr: 'Fallo en el respaldo, error: {{ .detail }}, se ignora este error...'
IgnoreUploadErr: 'Fallo en la subida, error: {{ .detail }}, se ignora este error...'
Upload: "Subir"
LoadBackupFailed: "Error al obtener la conexión de la cuenta de respaldo, error: {{ .detail }}"
InExecuting: "La tarea actual se está ejecutando, por favor no la repita"
NoSuchResource: "No se encontraron contenidos de respaldo en la base de datos, omitiendo..."
#toolbox
ErrNotExistUser: 'El usuario actual no existe, modifíquelo e intente de nuevo'
ErrBanAction: 'Fallo al configurar. El servicio {{ .name }} no está disponible, revise e intente de nuevo'
ErrClamdscanNotFound: 'El comando clamdscan no fue detectado, siga la documentación para instalarlo'
TaskSwapSet: "Configurar Swap"
SetSwap: "Configurar Swap {{ .path }} - {{ .size }}"
CreateSwap: "Crear Archivo Swap"
FormatSwap: "Formatear Archivo Swap"
EnableSwap: "Habilitar Swap"
#tamper
CleanTamperSetting: "Limpiar configuraciones de protección históricas"
SetTamperWithRules: "Iniciar protección de directorio según reglas"
ProtectDir: "Proteger directorio {{ .name }}"
IgnoreFile: "Proteger archivo {{ .name }}"
TamperSetSuccessful: "Configuración de protección completada, comenzando monitoreo de los siguientes directorios:"
#waf
ErrScope: 'No se admite la modificación de esta configuración'
ErrStateChange: 'Fallo al cambiar de estado'
ErrRuleExist: 'La regla ya existe'
ErrRuleNotExist: 'La regla no existe'
ErrParseIP: 'Formato de IP incorrecto'
ErrDefaultIP: 'default es un nombre reservado, cámbielo'
ErrGroupInUse: 'El grupo IP está en uso por listas negras/blancas y no se puede eliminar'
ErrIPGroupAclUse: "El grupo IP está en uso por reglas personalizadas del sitio web {{ .name }}, no puede eliminarse"
ErrGroupExist: 'El nombre del grupo IP ya existe'
ErrIPRange: 'Rango de IP incorrecto'
ErrIPExist: 'La IP ya existe'
urlDefense: 'Reglas de URL'
urlHelper: 'URL prohibida'
dirFilter: 'Filtro de directorio'
xss: 'XSS'
phpExec: 'Ejecución de scripts PHP'
oneWordTrojan: 'Troyano de una sola palabra'
appFilter: 'Filtrar directorios peligrosos'
webshell: 'Webshell'
args: 'Reglas de parámetros'
protocolFilter: 'Filtrado de protocolos'
javaFileter: 'Filtrado de archivos Java peligrosos'
scannerFilter: 'Filtrado de escáneres'
escapeFilter: 'Filtro de escape'
customRule: 'Regla personalizada'
httpMethod: 'Filtrado de métodos HTTP'
fileExt: 'Restricciones de carga de archivos'
defaultIpBlack: 'Grupo de IPs maliciosas'
cookie: 'Reglas de Cookie'
urlBlack: 'Lista negra de URLs'
uaBlack: 'Lista negra de User-Agent'
attackCount: 'Límite de frecuencia de ataques'
fileExtCheck: 'Restricción de carga de archivos'
geoRestrict: 'Restricciones de acceso regional'
unknownWebsite: 'Acceso no autorizado al dominio'
notFoundCount: 'Límite de tasa 404'
headerDefense: 'Reglas de encabezado'
defaultUaBlack: 'Reglas de User-Agent'
methodWhite: 'Reglas HTTP'
captcha: 'Verificación humano-máquina'
fiveSeconds: 'Verificación de 5 segundos'
vulnCheck: 'Reglas suplementarias'
acl: 'Reglas personalizadas'
sql: 'Inyección SQL'
cc: 'Límite de frecuencia de acceso'
defaultUrlBlack: 'Reglas de URL'
sqlInject: 'Inyección SQL'
ErrDBNotExist: 'La base de datos no existe'
allow: 'permitir'
deny: 'denegar'
OpenrestyNotFound: 'Openresty no está instalado'
remoteIpIsNull: "La lista de IP está vacía"
OpenrestyVersionErr: "La versión de Openresty es demasiado baja, actualice a 1.27.1.2-2-2-focal"
#task
TaskStart: 'La tarea {{ .name }} inicia [INICIO]'
TaskEnd: 'La tarea {{ .name }} completada [COMPLETADA]'
TaskFailed: 'La tarea {{ .name }} falló'
TaskTimeout: 'La tarea {{ .name }} excedió el tiempo'
TaskSuccess: 'La tarea {{ .name }} se realizó con éxito'
TaskRetry: 'Iniciar el {{ .name }} reintento'
SubTaskSuccess: '{{ .name }} exitoso'
SubTaskFailed: '{{ .name }} falló: {{ .err }}'
TaskInstall: 'Instalar'
TaskUninstall: 'Desinstalar'
TaskCreate: 'Crear'
TaskProtect: "Proteger"
TaskDelete: 'Eliminar'
TaskUpgrade: 'Actualizar'
TaskUpdate: 'Actualizar'
TaskRestart: 'Reiniciar'
TaskBackup: 'Respaldar'
TaskRecover: 'Recuperar'
TaskRollback: 'Revertir'
TaskPull: 'Descargar'
TaskCommit: 'Commit'
TaskBuild: 'Construir'
TaskPush: 'Subir'
TaskHandle: 'Ejecutar'
Website: 'Sitio web'
App: 'Aplicación'
Runtime: 'Entorno de ejecución'
Database: 'Base de datos'
ConfigFTP: 'Crear usuario FTP {{ .name }}'
ConfigOpenresty: 'Crear archivo de configuración Openresty'
InstallAppSuccess: 'Aplicación {{ .name }} instalada correctamente'
ConfigRuntime: 'Configurar entorno de ejecución'
ConfigApp: 'Configurar aplicación'
SuccessStatus: '{{ .name }} exitoso'
FailedStatus: '{{ .name }} falló {{ .err }}'
HandleLink: 'Gestionar asociación de aplicación'
HandleDatabaseApp: 'Gestionar parámetros de aplicación'
ExecShell: 'Ejecutar script {{ .name }}'
PullImage: 'Descargar imagen'
Start: 'Iniciar'
Run: 'Ejecutar'
Stop: 'Detener'
Image: 'Imagen'
Compose: 'Orquestación'
Container: 'Contenedor'
AppLink: 'Aplicación enlazada'
EnableSSL: 'Habilitar HTTPS'
AppStore: 'Tienda de aplicaciones'
TaskSync: 'Sincronizar'
LocalApp: 'Aplicación local'
SubTask: 'Subtarea'
RuntimeExtension: 'Extensión del entorno de ejecución'
TaskIsExecuting: 'Tarea en ejecución'
CustomAppstore: 'Almacén de aplicaciones personalizado'
TaskClean: "Limpieza"
TaskExec: "Ejecutar"
TaskBatch: "Operación por Lotes"
FileConvert: 'Conversión de Formato de Archivo'
# task - ai
OllamaModelPull: 'Descargar modelo Ollama {{ .name }}'
OllamaModelSize: 'Obtener tamaño del modelo Ollama {{ .name }}'
# task - clam
Clamscan: "Escanear {{ .name }}"
TaskScan: "Escaneo"
# task-snapshot
Snapshot: 'Instantánea'
SnapDBInfo: 'Escribir información de base de datos de 1Panel'
SnapCopy: 'Copiar archivos y directorios {{ .name }}'
SnapNewDB: 'Inicializar conexión a base de datos {{ .name }}'
SnapDeleteOperationLog: 'Eliminar log de operaciones'
SnapDeleteLoginLog: 'Eliminar log de accesos'
SnapDeleteMonitor: 'Eliminar datos de monitoreo'
SnapRemoveSystemIP: 'Eliminar IP del sistema'
SnapBaseInfo: 'Escribir información básica de 1Panel'
SnapInstallAppImageEmpty: 'No se seleccionaron imágenes de aplicaciones, omitiendo...'
SnapInstallApp: 'Respaldar aplicaciones instaladas de 1Panel'
SnapDockerSave: 'Comprimir aplicaciones instaladas'
SnapLocalBackup: 'Respaldar directorio local de 1Panel'
SnapCompressBackup: 'Comprimir directorio local de respaldo'
SnapPanelData: 'Respaldar directorio de datos de 1Panel'
SnapCompressPanel: 'Directorio de datos comprimido'
SnapWebsite: 'Respaldar directorio de sitios web de 1Panel'
SnapCloseDBConn: 'Cerrar conexión de base de datos'
SnapCompress: 'Crear archivos de instantánea'
SnapCompressFile: 'Comprimir archivo de instantánea'
SnapCheckCompress: 'Verificar archivo de compresión de instantánea'
SnapCompressSize: 'Tamaño del archivo de instantánea {{ .name }}'
SnapUpload: 'Subir archivo de instantánea'
SnapUploadTo: 'Subir archivo de instantánea a {{ .name }}'
SnapshotRecover: 'Restaurar instantánea'
RecoverDownload: 'Descargar archivo de instantánea'
Download: 'Descargar'
RecoverDownloadAccount: 'Obtener cuenta de respaldo para descargar instantánea {{ .name }}'
RecoverDecompress: 'Descomprimir archivos de instantánea'
Decompress: 'Descompresión'
BackupBeforeRecover: 'Respaldar datos del sistema antes de restaurar instantánea'
Readjson: 'Leer archivo Json de la instantánea'
ReadjsonPath: 'Obtener ruta del archivo Json en la instantánea'
ReadjsonContent: 'Leer archivo Json'
ReadjsonMarshal: 'Procesar escape de Json'
RecoverApp: 'Restaurar aplicaciones instaladas'
RecoverWebsite: 'Recuperar directorio del sitio web'
RecoverAppImage: 'Restaurar imagen de la instantánea'
RecoverCompose: 'Restaurar otros contenidos de compose'
RecoverComposeList: 'Obtener todos los compose a restaurar'
RecoverComposeItem: 'Restaurar compose {{ .name }}'
RecoverAppEmpty: 'No se encontraron imágenes de respaldo de aplicaciones en la instantánea'
RecoverBaseData: 'Recuperar datos y archivos básicos'
RecoverDaemonJsonEmpty: 'El archivo daemon.json no existe ni en la instantánea ni en el equipo actual'
RecoverDaemonJson: 'Restaurar archivo daemon.json de configuración de contenedor'
RecoverDBData: 'Restaurar datos de base de datos'
RecoverBackups: 'Restaurar directorio local de respaldo'
RecoverPanelData: 'Recuperar directorio de datos'
# task - container
ContainerNewCliet: 'Inicializar cliente Docker'
ContainerImagePull: 'Descargar imagen de contenedor {{ .name }}'
ContainerRemoveOld: 'Eliminar el contenedor original {{ .name }}'
ContainerImageCheck: 'Comprobar si la imagen se descargó correctamente'
ContainerLoadInfo: 'Obtener información básica del contenedor'
ContainerRecreate: 'Actualización del contenedor fallida, restaurando el contenedor original'
ContainerCreate: 'Crear nuevo contenedor {{ .name }}'
ContainerCreateFailed: 'Falló la creación del contenedor, eliminando el contenedor fallido'
ContainerStartCheck: 'Verificar si el contenedor ha iniciado'
# task - image
ImageBuild: 'Construcción de imagen'
ImageBuildStdoutCheck: 'Analizar salida de la imagen'
ImageBuildRes: 'Salida de construcción de imagen: {{ .name }}'
ImagePull: 'Descargar imagen'
ImagePush: 'Subir imagen'
ImageRenameTag: 'Modificar etiqueta de imagen'
ImageNewTag: 'Nueva etiqueta de imagen {{ .name }}'
ComposeCreate: 'Crear orquestación'
ComposeCreateRes: 'Salida de creación de orquestación: {{ .name }}'
ImageRepoAuthFromDB: "Obtener información de autenticación del repositorio desde la base de datos"
ImaegPullRes: "Salida de descarga de imagen: {{ .name }}"
ImaegPushRes: "Salida de subida de imagen: {{ .name }}"
# task - website
BackupNginxConfig: 'Respaldar archivo de configuración OpenResty'
CompressFileSuccess: 'Directorio comprimido con éxito, guardado en {{ .name }}'
CompressDir: 'Directorio comprimido'
DeCompressFile: 'Descomprimir archivo {{ .name }}'
ErrCheckValid: 'Verificación de archivo de respaldo fallida, {{ .name }}'
Rollback: 'Revertir'
websiteDir: 'Directorio del sitio web'
RecoverFailedStartRollBack: 'Restauración fallida, iniciando reversión'
AppBackupFileIncomplete: 'El archivo de respaldo está incompleto, falta app.json o app.tar.gz'
AppAttributesNotMatch: 'El tipo o nombre de la aplicación no coincide'
#alert
ErrAlert: 'El formato del mensaje de alerta es incorrecto, ¡revise e intente de nuevo!'
ErrAlertPush: 'Error al enviar la alerta, ¡revise e intente de nuevo!'
ErrAlertSave: 'Error al guardar la alerta, ¡revise e intente de nuevo!'
ErrAlertSync: 'Error en la sincronización de la alerta, ¡revise e intente de nuevo!'
ErrAlertRemote: 'Error remoto de alerta, ¡revise e intente de nuevo!'
CommonAlert: "Su 1Panel: {{ .msg }}, por favor inicie sesión en el panel para más detalles."
NodeExceptionAlert: "Su 1Panel tiene {{ .num }} nodos anómalos, inicie sesión para más detalles."
LicenseExceptionAlert: "Su 1Panel tiene {{ .num }} licencias anómalas, inicie sesión para más detalles."
SSHAndPanelLoginAlert: "Su 1Panel detectó un inicio de sesión anómalo en el panel {{ .name }} desde {{ .ip }}, revise en el panel para más detalles."
#task - runtime
ErrInstallExtension: "Ya hay una tarea de instalación en curso, espere a que termine"
# alert mail template
PanelAlertTitle: "Notificación de alerta del panel"
TestAlertTitle: "Correo de prueba - Verificar conectividad de correo"
TestAlert: "Este es un correo de prueba para verificar que la configuración de envío de correos es correcta."
LicenseExpirationAlert: "Su licencia de 1Panel expirará en {{ .day }} días. Inicie sesión para más detalles."
CronJobFailedAlert: "Su tarea programada '{{ .name }}' ha fallado. Inicie sesión en el panel para más detalles."
ClamAlert: "La tarea de escaneo de virus detectó {{ .num }} archivos infectados. Inicie sesión para detalles."
WebSiteAlert: "Hay {{ .num }} sitios web en su 1Panel que expirarán en {{ .day }} días. Inicie sesión para más detalles."
SSLAlert: "Hay {{ .num }} certificados SSL en su 1Panel que expirarán en {{ .day }} días. Inicie sesión para detalles."
DiskUsedAlert: "El disco '{{ .name }}' de su 1Panel ha utilizado {{ .used }}. Inicie sesión para más detalles."
ResourceAlert: "El uso promedio de {{ .name }} en {{ .time }} minutos es de {{ .used }}. Inicie sesión para más detalles."
PanelVersionAlert: "Hay una nueva versión de 1Panel disponible. Inicie sesión para actualizar."
PanelPwdExpirationAlert: "Su contraseña de 1Panel expirará en {{ .day }} días. Inicie sesión para más detalles."
#disk
DeviceNotFound: "Dispositivo {{ .name }} no encontrado"
DeviceIsMounted: "El dispositivo {{ .name }} está montado, desmóntelo primero"
PartitionDiskErr: "Error al particionar, {{ .err }}"
FormatDiskErr: "Error al formatear disco, {{ .err }}"
MountDiskErr: "Error al montar disco, {{ .err }}"
UnMountDiskErr: "Error al desmontar disco, {{ .err }}"
XfsNotFound: "No se detectó el sistema de archivos xfs, por favor instale xfsprogs primero"
-21
View File
@@ -94,7 +94,6 @@ ErrCustomRuntimes: 'ランタイム環境がインストールされています
ErrAppVersionDeprecated: "{{ .name }} アプリケーションは現在の 1Panel バージョンと互換性がありません、スキップしました"
ErrDockerFailed: "Docker の状態が異常です。サービス状態を確認してください"
ErrDockerComposeCmdNotFound: "Docker Compose コマンドは存在しません。ホストマシンにこのコマンドを先にインストールしてください"
UseExistImage: 'イメージのプルに失敗しました、既存のイメージを使用します'
#ssh
ExportIP: "ログインIP"
@@ -123,7 +122,6 @@ ErrLogFileToLarge: "ログファイルが500MBを超えており、開くこと
FileDropFailed: "ファイル {{ .name }} のクリーンアップに失敗しました: {{ .err }}"
FileDropSuccess: "ファイル {{ .name }} のクリーンアップに成功しました、{{ .count }} ファイルを削除、{{ .size }} のディスク領域を解放"
FileDropSum: "ファイルのクリーンアップが完了しました、合計 {{ .count }} ファイルを削除、合計 {{ .size }} のディスク領域を解放"
ErrBadDecrypt: "圧縮パッケージの解凍パスワードが間違っています。解凍に失敗しました。確認して再試行してください!"
#website
ErrAliasIsExist: 'エイリアスがすでに存在します'
@@ -142,10 +140,6 @@ ErrSSLValid: '証明書ファイルが異常です、証明書の状態を確認
ErrWebsiteDir: "ウェブサイトディレクトリ内のディレクトリを選択してください。"
ErrComposerFileNotFound: "composer.json ファイルが存在しません"
ErrRuntimeNoPort: "ランタイム環境にポートが設定されていません。先にランタイム環境を編集してください。"
Status: 'ステータス'
start: '開始'
stop: '停止'
delete: '削除'
#ssl
ErrSSLCannotDelete: '{{ .name }} 証明書は Web サイトで使用されているため、削除できません'
@@ -247,18 +241,6 @@ NoSuchResource: "データベースにバックアップ内容が見つかりま
ErrNotExistUser: '現在のユーザーは存在しません。変更してもう一度お試しください。'
ErrBanAction: '設定に失敗しました。現在の {{ .name }} サービスは利用できません。確認してもう一度お試しください。'
ErrClamdscanNotFound: 'clamdscan コマンドが検出されませんでした。インストールするにはドキュメントを参照してください。'
TaskSwapSet: "Swap設定"
SetSwap: "Swap設定 {{ .path }} - {{ .size }}"
CreateSwap: "Swapファイル作成"
FormatSwap: "Swapファイルフォーマット"
EnableSwap: "Swapファイル有効化"
#tamper
CleanTamperSetting: "履歴保護設定をクリーンアップ"
SetTamperWithRules: "ルールに従ってディレクトリ保護を開始"
ProtectDir: "ディレクトリを保護 {{ .name }}"
IgnoreFile: "ファイルを保護 {{ .name }}"
TamperSetSuccessful: "保護設定が完了し、以下のディレクトリの監視を開始します:"
#waf
ErrScope: 'この構成の変更はサポートされていません'
@@ -331,7 +313,6 @@ TaskDelete: '削除'
TaskUpgrade: 'アップグレード'
TaskUpdate: '更新'
TaskRestart: '再起動'
TaskProtect: "保護"
TaskBackup: 'バックアップ'
TaskRecover: '回復'
TaskRollback: 'ロールバック'
@@ -372,8 +353,6 @@ RuntimeExtension: 'ランタイム環境拡張'
TaskIsExecuting: 'タスクは実行中です'
CustomAppstore: 'カスタム アプリケーション ウェアハウス'
TaskExec: '実行'
TaskBatch: "一括操作"
FileConvert: 'ファイル形式の変換'
# task - clam
Clamscan: "{{ .name }} をスキャン"
-22
View File
@@ -14,7 +14,6 @@ ErrApiConfigKeyInvalid: 'API 인터페이스 키 오류: {{ .detail }}'
ErrApiConfigIPInvalid: 'API 인터페이스를 호출하는 데 사용된 IP가 허용 목록에 없습니다: {{ .detail }}'
ErrApiConfigDisable: '이 인터페이스는 API 인터페이스 호출 사용을 금지합니다: {{ .detail }}'
ErrApiConfigKeyTimeInvalid: 'API 인터페이스 타임스탬프 오류: {{ .detail }}'
ErrShutDown: "명령이 수동으로 종료되었습니다!"
ErrMinQuickJump: "최소 하나의 빠른 점프 항목을 설정해 주세요!"
ErrMaxQuickJump: "최대 네 개의 빠른 점프 항목을 설정할 수 있습니다!"
@@ -95,7 +94,6 @@ ErrCustomRuntimes: '설치된 런타임 환경이 있습니다. 먼저 삭제해
ErrAppVersionDeprecated: "{{ .name }} 응용 프로그램은 현재 1Panel 버전과 호환되지 않아 건너뛰었습니다"
ErrDockerFailed: "Docker의 상태가 비정상입니다. 서비스 상태를 확인하세요"
ErrDockerComposeCmdNotFound: "Docker Compose 명령이 없습니다. 호스트 머신에 먼저 이 명령을 설치하세요"
UseExistImage: '이미지 가져오기 실패, 기존 이미지 사용'
#ssh
ExportIP: "로그인 IP"
@@ -124,7 +122,6 @@ ErrLogFileToLarge: "로그 파일이 500MB를 초과하여 열 수 없습니다"
FileDropFailed: "파일 {{ .name }} 정리 실패: {{ .err }}"
FileDropSuccess: "파일 {{ .name }} 정리 성공, {{ .count }}개 파일 삭제, {{ .size }} 디스크 공간 확보"
FileDropSum: "파일 정리 완료, 총 {{ .count }}개 파일 삭제, 총 {{ .size }} 디스크 공간 확보"
ErrBadDecrypt: "압축 패키지 암호 해제 비밀번호 오류, 압축 해제 실패, 확인 후 다시 시도하세요!"
#웹사이트
ErrAliasIsExist: '별칭이 이미 존재합니다'
@@ -143,10 +140,6 @@ ErrSSLValid: '인증서 파일에 문제가 있습니다. 인증서 상태를
ErrWebsiteDir: "웹사이트 디렉토리 내의 디렉토리를 선택하세요."
ErrComposerFileNotFound: "composer.json 파일이 존재하지 않습니다"
ErrRuntimeNoPort: "런타임 환경에 포트가 설정되지 않았습니다. 먼저 런타임 환경을 편집하세요."
Status: '상태'
start: '시작'
stop: '중지'
delete: '삭제'
#SSL인증
ErrSSLCannotDelete: '{{ .name }} 인증서는 웹사이트에서 사용 중이므로 삭제할 수 없습니다.'
@@ -248,18 +241,6 @@ NoSuchResource: "데이터베이스에서 백업 내용을 찾을 수 없어 건
ErrNotExistUser: '현재 사용자가 존재하지 않습니다. 수정한 후 다시 시도하세요!'
ErrBanAction: '설정에 실패했습니다. 현재 {{ .name }} 서비스를 사용할 수 없습니다. 확인하고 다시 시도하세요!'
ErrClamdscanNotFound: 'clamdscan 명령이 감지되지 않았습니다. 설명서를 참조하여 설치하세요!'
TaskSwapSet: "Swap 설정"
SetSwap: "Swap 설정 {{ .path }} - {{ .size }}"
CreateSwap: "Swap 파일 생성"
FormatSwap: "Swap 파일 포맷"
EnableSwap: "Swap 활성화"
#tamper
CleanTamperSetting: "히스토리 보호 설정 정리"
SetTamperWithRules: "규칙에 따라 디렉토리 보호 시작"
ProtectDir: "디렉토리 보호 {{ .name }}"
IgnoreFile: "파일 보호 {{ .name }}"
TamperSetSuccessful: "보호 설정 완료, 다음 디렉토리 모니터링 시작:"
#와프
ErrScope: '이 구성을 수정하는 것은 지원되지 않습니다'
@@ -332,7 +313,6 @@ TaskDelete: '삭제'
TaskUpgrade: '업그레이드'
TaskUpdate: '업데이트'
TaskRestart: '다시 시작'
TaskProtect: "보호"
TaskBackup: '백업'
TaskRecover: '복구'
TaskRollback: '롤백'
@@ -373,8 +353,6 @@ RuntimeExtension: '런타임 환경 확장'
TaskIsExecuting: '작업이 실행 중입니다'
CustomAppstore: '사용자 정의 애플리케이션 웨어하우스'
TaskExec: '실행'
TaskBatch: "일괄 작업"
FileConvert: '파일 형식 변환'
# task - clam
Clamscan: "{{ .name }} 스캔"
-22
View File
@@ -17,7 +17,6 @@ ErrApiConfigKeyTimeInvalid: 'Ralat cap masa antara muka API: {{ .detail }}'
StartPushSSLToNode: "Mula menolak sijil ke nod"
PushSSLToNodeFailed: "Gagal menolak sijil ke nod: {{ .err }}"
PushSSLToNodeSuccess: "Berjaya menolak sijil ke nod"
ErrShutDown: "Arahan dihentikan secara manual!"
ErrMinQuickJump: "Sila tetapkan sekurang-kurangnya satu entri lompat pantas!"
ErrMaxQuickJump: "Anda boleh menetapkan sehingga empat entri lompat pantas!"
@@ -98,7 +97,6 @@ ErrCustomRuntimes: 'Terdapat persekitaran masa jalan yang dipasang, sila padamka
ErrAppVersionDeprecated: "Aplikasi {{ .name }} tidak sesuai dengan versi 1Panel saat ini, dilewati"
ErrDockerFailed: "Keadaan Docker tidak normal, sila periksa status perkhidmatan"
ErrDockerComposeCmdNotFound: "Perintah Docker Compose tidak wujud, sila pasang perintah ini di mesin tuan terlebih dahulu"
UseExistImage: 'Gagal menarik imej, menggunakan imej sedia ada'
#ssh
ExportIP: "IP Log Masuk"
@@ -127,7 +125,6 @@ ErrLogFileTooLarge: "Fail log melebihi 500MB dan tidak boleh dibuka"
FileDropFailed: "Gagal membersihkan fail {{ .name }}: {{ .err }}"
FileDropSuccess: "Berjaya membersihkan fail {{ .name }}, {{ .count }} fail dibersihkan, {{ .size }} ruang cakera dibebaskan"
FileDropSum: "Pembersihan fail selesai, sejumlah {{ .count }} fail dibersihkan, sejumlah {{ .size }} ruang cakera dibebaskan"
ErrBadDecrypt: "Kata laluan penyahsulitan pakej termampat salah, penyahmampatan gagal, sila periksa dan cuba lagi!"
#laman web
ErrAliasIsExist: 'Alias sudah wujud'
@@ -146,10 +143,6 @@ ErrSSLValid: 'Fail sijil bermasalah, sila periksa status sijil!'
ErrWebsiteDir: "Sila pilih direktori dalam direktori laman web."
ErrComposerFileNotFound: "Fail composer.json tidak wujud"
ErrRuntimeNoPort: "Persekitaran runtime tidak diset dengan port, sila edit persekitaran runtime terlebih dahulu."
Status: 'Status'
start: 'Mulakan'
stop: 'Berhenti'
delete: 'Padam'
#ssl
ErrSSLCannotDelete: 'Sijil {{ .name }} sedang digunakan oleh tapak web dan tidak boleh dipadamkan'
@@ -248,18 +241,6 @@ NoSuchResource: "Tiada kandungan sandaran ditemui dalam pangkalan data, dilangka
ErrNotExistUser: 'Pengguna semasa tidak wujud, sila ubah suai dan cuba lagi!'
ErrBanAction: 'Tetapan gagal. Perkhidmatan {{ .name }} semasa tidak tersedia. Sila semak dan cuba lagi!'
ErrClamdscanNotFound: 'Arahan clamdscan tidak dikesan, sila rujuk dokumentasi untuk memasangnya!'
TaskSwapSet: "Tetapkan Swap"
SetSwap: "Tetapkan Swap {{ .path }} - {{ .size }}"
CreateSwap: "Buat Fail Swap"
FormatSwap: "Format Fail Swap"
EnableSwap: "Dayakan Swap"
#tamper
CleanTamperSetting: "Bersihkan tetapan perlindungan sejarah"
SetTamperWithRules: "Mulakan perlindungan direktori mengikut peraturan"
ProtectDir: "Lindungi direktori {{ .name }}"
IgnoreFile: "Lindungi fail {{ .name }}"
TamperSetSuccessful: "Tetapan perlindungan selesai, mula memantau direktori berikut:"
#waf
ErrScope: 'Mengubah suai konfigurasi ini tidak disokong'
@@ -332,7 +313,6 @@ TaskDelete: 'Padam'
TaskUpgrade: 'Naik taraf'
TaskUpdate: 'Kemas kini'
TaskRestart: 'Mulakan semula'
TaskProtect: "Lindungi"
TaskBackup: 'Sandaran'
TaskRecover: 'Pulihkan'
TaskRollback: 'Rollback'
@@ -373,8 +353,6 @@ RuntimeExtension: 'Sambungan Persekitaran Runtime'
TaskIsExecuting: 'Tugas sedang berjalan'
CustomAppstore: 'Gudang aplikasi tersuai'
TaskExec: 'Laksanakan'
TaskBatch: "Operasi Batch"
FileConvert: 'Penukaran Format Fail'
# task - clam
Clamscan: "Imbas {{ .name }}"
-22
View File
@@ -17,7 +17,6 @@ ErrApiConfigKeyTimeInvalid: 'Erro de registro de data e hora da interface da API
StartPushSSLToNode: "Iniciando o envio do certificado para o nó"
PushSSLToNodeFailed: "Falha ao enviar o certificado para o nó: {{ .err }}"
PushSSLToNodeSuccess: "Certificado enviado com sucesso para o nó"
ErrShutDown: "Comando terminado manualmente!"
ErrMinQuickJump: "Defina pelo menos uma entrada de salto rápido!"
ErrMaxQuickJump: "Você pode definir até quatro entradas de salto rápido!"
@@ -98,7 +97,6 @@ ErrCustomRuntimes: 'Há um ambiente de execução instalado, exclua-o primeiro'
ErrAppVersionDeprecated: "O aplicativo {{ .name }} não é compatível com a versão atual do 1Panel, ignorado"
ErrDockerFailed: "O estado do Docker está anormal, verifique o status do serviço"
ErrDockerComposeCmdNotFound: "O comando Docker Compose não existe, por favor, instale este comando na máquina host primeiro"
UseExistImage: 'Falha ao puxar a imagem, usando imagem existente'
#ssh
ExportIP: "IP de Login"
@@ -127,7 +125,6 @@ ErrLogFileToLarge: "Fail log melebihi 500MB, tidak boleh dibuka"
FileDropFailed: "Falha ao limpar arquivo {{ .name }}: {{ .err }}"
FileDropSuccess: "Arquivo {{ .name }} limpo com sucesso, {{ .count }} arquivos removidos, {{ .size }} de espaço em disco liberado"
FileDropSum: "Limpeza de arquivos concluída com sucesso, total de {{ .count }} arquivos removidos, total de {{ .size }} de espaço em disco liberado"
ErrBadDecrypt: "Erro de senha de descriptografia do pacote compactado, descompactação falhou, verifique e tente novamente!"
#site
ErrAliasIsExist: 'Alias já existe'
@@ -146,10 +143,6 @@ ErrSSLValid: 'O arquivo do certificado está anormal, verifique o status do cert
ErrWebsiteDir: "Por favor, selecione um diretório dentro do diretório do site."
ErrComposerFileNotFound: "O arquivo composer.json não existe"
ErrRuntimeNoPort: "O ambiente de tempo de execução não está configurado com uma porta, edite o ambiente de tempo de execução primeiro."
Status: 'Status'
start: 'Iniciar'
stop: 'Parar'
delete: 'Excluir'
#ssl
ErrSSLCannotDelete: 'O certificado {{ .name }} está sendo usado por um site e não pode ser excluído'
@@ -248,18 +241,6 @@ NoSuchResource: "Nenhum conteúdo de backup encontrado no banco de dados, ignora
ErrNotExistUser: 'O usuário atual não existe, modifique e tente novamente!'
ErrBanAction: 'Falha na configuração. O serviço atual {{ .name }} não está disponível. Verifique e tente novamente!'
ErrClamdscanNotFound: 'O comando clamdscan não foi detectado, consulte a documentação para instalá-lo!'
TaskSwapSet: "Configurar Swap"
SetSwap: "Configurar Swap {{ .path }} - {{ .size }}"
CreateSwap: "Criar Arquivo Swap"
FormatSwap: "Formatar Arquivo Swap"
EnableSwap: "Ativar Swap"
#tamper
CleanTamperSetting: "Limpar configurações de proteção históricas"
SetTamperWithRules: "Iniciar proteção de diretório de acordo com as regras"
ProtectDir: "Proteger diretório {{ .name }}"
IgnoreFile: "Proteger arquivo {{ .name }}"
TamperSetSuccessful: "Configurações de proteção concluídas, iniciando monitoramento dos seguintes diretórios:"
#waf
ErrScope: 'A modificação desta configuração não é suportada'
@@ -332,7 +313,6 @@ TaskDelete: 'Excluir'
TaskUpgrade: 'Atualizar'
TaskUpdate: 'Atualizar'
TaskRestart: 'Reiniciar'
TaskProtect: "Proteger"
Backup de Tarefa: 'Backup'
TaskRecover: 'Recuperar'
TaskRollback: 'Reverter'
@@ -373,8 +353,6 @@ RuntimeExtension: 'Extensão do ambiente de tempo de execução'
TaskIsExecuting: 'A tarefa está em execução'
CustomAppstore: 'Armazém de aplicativos personalizados'
TaskExec: 'Executar'
TaskBatch: "Operação em Lote"
FileConvert: 'Conversão de Formato de Arquivo'
# task - clam
Clamscan: "Escanear {{ .name }}"

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