2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 05:31:44 +08:00

fix: 修复安装问题

This commit is contained in:
2026-01-07 03:35:21 +08:00
parent 0bc2585824
commit 7a5eb3210c
9 changed files with 94 additions and 44 deletions

View File

@@ -9,6 +9,7 @@ type EnvironmentRepo interface {
Types() []types.LV
All(typ ...string) api.Environments
IsInstalled(typ, slug string) bool
InstalledVersion(typ, slug string) string
HasUpdate(typ, slug string) bool
Install(typ, slug string) error
Uninstall(typ, slug string) error

View File

@@ -19,7 +19,7 @@ const (
SettingKeyMySQLRootPassword SettingKey = "mysql_root_password"
SettingKeyOfflineMode SettingKey = "offline_mode"
SettingKeyAutoUpdate SettingKey = "auto_update"
SettingKeyWebServer SettingKey = "web_server"
SettingKeyWebserver SettingKey = "webserver"
)
type Setting struct {

View File

@@ -201,7 +201,7 @@ func (r *appRepo) Install(channel, slug string) error {
if vs.GreaterThan(panel) && !r.conf.App.Debug {
return errors.New(r.t.Get("app %s requires panel version %s, current version %s", item.Name, ch.Panel, app.Version))
}
shellUrl = ch.Install
shellUrl = fmt.Sprintf("https://%s%s", r.conf.App.DownloadEndpoint, ch.Install)
shellChannel = ch.Slug
shellVersion = ch.Version
break
@@ -261,7 +261,7 @@ func (r *appRepo) UnInstall(slug string) error {
if vs.GreaterThan(panel) && !r.conf.App.Debug {
return errors.New(r.t.Get("app %s requires panel version %s, current version %s", item.Name, ch.Panel, app.Version))
}
shellUrl = ch.Uninstall
shellUrl = fmt.Sprintf("https://%s%s", r.conf.App.DownloadEndpoint, ch.Uninstall)
shellChannel = ch.Slug
shellVersion = installed.Version
break
@@ -316,7 +316,7 @@ func (r *appRepo) Update(slug string) error {
if vs.GreaterThan(panel) && !r.conf.App.Debug {
return errors.New(r.t.Get("app %s requires panel version %s, current version %s", item.Name, ch.Panel, app.Version))
}
shellUrl = ch.Update
shellUrl = fmt.Sprintf("https://%s%s", r.conf.App.DownloadEndpoint, ch.Update)
shellChannel = ch.Slug
shellVersion = ch.Version
break

View File

@@ -2,6 +2,7 @@ package data
import (
"encoding/json"
"errors"
"fmt"
"os"
"path/filepath"
@@ -69,43 +70,70 @@ func (r *environmentRepo) GetByTypeAndSlug(typ, slug string) *api.Environment {
func (r *environmentRepo) IsInstalled(typ, slug string) bool {
path := filepath.Join(app.Root, "server", typ, slug)
exist, _ := os.Stat(path)
return exist != nil && exist.IsDir()
var binFile string
switch typ {
case "php":
binFile = filepath.Join(path, "bin", "php")
default:
return false
}
_, err := os.Stat(binFile)
return err == nil
}
func (r *environmentRepo) InstalledVersion(typ, slug string) string {
if !r.IsInstalled(typ, slug) {
return ""
}
var basePath = filepath.Join(app.Root, "server", typ, slug)
switch typ {
case "php":
version, err := shell.Exec(filepath.Join(basePath, "bin", "php") + " -v | head -n 1 | awk '{print $2}'")
if err != nil {
return ""
}
return version
default:
return ""
}
}
func (r *environmentRepo) HasUpdate(typ, slug string) bool {
if !r.IsInstalled(typ, slug) {
return false
}
var basePath = filepath.Join(app.Root, "server", typ, slug)
env := r.GetByTypeAndSlug(typ, slug)
if env == nil {
return false
}
mainlineVersion := env.Version
switch typ {
case "php":
installedVersion, err := shell.Exec(filepath.Join(basePath, "bin", "php") + " -v | head -n 1 | awk '{print $2}'")
if err != nil {
return false
}
return installedVersion != mainlineVersion
default:
return false
}
mainlineVersion := env.Version
installedVersion := r.InstalledVersion(typ, slug)
return mainlineVersion != installedVersion && mainlineVersion != "" && installedVersion != ""
}
func (r *environmentRepo) Install(typ, slug string) error {
if installed := r.IsInstalled(typ, slug); installed {
return errors.New(r.t.Get("environment %s-%s already installed", typ, slug))
}
return r.do(typ, slug, "install")
}
func (r *environmentRepo) Uninstall(typ, slug string) error {
if installed := r.IsInstalled(typ, slug); !installed {
return errors.New(r.t.Get("environment %s-%s not installed", typ, slug))
}
return r.do(typ, slug, "uninstall")
}
func (r *environmentRepo) Update(typ, slug string) error {
if installed := r.IsInstalled(typ, slug); !installed {
return errors.New(r.t.Get("environment %s-%s not installed", typ, slug))
}
return r.do(typ, slug, "update")
}
@@ -118,7 +146,7 @@ func (r *environmentRepo) do(typ, slug, action string) error {
shellUrl := fmt.Sprintf("https://%s/%s/%s.sh", r.conf.App.DownloadEndpoint, typ, action)
if app.IsCli {
return shell.ExecfWithOutput(`curl -sSLm 10 --retry 3 "%s" | bash -s -- "%s"`, shellUrl, slug)
return shell.ExecfWithOutput(`curl -sSLm 10 --retry 3 "%s" | bash -s -- "%s" "%s"`, shellUrl, env.Slug, env.Version)
}
var name string
@@ -134,8 +162,8 @@ func (r *environmentRepo) do(typ, slug, action string) error {
task := new(biz.Task)
task.Name = name
task.Status = biz.TaskStatusWaiting
task.Shell = fmt.Sprintf(`curl -sSLm 10 --retry 3 "%s" | bash -s -- "%s" >> /tmp/%s-%s.log 2>&1`, shellUrl, slug, typ, slug)
task.Log = fmt.Sprintf("/tmp/%s-%s.log", typ, slug)
task.Shell = fmt.Sprintf(`curl -sSLm 10 --retry 3 "%s" | bash -s -- "%s" "%s" >> /tmp/%s-%s.log 2>&1`, shellUrl, env.Slug, env.Version, env.Type, env.Slug)
task.Log = fmt.Sprintf("/tmp/%s-%s.log", env.Type, env.Slug)
return r.task.Push(task)
}

View File

@@ -768,7 +768,7 @@ func (r *websiteRepo) ObtainCert(ctx context.Context, id uint) error {
}
func (r *websiteRepo) getVhost(website *biz.Website) (webservertypes.Vhost, error) {
webServer, err := r.setting.Get(biz.SettingKeyWebServer)
webServer, err := r.setting.Get(biz.SettingKeyWebserver)
if err != nil {
return nil, err
}
@@ -800,7 +800,7 @@ func (r *websiteRepo) getPHPVersion(name string) uint {
}
func (r *websiteRepo) reloadWebServer() error {
webServer, err := r.setting.Get(biz.SettingKeyWebServer)
webServer, err := r.setting.Get(biz.SettingKeyWebserver, "unknown")
if err != nil {
return err
}
@@ -816,5 +816,5 @@ func (r *websiteRepo) reloadWebServer() error {
return err
}
}
return nil
return errors.New(r.t.Get("unsupported web server: %s", webServer))
}

View File

@@ -38,12 +38,14 @@ func (s *EnvironmentService) List(w http.ResponseWriter, r *http.Request) {
continue
}
environments = append(environments, types.EnvironmentDetail{
Type: item.Type,
Name: item.Name,
Description: item.Description,
Slug: item.Slug,
Installed: s.environmentRepo.IsInstalled(item.Type, item.Slug),
HasUpdate: s.environmentRepo.HasUpdate(item.Type, item.Slug),
Type: item.Type,
Name: item.Name,
Description: item.Description,
Slug: item.Slug,
Version: item.Version,
InstalledVersion: s.environmentRepo.InstalledVersion(item.Type, item.Slug),
Installed: s.environmentRepo.IsInstalled(item.Type, item.Slug),
HasUpdate: s.environmentRepo.HasUpdate(item.Type, item.Slug),
})
}

View File

@@ -2,10 +2,12 @@ package types
// EnvironmentDetail 环境详情
type EnvironmentDetail struct {
Type string `json:"type"`
Name string `json:"name"`
Description string `json:"description"`
Slug string `json:"slug"`
Installed bool `json:"installed"`
HasUpdate bool `json:"has_update"`
Type string `json:"type"`
Name string `json:"name"`
Description string `json:"description"`
Slug string `json:"slug"`
Version string `json:"version"`
InstalledVersion string `json:"installed_version"`
Installed bool `json:"installed"`
HasUpdate bool `json:"has_update"`
}

View File

@@ -6,10 +6,8 @@ import { useGettext } from 'vue3-gettext'
const { $gettext } = useGettext()
// 当前选中的类型(默认为全部)
const selectedType = ref<string>('')
// 环境类型列表
const { data: types } = useRequest(environment.types, {
initialData: []
})
@@ -36,6 +34,12 @@ const columns: any = [
minWidth: 300,
ellipsis: { tooltip: true }
},
{
title: $gettext('Latest Version'),
key: 'version',
width: 160,
ellipsis: { tooltip: true }
},
{
title: $gettext('Installed Version'),
key: 'installed_version',
@@ -45,7 +49,7 @@ const columns: any = [
{
title: $gettext('Actions'),
key: 'actions',
width: 350,
width: 240,
hideInExcel: true,
render(row: any) {
return h(NFlex, null, {

View File

@@ -13,7 +13,8 @@ const doSubmit = ref(false)
const model = ref({
channel: null,
version: ''
version: '',
log: ''
})
const options = computed(() => {
@@ -37,7 +38,8 @@ const handleSubmit = () => {
show.value = false
model.value = {
channel: null,
version: ''
version: '',
log: ''
}
})
}
@@ -46,6 +48,7 @@ const handleChannelUpdate = (value: string) => {
const channel = info.value.channels.find((channel) => channel.slug === value)
if (channel) {
model.value.version = channel.version
model.value.log = channel.log
}
}
@@ -53,7 +56,8 @@ const handleClose = () => {
show.value = false
model.value = {
channel: null,
version: ''
version: '',
log: ''
}
}
</script>
@@ -86,6 +90,15 @@ const handleClose = () => {
disabled
/>
</n-form-item>
<n-form-item v-if="model.log" path="log" :label="$gettext('Release Log')">
<n-card embedded :bordered="false" content-style="padding: 12px;">
<n-scrollbar style="max-height: 200px">
<pre style="margin: 0; white-space: pre-wrap; word-break: break-word">{{
model.log
}}</pre>
</n-scrollbar>
</n-card>
</n-form-item>
</n-form>
<n-button
type="info"
@@ -94,7 +107,7 @@ const handleClose = () => {
:disabled="model.channel == null || doSubmit"
@click="handleSubmit"
>
{{ $gettext('Submit') }}
{{ operation }}
</n-button>
</n-modal>
</template>