diff --git a/flask-consul/manager.py b/flask-consul/manager.py index b34f2b1..032149c 100755 --- a/flask-consul/manager.py +++ b/flask-consul/manager.py @@ -7,7 +7,7 @@ skey_path = 'ConsulManager/assets/secret/skey' if consul_kv.get_kv_dict(skey_path) == {}: consul_kv.put_kv(skey_path,{'sk':''.join(str(uuid.uuid4()).split('-'))}) -from views import login, blackbox, consul, jobs, nodes, selfnode, avd, exp, jms +from views import login, blackbox, consul, jobs, nodes, selfnode, avd, exp, jms, edit_cloud from units.cloud import huaweicloud,alicloud,tencent_cloud from units.avd import avd_list from units.jms import sync_jms @@ -25,6 +25,7 @@ app.register_blueprint(selfnode.blueprint) app.register_blueprint(avd.blueprint) app.register_blueprint(exp.blueprint) app.register_blueprint(jms.blueprint) +app.register_blueprint(edit_cloud.blueprint) class Config(object): JOBS = [] diff --git a/flask-consul/units/cloud/alicloud.py b/flask-consul/units/cloud/alicloud.py index 85038db..5db4f91 100644 --- a/flask-consul/units/cloud/alicloud.py +++ b/flask-consul/units/cloud/alicloud.py @@ -93,7 +93,7 @@ def exp(account,collect_days,notify_days,notify_amount): def group(account): ak,sk = consul_kv.get_aksk('alicloud',account) - now = datetime.datetime.now().strftime('%m%d/%H:%M') + now = datetime.datetime.now().strftime('%m.%d/%H:%M') config = open_api_models.Config(access_key_id=ak,access_key_secret=sk) config.endpoint = f'resourcemanager.aliyuncs.com' client = ResourceManager20200331Client(config) @@ -123,7 +123,7 @@ def group(account): def ecs(account,region): ak,sk = consul_kv.get_aksk('alicloud',account) - now = datetime.datetime.now().strftime('%m%d/%H:%M') + now = datetime.datetime.now().strftime('%m.%d/%H:%M') group_dict = consul_kv.get_value(f'ConsulManager/assets/alicloud/group/{account}') config = open_api_models.Config(access_key_id=ak,access_key_secret=sk) diff --git a/flask-consul/units/cloud/huaweicloud.py b/flask-consul/units/cloud/huaweicloud.py index ddcb318..12091eb 100644 --- a/flask-consul/units/cloud/huaweicloud.py +++ b/flask-consul/units/cloud/huaweicloud.py @@ -93,7 +93,7 @@ def exp(account,collect_days,notify_days,notify_amount): def group(account): ak,sk = consul_kv.get_aksk('huaweicloud',account) - now = datetime.datetime.now().strftime('%m%d/%H:%M') + now = datetime.datetime.now().strftime('%m.%d/%H:%M') credentials = GlobalCredentials(ak, sk) try: client = EpsClient.new_builder() \ @@ -128,7 +128,7 @@ def group(account): def ecs(account,region): ak,sk = consul_kv.get_aksk('huaweicloud',account) - now = datetime.datetime.now().strftime('%m%d/%H:%M') + now = datetime.datetime.now().strftime('%m.%d/%H:%M') group_dict = consul_kv.get_value(f'ConsulManager/assets/huaweicloud/group/{account}') credentials = BasicCredentials(ak, sk) try: @@ -173,7 +173,7 @@ def ecs(account,region): def rds(account,region): ak,sk = consul_kv.get_aksk('huaweicloud',account) - now = datetime.datetime.now().strftime('%m%d/%H:%M') + now = datetime.datetime.now().strftime('%m.%d/%H:%M') group_dict = consul_kv.get_value(f'ConsulManager/assets/huaweicloud/group/{account}') credentials = BasicCredentials(ak, sk) try: @@ -198,7 +198,7 @@ def rds(account,region): 'cpu':f"{i['cpu']}核", 'mem':f"{i['mem']}GB", 'disk':f"{i['volume']['size']}GB", - 'exp': i['expiration_time'] + 'exp': '-' if i['expiration_time'] == None else i['expiration_time'].split('T')[0] } for i in info} count = len(rds_dict) off,on = sync_rds.w2consul('huaweicloud',account,region,rds_dict) diff --git a/flask-consul/units/cloud/sync_rds.py b/flask-consul/units/cloud/sync_rds.py index 3850d6e..6b93f93 100644 --- a/flask-consul/units/cloud/sync_rds.py +++ b/flask-consul/units/cloud/sync_rds.py @@ -54,6 +54,7 @@ def w2consul(vendor,account,region,rds_dict): 'group': v['group'], 'instance': instance, 'account': account, + 'itype': v['itype'], 'vendor': vendors.get(vendor,'未找到'), 'disk': v['disk'], 'cpu': v['cpu'], diff --git a/flask-consul/units/cloud/tencent_cloud.py b/flask-consul/units/cloud/tencent_cloud.py index f3925a1..451f250 100644 --- a/flask-consul/units/cloud/tencent_cloud.py +++ b/flask-consul/units/cloud/tencent_cloud.py @@ -80,7 +80,7 @@ def exp(account,collect_days,notify_days,notify_amount): def group(account): from tencentcloud.dcdb.v20180411 import dcdb_client, models ak,sk = consul_kv.get_aksk('tencent_cloud',account) - now = datetime.datetime.now().strftime('%m%d/%H:%M') + now = datetime.datetime.now().strftime('%m.%d/%H:%M') try: cred = credential.Credential(ak, sk) httpProfile = HttpProfile() @@ -115,7 +115,7 @@ def group(account): def ecs(account,region): from tencentcloud.cvm.v20170312 import cvm_client, models ak,sk = consul_kv.get_aksk('tencent_cloud',account) - now = datetime.datetime.now().strftime('%m%d/%H:%M') + now = datetime.datetime.now().strftime('%m.%d/%H:%M') group_dict = consul_kv.get_value(f'ConsulManager/assets/tencent_cloud/group/{account}') try: cred = credential.Credential(ak, sk) diff --git a/flask-consul/units/consul_kv.py b/flask-consul/units/consul_kv.py index 7cebe00..2441b69 100644 --- a/flask-consul/units/consul_kv.py +++ b/flask-consul/units/consul_kv.py @@ -57,7 +57,7 @@ def del_key_all(path): else: return None -def get_ecs_services(job_id): +def get_res_services(job_id): cloud,account,itype,region = job_id.split('/') service = f'{cloud}_{account}_{itype}' region = f'and "{region}" in Tags' @@ -65,8 +65,8 @@ def get_ecs_services(job_id): response = requests.get(url, headers=headers) if response.status_code == 200: info = response.json() - ecs_list = [i['Meta'] for i in info.values()] - return {'code': 20000,'ecs_list': ecs_list} + res_list = [i['Meta'] for i in info.values()] + return {'code': 20000,'res_list': res_list} else: return {'code': 50000, 'data': f'{response.status_code}:{response.text}'} diff --git a/vue-consul/src/api/.node-exporter.js.swp b/flask-consul/views/.nodes.py.swp similarity index 60% rename from vue-consul/src/api/.node-exporter.js.swp rename to flask-consul/views/.nodes.py.swp index 45b6d44..fb4d4c6 100644 Binary files a/vue-consul/src/api/.node-exporter.js.swp and b/flask-consul/views/.nodes.py.swp differ diff --git a/flask-consul/views/edit_cloud.py b/flask-consul/views/edit_cloud.py new file mode 100644 index 0000000..f5cc7f8 --- /dev/null +++ b/flask-consul/views/edit_cloud.py @@ -0,0 +1,115 @@ +from flask import Blueprint +from flask_restful import reqparse, Resource, Api +from flask_apscheduler import APScheduler +from config import vendors,regions +from units import token_auth,consul_kv +from .jobs import deljob,addjob,runjob,modjob_interval +import json +blueprint = Blueprint('edit_cloud',__name__) +api = Api(blueprint) + +parser = reqparse.RequestParser() +parser.add_argument('vendor',type=str) +parser.add_argument('account',type=str) +parser.add_argument('region',type=str) +parser.add_argument('editJob',type=dict) +class Edit(Resource): + decorators = [token_auth.auth.login_required] + job_list = list(consul_kv.get_kv_dict(f'ConsulManager/jobs').values()) + def get(self,stype): + if stype == 'cloud': + cloud_dict = {} + for i in self.job_list: + vendor,account = i['id'].split('/')[0:2] + if vendor in cloud_dict: + if account not in cloud_dict[vendor]: + cloud_dict[vendor].append(account) + else: + cloud_dict[vendor] = [account] + return {'code': 20000,'cloud_dict': cloud_dict} + if stype == 'find': + args = parser.parse_args() + vendor = args['vendor'] + account = args['account'] + region = args['region'] + restype = ['group'] + interval = {'proj_interval': 60, 'ecs_interval': 5, 'rds_interval': 5} + for i in self.job_list: + if f'{vendor}/{account}/group' == i['id']: + interval['proj_interval'] = i['minutes'] + elif f'{vendor}/{account}/ecs/{region}' == i['id']: + restype.append('ecs') + interval['ecs_interval'] = i['minutes'] + elif f'{vendor}/{account}/rds/{region}' == i['id']: + restype.append('rds') + interval['rds_interval'] = i['minutes'] + return {'code': 20000, 'restype': restype, 'interval': interval} + def post(self,stype): + if stype == 'commit': + args = parser.parse_args() + editjob_dict = args['editJob'] + vendor = editjob_dict['vendor'] + account = editjob_dict['account'] + region = editjob_dict['region'] + restype = editjob_dict['restype'] + proj_interval = int(editjob_dict['proj_interval']) + ecs_interval = int(editjob_dict['ecs_interval']) + rds_interval = int(editjob_dict['rds_interval']) + print(editjob_dict) + if editjob_dict['akskswitch']: + ak = editjob_dict['ak'] + sk = editjob_dict['sk'] + consul_kv.put_aksk(editjob_dict['vendor'],editjob_dict['account'],ak,sk) + + jobgroup = [x for x in self.job_list if x['id'] == f'{vendor}/{account}/group'][0] + if proj_interval != jobgroup['minutes']: + jobgroup['minutes'] = proj_interval + jobid = f'{vendor}/{account}/group' + consul_kv.put_kv(f'ConsulManager/jobs/{jobid}',jobgroup) + modjob_interval(jobid,proj_interval) + + ecs_jobid = f'{vendor}/{account}/ecs/{region}' + rds_jobid = f'{vendor}/{account}/rds/{region}' + if 'ecs' in restype: + isecs = [x for x in self.job_list if x['id'] == f'{vendor}/{account}/ecs/{region}'] + if len(isecs) == 1: + if ecs_interval != isecs[0]['minutes']: + consul_kv.put_kv(f'ConsulManager/jobs/{ecs_jobid}',isecs[0]) + modjob_interval(ecs_jobid,ecs_interval) + else: + job_func = f"__main__:{vendor}.ecs" + job_args = [account,region] + job_interval = ecs_interval + addjob(ecs_jobid, job_func, job_args, job_interval) + job_dict = {'id':ecs_jobid,'func':job_func,'args':job_args,'minutes':job_interval, + "trigger": "interval","replace_existing": True} + consul_kv.put_kv(f'ConsulManager/jobs/{ecs_jobid}',job_dict) + else: + try: + consul_kv.del_key(f'ConsulManager/jobs/{ecs_jobid}') + deljob(ecs_jobid) + except: + pass + + if 'rds' in restype: + isrds = [x for x in self.job_list if x['id'] == f'{vendor}/{account}/rds/{region}'] + if len(isrds) == 1: + if rds_interval != isrds[0]['minutes']: + consul_kv.put_kv(f'ConsulManager/jobs/{rds_jobid}',isrds[0]) + modjob_interval(rds_jobid,rds_interval) + else: + job_func = f"__main__:{vendor}.rds" + job_args = [account,region] + job_interval = rds_interval + addjob(rds_jobid, job_func, job_args, job_interval) + job_dict = {'id':rds_jobid,'func':job_func,'args':job_args,'minutes':job_interval, + "trigger": "interval","replace_existing": True} + consul_kv.put_kv(f'ConsulManager/jobs/{rds_jobid}',job_dict) + else: + try: + consul_kv.del_key(f'ConsulManager/jobs/{rds_jobid}') + deljob(rds_jobid) + except: + pass + return {'code': 20000, 'data': f'{vendor}/{account}/{region}:编辑成功!'} +api.add_resource(Edit, '/api/edit/<stype>') diff --git a/flask-consul/views/jms.py b/flask-consul/views/jms.py index 7e222a9..14da4bf 100644 --- a/flask-consul/views/jms.py +++ b/flask-consul/views/jms.py @@ -63,7 +63,7 @@ class Jms(Resource): jms_job = consul_kv.get_value(f'ConsulManager/record/jms/{vendor}/{account}') runtime = jms_job.get('update') count_sync = jms_job.get('count') - nextime = getjob(f'{vendor}/{account}/jms').next_run_time.strftime("%m%d/%H:%M") + nextime = getjob(f'{vendor}/{account}/jms').next_run_time.strftime("%m.%d/%H:%M") sync = True ecs_list.append({'vendor':vendors[vendor],'account':account,'count_linux':count_linux, 'count_win':count_win,'count_mem':f'{count_mem}GB','count_cpu':f'{count_cpu}核', diff --git a/flask-consul/views/jobs.py b/flask-consul/views/jobs.py index 3c212b0..5d696d2 100644 --- a/flask-consul/views/jobs.py +++ b/flask-consul/views/jobs.py @@ -20,6 +20,9 @@ def init(): def deljob(jobid): Scheduler.remove_job(jobid) +def modjob_interval(jobid,job_interval): + Scheduler.modify_job(jobid,trigger='interval',minutes=job_interval) + def addjob(job_id,job_func,job_args,job_interval): Scheduler.add_job(id=job_id, func=job_func, args=job_args, trigger='interval', minutes=job_interval, replace_existing=True) @@ -38,7 +41,7 @@ class Jobs(Resource): query_dict['vendor'] = {v : k for k, v in vendors.items()}[query_dict['vendor']] query_set = set({k:v for k,v in query_dict.items() if v != ''}.items()) job_list = list(consul_kv.get_kv_dict(f'ConsulManager/jobs').values()) - job_run_dict = {job.id:job.next_run_time.strftime("%m%d/%H:%M") for job in Scheduler.get_jobs()} + job_run_dict = {job.id:job.next_run_time.strftime("%m.%d/%H:%M") for job in Scheduler.get_jobs()} job_count_dict = consul_kv.get_kv_dict('ConsulManager/record/jobs') jobs = [] for i in job_list: @@ -91,17 +94,17 @@ class Jobs(Resource): if record_dict['status'] == 20000: consul_kv.put_kv(f'ConsulManager/jobs/{proj_job_id}',proj_job_dict) for res in restype: + for reg in job_dict['region']: + res_job_id = f"{job_dict['vendor']}/{job_dict['account']}/{res}/{reg}" + res_job_func = f"__main__:{job_dict['vendor']}.{res}" + res_job_args = [job_dict['account'],reg] + res_job_interval = int(job_dict[f'{res}_interval']) + Scheduler.add_job(id=res_job_id, func=res_job_func, args=res_job_args, trigger='interval', + minutes=res_job_interval, replace_existing=True) + res_job_dict = {'id':res_job_id,'func':res_job_func,'args':res_job_args,'minutes':res_job_interval, + 'trigger': 'interval','replace_existing': True} - res_job_id = f"{job_dict['vendor']}/{job_dict['account']}/{res}/{job_dict['region']}" - res_job_func = f"__main__:{job_dict['vendor']}.{res}" - res_job_args = [job_dict['account'],job_dict['region']] - res_job_interval = int(job_dict[f'{res}_interval']) - Scheduler.add_job(id=res_job_id, func=res_job_func, args=res_job_args, trigger='interval', - minutes=res_job_interval, replace_existing=True) - res_job_dict = {'id':res_job_id,'func':res_job_func,'args':res_job_args,'minutes':res_job_interval, - "trigger": "interval","replace_existing": True} - - consul_kv.put_kv(f'ConsulManager/jobs/{res_job_id}',res_job_dict) + consul_kv.put_kv(f'ConsulManager/jobs/{res_job_id}',res_job_dict) else: Scheduler.remove_job(proj_job_id) diff --git a/flask-consul/views/nodes.py b/flask-consul/views/nodes.py index c6bd2ea..d2be7cf 100644 --- a/flask-consul/views/nodes.py +++ b/flask-consul/views/nodes.py @@ -25,15 +25,19 @@ class Nodes(Resource): group_dict = consul_kv.get_value(f'ConsulManager/assets/{cloud}/group/{account}') group_list = [{'gid':k,'gname':v}for k,v in group_dict.items()] return {'code': 20000,'group':group_list} - elif stype == 'ecs': + elif stype == 'res': if job_id == '' or job_id == None: - return {'code': 20000,'ecs_list': [] } + return {'code': 20000,'res_list': [] } else: - return consul_kv.get_ecs_services(job_id) + return consul_kv.get_res_services(job_id) elif stype == 'jobecs': jobecs = consul_kv.get_keys_list('ConsulManager/jobs') jobecs_list = [i.split('/jobs/')[1] for i in jobecs if '/ecs/' in i] return {'code': 20000,'jobecs':jobecs_list} + elif stype == 'jobrds': + jobrds = consul_kv.get_keys_list('ConsulManager/jobs') + jobrds_list = [i.split('/jobs/')[1] for i in jobrds if '/rds/' in i] + return {'code': 20000,'jobrds':jobrds_list} elif stype == 'ecs_services': jobecs = consul_kv.get_keys_list('ConsulManager/jobs') jobecs_list = [i.split('/jobs/')[1] for i in jobecs if '/ecs/' in i] @@ -60,12 +64,12 @@ class Nodes(Resource): checked = args['checked'] cst_ecs_dict = consul_kv.get_kv_dict('ConsulManager/assets/sync_ecs_custom/') cst_ecs_keylist = [k.split('/')[-1] for k,v in cst_ecs_dict.items() if v != {}] - ecs_info = consul_kv.get_ecs_services(jobecs_name) + ecs_info = consul_kv.get_res_services(jobecs_name) if checked == 'false': return ecs_info else: - cst_ecs_list = [i for i in ecs_info['ecs_list'] if i['iid'] in cst_ecs_keylist] - return {'code': 20000, 'ecs_list': cst_ecs_list} + cst_ecs_list = [i for i in ecs_info['res_list'] if i['iid'] in cst_ecs_keylist] + return {'code': 20000, 'res_list': cst_ecs_list} def post(self, stype): if stype == 'config': diff --git a/vue-consul/src/api/edit.js b/vue-consul/src/api/edit.js new file mode 100644 index 0000000..16d3aee --- /dev/null +++ b/vue-consul/src/api/edit.js @@ -0,0 +1,22 @@ +import request from '@/utils/request-ops' + +export function getCloud() { + return request({ + url: '/api/edit/cloud', + method: 'get' + }) +} +export function findGroup(vendor, account, region) { + return request({ + url: '/api/edit/find', + method: 'get', + params: { vendor, account, region } + }) +} +export function PostEditJob(editJob) { + return request({ + url: '/api/edit/commit', + method: 'post', + data: { editJob } + }) +} diff --git a/vue-consul/src/api/node-exporter.js b/vue-consul/src/api/node-exporter.js index 62ac1ed..946dd33 100644 --- a/vue-consul/src/api/node-exporter.js +++ b/vue-consul/src/api/node-exporter.js @@ -32,14 +32,21 @@ export function getGroup(job_id) { }) } -export function getEcsList(job_id) { +export function getResList(job_id) { return request({ - url: '/api/nodes/ecs', + url: '/api/nodes/res', method: 'get', params: { job_id } }) } +export function getJobRds() { + return request({ + url: '/api/nodes/jobrds', + method: 'get' + }) +} + export function getJobEcs() { return request({ url: '/api/nodes/jobecs', diff --git a/vue-consul/src/router/index.js b/vue-consul/src/router/index.js index 96e2efe..87712e1 100644 --- a/vue-consul/src/router/index.js +++ b/vue-consul/src/router/index.js @@ -86,14 +86,14 @@ export const constantRoutes = [ path: '/nodes', component: Layout, redirect: '/nodes/jobs', - name: '云资源监控', - meta: { title: '云资源监控', icon: 'el-icon-shopping-bag-2' }, + name: '云资源管理', + meta: { title: '云资源管理', icon: 'el-icon-shopping-bag-2' }, children: [ { path: 'jobs', - name: '接入数据源', + name: '接入云厂商', component: () => import('@/views/node-exporter/jobs'), - meta: { title: '接入数据源', icon: 'el-icon-school' } + meta: { title: '接入云厂商', icon: 'el-icon-school' } }, { path: 'exp', @@ -149,7 +149,7 @@ export const constantRoutes = [ path: 'rds', name: 'RDS', component: () => import('@/views/rds/index'), - meta: { title: 'MySQL管理', icon: 'el-icon-cpu' }, + meta: { title: 'MySQL管理', icon: 'el-icon-coin' }, children: [ { path: 'lists', @@ -157,12 +157,14 @@ export const constantRoutes = [ component: () => import('@/views/rds/lists'), meta: { title: '云MySQL列表', icon: 'el-icon-cloudy' } }, + /** { path: 'self', name: '自建MySQL管理', component: () => import('@/views/rds/self'), meta: { title: '自建MySQL管理', icon: 'el-icon-s-platform' } }, + */ { path: 'pconfig', name: 'rds-pconfig', diff --git a/vue-consul/src/views/node-exporter/.jobs.vue.swp b/vue-consul/src/views/node-exporter/.jobs.vue.swp new file mode 100644 index 0000000..8d38108 Binary files /dev/null and b/vue-consul/src/views/node-exporter/.jobs.vue.swp differ diff --git a/vue-consul/src/views/node-exporter/jobs.vue b/vue-consul/src/views/node-exporter/jobs.vue index c396b10..c7b24bb 100644 --- a/vue-consul/src/views/node-exporter/jobs.vue +++ b/vue-consul/src/views/node-exporter/jobs.vue @@ -1,6 +1,6 @@ <template> <div class="app-container"> - <el-alert type="success" center close-text="知道了"> + <el-alert type="success" center close-text="朕知道了"> <el-link icon="el-icon-warning" type="success" href="https://github.com/starsliao/ConsulManager/blob/main/docs/ECS%E4%B8%BB%E6%9C%BA%E7%9B%91%E6%8E%A7.md" target="_blank">应用场景:如何优雅的使用Consul管理ECS主机监控</el-link> </el-alert> <el-select v-model="query.vendor" placeholder="云厂商" clearable style="width: 150px" class="filter-item" @change="fetchData(query)"> @@ -16,8 +16,11 @@ <el-tooltip class="item" effect="light" content="清空查询条件" placement="top"> <el-button class="filter-item" style="margin-left: 10px;" type="info" icon="el-icon-delete" circle @click="resetData" /> </el-tooltip> - <el-button class="filter-item" type="primary" icon="el-icon-edit" @click="handleCreate"> - 新增同步源 + <el-button class="filter-item" type="primary" icon="el-icon-s-promotion" @click="handleCreate"> + 新增云资源 + </el-button> + <el-button class="filter-item" type="warning" icon="el-icon-edit" @click="handleEdit"> + 编辑云资源 </el-button> <div style="float: right;"> <el-tooltip class="item" effect="light" content="刷新当前页面" placement="top"> @@ -31,7 +34,7 @@ <el-table-column prop="account" label="账户" sortable align="center" /> <el-table-column prop="itype" label="资源" sortable align="center"> <template slot-scope="{row}"> - <div v-if="row.itype === 'ecs'" slot="reference" class="name-wrapper"> + <div v-if="row.itype !== 'group'" slot="reference" class="name-wrapper"> <el-tag size="medium">{{ row.itype.toUpperCase() }}</el-tag> </div> <div v-else> @@ -43,7 +46,7 @@ <el-table-column prop="count" label="资源数" sortable align="center"> <template slot-scope="{row}"> <span style="font-weight:bold">{{ row.count }} </span> - <el-tooltip v-if="row.itype === 'ecs'" style="diaplay:inline" effect="dark" placement="top"> + <el-tooltip v-if="row.itype !== 'group'" style="diaplay:inline" effect="dark" placement="top"> <div slot="content"> 开机:{{ row.on }},关机:{{ row.off }} </div> <i class="el-icon-info" /> </el-tooltip> @@ -82,10 +85,10 @@ </el-table> </el-dialog> - <el-dialog title="新增同步源" :visible.sync="newFormVisible" width="40%"> + <el-dialog title="新增云资源" :visible.sync="newFormVisible" width="40%"> <el-form ref="dataForm" :rules="rules" :model="ecsJob" label-position="right" label-width="auto" style="width: 90%; margin-left: 1px;"> <el-form-item label="云厂商" prop="vendor"> - <el-select v-model="ecsJob.vendor" placeholder="请选择" @change="ecsJob.region=''"> + <el-select v-model="ecsJob.vendor" placeholder="请选择" @change="ecsJob.region=[]"> <el-option v-for="item in vendors" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </el-form-item> @@ -107,7 +110,7 @@ <el-input v-model="ecsJob.sk" placeholder="请输入AccessKey Secret" show-password /> </el-form-item> <el-form-item label="区域" prop="region"> - <el-select v-model="ecsJob.region" placeholder="请选择"> + <el-select v-model="ecsJob.region" filterable multiple collapse-tags placeholder="请选择"> <el-option v-for="item in regions[ecsJob.vendor]" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </el-form-item> @@ -116,7 +119,7 @@ <el-checkbox-group v-model="restype"> <el-checkbox label="group" disabled>分组</el-checkbox> <el-checkbox label="ecs">ECS</el-checkbox> - <el-checkbox label="rds">RDS</el-checkbox> + <el-checkbox label="rds">MySQL</el-checkbox> </el-checkbox-group> </el-form-item> @@ -134,7 +137,7 @@ <el-form-item v-if="restype.includes('ecs')" label="ECS同步间隔(分钟)" prop="ecs_interval"> <el-input v-model="ecsJob.ecs_interval" /> </el-form-item> - <el-form-item v-if="restype.includes('rds')" label="RDS同步间隔(分钟)" prop="rds_interval"> + <el-form-item v-if="restype.includes('rds')" label="MySQL同步间隔(分钟)" prop="rds_interval"> <el-input v-model="ecsJob.rds_interval" /> </el-form-item> </el-form> @@ -152,6 +155,72 @@ </div> </el-dialog> + <el-dialog title="编辑云资源" :visible.sync="editFormVisible" width="40%"> + <el-form ref="dataForm" :rules="rules" :model="editJob" label-position="right" label-width="auto" style="width: 90%; margin-left: 1px;"> + <el-form-item label="云厂商" prop="vendor"> + <el-select v-model="editJob.vendor" placeholder="请选择" @change="editJob.region=[];editJob.account=''"> + <el-option v-for="item in vendors" :key="item.value" :label="item.label" :value="item.value" /> + </el-select> + </el-form-item> + + <el-form-item label="账户" prop="account"> + <el-select v-model="editJob.account" placeholder="请选择" @change="editJob.akskswitch=false;editJob.region=''"> + <el-option v-for="item in cloud_dict[editJob.vendor]" :key="item" :label="item" :value="item" /> + </el-select> + </el-form-item> + <el-form-item label="修改密钥"> + <el-switch v-model="editJob.akskswitch" /> + </el-form-item> + <el-form-item v-if="editJob.akskswitch" label="Access Key" prop="ak"> + <el-input v-model="editJob.ak" placeholder="请输AccessKey ID" /> + </el-form-item> + <el-form-item v-if="editJob.akskswitch" label="Secret Key" prop="sk"> + <el-input v-model="editJob.sk" placeholder="请输入AccessKey Secret" show-password /> + </el-form-item> + + <el-form-item label="区域" prop="region"> + <el-select v-model="editJob.region" filterable placeholder="请选择" @change="fetchGroup(editJob.vendor, editJob.account, editJob.region)"> + <el-option v-for="item in regions[editJob.vendor]" :key="item.value" :label="item.label" :value="item.value" /> + </el-select> + </el-form-item> + + <el-form-item label="资源类型"> + <el-checkbox-group v-model="editJob.restype"> + <el-checkbox label="group" disabled>分组</el-checkbox> + <el-checkbox label="ecs">ECS</el-checkbox> + <el-checkbox label="rds">MySQL</el-checkbox> + </el-checkbox-group> + </el-form-item> + + <el-form-item prop="proj_interval"> + <span slot="label"> + <span class="span-box"> + <span>分组同步间隔(分钟)</span> + <el-tooltip style="diaplay:inline" effect="dark" content="分组是采集云厂商用于资源分组的字段,阿里云:资源组,华为云:企业项目,腾讯云:所属项目。请在创建云主机时设置好属组。" placement="top"> + <i class="el-icon-info" /> + </el-tooltip> + </span> + </span> + <el-input v-model="editJob.proj_interval" /> + </el-form-item> + <el-form-item v-if="editJob.restype.includes('ecs')" label="ECS同步间隔(分钟)" prop="ecs_interval"> + <el-input v-model="editJob.ecs_interval" /> + </el-form-item> + <el-form-item v-if="editJob.restype.includes('rds')" label="MySQL同步间隔(分钟)" prop="rds_interval"> + <el-input v-model="editJob.rds_interval" /> + </el-form-item> + </el-form> + + <div slot="footer" class="dialog-footer"> + <el-button @click="editFormVisible = false"> + 取消 + </el-button> + <el-button type="primary" @click="editData(editJob)"> + 确认 + </el-button> + </div> + </el-dialog> + <el-dialog title="更新同步间隔" :visible.sync="upFormVisible" width="30%"> <el-form ref="dataForm" :rules="rules" :model="upjob" label-position="right" label-width="130px" style="margin-left: 20px;"> <el-form-item label="同步间隔(分钟)" prop="interval"> @@ -172,6 +241,7 @@ <script> import { getAllJobs, PostJob, DelJob, getGroup } from '@/api/node-exporter' +import { getCloud, findGroup, PostEditJob } from '@/api/edit' export default { data() { const validateInput = (rule, value, callback) => { @@ -202,8 +272,7 @@ export default { { validator: validateInput, trigger: ['blur', 'change'] }], sk: [{ required: true, message: '此为必填项', trigger: 'change' }, { validator: validateInput, trigger: ['blur', 'change'] }], - region: [{ required: true, message: '此为必填项', trigger: 'blur' }, - { validator: validateInput, trigger: ['blur'] }], + region: [{ required: true, message: '此为必填项', trigger: 'blur' }], proj_interval: [{ required: true, message: '此为必填项', trigger: 'change' }, { validator: validateInput, trigger: ['blur', 'change'] }], ecs_interval: [{ required: true, message: '此为必填项', trigger: 'change' }, @@ -257,10 +326,13 @@ export default { ] }, - ecsJob: { vendor: '', ak: '', sk: '', region: '', account: '', proj_interval: 60, ecs_interval: 5, rds_interval: 5 }, + ecsJob: { vendor: '', ak: '', sk: '', region: [], account: '', proj_interval: 60, ecs_interval: 5, rds_interval: 5 }, + editJob: { restype: ['group'] }, + cloud_dict: {}, upjob: { jobid: '', interval: '' }, newFormVisible: false, upFormVisible: false, + editFormVisible: false, entFormVisible: false } }, @@ -280,6 +352,8 @@ export default { tableRowClassName({ row }) { if (row.itype === 'ecs') { return 'success-row' + } else if (row.itype === 'rds') { + return 'warning-row' } return '' }, @@ -297,8 +371,26 @@ export default { this.listLoading = false }) }, + + fetchGroup(vendor, account, region) { + this.listLoading = true + findGroup(vendor, account, region).then(response => { + this.editJob.restype = response.restype + this.editJob.proj_interval = response.interval.proj_interval + this.editJob.ecs_interval = response.interval.ecs_interval + this.editJob.rds_interval = response.interval.rds_interval + this.listLoading = false + }) + }, + handleEdit() { + this.editJob = { vendor: '', akskswitch: false, ak: '', sk: '', region: '', account: '', restype: ['group'], proj_interval: 60, ecs_interval: 5, rds_interval: 5 } + getCloud().then(response => { + this.cloud_dict = response.cloud_dict + }) + this.editFormVisible = true + }, handleCreate() { - this.ecsJob = { vendor: '', ak: '', sk: '', region: '', account: '', proj_interval: 60, ecs_interval: 5, rds_interval: 5 } + this.ecsJob = { vendor: '', ak: '', sk: '', region: [], account: '', proj_interval: 60, ecs_interval: 5, rds_interval: 5 } this.ecsJob.account = this.query.account this.newFormVisible = true }, @@ -322,6 +414,21 @@ export default { } }) }, + editData(editJob) { + this.$refs['dataForm'].validate((valid) => { + if (valid) { + this.editFormVisible = false + this.listLoading = true + PostEditJob(editJob).then(response => { + this.fetchData() + this.$message({ + message: response.data, + type: 'success' + }) + }) + } + }) + }, createData() { this.$refs['dataForm'].validate((valid) => { if (valid) { @@ -335,7 +442,7 @@ export default { message: response.data, type: 'success' }) - this.ecsJob.region = '' + this.ecsJob.region = [] }) } }) @@ -408,4 +515,7 @@ export default { .el-table .success-row { background: #f0f9eb; } + .el-table .warning-row { + background: oldlace; + } </style> diff --git a/vue-consul/src/views/node-exporter/lists.vue b/vue-consul/src/views/node-exporter/lists.vue index 65fab37..35a3b13 100644 --- a/vue-consul/src/views/node-exporter/lists.vue +++ b/vue-consul/src/views/node-exporter/lists.vue @@ -66,7 +66,7 @@ </template> <script> -import { getEcsList, getJobEcs, postCstEcs, getCstEcsConfig, getCstEcsList } from '@/api/node-exporter' +import { getResList, getJobEcs, postCstEcs, getCstEcsConfig, getCstEcsList } from '@/api/node-exporter' export default { data() { return { @@ -100,7 +100,7 @@ export default { cstEcsList(jobecs_name, checked) { this.listLoading = true getCstEcsList(jobecs_name, checked).then(response => { - this.ecs_list = response.ecs_list + this.ecs_list = response.res_list this.listLoading = false }) }, @@ -136,8 +136,8 @@ export default { fetchEcs(job_id) { this.checked = false this.listLoading = true - getEcsList(job_id).then(response => { - this.ecs_list = response.ecs_list + getResList(job_id).then(response => { + this.ecs_list = response.res_list this.listLoading = false }) } diff --git a/vue-consul/src/views/rds/.lists.vue.swp b/vue-consul/src/views/rds/.lists.vue.swp deleted file mode 100644 index 0ee9a00..0000000 Binary files a/vue-consul/src/views/rds/.lists.vue.swp and /dev/null differ diff --git a/vue-consul/src/views/rds/lists.vue b/vue-consul/src/views/rds/lists.vue index c55b577..ad8bf89 100644 --- a/vue-consul/src/views/rds/lists.vue +++ b/vue-consul/src/views/rds/lists.vue @@ -1,44 +1,18 @@ <template> <div class="app-container"> - <el-select v-model="jobecs_name" placeholder="请选择需要查询的云MySQL列表" filterable collapse-tags clearable style="width: 350px" class="filter-item" @change="fetchEcs(jobecs_name)"> - <el-option v-for="item in jobecs_list" :key="item" :label="item" :value="item" /> + <el-select v-model="jobrds_name" placeholder="请选择需要查询的云MySQL列表" filterable collapse-tags clearable style="width: 350px" class="filter-item" @change="fetchRds(jobrds_name)"> + <el-option v-for="item in jobrds_list" :key="item" :label="item" :value="item" /> </el-select> - <el-checkbox v-model="checked" style="margin-left: 10px;" label="仅显示修改过的" border @change="cstEcsList(jobecs_name,checked)" /> - <el-tooltip class="item" effect="light" content="刷新当前ECS列表" placement="top"> - <el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-refresh" circle @click="fetchEcs(jobecs_name)" /> + <el-tooltip class="item" effect="light" content="刷新当前RDS列表" placement="top"> + <el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-refresh" circle @click="fetchRds(jobrds_name)" /> </el-tooltip> <div style="float: right;margin-left: 10px;"> <el-input v-model="iname" prefix-icon="el-icon-search" placeholder="请输入名称、实例或实例ID进行筛选" clearable style="width: 300px" class="filter-item" /> </div> - <el-dialog title="自定义实例信息" :visible.sync="dialogFormVisible" width="45%"> - <el-form ref="dataForm" :model="cst_ecs" label-position="right" label-width="auto" style="width: 90%; margin-left: 20px;"> - <el-form-item label="自定义端口"> - <el-switch v-model="cst_ecs.portswitch" /> - </el-form-item> - <el-form-item v-if="cst_ecs.portswitch" required label="端口:"> - <el-input v-model="cst_ecs.port" /> - </el-form-item> - <el-form-item label="自定义IP"> - <el-switch v-model="cst_ecs.ipswitch" /> - </el-form-item> - <el-form-item v-if="cst_ecs.ipswitch" required label="IP:"> - <el-input v-model="cst_ecs.ip" /> - </el-form-item> - <font size="3px" color="#ff0000">如需恢复同步该实例的IP端口信息,请关闭开启的自定义选项后,再同步一次所属数据源。</font> - </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-table v-loading="listLoading" - :data="ecs_list.filter(data => !iname || (data.name.toLowerCase().includes(iname.toLowerCase()) || data.instance.toLowerCase().includes(iname.toLowerCase()) || data.iid.toLowerCase().includes(iname.toLowerCase())))" + :data="rds_list.filter(data => !iname || (data.name.toLowerCase().includes(iname.toLowerCase()) || data.instance.toLowerCase().includes(iname.toLowerCase()) || data.iid.toLowerCase().includes(iname.toLowerCase())))" :default-sort="{ prop: 'exp', order: 'ascending' }" border fit @@ -48,96 +22,66 @@ <el-table-column type="index" align="center" /> <el-table-column prop="group" label="分组" sortable align="center" width="150" show-overflow-tooltip /> <el-table-column prop="name" label="名称" sortable align="center" width="220" show-overflow-tooltip /> - <el-table-column prop="instance" label="实例" sortable align="center" width="180" /> - <el-table-column prop="os" label="系统" sortable align="center" width="100" /> - <el-table-column prop="cpu" label="CPU" sortable align="center" width="80" /> - <el-table-column prop="mem" label="内存" sortable align="center" width="80" /> - <el-table-column prop="exp" label="到期日" sortable align="center" width="120" /> - <el-table-column prop="iid" label="实例ID" sortable align="center" /> - <el-table-column label="操作" align="center" width="120" class-name="small-padding fixed-width"> + <el-table-column prop="instance" label="实例" sortable align="center" width="180"> <template slot-scope="{row}"> - <el-button type="primary" size="mini" @click="handleUpdate(row.iid)"> - 自定义实例 - </el-button> + <span style="font-weight:bold">{{ row.instance }} </span> + <el-tooltip style="diaplay:inline" effect="dark" placement="top"> + <div slot="content"> 域名:{{ row.domain }}</div> + <i class="el-icon-info" /> + </el-tooltip> </template> </el-table-column> + <el-table-column prop="ver" label="版本" sortable align="center" width="80" /> + <el-table-column prop="cpu" label="CPU" sortable align="center" width="80" /> + <el-table-column prop="mem" label="内存" sortable align="center" width="80" /> + <el-table-column prop="disk" label="磁盘" sortable align="center" width="80" /> + <el-table-column prop="exp" label="到期日" sortable align="center" width="120" /> + <el-table-column prop="iid" label="实例ID" sortable align="center" /> </el-table> </div> </template> <script> -import { getEcsList, getJobEcs, postCstEcs, getCstEcsConfig, getCstEcsList } from '@/api/node-exporter' +import { getResList, getJobRds } from '@/api/node-exporter' export default { data() { return { listLoading: false, dialogFormVisible: false, checked: false, - jobecs_name: '', + jobrds_name: '', iname: '', - jobecs_list: [], - ecs_list: [], - cst_ecs: { iid: '', portswitch: false, ipswitch: false, port: '', ip: '' } + jobrds_list: [], + rds_list: [] } }, created() { - getJobEcs().then(response => { - this.jobecs_list = response.jobecs + getJobRds().then(response => { + this.jobrds_list = response.jobrds if (this.$route.query.job_id) { - this.fetchEcs(this.$route.query.job_id) + this.fetchRds(this.$route.query.job_id) } else { - this.jobecs_name = this.jobecs_list[0] - this.fetchEcs(this.jobecs_name) + this.jobrds_name = this.jobrds_list[0] + this.fetchRds(this.jobrds_name) } }) }, mounted() { if (this.$route.query.job_id) { - this.jobecs_name = this.$route.query.job_id + this.jobrds_name = this.$route.query.job_id } }, methods: { - cstEcsList(jobecs_name, checked) { - this.listLoading = true - getCstEcsList(jobecs_name, checked).then(response => { - this.ecs_list = response.ecs_list - this.listLoading = false + fetchJobRds() { + getJobRds().then(response => { + this.jobrds_list = response.jobrds }) }, - handleUpdate(iid) { - this.listLoading = true - this.dialogFormVisible = true - getCstEcsConfig(iid).then(response => { - this.cst_ecs = response.cst_ecs - this.listLoading = false - this.dialogFormVisible = true - }) - }, - createData() { - this.$refs['dataForm'].validate((valid) => { - if (valid) { - this.dialogFormVisible = false - this.listLoading = true - postCstEcs(this.cst_ecs).then(response => { - this.fetchEcs(this.jobecs_name) - this.$message({ - message: response.data, - type: 'success' - }) - }) - } - }) - }, - fetchJobEcs() { - getJobEcs().then(response => { - this.jobecs_list = response.jobecs - }) - }, - fetchEcs(job_id) { + fetchRds(job_id) { this.checked = false this.listLoading = true - getEcsList(job_id).then(response => { - this.ecs_list = response.ecs_list + getResList(job_id).then(response => { + this.rds_list = response.res_list this.listLoading = false }) }