jumpserver同步功能完成,blackbox监控优化用户体验
This commit is contained in:
parent
43c141f437
commit
b049ad7495
|
@ -49,7 +49,7 @@ groups: #新rule文件需要加这行开头,追加旧的rule文件则不需
|
||||||
interval: 1m
|
interval: 1m
|
||||||
rules:
|
rules:
|
||||||
- record: cpu:usage:rate1m
|
- record: cpu:usage:rate1m
|
||||||
expr: (1 - avg(rate(node_cpu_seconds_total{mode="idle"}[1m])) by (instance,vendor,account,group,name)) * 100
|
expr: (1 - avg(irate(node_cpu_seconds_total{mode="idle"}[3m])) by (instance,vendor,account,group,name)) * 100
|
||||||
- record: mem:usage:rate1m
|
- record: mem:usage:rate1m
|
||||||
expr: (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100
|
expr: (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100
|
||||||
```
|
```
|
||||||
|
|
|
@ -4,7 +4,7 @@ WORKDIR /flask
|
||||||
RUN sed -i 's/dl-cdn.alpinelinux.org/repo.huaweicloud.com/g' /etc/apk/repositories \
|
RUN sed -i 's/dl-cdn.alpinelinux.org/repo.huaweicloud.com/g' /etc/apk/repositories \
|
||||||
&& apk add --no-cache gcc libc-dev libffi-dev \
|
&& apk add --no-cache gcc libc-dev libffi-dev \
|
||||||
&& rm -rf /var/cache/apk/* \
|
&& rm -rf /var/cache/apk/* \
|
||||||
&& pip3 install --upgrade pip -i https://repo.huaweicloud.com/repository/pypi/simple \
|
&& pip3 install --upgrade pip -i https://repo.huaweicloud.com/repository/pypi/simple --no-cache-dir\
|
||||||
&& pip3 install -r requirements.txt -i https://repo.huaweicloud.com/repository/pypi/simple
|
&& pip3 install -r requirements.txt -i https://repo.huaweicloud.com/repository/pypi/simple --no-cache-dir
|
||||||
EXPOSE 2026
|
EXPOSE 2026
|
||||||
CMD ["python3","./manager.py"]
|
CMD ["python3","./manager.py"]
|
||||||
|
|
|
@ -38,7 +38,7 @@ init_jobs = { **ecs_jobs, **avd_jobs, **exp_jobs, **jms_jobs }
|
||||||
|
|
||||||
if init_jobs is not None:
|
if init_jobs is not None:
|
||||||
for k,v in init_jobs.items():
|
for k,v in init_jobs.items():
|
||||||
print(f'【初始化任务】{k}:\n {v}', flush=True)
|
print(f"【初始化任务】{k}:{v['args']},{v['minutes']}m", flush=True)
|
||||||
Config.JOBS = init_jobs.values()
|
Config.JOBS = init_jobs.values()
|
||||||
|
|
||||||
app.config.from_object(Config())
|
app.config.from_object(Config())
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
import requests,json
|
import requests,json,consul_kv
|
||||||
import sys
|
|
||||||
sys.path.append("..")
|
|
||||||
from config import consul_token,consul_url
|
from config import consul_token,consul_url
|
||||||
|
|
||||||
headers = {'X-Consul-Token': consul_token}
|
headers = {'X-Consul-Token': consul_token}
|
||||||
|
init_module_list = ['http_2xx','http_4xx','tcp_connect','icmp','http200igssl','httpNoRedirect4ssl','http_5xx','http_post_2xx','ssh_banner']
|
||||||
def get_all_list(module,company,project,env):
|
def get_all_list(module,company,project,env):
|
||||||
module = f'and Meta.module=="{module}"' if module != '' else f'and Meta.module != ""'
|
module = f'and Meta.module=="{module}"' if module != '' else f'and Meta.module != ""'
|
||||||
company = f'and Meta.company=="{company}"' if company != '' else f'and Meta.company != ""'
|
company = f'and Meta.company=="{company}"' if company != '' else f'and Meta.company != ""'
|
||||||
|
@ -15,10 +13,14 @@ def get_all_list(module,company,project,env):
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
info = response.json()
|
info = response.json()
|
||||||
all_list = [i['Meta'] for i in info.values()]
|
all_list = [i['Meta'] for i in info.values()]
|
||||||
module_list = sorted(list(set([i['module'] for i in all_list])))
|
module_list = consul_kv.get_value('ConsulManager/record/blackbox/module_list')['module_list']
|
||||||
company_list = sorted(list(set([i['company'] for i in all_list])))
|
company_list = sorted(list(set([i['company'] for i in all_list])))
|
||||||
project_list = sorted(list(set([i['project'] for i in all_list])))
|
project_list = sorted(list(set([i['project'] for i in all_list])))
|
||||||
env_list = sorted(list(set([i['env'] for i in all_list])))
|
env_list = sorted(list(set([i['env'] for i in all_list])))
|
||||||
|
|
||||||
|
init_m_list = [x for x in init_module_list if x not in module_list]
|
||||||
|
module_list = module_list + ['---'] + init_m_list
|
||||||
|
|
||||||
return {'code': 20000,'all_list':all_list,'module_list':module_list,
|
return {'code': 20000,'all_list':all_list,'module_list':module_list,
|
||||||
'company_list':company_list,'project_list':project_list,'env_list':env_list}
|
'company_list':company_list,'project_list':project_list,'env_list':env_list}
|
||||||
else:
|
else:
|
||||||
|
@ -33,6 +35,10 @@ def get_service():
|
||||||
company_list = sorted(list(set([i['company'] for i in all_list])))
|
company_list = sorted(list(set([i['company'] for i in all_list])))
|
||||||
project_list = sorted(list(set([i['project'] for i in all_list])))
|
project_list = sorted(list(set([i['project'] for i in all_list])))
|
||||||
env_list = sorted(list(set([i['env'] for i in all_list])))
|
env_list = sorted(list(set([i['env'] for i in all_list])))
|
||||||
|
consul_kv.put_kv('ConsulManager/record/blackbox/module_list',{'module_list':module_list})
|
||||||
|
init_m_list = [x for x in init_module_list if x not in module_list]
|
||||||
|
module_list = module_list + ['------'] + init_m_list
|
||||||
|
|
||||||
return {'code': 20000,'all_list':all_list,'module_list':module_list,
|
return {'code': 20000,'all_list':all_list,'module_list':module_list,
|
||||||
'company_list':company_list,'project_list':project_list,'env_list':env_list}
|
'company_list':company_list,'project_list':project_list,'env_list':env_list}
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -50,7 +50,7 @@ def update_jms_ecs(jms_url,headers,new_node_dict,node_id,cloud,account,ecs_info,
|
||||||
admin_user = custom_info[ostype][1]
|
admin_user = custom_info[ostype][1]
|
||||||
payload = {
|
payload = {
|
||||||
"ip": ip,
|
"ip": ip,
|
||||||
"hostname": "cm_" + iname,
|
"hostname": iname,
|
||||||
"protocols": protocols,
|
"protocols": protocols,
|
||||||
"platform": platform,
|
"platform": platform,
|
||||||
"is_active": True,
|
"is_active": True,
|
||||||
|
@ -60,7 +60,7 @@ def update_jms_ecs(jms_url,headers,new_node_dict,node_id,cloud,account,ecs_info,
|
||||||
"comment": comment
|
"comment": comment
|
||||||
}
|
}
|
||||||
if ip in jms_ecs_dict.keys():
|
if ip in jms_ecs_dict.keys():
|
||||||
if jms_ecs_dict[ip]['name'] != "cm_" + iname or jms_ecs_dict[ip]['node'].split('/')[-1] != v['ent']:
|
if jms_ecs_dict[ip]['name'] != iname or jms_ecs_dict[ip]['node'].split('/')[-1] != v['ent']:
|
||||||
response = requests.request("PUT", f"{ecs_url}{jms_ecs_dict[ip]['id']}/", headers=headers, data = json.dumps(payload))
|
response = requests.request("PUT", f"{ecs_url}{jms_ecs_dict[ip]['id']}/", headers=headers, data = json.dumps(payload))
|
||||||
print(' 【JMS】update:主机名:',response.json()['hostname'],response.status_code,flush=True)
|
print(' 【JMS】update:主机名:',response.json()['hostname'],response.status_code,flush=True)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -11,7 +11,8 @@ api = Api(blueprint)
|
||||||
parser = reqparse.RequestParser()
|
parser = reqparse.RequestParser()
|
||||||
parser.add_argument('query_dict',type=str)
|
parser.add_argument('query_dict',type=str)
|
||||||
parser.add_argument('jms_config',type=dict)
|
parser.add_argument('jms_config',type=dict)
|
||||||
parser.add_argument('isnotify_dict',type=dict)
|
parser.add_argument('jms_sync',type=dict)
|
||||||
|
parser.add_argument('switch_dict',type=dict)
|
||||||
|
|
||||||
class Jms(Resource):
|
class Jms(Resource):
|
||||||
decorators = [token_auth.auth.login_required]
|
decorators = [token_auth.auth.login_required]
|
||||||
|
@ -74,15 +75,17 @@ class Jms(Resource):
|
||||||
if stype == 'config':
|
if stype == 'config':
|
||||||
ecs_info = consul_kv.get_value('ConsulManager/jms/ecs_info')
|
ecs_info = consul_kv.get_value('ConsulManager/jms/ecs_info')
|
||||||
jms_info = consul_kv.get_value('ConsulManager/jms/jms_info')
|
jms_info = consul_kv.get_value('ConsulManager/jms/jms_info')
|
||||||
|
custom_ecs_info = consul_kv.get_value('ConsulManager/jms/custom_ecs_info')
|
||||||
if ecs_info != {} and jms_info != {}:
|
if ecs_info != {} and jms_info != {}:
|
||||||
linuxport = ecs_info['linux'][0][0].split('/')[-1]
|
linuxport = ecs_info['linux'][0][0].split('/')[-1]
|
||||||
linuxuid = ecs_info['linux'][-1]
|
linuxuid = ecs_info['linux'][-1]
|
||||||
winport = ecs_info['windows'][0][0].split('/')[-1]
|
winport = ecs_info['windows'][0][0].split('/')[-1]
|
||||||
winuid = ecs_info['windows'][-1]
|
winuid = ecs_info['windows'][-1]
|
||||||
token = myaes.decrypt(jms_info['token'])
|
token = myaes.decrypt(jms_info['token'])
|
||||||
|
custom_ecs_json = json.dumps(custom_ecs_info, indent=8) if custom_ecs_info != {} else ''
|
||||||
jms_config = {'url': jms_info['url'], 'token': token,
|
jms_config = {'url': jms_info['url'], 'token': token,
|
||||||
'linuxport': linuxport, 'linuxuid': linuxuid,
|
'linuxport': linuxport, 'linuxuid': linuxuid,
|
||||||
'winport': winport, 'winuid': winuid}
|
'winport': winport, 'winuid': winuid, 'custom_ecs_info':custom_ecs_json}
|
||||||
else:
|
else:
|
||||||
jms_config = {}
|
jms_config = {}
|
||||||
return {'code': 20000, 'jms_config': jms_config}
|
return {'code': 20000, 'jms_config': jms_config}
|
||||||
|
@ -96,5 +99,49 @@ class Jms(Resource):
|
||||||
ecs_info = {"linux": [[f"ssh/{jms_config['linuxport']}"],jms_config['linuxuid']],
|
ecs_info = {"linux": [[f"ssh/{jms_config['linuxport']}"],jms_config['linuxuid']],
|
||||||
"windows": [[f"rdp/{jms_config['winport']}"],jms_config['winuid']]}
|
"windows": [[f"rdp/{jms_config['winport']}"],jms_config['winuid']]}
|
||||||
consul_kv.put_kv('ConsulManager/jms/ecs_info', ecs_info)
|
consul_kv.put_kv('ConsulManager/jms/ecs_info', ecs_info)
|
||||||
|
custom_ecs_info = jms_config['custom_ecs_info']
|
||||||
|
if custom_ecs_info != '':
|
||||||
|
try:
|
||||||
|
custom_ecs_dict = json.loads(custom_ecs_info)
|
||||||
|
consul_kv.put_kv('ConsulManager/jms/custom_ecs_info',custom_ecs_dict)
|
||||||
|
except Exception as e:
|
||||||
|
print(e,flush=True)
|
||||||
|
return {'code': 50000, 'data': 'Json解析错误,请检查!'}
|
||||||
|
else:
|
||||||
|
consul_kv.put_kv('ConsulManager/jms/custom_ecs_info',{})
|
||||||
return {'code': 20000, 'data': '配置完成'}
|
return {'code': 20000, 'data': '配置完成'}
|
||||||
|
if stype == 'switch':
|
||||||
|
args = parser.parse_args()
|
||||||
|
switch_dict = args['switch_dict']
|
||||||
|
vendor = {v : k for k, v in vendors.items()}[switch_dict['vendor']]
|
||||||
|
account = switch_dict['account']
|
||||||
|
sync = switch_dict['sync']
|
||||||
|
if sync:
|
||||||
|
node = consul_kv.get_value(f'ConsulManager/jms/{vendor}/{account}/node_id')
|
||||||
|
nodeid = node.get('node_id','')
|
||||||
|
interval = node.get('interval',3)
|
||||||
|
return {'code': 20000, 'interval': interval, 'nodeid': nodeid}
|
||||||
|
else:
|
||||||
|
deljob(f'{vendor}/{account}/jms')
|
||||||
|
consul_kv.del_key(f'ConsulManager/jms/jobs/{vendor}/{account}')
|
||||||
|
return {'code': 20000, 'data': f'【{vendor}/{account}】同步功能关闭!'}
|
||||||
|
if stype == 'sync':
|
||||||
|
args = parser.parse_args()
|
||||||
|
jms_sync = args['jms_sync']
|
||||||
|
vendor = {v : k for k, v in vendors.items()}[jms_sync['vendor']]
|
||||||
|
account = jms_sync['account']
|
||||||
|
nodeid = jms_sync['nodeid']
|
||||||
|
interval = int(jms_sync['interval'])
|
||||||
|
consul_kv.put_kv(f'ConsulManager/jms/{vendor}/{account}/node_id',{'node_id':nodeid,'interval':interval})
|
||||||
|
|
||||||
|
jms_job_id = f'{vendor}/{account}/jms'
|
||||||
|
jms_job_func = "__main__:sync_jms.run"
|
||||||
|
jms_job_args = [vendor,account]
|
||||||
|
|
||||||
|
addjob(jms_job_id,jms_job_func,jms_job_args,interval)
|
||||||
|
runjob(jms_job_id)
|
||||||
|
jms_job_dict = {'id':jms_job_id,'func':jms_job_func,'args':jms_job_args,'minutes':interval,
|
||||||
|
'trigger': 'interval','replace_existing': True}
|
||||||
|
consul_kv.put_kv(f'ConsulManager/jms/jobs/{vendor}/{account}',jms_job_dict)
|
||||||
|
return {'code': 20000, 'data': f'【{vendor}/{account}】同步JumpServer功能开启!首次同步完成'}
|
||||||
api.add_resource(Jms, '/api/jms/<stype>')
|
api.add_resource(Jms, '/api/jms/<stype>')
|
||||||
|
|
|
@ -22,10 +22,19 @@ export function postJmsConfig(jms_config) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function postExpIsnotify(isnotify_dict) {
|
export function postJmsSwitch(switch_dict) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/exp/isnotify',
|
url: '/api/jms/switch',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: { isnotify_dict }
|
data: { switch_dict }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function postJmsSync(jms_sync) {
|
||||||
|
return request({
|
||||||
|
url: '/api/jms/sync',
|
||||||
|
method: 'post',
|
||||||
|
timeout: 600 * 1000,
|
||||||
|
data: { jms_sync }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<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/blackbox%E7%AB%99%E7%82%B9%E7%9B%91%E6%8E%A7.md" target="_blank">应用场景:如何优雅的使用Consul管理Blackbox站点监控</el-link>
|
<el-link icon="el-icon-warning" type="success" href="https://github.com/starsliao/ConsulManager/blob/main/docs/blackbox%E7%AB%99%E7%82%B9%E7%9B%91%E6%8E%A7.md" target="_blank">应用场景:如何优雅的使用Consul管理Blackbox站点监控</el-link>
|
||||||
</el-alert>
|
</el-alert>
|
||||||
<div class="filter-container" style="flex: 1;display: flex;align-items: center;height: 50px;">
|
<div class="filter-container" style="flex: 1;display: flex;align-items: center;height: 50px;">
|
||||||
|
@ -47,7 +47,7 @@
|
||||||
批量删除
|
批量删除
|
||||||
</el-button>
|
</el-button>
|
||||||
<div style="float: right;margin-left: 10px;">
|
<div style="float: right;margin-left: 10px;">
|
||||||
<el-input v-model="iname" prefix-icon="el-icon-search" placeholder="请输入名称或实例进行筛选" clearable style="width:180px" class="filter-item" @input="inameFilter(iname)" />
|
<el-input v-model="iname" prefix-icon="el-icon-search" placeholder="名称或URL筛选" clearable style="width:180px" class="filter-item" @input="inameFilter(iname)" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@
|
||||||
<span>{{ row.name }}</span>
|
<span>{{ row.name }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="instance" label="实例" sortable align="center" show-overflow-tooltip>
|
<el-table-column prop="instance" label="URL" sortable align="center" show-overflow-tooltip>
|
||||||
<template slot-scope="{row}">
|
<template slot-scope="{row}">
|
||||||
<span style="font-size: 12px">{{ row.instance }}</span>
|
<span style="font-size: 12px">{{ row.instance }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
@ -121,30 +121,30 @@
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<el-autocomplete v-model="temp.module" :fetch-suggestions="Sugg_module" placeholder="优先选择" clearable class="filter-item" />
|
<el-autocomplete v-model="temp.module" :fetch-suggestions="Sugg_module" placeholder="优先选择,填写可新增" clearable class="filter-item" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="公司部门" prop="company">
|
<el-form-item label="公司部门" prop="company">
|
||||||
<el-autocomplete v-model="temp.company" :fetch-suggestions="Sugg_company" placeholder="优先选择" clearable class="filter-item" />
|
<el-autocomplete v-model="temp.company" :fetch-suggestions="Sugg_company" placeholder="优先选择,填写可新增" clearable class="filter-item" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="项目" prop="project">
|
<el-form-item label="项目" prop="project">
|
||||||
<el-autocomplete v-model="temp.project" :fetch-suggestions="Sugg_project" placeholder="优先选择" clearable class="filter-item" />
|
<el-autocomplete v-model="temp.project" :fetch-suggestions="Sugg_project" placeholder="优先选择,填写可新增" clearable class="filter-item" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="环境" prop="env">
|
<el-form-item label="环境" prop="env">
|
||||||
<el-autocomplete v-model="temp.env" :fetch-suggestions="Sugg_env" placeholder="优先选择" clearable class="filter-item" />
|
<el-autocomplete v-model="temp.env" :fetch-suggestions="Sugg_env" placeholder="优先选择,填写可新增" clearable class="filter-item" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="名称" prop="name">
|
<el-form-item label="名称" prop="name">
|
||||||
<el-input v-model="temp.name" placeholder="请输入" clearable class="filter-item" /><font size="3px" color="#ff0000">上面5个字段组合后需唯一,重复会覆盖已有监控项!</font>
|
<el-input v-model="temp.name" placeholder="请输入" clearable class="filter-item" /><br><font size="3px" color="#ff0000">以上5个字段组合后需唯一,重复会覆盖已有监控项!</font>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="instance">
|
<el-form-item prop="instance">
|
||||||
<span slot="label">
|
<span slot="label">
|
||||||
<span class="span-box">
|
<span class="span-box">
|
||||||
<span>实例</span>
|
<span>URL</span>
|
||||||
<el-tooltip style="diaplay:inline" effect="dark" content="TCP类检查格式为:IP:端口 ,HTTP类检查格式为完整的URL,必须以http(s)://开头。" placement="top">
|
<el-tooltip style="diaplay:inline" effect="dark" content="TCP类检查格式为:IP:端口 ,HTTP类检查格式为完整的URL,必须以http(s)://开头,ICMP检查仅填IP或域名。" placement="top">
|
||||||
<i class="el-icon-info" />
|
<i class="el-icon-info" />
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<el-input v-model="temp.instance" :autosize="{ minRows: 2, maxRows: 4}" type="textarea" placeholder="请输入" class="filter-item" />
|
<el-input v-model="temp.instance" placeholder="一次仅添加一个URL,批量添加可使用导入" clearable class="filter-item" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div slot="footer" class="dialog-footer">
|
<div slot="footer" class="dialog-footer">
|
||||||
|
@ -228,7 +228,7 @@ export default {
|
||||||
dialogStatus: '',
|
dialogStatus: '',
|
||||||
textMap: {
|
textMap: {
|
||||||
update: '更新',
|
update: '更新',
|
||||||
create: '创建'
|
create: '创建URL监控'
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
module: [{ required: true, message: '此为必填项', trigger: 'change' },
|
module: [{ required: true, message: '此为必填项', trigger: 'change' },
|
||||||
|
@ -437,6 +437,7 @@ export default {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
handleReset() {
|
handleReset() {
|
||||||
|
this.fetchData()
|
||||||
this.listQuery.module = ''
|
this.listQuery.module = ''
|
||||||
this.listQuery.company = ''
|
this.listQuery.company = ''
|
||||||
this.listQuery.project = ''
|
this.listQuery.project = ''
|
||||||
|
@ -511,7 +512,7 @@ export default {
|
||||||
handleDownload() {
|
handleDownload() {
|
||||||
this.downloadLoading = true
|
this.downloadLoading = true
|
||||||
import('@/vendor/Export2Excel').then(excel => {
|
import('@/vendor/Export2Excel').then(excel => {
|
||||||
const tHeader = ['监控模块', '公司部门', '项目', '环境', '名称', '实例(tcp的格式为IP:端口,URL需要以http(s)://开头)']
|
const tHeader = ['监控模块', '公司部门', '项目', '环境', '名称', 'URL(tcp的格式为IP:端口,URL需要以http(s)://开头)']
|
||||||
const filterVal = ['module', 'company', 'project', 'env', 'name', 'instance']
|
const filterVal = ['module', 'company', 'project', 'env', 'name', 'instance']
|
||||||
const data = this.formatJson(filterVal)
|
const data = this.formatJson(filterVal)
|
||||||
excel.export_json_to_excel({
|
excel.export_json_to_excel({
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<el-alert title="菜单只显示有到期资源的账户,余额可查询所有账户;单个资源的通知可独立关闭。【自动续费、到期转按需、到期不续费的资源不会采集】【腾讯云仅采集主机到期列表(未找到整体到期接口)】" type="error" close-text="朕知道了" />
|
<el-alert type="success" center close-text="朕知道了">
|
||||||
|
<el-link icon="el-icon-warning" type="success" href="https://github.com/starsliao/ConsulManager/blob/43c141f4373cb3288e213116a69b33820b6cce10/docs/%E5%A6%82%E4%BD%95%E6%8A%8A%E4%B8%BB%E6%9C%BA%E8%87%AA%E5%8A%A8%E5%90%8C%E6%AD%A5%E5%88%B0JumpServer.md" target="_blank">应用场景:如何优雅的把主机信息自动同步到JumpServer</el-link>
|
||||||
|
</el-alert>
|
||||||
<el-select v-model="query.vendor" placeholder="云厂商" clearable style="width: 150px" class="filter-item" @change="fetchData(query)">
|
<el-select v-model="query.vendor" placeholder="云厂商" clearable style="width: 150px" class="filter-item" @change="fetchData(query)">
|
||||||
<el-option v-for="item in vendor_list" :key="item" :label="item" :value="item" />
|
<el-option v-for="item in vendor_list" :key="item" :label="item" :value="item" />
|
||||||
</el-select>
|
</el-select>
|
||||||
|
@ -11,10 +13,11 @@
|
||||||
<el-button class="filter-item" style="margin-left: 10px;" type="success" icon="el-icon-magic-stick" circle @click="resetData" />
|
<el-button class="filter-item" style="margin-left: 10px;" type="success" icon="el-icon-magic-stick" circle @click="resetData" />
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-button class="filter-item" type="primary" icon="el-icon-edit" @click="handleCreate">接入JumpServer</el-button>
|
<el-button class="filter-item" type="primary" icon="el-icon-edit" @click="handleCreate">接入JumpServer</el-button>
|
||||||
<el-tooltip class="item" effect="light" content="根据菜单选择查询对应账户余额,菜单为空时,查询所有账户。" placement="top">
|
<el-dialog :visible.sync="dialogFormVisible" width="40%">
|
||||||
<el-button class="filter-item" type="warning" icon="el-icon-data-line" @click="handleamount">查看余额</el-button>
|
<div slot="title" class="header-title">
|
||||||
</el-tooltip>
|
<span style="font-size:16px;font-weight:bold;">接入JumpServer</span>
|
||||||
<el-dialog title="接入JumpServer" :visible.sync="dialogFormVisible" width="45%">
|
<el-link type="primary" href="https://github.com/starsliao/ConsulManager/blob/43c141f4373cb3288e213116a69b33820b6cce10/docs/%E5%A6%82%E4%BD%95%E6%8A%8A%E4%B8%BB%E6%9C%BA%E8%87%AA%E5%8A%A8%E5%90%8C%E6%AD%A5%E5%88%B0JumpServer.md" target="_blank" icon="el-icon-question">如何填写</el-link>
|
||||||
|
</div>
|
||||||
<el-form ref="dataForm" :model="jms_config" label-position="right" label-width="auto" style="width: 90%; margin-left: 20px;">
|
<el-form ref="dataForm" :model="jms_config" label-position="right" label-width="auto" style="width: 90%; margin-left: 20px;">
|
||||||
<el-form-item label="JumpServer URL">
|
<el-form-item label="JumpServer URL">
|
||||||
<el-input v-model="jms_config.url" placeholder="http开头" style="width: 390px;" />
|
<el-input v-model="jms_config.url" placeholder="http开头" style="width: 390px;" />
|
||||||
|
@ -22,17 +25,21 @@
|
||||||
<el-form-item label="JumpServer Token">
|
<el-form-item label="JumpServer Token">
|
||||||
<el-input v-model="jms_config.token" placeholder="请输入Admin Token" style="width: 390px;" show-password />
|
<el-input v-model="jms_config.token" placeholder="请输入Admin Token" style="width: 390px;" show-password />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="全局管理用户信息:" />
|
<hr style="FILTER: alpha(opacity=100,finishopacity=0,style=2)" align=left width="96%" SIZE=1>
|
||||||
|
<h3>全局通用主机【管理用户】信息:</h3>
|
||||||
<div class="demo-input-suffix">
|
<div class="demo-input-suffix">
|
||||||
<h3>Linux:</h3>
|
<h4>Linux:</h4>
|
||||||
ssh端口:<el-input v-model="jms_config.linuxport" style="width: 72px;" />
|
ssh端口:<el-input v-model="jms_config.linuxport" style="width: 72px;" />
|
||||||
管理用户ID:<el-input v-model="jms_config.linuxuid" style="width: 300px;" />
|
管理用户ID:<el-input v-model="jms_config.linuxuid" style="width: 300px;" />
|
||||||
</div>
|
</div>
|
||||||
<div class="demo-input-suffix">
|
<div class="demo-input-suffix">
|
||||||
<h3>Windows:</h3>
|
<h4>Windows:</h4>
|
||||||
rdp端口:<el-input v-model="jms_config.winport" style="width: 72px;" />
|
rdp端口:<el-input v-model="jms_config.winport" style="width: 72px;" />
|
||||||
管理用户ID:<el-input v-model="jms_config.winuid" style="width: 300px;" />
|
管理用户ID:<el-input v-model="jms_config.winuid" style="width: 300px;" />
|
||||||
</div>
|
</div>
|
||||||
|
<hr style="FILTER: alpha(opacity=100,finishopacity=0,style=2)" align=left width="96%" SIZE=1>
|
||||||
|
<h3>全局特殊主机【管理用户】信息:</h3>
|
||||||
|
<el-input v-model="jms_config.custom_ecs_info" :autosize="{ minRows: 5, maxRows: 18}" type="textarea" placeholder="请输入标准Json格式,无特殊主机请留空。" class="filter-item" style="width: 530px;" />
|
||||||
</el-form>
|
</el-form>
|
||||||
<div slot="footer" class="dialog-footer">
|
<div slot="footer" class="dialog-footer">
|
||||||
<el-button @click="dialogFormVisible = false">
|
<el-button @click="dialogFormVisible = false">
|
||||||
|
@ -66,50 +73,87 @@
|
||||||
<el-table-column prop="nextime" label="下次同步" sortable align="center" />
|
<el-table-column prop="nextime" label="下次同步" sortable align="center" />
|
||||||
<el-table-column label="同步" align="center" width="60" class-name="small-padding fixed-width">
|
<el-table-column label="同步" align="center" width="60" class-name="small-padding fixed-width">
|
||||||
<template slot-scope="{row}">
|
<template slot-scope="{row}">
|
||||||
<el-switch v-model="row.sync" active-color="#13ce66" @change="fetchNotify(row.vendor, row.account, row.notify_id, row.isnotify)" />
|
<el-switch v-model="row.sync" active-color="#13ce66" @change="fetchSwitch(row.vendor, row.account, row.sync)" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<el-dialog title="查询余额" :visible.sync="amountFormVisible" width="60%">
|
<el-dialog title="开启同步JumpServer" :visible.sync="swFormVisible" :before-close="fetchData" width="33%">
|
||||||
<el-table v-loading="listLoading" :data="amount_list" height="540" :default-sort="{ prop: 'amount', order: 'ascending' }" border fit highlight-current-row style="width: 100%;">
|
<el-form ref="dataForm" :model="jms_sync" label-position="right" label-width="auto" style="width: 90%; margin-left: 20px;">
|
||||||
<el-table-column prop="vendor" label="云厂商" sortable align="center" />
|
<el-form-item label="同步间隔">
|
||||||
<el-table-column prop="account" label="账户" sortable align="center" />
|
<el-input v-model="jms_sync.interval" style="width: 180px;" type="number">
|
||||||
<el-table-column prop="amount" label="余额(元)" sortable align="center" />
|
<template slot="append">分钟</template>
|
||||||
</el-table>
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="新节点ID">
|
||||||
|
<el-input v-model="jms_sync.nodeid" />
|
||||||
|
</el-form-item>
|
||||||
|
<font size="3px" color="#ff0000">注意:JumpServer中已有的同名主机不会同步。</font>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="fetchData">
|
||||||
|
取消
|
||||||
|
</el-button>
|
||||||
|
<el-button type="primary" @click="createSync(jms_sync)">
|
||||||
|
确认
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getJmsList, getJmsConfig, postJmsConfig, postExpIsnotify } from '@/api/jms'
|
import { getJmsList, getJmsConfig, postJmsConfig, postJmsSwitch, postJmsSync } from '@/api/jms'
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
jms_config: { url: '', token: '', linuxport: '22', linuxuid: '', winport: '3389', winuid: '' },
|
jms_config: { url: '', token: '', linuxport: '22', linuxuid: '', winport: '3389', winuid: '', custom_ecs_info: '' },
|
||||||
listLoading: false,
|
listLoading: false,
|
||||||
dialogFormVisible: false,
|
dialogFormVisible: false,
|
||||||
query: { vendor: '', account: '' },
|
query: { vendor: '', account: '' },
|
||||||
ecs_list: [],
|
ecs_list: [],
|
||||||
vendor_list: [],
|
vendor_list: [],
|
||||||
account_list: [],
|
account_list: [],
|
||||||
amount_list: [],
|
jms_sync: { vendor: '', account: '', interval: '3', nodeid: '' },
|
||||||
isnotify_dict: {},
|
switch_dict: {},
|
||||||
amountFormVisible: false
|
swFormVisible: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.fetchData()
|
this.fetchData()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
fetchNotify(vendor, account, notify_id, isnotify) {
|
fetchSwitch(vendor, account, sync) {
|
||||||
this.isnotify_dict = { vendor: vendor, account: account, notify_id: notify_id, isnotify: isnotify }
|
this.switch_dict = { vendor: vendor, account: account, sync: sync }
|
||||||
postExpIsnotify(this.isnotify_dict).then(response => {
|
if (sync) {
|
||||||
this.$message({
|
this.jms_sync.vendor = vendor
|
||||||
message: response.data,
|
this.jms_sync.account = account
|
||||||
type: response.type
|
postJmsSwitch(this.switch_dict).then(response => {
|
||||||
|
this.jms_sync.interval = response.interval
|
||||||
|
this.jms_sync.nodeid = response.nodeid
|
||||||
|
this.swFormVisible = true
|
||||||
})
|
})
|
||||||
})
|
} else {
|
||||||
|
this.$confirm('此操作将关闭同步功能,是否继续?', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
postJmsSwitch(this.switch_dict).then(response => {
|
||||||
|
this.fetchData()
|
||||||
|
this.$message({
|
||||||
|
message: response.data,
|
||||||
|
type: response.type
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}).catch(() => {
|
||||||
|
this.fetchData()
|
||||||
|
this.$message({
|
||||||
|
type: 'info',
|
||||||
|
message: '操作已取消'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
handleCreate() {
|
handleCreate() {
|
||||||
this.listLoading = true
|
this.listLoading = true
|
||||||
|
@ -126,6 +170,7 @@ export default {
|
||||||
this.fetchData()
|
this.fetchData()
|
||||||
},
|
},
|
||||||
fetchData() {
|
fetchData() {
|
||||||
|
this.swFormVisible = false
|
||||||
this.listLoading = true
|
this.listLoading = true
|
||||||
getJmsList(this.query).then(response => {
|
getJmsList(this.query).then(response => {
|
||||||
this.vendor_list = response.vendor_list
|
this.vendor_list = response.vendor_list
|
||||||
|
@ -137,10 +182,12 @@ export default {
|
||||||
createData() {
|
createData() {
|
||||||
this.$refs['dataForm'].validate((valid) => {
|
this.$refs['dataForm'].validate((valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
this.dialogFormVisible = false
|
|
||||||
this.listLoading = true
|
this.listLoading = true
|
||||||
postJmsConfig(this.jms_config).then(response => {
|
postJmsConfig(this.jms_config).then(response => {
|
||||||
this.listLoading = false
|
this.listLoading = false
|
||||||
|
if (response.code === 20000) {
|
||||||
|
this.dialogFormVisible = false
|
||||||
|
}
|
||||||
this.$message({
|
this.$message({
|
||||||
message: response.data,
|
message: response.data,
|
||||||
type: 'success'
|
type: 'success'
|
||||||
|
@ -149,8 +196,32 @@ export default {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
handleamount() {
|
createSync(jms_sync) {
|
||||||
this.amountFormVisible = true
|
this.$confirm('此操作将开启同步功能,并进行首次同步,请等待(耗时依主机数而定,可在日志中查看进度)是否继续?', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
this.$refs['dataForm'].validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
this.swFormVisible = false
|
||||||
|
this.listLoading = true
|
||||||
|
postJmsSync(jms_sync).then(response => {
|
||||||
|
this.listLoading = false
|
||||||
|
this.fetchData()
|
||||||
|
this.$message({
|
||||||
|
message: response.data,
|
||||||
|
type: 'success'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}).catch(() => {
|
||||||
|
this.$message({
|
||||||
|
type: 'info',
|
||||||
|
message: '操作已取消'
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue