Skip to content

Commit

Permalink
增加consul web管理
Browse files Browse the repository at this point in the history
  • Loading branch information
starsliao committed Feb 10, 2022
1 parent c523e7e commit 1590ac3
Show file tree
Hide file tree
Showing 14 changed files with 1,051 additions and 14 deletions.
4 changes: 2 additions & 2 deletions docker-push.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash
vf=0.1.3
vb=0.2.0
vf=0.3.0
vb=0.3.0
docker login [email protected] registry.cn-shenzhen.aliyuncs.com

docker tag nginx-consul:latest registry.cn-shenzhen.aliyuncs.com/starsl/nginx-consul:latest
Expand Down
6 changes: 3 additions & 3 deletions flask-consul/config.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import os
from itsdangerous import TimedJSONWebSignatureSerializer

consul_token = os.environ.get('consul_token','a94d1ecb-81d3-ea0a-4dc8-5e6701e528c5')
consul_url = os.environ.get('consul_url','http://10.5.148.67:8500/v1')
admin_passwd = os.environ.get('admin_passwd','cass.007')
consul_token = os.environ.get('consul_token','635abc53-c18c-f780-58a9-f04feb28fef1')
consul_url = os.environ.get('consul_url','http://10.0.0.26:8500/v1')
admin_passwd = os.environ.get('admin_passwd','123456')
secret_key = os.environ.get('secret_key',consul_token)
s = TimedJSONWebSignatureSerializer(secret_key)
3 changes: 2 additions & 1 deletion flask-consul/manager.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#!/usr/bin/env python3
from flask import Flask
from views import login, blackbox
from views import login, blackbox, consul

app = Flask(__name__)
app.register_blueprint(login.blueprint)
app.register_blueprint(blackbox.blueprint)
app.register_blueprint(consul.blueprint)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=2026)
120 changes: 120 additions & 0 deletions flask-consul/units/consul_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import requests,json
import sys
sys.path.append("..")
from config import consul_token,consul_url

headers = {'X-Consul-Token': consul_token}

def get_hosts():
url = f'{consul_url}/agent/host'
response = requests.get(url, headers=headers)
if response.status_code == 200:
info = response.json()
pmem = round(info["Memory"]["usedPercent"])
pdisk = round(info["Disk"]["usedPercent"])
host = {'hostname':info["Host"]["hostname"],'uptime':f'{round(info["Host"]["uptime"]/3600/24)}天',
'os':f'{info["Host"]["platform"]} {info["Host"]["platformVersion"]}','kernel':info["Host"]["kernelVersion"]}
cpu = {'cores':f'{len(info["CPU"])}核','vendorId':info["CPU"][0]["vendorId"],'modelName':info["CPU"][0]["modelName"]}
memory = {'total':f'{round(info["Memory"]["total"]/1024**3)}GB','available':f'{round(info["Memory"]["available"]/1024**3)}GB',
'used':f'{round(info["Memory"]["used"]/1024**3)}GB','usedPercent':f'{pmem}%'}
disk = {'path':info["Disk"]["path"],'fstype':info["Disk"]["fstype"],'total':f'{round(info["Disk"]["total"]/1024**3)}GB',
'free':f'{round(info["Disk"]["free"]/1024**3)}GB','used':f'{round(info["Disk"]["used"]/1024**3)}GB','usedPercent':f'{pdisk}%'}
return {'code': 20000,'host':host,'cpu':cpu,'memory':memory,'disk':disk, 'pmem':pmem, 'pdisk':pdisk}
else:
return {'code': 50000, 'data': f'{response.status_code}:{response.text}'}
def get_services():
url = f'{consul_url}/internal/ui/services'
response = requests.get(url, headers=headers)
if response.status_code == 200:
info = response.json()
services_list = [{'Name':i['Name'],'Datacenter':i['Datacenter'],'InstanceCount':i['InstanceCount'],'ChecksCritical':i['ChecksCritical'],'ChecksPassing':i['ChecksPassing'],'Tags':i['Tags'],'Nodes':list(set(i['Nodes']))} for i in info if i['Name'] != 'consul']
return {'code': 20000,'services':services_list}
else:
return {'code': 50000, 'data': f'{response.status_code}:{response.text}'}
def get_services_nameonly():
url = f'{consul_url}/catalog/services'
response = requests.get(url, headers=headers)
if response.status_code == 200:
info = response.json()
info.pop('consul')
return {'code': 20000,'services_name':list(info.keys())}
else:
return {'code': 50000, 'data': f'{response.status_code}:{response.text}'}
def get_instances(service_name):
url = f'{consul_url}/health/service/{service_name}'
response = requests.get(url, headers=headers)
if response.status_code == 200:
info = response.json()
instances_list = []
for i in info:
instance_dict = {}
instance_dict['ID'] = i['Service']['ID']
instance_dict['name'] = i['Service']['Service']
instance_dict['tags'] = '无' if i['Service']['Tags'] == [] else i['Service']['Tags']
instance_dict['address'] = i['Service'].get('Address')
instance_dict['port'] = i['Service'].get('Port')
if i['Service']['Meta'] == {} or i['Service']['Meta'] is None:
instance_dict['meta'] = '无'
else:
instance_dict['meta'] = [i['Service']['Meta']]
instance_dict['meta_label'] = [{'prop': x, 'label': x} for x in i['Service']['Meta'].keys()]
if len(i['Checks']) ==2:
instance_dict['status'] = i['Checks'][1]['Status']
instance_dict['output'] = i['Checks'][1]['Output']
else:
instance_dict['status'] = '无'
instance_dict['output'] = '无'
instances_list.append(instance_dict)
return {'code': 20000,'instances':instances_list}
else:
return {'code': 50000, 'data': f'{response.status_code}:{response.text}'}

def del_instance(service_id):
reg = requests.put(f'{consul_url}/agent/service/deregister/{service_id}', headers=headers)
if reg.status_code == 200:
return {"code": 20000, "data": f"【{service_id}】删除成功!"}
else:
return {"code": 50000, "data": f"{reg.status_code}{service_id}{reg.text}"}

def add_instance(instance_dict):
isMeta = instance_dict['metaInfo']['isMeta']
isCheck = instance_dict['checkInfo']['isCheck']
address = instance_dict['address']
port = None if instance_dict['port'] == '' else int(instance_dict['port'])
instance_dict['port'] = port
if isMeta:
try:
metaJson = json.loads(instance_dict['metaInfo']['metaJson'])
instance_dict['meta'] = metaJson
except:
return {"code": 50000, "data": "Meta必须JSON字符串格式!"}
if isCheck:
ctype = instance_dict['checkInfo']['ctype']
interval = instance_dict['checkInfo']['interval']
timeout = instance_dict['checkInfo']['timeout']
if instance_dict['checkInfo']['isAddress'] == 'true':
if port is not None and address != '' and ctype != 'HTTP':
checkaddress = f'{address}:{port}'
elif port is not None and address != '' and ctype == 'HTTP':
checkaddress = f'http://{address}:{port}'
else:
return {"code": 50000, "data": "健康检查地址使用与实例IP端口一致时,地址/端口不可为空!"}
else:
checkaddress = instance_dict['checkInfo']['caddress']
if checkaddress == '':
return {"code": 50000, "data": "自定义健康检查,地址信息不可为空!"}

check = {ctype: checkaddress,"Interval": interval,"Timeout": timeout}
instance_dict['check'] = check

del instance_dict['metaInfo']
del instance_dict['checkInfo']
print(instance_dict)

reg = requests.put(f'{consul_url}/agent/service/register', headers=headers, data=json.dumps(instance_dict))
sid = instance_dict['ID']
if reg.status_code == 200:
return {"code": 20000, "data": f"【{sid}】增加成功!"}
else:
return {"code": 50000, "data": f"{reg.status_code}{sid}{reg.text}"}

48 changes: 48 additions & 0 deletions flask-consul/views/consul.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from flask import Blueprint
from flask_restful import reqparse, Resource, Api
import sys
sys.path.append("..")
from units import token_auth,consul_manager

blueprint = Blueprint('consul',__name__)
api = Api(blueprint)

parser = reqparse.RequestParser()
parser.add_argument('service_name',type=str)
parser.add_argument('sid',type=str)
parser.add_argument('instance_dict',type=dict)

class ConsulApi(Resource):
decorators = [token_auth.auth.login_required]
def get(self, stype):
if stype == 'services':
return consul_manager.get_services()
elif stype == 'services_name':
return consul_manager.get_services_nameonly()
elif stype == 'instances':
args = parser.parse_args()
return consul_manager.get_instances(args['service_name'])
elif stype == 'hosts':
return consul_manager.get_hosts()

def post(self, stype):
if stype == 'sid':
args = parser.parse_args()
return consul_manager.add_instance(args['instance_dict'])

