SysUpdate.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. <template>
  2. <el-container>
  3. <el-header height="220">
  4. <h3>系统更新</h3>
  5. <el-row style="margin-top: 10px">
  6. <span>节点类型</span>
  7. <el-select
  8. v-model="queryInfo.nodeType"
  9. size="mini"
  10. placeholder="节点类型"
  11. style="margin-left: 5px"
  12. @change="onSelectChange"
  13. >
  14. <el-option label="mgr" value="mgr" />
  15. <el-option label="agent" value="agent" />
  16. </el-select>
  17. <el-button size="mini" type="warning" icon="el-icon-files" style="margin-left: 5px" @click="handleAgentConfig">节点配置列表</el-button>
  18. <el-button size="mini" type="warning" icon="el-icon-refresh" style="margin-left: 5px" @click="getData">刷新</el-button>
  19. <el-button size="mini" type="warning" icon="el-icon-plus" style="margin-left: 5px" @click="handleAdd">添加节点</el-button>
  20. <el-button size="mini" type="warning" icon="el-icon-upload" style="margin-left: 5px" @click="handleUpdate">更新</el-button>
  21. </el-row>
  22. </el-header>
  23. <el-main>
  24. <el-row>
  25. <el-col style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px">
  26. <el-table
  27. :data="dataList"
  28. border
  29. height="480"
  30. style="width: 100%"
  31. >
  32. <el-table-column
  33. prop="nodeType"
  34. label="节点类型"
  35. />
  36. <el-table-column
  37. prop="host"
  38. label="部署的机器地址"
  39. />
  40. <el-table-column
  41. prop="appDir"
  42. label="应用目录"
  43. />
  44. <el-table-column
  45. prop="config"
  46. label="配置"
  47. >
  48. <template slot-scope="scope">
  49. <el-button
  50. style="margin-top: 5px; margin-left: 5px"
  51. size="mini"
  52. type="success"
  53. @click="handleShowConfig(scope.$index, scope.row)"
  54. >查看</el-button>
  55. </template>
  56. </el-table-column>
  57. <el-table-column
  58. prop="appVersion"
  59. label="应用版本"
  60. />
  61. <el-table-column
  62. prop="updateTime"
  63. label="更新时间"
  64. />
  65. <el-table-column
  66. fixed="right"
  67. label="操作"
  68. width="120"
  69. >
  70. <template slot-scope="scope">
  71. <el-button
  72. style="margin-top: 5px; margin-left: 5px"
  73. size="mini"
  74. type="danger"
  75. @click="handleDelete(scope.$index, scope.row)"
  76. >删除</el-button>
  77. </template>
  78. </el-table-column>
  79. </el-table>
  80. </el-col>
  81. </el-row>
  82. </el-main>
  83. <el-dialog
  84. title="添加节点"
  85. append-to-body
  86. :visible.sync="showAddDialog"
  87. width="50%"
  88. center
  89. >
  90. <div>
  91. <el-form :model="addForm" label-width="80px">
  92. <el-form-item label="节点类型" style="width: 70%; padding-right: 2px">
  93. <el-input v-model="queryInfo.nodeType" style="width: 70%; padding-right: 2px" readonly />
  94. </el-form-item>
  95. <el-form-item label="部署的机器地址">
  96. <el-input v-model="addForm.host" style="width: 70%; padding-right: 2px" />
  97. </el-form-item>
  98. <el-form-item label="SSH 端口">
  99. <el-input v-model="addForm.port" style="width: 70%; padding-right: 2px" />
  100. </el-form-item>
  101. <el-form-item label="认证方式" style="width: 70%; padding-right: 2px">
  102. <el-select v-model="addForm.authType" placeholder="选择认证方式">
  103. <el-option label="密码认证" value="password" />
  104. <el-option label="私钥认证" value="privateKey" />
  105. </el-select>
  106. </el-form-item>
  107. <el-form-item label="用户名" style="width: 70%; padding-right: 2px">
  108. <el-input v-model="addForm.username" style="width: 70%; padding-right: 2px" />
  109. </el-form-item>
  110. <el-form-item v-if="addForm.authType === 'password'" label="密码" style="width: 70%; padding-right: 2px">
  111. <el-input v-model="addForm.password" style="width: 70%; padding-right: 2px" />
  112. </el-form-item>
  113. <el-form-item v-else label="私钥" style="width: 70%; padding-right: 2px">
  114. <el-input
  115. v-model="addForm.privateKey"
  116. type="textarea"
  117. maxlength="10000"
  118. :rows="10"
  119. style="padding: 5px"
  120. />
  121. </el-form-item>
  122. <el-form-item label="应用目录">
  123. <el-input v-model="addForm.appDir" style="width: 70%; padding-right: 2px" />
  124. </el-form-item>
  125. <div v-if="queryInfo.nodeType === 'agent'">
  126. <el-form-item label="连接的 mgr 地址" style="width: 70%; padding-right: 2px">
  127. <el-select v-model="addForm.remoteAgentConfig" placeholder="选择 mgr 地址">
  128. <el-option
  129. v-for="(item, index) in agentConfigList"
  130. :key="index"
  131. :label="item.mgrHost"
  132. :value="item.id"
  133. />
  134. </el-select>
  135. </el-form-item>
  136. </div>
  137. <div v-else>
  138. <el-form-item label="mgr 配置" style="width: 70%; padding-right: 2px">
  139. <el-select v-model="addForm.remoteAgentConfig" placeholder="选择 mgr 配置">
  140. <el-option
  141. v-for="(item, index) in agentConfigList"
  142. :key="index"
  143. :label="item.id"
  144. :value="item.id"
  145. />
  146. </el-select>
  147. </el-form-item>
  148. </div>
  149. <el-form-item>
  150. <el-button type="primary" @click="onAdd">确定</el-button>
  151. </el-form-item>
  152. </el-form>
  153. </div>
  154. </el-dialog>
  155. <el-dialog
  156. title="节点配置列表"
  157. append-to-body
  158. :visible.sync="showAgentConfigDialog"
  159. center
  160. >
  161. <template>
  162. <el-button size="mini" type="warning" icon="el-icon-plus" style="margin: 5px" @click="handleAgentConfigAdd">添加</el-button>
  163. <el-table
  164. :data="agentConfigList"
  165. border
  166. height="480"
  167. style="width: 100%"
  168. >
  169. <el-table-column
  170. prop="id"
  171. label="ID"
  172. />
  173. <el-table-column
  174. prop="nodeType"
  175. label="节点类型"
  176. />
  177. <el-table-column
  178. prop="mgrProtocol"
  179. label="协议"
  180. />
  181. <el-table-column
  182. prop="mgrHost"
  183. label="mgr 地址"
  184. />
  185. <el-table-column
  186. prop="mgrPort"
  187. label="mgr 端口"
  188. />
  189. <el-table-column
  190. prop="mgrConfig"
  191. label="mgr 配置"
  192. />
  193. <el-table-column
  194. fixed="right"
  195. label="操作"
  196. width="120"
  197. >
  198. <template slot-scope="scope">
  199. <el-button
  200. style="margin-top: 5px; margin-left: 5px"
  201. size="mini"
  202. type="danger"
  203. @click="handleAgentConfigDelete(scope.$index, scope.row)"
  204. >删除</el-button>
  205. </template>
  206. </el-table-column>
  207. </el-table>
  208. </template>
  209. </el-dialog>
  210. <el-dialog
  211. title="添加节点配置"
  212. append-to-body
  213. :visible.sync="addAgentConfigDialog"
  214. center
  215. >
  216. <template>
  217. <el-form :model="configForm" label-width="80px">
  218. <el-form-item label="节点类型" style="width: 70%; padding-right: 2px">
  219. <el-input v-model="queryInfo.nodeType" style="width: 70%; padding-right: 2px" />
  220. </el-form-item>
  221. <div v-if="queryInfo.nodeType === 'agent'">
  222. <el-form-item label="mgr 协议" style="width: 70%; padding-right: 2px">
  223. <el-select v-model="configForm.mgrProtocol" placeholder="选择 websocket 协议">
  224. <el-option label="ws" value="ws" />
  225. <el-option label="wss" value="wss" />
  226. </el-select>
  227. </el-form-item>
  228. <el-form-item label="mgr 地址" style="width: 70%; padding-right: 2px">
  229. <el-input v-model="configForm.mgrHost" style="width: 70%; padding-right: 2px" />
  230. </el-form-item>
  231. <el-form-item label="mgr 端口" style="width: 70%; padding-right: 2px">
  232. <el-input v-model="configForm.mgrPort" style="width: 70%; padding-right: 2px" />
  233. </el-form-item>
  234. </div>
  235. <div v-else>
  236. <el-form-item label="mgr 配置" style="width: 70%; padding-right: 2px">
  237. <el-input
  238. v-model="configForm.mgrConfig"
  239. type="textarea"
  240. maxlength="10000"
  241. :rows="10"
  242. style="padding: 5px"
  243. />
  244. </el-form-item>
  245. </div>
  246. <el-form-item>
  247. <el-button type="primary" @click="onAgentConfigAdd">确定</el-button>
  248. </el-form-item>
  249. </el-form>
  250. </template>
  251. </el-dialog>
  252. <el-dialog
  253. :title="title"
  254. append-to-body
  255. :visible.sync="showConfigDialog"
  256. center
  257. >
  258. <template>
  259. <span v-if="queryInfo.nodeType === 'agent'">
  260. <el-form :model="configForm" label-width="80px">
  261. <el-form-item label="mgr 协议" style="width: 70%; padding-right: 2px">
  262. <el-input v-model="configForm.mgrProtocol" style="width: 70%; padding-right: 2px" readonly />
  263. </el-form-item>
  264. <el-form-item label="mgr 地址" style="width: 70%; padding-right: 2px">
  265. <el-input v-model="configForm.mgrHost" style="width: 70%; padding-right: 2px" readonly />
  266. </el-form-item>
  267. <el-form-item label="mgr 端口" style="width: 70%; padding-right: 2px">
  268. <el-input v-model="configForm.mgrPort" style="width: 70%; padding-right: 2px" readonly />
  269. </el-form-item>
  270. </el-form>
  271. </span>
  272. <span v-else>
  273. <el-form>
  274. <el-form-item style="width: 70%; padding-right: 2px">
  275. <el-input
  276. v-model="configForm.mgrConfig"
  277. type="textarea"
  278. maxlength="10000"
  279. :rows="10"
  280. style="padding: 5px"
  281. readonly
  282. />
  283. </el-form-item>
  284. </el-form>
  285. </span>
  286. </template>
  287. </el-dialog>
  288. </el-container>
  289. </template>
  290. <script>
  291. import {
  292. addAgentConfig,
  293. addRemoteHost, deleteAgentConfig,
  294. deleteRemoteHost,
  295. getAgentConfigList,
  296. getRemoteHostList,
  297. updateRemoteApp
  298. } from '@/api/devops'
  299. export default {
  300. name: 'SysUpdate',
  301. data() {
  302. return {
  303. queryInfo: {
  304. nodeType: 'agent'
  305. },
  306. dataList: [],
  307. // **********************************************************************
  308. showAddDialog: false,
  309. addForm: {
  310. nodeType: 'agent',
  311. host: '',
  312. port: 22,
  313. authType: 'password',
  314. username: 'root',
  315. password: '',
  316. privateKey: '',
  317. appDir: '/opt/app/devops',
  318. remoteAgentConfig: null
  319. },
  320. // **********************************************************************
  321. showAgentConfigDialog: false,
  322. agentConfigList: [],
  323. addAgentConfigDialog: false,
  324. configForm: {
  325. nodeType: '',
  326. mgrProtocol: 'ws',
  327. mgrHost: '127.0.0.1',
  328. mgrPort: 4030,
  329. mgrConfig: ''
  330. },
  331. // **********************************************************************
  332. showConfigDialog: false,
  333. title: ' 节点配置',
  334. mgrConfig: ''
  335. }
  336. },
  337. created() {
  338. document.title = '系统更新'
  339. this.getData()
  340. },
  341. methods: {
  342. getData() {
  343. this.dataList = []
  344. getRemoteHostList(this.queryInfo).then(resp => {
  345. if (resp.code === 0) {
  346. this.dataList = resp.data
  347. } else {
  348. this.$message.warning(resp.msg)
  349. }
  350. }).catch(error => {
  351. this.$message.error(error.message)
  352. })
  353. },
  354. onSelectChange() {
  355. this.getData()
  356. },
  357. handleAdd() {
  358. getAgentConfigList(this.queryInfo).then(resp => {
  359. if (resp.code === 0) {
  360. this.agentConfigList = resp.data
  361. this.showAddDialog = true
  362. } else {
  363. this.$message.warning(resp.msg)
  364. }
  365. }).catch(error => {
  366. this.$message.error(error.message)
  367. })
  368. },
  369. onAdd() {
  370. this.addForm.nodeType = this.queryInfo.nodeType
  371. addRemoteHost(this.addForm).then(resp => {
  372. if (resp.code === 0) {
  373. this.getData()
  374. } else {
  375. this.$message.warning(resp.msg)
  376. }
  377. }).catch(error => {
  378. this.$message.error(error.message)
  379. }).finally(() => {
  380. this.showAddDialog = false
  381. })
  382. },
  383. handleDelete(index, row) {
  384. const form = {}
  385. form.id = row.id
  386. deleteRemoteHost(form).then(resp => {
  387. if (resp.code === 0) {
  388. this.getData()
  389. } else {
  390. this.$message.warning(resp.msg)
  391. }
  392. }).catch(error => {
  393. this.$message.error(error.message)
  394. })
  395. },
  396. handleUpdate() {
  397. const hostList = []
  398. for (const item of this.dataList) {
  399. hostList.push(item.host)
  400. }
  401. this.$confirm('确定要更新所有机器上的 ' + this.queryInfo.nodeType + '?', '提示', {
  402. confirmButtonText: '确定',
  403. cancelButtonText: '取消',
  404. type: 'warning'
  405. }).then(() => {
  406. const form = {}
  407. form.hostList = hostList
  408. updateRemoteApp(form).then(resp => {
  409. this.$message.warning(resp.msg)
  410. }).catch(error => {
  411. this.$message.error(error.message)
  412. })
  413. }).catch(() => {
  414. this.$message({
  415. type: 'info',
  416. message: '已取消'
  417. })
  418. }).finally(() => {
  419. this.loading = false
  420. })
  421. },
  422. handleAgentConfig() {
  423. getAgentConfigList(this.queryInfo).then(resp => {
  424. if (resp.code === 0) {
  425. this.agentConfigList = resp.data
  426. this.showAgentConfigDialog = true
  427. } else {
  428. this.$message.warning(resp.msg)
  429. }
  430. }).catch(error => {
  431. this.$message.error(error.message)
  432. })
  433. },
  434. handleAgentConfigAdd() {
  435. this.addAgentConfigDialog = true
  436. },
  437. onAgentConfigAdd() {
  438. this.configForm.nodeType = this.queryInfo.nodeType
  439. addAgentConfig(this.configForm).then(resp => {
  440. if (resp.code === 0) {
  441. this.handleAgentConfig()
  442. } else {
  443. this.$message.warning(resp.msg)
  444. }
  445. }).catch(error => {
  446. this.$message.error(error.message)
  447. }).finally(() => {
  448. this.addAgentConfigDialog = false
  449. })
  450. },
  451. handleAgentConfigDelete(index, row) {
  452. const form = {}
  453. form.id = row.id
  454. deleteAgentConfig(form).then(resp => {
  455. if (resp.code === 0) {
  456. this.handleAgentConfig()
  457. } else {
  458. this.$message.warning(resp.msg)
  459. }
  460. }).catch(error => {
  461. this.$message.error(error.message)
  462. })
  463. },
  464. handleShowConfig(index, row) {
  465. this.configForm = row.remoteAgentConfig
  466. this.title = this.queryInfo.nodeType + ' 节点配置'
  467. this.showConfigDialog = true
  468. }
  469. }
  470. }
  471. </script>
  472. <style>
  473. </style>