parent
9eb050173f
commit
3a19623351
|
@ -48,6 +48,7 @@ services:
|
|||
image: mariadb:10
|
||||
labels:
|
||||
restic-compose-backup.mariadb: true
|
||||
restic-compose-backup.tags: db,test
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=my-secret-pw
|
||||
- MYSQL_DATABASE=mydb
|
||||
|
@ -71,6 +72,7 @@ services:
|
|||
image: itzg/minecraft-server
|
||||
labels:
|
||||
restic-compose-backup.minecraft: true
|
||||
restic-compose-backup.tags: "test,foo,bar"
|
||||
restic-compose-backup.volumes.include: "minecraft"
|
||||
environment:
|
||||
- RCON_PASSWORD=minecraft
|
||||
|
|
|
@ -316,6 +316,7 @@ def cleanup(config, containers):
|
|||
config.keep_monthly,
|
||||
config.keep_yearly,
|
||||
config.keep_tags,
|
||||
config.filter_tags
|
||||
)
|
||||
logger.info('Prune stale data freeing storage space')
|
||||
prune_result = restic.prune(config.repository)
|
||||
|
|
|
@ -28,6 +28,7 @@ class Config:
|
|||
self.keep_monthly = os.environ.get('KEEP_MONTHLY') or "12"
|
||||
self.keep_yearly = os.environ.get('KEEP_YEARLY') or "3"
|
||||
self.keep_tags = os.environ.get('KEEP_TAGS') or "keep"
|
||||
self.filter_tags = os.environ.get('FILTER_TAGS') or ""
|
||||
|
||||
if check:
|
||||
self.check()
|
||||
|
|
|
@ -186,6 +186,11 @@ class Container:
|
|||
"""Is this container the running backup process?"""
|
||||
return self.get_label(self.backup_process_label) == 'True'
|
||||
|
||||
@property
|
||||
def tags(self) -> str:
|
||||
"""Gets all backup tags"""
|
||||
return self.get_label(enums.LABEL_RESTIC_TAGS)
|
||||
|
||||
@property
|
||||
def is_running(self) -> bool:
|
||||
"""bool: Is the container running?"""
|
||||
|
|
|
@ -54,6 +54,7 @@ class MariadbContainer(Container):
|
|||
config.repository,
|
||||
self.backup_destination_path(),
|
||||
self.dump_command(),
|
||||
tags=self.tags
|
||||
)
|
||||
|
||||
def backup_destination_path(self) -> str:
|
||||
|
@ -115,6 +116,7 @@ class MysqlContainer(Container):
|
|||
config.repository,
|
||||
self.backup_destination_path(),
|
||||
self.dump_command(),
|
||||
tags=self.tags
|
||||
)
|
||||
|
||||
def backup_destination_path(self) -> str:
|
||||
|
@ -175,6 +177,7 @@ class PostgresContainer(Container):
|
|||
config.repository,
|
||||
self.backup_destination_path(),
|
||||
self.dump_command(),
|
||||
tags=self.tags
|
||||
)
|
||||
|
||||
def backup_destination_path(self) -> str:
|
||||
|
|
|
@ -64,7 +64,7 @@ class MinecraftContainer(Container):
|
|||
for mount in self.filter_mounts():
|
||||
backup_data = self.get_volume_backup_destination(mount, '/minecraft')
|
||||
logger.info('Backing up %s', mount.source)
|
||||
vol_result = restic.backup_files(config.repository, source=backup_data)
|
||||
vol_result = restic.backup_files(config.repository, source=backup_data, tags=self.tags)
|
||||
logger.debug('Minecraft backup exit code: %s', vol_result)
|
||||
if vol_result != 0:
|
||||
logger.error('Minecraft backup exited with non-zero code: %s', vol_result)
|
||||
|
|
|
@ -10,4 +10,6 @@ LABEL_MARIADB_ENABLED = 'restic-compose-backup.mariadb'
|
|||
|
||||
LABEL_BACKUP_PROCESS = 'restic-compose-backup.process'
|
||||
|
||||
LABEL_MINECRAFT_ENABLED = 'restic-compose-backup.minecraft'
|
||||
LABEL_MINECRAFT_ENABLED = 'restic-compose-backup.minecraft'
|
||||
|
||||
LABEL_RESTIC_TAGS = 'restic-compose-backup.tags'
|
|
@ -4,7 +4,7 @@ Restic commands
|
|||
import logging
|
||||
from typing import List, Tuple
|
||||
from subprocess import Popen, PIPE
|
||||
from restic_compose_backup import commands
|
||||
from restic_compose_backup import commands, utils
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -19,25 +19,29 @@ def init_repo(repository: str):
|
|||
]))
|
||||
|
||||
|
||||
def backup_files(repository: str, source='/volumes'):
|
||||
return commands.run(restic(repository, [
|
||||
def backup_files(repository: str, source='/volumes', tags=''):
|
||||
args = [
|
||||
"--verbose",
|
||||
"backup",
|
||||
source,
|
||||
]))
|
||||
source
|
||||
]
|
||||
args.extend(utils.format_tags(tags))
|
||||
return commands.run(restic(repository, args))
|
||||
|
||||
|
||||
def backup_from_stdin(repository: str, filename: str, source_command: List[str]):
|
||||
def backup_from_stdin(repository: str, filename: str, source_command: List[str], tags=''):
|
||||
"""
|
||||
Backs up from stdin running the source_command passed in.
|
||||
It will appear in restic with the filename (including path) passed in.
|
||||
"""
|
||||
dest_command = restic(repository, [
|
||||
args = [
|
||||
'backup',
|
||||
'--stdin',
|
||||
'--stdin-filename',
|
||||
filename,
|
||||
])
|
||||
]
|
||||
args.extend(utils.format_tags(tags))
|
||||
dest_command = restic(repository, args)
|
||||
|
||||
# pipe source command into dest command
|
||||
source_process = Popen(source_command, stdout=PIPE, bufsize=65536)
|
||||
|
@ -75,8 +79,8 @@ def is_initialized(repository: str) -> bool:
|
|||
return commands.run(restic(repository, ["snapshots", '--last'])) == 0
|
||||
|
||||
|
||||
def forget(repository: str, keeplast: str, hourly: str, daily: str, weekly: str, monthly: str, yearly: str, tags: str):
|
||||
return commands.run(restic(repository, [
|
||||
def forget(repository: str, keeplast: str, hourly: str, daily: str, weekly: str, monthly: str, yearly: str, keep_tags='', filter_tags=''):
|
||||
args = [
|
||||
'forget',
|
||||
'--group-by',
|
||||
'paths,tags',
|
||||
|
@ -91,10 +95,11 @@ def forget(repository: str, keeplast: str, hourly: str, daily: str, weekly: str,
|
|||
'--keep-monthly',
|
||||
monthly,
|
||||
'--keep-yearly',
|
||||
yearly,
|
||||
'--keep-tag',
|
||||
tags,
|
||||
]))
|
||||
yearly
|
||||
]
|
||||
args.extend(utils.format_tags(keep_tags, '--keep-tag'))
|
||||
args.extend(utils.format_tags(filter_tags))
|
||||
return commands.run(restic(repository, args))
|
||||
|
||||
|
||||
def prune(repository: str):
|
||||
|
|
|
@ -82,6 +82,25 @@ def strip_root(path):
|
|||
|
||||
return path
|
||||
|
||||
def format_tags(tags: str, arg = "--tag") -> List[str]:
|
||||
"""
|
||||
Takes a comma separated list of tags.
|
||||
Splits them and appends --tag to each tag.
|
||||
Use the output as the command line argument for the restic cli.
|
||||
Example: foo,bar,test becomes --tag foo --tag bar --tag test
|
||||
"""
|
||||
if not tags:
|
||||
return []
|
||||
|
||||
tags = tags.strip()
|
||||
splitTags = tags.split(",")
|
||||
output = []
|
||||
for tag in splitTags:
|
||||
tag = tag.strip()
|
||||
if tag:
|
||||
output.extend([arg, tag])
|
||||
|
||||
return output
|
||||
|
||||
@contextmanager
|
||||
def environment(name, value):
|
||||
|
|
Loading…
Reference in New Issue