11 Commits

Author SHA1 Message Date
3wc
2a7e564a24 Switch ENTRYPOINT to try to resolve loop on start 2024-10-01 22:43:12 -04:00
3wc
5f381f395d Update requirements 2024-10-01 22:43:12 -04:00
3wc
e0ee16426b Make entrypoint executable 2024-10-01 22:43:12 -04:00
3wc
92845c4142 Add --break-system-packages, surely we don't need a virtualenv 2024-10-01 22:43:12 -04:00
3wc
d0d0f29c79 Move entrypoint script into Docker image 2024-10-01 22:43:12 -04:00
3wc
88168de90e Move /entrypoint.sh to Dockerfile 2024-10-01 22:43:12 -04:00
3wc
71c88d0428 Remove redundant stuff from entrypoint 2024-10-01 22:43:12 -04:00
3wc
15b2d656bb Whoops, wrong image 2024-10-01 22:43:12 -04:00
3wc
46522a2e9a Switch to backup-bot-two image 2024-10-01 22:43:12 -04:00
3wc
30e88a972a Whoops skip shellcheck 2024-10-01 22:43:12 -04:00
3wc
64e09a6472 Reinstate Docker image 2024-10-01 22:43:12 -04:00
3 changed files with 9 additions and 18 deletions

View File

@ -4,8 +4,6 @@ SECRET_RESTIC_PASSWORD_VERSION=v1
COMPOSE_FILE=compose.yml
DOMAIN=backup-bot-two.example.com
RESTIC_REPOSITORY=/backups/restic
CRON_SCHEDULE='30 3 * * *'

View File

@ -10,7 +10,7 @@ Automatically take backups from all volumes of running Docker Swarm services and
* **Category**: Utilities
* **Status**: 0, work-in-progress
* **Image**: [`git.coopcloud.tech/coop-cloud/backup-bot-two`](https://git.coopcloud.tech/coop-cloud/-/packages/container/backup-bot-two), 4, upstream
* **Image**: [`thecoopcloud/backup-bot-two`](https://hub.docker.com/r/thecoopcloud/backup-bot-two), 4, upstream
* **Healthcheck**: No
* **Backups**: N/A
* **Email**: N/A

View File

@ -42,7 +42,7 @@ sys.excepthook = handle_exception
@click.option('-l', '--log', 'loglevel')
@click.option('-m', '--machine-logs', 'machine_logs', is_flag=True)
@click.option('service', '--host', '-h', envvar='SERVICE')
@click.option('repository', '--repo', '-r', envvar='RESTIC_REPOSITORY')
@click.option('repository', '--repo', '-r', envvar='RESTIC_REPOSITORY', required=True)
def cli(loglevel, service, repository, machine_logs):
global SERVICE
if service:
@ -54,25 +54,21 @@ def cli(loglevel, service, repository, machine_logs):
if not isinstance(numeric_level, int):
raise ValueError('Invalid log level: %s' % loglevel)
logger.setLevel(numeric_level)
logHandler = logging.StreamHandler()
if machine_logs:
logHandler = logging.StreamHandler()
formatter = jsonlogger.JsonFormatter(
"%(levelname)s %(filename)s %(lineno)s %(process)d %(message)s", rename_fields={"levelname": "message_type"})
logHandler.setFormatter(formatter)
logger.addHandler(logHandler)
logger.addHandler(logHandler)
export_secrets()
init_repo()
def init_repo():
if repo:= os.environ.get('RESTIC_REPOSITORY_FILE'):
# RESTIC_REPOSITORY_FILE and RESTIC_REPOSITORY are mutually exclusive
del os.environ['RESTIC_REPOSITORY']
else:
repo = os.environ['RESTIC_REPOSITORY']
restic.repository = repo
repo = os.environ['RESTIC_REPOSITORY']
logger.debug(f"set restic repository location: {repo}")
restic.repository = repo
restic.password_file = '/var/run/secrets/restic_password'
try:
restic.cat.config()
@ -108,7 +104,7 @@ def create(retries):
def get_backup_cmds():
client = docker.from_env()
container_by_service = {
c.labels.get('com.docker.swarm.service.name'): c for c in client.containers.list()}
c.labels['com.docker.swarm.service.name']: c for c in client.containers.list()}
backup_paths = set()
backup_apps = set()
pre_commands = {}
@ -143,14 +139,14 @@ def copy_secrets(apps):
os.mkdir(SECRET_PATH)
client = docker.from_env()
container_by_service = {
c.labels.get('com.docker.swarm.service.name'): c for c in client.containers.list()}
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 and
(app_secs := s.attrs['Spec']['TaskTemplate']['ContainerSpec'].get('Secrets'))):
if not container_by_service.get(s.name):
logger.warning(
logger.error(
f"Container {s.name} is not running, secrets can not be copied.")
continue
container_id = container_by_service[s.name].id
@ -161,7 +157,6 @@ def copy_secrets(apps):
f"For the secret {sec['SecretName']} the file {src} does not exist for {s.name}")
continue
dst = SECRET_PATH + sec['SecretName']
logger.debug("Copy Secret {sec['SecretName']}")
copyfile(src, dst)
@ -189,8 +184,6 @@ def run_commands(commands):
def backup_volumes(backup_paths, apps, retries, dry_run=False):
while True:
try:
logger.info("Start volume backup")
logger.debug(backup_paths)
result = restic.backup(backup_paths, dry_run=dry_run, tags=apps)
logger.summary("backup finished", extra=result)
return