feat: Backup Secrets (copy secrets) #28
This commit is contained in:
parent
ebc0ea5d84
commit
5d4def6143
30
backupbot.py
30
backupbot.py
|
@ -9,9 +9,11 @@ import docker
|
|||
import restic
|
||||
from restic.errors import ResticFailedError
|
||||
from pathlib import Path
|
||||
from shutil import copyfile, rmtree
|
||||
#logging.basicConfig(level=logging.INFO)
|
||||
|
||||
VOLUME_PATH = "/var/lib/docker/volumes/"
|
||||
SECRET_PATH = '/secrets/'
|
||||
SERVICE = None
|
||||
|
||||
@click.group()
|
||||
|
@ -53,14 +55,15 @@ def export_secrets():
|
|||
@cli.command()
|
||||
def create():
|
||||
pre_commands, post_commands, backup_paths, apps = get_backup_cmds()
|
||||
copy_secrets(apps)
|
||||
backup_paths.append(SECRET_PATH)
|
||||
run_commands(pre_commands)
|
||||
backup_volumes(backup_paths, apps)
|
||||
run_commands(post_commands)
|
||||
|
||||
def get_backup_cmds():
|
||||
client = docker.from_env()
|
||||
containers = dict(map(lambda c: (
|
||||
c.labels['com.docker.swarm.service.name'], c), client.containers.list()))
|
||||
container_by_service = {c.labels['com.docker.swarm.service.name']: c for c in client.containers.list()}
|
||||
backup_paths = set()
|
||||
backup_apps = set()
|
||||
pre_commands = {}
|
||||
|
@ -73,7 +76,9 @@ def get_backup_cmds():
|
|||
if SERVICE and SERVICE != stack_name:
|
||||
continue
|
||||
backup_apps.add(stack_name)
|
||||
container = containers[s.name]
|
||||
container = container_by_service.get(s.name)
|
||||
if not container:
|
||||
logging.error("Container {s.name} is not running, hooks can not be executed")
|
||||
if prehook:= labels.get('backupbot.backup.pre-hook'):
|
||||
pre_commands[container] = prehook
|
||||
if posthook:= labels.get('backupbot.backup.post-hook'):
|
||||
|
@ -82,6 +87,25 @@ def get_backup_cmds():
|
|||
Path(VOLUME_PATH).glob(f"{stack_name}_*"))
|
||||
return pre_commands, post_commands, list(backup_paths), list(backup_apps)
|
||||
|
||||
def copy_secrets(apps):
|
||||
rmtree(SECRET_PATH, ignore_errors=True)
|
||||
os.mkdir(SECRET_PATH)
|
||||
client = docker.from_env()
|
||||
container_by_service = {c.labels['com.docker.swarm.service.name']: c for c in client.containers.list()}
|
||||
services = client.services.list()
|
||||
for s in services:
|
||||
app_name = s.attrs['Spec']['Labels']['com.docker.stack.namespace']
|
||||
if app_name in apps:
|
||||
if app_secs:= s.attrs['Spec']['TaskTemplate']['ContainerSpec'].get('Secrets'):
|
||||
if not container_by_service.get(s.name):
|
||||
logging.error("Container {s.name} is not running, secrets can not be copied.")
|
||||
continue
|
||||
container_id = container_by_service[s.name].id
|
||||
for sec in app_secs:
|
||||
src = f'/var/lib/docker/containers/{container_id}/mounts/secrets/{sec["SecretID"]}'
|
||||
dst = SECRET_PATH + sec['SecretName']
|
||||
copyfile(src, dst)
|
||||
|
||||
def run_commands(commands):
|
||||
for container, command in commands.items():
|
||||
if not command:
|
||||
|
|
|
@ -6,6 +6,7 @@ services:
|
|||
volumes:
|
||||
- "/var/run/docker.sock:/var/run/docker.sock"
|
||||
- "/var/lib/docker/volumes/:/var/lib/docker/volumes/"
|
||||
- "/var/lib/docker/containers/:/var/lib/docker/containers/:ro"
|
||||
- backups:/backups
|
||||
environment:
|
||||
- CRON_SCHEDULE
|
||||
|
|
Loading…
Reference in New Issue