mirror of
https://git.selfprivacy.org/SelfPrivacy/selfprivacy-rest-api.git
synced 2024-11-24 13:01:28 +00:00
test(backup): try to back up!
This commit is contained in:
parent
4547f02e1b
commit
88b715464d
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
# )
|
||||||
|
|
|
@ -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]:
|
||||||
|
|
|
@ -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)
|
Loading…
Reference in a new issue