docker-tidy/dockertidy/Autostop.py

90 lines
2.9 KiB
Python
Raw Normal View History

2020-03-05 22:51:21 +00:00
#!/usr/bin/env python3
"""Stop long running docker iamges."""
import dateutil.parser
import docker
import docker.errors
import requests.exceptions
from dockertidy.Config import SingleConfig
from dockertidy.Logger import SingleLog
from dockertidy.Parser import timedelta
class AutoStop:
2020-03-06 21:39:32 +00:00
"""Autostop object to handle long running containers."""
2020-03-05 22:51:21 +00:00
def __init__(self):
self.config = SingleConfig()
self.log = SingleLog()
self.logger = SingleLog().logger
self.docker = self._get_docker_client()
def stop_containers(self):
2020-03-06 21:39:32 +00:00
"""Identify long running containers and terminate them."""
2020-03-05 22:51:21 +00:00
client = self.docker
config = self.config.config
max_run_time = timedelta(config["stop"]["max_run_time"])
prefix = config["stop"]["prefix"]
dry_run = config["dry_run"]
matcher = self._build_container_matcher(prefix)
2020-03-09 09:25:45 +00:00
self.logger.info(
"Stopping containers older than '{}'".format(
timedelta(config["stop"]["max_run_time"], dt_format="%Y-%m-%d, %H:%M:%S")
)
)
2020-03-05 22:51:21 +00:00
for container_summary in client.containers():
container = client.inspect_container(container_summary["Id"])
name = container["Name"].lstrip("/")
2020-03-09 09:25:45 +00:00
if (
prefix and matcher(name) and self._has_been_running_since(container, max_run_time)
) or (not prefix and self._has_been_running_since(container, max_run_time)):
2020-03-05 22:51:21 +00:00
self.logger.info(
"Stopping container %s %s: running since %s" %
(container["Id"][:16], name, container["State"]["StartedAt"])
)
if not dry_run:
self._stop_container(client, container["Id"])
def _stop_container(self, client, cid):
try:
client.stop(cid)
except requests.exceptions.Timeout as e:
self.logger.warn("Failed to stop container %s: %s" % (cid, e))
except docker.errors.APIError as ae:
self.logger.warn("Error stopping %s: %s" % (cid, ae))
def _build_container_matcher(self, prefixes):
def matcher(name):
return any(name.startswith(prefix) for prefix in prefixes)
return matcher
def _has_been_running_since(self, container, min_time):
started_at = container.get("State", {}).get("StartedAt")
if not started_at:
return False
return dateutil.parser.parse(started_at) <= min_time
def _get_docker_client(self):
config = self.config.config
2020-03-09 00:05:17 +00:00
return docker.APIClient(version="auto", timeout=config["http_timeout"])
def run(self):
"""Autostop main method."""
2020-03-09 09:25:45 +00:00
self.logger.info("Start autostop")
config = self.config.config
if config["stop"]["max_run_time"]:
self.stop_containers()
if not config["stop"]["max_run_time"]:
self.logger.warn("Skipped, no arguments given")