forked from coop-cloud/backup-bot-two
fix(download): dump volumes and secrets per default into /tmp/backup.tar.gz
This commit is contained in:
parent
79d19e7ac5
commit
66e1c9617d
64
backupbot.py
64
backupbot.py
@ -7,6 +7,8 @@ import subprocess
|
|||||||
import logging
|
import logging
|
||||||
import docker
|
import docker
|
||||||
import restic
|
import restic
|
||||||
|
import tarfile
|
||||||
|
import io
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from restic.errors import ResticFailedError
|
from restic.errors import ResticFailedError
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@ -235,50 +237,66 @@ def list_files(snapshot, path):
|
|||||||
@click.option('volumes', '--volumes', '-v', is_flag=True)
|
@click.option('volumes', '--volumes', '-v', is_flag=True)
|
||||||
@click.option('secrets', '--secrets', '-c', is_flag=True)
|
@click.option('secrets', '--secrets', '-c', is_flag=True)
|
||||||
def download(snapshot, path, volumes, secrets):
|
def download(snapshot, path, volumes, secrets):
|
||||||
if sum(map(bool, [path, volumes, secrets])) != 1:
|
file_dumps = []
|
||||||
logging.error(
|
if not any([path, volumes, secrets]):
|
||||||
"Please specify exactly one of '--path', '--volumes', '--secrets'")
|
volumes = secrets = True
|
||||||
exit(1)
|
|
||||||
if path:
|
if path:
|
||||||
path = path.removesuffix('/')
|
path = path.removesuffix('/')
|
||||||
|
binary_output = dump(snapshot, path)
|
||||||
files = list_files(snapshot, path)
|
files = list_files(snapshot, path)
|
||||||
filetype = [f.get('type') for f in files if f.get('path') == path][0]
|
filetype = [f.get('type') for f in files if f.get('path') == path][0]
|
||||||
filename = "/tmp/" + Path(path).name
|
filename = Path(path).name
|
||||||
if filetype == 'dir':
|
if filetype == 'dir':
|
||||||
filename = filename + ".tar"
|
filename = filename + ".tar"
|
||||||
output = dump(snapshot, path)
|
tarinfo = tarfile.TarInfo(name=filename)
|
||||||
with open(filename, "wb") as file:
|
tarinfo.size = len(binary_output)
|
||||||
file.write(output)
|
file_dumps.append((binary_output, tarinfo))
|
||||||
print(filename)
|
if volumes:
|
||||||
elif volumes:
|
|
||||||
if not SERVICE:
|
if not SERVICE:
|
||||||
logging.error("Please specify '--host' when using '--volumes'")
|
logging.error("Please specify '--host' when using '--volumes'")
|
||||||
exit(1)
|
exit(1)
|
||||||
filename = f"/tmp/{SERVICE}.tar"
|
|
||||||
files = list_files(snapshot, VOLUME_PATH)
|
files = list_files(snapshot, VOLUME_PATH)
|
||||||
for f in files[1:]:
|
for f in files[1:]:
|
||||||
path = f['path']
|
path = f['path']
|
||||||
if SERVICE in path and f['type'] == 'dir':
|
if Path(path).name.startswith(SERVICE) and f['type'] == 'dir':
|
||||||
content = dump(snapshot, path)
|
binary_output = dump(snapshot, path)
|
||||||
# Concatenate tar files (extract with tar -xi)
|
filename = f"{Path(path).name}.tar"
|
||||||
with open(filename, "ab") as file:
|
tarinfo = tarfile.TarInfo(name=filename)
|
||||||
file.write(content)
|
tarinfo.size = len(binary_output)
|
||||||
elif secrets:
|
file_dumps.append((binary_output, tarinfo))
|
||||||
|
if secrets:
|
||||||
if not SERVICE:
|
if not SERVICE:
|
||||||
logging.error("Please specify '--host' when using '--secrets'")
|
logging.error("Please specify '--host' when using '--secrets'")
|
||||||
exit(1)
|
exit(1)
|
||||||
filename = f"/tmp/SECRETS_{SERVICE}.json"
|
filename = f"{SERVICE}.json"
|
||||||
files = list_files(snapshot, SECRET_PATH)
|
files = list_files(snapshot, SECRET_PATH)
|
||||||
secrets = {}
|
secrets = {}
|
||||||
for f in files[1:]:
|
for f in files[1:]:
|
||||||
path = f['path']
|
path = f['path']
|
||||||
if SERVICE in path and f['type'] == 'file':
|
if Path(path).name.startswith(SERVICE) and f['type'] == 'file':
|
||||||
secret = dump(snapshot, path).decode()
|
secret = dump(snapshot, path).decode()
|
||||||
secret_name = path.removeprefix(f'{SECRET_PATH}{SERVICE}_')
|
secret_name = path.removeprefix(f'{SECRET_PATH}{SERVICE}_')
|
||||||
secrets[secret_name] = secret
|
secrets[secret_name] = secret
|
||||||
with open(filename, "w") as file:
|
binary_output = json.dumps(secrets).encode()
|
||||||
json.dump(secrets, file)
|
tarinfo = tarfile.TarInfo(name=filename)
|
||||||
print(filename)
|
tarinfo.size = len(binary_output)
|
||||||
|
file_dumps.append((binary_output, tarinfo))
|
||||||
|
with tarfile.open('/tmp/backup.tar.gz', "w:gz") as tar:
|
||||||
|
print(f"Writing files to /tmp/backup.tar.gz...")
|
||||||
|
for binary_output, tarinfo in file_dumps:
|
||||||
|
tar.addfile(tarinfo, fileobj=io.BytesIO(binary_output))
|
||||||
|
size = get_formatted_size('/tmp/backup.tar.gz')
|
||||||
|
print(f"Backup has been written to /tmp/backup.tar.gz with a size of {size}")
|
||||||
|
|
||||||
|
|
||||||
|
def get_formatted_size(file_path):
|
||||||
|
file_size = os.path.getsize(file_path)
|
||||||
|
units = ['Bytes', 'KB', 'MB', 'GB', 'TB']
|
||||||
|
for unit in units:
|
||||||
|
if file_size < 1024:
|
||||||
|
return f"{round(file_size, 3)} {unit}"
|
||||||
|
file_size /= 1024
|
||||||
|
return f"{round(file_size, 3)} {units[-1]}"
|
||||||
|
|
||||||
|
|
||||||
def dump(snapshot, path):
|
def dump(snapshot, path):
|
||||||
@ -286,7 +304,7 @@ def dump(snapshot, path):
|
|||||||
if SERVICE:
|
if SERVICE:
|
||||||
cmd = cmd + ['--tag', SERVICE]
|
cmd = cmd + ['--tag', SERVICE]
|
||||||
cmd = cmd + [snapshot, path]
|
cmd = cmd + [snapshot, path]
|
||||||
logging.debug(f"Dumping {path} from snapshot '{snapshot}'")
|
print(f"Dumping {path} from snapshot '{snapshot}'")
|
||||||
output = subprocess.run(cmd, capture_output=True)
|
output = subprocess.run(cmd, capture_output=True)
|
||||||
if output.returncode:
|
if output.returncode:
|
||||||
logging.error(
|
logging.error(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user