From ab79c3ee6cb8aaa3a31b1ad1b4a7a42349b57081 Mon Sep 17 00:00:00 2001 From: Peter Sabaini Date: Sat, 5 Dec 2020 17:27:25 +0100 Subject: [PATCH] Fix: do not use charmhelpers in non-charm context In change I60141397f39e3b1b0274230db8d984934c98a08d charmhelper library is being used in the rabbitmq queue nrpe check. This is problematic as the check does not actually run in a charm context and therefore does not have access to the charm environment such as the current config. Additionally an issue in collating check results had been introduced. This change aims to fix these issues. Instead of using the charmhelper library, the cronspec is read out from the cron job definition itself, and the series is probed from /etc/lsb-release Change-Id: I952aeda31e997ccadb6cff62e3b0d46349650979 --- files/check_rabbitmq_queues.py | 23 ++++++++++++++++++----- unit_tests/test_nrpe_checks.py | 34 ++++++++++++++++++++++++---------- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/files/check_rabbitmq_queues.py b/files/check_rabbitmq_queues.py index 962ccc8e..0e5eb0ed 100755 --- a/files/check_rabbitmq_queues.py +++ b/files/check_rabbitmq_queues.py @@ -12,13 +12,20 @@ import argparse import os import sys -from charmhelpers.core.hookenv import config -from charmhelpers.core.host import CompareHostReleases, get_distrib_codename -if CompareHostReleases(get_distrib_codename()) > 'trusty': +lsb_dict = {} +with open("/etc/lsb-release") as f: + lsb = [s.split("=") for s in f.readlines()] + lsb_dict = dict([(k, v.strip()) for k, v in lsb]) + +if lsb_dict.get("DISTRIB_CODENAME") != "trusty": + # Trusty doesn't have croniter from croniter import croniter +CRONJOB = "/etc/cron.d/rabbitmq-stats" + + def gen_data_lines(filename): with open(filename, "rt") as fin: for line in fin: @@ -85,6 +92,12 @@ def get_cron_interval(cronspec, base): return it.get_next(datetime) - it.get_prev(datetime) +def get_stats_cron_schedule(): + with open(CRONJOB) as f: + cronjob = f.read() + return cronjob.split("root")[0].strip() + + def check_stats_file_freshness(stats_file, asof=None): """Check if a rabbitmq stats file is fresh @@ -97,7 +110,7 @@ def check_stats_file_freshness(stats_file, asof=None): if asof is None: asof = datetime.now() file_mtime = datetime.fromtimestamp(os.path.getmtime(stats_file)) - cronspec = config("stats_cron_schedule") + cronspec = get_stats_cron_schedule() interval = get_cron_interval(cronspec, asof) # We expect the file to be modified in the last 2 cron intervals cutoff_time = asof - (2 * interval) @@ -147,7 +160,7 @@ if __name__ == "__main__": if "croniter" in sys.modules.keys(): # not on trusty and imported croniter freshness_results = [check_stats_file_freshness(f) for f in args.stats_file] - criticals.append( + criticals.extend( msg for status, msg in freshness_results if status == "CRIT" ) diff --git a/unit_tests/test_nrpe_checks.py b/unit_tests/test_nrpe_checks.py index 20cbf603..228a7665 100644 --- a/unit_tests/test_nrpe_checks.py +++ b/unit_tests/test_nrpe_checks.py @@ -13,18 +13,32 @@ # limitations under the License. from datetime import datetime, timedelta -from tempfile import NamedTemporaryFile +from pathlib import Path +from tempfile import NamedTemporaryFile, TemporaryDirectory import unittest -from mock import MagicMock, patch import check_rabbitmq_queues class CheckRabbitTest(unittest.TestCase): - @patch( - "check_rabbitmq_queues.config", - MagicMock(return_value="*/5 * * * *"), - ) + + @classmethod + def setUpClass(cls): + cls.tmpdir = TemporaryDirectory() + cronjob = Path(cls.tmpdir.name) / "rabbitmq-stats" + with cronjob.open('w') as f: + f.write("*/5 * * * * root timeout -k 10s -s SIGINT 300 " + "/usr/local/bin/collect_rabbitmq_stats.sh 2>&1 | " + "logger -p local0.notice") + cls.old_cron = check_rabbitmq_queues.CRONJOB + check_rabbitmq_queues.CRONJOB = str(cronjob) + + @classmethod + def tearDownClass(cls): + """Tear down class fixture.""" + cls.tmpdir.cleanup() + check_rabbitmq_queues.CRONJOB = cls.old_cron + def test_check_stats_file_freshness_fresh(self): with NamedTemporaryFile() as stats_file: results = check_rabbitmq_queues.check_stats_file_freshness( @@ -32,10 +46,6 @@ class CheckRabbitTest(unittest.TestCase): ) self.assertEqual(results[0], "OK") - @patch( - "check_rabbitmq_queues.config", - MagicMock(return_value="*/5 * * * *"), - ) def test_check_stats_file_freshness_nonfresh(self): with NamedTemporaryFile() as stats_file: next_hour = datetime.now() + timedelta(hours=1) @@ -43,3 +53,7 @@ class CheckRabbitTest(unittest.TestCase): stats_file.name, asof=next_hour ) self.assertEqual(results[0], "CRIT") + + def test_get_stats_cron_schedule(self): + schedule = check_rabbitmq_queues.get_stats_cron_schedule() + self.assertEqual(schedule, "*/5 * * * *")