From f0540559bb880201044ddcddca5384395fc8629b Mon Sep 17 00:00:00 2001 From: "meilin.huang" <954537473@qq.com> Date: Wed, 20 Jul 2022 23:25:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=95=B0=E6=8D=AE=E5=BA=93=E3=80=81red?= =?UTF-8?q?is=E3=80=81mongo=E6=94=AF=E6=8C=81ssh=E9=9A=A7=E9=81=93?= =?UTF-8?q?=E7=AD=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LICENSE | 2 +- README.en.md | 36 - mayfly_go_web/package-lock.json | 33 +- mayfly_go_web/src/views/ops/db/DbEdit.vue | 83 +- .../src/views/ops/machine/MachineEdit.vue | 65 +- .../src/views/ops/machine/MachineList.vue | 6 +- .../src/views/ops/mongo/MongoEdit.vue | 38 +- .../src/views/ops/redis/RedisEdit.vue | 37 +- mayfly_go_web/yarn.lock | 2545 ++++++++--------- server/config.yml | 2 +- server/go.mod | 2 +- server/internal/devops/api/db.go | 14 +- server/internal/devops/api/form/db.go | 7 +- server/internal/devops/api/form/machine.go | 14 +- server/internal/devops/api/form/mongo.go | 16 +- server/internal/devops/api/form/redis.go | 22 +- server/internal/devops/api/machine.go | 18 +- server/internal/devops/api/vo/db.go | 6 +- server/internal/devops/api/vo/redis.go | 24 +- server/internal/devops/api/vo/vo.go | 1 + server/internal/devops/application/db_app.go | 137 +- .../internal/devops/application/mongo_app.go | 86 +- .../internal/devops/application/redis_app.go | 94 +- server/internal/devops/domain/entity/db.go | 26 +- .../internal/devops/domain/entity/machine.go | 11 +- server/internal/devops/domain/entity/mongo.go | 14 +- server/internal/devops/domain/entity/redis.go | 20 +- .../devops/infrastructure/machine/machine.go | 170 +- server/mayfly-go.sql | 14 +- server/pkg/utils/ssh_conn_wrap.go | 36 + 30 files changed, 1885 insertions(+), 1694 deletions(-) delete mode 100644 README.en.md create mode 100644 server/pkg/utils/ssh_conn_wrap.go diff --git a/LICENSE b/LICENSE index 261eeb9e..850c937d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ Apache License Version 2.0, January 2004 - http://www.apache.org/licenses/ + http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION diff --git a/README.en.md b/README.en.md deleted file mode 100644 index 7b4cf095..00000000 --- a/README.en.md +++ /dev/null @@ -1,36 +0,0 @@ -# mayfly-go - -#### Description -golang实现linux运维等 - -#### Software Architecture -Software architecture description - -#### Installation - -1. xxxx -2. xxxx -3. xxxx - -#### Instructions - -1. xxxx -2. xxxx -3. xxxx - -#### Contribution - -1. Fork the repository -2. Create Feat_xxx branch -3. Commit your code -4. Create Pull Request - - -#### Gitee Feature - -1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md -2. Gitee blog [blog.gitee.com](https://blog.gitee.com) -3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) -4. The most valuable open source project [GVP](https://gitee.com/gvp) -5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) -6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/mayfly_go_web/package-lock.json b/mayfly_go_web/package-lock.json index d5bcc165..2a45a216 100644 --- a/mayfly_go_web/package-lock.json +++ b/mayfly_go_web/package-lock.json @@ -15,6 +15,7 @@ "cropperjs": "^1.5.11", "echarts": "^5.3.3", "element-plus": "^2.2.9", + "jsencrypt": "^3.2.1", "jsoneditor": "^9.9.0", "lodash": "^4.17.21", "mitt": "^3.0.0", @@ -24,7 +25,7 @@ "sql-formatter": "^7.0.3", "vue": "^3.2.37", "vue-clipboard3": "^1.0.1", - "vue-router": "^4.0.16", + "vue-router": "^4.1.2", "vuex": "^4.0.2", "xterm": "^4.19.0", "xterm-addon-fit": "^0.5.0" @@ -1880,6 +1881,11 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsencrypt": { + "version": "3.2.1", + "resolved": "https://registry.npmmirror.com/jsencrypt/-/jsencrypt-3.2.1.tgz", + "integrity": "sha512-k1sD5QV0KPn+D8uG9AdGzTQuamt82QZ3A3l6f7TRwMU6Oi2Vg0BsL+wZIQBONcraO1pc78ExMdvmBBJ8WhNYUA==" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npm.taobao.org/json-schema-traverse/download/json-schema-traverse-0.4.1.tgz", @@ -2931,15 +2937,11 @@ } }, "node_modules/vue-router": { - "version": "4.0.16", - "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.0.16.tgz", - "integrity": "sha512-JcO7cb8QJLBWE+DfxGUL3xUDOae/8nhM1KVdnudadTAORbuxIC/xAydC5Zr/VLHUDQi1ppuTF5/rjBGzgzrJNA==", - "license": "MIT", + "version": "4.1.2", + "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.1.2.tgz", + "integrity": "sha512-5BP1qXFncVRwgV/XnqzsKApdMjQPqWIpoUBdL1ynz8HyLxIX/UDAx7Ql2BjmA5CXT/p61JfZvkpiFWFpaqcfag==", "dependencies": { - "@vue/devtools-api": "^6.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/posva" + "@vue/devtools-api": "^6.1.4" }, "peerDependencies": { "vue": "^3.2.0" @@ -4358,6 +4360,11 @@ "argparse": "^2.0.1" } }, + "jsencrypt": { + "version": "3.2.1", + "resolved": "https://registry.npmmirror.com/jsencrypt/-/jsencrypt-3.2.1.tgz", + "integrity": "sha512-k1sD5QV0KPn+D8uG9AdGzTQuamt82QZ3A3l6f7TRwMU6Oi2Vg0BsL+wZIQBONcraO1pc78ExMdvmBBJ8WhNYUA==" + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npm.taobao.org/json-schema-traverse/download/json-schema-traverse-0.4.1.tgz", @@ -5044,11 +5051,11 @@ } }, "vue-router": { - "version": "4.0.16", - "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.0.16.tgz", - "integrity": "sha512-JcO7cb8QJLBWE+DfxGUL3xUDOae/8nhM1KVdnudadTAORbuxIC/xAydC5Zr/VLHUDQi1ppuTF5/rjBGzgzrJNA==", + "version": "4.1.2", + "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.1.2.tgz", + "integrity": "sha512-5BP1qXFncVRwgV/XnqzsKApdMjQPqWIpoUBdL1ynz8HyLxIX/UDAx7Ql2BjmA5CXT/p61JfZvkpiFWFpaqcfag==", "requires": { - "@vue/devtools-api": "^6.0.0" + "@vue/devtools-api": "^6.1.4" } }, "vuex": { diff --git a/mayfly_go_web/src/views/ops/db/DbEdit.vue b/mayfly_go_web/src/views/ops/db/DbEdit.vue index 7c27ce30..253ff9a9 100644 --- a/mayfly_go_web/src/views/ops/db/DbEdit.vue +++ b/mayfly_go_web/src/views/ops/db/DbEdit.vue @@ -23,10 +23,13 @@ - - - - + + + + : + + + @@ -68,26 +71,22 @@ + 添加数据库 - - - - - - - - - - - - - - + + + + + 机器: + + + + + + @@ -105,6 +104,7 @@ import { toRefs, reactive, nextTick, watch, defineComponent, ref } from 'vue'; import { dbApi } from './api'; import { projectApi } from '../project/api.ts'; +import { machineApi } from '../machine/api.ts'; import { ElMessage } from 'element-plus'; import type { ElInput } from 'element-plus'; import { notBlank } from '@/common/assert'; @@ -135,6 +135,7 @@ export default defineComponent({ projects: [], envs: [], databaseList: [] as any, + sshTunnelMachineList: [], inputDbVisible: false, inputDbValue: '', form: { @@ -149,11 +150,8 @@ export default defineComponent({ projectId: null, envId: null, env: null, - enable_ssh: null, - ssh_host: null, - ssh_user: null, - ssh_pass: null, - ssh_port: 22, + enableSshTunnel: null, + sshTunnelMachineId: null, }, btnLoading: false, rules: { @@ -188,14 +186,7 @@ export default defineComponent({ host: [ { required: true, - message: '请输入主机ip', - trigger: ['change', 'blur'], - }, - ], - port: [ - { - required: true, - message: '请输入端口', + message: '请输入主机ip和port', trigger: ['change', 'blur'], }, ], @@ -217,6 +208,10 @@ export default defineComponent({ }); watch(props, (newValue) => { + state.dialogVisible = newValue.visible; + if (!state.dialogVisible) { + return; + } state.projects = newValue.projects; if (newValue.db) { getEnvs(newValue.db.projectId); @@ -225,10 +220,10 @@ export default defineComponent({ state.databaseList = newValue.db.database.split(' '); } else { state.envs = []; - state.form = { port: 3306 } as any; + state.form = { port: 3306, enableSshTunnel: -1 } as any; state.databaseList = []; } - state.dialogVisible = newValue.visible; + getSshTunnelMachines(); }); const handleClose = (db: string) => { @@ -259,6 +254,13 @@ export default defineComponent({ state.form.database = state.databaseList.length == 0 ? '' : state.databaseList.join(' '); }; + const getSshTunnelMachines = async () => { + if (state.form.enableSshTunnel == 1 && state.sshTunnelMachineList.length == 0) { + const res = await machineApi.list.request({ pageNum: 1, pageSize: 100 }); + state.sshTunnelMachineList = res.list; + } + }; + const getEnvs = async (projectId: any) => { state.envs = await projectApi.projectEnvs.request({ projectId }); }; @@ -291,7 +293,7 @@ export default defineComponent({ if (valid) { const reqForm = { ...state.form }; reqForm.password = await RsaEncrypt(reqForm.password); - reqForm.ssh_pass = await RsaEncrypt(reqForm.ssh_pass); + // reqForm.ssh_pass = await RsaEncrypt(reqForm.ssh_pass); dbApi.saveDb.request(reqForm).then(() => { ElMessage.success('保存成功'); emit('val-change', state.form); @@ -330,6 +332,7 @@ export default defineComponent({ handleClose, showInputDb, handleInputDbConfirm, + getSshTunnelMachines, changeProject, changeEnv, btnOk, diff --git a/mayfly_go_web/src/views/ops/machine/MachineEdit.vue b/mayfly_go_web/src/views/ops/machine/MachineEdit.vue index 5ec30aaf..7741cbed 100644 --- a/mayfly_go_web/src/views/ops/machine/MachineEdit.vue +++ b/mayfly_go_web/src/views/ops/machine/MachineEdit.vue @@ -11,15 +11,24 @@ - - - - + + + + : + + + - + + + + + + + + + + @@ -76,9 +88,10 @@ export default defineComponent({ projectId: null, projectName: null, name: null, + authMethod: 1, port: 22, - username: "", - password: "", + username: '', + password: '', remark: '', }, btnLoading: false, @@ -107,14 +120,7 @@ export default defineComponent({ ip: [ { required: true, - message: '请输入主机ip', - trigger: ['change', 'blur'], - }, - ], - port: [ - { - required: true, - message: '请输入端口', + message: '请输入主机ip和端口', trigger: ['change', 'blur'], }, ], @@ -125,16 +131,26 @@ export default defineComponent({ trigger: ['change', 'blur'], }, ], + authMethod: [ + { + required: true, + message: '请选择认证方式', + trigger: ['change', 'blur'], + }, + ], }, }); watch(props, async (newValue) => { state.dialogVisible = newValue.visible; + if (!state.dialogVisible) { + return; + } state.projects = newValue.projects; if (newValue.machine) { state.form = { ...newValue.machine }; } else { - state.form = { port: 22 } as any; + state.form = { port: 22, authMethod: 1 } as any; } }); @@ -153,17 +169,18 @@ export default defineComponent({ machineForm.value.validate(async (valid: boolean) => { if (valid) { const reqForm = { ...state.form }; - reqForm.password = await RsaEncrypt(state.form.password); - machineApi.saveMachine.request(reqForm).then(() => { + if (reqForm.authMethod == 1) { + reqForm.password = await RsaEncrypt(state.form.password); + } + state.btnLoading = true; + try { + await machineApi.saveMachine.request(reqForm); ElMessage.success('保存成功'); emit('val-change', state.form); - state.btnLoading = true; - setTimeout(() => { - state.btnLoading = false; - }, 1000); - cancel(); - }); + } finally { + state.btnLoading = false; + } } else { ElMessage.error('请正确填写信息'); return false; diff --git a/mayfly_go_web/src/views/ops/machine/MachineList.vue b/mayfly_go_web/src/views/ops/machine/MachineList.vue index daea12db..29ec0ba8 100644 --- a/mayfly_go_web/src/views/ops/machine/MachineList.vue +++ b/mayfly_go_web/src/views/ops/machine/MachineList.vue @@ -260,13 +260,13 @@ export default defineComponent({ search(); }; - const openFormDialog = (redis: any) => { + const openFormDialog = (machine: any) => { let dialogTitle; - if (redis) { + if (machine) { state.machineEditDialog.data = state.currentData as any; dialogTitle = '编辑机器'; } else { - state.machineEditDialog.data = { port: 22 } as any; + state.machineEditDialog.data = null; dialogTitle = '添加机器'; } diff --git a/mayfly_go_web/src/views/ops/mongo/MongoEdit.vue b/mayfly_go_web/src/views/ops/mongo/MongoEdit.vue index ce38a7bc..facca3ed 100644 --- a/mayfly_go_web/src/views/ops/mongo/MongoEdit.vue +++ b/mayfly_go_web/src/views/ops/mongo/MongoEdit.vue @@ -1,7 +1,7 @@