docker service stopper decorator

This commit is contained in:
John Lancaster
2024-05-27 00:51:59 -05:00
parent 8454e65460
commit 1a3696fd62
2 changed files with 70 additions and 5 deletions

View File

@@ -1,6 +1,7 @@
import json import json
import logging import logging
import subprocess import subprocess
from functools import partial
from pathlib import Path from pathlib import Path
import click import click
@@ -8,8 +9,9 @@ from rich.console import Console
from rich.logging import RichHandler from rich.logging import RichHandler
from rich.progress import Progress from rich.progress import Progress
from restic import loki, snapshots from restic import snapshots
from restic.console import console, logger from restic.console import console, logger
from restic.docker import manage_containers
from restic.loki import send_to_loki from restic.loki import send_to_loki
@@ -55,16 +57,35 @@ def run(backup_dir: Path, loki_url: str = None, tag: str = 'python-script'):
envvar='BACKUP_DIR', envvar='BACKUP_DIR',
) )
@click.option('--loki-url', type=str, help='Loki URL for logging', envvar='LOKI_URL') @click.option('--loki-url', type=str, help='Loki URL for logging', envvar='LOKI_URL')
@click.option('--tag', type=str, help='Tag to use in restic') @click.option('--tag', type=str, help='Tag to use in restic', default='python-script')
def main(backup_dir: Path, loki_url: str = None, tag: str = 'python-script'): @click.option(
'--project', type=str, help='Name of the Docker compose project to use when stopping containers'
)
@click.option(
'--services',
type=str,
help='Comma-delimited names of the Docker compose services to stop before backing up. ',
)
def main(
backup_dir: Path,
loki_url: str = None,
tag: str = 'python-script',
project: str = None,
services: str = None,
):
console = Console() console = Console()
logging.basicConfig( logging.basicConfig(
level='DEBUG', format='%(message)s', handlers=[RichHandler(markup=True, console=console)] level='DEBUG', format='%(message)s', handlers=[RichHandler(markup=True, console=console)]
) )
run(backup_dir, loki_url, tag) if project is not None and services is not None:
snapshots.run(loki_url) decorator = manage_containers(project=project, services=services.split(','))
func = decorator(run)
else:
func = run
func(backup_dir, loki_url, tag)
if __name__ == '__main__': if __name__ == '__main__':

44
src/restic/docker.py Normal file
View File

@@ -0,0 +1,44 @@
from functools import wraps
import docker
from docker.models.containers import Container
from restic.console import logger
def manage_containers(project: str, services: list[str]):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
client = docker.from_env()
containers: list[Container] = [
c
for c in client.containers.list()
if c.labels['com.docker.compose.project'] == project
and c.labels['com.docker.compose.service'] in services
]
try:
# Start the containers
for container in containers:
container.stop()
logger.info(f'Stopped container [blue]{container.name}[/]')
# Execute the wrapped function
result = func(*args, **kwargs)
except Exception as e:
# Handle exceptions and ensure containers are stopped
raise e
else:
return result
finally:
# Stop the containers
for container in containers:
container.start()
logger.info(f'Started container [blue]{container.name}[/]')
return wrapper
return decorator