mirror of
https://gitee.com/fit2cloud-feizhiyun/1Panel.git
synced 2024-12-02 11:57:56 +08:00
feat: 完成数据库端口修改功能
This commit is contained in:
parent
85419b6dd4
commit
8431f49c47
@ -1,11 +1,13 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/gin-gonic/gin"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func (b *BaseApi) SearchApp(c *gin.Context) {
|
||||
@ -180,3 +182,22 @@ func (b *BaseApi) GetUpdateVersions(c *gin.Context) {
|
||||
|
||||
helper.SuccessWithData(c, versions)
|
||||
}
|
||||
|
||||
func (b *BaseApi) ChangeAppPort(c *gin.Context) {
|
||||
var req dto.PortUpdate
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
if err := global.VALID.Struct(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := appService.ChangeAppPort(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package dto
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
)
|
||||
|
||||
@ -78,6 +79,12 @@ type AppInstallOperate struct {
|
||||
Operate AppOperate `json:"operate" validate:"required"`
|
||||
}
|
||||
|
||||
type PortUpdate struct {
|
||||
Key string `json:"key"`
|
||||
Name string `json:"name"`
|
||||
Port int64 `json:"port"`
|
||||
}
|
||||
|
||||
type AppService struct {
|
||||
Label string `json:"label"`
|
||||
Value string `json:"value"`
|
||||
|
@ -151,6 +151,7 @@ type RedisConfUpdateByFile struct {
|
||||
|
||||
type RedisConf struct {
|
||||
Name string `json:"name"`
|
||||
Port int64 `json:"port"`
|
||||
ContainerName string `json:"containerName"`
|
||||
Timeout string `json:"timeout"`
|
||||
Maxclients string `json:"maxclients"`
|
||||
|
@ -22,7 +22,7 @@ type IMysqlRepo interface {
|
||||
LoadRunningVersion(keys []string) ([]string, error)
|
||||
LoadBaseInfoByName(name string) (*RootInfo, error)
|
||||
LoadRedisBaseInfo() (*RootInfo, error)
|
||||
UpdateDatabasePassword(id uint, vars map[string]interface{}) error
|
||||
UpdateDatabaseInfo(id uint, vars map[string]interface{}) error
|
||||
}
|
||||
|
||||
func NewIMysqlRepo() IMysqlRepo {
|
||||
@ -181,7 +181,7 @@ func (u *MysqlRepo) Update(id uint, vars map[string]interface{}) error {
|
||||
return global.DB.Model(&model.DatabaseMysql{}).Where("id = ?", id).Updates(vars).Error
|
||||
}
|
||||
|
||||
func (u *MysqlRepo) UpdateDatabasePassword(id uint, vars map[string]interface{}) error {
|
||||
func (u *MysqlRepo) UpdateDatabaseInfo(id uint, vars map[string]interface{}) error {
|
||||
if err := global.DB.Model(&model.AppInstall{}).Where("id = ?", id).Updates(vars).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -5,6 +5,12 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/repo"
|
||||
@ -16,9 +22,6 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||
"golang.org/x/net/context"
|
||||
"gopkg.in/yaml.v3"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type AppService struct {
|
||||
@ -197,6 +200,58 @@ func (a AppService) OperateInstall(req dto.AppInstallOperate) error {
|
||||
return appInstallRepo.Save(&install)
|
||||
}
|
||||
|
||||
func (a AppService) ChangeAppPort(req dto.PortUpdate) error {
|
||||
var (
|
||||
files []string
|
||||
newFiles []string
|
||||
)
|
||||
app, err := mysqlRepo.LoadBaseInfoByName(req.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ComposeDir := fmt.Sprintf("%s/%s/%s", constant.AppInstallDir, req.Key, req.Name)
|
||||
ComposeFile := fmt.Sprintf("%s/%s/%s/docker-compose.yml", constant.AppInstallDir, req.Key, req.Name)
|
||||
path := fmt.Sprintf("%s/.env", ComposeDir)
|
||||
lineBytes, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
files = strings.Split(string(lineBytes), "\n")
|
||||
}
|
||||
for _, line := range files {
|
||||
if strings.HasPrefix(line, "PANEL_APP_PORT_HTTP=") {
|
||||
newFiles = append(newFiles, fmt.Sprintf("PANEL_APP_PORT_HTTP=%v", req.Port))
|
||||
} else {
|
||||
newFiles = append(newFiles, line)
|
||||
}
|
||||
}
|
||||
file, err := os.OpenFile(path, os.O_WRONLY, 0666)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
_, err = file.WriteString(strings.Join(newFiles, "\n"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := mysqlRepo.UpdateDatabaseInfo(app.ID, map[string]interface{}{
|
||||
"env": strings.ReplaceAll(app.Env, strconv.FormatInt(app.Port, 10), strconv.FormatInt(req.Port, 10)),
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
stdout, err := compose.Down(ComposeFile)
|
||||
if err != nil {
|
||||
return errors.New(stdout)
|
||||
}
|
||||
stdout, err = compose.Up(ComposeFile)
|
||||
if err != nil {
|
||||
return errors.New(stdout)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a AppService) Install(name string, appDetailId uint, params map[string]interface{}) error {
|
||||
|
||||
httpPort, err := checkPort("PANEL_APP_PORT_HTTP", params)
|
||||
|
@ -224,7 +224,7 @@ func (u *MysqlService) ChangeInfo(info dto.ChangeDBInfo) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = mysqlRepo.UpdateDatabasePassword(app.ID, map[string]interface{}{
|
||||
_ = mysqlRepo.UpdateDatabaseInfo(app.ID, map[string]interface{}{
|
||||
"param": strings.ReplaceAll(app.Param, app.Password, info.Value),
|
||||
"env": strings.ReplaceAll(app.Env, app.Password, info.Value),
|
||||
})
|
||||
|
@ -47,7 +47,7 @@ func (u *RedisService) UpdateConf(req dto.RedisConfUpdate) error {
|
||||
if err := configSetStr(redisInfo.ContainerName, redisInfo.Password, "maxclients", req.Maxclients); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := mysqlRepo.UpdateDatabasePassword(redisInfo.ID, map[string]interface{}{
|
||||
if err := mysqlRepo.UpdateDatabaseInfo(redisInfo.ID, map[string]interface{}{
|
||||
"param": strings.ReplaceAll(redisInfo.Param, redisInfo.Password, req.Requirepass),
|
||||
"env": strings.ReplaceAll(redisInfo.Env, redisInfo.Password, req.Requirepass),
|
||||
}); err != nil {
|
||||
@ -133,6 +133,7 @@ func (u *RedisService) LoadConf() (*dto.RedisConf, error) {
|
||||
var item dto.RedisConf
|
||||
item.ContainerName = redisInfo.ContainerName
|
||||
item.Name = redisInfo.Name
|
||||
item.Port = redisInfo.Port
|
||||
if item.Timeout, err = configGetStr(redisInfo.ContainerName, redisInfo.Password, "timeout"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ func (a *AppRouter) InitAppRouter(Router *gin.RouterGroup) {
|
||||
appRouter.POST("/installed/sync", baseApi.SyncInstalled)
|
||||
appRouter.POST("/installed/backups", baseApi.SearchInstalledBackup)
|
||||
appRouter.POST("/installed/backups/del", baseApi.DeleteAppBackup)
|
||||
appRouter.POST("/installed/port/change", baseApi.ChangeAppPort)
|
||||
appRouter.GET("/services/:key", baseApi.GetServices)
|
||||
}
|
||||
}
|
||||
|
@ -62,6 +62,12 @@ export namespace App {
|
||||
params: any;
|
||||
}
|
||||
|
||||
export interface ChangePort {
|
||||
key: string;
|
||||
name: string;
|
||||
port: number;
|
||||
}
|
||||
|
||||
export interface AppInstalled extends CommonModel {
|
||||
name: string;
|
||||
appId: string;
|
||||
|
@ -150,6 +150,7 @@ export namespace Database {
|
||||
}
|
||||
export interface RedisConf {
|
||||
name: string;
|
||||
port: number;
|
||||
timeout: number;
|
||||
maxclients: number;
|
||||
requirepass: string;
|
||||
|
@ -22,6 +22,10 @@ export const InstallApp = (install: App.AppInstall) => {
|
||||
return http.post<any>('apps/install', install);
|
||||
};
|
||||
|
||||
export const ChangePort = (params: App.ChangePort) => {
|
||||
return http.post<any>('apps/installed/port/change', params);
|
||||
};
|
||||
|
||||
export const GetAppInstalled = (info: ReqPage) => {
|
||||
return http.post<ResPage<App.AppInstalled>>('apps/installed', info);
|
||||
};
|
||||
|
@ -171,6 +171,7 @@ export default {
|
||||
baseSetting: '基础设置',
|
||||
remoteConnHelper: 'root 帐号远程连接 mysql 有安全风险,开启需谨慎!',
|
||||
confChange: '配置修改',
|
||||
portHelper: '该端口为容器对外暴露端口,修改需要单独保存并且重启容器!',
|
||||
|
||||
currentStatus: '当前状态',
|
||||
runTime: '启动时间',
|
||||
|
@ -104,6 +104,7 @@ import {
|
||||
updateMysqlConfByFile,
|
||||
updateMysqlDBInfo,
|
||||
} from '@/api/modules/database';
|
||||
import { ChangePort } from '@/api/modules/app';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import i18n from '@/lang';
|
||||
|
||||
@ -152,6 +153,16 @@ const onSave = async (formEl: FormInstance | undefined, key: string, val: any) =
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
if (key === 'port') {
|
||||
let params = {
|
||||
key: baseInfo.mysqlKey,
|
||||
name: mysqlName.value,
|
||||
port: val,
|
||||
};
|
||||
await ChangePort(params);
|
||||
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
|
||||
return;
|
||||
}
|
||||
let changeForm = {
|
||||
id: 0,
|
||||
mysqlName: mysqlName.value,
|
||||
|
@ -9,8 +9,15 @@
|
||||
<el-row style="margin-top: 20px">
|
||||
<el-col :span="1"><br /></el-col>
|
||||
<el-col :span="10">
|
||||
<el-form-item :label="$t('setting.port')" prop="port">
|
||||
<el-input clearable type="number" v-model.number="form.port" />
|
||||
<el-form-item :label="$t('setting.port')" prop="port" :rules="Rules.port">
|
||||
<el-input clearable type="number" v-model.number="form.port">
|
||||
<template #append>
|
||||
<el-button @click="onChangePort(formRef)" icon="Collection">
|
||||
{{ $t('commons.button.save') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
<span class="input-help">{{ $t('database.portHelper') }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('setting.password')" prop="requirepass">
|
||||
<el-input type="password" show-password clearable v-model="form.requirepass" />
|
||||
@ -71,6 +78,7 @@ import ConfirmDialog from '@/components/confirm-dialog/index.vue';
|
||||
import { loadRedisConf, updateRedisConf, updateRedisConfByFile } from '@/api/modules/database';
|
||||
import i18n from '@/lang';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import { ChangePort } from '@/api/modules/app';
|
||||
|
||||
const extensions = [javascript(), oneDark];
|
||||
const confShowType = ref('base');
|
||||
@ -78,7 +86,7 @@ const confShowType = ref('base');
|
||||
const restartNow = ref(false);
|
||||
const form = reactive({
|
||||
name: '',
|
||||
port: 3306,
|
||||
port: 6379,
|
||||
requirepass: '',
|
||||
timeout: 0,
|
||||
maxclients: 0,
|
||||
@ -105,6 +113,29 @@ const onClose = (): void => {
|
||||
settingShow.value = false;
|
||||
};
|
||||
|
||||
const onChangePort = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
const result = await formEl.validateField('port', callback);
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
let params = {
|
||||
key: 'redis',
|
||||
name: form.name,
|
||||
port: form.port,
|
||||
};
|
||||
await ChangePort(params);
|
||||
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
|
||||
return;
|
||||
};
|
||||
function callback(error: any) {
|
||||
if (error) {
|
||||
return error.message;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const onSave = async (formEl: FormInstance | undefined) => {
|
||||
if (confShowType.value === 'all') {
|
||||
onSaveFile();
|
||||
@ -149,6 +180,7 @@ const loadform = async () => {
|
||||
form.maxclients = Number(res.data?.maxclients);
|
||||
form.requirepass = res.data?.requirepass;
|
||||
form.maxmemory = Number(res.data?.maxmemory);
|
||||
form.port = Number(res.data?.port);
|
||||
loadMysqlConf(`/opt/1Panel/data/apps/redis/${form.name}/conf/redis.conf`);
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user