test(backup): try to back up!

This commit is contained in:
Houkime 2023-02-08 14:05:25 +00:00 committed by Inex Code
parent a9cd8dda37
commit 54103973bc
4 changed files with 51 additions and 33 deletions

View file

@ -1,5 +1,10 @@
from abc import ABC from abc import ABC, abstractmethod
class AbstractBackuper(ABC): class AbstractBackuper(ABC):
def __init__(self): def __init__(self):
pass pass
@abstractmethod
def start_backup(self, folder: str):
raise NotImplementedError

View file

@ -18,44 +18,54 @@ class ResticBackuper(AbstractBackuper):
def restic_repo(self, repository_name: str) -> str: def restic_repo(self, repository_name: str) -> str:
# https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html#other-services-via-rclone # https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html#other-services-via-rclone
# https://forum.rclone.org/t/can-rclone-be-run-solely-with-command-line-options-no-config-no-env-vars/6314/5 # https://forum.rclone.org/t/can-rclone-be-run-solely-with-command-line-options-no-config-no-env-vars/6314/5
return f"rclone::{self.type}:{self._repository_name}/sfbackup" return f"rclone::{self.type}:{repository_name}/sfbackup"
def rclone_args(self): def rclone_args(self):
return "rclone.args=serve restic --stdio" + self.backend_rclone_args() return "rclone.args=serve restic --stdio" + self.backend_rclone_args()
def backend_rclone_args(self, account: str, key: str) -> str: def backend_rclone_args(self) -> str:
acc_arg = "" acc_arg = ""
key_arg = "" key_arg = ""
if account != "": if self.account != "":
acc_arg = f"{self.login_flag} {account}" acc_arg = f"{self.login_flag} {self.account}"
if key != "": if self.key != "":
key_arg = f"{self.key_flag} {key}" key_arg = f"{self.key_flag} {self.key}"
return f"{acc_arg} {key_arg}" return f"{acc_arg} {key_arg}"
def restic_command(self, account: str, key: str, *args): def restic_command(self, repo_name: str, *args):
return [ command = [
"restic", "restic",
"-o", "-o",
self.rclone_args(), self.rclone_args(),
"-r", "-r",
self.restic_repo(account, key), self.restic_repo(repo_name),
].extend(args) ]
if args != []:
command.extend(args)
return command
def start_backup(self, folder: str): def start_backup(self, folder: str, repo_name: str):
""" """
Start backup with restic Start backup with restic
""" """
backup_command = self.restic_command( backup_command = self.restic_command(
self.account, repo_name,
self.key,
"backup", "backup",
folder, folder,
) )
with open("/var/backup.log", "w", encoding="utf-8") as log_file:
subprocess.Popen( subprocess.Popen(
backup_command, backup_command,
shell=False, shell=False,
stdout=log_file,
stderr=subprocess.STDOUT, stderr=subprocess.STDOUT,
) )
# TODO: we might want to provide logging facilities
# that are reroutable for testing
# with open("/var/backup.log", "w", encoding="utf-8") as log_file:
# subprocess.Popen(
# backup_command,
# shell=False,
# stdout=log_file,
# stderr=subprocess.STDOUT,
# )

View file

@ -14,8 +14,8 @@ from selfprivacy_api.services.test_service.icon import BITWARDEN_ICON
class DummyService(Service): class DummyService(Service):
"""A test service""" """A test service"""
def __init__(self, location): def __init_subclass__(cls, location):
self.loccation = location cls.location = location
@staticmethod @staticmethod
def get_id() -> str: def get_id() -> str:
@ -106,13 +106,9 @@ class DummyService(Service):
storage_usage = 0 storage_usage = 0
return storage_usage return storage_usage
@staticmethod @classmethod
def get_location() -> str: def get_location(cls) -> str:
with ReadUserData() as user_data: return cls.location
if user_data.get("useBinds", False):
return user_data.get("bitwarden", {}).get("location", "sda1")
else:
return "sda1"
@staticmethod @staticmethod
def get_dns_records() -> typing.List[ServiceDnsRecord]: def get_dns_records() -> typing.List[ServiceDnsRecord]:

View file

@ -11,6 +11,7 @@ from selfprivacy_api.graphql.queries.providers import BackupProvider
TESTFILE_BODY = "testytest!" TESTFILE_BODY = "testytest!"
REPO_NAME = "test_backup"
@pytest.fixture() @pytest.fixture()
@ -18,11 +19,16 @@ def test_service(tmpdir):
testile_path = path.join(tmpdir, "testfile.txt") testile_path = path.join(tmpdir, "testfile.txt")
with open(testile_path, "w") as file: with open(testile_path, "w") as file:
file.write(TESTFILE_BODY) file.write(TESTFILE_BODY)
return DummyService(tmpdir)
# we need this to not change get_location() much
class TestDummyService (DummyService, location=tmpdir):
pass
return TestDummyService()
@pytest.fixture() @pytest.fixture()
def memory_backup(): def memory_backup() -> AbstractBackupProvider:
ProviderClass = providers.get_provider(BackupProvider.MEMORY) ProviderClass = providers.get_provider(BackupProvider.MEMORY)
assert ProviderClass is not None assert ProviderClass is not None
memory_provider = ProviderClass(login="", key="") memory_provider = ProviderClass(login="", key="")
@ -40,3 +46,4 @@ def test_backup_service(test_service, memory_backup):
# temporarily incomplete # temporarily incomplete
assert test_service is not None assert test_service is not None
assert memory_backup is not None assert memory_backup is not None
memory_backup.backuper.start_backup(test_service.get_location(), REPO_NAME)