mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-10-30 16:05:30 +00:00
90 lines
2.7 KiB
Go
90 lines
2.7 KiB
Go
package service
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"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/global"
|
|
"github.com/1Panel-dev/1Panel/agent/utils/req_helper"
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
func ensureAppDetailCompose(app model.App, detail *model.AppDetail) error {
|
|
if strings.TrimSpace(detail.DockerCompose) != "" && validateAppDetailCompose([]byte(detail.DockerCompose)) == nil {
|
|
return nil
|
|
}
|
|
var content []byte
|
|
var err error
|
|
if app.IsLocalApp() || app.IsCustomApp() {
|
|
content, err = os.ReadFile(filepath.Join(app.GetAppResourcePath(), detail.Version, "docker-compose.yml"))
|
|
} else {
|
|
var composeURL string
|
|
if detail.DownloadUrl == "" {
|
|
composeURL = fmt.Sprintf("%s/%s/1panel/%s/%s/docker-compose.yml", global.AppRepoURL(), global.CONF.Base.Mode, app.Key, detail.Version)
|
|
} else {
|
|
var source *url.URL
|
|
source, err = url.Parse(detail.DownloadUrl)
|
|
if err == nil {
|
|
source.Path = path.Join(path.Dir(source.Path), "docker-compose.yml")
|
|
source.RawPath = ""
|
|
composeURL = source.String()
|
|
}
|
|
}
|
|
if err == nil {
|
|
composeURL, err = currentAppDownloadURL(composeURL)
|
|
}
|
|
if err == nil {
|
|
var status int
|
|
status, content, err = req_helper.HandleRequest(composeURL, http.MethodGet, constant.TimeOut20s)
|
|
if status == http.StatusNotFound {
|
|
return buserr.New("ErrAppVersionUnavailable")
|
|
}
|
|
}
|
|
}
|
|
if err != nil {
|
|
return buserr.WithDetail("ErrGetCompose", err.Error(), err)
|
|
}
|
|
return cacheAppDetailCompose(detail, content)
|
|
}
|
|
|
|
func validateAppDetailCompose(content []byte) error {
|
|
var compose struct {
|
|
Services map[string]map[string]interface{} `yaml:"services"`
|
|
}
|
|
if err := yaml.Unmarshal(content, &compose); err != nil {
|
|
return buserr.WithDetail("ErrGetCompose", err.Error(), err)
|
|
}
|
|
if len(compose.Services) == 0 {
|
|
return buserr.WithDetail("ErrGetCompose", "docker-compose.yml has no services", nil)
|
|
}
|
|
for name, service := range compose.Services {
|
|
if strings.TrimSpace(name) == "" || len(service) == 0 {
|
|
return buserr.WithDetail("ErrGetCompose", "docker-compose.yml has an empty service", nil)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func cacheAppDetailCompose(detail *model.AppDetail, content []byte) error {
|
|
if err := validateAppDetailCompose(content); err != nil {
|
|
return err
|
|
}
|
|
stored, err := appDetailRepo.CacheCompose(*detail, string(content))
|
|
if err != nil {
|
|
return buserr.WithDetail("ErrGetCompose", err.Error(), err)
|
|
}
|
|
if !stored {
|
|
return buserr.WithDetail("ErrGetCompose", "application resources changed; retry the operation", nil)
|
|
}
|
|
detail.DockerCompose = string(content)
|
|
return nil
|
|
}
|