Commit 2cecd072 authored by Łukasz Nowak's avatar Łukasz Nowak

Feature/promise surykatka improvements

Improvements:

 * total_seconds from surykatka is parsed
 * failure-amount is configurable
 * various smaller bugfixes

/reviewed-on nexedi/slapos.toolbox!77
parents ded03013 0d91448e
...@@ -24,13 +24,18 @@ class RunPromise(GenericPromise): ...@@ -24,13 +24,18 @@ class RunPromise(GenericPromise):
super(RunPromise, self).__init__(config) super(RunPromise, self).__init__(config)
# Set frequency compatible to default surykatka interval - 2 minutes # Set frequency compatible to default surykatka interval - 2 minutes
self.setPeriodicity(float(self.getConfig('frequency', 2))) self.setPeriodicity(float(self.getConfig('frequency', 2)))
self.failure_amount = int(
self.getConfig('failure-amount', self.getConfig('failure_amount', 1)))
self.result_count = self.failure_amount
self.error_list = [] self.error_list = []
self.info_list = [] self.info_list = []
# Make promise test-less, as it's result is not important for instantiation
self.setTestLess()
def appendError(self, message): def appendErrorMessage(self, message):
self.error_list.append(message) self.error_list.append(message)
def appendInfo(self, message): def appendInfoMessage(self, message):
self.info_list.append(message) self.info_list.append(message)
def emitLog(self): def emitLog(self):
...@@ -39,24 +44,30 @@ class RunPromise(GenericPromise): ...@@ -39,24 +44,30 @@ class RunPromise(GenericPromise):
else: else:
emit = self.logger.info emit = self.logger.info
emit(' '.join(self.error_list + self.info_list)) message_list = self.error_list + self.info_list
url = self.getConfig('url')
if url:
message_list.insert(0, '%s :' % (url,))
emit(' '.join(message_list))
def senseBotStatus(self): def senseBotStatus(self):
key = 'bot_status' key = 'bot_status'
def logError(msg, *args): def appendError(msg, *args):
self.appendError(key + ': ' + msg % args) self.appendErrorMessage(key + ': ERROR ' + msg % args)
if key not in self.surykatka_json: if key not in self.surykatka_json:
logError("%r not in %r", key, self.json_file) appendError("%r not in %r", key, self.json_file)
return return
bot_status_list = self.surykatka_json[key] bot_status_list = self.surykatka_json[key]
if len(bot_status_list) == 0: if len(bot_status_list) == 0:
logError("%r empty in %r", key, self.json_file) appendError("%r empty in %r", key, self.json_file)
return return
bot_status = bot_status_list[0] bot_status = bot_status_list[0]
if bot_status.get('text') != 'loop': if bot_status.get('text') != 'loop':
logError("No type loop detected in %r", self.json_file) appendError(
"bot_status is %r instead of 'loop' in %r",
str(bot_status.get('text')), self.json_file)
return return
timetuple = email.utils.parsedate(bot_status['date']) timetuple = email.utils.parsedate(bot_status['date'])
last_bot_datetime = datetime.datetime.fromtimestamp(time.mktime(timetuple)) last_bot_datetime = datetime.datetime.fromtimestamp(time.mktime(timetuple))
...@@ -64,23 +75,24 @@ class RunPromise(GenericPromise): ...@@ -64,23 +75,24 @@ class RunPromise(GenericPromise):
delta = self.utcnow - last_bot_datetime delta = self.utcnow - last_bot_datetime
# sanity check # sanity check
if delta < datetime.timedelta(minutes=0): if delta < datetime.timedelta(minutes=0):
logError('Last bot datetime %s is in future, UTC now %s', appendError('Last bot datetime %s is in future, UTC now %s',
last_bot_datetime_string, self.utcnow_string) last_bot_datetime_string, self.utcnow_string)
return return
if delta > datetime.timedelta(minutes=15): if delta > datetime.timedelta(minutes=15):
logError('Last bot datetime %s is more than 15 minutes old, UTC now %s', appendError(
'Last bot datetime %s is more than 15 minutes old, UTC now %s',
last_bot_datetime_string, self.utcnow_string) last_bot_datetime_string, self.utcnow_string)
return return
self.appendInfo( self.appendInfoMessage(
'%s: Last bot status from %s ok, UTC now is %s' % '%s: OK Last bot status from %s, UTC now is %s' %
(key, last_bot_datetime_string, self.utcnow_string)) (key, last_bot_datetime_string, self.utcnow_string))
def senseSslCertificate(self): def senseSslCertificate(self):
key = 'ssl_certificate' key = 'ssl_certificate'
def appendError(msg, *args): def appendError(msg, *args):
self.appendError(key + ': ' + msg % args) self.appendErrorMessage(key + ': ERROR ' + msg % args)
url = self.getConfig('url') url = self.getConfig('url')
parsed_url = urlparse(url) parsed_url = urlparse(url)
...@@ -104,46 +116,49 @@ class RunPromise(GenericPromise): ...@@ -104,46 +116,49 @@ class RunPromise(GenericPromise):
self.getConfig('certificate-expiration-days')) self.getConfig('certificate-expiration-days'))
return return
if not hostname: if not hostname:
appendError('url %r is incorrect', url) appendError('url is incorrect')
return return
if key not in self.surykatka_json: if key not in self.surykatka_json:
appendError( appendError(
'No data for %s . If the error persist, please update surykatka.', url) 'No key %r. If the error persist, please update surykatka.' % (key,))
return return
entry_list = [ entry_list = [
q for q in self.surykatka_json[key] if q['hostname'] == hostname] q for q in self.surykatka_json[key] if q['hostname'] == hostname]
if len(entry_list) == 0: if len(entry_list) == 0:
appendError('No data for %s', url) appendError('No data')
return return
for entry in entry_list: for entry in entry_list:
timetuple = email.utils.parsedate(entry['not_after']) timetuple = email.utils.parsedate(entry['not_after'])
if timetuple is None:
appendError('No certificate information for %s' % (entry['ip']))
else:
certificate_expiration_time = datetime.datetime.fromtimestamp( certificate_expiration_time = datetime.datetime.fromtimestamp(
time.mktime(timetuple)) time.mktime(timetuple))
if certificate_expiration_time - datetime.timedelta( if certificate_expiration_time - datetime.timedelta(
days=certificate_expiration_days) < self.utcnow: days=certificate_expiration_days) < self.utcnow:
appendError( appendError(
'Certificate for %s will expire on %s, which is less than %s days, ' 'Certificate on %s will expire on %s, which is less than %s days, '
'UTC now is %s', 'UTC now is %s',
url, entry['not_after'], certificate_expiration_days, entry['ip'], entry['not_after'], certificate_expiration_days,
self.utcnow_string) self.utcnow_string)
return return
else: else:
self.appendInfo( self.appendInfoMessage(
'%s: Certificate for %s will expire on %s, which is more than %s ' '%s: OK Certificate on %s will expire on %s, which is more than '
'days, UTC now is %s' % '%s days, UTC now is %s' %
(key, url, entry['not_after'], certificate_expiration_days, (key, entry['ip'], entry['not_after'], certificate_expiration_days,
self.utcnow_string)) self.utcnow_string))
return return
def senseHttpQuery(self): def senseHttpQuery(self):
key = 'http_query' key = 'http_query'
error_list = [] error = False
def logError(msg, *args): def appendError(msg, *args):
self.appendError(key + ': ' + msg % args) self.appendErrorMessage(key + ': ERROR ' + msg % args)
if key not in self.surykatka_json: if key not in self.surykatka_json:
logError("%r not in %r", key, self.json_file) appendError("%r not in %r", key, self.json_file)
return return
url = self.getConfig('url') url = self.getConfig('url')
...@@ -152,9 +167,8 @@ class RunPromise(GenericPromise): ...@@ -152,9 +167,8 @@ class RunPromise(GenericPromise):
entry_list = [q for q in self.surykatka_json[key] if q['url'] == url] entry_list = [q for q in self.surykatka_json[key] if q['url'] == url]
if len(entry_list) == 0: if len(entry_list) == 0:
logError('No data for %s', url) appendError('No data')
return return
error_list = []
for entry in entry_list: for entry in entry_list:
entry_status_code = str(entry['status_code']) entry_status_code = str(entry['status_code'])
if entry_status_code != status_code: if entry_status_code != status_code:
...@@ -165,26 +179,63 @@ class RunPromise(GenericPromise): ...@@ -165,26 +179,63 @@ class RunPromise(GenericPromise):
entry_status_code, status_code_explanation) entry_status_code, status_code_explanation)
else: else:
status_code_explanation = entry_status_code status_code_explanation = entry_status_code
error_list.append( appendError(
'IP %s got status code %s instead of %s' % ( 'IP %s got status code %s instead of %s' % (
entry['ip'], status_code_explanation, status_code)) entry['ip'], status_code_explanation, status_code))
error = True
db_ip_list = [q['ip'] for q in entry_list] db_ip_list = [q['ip'] for q in entry_list]
if len(ip_list): if len(ip_list):
if set(ip_list) != set(db_ip_list): if set(ip_list) != set(db_ip_list):
error_list.append( appendError(
'expected IPs %s differes from got %s' % ( 'expected IPs %s differes from got %s' % (
' '.join(ip_list), ' '.join(db_ip_list))) ' '.join(ip_list), ' '.join(db_ip_list)))
if len(error_list): error = True
logError('Problem with %s : ' % (url,) + ', '.join(error_list)) if error:
return return
if len(ip_list) > 0: if len(ip_list) > 0:
self.appendInfo( self.appendInfoMessage('%s: OK status code %s on IPs %s' % (
'%s: %s replied correctly with status code %s on ip list %s' % key, status_code, ' '.join(ip_list)))
(key, url, status_code, ' '.join(ip_list))) else:
self.appendInfoMessage('%s: OK with status code %s' % (
key, status_code))
def senseElapsedTime(self):
key = 'elapsed_time'
surykatka_key = 'http_query'
def appendError(msg, *args):
self.appendErrorMessage(key + ': ERROR ' + msg % args)
if surykatka_key not in self.surykatka_json:
appendError(
'No key %r. If the error persist, please update surykatka.' % (
surykatka_key,))
return
url = self.getConfig('url')
maximum_elapsed_time = self.getConfig('maximum-elapsed-time')
entry_list = [
q for q in self.surykatka_json[surykatka_key] if q['url'] == url]
if len(entry_list) == 0:
appendError('No data')
return
for entry in entry_list:
if maximum_elapsed_time:
if 'total_seconds' in entry:
maximum_elapsed_time = float(maximum_elapsed_time)
if entry['total_seconds'] == 0.:
appendError('IP %s failed to reply' % (entry['ip']))
elif entry['total_seconds'] > maximum_elapsed_time:
appendError(
'IP %s replied in %.2fs which is longer than '
'maximum %.2fs' %
(entry['ip'], entry['total_seconds'], maximum_elapsed_time))
else: else:
self.appendInfo( self.appendInfoMessage(
'%s: %s replied correctly with status code %s' % '%s: OK IP %s replied in %.2fs which is shorter than '
(key, url, status_code)) 'maximum %.2fs' % (key, entry['ip'],
entry['total_seconds'], maximum_elapsed_time))
def sense(self): def sense(self):
""" """
...@@ -202,13 +253,14 @@ class RunPromise(GenericPromise): ...@@ -202,13 +253,14 @@ class RunPromise(GenericPromise):
self.json_file = self.getConfig('json-file', '') self.json_file = self.getConfig('json-file', '')
if not os.path.exists(self.json_file): if not os.path.exists(self.json_file):
self.appendError('File %r does not exists' % self.json_file) self.appendErrorMessage('ERROR File %r does not exists' % self.json_file)
else: else:
with open(self.json_file) as fh: with open(self.json_file) as fh:
try: try:
self.surykatka_json = json.load(fh) self.surykatka_json = json.load(fh)
except Exception: except Exception:
self.appendError("Problem loading JSON from %r" % self.json_file) self.appendErrorMessage(
"ERROR loading JSON from %r" % self.json_file)
else: else:
report = self.getConfig('report') report = self.getConfig('report')
if report == 'bot_status': if report == 'bot_status':
...@@ -216,9 +268,12 @@ class RunPromise(GenericPromise): ...@@ -216,9 +268,12 @@ class RunPromise(GenericPromise):
elif report == 'http_query': elif report == 'http_query':
self.senseHttpQuery() self.senseHttpQuery()
self.senseSslCertificate() self.senseSslCertificate()
self.senseElapsedTime()
else: else:
self.appendError("Report %r is not supported" % report) self.appendErrorMessage(
"ERROR Report %r is not supported" % report)
self.emitLog() self.emitLog()
def anomaly(self): def anomaly(self):
return self._test(result_count=3, failure_amount=3) return self._test(
result_count=self.result_count, failure_amount=self.failure_amount)
...@@ -46,31 +46,31 @@ class CheckSurykatkaJSONMixin(TestPromisePluginMixin): ...@@ -46,31 +46,31 @@ class CheckSurykatkaJSONMixin(TestPromisePluginMixin):
class TestCheckSurykatkaJSON(CheckSurykatkaJSONMixin): class TestCheckSurykatkaJSON(CheckSurykatkaJSONMixin):
def test_no_config(self): def test_no_config(self):
self.writeSurykatkaPromise() self.writeSurykatkaPromise()
self.configureLauncher() self.configureLauncher(enable_anomaly=True)
with self.assertRaises(PromiseError): with self.assertRaises(PromiseError):
self.launcher.run() self.launcher.run()
self.assertFailedMessage( self.assertFailedMessage(
self.getPromiseResult(self.promise_name), self.getPromiseResult(self.promise_name),
"File '' does not exists") "ERROR File '' does not exists")
def test_not_existing_file(self): def test_not_existing_file(self):
self.writeSurykatkaPromise({'json-file': self.json_file}) self.writeSurykatkaPromise({'json-file': self.json_file})
self.configureLauncher() self.configureLauncher(enable_anomaly=True)
with self.assertRaises(PromiseError): with self.assertRaises(PromiseError):
self.launcher.run() self.launcher.run()
self.assertFailedMessage( self.assertFailedMessage(
self.getPromiseResult(self.promise_name), self.getPromiseResult(self.promise_name),
"File '%s' does not exists" % (self.json_file,)) "ERROR File '%s' does not exists" % (self.json_file,))
def test_empty_file(self): def test_empty_file(self):
self.writeSurykatkaPromise({'json-file': self.json_file}) self.writeSurykatkaPromise({'json-file': self.json_file})
self.writeSurykatkaJson('') self.writeSurykatkaJson('')
self.configureLauncher() self.configureLauncher(enable_anomaly=True)
with self.assertRaises(PromiseError): with self.assertRaises(PromiseError):
self.launcher.run() self.launcher.run()
self.assertFailedMessage( self.assertFailedMessage(
self.getPromiseResult(self.promise_name), self.getPromiseResult(self.promise_name),
"Problem loading JSON from '%s'" % (self.json_file,)) "ERROR loading JSON from '%s'" % (self.json_file,))
class TestCheckSurykatkaJSONUnknownReport(CheckSurykatkaJSONMixin): class TestCheckSurykatkaJSONUnknownReport(CheckSurykatkaJSONMixin):
...@@ -84,12 +84,12 @@ class TestCheckSurykatkaJSONUnknownReport(CheckSurykatkaJSONMixin): ...@@ -84,12 +84,12 @@ class TestCheckSurykatkaJSONUnknownReport(CheckSurykatkaJSONMixin):
self.writeSurykatkaJson("""{ self.writeSurykatkaJson("""{
} }
""") """)
self.configureLauncher() self.configureLauncher(enable_anomaly=True)
with self.assertRaises(PromiseError): with self.assertRaises(PromiseError):
self.launcher.run() self.launcher.run()
self.assertFailedMessage( self.assertFailedMessage(
self.getPromiseResult(self.promise_name), self.getPromiseResult(self.promise_name),
"Report 'NOT_EXISTING_ENTRY' is not supported") "ERROR Report 'NOT_EXISTING_ENTRY' is not supported")
class TestCheckSurykatkaJSONBotStatus(CheckSurykatkaJSONMixin): class TestCheckSurykatkaJSONBotStatus(CheckSurykatkaJSONMixin):
...@@ -110,12 +110,38 @@ class TestCheckSurykatkaJSONBotStatus(CheckSurykatkaJSONMixin): ...@@ -110,12 +110,38 @@ class TestCheckSurykatkaJSONBotStatus(CheckSurykatkaJSONMixin):
] ]
} }
""") """)
self.configureLauncher() self.configureLauncher(enable_anomaly=True)
self.launcher.run() self.launcher.run()
self.assertPassedMessage( self.assertPassedMessage(
self.getPromiseResult(self.promise_name), self.getPromiseResult(self.promise_name),
"bot_status: Last bot status from Fri, 13 Dec 2222 08:10:11 -0000 " "bot_status: OK Last bot status from Fri, 13 Dec 2222 08:10:11 -0000, "
"ok, UTC now is Wed, 13 Dec 2222 09:11:12 -0000" "UTC now is Wed, 13 Dec 2222 09:11:12 -0000"
)
def test_no_loop(self):
self.writeSurykatkaPromise(
{
'report': 'bot_status',
'json-file': self.json_file,
'test-utcnow': 'Wed, 13 Dec 2222 09:11:12 -0000'
}
)
self.writeSurykatkaJson("""{
"bot_status": [
{
"date": "Wed, 13 Dec 2222 09:10:11 -0000",
"text": "error"
}
]
}
""")
self.configureLauncher(enable_anomaly=True)
with self.assertRaises(PromiseError):
self.launcher.run()
self.assertFailedMessage(
self.getPromiseResult(self.promise_name),
"bot_status: ERROR bot_status is 'error' instead of 'loop' in '%s'" % (
self.json_file,)
) )
def test_bot_status_future(self): def test_bot_status_future(self):
...@@ -135,12 +161,12 @@ class TestCheckSurykatkaJSONBotStatus(CheckSurykatkaJSONMixin): ...@@ -135,12 +161,12 @@ class TestCheckSurykatkaJSONBotStatus(CheckSurykatkaJSONMixin):
] ]
} }
""") """)
self.configureLauncher() self.configureLauncher(enable_anomaly=True)
with self.assertRaises(PromiseError): with self.assertRaises(PromiseError):
self.launcher.run() self.launcher.run()
self.assertFailedMessage( self.assertFailedMessage(
self.getPromiseResult(self.promise_name), self.getPromiseResult(self.promise_name),
"bot_status: Last bot datetime Sat, 13 Dec 2223 08:10:11 -0000 is " "bot_status: ERROR Last bot datetime Sat, 13 Dec 2223 08:10:11 -0000 is "
"in future, UTC now Wed, 13 Dec 2222 09:11:12 -0000" "in future, UTC now Wed, 13 Dec 2222 09:11:12 -0000"
) )
...@@ -161,12 +187,12 @@ class TestCheckSurykatkaJSONBotStatus(CheckSurykatkaJSONMixin): ...@@ -161,12 +187,12 @@ class TestCheckSurykatkaJSONBotStatus(CheckSurykatkaJSONMixin):
] ]
} }
""") """)
self.configureLauncher() self.configureLauncher(enable_anomaly=True)
with self.assertRaises(PromiseError): with self.assertRaises(PromiseError):
self.launcher.run() self.launcher.run()
self.assertFailedMessage( self.assertFailedMessage(
self.getPromiseResult(self.promise_name), self.getPromiseResult(self.promise_name),
"bot_status: Last bot datetime Sat, 13 Dec 2223 08:10:11 -0000 is " "bot_status: ERROR Last bot datetime Sat, 13 Dec 2223 08:10:11 -0000 is "
"more than 15 minutes old, UTC now Wed, 13 Dec 2223 09:26:12 -0000" "more than 15 minutes old, UTC now Wed, 13 Dec 2223 09:26:12 -0000"
) )
...@@ -180,12 +206,12 @@ class TestCheckSurykatkaJSONBotStatus(CheckSurykatkaJSONMixin): ...@@ -180,12 +206,12 @@ class TestCheckSurykatkaJSONBotStatus(CheckSurykatkaJSONMixin):
self.writeSurykatkaJson("""{ self.writeSurykatkaJson("""{
} }
""") """)
self.configureLauncher() self.configureLauncher(enable_anomaly=True)
with self.assertRaises(PromiseError): with self.assertRaises(PromiseError):
self.launcher.run() self.launcher.run()
self.assertFailedMessage( self.assertFailedMessage(
self.getPromiseResult(self.promise_name), self.getPromiseResult(self.promise_name),
"bot_status: 'bot_status' not in '%s'" % (self.json_file,)) "bot_status: ERROR 'bot_status' not in '%s'" % (self.json_file,))
def test_empty_bot_status(self): def test_empty_bot_status(self):
self.writeSurykatkaPromise( self.writeSurykatkaPromise(
...@@ -198,12 +224,12 @@ class TestCheckSurykatkaJSONBotStatus(CheckSurykatkaJSONMixin): ...@@ -198,12 +224,12 @@ class TestCheckSurykatkaJSONBotStatus(CheckSurykatkaJSONMixin):
"bot_status": [] "bot_status": []
} }
""") """)
self.configureLauncher() self.configureLauncher(enable_anomaly=True)
with self.assertRaises(PromiseError): with self.assertRaises(PromiseError):
self.launcher.run() self.launcher.run()
self.assertFailedMessage( self.assertFailedMessage(
self.getPromiseResult(self.promise_name), self.getPromiseResult(self.promise_name),
"bot_status: 'bot_status' empty in '%s'" % (self.json_file,)) "bot_status: ERROR 'bot_status' empty in '%s'" % (self.json_file,))
class TestCheckSurykatkaJSONHttpQuery(CheckSurykatkaJSONMixin): class TestCheckSurykatkaJSONHttpQuery(CheckSurykatkaJSONMixin):
...@@ -255,15 +281,203 @@ class TestCheckSurykatkaJSONHttpQuery(CheckSurykatkaJSONMixin): ...@@ -255,15 +281,203 @@ class TestCheckSurykatkaJSONHttpQuery(CheckSurykatkaJSONMixin):
] ]
} }
""") """)
self.configureLauncher() self.configureLauncher(enable_anomaly=True)
self.launcher.run() self.launcher.run()
self.assertPassedMessage( self.assertPassedMessage(
self.getPromiseResult(self.promise_name), self.getPromiseResult(self.promise_name),
"http_query: https://www.erp5.com/ replied correctly with " "https://www.erp5.com/ : http_query: OK status code 302 on IPs "
"status code 302 on ip list 127.0.0.1 127.0.0.2 ssl_certificate: " "127.0.0.1 127.0.0.2 ssl_certificate: OK Certificate on 127.0.0.1 will "
"Certificate for https://www.erp5.com/ will expire on Mon, 13 Jul " "expire on Mon, 13 Jul 2020 12:00:00 -0000, which is more than 15 days, "
"2020 12:00:00 -0000, which is more than 15 days, UTC now is " "UTC now is Fri, 27 Dec 2019 15:11:12 -0000"
"Fri, 27 Dec 2019 15:11:12 -0000" )
def test_maximum_elapsed_time(self):
self.writeSurykatkaPromise(
{
'report': 'http_query',
'json-file': self.json_file,
'url': 'https://www.erp5.com/',
'status-code': '302',
'ip-list': '127.0.0.1 127.0.0.2',
'maximum-elapsed-time': '5',
'test-utcnow': 'Fri, 27 Dec 2019 15:11:12 -0000'
}
)
self.writeSurykatkaJson("""{
"http_query": [
{
"date": "Wed, 11 Dec 2019 09:35:28 -0000",
"ip": "127.0.0.1",
"status_code": 302,
"url": "https://www.erp5.com/",
"total_seconds": 4
},
{
"date": "Wed, 11 Dec 2019 09:35:28 -0000",
"ip": "127.0.0.2",
"status_code": 302,
"url": "https://www.erp5.com/",
"total_seconds": 4
},
{
"date": "Wed, 11 Dec 2019 09:35:28 -0000",
"ip": "176.31.129.213",
"status_code": 200,
"url": "https://www.erp5.org/",
"total_seconds": 4
}
],
"ssl_certificate": [
{
"date": "Fri, 27 Dec 2019 14:43:26 -0000",
"hostname": "www.erp5.com",
"ip": "127.0.0.1",
"not_after": "Mon, 13 Jul 2020 12:00:00 -0000"
},
{
"date": "Fri, 27 Dec 2019 14:43:26 -0000",
"hostname": "www.erp5.com",
"ip": "127.0.0.2",
"not_after": "Mon, 13 Jul 2020 12:00:00 -0000"
}
]
}
""")
self.configureLauncher(enable_anomaly=True)
self.launcher.run()
self.assertPassedMessage(
self.getPromiseResult(self.promise_name),
"https://www.erp5.com/ : http_query: OK status code 302 on IPs "
"127.0.0.1 127.0.0.2 ssl_certificate: OK Certificate on 127.0.0.1 will "
"expire on Mon, 13 Jul 2020 12:00:00 -0000, which is more than 15 days, "
"UTC now is Fri, 27 Dec 2019 15:11:12 -0000 elapsed_time: OK IP "
"127.0.0.1 replied in 4.00s which is shorter than maximum 5.00s "
"elapsed_time: OK IP 127.0.0.2 replied in 4.00s which is shorter than "
"maximum 5.00s"
)
def test_maximum_elapsed_time_too_long(self):
self.writeSurykatkaPromise(
{
'report': 'http_query',
'json-file': self.json_file,
'url': 'https://www.erp5.com/',
'status-code': '302',
'ip-list': '127.0.0.1 127.0.0.2',
'maximum-elapsed-time': '5',
'test-utcnow': 'Fri, 27 Dec 2019 15:11:12 -0000'
}
)
self.writeSurykatkaJson("""{
"http_query": [
{
"date": "Wed, 11 Dec 2019 09:35:28 -0000",
"ip": "127.0.0.1",
"status_code": 302,
"url": "https://www.erp5.com/",
"total_seconds": 6
},
{
"date": "Wed, 11 Dec 2019 09:35:28 -0000",
"ip": "127.0.0.2",
"status_code": 302,
"url": "https://www.erp5.com/",
"total_seconds": 0
},
{
"date": "Wed, 11 Dec 2019 09:35:28 -0000",
"ip": "176.31.129.213",
"status_code": 200,
"url": "https://www.erp5.org/",
"total_seconds": 4
}
],
"ssl_certificate": [
{
"date": "Fri, 27 Dec 2019 14:43:26 -0000",
"hostname": "www.erp5.com",
"ip": "127.0.0.1",
"not_after": "Mon, 13 Jul 2020 12:00:00 -0000"
},
{
"date": "Fri, 27 Dec 2019 14:43:26 -0000",
"hostname": "www.erp5.com",
"ip": "127.0.0.2",
"not_after": "Mon, 13 Jul 2020 12:00:00 -0000"
}
]
}
""")
self.configureLauncher(enable_anomaly=True)
with self.assertRaises(PromiseError):
self.launcher.run()
self.assertFailedMessage(
self.getPromiseResult(self.promise_name),
"https://www.erp5.com/ : elapsed_time: ERROR IP 127.0.0.1 replied in "
"6.00s which is longer than maximum 5.00s elapsed_time: ERROR IP "
"127.0.0.2 failed to reply http_query: OK status code 302 on IPs "
"127.0.0.1 127.0.0.2 ssl_certificate: OK Certificate on 127.0.0.1 will "
"expire on Mon, 13 Jul 2020 12:00:00 -0000, which is more than 15 days, "
"UTC now is Fri, 27 Dec 2019 15:11:12 -0000"
)
def test_maximum_elapsed_time_no_total_seconds(self):
self.writeSurykatkaPromise(
{
'report': 'http_query',
'json-file': self.json_file,
'url': 'https://www.erp5.com/',
'status-code': '302',
'ip-list': '127.0.0.1 127.0.0.2',
'maximum-elapsed-time': '5',
'test-utcnow': 'Fri, 27 Dec 2019 15:11:12 -0000'
}
)
self.writeSurykatkaJson("""{
"http_query": [
{
"date": "Wed, 11 Dec 2019 09:35:28 -0000",
"ip": "127.0.0.1",
"status_code": 302,
"url": "https://www.erp5.com/"
},
{
"date": "Wed, 11 Dec 2019 09:35:28 -0000",
"ip": "127.0.0.2",
"status_code": 302,
"url": "https://www.erp5.com/"
},
{
"date": "Wed, 11 Dec 2019 09:35:28 -0000",
"ip": "176.31.129.213",
"status_code": 200,
"url": "https://www.erp5.org/"
}
],
"ssl_certificate": [
{
"date": "Fri, 27 Dec 2019 14:43:26 -0000",
"hostname": "www.erp5.com",
"ip": "127.0.0.1",
"not_after": "Mon, 13 Jul 2020 12:00:00 -0000"
},
{
"date": "Fri, 27 Dec 2019 14:43:26 -0000",
"hostname": "www.erp5.com",
"ip": "127.0.0.2",
"not_after": "Mon, 13 Jul 2020 12:00:00 -0000"
}
]
}
""")
self.configureLauncher(enable_anomaly=True)
self.launcher.run()
self.assertPassedMessage(
self.getPromiseResult(self.promise_name),
"https://www.erp5.com/ : http_query: OK status code 302 on IPs "
"127.0.0.1 127.0.0.2 ssl_certificate: OK Certificate on 127.0.0.1 will "
"expire on Mon, 13 Jul 2020 12:00:00 -0000, which is more than 15 days, "
"UTC now is Fri, 27 Dec 2019 15:11:12 -0000"
) )
def test_http(self): def test_http(self):
...@@ -302,12 +516,12 @@ class TestCheckSurykatkaJSONHttpQuery(CheckSurykatkaJSONMixin): ...@@ -302,12 +516,12 @@ class TestCheckSurykatkaJSONHttpQuery(CheckSurykatkaJSONMixin):
] ]
} }
""") """)
self.configureLauncher() self.configureLauncher(enable_anomaly=True)
self.launcher.run() self.launcher.run()
self.assertPassedMessage( self.assertPassedMessage(
self.getPromiseResult(self.promise_name), self.getPromiseResult(self.promise_name),
"http_query: http://www.erp5.com/ replied correctly with " "http://www.erp5.com/ : http_query: OK status code 302 on IPs 127.0.0.1 "
"status code 302 on ip list 127.0.0.1 127.0.0.2" "127.0.0.2"
) )
def test_no_ip_list(self): def test_no_ip_list(self):
...@@ -357,14 +571,14 @@ class TestCheckSurykatkaJSONHttpQuery(CheckSurykatkaJSONMixin): ...@@ -357,14 +571,14 @@ class TestCheckSurykatkaJSONHttpQuery(CheckSurykatkaJSONMixin):
] ]
} }
""") """)
self.configureLauncher() self.configureLauncher(enable_anomaly=True)
self.launcher.run() self.launcher.run()
self.assertPassedMessage( self.assertPassedMessage(
self.getPromiseResult(self.promise_name), self.getPromiseResult(self.promise_name),
"http_query: https://www.erp5.com/ replied correctly with status " "https://www.erp5.com/ : http_query: OK with status code 302 "
"code 302 ssl_certificate: Certificate for https://www.erp5.com/ will " "ssl_certificate: OK Certificate on 127.0.0.1 will expire on Mon, 13 "
"expire on Mon, 13 Jul 2020 12:00:00 -0000, which is more than 15 " "Jul 2020 12:00:00 -0000, which is more than 15 days, UTC now is Fri, "
"days, UTC now is Fri, 27 Dec 2019 15:11:12 -0000" "27 Dec 2019 15:11:12 -0000"
) )
def test_no_http_query_data(self): def test_no_http_query_data(self):
...@@ -397,15 +611,15 @@ class TestCheckSurykatkaJSONHttpQuery(CheckSurykatkaJSONMixin): ...@@ -397,15 +611,15 @@ class TestCheckSurykatkaJSONHttpQuery(CheckSurykatkaJSONMixin):
] ]
} }
""") """)
self.configureLauncher() self.configureLauncher(enable_anomaly=True)
with self.assertRaises(PromiseError): with self.assertRaises(PromiseError):
self.launcher.run() self.launcher.run()
self.assertFailedMessage( self.assertFailedMessage(
self.getPromiseResult(self.promise_name), self.getPromiseResult(self.promise_name),
"http_query: No data for https://www.erp5.com/ ssl_certificate: " "https://www.erp5.com/ : http_query: ERROR No data elapsed_time: ERROR "
"Certificate for https://www.erp5.com/ will expire on Mon, 13 Jul " "No data ssl_certificate: OK Certificate on 127.0.0.1 will expire on "
"2020 12:00:00 -0000, which is more than 15 days, UTC now is " "Mon, 13 Jul 2020 12:00:00 -0000, which is more than 15 days, UTC now "
"Fri, 27 Dec 2019 15:11:12 -0000" "is Fri, 27 Dec 2019 15:11:12 -0000"
) )
def test_no_ssl_certificate_data(self): def test_no_ssl_certificate_data(self):
...@@ -444,14 +658,13 @@ class TestCheckSurykatkaJSONHttpQuery(CheckSurykatkaJSONMixin): ...@@ -444,14 +658,13 @@ class TestCheckSurykatkaJSONHttpQuery(CheckSurykatkaJSONMixin):
] ]
} }
""") """)
self.configureLauncher() self.configureLauncher(enable_anomaly=True)
with self.assertRaises(PromiseError): with self.assertRaises(PromiseError):
self.launcher.run() self.launcher.run()
self.assertFailedMessage( self.assertFailedMessage(
self.getPromiseResult(self.promise_name), self.getPromiseResult(self.promise_name),
"ssl_certificate: No data for https://www.erp5.com/ http_query: " "https://www.erp5.com/ : ssl_certificate: ERROR No data http_query: "
"https://www.erp5.com/ replied correctly with " "OK status code 302 on IPs 127.0.0.1 127.0.0.2"
"status code 302 on ip list 127.0.0.1 127.0.0.2"
) )
def test_no_ssl_certificate(self): def test_no_ssl_certificate(self):
...@@ -488,14 +701,14 @@ class TestCheckSurykatkaJSONHttpQuery(CheckSurykatkaJSONMixin): ...@@ -488,14 +701,14 @@ class TestCheckSurykatkaJSONHttpQuery(CheckSurykatkaJSONMixin):
] ]
} }
""") """)
self.configureLauncher() self.configureLauncher(enable_anomaly=True)
with self.assertRaises(PromiseError): with self.assertRaises(PromiseError):
self.launcher.run() self.launcher.run()
self.assertFailedMessage( self.assertFailedMessage(
self.getPromiseResult(self.promise_name), self.getPromiseResult(self.promise_name),
"ssl_certificate: No data for https://www.erp5.com/ . If the error " "https://www.erp5.com/ : ssl_certificate: ERROR No key "
"persist, please update surykatka. http_query: https://www.erp5.com/ " "'ssl_certificate'. If the error persist, please update surykatka. "
"replied correctly with status code 302 on ip list 127.0.0.1 127.0.0.2" "http_query: OK status code 302 on IPs 127.0.0.1 127.0.0.2"
) )
def test_bad_code(self): def test_bad_code(self):
...@@ -545,16 +758,15 @@ class TestCheckSurykatkaJSONHttpQuery(CheckSurykatkaJSONMixin): ...@@ -545,16 +758,15 @@ class TestCheckSurykatkaJSONHttpQuery(CheckSurykatkaJSONMixin):
] ]
} }
""") """)
self.configureLauncher() self.configureLauncher(enable_anomaly=True)
with self.assertRaises(PromiseError): with self.assertRaises(PromiseError):
self.launcher.run() self.launcher.run()
self.assertFailedMessage( self.assertFailedMessage(
self.getPromiseResult(self.promise_name), self.getPromiseResult(self.promise_name),
"http_query: Problem with https://www.erp5.com/ : IP 127.0.0.1 got " "https://www.erp5.com/ : http_query: ERROR IP 127.0.0.1 got status code "
"status code 302 instead of 301 ssl_certificate: Certificate for " "302 instead of 301 ssl_certificate: OK Certificate on 127.0.0.1 will "
"https://www.erp5.com/ will expire on Mon, 13 Jul 2020 12:00:00 " "expire on Mon, 13 Jul 2020 12:00:00 -0000, which is more than 15 days, "
"-0000, which is more than 15 days, UTC now is Fri, 27 Dec 2019 " "UTC now is Fri, 27 Dec 2019 15:11:12 -0000"
"15:11:12 -0000"
) )
def _test_bad_code_explanation(self, status_code, explanation): def _test_bad_code_explanation(self, status_code, explanation):
...@@ -592,16 +804,15 @@ class TestCheckSurykatkaJSONHttpQuery(CheckSurykatkaJSONMixin): ...@@ -592,16 +804,15 @@ class TestCheckSurykatkaJSONHttpQuery(CheckSurykatkaJSONMixin):
] ]
} }
""" % status_code) """ % status_code)
self.configureLauncher() self.configureLauncher(enable_anomaly=True)
with self.assertRaises(PromiseError): with self.assertRaises(PromiseError):
self.launcher.run() self.launcher.run()
self.assertFailedMessage( self.assertFailedMessage(
self.getPromiseResult(self.promise_name), self.getPromiseResult(self.promise_name),
"http_query: Problem with https://www.erp5.com/ : IP 127.0.0.1 got " "https://www.erp5.com/ : http_query: ERROR IP 127.0.0.1 got status code "
"status code %s instead of 301 ssl_certificate: Certificate for " "%s instead of 301 ssl_certificate: OK Certificate on 127.0.0.1 will "
"https://www.erp5.com/ will expire on Mon, 13 Jul 2020 12:00:00 " "expire on Mon, 13 Jul 2020 12:00:00 -0000, which is more than 15 days, "
"-0000, which is more than 15 days, UTC now is Fri, 27 Dec 2019 " "UTC now is Fri, 27 Dec 2019 15:11:12 -0000" % (explanation,)
"15:11:12 -0000" % explanation
) )
def test_bad_code_explanation_520(self): def test_bad_code_explanation_520(self):
...@@ -664,16 +875,16 @@ class TestCheckSurykatkaJSONHttpQuery(CheckSurykatkaJSONMixin): ...@@ -664,16 +875,16 @@ class TestCheckSurykatkaJSONHttpQuery(CheckSurykatkaJSONMixin):
] ]
} }
""") """)
self.configureLauncher() self.configureLauncher(enable_anomaly=True)
with self.assertRaises(PromiseError): with self.assertRaises(PromiseError):
self.launcher.run() self.launcher.run()
self.assertFailedMessage( self.assertFailedMessage(
self.getPromiseResult(self.promise_name), self.getPromiseResult(self.promise_name),
"http_query: Problem with https://www.erp5.com/ : expected IPs " "https://www.erp5.com/ : http_query: ERROR expected IPs 127.0.0.1 "
"127.0.0.1 127.0.0.2 differes from got 127.0.0.1 127.0.0.4 " "127.0.0.2 differes from got 127.0.0.1 127.0.0.4 ssl_certificate: "
"ssl_certificate: Certificate for https://www.erp5.com/ will expire " "OK Certificate on 127.0.0.1 will expire on Mon, 13 Jul 2020 12:00:00 "
"on Mon, 13 Jul 2020 12:00:00 -0000, which is more than 15 days, " "-0000, which is more than 15 days, UTC now is Fri, 27 Dec 2019 "
"UTC now is Fri, 27 Dec 2019 15:11:12 -0000" "15:11:12 -0000"
) )
def test_bad_ip_status_code(self): def test_bad_ip_status_code(self):
...@@ -724,15 +935,68 @@ class TestCheckSurykatkaJSONHttpQuery(CheckSurykatkaJSONMixin): ...@@ -724,15 +935,68 @@ class TestCheckSurykatkaJSONHttpQuery(CheckSurykatkaJSONMixin):
] ]
} }
""") """)
self.configureLauncher() self.configureLauncher(enable_anomaly=True)
with self.assertRaises(PromiseError): with self.assertRaises(PromiseError):
self.launcher.run() self.launcher.run()
self.assertFailedMessage( self.assertFailedMessage(
self.getPromiseResult(self.promise_name), self.getPromiseResult(self.promise_name),
"http_query: Problem with https://www.erp5.com/ : IP 127.0.0.1 got " "https://www.erp5.com/ : http_query: ERROR IP 127.0.0.1 got status code "
"status code 302 instead of 301, expected IPs 127.0.0.1 127.0.0.2 " "302 instead of 301 http_query: ERROR expected IPs 127.0.0.1 127.0.0.2 "
"differes from got 127.0.0.1 127.0.0.4 ssl_certificate: Certificate " "differes from got 127.0.0.1 127.0.0.4 ssl_certificate: OK Certificate "
"for https://www.erp5.com/ will expire on Mon, 13 Jul 2020 12:00:00 " "on 127.0.0.1 will expire on Mon, 13 Jul 2020 12:00:00 -0000, which is "
"-0000, which is more than 15 days, UTC now is Fri, 27 Dec 2019 " "more than 15 days, UTC now is Fri, 27 Dec 2019 15:11:12 -0000"
"15:11:12 -0000" )
def test_https_no_cert(self):
self.writeSurykatkaPromise(
{
'report': 'http_query',
'json-file': self.json_file,
'url': 'https://www.erp5.com/',
'status-code': '301',
'ip-list': '127.0.0.1 127.0.0.2',
'test-utcnow': 'Fri, 27 Dec 2019 15:11:12 -0000'
}
)
self.writeSurykatkaJson("""{
"http_query": [
{
"date": "Wed, 11 Dec 2019 09:35:28 -0000",
"ip": "127.0.0.1",
"status_code": 302,
"url": "https://www.erp5.com/"
},
{
"date": "Wed, 11 Dec 2019 09:35:28 -0000",
"ip": "127.0.0.4",
"status_code": 301,
"url": "https://www.erp5.com/"
}
],
"ssl_certificate": [
{
"date": "Fri, 27 Dec 2019 14:43:26 -0000",
"hostname": "www.erp5.com",
"ip": "127.0.0.1",
"not_after": null
},
{
"date": "Fri, 27 Dec 2019 14:43:26 -0000",
"hostname": "www.erp5.com",
"ip": "127.0.0.2",
"not_after": null
}
]
}
""")
self.configureLauncher(enable_anomaly=True)
with self.assertRaises(PromiseError):
self.launcher.run()
self.assertFailedMessage(
self.getPromiseResult(self.promise_name),
"https://www.erp5.com/ : http_query: ERROR IP 127.0.0.1 got status code "
"302 instead of 301 http_query: ERROR expected IPs 127.0.0.1 127.0.0.2 "
"differes from got 127.0.0.1 127.0.0.4 ssl_certificate: ERROR No "
"certificate information for 127.0.0.1 ssl_certificate: ERROR No "
"certificate information for 127.0.0.2"
) )
Markdown is supported
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