Commit c1240313 authored by 黎博's avatar 黎博

提交

parent 70dce501
...@@ -8,3 +8,120 @@ export function getNamespaceList(queryInfo) { ...@@ -8,3 +8,120 @@ export function getNamespaceList(queryInfo) {
params: queryInfo params: queryInfo
}) })
} }
// 获取服务列表
export function getServiceList(queryInfo) {
return request({
url: '/k8s/service/list',
method: 'get',
params: queryInfo
})
}
// 获取单个类型下的所有项目
export function getSingleTypeApp(queryInfo) {
return request({
url: '/k8s/getSingleTypeApp',
method: 'get',
params: queryInfo
})
}
// 获取镜像列表
export function getImageList(queryInfo) {
return request({
url: '/k8s/image/list',
method: 'get',
params: queryInfo
})
}
// 创建服务
export function createK8sService(data) {
return request({
url: '/k8s/service/create',
method: 'post',
data
})
}
// 获取k8s服务详情
export function getServiceDetail(queryInfo) {
return request({
url: '/k8s/service/detail',
method: 'get',
params: queryInfo
})
}
// 重置服务
export function serviceRedeploy(data) {
return request({
url: '/k8s/service/redeploy',
method: 'post',
data
})
}
// 更新部署
export function serviceModify(data) {
return request({
url: '/k8s/service/modify',
method: 'post',
data
})
}
// 删除服务
export function serviceDelete(data) {
return request({
url: '/k8s/service/delete',
method: 'post',
data
})
}
// 根据类型将docker项目分类
export function getDockerProjectType(queryInfo) {
return request({
url: '/docker/project/type',
method: 'get',
params: queryInfo
})
}
// 获取项目配置列表
export function getDockerProjectList(queryInfo) {
return request({
url: '/docker/project/list',
method: 'get',
params: queryInfo
})
}
// 新增项目
export function addDockerProject(data) {
return request({
url: '/docker/project/add',
method: 'post',
data
})
}
// 编辑项目
export function updateDockerProject(data) {
return request({
url: '/docker/project/edit',
method: 'post',
data
})
}
// 获取项目配置详情
export function getDockerProjectDetail(queryInfo) {
return request({
url: '/docker/project/detail',
method: 'get',
params: queryInfo
})
}
...@@ -55,7 +55,9 @@ import { ...@@ -55,7 +55,9 @@ import {
DropdownItem, DropdownItem,
DropdownMenu, DropdownMenu,
Checkbox, Checkbox,
CheckboxGroup CheckboxGroup,
Popover,
Alert
} from 'element-ui' } from 'element-ui'
Vue.config.productionTip = false Vue.config.productionTip = false
...@@ -109,6 +111,8 @@ Vue.use(DropdownItem) ...@@ -109,6 +111,8 @@ Vue.use(DropdownItem)
Vue.use(DropdownMenu) Vue.use(DropdownMenu)
Vue.use(Checkbox) Vue.use(Checkbox)
Vue.use(CheckboxGroup) Vue.use(CheckboxGroup)
Vue.use(Popover)
Vue.use(Alert)
// Vue.use(Sortable) // Vue.use(Sortable)
/* eslint-disable no-new */ /* eslint-disable no-new */
new Vue({ new Vue({
......
...@@ -40,6 +40,10 @@ import role from '../views/user/role' ...@@ -40,6 +40,10 @@ import role from '../views/user/role'
import permission from '../views/user/permission' import permission from '../views/user/permission'
// 添加发送短信功能(2021-08-16) // 添加发送短信功能(2021-08-16)
import sendMessage from '../views/effect/SendMessage' import sendMessage from '../views/effect/SendMessage'
import TestEnv from '../views/docker/TestEnv'
import DevEnv from '../views/docker/DevEnv'
import EnvDetail from '../views/docker/EnvDetail'
import ProConfig from '../views/docker/ProConfig'
const originalPush = Router.prototype.push const originalPush = Router.prototype.push
Router.prototype.push = function push(location) { Router.prototype.push = function push(location) {
...@@ -216,6 +220,26 @@ const router = new Router({ ...@@ -216,6 +220,26 @@ const router = new Router({
path: '/effect/msg', path: '/effect/msg',
name: sendMessage, name: sendMessage,
component: sendMessage component: sendMessage
},
{
path: '/docker/TestEnv',
name: 'docker测试环境',
component: TestEnv
},
{
path: '/docker/DevEnv',
name: 'docker开发环境',
component: DevEnv
},
{
path: '/docker/env',
name: 'docker详情页',
component: EnvDetail
},
{
path: '/docker/ProConfig',
name: '项目配置管理',
component: ProConfig
} }
] ]
} }
......
...@@ -50,7 +50,12 @@ export default { ...@@ -50,7 +50,12 @@ export default {
return index + 1 return index + 1
}, },
// 跳转到详情页面 // 跳转到详情页面
jumpToDetail() {}, jumpToDetail(name) {
window.sessionStorage.setItem('env', name)
this.$router.push({
path: `/docker/env`
})
},
syncMySQL() {} syncMySQL() {}
}, },
created() { created() {
......
<template> <template>
<div> <div>
<div style="padding:5px 20px;height: 30px;">
<div style="float:right;font-size:13px">
<span>自动刷新</span>
<el-switch v-model="timer" @change="refreshInterval" />
<span class="link-type" style="margin-left:20px" @click="openConf()">遇到问题?</span>
</div>
</div>
<el-alert v-show="notify.length>0" type="info" style=" font-size: 14px;" show-icon>
<slot name="description">
<p v-for="item in notify" :key="item._id">{{ item.content }}</p>
</slot>
</el-alert>
<div class="shadow-content" style="margin-top:20px"> <div class="shadow-content" style="margin-top:20px">
<div class="warn-content"> <div class="warn-content">
<svg-icon icon-class="service" /> <i class="el-icon-menu"></i>
基础服务 基础服务
<div style="float: right;"> <div style="float: right;">
<el-button type="warning" size="mini" round @click="getRepository('base')">新增服务</el-button> <el-button type="warning" size="mini" round @click="getRepository('base')">新增服务</el-button>
...@@ -34,10 +21,10 @@ ...@@ -34,10 +21,10 @@
</div> </div>
</div> </div>
<el-table :data="FormatTabledata.base" :header-cell-style="{background:'#F3F4F7',color:'#555'}" size="medium" align="center" style="width: 100%"> <el-table :data="FormatTabledata.base" :header-cell-style="{background:'#F3F4F7',color:'#555'}" size="medium" align="center" style="width: 100%">
<el-table-column :index="indexMethod" type="index" /> <el-table-column :index="indexMethod" type="index" label="#" />
<el-table-column v-if="serviceName!=='rabbitmq'" label="服务名"> <el-table-column v-if="serviceName!=='rabbitmq'" label="服务名">
<template slot-scope="scope"> <template slot-scope="scope">
<i v-if="scope.row.status == 'Normal'" class="el-icon-success" style="color: #67c23a" /> <i v-if="scope.row.status === 'Normal'" class="el-icon-success" style="color: #67c23a" />
<i v-else class="el-icon-error" style="color: #f56c6c" /> <i v-else class="el-icon-error" style="color: #f56c6c" />
<span v-if="scope.row.serviceName === 'consul'"> <span v-if="scope.row.serviceName === 'consul'">
...@@ -89,13 +76,19 @@ ...@@ -89,13 +76,19 @@
</el-table-column> </el-table-column>
<el-table-column prop="image" label="镜像"> <el-table-column prop="image" label="镜像">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.image | formatImages }} {{ scope.row.image.split('/')[2] }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="createdAt" width="120" label="创建时间" /> <el-table-column prop="createdAt" width="120" label="创建时间" />
<el-table-column prop="status" width="100" label="运行状态"> <el-table-column prop="status" width="100" label="运行状态">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.status | formatStatus }} <el-tag type="success" v-if="scope.row.status === 'Normal'">正常</el-tag>
<el-tag type="warning" v-else-if="scope.row.status === 'Pending'">Pod等待中</el-tag>
<el-tag v-else-if="scope.row.status === 'Waiting'">服务启动中</el-tag>
<el-tag v-else-if="scope.row.status === 'PodScheduling'">Pod调度中</el-tag>
<el-tag v-else-if="scope.row.status === 'ContainerCreating'">容器创建中</el-tag>
<el-tag type="danger" v-else-if="scope.row.status === 'Terminating'">删除中</el-tag>
<el-tag type="info" v-else>未知状态</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" width="80" fixed="right"> <el-table-column label="操作" width="80" fixed="right">
...@@ -106,19 +99,15 @@ ...@@ -106,19 +99,15 @@
</el-button> </el-button>
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native="getServiceDetails(scope.row)"> <el-dropdown-item @click.native="getServiceDetails(scope.row)">
<svg-icon icon-class="detail" /> <i class="el-icon-document"></i>
详细信息 详细信息
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item @click.native="restartService(scope.row)"> <el-dropdown-item @click.native="restartService(scope.row)">
<svg-icon icon-class="restart" /> <i class="el-icon-refresh"></i>
重置服务 重置服务
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item @click.native="updateDeploy(scope.row)"> <el-dropdown-item style="color: red" @click.native="deleteService(scope.row) ">
<svg-icon icon-class="f5" /> <i class="el-icon-delete"></i>
更新部署
</el-dropdown-item>
<el-dropdown-item v-permission="['admin']" style="color: red" @click.native="deleteService(scope.row) ">
<svg-icon icon-class="delete" />
删除服务 删除服务
</el-dropdown-item> </el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
...@@ -127,39 +116,45 @@ ...@@ -127,39 +116,45 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
</div> </div>
<!-- 业务服务 -->
<div v-for="(item,index) in typeList" :key="index" class="shadow-content"> <div v-for="(item,index) in typeList" :key="index" class="shadow-content">
<div class="warn-content"> <div class="warn-content">
<svg-icon icon-class="service" /> <i class="el-icon-menu"></i>
{{ item._id.toUpperCase() }} 服务 {{ item.projectType.toUpperCase() }} 服务
<div style="float: right"> <div style="float: right">
<el-button type="primary" size="mini" round @click="deployMaster(FormatTabledata[item._id])">一键部署master</el-button> <el-button type="warning" size="mini" round @click="getRepository(item.projectType)">新增服务</el-button>
<el-button type="warning" size="mini" round @click="getRepository(item._id)">新增服务</el-button>
<el-button type="success" size="mini" round @click="refresh">刷新状态</el-button> <el-button type="success" size="mini" round @click="refresh">刷新状态</el-button>
<el-button type="danger" size="mini" round @click="restartAll(FormatTabledata[item._id])">重置所有服务</el-button>
</div> </div>
</div> </div>
<el-table :data="FormatTabledata[item._id]" :header-cell-style="{background:'#F3F4F7',color:'#555'}" size="medium" align="center" style="width: 100%"> <el-table :data="FormatTabledata[item.projectType]" :header-cell-style="{background:'#F3F4F7',color:'#555'}" size="medium" align="center" style="width: 100%">
<el-table-column :index="indexMethod" type="index" /> <el-table-column :index="indexMethod" label="#" type="index" />
<el-table-column prop="serviceName" label="服务名"> <el-table-column prop="serviceName" label="服务名">
<template slot-scope="scope"> <template slot-scope="scope">
<i v-if="scope.row.status == 'Normal'" class="el-icon-success" style="color: #67c23a" /> <i v-if="scope.row.status === 'Normal'" class="el-icon-success" style="color: #67c23a" />
<i v-else class="el-icon-error" style="color: #f56c6c" /> <i v-else class="el-icon-error" style="color: #f56c6c" />
<span class="link-type" @click="handleDetail(scope.row)">{{ scope.row.serviceName }}</span> <span class="link-type" @click="handleDetail(scope.row)">{{ scope.row.serviceName }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="image" label="镜像"> <el-table-column prop="image" label="镜像">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.image | filterTag }} {{ scope.row.image.split(':')[1] }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="createdAt" width="120" label="创建时间" /> <el-table-column prop="createdAt" width="160" label="创建时间" />
<el-table-column prop="status" width="100" label="运行状态"> <el-table-column prop="status" width="140" label="运行状态">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.status | formatStatus }} <el-tag type="success" v-if="scope.row.status === 'Normal'">正常</el-tag>
<el-tag type="warning" v-else-if="scope.row.status === 'Pending'">Pod等待中</el-tag>
<el-tag v-else-if="scope.row.status === 'Waiting'">服务启动中</el-tag>
<el-tag v-else-if="scope.row.status === 'PodScheduling'">Pod调度中</el-tag>
<el-tag v-else-if="scope.row.status === 'ContainerCreating'">容器创建中</el-tag>
<el-tag type="danger" v-else-if="scope.row.status === 'Terminating'">删除中</el-tag>
<el-tag type="info" v-else>未知状态</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column v-if="item._id==='java'" show-overflow-tooltip width="90" label="Mock"> <el-table-column v-if="item.projectType==='java'" show-overflow-tooltip width="60" label="Mock">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tooltip v-show="scope.row.labels.mock==='1'" placement="top"> <el-tooltip v-show="scope.row.labels.mock==='1'" placement="top">
<div slot="content">使用apollo集群k8s-mock进行启动</div> <div slot="content">使用apollo集群k8s-mock进行启动</div>
...@@ -168,7 +163,7 @@ ...@@ -168,7 +163,7 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column v-if="item._id==='java'" width="150" label="调试"> <el-table-column v-if="item.projectType==='java'" width="150" label="调试">
<template slot-scope="scope"> <template slot-scope="scope">
<span v-if="scope.row.serviceType==='NodePort'">{{ scope.row.lanIp }}:{{ scope.row.portMappings[1].nodePort }}</span> <span v-if="scope.row.serviceType==='NodePort'">{{ scope.row.lanIp }}:{{ scope.row.portMappings[1].nodePort }}</span>
</template> </template>
...@@ -195,46 +190,39 @@ ...@@ -195,46 +190,39 @@
</el-button> </el-button>
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native="getServiceDetails(scope.row)"> <el-dropdown-item @click.native="getServiceDetails(scope.row)">
<svg-icon icon-class="detail" /> <i class="el-icon-document"></i>
详细信息 详细信息
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item @click.native="updateService(scope.row)"> <el-dropdown-item @click.native="openUpdateServiceDialog(scope.row)">
<svg-icon icon-class="f5" /> <i class="el-icon-refresh"></i>
更新服务 更新服务
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item @click.native="restartService(scope.row)"> <el-dropdown-item @click.native="restartService(scope.row)">
<svg-icon icon-class="restart" /> <i class="el-icon-refresh"></i>
重置服务 重置服务
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item @click.native="updateDomain(scope.row)">
<svg-icon icon-class="doamin" />
更新域名
</el-dropdown-item>
<el-dropdown-item style="color: red" @click.native="deleteService(scope.row, item) "> <el-dropdown-item style="color: red" @click.native="deleteService(scope.row, item) ">
<svg-icon icon-class="delete" /> <i class="el-icon-delete"></i>
删除服务 删除服务
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item @click.native="updateDeploy(scope.row)">
<svg-icon icon-class="f5" />
更新部署
</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</div> </div>
<!--添加服务dialog--> <!--添加服务dialog-->
<el-dialog :visible.sync="dialogVisible" :title="title"> <el-dialog :visible.sync="dialogVisible" title="添加服务">
<el-alert :closable="false" title="温馨提醒" type="warning" description="该操作会创建这个服务对应的镜像分支。" /> <el-alert :closable="false" title="温馨提醒" type="warning" description="该操作会创建这个服务对应的镜像分支。" />
<p class="title-sub">选择服务</p> <p class="title-sub">选择服务</p>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="14"> <el-col :span="14">
<el-select v-model="reponame" clearable filterable class="elSelect" placeholder="请选择服务,支持模糊搜索" @change="getTag"> <el-select v-model="reponame" clearable filterable class="elSelect" placeholder="请选择服务,支持模糊搜索" @change="getTag">
<el-option v-for="(item,index) in options" :key="index" :label="item.appname.split(':')[0]" :value="item.tag.split(':')[0]" /> <el-option v-for="(item,index) in options" :key="index" :label="item.RepoName.split('/')[1]" :value="item.RepoName" />
</el-select> </el-select>
</el-col> </el-col>
</el-row> </el-row>
...@@ -250,7 +238,7 @@ ...@@ -250,7 +238,7 @@
</el-row> </el-row>
</div> </div>
<div v-permission="['admin']" v-show="is_show"> <div v-show="is_show">
<p class="title-sub">服务名称<span style="font-size: 12px">(创建多个mysql时需要填写此字段)</span></p> <p class="title-sub">服务名称<span style="font-size: 12px">(创建多个mysql时需要填写此字段)</span></p>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="14"> <el-col :span="14">
...@@ -263,7 +251,7 @@ ...@@ -263,7 +251,7 @@
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="14"> <el-col :span="14">
<el-select v-model="tagName" filterable clearable class="elSelect" placeholder="请选择镜像,支持模糊搜索"> <el-select v-model="tagName" filterable clearable class="elSelect" placeholder="请选择镜像,支持模糊搜索">
<el-option v-for="(item,index) in tagOptions" :key="index" :label="item.tagName" :value="item.tagName" /> <el-option v-for="(item,index) in tagOptions" :key="index" :label="item.TagName" :value="item.TagName" />
</el-select> </el-select>
</el-col> </el-col>
</el-row> </el-row>
...@@ -277,25 +265,14 @@ ...@@ -277,25 +265,14 @@
</el-col> </el-col>
</el-row> </el-row>
<div v-show="is_wechat">
<p class="title-sub">是否微信模式<span style="font-size: 12px">(测试微信时选择是)</span></p>
<el-row :gutter="20">
<el-col :span="14">
<el-select v-model="wechat.key" filterable clearable class="elSelect" placeholder="请选择是否微信模式,测试微信时选择是">
<el-option v-for="item in debugOptions" :key="item.key" :label="item.display_name" :value="item.key" />
</el-select>
</el-col>
</el-row>
</div>
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button> <el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="createClusterService">确 定</el-button> <el-button type="primary" @click="createService">确 定</el-button>
</span> </span>
</el-dialog> </el-dialog>
<!--更新服务的弹框--> <!--更新服务的弹框-->
<el-dialog :visible.sync="updateDialog" title="更新服务"> <el-dialog :visible.sync="updateDialogVisible" title="更新服务">
<el-alert :closable="false" title="温馨提醒" type="warning" description="警告:该操作将会更新这个服务为指定版本,在这个pod上做的所有操作将会丢失。" /> <el-alert :closable="false" title="温馨提醒" type="warning" description="警告:该操作将会更新这个服务为指定版本,在这个pod上做的所有操作将会丢失。" />
<p class="title-sub">选择服务</p> <p class="title-sub">选择服务</p>
<el-row :gutter="20"> <el-row :gutter="20">
...@@ -308,42 +285,332 @@ ...@@ -308,42 +285,332 @@
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="14"> <el-col :span="14">
<el-select v-model="tagName" filterable clearable class="elSelect" placeholder="请选择镜像,支持模糊搜索"> <el-select v-model="tagName" filterable clearable class="elSelect" placeholder="请选择镜像,支持模糊搜索">
<el-option v-for="(item,index) in tagOptions" :key="index" :label="item.tagName" :value="item.tagName" /> <el-option v-for="(item,index) in tagOptions" :key="index" :label="item.TagName" :value="item.TagName" />
</el-select> </el-select>
</el-col> </el-col>
</el-row> </el-row>
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
<el-button @click="updateDialog = false">取 消</el-button> <el-button @click="updateDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="updateClusterService()">确 定</el-button> <el-button type="primary" @click="updateService()">确 定</el-button>
</span> </span>
</el-dialog> </el-dialog>
<el-dialog :visible.sync="centerDialogVisible" title="详细信息" height="500px" center> <el-dialog :visible.sync="centerDialogVisible" title="详细信息" height="500px" center>
<div class="editor-container"> <div class="editor-container">
<json-editor ref="jsonEditor" v-model="value" /> <json-viewer :expand-depth=3 :value='detailValue' style="margin-top:-25px"></json-viewer>
</div> </div>
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
<el-button @click="centerDialogVisible = false">取 消</el-button> <el-button @click="centerDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="centerDialogVisible = false">确 定</el-button> <el-button type="primary" @click="centerDialogVisible = false">确 定</el-button>
</span> </span>
</el-dialog> </el-dialog>
<el-dialog :visible.sync="dialogHost" title="更新域名">
<el-form ref="form" :model="form" :rules="rules">
<el-form-item label="域名" prop="host">
<el-input v-model="form.host" autocomplete="off" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogHost=false">取 消</el-button>
<el-button type="primary" @click="submitHost('form')">确 定</el-button>
</div>
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
export default {} import {
getServiceList,
getSingleTypeApp,
getImageList,
createK8sService,
getDockerProjectDetail,
getServiceDetail,
serviceRedeploy,
serviceModify,
serviceDelete,
getDockerProjectType
} from '@/api/k8s'
export default {
data() {
return {
namespace: window.sessionStorage.getItem('env'),
FormatTabledata: [],
moreArray: [],
lostArray: [],
moreShow: false,
lostShow: false,
// 项目类型列表
typeList: [],
dialogVisible: false,
centerDialogVisible: false,
is_mock: false,
is_show: false,
label: '',
updateDialogVisible: false,
reponame: '',
options: [],
mock: {},
server: '',
debug: {},
debugOptions: [
{ key: 1, display_name: '' },
{ key: 0, display_name: '' }
],
tagOptions: [],
tagName: '',
detailValue: {},
// 当前选中的项目名
serviceName: '',
mysqlName: ''
}
},
created() {
this.getServiceList()
getDockerProjectType({}).then((resp) => {
this.typeList = resp.data.data
})
},
methods: {
indexMethod(index) {
return index + 1
},
array2Object(original) {
// 将数组转成对象存储
this.FormatTabledata = {}
original.forEach((item, index) => {
if (Object.keys(this.FormatTabledata).indexOf(item.labels.type) > -1) {
this.FormatTabledata[item.labels.type].push(item)
} else {
this.FormatTabledata[item.labels.type] = []
this.FormatTabledata[item.labels.type].push(item)
}
})
},
// 获取服务列表
getServiceList() {
getServiceList({ namespace: this.namespace }).then((resp) => {
const serviceList = resp.data.data
this.array2Object(serviceList)
})
},
// 刷新,重新获取服务列表
refresh() {
this.getServiceList()
},
// 新增服务,获取服务列表
getRepository(label) {
this.label = label
this.reponame = ''
this.tagName = ''
this.options = []
this.tagOptions = []
this.is_mock = label === 'java'
this.is_show = false
this.debug = { key: 0, display_name: '' }
this.mock = { key: 0, display_name: '' }
getSingleTypeApp({ namespace: 'qa-' + label }).then((resp) => {
this.options = resp.data.data.RepoInfo
})
this.dialogVisible = true
},
// 根据repoName获取镜像列表
getTag() {
getImageList({ repoName: this.reponame }).then((resp) => {
this.tagOptions = resp.data.data.TagInfo
this.tagName = resp.data.data.TagInfo[0].TagName
})
getDockerProjectDetail({ projectName: this.reponame.split('/')[1] }).then(
(resp) => {
this.domain = resp.data.data.hostName
}
)
},
// 同步数据库
syncDb() {},
// 通过Mq
syncMq() {},
// 清空redis
clearRedis() {},
// 获取服务详情
getServiceDetails(service) {
getServiceDetail({
namespace: this.namespace,
serviceType: service.labels.type,
serviceName: service.serviceName
}).then((resp) => {
this.detailValue = resp.data.data
this.centerDialogVisible = true
})
},
// 重启服务
restartService(service) {
var formdata = new FormData()
formdata.set('namespace', this.namespace)
formdata.set('podName', service.podName)
serviceRedeploy(formdata).then((resp) => {
if (resp.data.data === true) {
return this.$message.success('重置成功!')
} else {
return this.$message.error('重置失败!')
}
})
},
// 打开更新服务对话框
openUpdateServiceDialog(service) {
this.updateDialogVisible = true
this.serviceName = service.serviceName
// 获取镜像列表
getImageList({
repoName: 'qa-test/' + service.serviceName
}).then((resp) => {
if (resp.data.data.TagCount > 0) {
this.tagOptions = resp.data.data.TagInfo
this.reponame = resp.data.data.RepoName
this.tagName = resp.data.data.TagInfo[0].TagName
this.server = resp.data.data.Server
}
})
},
// 调用接口更新服务
updateService() {
var formdata = new FormData()
formdata.set('namespace', this.namespace)
formdata.set('serviceName', this.serviceName)
formdata.set('image', this.tagName)
serviceModify(formdata).then((resp) => {
if (resp.data.data) {
this.updateDialogVisible = false
this.getServiceList()
return this.$message.success('更新成功!')
}
})
},
// 删除服务
deleteService(service) {
this.$messageBox(
`此操作将删除 ${service.serviceName} 服务, 是否继续?`,
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
).then(() => {
var formdata = new FormData()
formdata.set('namespace', this.namespace)
formdata.set('serviceName', service.serviceName)
serviceDelete(formdata).then((resp) => {
if (resp.data.data === true) {
this.getServiceList()
return this.$message.success('删除成功!')
} else {
return this.$message.error('删除失败!')
}
})
})
},
// 创建服务
createService() {
createK8sService({
namespace: this.namespace,
serviceName: this.reponame.split('/')[1],
type: this.label === 'base' ? this.reponame.split('/')[1] : this.label,
label: this.label,
domain: this.domain === undefined ? '' : this.domain.split('.')[0],
debug: this.debug.key,
mock: this.mock.key,
image: `${this.reponame}:${this.tagName}`
}).then((resp) => {
if (resp.data.data) {
this.dialogVisible = false
this.getServiceList()
return this.$message.success('创建成功!')
} else {
return this.$message.error(resp.data.msg)
}
})
},
linkShell(scopeData) {
window.open(
`http://172.30.220.24:9600/static/terminal.html?namespace=${this.namespace}&pod=${scopeData.podName}`,
'_blank'
)
},
linkKibana(scopeData) {
const sn = scopeData.serviceName
const ns = this.namespace
console.log('sn: ' + sn)
console.log('ns: ' + ns)
// const url = `http://kibana-new.quantgroups.com/app/kibana#/discover?_g=(filters:!(),refreshInterval:(pause:!f,value:5000),time:(from:now-2m,to:now))&_a=(columns:!(message),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:c7d3a2f0-b760-11e9-a937-01944fbd6d1d,key:k8s.namespace,negate:!f,params:(query:${ns}),type:phrase,value:${ns}),query:(match:(k8s.namespace:(query:${ns},type:phrase)))),('$state':(store:appState),meta:(alias:!n,disabled:!f,index:c7d3a2f0-b760-11e9-a937-01944fbd6d1d,key:k8s.svcname,negate:!f,params:(query:${sn}),type:phrase,value:${sn}),query:(match:(k8s.svcname:(query:${sn},type:phrase))))),index:c7d3a2f0-b760-11e9-a937-01944fbd6d1d,interval:auto,query:(language:kuery,query:''),sort:!(logtime,desc))`
const url = `http://kibana.liangkebang.com/app/kibana#/discover?_g=(filters:!(),refreshInterval:(pause:!t,value:5000),time:(from:now-15m,to:now))&_a=(columns:!(message),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:'64887440-a955-11ea-8847-cfc3eef68da1',key:k8s.namespace,negate:!f,params:(query:${ns}),type:phrase,value:${ns}),query:(match:(k8s.namespace:(query:${ns},type:phrase)))),('$state':(store:appState),meta:(alias:!n,disabled:!f,index:'64887440-a955-11ea-8847-cfc3eef68da1',key:k8s.svcname,negate:!f,params:(query:${sn}),type:phrase,value:${sn}),query:(match:(k8s.svcname:(query:${sn},type:phrase))))),index:'64887440-a955-11ea-8847-cfc3eef68da1',interval:auto,query:(language:kuery,query:''),sort:!(logtime,desc))`
window.open(`${url}`, '_blank')
},
linkLog(scopeData) {
let path = ''
if (scopeData.labels.type === 'ui') {
path =
'/usr/local/openresty/nginx/logs/access.log /usr/local/openresty/nginx/logs/error.log'
} else {
path = `/home/quant_group/logs/*.log`
}
window.open(
`http://172.30.220.24:9600/static/logs.html?namespace=${this.namespace}&pod=${scopeData.podName}&paths=${path}`,
'_blank'
)
},
openConsole(data) {
let port
if (data.serviceName === 'rabbitmq') {
port = data.portMappings.filter((item) => item.port === 15672)[0]
.nodePort
}
if (data.serviceName === 'consul') {
port = data.portMappings.filter((item) => item.port === 8500)[0]
.nodePort
}
if (data.serviceName === 'redash') {
port = data.portMappings.filter((item) => item.port === 5000)[0]
.nodePort
}
window.open(`http://${data.lanIp}:${port}/`, '_blank')
},
handleDetail(data) {
window.open(`https://${data.host}/`, '_blank')
}
}
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.shadow-content {
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
margin-top: 30px;
}
.warn-content {
background: rgba(66, 185, 131, 0.1);
border-radius: 2px;
padding: 16px;
padding: 1rem;
line-height: 1.6rem;
word-spacing: 0.05rem;
a {
color: #42b983;
font-weight: 600;
}
}
.title-sub {
margin-top: 30px;
font-size: 15px;
}
.elSelect {
width: 100%;
}
.port {
display: inline-block;
padding: 2px;
/*background: #f0f0f0;*/
border: 1px solid #f0f2f5;
margin: 2px;
}
.link-type,
.link-type:focus {
color: #337ab7;
cursor: pointer;
&:hover {
color: rgb(32, 160, 255);
}
}
</style> </style>
<template>
<!-- 顶部搜索框 -->
<div class="app-container">
<div class="filter-container">
<el-input v-model="listQuery.projectName" placeholder="服务名称" clearable style="width: 200px;" class="filter-item" @keyup.enter.native="getProjectList" />
<el-select v-model="listQuery.projectType" placeholder="服务类型" clearable style="width: 200px" class="filter-item">
<el-option v-for="item in typeOptions" :key="item.projectType" :label="item.projectType" :value="item.projectType" />
</el-select>
<el-select v-model="listQuery.isActive" placeholder="是否服役" clearable style="width: 200px" class="filter-item" @clear="clearIsActive()">
<el-option v-for="item in avtiveOptions" :key="item.key" :label="item.label" :value="item.key" />
</el-select>
<el-button class="filter-item" type="primary" icon="el-icon-search" @click="getProjectList">搜索</el-button>
<el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate">添加</el-button>
</div>
<!-- 表格 -->
<el-table :data="proconfigs" fit max-height="700" size="medium" style="width: 100%;">
<el-table-column label="ID" type="index" align="center" width="55" >
<template slot-scope="scope">
<span> {{ (listQuery.pageNum - 1) * (listQuery.pageSize) + scope.$index + 1}}</span>
</template>
</el-table-column>
<el-table-column label="服务名称" align="center">
<template slot-scope="scope">
<span class="link-type" @click="handleUpdate(scope.row)">{{ scope.row.projectName }}</span>
</template>
</el-table-column>
<el-table-column label="服务描述" prop="desc" align="center" />
<el-table-column label="线上域名" prop="hostName" align="center" />
<el-table-column label="负责人" width="80px" prop="owner" align="center" />
<el-table-column label="状态" width="90px" align="center">
<template slot-scope="scope">
<el-tag type="success" v-if="scope.row.isActive === 1">服役中</el-tag>
<el-tag type="danger" v-else>退役了</el-tag>
</template>
</el-table-column>
<el-table-column label="部署容器" width="90px" align="center">
<template slot-scope="scope">
<el-tag type="success" v-if="scope.row.deployToDocker === 1"></el-tag>
<el-tag type="danger" v-else></el-tag>
</template>
</el-table-column>
<el-table-column label="API地址" align="center" width="80px">
<template slot-scope="scope">
<el-tooltip :content="scope.row.api" class="item" effect="dark" placement="top">
<el-button v-show="scope.row.api" type="primary" icon="el-icon-time" circle @click="openUrl(scope.row.api)" />
</el-tooltip>
</template>
</el-table-column>
<el-table-column label="DDL地址" width="80px" align="center">
<template slot-scope="scope">
<el-tooltip :content="scope.row.ddl" class="item" effect="dark" placement="top">
<el-button v-show="scope.row.ddl" type="success" icon="el-icon-time" circle @click="openUrl(scope.row.ddl)" />
</el-tooltip>
</template>
</el-table-column>
<el-table-column label="Wiki" width="80px" align="center">
<template slot-scope="scope">
<el-tooltip :content="scope.row.wiki" class="item" effect="dark" placement="top">
<el-button v-show="scope.row.wiki" type="warning" icon="el-icon-time" circle @click="openUrl(scope.row.wiki)" />
</el-tooltip>
</template>
</el-table-column>
<el-table-column label="Git地址" width="80px" align="center">
<template slot-scope="scope">
<el-tooltip :content="scope.row.gitPath" class="item" effect="dark" placement="top">
<el-button type="info" icon="el-icon-tickets" circle />
</el-tooltip>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="80" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button type="primary" size="mini" @click="handleUpdate(scope.row)">编辑</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page.sync="listQuery.pageNum" :page-sizes="[10, 20, 50, 100, 200, 300]" :page-size="listQuery.pageSize" layout="total, sizes, prev, pager, next" :total="total"></el-pagination>
<el-dialog title="xx对话框" :visible.sync="dialogFormVisible">
<el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="115px" style="width: 90%; margin-left:40px;">
<el-form-item label="类型" prop="projectType">
<el-select v-model="temp.projectType" class="filter-item" placeholder="Please select">
<el-option v-for="item in typeOptions" :key="item.projectType" :label="item.projectType" :value="item.projectType" />
</el-select>
</el-form-item>
<el-form-item label="Git地址" prop="gitPath" style="width: 100%;">
<el-input v-model="temp.gitPath" />
</el-form-item>
<el-form-item label="负责人" style="width: 100%;" prop="owner">
<el-input v-model="temp.owner" />
</el-form-item>
<el-form-item label="服务描述" style="width: 100%;">
<el-input :autosize="{ minRows: 1, maxRows: 4}" v-model="temp.desc" type="textarea" placeholder="Please input" />
</el-form-item>
<el-form-item label="API" style="width: 100%;">
<el-input v-model="temp.api" />
</el-form-item>
<el-form-item label="数据库DDL" style="width: 100%;">
<el-input v-model="temp.ddl" />
</el-form-item>
<el-form-item label="Wiki" style="width: 100%;">
<el-input v-model="temp.wiki" />
</el-form-item>
<el-form-item label="是否服役" prop="isActive">
<el-select v-model="temp.isActive" class="filter-item" placeholder="Please select">
<el-option v-for="item in avtiveOptions" :key="item.key" :label="item.label" :value="item.key" />
</el-select>
</el-form-item>
<el-form-item label="是否部署容器" prop="deployToDocker">
<el-select v-model="temp.deployToDocker" class="filter-item" placeholder="Please select">
<el-option v-for="item in deployOptions" :key="item.key" :label="item.label" :value="item.key" />
</el-select>
</el-form-item>
<el-form-item v-if="temp.deployToDocker == 1" label="线上域名" prop="hostName" style="width: 100%;">
<el-input v-model="temp.hostName" />
</el-form-item>
<el-form-item v-if="temp.deployToDocker === 1" label="配置文件路径" style="width: 100%;">
<el-input v-model="temp.configPath" />
</el-form-item>
<el-form-item v-if="temp.deployToDocker === 1" label="Build文件路径" style="width: 100%;">
<el-input v-model="temp.jarPath" />
</el-form-item>
<el-form-item v-if="temp.deployToDocker === 1" label="日志路径" style="width: 100%;">
<el-input v-model="temp.logPath" />
</el-form-item>
<el-form-item v-if="temp.deployToDocker === 1" label="部署命令" style="width: 100%;">
<el-input v-model="temp.buildCommand" />
</el-form-item>
<el-form-item v-if="temp.deployToDocker === 1" label="Sonar扫描" prop="sonar">
<el-select v-model="temp.sonar" class="filter-item" placeholder="Please select">
<el-option v-for="item in deployOptions" :key="item.key" :label="item.label" :value="item.key" />
</el-select>
</el-form-item>
<el-form-item v-show="temp.projectType==='java' && temp.deployToDocker" label="Database" style="width: 100%;">
<el-input :autosize="{ minRows: 1, maxRows: 2}" v-model="temp.database" type="textarea" placeholder="依赖的数据库,库名与库名之间使用空格分隔" />
</el-form-item>
<el-alert v-show="temp.projectType==='java' && temp.deployToDocker" style="margin-bottom:20px" title="编辑启动命令需要管理员权限" type="warning" />
<el-form-item v-show="temp.projectType==='java' && temp.deployToDocker" label="启动命令" style="width: 100%;">
<el-input :autosize="{ minRows: 2, maxRows: 10}" v-model="temp.startCommand" :disabled="disabled" type="textarea" placeholder="Please input" />
</el-form-item>
<el-card v-if="temp.deployToDocker" class="box-card">
<div slot="header">
<span>Kubernetes设置</span>
</div>
<el-form :inline="true" size="medium">
<el-form-item label="CPU request" style="width:40%" prop="cpuRequest">
<el-input v-model="temp.cpuRequest" />
</el-form-item>
<el-form-item label="CPU limit" style="width:40%" prop="cpuLimit">
<el-input v-model="temp.cpuLimit" />
</el-form-item>
<el-form-item label="内存 request" style="width:40%" prop="memRequest">
<el-input v-model="temp.memRequest" />
</el-form-item>
<el-form-item label="内存 limit" style="width:40%" prop="memLimit">
<el-input v-model="temp.memLimit" />
</el-form-item>
</el-form>
</el-card>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取消</el-button>
<el-button type="primary" @click="createData()">确认</el-button>
</div>
</el-dialog>
<el-dialog :visible.sync="dialogDeleteVisible" :data="temp" title="Delete">
<span>
确定要删除{{ temp.projectName }}吗?
</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogDeleteVisible = false">取消</el-button>
<el-button type="primary" @click="deleteData()">确认</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { getDockerProjectList, getDockerProjectType, addDockerProject } from '@/api/k8s'
export default {
data() {
return {
total: 0,
listQuery: {
pageNum: 1,
pageSize: 10
},
typeOptions: [],
avtiveOptions: [
{ key: 1, label: '服役中' },
{ key: 0, label: '退役了' }
],
deployOptions: [
{ key: 1, label: '' },
{ key: 0, label: '' }
],
sortOptions: [
{ label: '服务名升序', key: '+project_name' },
{ label: '服务名降序', key: '-project_name' }
],
temp: {},
dialogFormVisible: false,
dialogDeleteVisible: false,
dialogStatus: '',
textMap: {
update: 'Edit',
create: 'Create'
},
proconfigs: [],
disabled: undefined,
rules: {
projectType: [{ required: true, message: '请选择', trigger: 'change' }],
gitPath: [{ required: true, message: '请输入', trigger: 'change' }],
isActive: [{ required: true, message: '请选择', trigger: 'change' }],
deployToDocker: [
{ required: true, message: '请选择', trigger: 'change' }
],
hostName: [{ required: true, message: '请输入', trigger: 'change' }],
owner: [{ required: true, message: '请输入', trigger: 'change' }]
}
}
},
created() {
this.getType()
this.getProjectList()
},
methods: {
// 获取项目列表
getProjectList() {
getDockerProjectList(this.listQuery).then((resp) => {
if (resp.data.data != null) {
this.proconfigs = resp.data.data.list
this.total = resp.data.data.total
} else {
this.$message.error('获取项目列表失败')
}
})
},
// 获取项目类型
getType() {
getDockerProjectType().then((resp) => {
if (resp.data.data) {
this.typeOptions = resp.data.data
}
})
},
// 打开链接
openUrl(data) {
window.open(`${data}`, '_blank')
},
// 打开新建项目对话框
handleCreate() {
this.temp = {}
this.dialogFormVisible = true
this.$nextTick(() => {
this.$refs['dataForm'].clearValidate()
})
},
// 打开更新项目对话框
handleUpdate(row) {
this.temp = Object.assign({}, row)
this.dialogFormVisible = true
this.$nextTick(() => {
this.$refs['dataForm'].clearValidate()
})
},
// 新建项目
createData() {
var projectName = this.temp.gitPath.split('/')[1].split('.')[0]
this.temp.projectName = projectName
this.$refs['dataForm'].validate((valid) => {
if (valid) {
addDockerProject(this.temp).then(resp => {
if (resp.data.data === true) {
this.dialogFormVisible = false
return this.$message.success('创建成功!')
} else {
return this.$message.error('创建失败!')
}
})
}
})
},
deleteData() {},
// 每页数量变化
handleSizeChange(newSize) {
this.listQuery.pageSize = newSize
this.getProjectList()
},
// 页数切换
handleCurrentChange(newPage) {
this.listQuery.pageNum = newPage
this.getProjectList()
},
// 清空是否服役
clearIsActive() {
delete this.listQuery.isActive
}
}
}
</script>
<style lang="less" scoped>
.app-container {
padding: 20px;
}
.filter-container {
padding-bottom: 10px;
.filter-item {
display: inline-block;
vertical-align: middle;
margin-bottom: 10px;
}
}
.link-type,
.link-type:focus {
color: #337ab7;
cursor: pointer;
&:hover {
color: rgb(32, 160, 255);
}
}
</style>
...@@ -50,10 +50,13 @@ export default { ...@@ -50,10 +50,13 @@ export default {
return index + 1 return index + 1
}, },
// 跳转到详情页面 // 跳转到详情页面
jumpToDetail() { jumpToDetail(name) {
window.sessionStorage.setItem('env', name)
this.$router.push({ this.$router.push({
path: `/docker/env` path: `/docker/env`
}) })
// 强制刷新整个页面
this.$router.go(0)
}, },
syncMySQL() {} syncMySQL() {}
}, },
......
...@@ -172,7 +172,7 @@ export default { ...@@ -172,7 +172,7 @@ export default {
} }
.el-main { .el-main {
padding: 0px 10px 10px 15px; padding: 0px 10px 10px 10px;
} }
/*组件过渡动画*/ /*组件过渡动画*/
.compAnimate-enter { .compAnimate-enter {
......
{ {
"menu": [ "menu": [
{ {
"id": 1, "id": 2,
"icon": "",
"title": "Docker",
"child": [
{
"id": 1,
"title": "测试环境",
"icon": "",
"path": "/docker/TestEnv"
},
{
"id": 2,
"title": "开发环境",
"icon": "",
"path": "/docker/DevEnv"
},
{
"id": 3,
"title": "服务配置管理",
"icon": "",
"path": "/docker/ProConfig"
}
]
},
{
"id": 3,
"icon": "iconfont icon-icon_yhq_n", "icon": "iconfont icon-icon_yhq_n",
"title": "现金分期", "title": "现金分期",
"child": [ "child": [
...@@ -20,7 +45,7 @@ ...@@ -20,7 +45,7 @@
] ]
}, },
{ {
"id": 2, "id": 4,
"icon": "iconfont icon-icon_ckbl_n", "icon": "iconfont icon-icon_ckbl_n",
"title": "消费分期", "title": "消费分期",
"child": [ "child": [
...@@ -57,7 +82,7 @@ ...@@ -57,7 +82,7 @@
] ]
}, },
{ {
"id": 3, "id": 5,
"title": "Mock", "title": "Mock",
"icon": "iconfont icon-icon_yxtj_n", "icon": "iconfont icon-icon_yxtj_n",
"child": [ "child": [
...@@ -70,7 +95,7 @@ ...@@ -70,7 +95,7 @@
] ]
}, },
{ {
"id": 4, "id": 6,
"title": "小工具", "title": "小工具",
"icon": "iconfont icon-icon_dpsz", "icon": "iconfont icon-icon_dpsz",
"child": [ "child": [
...@@ -119,7 +144,7 @@ ...@@ -119,7 +144,7 @@
] ]
}, },
{ {
"id": 5, "id": 7,
"title": "接口自动化", "title": "接口自动化",
"icon": "iconfont icon-icon_yydd_n", "icon": "iconfont icon-icon_yydd_n",
"child": [ "child": [
...@@ -162,7 +187,7 @@ ...@@ -162,7 +187,7 @@
] ]
}, },
{ {
"id": 6, "id": 8,
"title": "质量保证", "title": "质量保证",
"icon": "iconfont icon-quality", "icon": "iconfont icon-quality",
"child": [ "child": [
...@@ -175,7 +200,7 @@ ...@@ -175,7 +200,7 @@
] ]
}, },
{ {
"id": 7, "id": 9,
"title": "用户权限管理", "title": "用户权限管理",
"icon": "iconfont icon-mg-role", "icon": "iconfont icon-mg-role",
"child": [ "child": [
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment