nginx-site-discovery/nginx_site_discovery/extract_sites.py

111 lines
3.3 KiB
Python

import os
from collections import namedtuple
OPT_PREFIX = 'monitoring:'
DEFAULT_HEALTH_PATH = '/'
Job = namedtuple('Target', ['targets', 'labels'])
def parse_listen(words):
scheme = 'http'
port = 80
parse_discovery_opt = False
labels = {}
ip = None
for word in words:
if parse_discovery_opt:
opt_name, _, opt_value = word.partition('=')
if opt_name == 'ignore':
return None
elif opt_name == 'healthcheck_url':
extra_labels['healthcheck_url'] = opt_value
elif ':' in word or word.isdecimal():
ip, _sep, port = word.rpartition(':')
port = int(port)
elif word == 'ssl':
scheme = 'https'
elif word == '#':
parse_discovery_opt = True
return {
'scheme': scheme,
'port': port,
'ip': ip,
'labels': labels
}
def parse_server_name(words):
return [word for word in words[1::] if word != 'default']
def parse_opt(words):
opt = {}
for word in words:
if word.startswith(OPT_PREFIX):
if '=' in word:
name, _, value = word.partition('=')
opt[name[len(OPT_PREFIX):]] = value
else:
opt[word[len(OPT_PREFIX):]] = True
return opt
def extract_site(config_file):
server = {'listens':[], 'healthcheck_url': DEFAULT_HEALTH_PATH}
servers = []
with open(config_file) as fd:
for line in fd:
line, _, comment = line.partition('#')
words = line.replace(';', '').split()
opt = parse_opt(comment.split())
if words and 'server' == words[0]:
servers.append(server)
server = {'listens':[], 'healthcheck_url': DEFAULT_HEALTH_PATH}
elif words and 'listen' == words[0] and not opt.get('ignore'):
server['listens'].append(parse_listen(words))
elif words and 'server_name' == words[0]:
server['names'] = parse_server_name(words)
if 'healthcheck_url' in opt:
server['healthcheck_url'] = opt['healthcheck_url']
servers.append(server)
return servers
def build_urls(servers):
jobs = []
for server in servers:
for listens in filter(None, server['listens']):
scheme = listens['scheme']
port = listens['port']
ip = listens['ip']
job = Job([], {'healthcheck_url': server['healthcheck_url']})
if 'names' in server:
for host in server['names']:
url = '%s://%s' % (scheme, host)
if (scheme == 'http' and port != 80) or (scheme == 'https' and port != 443):
url += ':%d' % port
job.targets.append(url)
elif ip:
url = '%s://%s:%d' % (scheme, ip, port)
job.targets.append(url)
if job.targets:
jobs.append(job)
return jobs
def walk_sites_enabled(path, extension):
jobs = []
for (root, _dirs, files) in os.walk(path):
for config in files:
if config.endswith(extension):
config_urls = build_urls(extract_site(os.path.join(root, config)))
jobs.extend(config_urls)
return jobs