From e02c1a878bc4efb50f9dc6354f94e6add0eeb241 Mon Sep 17 00:00:00 2001 From: Houkime <> Date: Mon, 13 Mar 2023 19:03:41 +0000 Subject: [PATCH] feature(backups): provider storage and retrieval --- selfprivacy_api/backup/__init__.py | 37 +++++++++++++++++--- selfprivacy_api/backup/providers/__init__.py | 6 ++++ tests/test_graphql/test_backup.py | 30 +++++++++++++++- 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/selfprivacy_api/backup/__init__.py b/selfprivacy_api/backup/__init__.py index f34f43d..d24872d 100644 --- a/selfprivacy_api/backup/__init__.py +++ b/selfprivacy_api/backup/__init__.py @@ -1,17 +1,25 @@ from typing import List from selfprivacy_api.models.backup.snapshot import Snapshot +from selfprivacy_api.models.backup.provider import BackupProviderModel from selfprivacy_api.utils.singleton_metaclass import SingletonMetaclass from selfprivacy_api.utils import ReadUserData +from selfprivacy_api.utils.redis_pool import RedisPool +from selfprivacy_api.utils.redis_model_storage import store_model_as_hash, hash_as_model + from selfprivacy_api.services import get_service_by_id from selfprivacy_api.services.service import Service from selfprivacy_api.backup.providers.provider import AbstractBackupProvider -from selfprivacy_api.backup.providers import get_provider +from selfprivacy_api.backup.providers import get_provider, get_kind from selfprivacy_api.graphql.queries.providers import BackupProvider +REDIS_PROVIDER_KEY = "backups:provider" + +redis = RedisPool().get_connection() + # Singleton has a property of being persistent between tests. # I don't know what to do with this yet @@ -37,6 +45,29 @@ class Backups: provider_class = get_provider(BackupProvider[kind]) return provider_class(login=login, key=key) + @staticmethod + def store_provider_redis(provider: AbstractBackupProvider): + store_model_as_hash( + redis, + REDIS_PROVIDER_KEY, + BackupProviderModel( + kind=get_kind(provider), login=provider.login, key=provider.key + ), + ) + + @staticmethod + def load_provider_redis() -> AbstractBackupProvider: + provider_model = hash_as_model(redis, REDIS_PROVIDER_KEY, BackupProviderModel) + if provider_model is None: + return None + return Backups.construct_provider( + provider_model.kind, provider_model.login, provider_model.key + ) + + @staticmethod + def reset(): + redis.delete(REDIS_PROVIDER_KEY) + def lookup_provider(self) -> AbstractBackupProvider: redis_provider = Backups.load_provider_redis() if redis_provider is not None: @@ -48,10 +79,6 @@ class Backups: return Backups.construct_provider("MEMORY", login="", key="") - @staticmethod - def load_provider_redis() -> AbstractBackupProvider: - pass - @staticmethod def load_provider_json() -> AbstractBackupProvider: with ReadUserData() as user_data: diff --git a/selfprivacy_api/backup/providers/__init__.py b/selfprivacy_api/backup/providers/__init__.py index 21c4467..5428e80 100644 --- a/selfprivacy_api/backup/providers/__init__.py +++ b/selfprivacy_api/backup/providers/__init__.py @@ -14,3 +14,9 @@ PROVIDER_MAPPING = { def get_provider(provider_type: BackupProvider) -> AbstractBackupProvider: return PROVIDER_MAPPING[provider_type] + + +def get_kind(provider: AbstractBackupProvider) -> str: + for key, value in PROVIDER_MAPPING.items(): + if isinstance(provider, value): + return key.value diff --git a/tests/test_graphql/test_backup.py b/tests/test_graphql/test_backup.py index 6d21c15..f6f3526 100644 --- a/tests/test_graphql/test_backup.py +++ b/tests/test_graphql/test_backup.py @@ -23,7 +23,16 @@ REPO_NAME = "test_backup" @pytest.fixture(scope="function") def backups(tmpdir): test_repo_path = path.join(tmpdir, "totallyunrelated") - return Backups(test_repo_path) + backups = Backups(test_repo_path) + backups.reset() + return backups + + +@pytest.fixture() +def backups_backblaze(generic_userdata): + backups = Backups() + backups.reset() + return backups @pytest.fixture() @@ -75,6 +84,7 @@ def file_backup(tmpdir) -> AbstractBackupProvider: def test_config_load(generic_userdata): backups = Backups() + backups.reset() provider = backups.provider assert provider is not None @@ -145,3 +155,21 @@ def test_sizing(backups, dummy_service): size = backups.service_snapshot_size(dummy_service, snap.id) assert size is not None assert size > 0 + + +def test_redis_storage(backups_backblaze): + backups = Backups() + backups.reset() + provider = backups.provider + + assert provider is not None + + assert isinstance(provider, Backblaze) + assert provider.login == "ID" + assert provider.key == "KEY" + + backups.store_provider_redis(provider) + restored_provider = backups.load_provider_redis() + assert isinstance(restored_provider, Backblaze) + assert restored_provider.login == "ID" + assert restored_provider.key == "KEY"