feat: 优化 PHP 运行环境扩展安装 (#6401)
Some checks failed
sync2gitee / repo-sync (push) Failing after -8m45s

This commit is contained in:
zhengkunwang 2024-09-06 18:37:51 +08:00 committed by GitHub
parent 1af83c1aeb
commit 7aefd0df1a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 106 additions and 46 deletions

View file

@ -12,6 +12,7 @@ import (
"path"
"path/filepath"
"regexp"
"sort"
"strconv"
"strings"
"time"
@ -536,10 +537,7 @@ func (r *RuntimeService) OperateRuntime(req request.RuntimeOperate) error {
}
runtime.Status = constant.RuntimeStopped
case constant.RuntimeRestart:
if err = runComposeCmdWithLog(constant.RuntimeDown, runtime.GetComposePath(), runtime.GetLogPath()); err != nil {
return err
}
if err = runComposeCmdWithLog(constant.RuntimeUp, runtime.GetComposePath(), runtime.GetLogPath()); err != nil {
if err = restartRuntime(runtime); err != nil {
return err
}
if err = SyncRuntimeContainerStatus(runtime); err != nil {
@ -659,27 +657,29 @@ func (r *RuntimeService) GetPHPExtensions(runtimeID uint) (response.PHPExtension
return res, err
}
extensions := strings.Split(out, "\n")
var cleanExtensions []string
exitExtensions := make(map[string]string)
for _, ext := range extensions {
extStr := strings.TrimSpace(ext)
if extStr != "" && extStr != "[Zend Modules]" && extStr != "[PHP Modules]" {
cleanExtensions = append(cleanExtensions, extStr)
exitExtensions[strings.ToLower(extStr)] = extStr
}
}
res.Extensions = cleanExtensions
var phpExtensions []response.SupportExtension
if err = json.Unmarshal(nginx_conf.PHPExtensionsJson, &phpExtensions); err != nil {
return res, err
}
for _, ext := range phpExtensions {
for _, cExt := range cleanExtensions {
if ext.Check == cExt {
ext.Installed = true
break
}
if _, ok := exitExtensions[strings.ToLower(ext.Check)]; ok {
ext.Installed = true
}
res.SupportExtensions = append(res.SupportExtensions, ext)
}
for _, name := range exitExtensions {
res.Extensions = append(res.Extensions, name)
}
sort.Slice(res.Extensions, func(i, j int) bool {
return strings.ToLower(res.Extensions[i]) < strings.ToLower(res.Extensions[j])
})
return res, nil
}
@ -688,7 +688,7 @@ func (r *RuntimeService) InstallPHPExtension(req request.PHPExtensionInstallReq)
if err != nil {
return err
}
installTask, err := task.NewTaskWithOps(req.Name, task.TaskInstall, task.TaskScopeRuntime, req.TaskID, runtime.ID)
installTask, err := task.NewTaskWithOps(req.Name, task.TaskInstall, task.TaskScopeRuntimeExtension, req.TaskID, runtime.ID)
if err != nil {
return err
}
@ -698,6 +698,27 @@ func (r *RuntimeService) InstallPHPExtension(req request.PHPExtensionInstallReq)
if err != nil {
return err
}
client, err := docker.NewClient()
defer client.Close()
if err == nil {
oldImageID, err := client.GetImageIDByName(runtime.Image)
commitCmd := fmt.Sprintf("docker commit %s %s", runtime.ContainerName, runtime.Image)
err = cmd2.ExecWithLogFile(commitCmd, 15*time.Minute, t.Task.LogFile)
if err != nil {
return err
}
newImageID, err := client.GetImageIDByName(runtime.Image)
if err == nil && newImageID != oldImageID {
if err := client.DeleteImage(oldImageID); err != nil {
t.Log(fmt.Sprintf("delete old image error %v", err))
} else {
t.Log("delete old image success")
}
}
}
if err = restartRuntime(runtime); err != nil {
return err
}
return nil
}, nil)
go func() {
@ -745,7 +766,10 @@ func (r *RuntimeService) UnInstallPHPExtension(req request.PHPExtensionInstallRe
if err != nil {
return err
}
if err := unInstallPHPExtension(runtime, []string{req.Name}); err != nil {
if err = unInstallPHPExtension(runtime, []string{req.Name}); err != nil {
return err
}
if err = restartRuntime(runtime); err != nil {
return err
}
return runtimeRepo.Save(runtime)
@ -858,10 +882,7 @@ func (r *RuntimeService) UpdatePHPConfig(req request.PHPConfigUpdate) (err error
return err
}
err = r.OperateRuntime(request.RuntimeOperate{
Operate: constant.RuntimeRestart,
ID: req.ID,
})
err = restartRuntime(runtime)
if err != nil {
_ = fileOp.WriteFile(phpConfigPath, strings.NewReader(string(contentBytes)), 0755)
return err

View file

@ -1,6 +1,7 @@
package service
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
@ -135,7 +136,7 @@ func runComposeCmdWithLog(operate string, composePath string, logPath string) er
if operate == "up" {
cmd = exec.Command("docker", "compose", "-f", composePath, operate, "-d")
}
logFile, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
logFile, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
global.LOG.Errorf("Failed to open log file: %v", err)
return err
@ -149,7 +150,7 @@ func runComposeCmdWithLog(operate string, composePath string, logPath string) er
err = cmd.Run()
if err != nil {
return errors.New(buserr.New(constant.ErrRuntimeStart).Error() + ":" + stderrBuf.String())
return errors.New(buserr.New(constant.ErrRuntimeStart).Error() + ":" + err.Error())
}
return nil
}
@ -206,21 +207,6 @@ func getRuntimeEnv(envStr, key string) string {
return ""
}
func getFileEnv(filePath, key string) (string, error) {
envContent, err := files.NewFileOp().GetContent(filePath)
if err != nil {
return "", err
}
env, err := gotenv.Unmarshal(string(envContent))
if err != nil {
return "", err
}
if v, ok := env[key]; ok {
return v, nil
}
return "", nil
}
func buildRuntime(runtime *model.Runtime, oldImageID string, oldEnv string, rebuild bool) {
runtimePath := runtime.GetPath()
composePath := runtime.GetComposePath()
@ -249,6 +235,9 @@ func buildRuntime(runtime *model.Runtime, oldImageID string, oldEnv string, rebu
runtime.Message = buserr.New(constant.ErrImageBuildErr).Error() + ":" + err.Error()
}
} else {
if err = runComposeCmdWithLog(constant.RuntimeDown, runtime.GetComposePath(), runtime.GetLogPath()); err != nil {
return
}
runtime.Message = ""
if oldImageID != "" {
client, err := docker.NewClient()
@ -500,6 +489,7 @@ func unInstallPHPExtension(runtime *model.Runtime, delExtensions []string) error
delMap[ext.Check] = struct{}{}
_ = fileOP.DeleteFile(path.Join(dir, "extensions", 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
}
}
@ -531,3 +521,48 @@ func unInstallPHPExtension(runtime *model.Runtime, delExtensions []string) error
runtime.Env = envContent
return nil
}
func removePHPIniExt(filePath, extensionName string) error {
file, err := os.Open(filePath)
if err != nil {
return err
}
defer file.Close()
targetLine1 := `extension="` + extensionName + `"`
targetLine2 := `zend_extension="` + extensionName + `"`
tempFile, err := os.CreateTemp(path.Dir(filePath), "temp_*.txt")
if err != nil {
return err
}
defer tempFile.Close()
scanner := bufio.NewScanner(file)
writer := bufio.NewWriter(tempFile)
for scanner.Scan() {
line := scanner.Text()
if !strings.Contains(line, targetLine1) && !strings.Contains(line, targetLine2) {
_, err := writer.WriteString(line + "\n")
if err != nil {
return err
}
}
}
if err := scanner.Err(); err != nil {
return err
}
return os.Rename(tempFile.Name(), filePath)
}
func restartRuntime(runtime *model.Runtime) (err error) {
if err = runComposeCmdWithLog(constant.RuntimeDown, runtime.GetComposePath(), runtime.GetLogPath()); err != nil {
return
}
if err = runComposeCmdWithLog(constant.RuntimeUp, runtime.GetComposePath(), runtime.GetLogPath()); err != nil {
return
}
return
}

View file

@ -54,11 +54,12 @@ const (
)
const (
TaskScopeWebsite = "Website"
TaskScopeApp = "App"
TaskScopeRuntime = "Runtime"
TaskScopeDatabase = "Database"
TaskScopeAppStore = "AppStore"
TaskScopeWebsite = "Website"
TaskScopeApp = "App"
TaskScopeRuntime = "Runtime"
TaskScopeDatabase = "Database"
TaskScopeAppStore = "AppStore"
TaskScopeRuntimeExtension = "RuntimeExtension"
)
const (

View file

@ -8,7 +8,7 @@
},
{
"name": "opcache",
"check": "opcache",
"check": "Zend OPcache",
"file": "opcache.so",
"versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83"],
"installed": false

View file

@ -243,4 +243,5 @@ AppStore: "App Store"
TaskSync: "Sync"
LocalApp: "Local App"
SubTask: "Subtask"
RuntimeExtension: "Runtime Extension"

View file

@ -245,4 +245,5 @@ AppStore: "應用商店"
TaskSync: "同步"
LocalApp: "本地應用"
SubTask: "子任務"
RuntimeExtension: "運行環境擴展"

View file

@ -246,4 +246,5 @@ EnableSSL: "开启 HTTPS"
AppStore: "应用商店"
TaskSync: "同步"
LocalApp: "本地应用"
SubTask: "子任务"
SubTask: "子任务"
RuntimeExtension: "运行环境扩展"

View file

@ -8,7 +8,7 @@
<div class="mt-5">
<el-text>{{ $t('runtime.popularExtension') }}</el-text>
</div>
<ComplexTable :data="supportExtensions" @search="search()" :heightDiff="350" :loading="loading">
<ComplexTable :data="supportExtensions" @search="search()" :heightDiff="350" v-loading="loading">
<el-table-column prop="name" :label="$t('commons.table.name')" />
<el-table-column prop="installed" :label="$t('commons.table.status')">
<template #default="{ row }">
@ -26,7 +26,7 @@
/>
</ComplexTable>
</DrawerPro>
<TaskLog ref="taskLogRef" @clos="search()" />
<TaskLog ref="taskLogRef" @close="search()" />
</template>
<script setup lang="ts">
@ -76,7 +76,7 @@ const installExtension = async (row: Runtime.SupportExtension) => {
}).then(async () => {
const req = {
id: runtime.value.id,
name: row.check,
name: row.name,
taskID: newUUID(),
};
loading.value = true;
@ -96,7 +96,7 @@ const unInstallPHPExtension = async (row: Runtime.SupportExtension) => {
}).then(async () => {
const req = {
id: runtime.value.id,
name: row.check,
name: row.name,
};
loading.value = true;
try {