mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-31 14:08:06 +08:00
parent
98df3806f5
commit
3e6cd1cab1
@ -34,6 +34,28 @@ func (b *BaseApi) CreateRemoteDB(c *gin.Context) {
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
// @Tags Database
|
||||
// @Summary Check remote database
|
||||
// @Description 检测远程数据库连接性
|
||||
// @Accept json
|
||||
// @Param request body dto.RemoteDBCreate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /databases/remote/check [post]
|
||||
// @x-panel-log {"bodyKeys":["name", "type"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"检测远程数据库 [name][type] 连接性","formatEN":"check if remote database [name][type] is connectable"}
|
||||
func (b *BaseApi) CheckeRemoteDB(c *gin.Context) {
|
||||
var req dto.RemoteDBCreate
|
||||
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
|
||||
}
|
||||
helper.SuccessWithData(c, remoteDBService.CheckeRemoteDB(req))
|
||||
}
|
||||
|
||||
// @Tags Database
|
||||
// @Summary Page remote databases
|
||||
// @Description 获取远程数据库列表分页
|
||||
|
@ -16,6 +16,7 @@ type RemoteDBService struct{}
|
||||
type IRemoteDBService interface {
|
||||
Get(name string) (dto.RemoteDBInfo, error)
|
||||
SearchWithPage(search dto.RemoteDBSearch) (int64, interface{}, error)
|
||||
CheckeRemoteDB(req dto.RemoteDBCreate) bool
|
||||
Create(req dto.RemoteDBCreate) error
|
||||
Update(req dto.RemoteDBUpdate) error
|
||||
Delete(id uint) error
|
||||
@ -68,6 +69,20 @@ func (u *RemoteDBService) List(dbType string) ([]dto.RemoteDBOption, error) {
|
||||
return datas, err
|
||||
}
|
||||
|
||||
func (u *RemoteDBService) CheckeRemoteDB(req dto.RemoteDBCreate) bool {
|
||||
if _, err := mysql.NewMysqlClient(client.DBInfo{
|
||||
From: "remote",
|
||||
Address: req.Address,
|
||||
Port: req.Port,
|
||||
Username: req.Username,
|
||||
Password: req.Password,
|
||||
Timeout: 6,
|
||||
}); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (u *RemoteDBService) Create(req dto.RemoteDBCreate) error {
|
||||
db, _ := remoteDBRepo.Get(commonRepo.WithByName(req.Name))
|
||||
if db.ID != 0 {
|
||||
@ -79,7 +94,7 @@ func (u *RemoteDBService) Create(req dto.RemoteDBCreate) error {
|
||||
Port: req.Port,
|
||||
Username: req.Username,
|
||||
Password: req.Password,
|
||||
Timeout: 300,
|
||||
Timeout: 6,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ func (s *DatabaseRouter) InitDatabaseRouter(Router *gin.RouterGroup) {
|
||||
cmdRouter.POST("/redis/conffile/update", baseApi.UpdateRedisConfByFile)
|
||||
cmdRouter.POST("/redis/persistence/update", baseApi.UpdateRedisPersistenceConf)
|
||||
|
||||
cmdRouter.POST("/remote/check", baseApi.CheckeRemoteDB)
|
||||
cmdRouter.POST("/remote", baseApi.CreateRemoteDB)
|
||||
cmdRouter.GET("/remote/:name", baseApi.GetRemoteDB)
|
||||
cmdRouter.GET("/remote/list/:type", baseApi.ListRemoteDB)
|
||||
|
@ -1,8 +1,10 @@
|
||||
package mysql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
@ -38,9 +40,16 @@ func NewMysqlClient(conn client.DBInfo) (MysqlClient, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := db.Ping(); err != nil {
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(conn.Timeout)*time.Second)
|
||||
defer cancel()
|
||||
if err := db.PingContext(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ctx.Err() == context.DeadlineExceeded {
|
||||
return nil, buserr.New(constant.ErrExecTimeOut)
|
||||
}
|
||||
|
||||
return client.NewRemote(client.Remote{
|
||||
Client: db,
|
||||
From: conn.From,
|
||||
|
@ -4410,6 +4410,49 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/databases/remote/check": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "检测远程数据库连接性",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Database"
|
||||
],
|
||||
"summary": "Check remote database",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.RemoteDBCreate"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFuntions": [],
|
||||
"bodyKeys": [
|
||||
"name",
|
||||
"type"
|
||||
],
|
||||
"formatEN": "check if remote database [name][type] is connectable",
|
||||
"formatZH": "检测远程数据库 [name][type] 连接性",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/databases/remote/del": {
|
||||
"post": {
|
||||
"security": [
|
||||
@ -11621,7 +11664,6 @@ const docTemplate = `{
|
||||
"dto.ChangeDBInfo": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"from",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
@ -12923,13 +12965,15 @@ const docTemplate = `{
|
||||
"type": "integer"
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"maxLength": 256
|
||||
},
|
||||
"protocol": {
|
||||
"type": "string"
|
||||
},
|
||||
"username": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"maxLength": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -13776,7 +13820,8 @@ const docTemplate = `{
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"maxLength": 256
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
@ -13817,7 +13862,8 @@ const docTemplate = `{
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"maxLength": 256
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
|
@ -4403,6 +4403,49 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/databases/remote/check": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "检测远程数据库连接性",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Database"
|
||||
],
|
||||
"summary": "Check remote database",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/dto.RemoteDBCreate"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFuntions": [],
|
||||
"bodyKeys": [
|
||||
"name",
|
||||
"type"
|
||||
],
|
||||
"formatEN": "check if remote database [name][type] is connectable",
|
||||
"formatZH": "检测远程数据库 [name][type] 连接性",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/databases/remote/del": {
|
||||
"post": {
|
||||
"security": [
|
||||
@ -11614,7 +11657,6 @@
|
||||
"dto.ChangeDBInfo": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"from",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
@ -12916,13 +12958,15 @@
|
||||
"type": "integer"
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"maxLength": 256
|
||||
},
|
||||
"protocol": {
|
||||
"type": "string"
|
||||
},
|
||||
"username": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"maxLength": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -13769,7 +13813,8 @@
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"maxLength": 256
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
@ -13810,7 +13855,8 @@
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"maxLength": 256
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
|
@ -127,7 +127,6 @@ definitions:
|
||||
value:
|
||||
type: string
|
||||
required:
|
||||
- from
|
||||
- value
|
||||
type: object
|
||||
dto.ChangeHostGroup:
|
||||
@ -1000,10 +999,12 @@ definitions:
|
||||
id:
|
||||
type: integer
|
||||
password:
|
||||
maxLength: 256
|
||||
type: string
|
||||
protocol:
|
||||
type: string
|
||||
username:
|
||||
maxLength: 256
|
||||
type: string
|
||||
type: object
|
||||
dto.ImageSave:
|
||||
@ -1565,6 +1566,7 @@ definitions:
|
||||
- remote
|
||||
type: string
|
||||
name:
|
||||
maxLength: 256
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
@ -1599,6 +1601,7 @@ definitions:
|
||||
id:
|
||||
type: integer
|
||||
name:
|
||||
maxLength: 256
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
@ -6648,6 +6651,34 @@ paths:
|
||||
summary: Get remote databases
|
||||
tags:
|
||||
- Database
|
||||
/databases/remote/check:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 检测远程数据库连接性
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/dto.RemoteDBCreate'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Check remote database
|
||||
tags:
|
||||
- Database
|
||||
x-panel-log:
|
||||
BeforeFuntions: []
|
||||
bodyKeys:
|
||||
- name
|
||||
- type
|
||||
formatEN: check if remote database [name][type] is connectable
|
||||
formatZH: 检测远程数据库 [name][type] 连接性
|
||||
paramKeys: []
|
||||
/databases/remote/del:
|
||||
post:
|
||||
consumes:
|
||||
|
@ -100,11 +100,14 @@ export const searchRemoteDBs = (params: Database.SearchRemoteDBPage) => {
|
||||
export const listRemoteDBs = (type: string) => {
|
||||
return http.get<Array<Database.RemoteDBOption>>(`/databases/remote/list/${type}`);
|
||||
};
|
||||
export const checkRemoteDB = (params: Database.RemoteDBCreate) => {
|
||||
return http.post<boolean>(`/databases/remote/check`, params, 40000);
|
||||
};
|
||||
export const addRemoteDB = (params: Database.RemoteDBCreate) => {
|
||||
return http.post(`/databases/remote`, params);
|
||||
return http.post(`/databases/remote`, params, 40000);
|
||||
};
|
||||
export const editRemoteDB = (params: Database.RemoteDBUpdate) => {
|
||||
return http.post(`/databases/remote/update`, params);
|
||||
return http.post(`/databases/remote/update`, params, 40000);
|
||||
};
|
||||
export const deleteRemoteDB = (id: number) => {
|
||||
return http.post(`/databases/remote/del`, { id: id });
|
||||
|
@ -8,7 +8,7 @@
|
||||
:back="handleClose"
|
||||
/>
|
||||
</template>
|
||||
<el-form ref="formRef" label-position="top" :model="dialogData.rowData" :rules="rules">
|
||||
<el-form ref="formRef" v-loading="loading" label-position="top" :model="dialogData.rowData" :rules="rules">
|
||||
<el-row type="flex" justify="center">
|
||||
<el-col :span="22">
|
||||
<el-form-item :label="$t('commons.table.name')" prop="name">
|
||||
@ -20,7 +20,7 @@
|
||||
<el-tag v-else>{{ dialogData.rowData!.name }}</el-tag>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('database.version')" prop="version">
|
||||
<el-select v-model="dialogData.rowData!.version">
|
||||
<el-select @change="isOK = false" v-model="dialogData.rowData!.version">
|
||||
<el-option value="5.6" label="5.6" />
|
||||
<el-option value="5.7" label="5.7" />
|
||||
<el-option value="8.0" label="8.0" />
|
||||
@ -28,17 +28,23 @@
|
||||
<span class="input-help">{{ $t('database.versionHelper') }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('database.address')" prop="address">
|
||||
<el-input clearable v-model.trim="dialogData.rowData!.address" />
|
||||
<el-input @change="isOK = false" clearable v-model.trim="dialogData.rowData!.address" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.table.port')" prop="port">
|
||||
<el-input clearable v-model.number="dialogData.rowData!.port" />
|
||||
<el-input @change="isOK = false" clearable v-model.number="dialogData.rowData!.port" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.login.username')" prop="username">
|
||||
<el-input clearable v-model.trim="dialogData.rowData!.username" />
|
||||
<el-input @change="isOK = false" clearable v-model.trim="dialogData.rowData!.username" />
|
||||
<span class="input-help">{{ $t('database.userHelper') }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.login.password')" prop="password">
|
||||
<el-input type="password" clearable show-password v-model.trim="dialogData.rowData!.password" />
|
||||
<el-input
|
||||
@change="isOK = false"
|
||||
type="password"
|
||||
clearable
|
||||
show-password
|
||||
v-model.trim="dialogData.rowData!.password"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.table.description')" prop="description">
|
||||
<el-input clearable v-model.trim="dialogData.rowData!.description" />
|
||||
@ -49,7 +55,10 @@
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="drawerVisiable = false">{{ $t('commons.button.cancel') }}</el-button>
|
||||
<el-button type="primary" @click="onSubmit(formRef)">
|
||||
<el-button @click="onSubmit(formRef, 'check')">
|
||||
{{ $t('terminal.testConn') }}
|
||||
</el-button>
|
||||
<el-button type="primary" :disabled="!isOK" @click="onSubmit(formRef, dialogData.title)">
|
||||
{{ $t('commons.button.confirm') }}
|
||||
</el-button>
|
||||
</span>
|
||||
@ -63,9 +72,9 @@ import i18n from '@/lang';
|
||||
import { ElForm } from 'element-plus';
|
||||
import { Database } from '@/api/interface/database';
|
||||
import DrawerHeader from '@/components/drawer-header/index.vue';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { MsgError, MsgSuccess } from '@/utils/message';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import { addRemoteDB, editRemoteDB } from '@/api/modules/database';
|
||||
import { addRemoteDB, checkRemoteDB, editRemoteDB } from '@/api/modules/database';
|
||||
|
||||
interface DialogProps {
|
||||
title: string;
|
||||
@ -77,6 +86,9 @@ const drawerVisiable = ref(false);
|
||||
const dialogData = ref<DialogProps>({
|
||||
title: '',
|
||||
});
|
||||
const isOK = ref(false);
|
||||
const loading = ref();
|
||||
|
||||
const acceptParams = (params: DialogProps): void => {
|
||||
dialogData.value = params;
|
||||
title.value = i18n.global.t('database.' + dialogData.value.title + 'RemoteDB');
|
||||
@ -100,40 +112,65 @@ const rules = reactive({
|
||||
type FormInstance = InstanceType<typeof ElForm>;
|
||||
const formRef = ref<FormInstance>();
|
||||
|
||||
const onSubmit = async (formEl: FormInstance | undefined) => {
|
||||
const onSubmit = async (formEl: FormInstance | undefined, operation: string) => {
|
||||
if (!formEl) return;
|
||||
formEl.validate(async (valid) => {
|
||||
if (!valid) return;
|
||||
if (dialogData.value.title === 'create') {
|
||||
let param = {
|
||||
name: dialogData.value.rowData.name,
|
||||
type: 'mysql',
|
||||
version: dialogData.value.rowData.version,
|
||||
from: 'remote',
|
||||
address: dialogData.value.rowData.address,
|
||||
port: dialogData.value.rowData.port,
|
||||
username: dialogData.value.rowData.username,
|
||||
password: dialogData.value.rowData.password,
|
||||
description: dialogData.value.rowData.description,
|
||||
};
|
||||
await addRemoteDB(param);
|
||||
}
|
||||
if (dialogData.value.title === 'edit') {
|
||||
let param = {
|
||||
id: dialogData.value.rowData.id,
|
||||
version: dialogData.value.rowData.version,
|
||||
address: dialogData.value.rowData.address,
|
||||
port: dialogData.value.rowData.port,
|
||||
username: dialogData.value.rowData.username,
|
||||
password: dialogData.value.rowData.password,
|
||||
description: dialogData.value.rowData.description,
|
||||
};
|
||||
await editRemoteDB(param);
|
||||
let param = {
|
||||
id: dialogData.value.rowData.id,
|
||||
name: dialogData.value.rowData.name,
|
||||
type: 'mysql',
|
||||
version: dialogData.value.rowData.version,
|
||||
from: 'remote',
|
||||
address: dialogData.value.rowData.address,
|
||||
port: dialogData.value.rowData.port,
|
||||
username: dialogData.value.rowData.username,
|
||||
password: dialogData.value.rowData.password,
|
||||
description: dialogData.value.rowData.description,
|
||||
};
|
||||
loading.value = true;
|
||||
|
||||
if (operation === 'check') {
|
||||
await checkRemoteDB(param)
|
||||
.then((res) => {
|
||||
loading.value = false;
|
||||
if (res.data) {
|
||||
isOK.value = true;
|
||||
MsgSuccess(i18n.global.t('terminal.connTestOk'));
|
||||
} else {
|
||||
MsgError(i18n.global.t('terminal.connTestFailed'));
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
MsgError(i18n.global.t('terminal.connTestFailed'));
|
||||
});
|
||||
}
|
||||
|
||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||
emit('search');
|
||||
drawerVisiable.value = false;
|
||||
if (operation === 'create') {
|
||||
await addRemoteDB(param)
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||
emit('search');
|
||||
drawerVisiable.value = false;
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
if (operation === 'edit') {
|
||||
await editRemoteDB(param)
|
||||
.then(() => {
|
||||
loading.value = false;
|
||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||
emit('search');
|
||||
drawerVisiable.value = false;
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user