def put(self, stype):
if stype == 'sid':
args = parser.parse_args()
resp_del = consul_manager.del_instance(args['sid'])
resp_add = consul_manager.add_instance(args['instance_dict'])
if resp_del["code"] == 20000 and resp_add["code"] == 20000:
return {"code": 20000, "data": f"更新成功!"}
else:
return {"code": 50000, "data": f"更新失败!"}

def delete(self, stype):
if stype == 'sid':
args = parser.parse_args()
return consul_manager.del_instance(args['sid'])

api.add_resource(ConsulApi, '/api/consul/<stype>')
3 changes: 2 additions & 1 deletion vue-consul/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ module.exports = {
// add your custom rules here
//it is base on https://github.com/vuejs/eslint-config-vue
rules: {
"no-irregular-whitespace": "off",
"vue/html-quotes": "off",
"vue/max-attributes-per-line": [2, {
"singleline": 10,
"multiline": {
Expand Down Expand Up @@ -96,7 +98,6 @@ module.exports = {
'no-implied-eval': 2,
'no-inner-declarations': [2, 'functions'],
'no-invalid-regexp': 2,
'no-irregular-whitespace': 2,
'no-iterator': 2,
'no-label-var': 2,
'no-labels': [2, {
Expand Down
54 changes: 54 additions & 0 deletions vue-consul/src/api/consul.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import request from '@/utils/request-ops'

export function getHosts() {
return request({
url: '/api/consul/hosts',
method: 'get'
})
}

export function getServices() {
return request({
url: '/api/consul/services',
method: 'get'
})
}

export function getServicesName() {
return request({
url: '/api/consul/services_name',
method: 'get'
})
}

export function getInstances(service_name) {
return request({
url: '/api/consul/instances',
method: 'get',
params: { service_name }
})
}

export function delSid(sid) {
return request({
url: '/api/consul/sid',
method: 'delete',
params: { sid }
})
}

export function addSid(instance_dict) {
return request({
url: '/api/consul/sid',
method: 'post',
data: { instance_dict }
})
}

export function updateSid(sid, instance_dict) {
return request({
url: '/api/consul/sid',
method: 'put',
data: { sid, instance_dict }
})
}
56 changes: 53 additions & 3 deletions vue-consul/src/router/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export const constantRoutes = [
{
path: '/',
component: Layout,
redirect: '/blackbox/index',
redirect: '/dashboard',
children: [{
path: 'dashboard',
name: 'Dashboard',
Expand All @@ -55,16 +55,66 @@ export const constantRoutes = [
}]
},

{
path: '/consul',
component: Layout,
redirect: '/consul/services',
name: 'Consul 管理',
meta: { title: 'Consul 管理', icon: 'example' },
children: [
{
path: 'hosts',
name: 'Hosts',
component: () => import('@/views/consul/hosts'),
meta: { title: 'Hosts', icon: 'el-icon-school' }
},
{
path: 'services',
name: 'Services',
component: () => import('@/views/consul/services'),
meta: { title: 'Services', icon: 'el-icon-news' }
},
{
path: 'instances',
name: 'Instances',
component: () => import('@/views/consul/instances'),
meta: { title: 'Instances', icon: 'el-icon-connection' }
}
]
},
{
path: '/blackbox',
component: Layout,
children: [{
path: 'index',
name: '站点监控',
name: 'Blackbox 站点监控',
component: () => import('@/views/blackbox/index'),
meta: { title: '站点监控', icon: 'tree' }
meta: { title: 'Blackbox 站点监控', icon: 'tree' }
}]
},
{
path: '友情链接',
component: Layout,
meta: { title: '友情链接', icon: 'link' },
children: [
{
path: 'https://starsl.cn',
meta: { title: 'StarsL.cn', icon: 'el-icon-s-custom' }
},
{
path: 'https://github.com/starsliao?tab=repositories',
meta: { title: '我的Github', icon: 'el-icon-star-off' }
},
{
path: 'https://grafana.com/orgs/starsliao/dashboards',
meta: { title: '我的Grafana', icon: 'el-icon-odometer' }
},
{
path: 'https://starsl.cn/static/img/qr.png',
meta: { title: '我的公众号', icon: 'el-icon-chat-dot-round' }
}
]
},

// 404 page must be placed at the end !!!
{ path: '*', redirect: '/404', hidden: true }
Expand Down
2 changes: 1 addition & 1 deletion vue-consul/src/settings.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module.exports = {

title: 'Blackbox Manager',
title: 'Consul Manager',

/**
* @type {boolean} true | false
Expand Down
Loading

0 comments on commit 1590ac3

Please sign in to comment.