From 6805182b17c8bfe0184057fecda91cf1268540f3 Mon Sep 17 00:00:00 2001 From: anima Date: Sun, 23 Feb 2025 02:45:17 +0100 Subject: [PATCH] inital version check swarmpit --- checks/check_api_swarmpit.py | 147 +++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 checks/check_api_swarmpit.py diff --git a/checks/check_api_swarmpit.py b/checks/check_api_swarmpit.py new file mode 100644 index 0000000..84cdd1e --- /dev/null +++ b/checks/check_api_swarmpit.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 +"""Check docker via swarmpit python check""" +"""dependencys: +- pip3 install nagiosplugin +- pip3 install argparse +- pip3 install requests +""" + +__version__ = '0.1.0' +__author__ = 'anima' + +# imports +import logging +import argparse +import nagiosplugin +import requests +import json + +# log settings +logging.basicConfig(format='[%(asctime)s] %(levelname)s %(message)s', level=logging.INFO) + +## API +class SwarmpitAPI: + def __init__(self, host:str, token:str, port:int = 8080, ssl:bool = False) -> None: + self.host = host + self.port = port + self.token = token + self.ssl = ssl + + def __query(self, query:str, query_type:str = 'get', data:dict = None) -> dict | None: + protocol = 'http' + if self.port is None and self.ssl: + self.port = 443 + elif self.port is None: + self.port = 80 + if self.ssl: + protocol += 's' + headers = dict() + headers['Content-Type'] = 'application/json' + headers['Authorization'] = f'Bearer {self.token}' + match query_type: + case 'get': + response = requests.get(f'{protocol}://{self.host}:{self.port}/api/{query}', headers=headers, verify=False) + case 'post': + response = requests.post(f'{protocol}://{self.host}:{self.port}/api/{query}', headers=headers, verify=False) + + if response.status_code == 200: + if 'application/json' in response.headers['Content-Type']: + json_response = json.loads(response.text) + return json_response + else: + return response.content + else: + logging.error(f'non successfull response {response.content} [{response.status_code}]') + logging.debug(f'{response.request.url=}') + logging.debug(f'{response.request.headers=}') + logging.debug(f'{response.request.body=}') + return None + + def statistics(self): + return self.__query('stats') + + +# +# Check Swarm Cores +# +class DockerSwarmCoresResource(nagiosplugin.Resource): + def __init__(self, api) -> None: + self.api = api + + def probe(self) -> list: + """check core usage of full swarm + + Returns: + nagiosplugin.Metric: single metric element (return) + """ + data = self.api.statistics() + cpu = data['cpu'] + cpu_usage_percent = round((cpu['usage'] / cpu['cores']) * 100, 2) + + return nagiosplugin.Metric(name='load', value=cpu_usage_percent, uom='%', context='scalar_context') + + +## Args +def parse_args() -> argparse.Namespace: + """evaluates given arguments + + Returns: + argsparse.Namespace: Namespace Object with all arguments insert (use: args.long_name_of_argument) + """ + argp = argparse.ArgumentParser(description=__doc__) + # Default args + argp.add_argument('-v', '--verbose', action='count', default=0, + help='increase output verbosity (use up to 3 times)') + argp.add_argument('-H', '--hostname', default='localhost', + help='IP address or hostname of device to query') + argp.add_argument('-t', '--timeout', default=30, + help='abort execution after TIMEOUT seconds') + # TEMPLATE TODO: edit choices + argp.add_argument('-m', '--check_mode', + choices=[ + 'load', + ], + help='check mode to run') + + # Nagios args / see https://nagios-plugins.org/doc/guidelines.html#THRESHOLDFORMAT + argp.add_argument('-w', '--warning', default=':80', + help='warning threshold') + argp.add_argument('-c', '--critical', default=':90', + help='critical threshold') + + # API args + argp.add_argument('-A', '--api-host', + help='Swarmpit API host') + argp.add_argument('-P', '--api-port', default=8080, + help='Swarmpot API port') + argp.add_argument('-S', '--api-ssl', action='store_true', + help='Must set if Swarmpit API use https') + argp.add_argument('-T', '--api-token', + help='Swarmpit API Token') + + args = argp.parse_args() + return args + +## run +def main(): + args = parse_args() + if args.verbose >= 3: + logging.getLogger().setLevel(logging.DEBUG) + + # dice which check will be run bases on check_mode + api = SwarmpitAPI(host=args.api_host, token=args.api_token, port=args.api_port, ssl=args.api_ssl) + match args.check_mode: + case 'load': + check = nagiosplugin.Check( + DockerSwarmCoresResource(api=api), + nagiosplugin.ScalarContext(name='scalar_context', warning=args.warning, critical=args.critical), + nagiosplugin.Summary()) + check.name = "swarm load" + + case _: + raise nagiosplugin.CheckError(f'Unknown check mode: {args.check_mode}') + + check.main(args.verbose, args.timeout) + +if __name__ == '__main__': + main() \ No newline at end of file