Commit 19e3e44b authored by Bram Daams's avatar Bram Daams
Browse files

Merge branch '17-get-checks-by-tag' into 'master'

Resolve "get checks by tag"

Closes #17

See merge request !12
parents ec449087 676d8835
Pipeline #40693 passed with stage
in 47 seconds
......@@ -8,7 +8,7 @@ import json
import os
import re
import socket
import sys
from urllib.parse import quote_plus
import arrow
import click
......@@ -215,21 +215,25 @@ class Healthchecks:
def __init__(self, cred):
self.cred = cred
self.auth_headers = {'X-Api-Key': self.cred.api_key}
self.checks = self.get_checks()
def get_checks(self):
def get_checks(self, query=''):
"""Returns a list of checks from the HC API"""
url = "{}checks/".format(self.cred.api_url)
url = "{api_url}checks/{query}".format(
api_url=self.cred.api_url,
query=query
)
try:
response = requests.get(url, headers=self.auth_headers)
response.raise_for_status()
except requests.exceptions.HTTPError as err:
print(err)
sys.exit(1)
logging.error("bad response %s", err)
return None
if response:
return response.json()['checks']
logging.error('fetching cron checks failed')
raise Exception('fetching cron checks failed')
def find_check(self, job):
......@@ -239,19 +243,18 @@ class Healthchecks:
tag_for_job_id = 'job_id={job_id}'.format(job_id=job.id)
tag_for_host = 'host={hostname}'.format(hostname=socket.getfqdn())
# see if there's a check with tags matching both this host
# and the job_id
for check in self.checks:
found_job_id = False
found_host = False
for tag in check['tags'].split(' '):
if tag == tag_for_job_id:
found_job_id = True
elif tag == tag_for_host:
found_host = True
if found_job_id and found_host:
return check
query = "?&tag={tag1}&tag={tag2}".format(
tag1=quote_plus(tag_for_job_id),
tag2=quote_plus(tag_for_host)
)
checks = self.get_checks(query)
# we are only interrested if we found exactly one match
if checks and len(checks) == 1:
return checks[0]
# no result found
return None
def ping(self, check, ping_type=''):
......@@ -267,7 +270,7 @@ class Healthchecks:
)
response.raise_for_status()
except requests.exceptions.HTTPError as err:
print(err)
logging.error('could not ping, error: %s', err)
@staticmethod
def get_check_hash(check):
......@@ -454,7 +457,9 @@ class Healthchecks:
last_ping=""
))
for i in self.checks:
checks = self.get_checks()
for i in checks:
if status_filter and i['status'] != status_filter:
continue
......
......@@ -71,6 +71,7 @@ def run():
an environment variable JOB_TAGS. Seperate multiple tags with a comma.
"""
# pylint:disable=too-many-statements
# pylint:disable=too-many-branches
# we should have excactly two arguments
if len(sys.argv) != 3:
......@@ -103,27 +104,55 @@ def run():
api_url=url,
api_key=key
)
try_hc = True
except configparser.Error:
logging.error(
'Could not find/read/parse config'
'file sch.conf or /etc/sch.conf'
)
try_hc = False
if try_hc:
# we do have the API url/key from the configuration
# lets try to communicate with Healthchecks
# pylint:disable=broad-except
try:
health_checks = Healthchecks(cred)
except Exception:
logging.error('Could not connect to Healthchecks')
try_hc = False
# pylint:enable=broad-except
if not job_id or not try_hc or not job:
health_checks = Healthchecks(cred)
check = None
interfere = False
# pylint:disable=broad-except
try:
check = health_checks.find_check(job)
except Exception:
# do not update or create checks because of communication problems
logging.error('Ooops! Could not communicate with the healthchecks API')
interfere = False
else:
if check:
# existing check found
logging.debug(
"found check for cron job (job.id=%s)",
job.id,
)
is_new_check = False
health_checks.update_check(check, job)
interfere = True
else:
# new check to be created
logging.debug(
"no check found for cron job (job.id=%s)",
job.id,
)
is_new_check = True
check = health_checks.new_check(job)
if check:
interfere = True
else:
logging.error(
"Could not find or register check for given command. "
"Using read-only API keys? (job.id=%s)",
job.id,
)
# pylint:enable=broad-except
if not interfere or not job_id or not job:
# for some reason, we can't do much with Healthchecks
# at this point. So, we run the job without too much SCH
# interference
......@@ -136,38 +165,15 @@ def run():
# at this point, we're setup to do some smart stuff ;-)
# we know the exact cron configration for the job
# and we already communicated successfully with the
# configured Healthchecks instance
check = health_checks.find_check(job)
if check:
logging.debug(
"found check for cron job (job.id=%s)",
job.id,
)
is_new_check = False
health_checks.update_check(check, job)
else:
logging.debug(
"no check found for cron job (job.id=%s)",
job.id,
)
is_new_check = True
check = health_checks.new_check(job)
if not check:
logging.error(
"Could not find or register check for given command. "
"Using read-only API keys? (job.id=%s)",
job.id,
)
# and are able to communicate with healthchecks
# ping start
health_checks.ping(check, '/start')
# start timer
timer = TicToc()
timer.tic()
# execute command
logging.debug(
"Executing shell commmand: %s (job.id=%s)",
......@@ -175,6 +181,8 @@ def run():
job.id,
)
exit_code = execute_shell_command(command)
# stop timer
timer.toc()
logging.debug(
......
Supports Markdown
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