diff --git a/checks/check_api_swarmpit.py b/checks/check_api_swarmpit.py index 06b15cb..c01f854 100644 --- a/checks/check_api_swarmpit.py +++ b/checks/check_api_swarmpit.py @@ -6,7 +6,7 @@ - pip3 install requests """ -__version__ = '0.3.1' +__version__ = '0.4.0' __author__ = 'anima' # imports @@ -79,6 +79,9 @@ class SwarmpitAPI: """Service list""" return self.__query('services') + def stacks(self): + """Stack list""" + return self.__query('stacks') # # Check Swarm Cores @@ -108,7 +111,7 @@ class DockerSwarmServiceStatesResource(nagiosplugin.Resource): self.api = api def probe(self) -> list: - """check running services + """check running service states Returns: Generator[nagisplugin.Metric]: multiple metric elements (yield) @@ -151,6 +154,72 @@ class DockerSwarmServiceStatesResult(nagiosplugin.Result): return f'Service {self.metric.value["name"]} ({self.metric.value["image"]}) is {self.metric.value["state"]}' +class DockerSwarmServiceUpdatesResource(nagiosplugin.Resource): + def __init__(self, api) -> None: + self.api = api + + def probe(self) -> list: + """check service updates + + maybe problems incomming with rate limit: https://docs.docker.com/docker-hub/usage/ + + Returns: + Generator[nagisplugin.Metric]: multiple metric elements (yield) + """ + response = self.api.services() + + for service in response: + data = dict() + data['name'] = service['serviceName'] + data['image'] = service['repository']['name'] + data['tag'] = service['repository']['tag'] + data['imageDigest'] = service['repository']['imageDigest'] + + versions = requests.get(f'https://hub.docker.com/v2/repositories/{data["image"]}/tags/latest') + if versions.status_code == 200: + json_data = json.loads(versions.text) + if 'digest' in json_data.keys(): + data['latestDigest'] = json_data['digest'] + else: + logging.error(f'no digest in response {versions.content} [{versions.status_code}]') + logging.debug(f'{versions.request.url=}') + logging.debug(f'{versions.request.headers=}') + logging.debug(f'{versions.request.body=}') + data['latestDigest'] = None + elif versions.status_code == 404: + logging.error(f'non successfull response {versions.content} [{versions.status_code}]') + logging.debug(f'{versions.request.url=}') + logging.debug(f'{versions.request.headers=}') + logging.debug(f'{versions.request.body=}') + data['latestDigest'] = None + yield nagiosplugin.Metric(name='docker_service', value=data, context='docker_service') + + +class DockerSwarmServiceUpdatesContext(nagiosplugin.Context): + def __init__(self, name): + super().__init__(name, fmt_metric='{name} is', result_cls=DockerSwarmServiceUpdatesResult) + + def evaluate(self, metric, resource): + if metric.value['imageDigest'] == metric.value['latestDigest']: + return self.result_cls(nagiosplugin.Ok, "ok", metric) + elif metric.value['latestDigest'] is None: + return self.result_cls(nagiosplugin.Ok, "ok", metric) + else: + return self.result_cls(nagiosplugin.Warn, "warning", metric) + + return self.result_cls(nagiosplugin.Unknown, "unknown", metric) + + +class DockerSwarmServiceUpdatesResult(nagiosplugin.Result): + def __str__(self): + if self.metric.value['imageDigest'] == self.metric.value['latestDigest']: + return f'Service {self.metric.value["name"]} ({self.metric.value["image"]}:{self.metric.value["tag"]}) is up2date' + elif self.metric.value['latestDigest'] is None: + return f'Service {self.metric.value["name"]} ({self.metric.value["image"]}:{self.metric.value["tag"]}) can not checked' + else: + return f'Service {self.metric.value["name"]} ({self.metric.value["image"]}:{self.metric.value["tag"]}) has a newer latest version' + + # # Docker Swarm general summary # @@ -187,7 +256,8 @@ def parse_args() -> argparse.Namespace: argp.add_argument('-m', '--check_mode', choices=[ 'load', - 'service_states' + 'service_states', + 'service_updates' ], help='check mode to run') @@ -231,6 +301,12 @@ def main(): DockerSwarmServiceStatesContext(name='docker_service'), DockerSwarmSummary()) check.name = "swarm service states" + case 'service_updates': + check = nagiosplugin.Check( + DockerSwarmServiceUpdatesResource(api=api), + DockerSwarmServiceUpdatesContext(name='docker_service'), + DockerSwarmSummary()) + check.name = "swarm service updates" case _: raise nagiosplugin.CheckError(f'Unknown check mode: {args.check_mode}')