From 0e7ab29af8f5130a338e9d3866dcff054341e0ab Mon Sep 17 00:00:00 2001 From: Anthoni Gleeson Date: Fri, 20 Dec 2024 12:10:26 +0000 Subject: [PATCH 01/14] redis and opensearch v2 decoupled provider from cache --- .../domain/config_validator.py | 29 ++++++++++++++ dbt_platform_helper/providers/opensearch.py | 26 ++++++++++++ dbt_platform_helper/providers/redis.py | 22 ++++++++++ .../providers/test_opensearch.py | 31 ++++++++++++++ tests/platform_helper/providers/test_redis.py | 40 +++++++++++++++++++ 5 files changed, 148 insertions(+) diff --git a/dbt_platform_helper/domain/config_validator.py b/dbt_platform_helper/domain/config_validator.py index 2bf5ee743..3f13d5d49 100644 --- a/dbt_platform_helper/domain/config_validator.py +++ b/dbt_platform_helper/domain/config_validator.py @@ -4,8 +4,11 @@ from dbt_platform_helper.constants import CODEBASE_PIPELINES_KEY from dbt_platform_helper.constants import ENVIRONMENTS_KEY from dbt_platform_helper.constants import PLATFORM_CONFIG_FILE +from dbt_platform_helper.providers.cache import CacheProvider from dbt_platform_helper.providers.opensearch import OpensearchProvider +from dbt_platform_helper.providers.opensearch import OpensearchProviderV2 from dbt_platform_helper.providers.redis import RedisProvider +from dbt_platform_helper.providers.redis import RedisProviderV2 from dbt_platform_helper.utils.messages import abort_with_error @@ -16,6 +19,26 @@ def get_env_deploy_account_info(config, env, key): ) +def get_client_provider(client: str): + if client == "elasticache": + return RedisProviderV2() + elif client == "opensearch": + return OpensearchProviderV2() + else: + # TODO make specific exception + raise Exception(f"client {client} not found") + + +def get_supported_versions(client: str, cache_provider=CacheProvider()): + client_provider = get_client_provider(client) + if cache_provider.cache_refresh_required(client_provider.get_reference()): + supported_versions = client_provider.get_supported_versions() + cache_provider.update_cache(client_provider.get_reference(), supported_versions) + return supported_versions + else: + return cache_provider.read_supported_versions_from_cache(client_provider.get_reference()) + + class ConfigValidator: def __init__(self, validations=[]): @@ -79,6 +102,9 @@ def validate_supported_redis_versions(self, config): config=config, extension_type="redis", version_key="engine", + # get_supported_versions=get_supported_versions( + # "elasticache" + # ), get_supported_versions=RedisProvider( boto3.client("elasticache") ).get_supported_redis_versions, @@ -89,6 +115,9 @@ def validate_supported_opensearch_versions(self, config): config=config, extension_type="opensearch", version_key="engine", + # get_supported_versions=get_supported_versions( + # "opensearch" + # ), get_supported_versions=OpensearchProvider( boto3.client("opensearch") ).get_supported_opensearch_versions, diff --git a/dbt_platform_helper/providers/opensearch.py b/dbt_platform_helper/providers/opensearch.py index 579e3629f..a88785c78 100644 --- a/dbt_platform_helper/providers/opensearch.py +++ b/dbt_platform_helper/providers/opensearch.py @@ -1,3 +1,5 @@ +import boto3 + from dbt_platform_helper.providers.cache import CacheProvider @@ -34,3 +36,27 @@ def get_supported_opensearch_versions(self) -> list[str]: @staticmethod def __get_cache_provider(): return CacheProvider() + + +class OpensearchProviderV2: + + def __init__(self, client: boto3.client = boto3.client("opensearch")): + self.client = client + # TODO extract engine so you could swap between opensearch and elastic in the same provider + self.engine = "OpenSearch" + + def get_reference(self) -> str: + return self.engine.lower() + + def get_supported_versions(self): + response = self.client.list_versions() + all_versions = response["Versions"] + + opensearch_versions = [ + version for version in all_versions if version.startswith(f"{self.engine}_") + ] + supported_versions = [ + version.removeprefix(f"{self.engine}_") for version in opensearch_versions + ] + + return supported_versions diff --git a/dbt_platform_helper/providers/redis.py b/dbt_platform_helper/providers/redis.py index 00da5f8e3..dd5a4e046 100644 --- a/dbt_platform_helper/providers/redis.py +++ b/dbt_platform_helper/providers/redis.py @@ -1,3 +1,5 @@ +import boto3 + from dbt_platform_helper.providers.cache import CacheProvider @@ -32,3 +34,23 @@ def get_supported_redis_versions(self): @staticmethod def __get_cache_provider(): return CacheProvider() + + +class RedisProviderV2: + + def __init__(self, client: boto3.client = boto3.client("opensearch")): + self.client = client + self.engine = "redis" + + def get_reference(self) -> str: + return self.engine.lower() + + def get_supported_versions(self): + supported_versions_response = self.client.describe_cache_engine_versions(Engine=self.engine) + + supported_versions = [ + version["EngineVersion"] + for version in supported_versions_response["CacheEngineVersions"] + ] + + return supported_versions diff --git a/tests/platform_helper/providers/test_opensearch.py b/tests/platform_helper/providers/test_opensearch.py index c2bfb1a27..e1328c7ba 100644 --- a/tests/platform_helper/providers/test_opensearch.py +++ b/tests/platform_helper/providers/test_opensearch.py @@ -3,6 +3,7 @@ import pytest from dbt_platform_helper.providers.opensearch import OpensearchProvider +from dbt_platform_helper.providers.opensearch import OpensearchProviderV2 @pytest.mark.skip_opensearch_fixture @@ -36,3 +37,33 @@ def test_get_supported_opensearch_versions_when_cache_refresh_required(): "opensearch", ["2.15", "2.13", "2.11", "2.9"] ) assert supported_opensearch_versions_response == ["2.15", "2.13", "2.11", "2.9"] + + +def test_opensearch_provider_get_reference(): + opensearch_client = MagicMock() + opensearch_provider = OpensearchProviderV2(opensearch_client) + + reference = opensearch_provider.get_reference() + + assert reference == "opensearch" + + +def test_opensearch_provider_get_supported_versions(): + + opensearch_client = MagicMock() + opensearch_client.list_versions.return_value = { + "Versions": [ + "OpenSearch_2.15", + "OpenSearch_2.13", + "OpenSearch_2.11", + "OpenSearch_2.9", + "Elasticsearch_7.10", + "Elasticsearch_7.9", + ] + } + opensearch_provider = OpensearchProviderV2(opensearch_client) + + supported_opensearch_versions_response = opensearch_provider.get_supported_versions() + + opensearch_client.list_versions.assert_called_with() + assert supported_opensearch_versions_response == ["2.15", "2.13", "2.11", "2.9"] diff --git a/tests/platform_helper/providers/test_redis.py b/tests/platform_helper/providers/test_redis.py index 352dcfcd3..30360ab11 100644 --- a/tests/platform_helper/providers/test_redis.py +++ b/tests/platform_helper/providers/test_redis.py @@ -3,6 +3,7 @@ import pytest from dbt_platform_helper.providers.redis import RedisProvider +from dbt_platform_helper.providers.redis import RedisProviderV2 # TODO - we don't want to use the fixtures from conftest since one applies get_supported_redis_versions @@ -42,3 +43,42 @@ def test_get_supported_redis_versions_when_cache_refresh_required(): elasticache_client.describe_cache_engine_versions.assert_called_with(Engine="redis") mock_cache_provider.update_cache.assert_called_with("redis", ["4.0.10", "5.0.6"]) assert supported_redis_versions_response == ["4.0.10", "5.0.6"] + + +def test_redis_provider_get_reference(): + elasticache_client = MagicMock() + redis_provider = RedisProviderV2(elasticache_client) + + reference = redis_provider.get_reference() + + assert reference == "redis" + + +def test_redis_provider_get_supported_versions(): + + elasticache_client = MagicMock() + elasticache_client.describe_cache_engine_versions.return_value = { + "CacheEngineVersions": [ + { + "Engine": "redis", + "EngineVersion": "4.0.10", + "CacheParameterGroupFamily": "redis4.0", + "CacheEngineDescription": "Redis", + "CacheEngineVersionDescription": "redis version 4.0.10", + }, + { + "Engine": "redis", + "EngineVersion": "5.0.6", + "CacheParameterGroupFamily": "redis5.0", + "CacheEngineDescription": "Redis", + "CacheEngineVersionDescription": "redis version 5.0.6", + }, + ] + } + + redis_provider = RedisProviderV2(elasticache_client) + + supported_versions_response = redis_provider.get_supported_versions() + + elasticache_client.describe_cache_engine_versions.assert_called_with(Engine="redis") + assert supported_versions_response == ["4.0.10", "5.0.6"] From a5e0c119ceff0779b7f2c87da83e9a158eadf198 Mon Sep 17 00:00:00 2001 From: Anthoni Gleeson Date: Fri, 20 Dec 2024 12:35:19 +0000 Subject: [PATCH 02/14] add exception and get_client_provider --- .../domain/config_validator.py | 3 ++- dbt_platform_helper/providers/aws.py | 5 +++++ .../providers/test_config_validator.py | 20 +++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/dbt_platform_helper/domain/config_validator.py b/dbt_platform_helper/domain/config_validator.py index 3f13d5d49..ad7263b4c 100644 --- a/dbt_platform_helper/domain/config_validator.py +++ b/dbt_platform_helper/domain/config_validator.py @@ -4,6 +4,7 @@ from dbt_platform_helper.constants import CODEBASE_PIPELINES_KEY from dbt_platform_helper.constants import ENVIRONMENTS_KEY from dbt_platform_helper.constants import PLATFORM_CONFIG_FILE +from dbt_platform_helper.providers.aws import InvalidAWSClient from dbt_platform_helper.providers.cache import CacheProvider from dbt_platform_helper.providers.opensearch import OpensearchProvider from dbt_platform_helper.providers.opensearch import OpensearchProviderV2 @@ -26,7 +27,7 @@ def get_client_provider(client: str): return OpensearchProviderV2() else: # TODO make specific exception - raise Exception(f"client {client} not found") + raise InvalidAWSClient(client) def get_supported_versions(client: str, cache_provider=CacheProvider()): diff --git a/dbt_platform_helper/providers/aws.py b/dbt_platform_helper/providers/aws.py index c7005489a..84155d326 100644 --- a/dbt_platform_helper/providers/aws.py +++ b/dbt_platform_helper/providers/aws.py @@ -19,6 +19,11 @@ def __init__(self, commit: str): ) +class InvalidAWSClient(AWSException): + def __init__(self, client: str): + super().__init__(f"""The client {client} was not found.""") + + class LogGroupNotFoundException(AWSException): def __init__(self, log_group_name: str): super().__init__(f"""No log group called "{log_group_name}".""") diff --git a/tests/platform_helper/providers/test_config_validator.py b/tests/platform_helper/providers/test_config_validator.py index 903857efc..b0437a79a 100644 --- a/tests/platform_helper/providers/test_config_validator.py +++ b/tests/platform_helper/providers/test_config_validator.py @@ -3,6 +3,9 @@ import pytest from dbt_platform_helper.domain.config_validator import ConfigValidator +from dbt_platform_helper.domain.config_validator import get_client_provider +from dbt_platform_helper.providers.opensearch import OpensearchProviderV2 +from dbt_platform_helper.providers.redis import RedisProviderV2 @pytest.mark.parametrize( @@ -355,3 +358,20 @@ def test_validate_extension_supported_versions(config, expected_response, capsys assert expected_response in captured.out assert captured.err == "" + + +@pytest.mark.parametrize( + "client, valid, client_type", + [ + ("elasticache", True, RedisProviderV2), + ("opensearch", True, OpensearchProviderV2), + ("invalid-client", False, None), + ], +) +def test_get_client_provider(client, valid, client_type): + if valid: + response_provider = get_client_provider(client) + assert isinstance(response_provider, client_type) + else: + with pytest.raises(Exception, match=f"The client {client} was not found."): + response_provider = get_client_provider(client) From f4fb49863fe9cf58e0866d963391968b98fab209 Mon Sep 17 00:00:00 2001 From: Anthoni Gleeson Date: Fri, 20 Dec 2024 12:37:08 +0000 Subject: [PATCH 03/14] completed TODO --- dbt_platform_helper/domain/config_validator.py | 1 - 1 file changed, 1 deletion(-) diff --git a/dbt_platform_helper/domain/config_validator.py b/dbt_platform_helper/domain/config_validator.py index ad7263b4c..a95951c07 100644 --- a/dbt_platform_helper/domain/config_validator.py +++ b/dbt_platform_helper/domain/config_validator.py @@ -26,7 +26,6 @@ def get_client_provider(client: str): elif client == "opensearch": return OpensearchProviderV2() else: - # TODO make specific exception raise InvalidAWSClient(client) From 1e4ed7c3e73d61bbf7b5ff1b8e68b86685b9e9a6 Mon Sep 17 00:00:00 2001 From: Anthoni Gleeson Date: Fri, 20 Dec 2024 12:42:19 +0000 Subject: [PATCH 04/14] fix client reference --- dbt_platform_helper/providers/redis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbt_platform_helper/providers/redis.py b/dbt_platform_helper/providers/redis.py index dd5a4e046..1a2126e02 100644 --- a/dbt_platform_helper/providers/redis.py +++ b/dbt_platform_helper/providers/redis.py @@ -38,7 +38,7 @@ def __get_cache_provider(): class RedisProviderV2: - def __init__(self, client: boto3.client = boto3.client("opensearch")): + def __init__(self, client: boto3.client = boto3.client("elasticache")): self.client = client self.engine = "redis" From 0ecf045961c71f26545a2acc29a3db119ebe4913 Mon Sep 17 00:00:00 2001 From: chiaramapellimt Date: Fri, 20 Dec 2024 14:04:48 +0000 Subject: [PATCH 05/14] Lint --- tests/platform_helper/test_command_pipeline.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/platform_helper/test_command_pipeline.py b/tests/platform_helper/test_command_pipeline.py index bd5552712..6def7acd0 100644 --- a/tests/platform_helper/test_command_pipeline.py +++ b/tests/platform_helper/test_command_pipeline.py @@ -205,6 +205,7 @@ def test_pipeline_generate_deletes_any_existing_config_files_and_writes_new_ones ): mock_codestar_connections_boto_client(mock_aws_session, ["test-app"]) setup_fixtures(fakefs) + fs.create_dir("copilot/pipelines") fs.create_file("copilot/pipelines/unnecessary_file.yml") codebases_files = setup_output_file_paths_for_codebases() From f233a4317fb891bc0343aa5f052506db6768efd8 Mon Sep 17 00:00:00 2001 From: Anthoni Gleeson Date: Fri, 20 Dec 2024 18:10:56 +0000 Subject: [PATCH 06/14] sub folder aws provider, move os & redis to folder, factory method in __init__.py, infterface file for ClientProvider, get_supported_versions test --- .../domain/config_validator.py | 24 ++++-------- dbt_platform_helper/domain/database_copy.py | 2 +- dbt_platform_helper/providers/aws/__init__.py | 14 +++++++ .../providers/{aws.py => aws/exceptions.py} | 0 .../providers/aws/interfaces.py | 17 +++++++++ .../providers/{ => aws}/opensearch.py | 3 +- .../providers/{ => aws}/redis.py | 0 dbt_platform_helper/providers/copilot.py | 2 +- dbt_platform_helper/utils/aws.py | 10 +++-- tests/platform_helper/conftest.py | 4 +- tests/platform_helper/domain/test_codebase.py | 6 ++- tests/platform_helper/domain/test_conduit.py | 2 +- .../domain/test_database_copy.py | 2 +- .../providers/test_config_validator.py | 38 +++++++++++++++++-- .../platform_helper/providers/test_copilot.py | 2 +- .../providers/test_opensearch.py | 4 +- tests/platform_helper/providers/test_redis.py | 4 +- .../platform_helper/test_command_codebase.py | 6 ++- tests/platform_helper/test_exceptions.py | 10 +++-- tests/platform_helper/utils/test_aws.py | 8 ++-- 20 files changed, 112 insertions(+), 46 deletions(-) create mode 100644 dbt_platform_helper/providers/aws/__init__.py rename dbt_platform_helper/providers/{aws.py => aws/exceptions.py} (100%) create mode 100644 dbt_platform_helper/providers/aws/interfaces.py rename dbt_platform_helper/providers/{ => aws}/opensearch.py (94%) rename dbt_platform_helper/providers/{ => aws}/redis.py (100%) diff --git a/dbt_platform_helper/domain/config_validator.py b/dbt_platform_helper/domain/config_validator.py index a95951c07..82ef5a460 100644 --- a/dbt_platform_helper/domain/config_validator.py +++ b/dbt_platform_helper/domain/config_validator.py @@ -4,12 +4,10 @@ from dbt_platform_helper.constants import CODEBASE_PIPELINES_KEY from dbt_platform_helper.constants import ENVIRONMENTS_KEY from dbt_platform_helper.constants import PLATFORM_CONFIG_FILE -from dbt_platform_helper.providers.aws import InvalidAWSClient +from dbt_platform_helper.providers.aws import get_client_provider +from dbt_platform_helper.providers.aws.opensearch import OpensearchProvider +from dbt_platform_helper.providers.aws.redis import RedisProvider from dbt_platform_helper.providers.cache import CacheProvider -from dbt_platform_helper.providers.opensearch import OpensearchProvider -from dbt_platform_helper.providers.opensearch import OpensearchProviderV2 -from dbt_platform_helper.providers.redis import RedisProvider -from dbt_platform_helper.providers.redis import RedisProviderV2 from dbt_platform_helper.utils.messages import abort_with_error @@ -20,17 +18,11 @@ def get_env_deploy_account_info(config, env, key): ) -def get_client_provider(client: str): - if client == "elasticache": - return RedisProviderV2() - elif client == "opensearch": - return OpensearchProviderV2() - else: - raise InvalidAWSClient(client) - - -def get_supported_versions(client: str, cache_provider=CacheProvider()): - client_provider = get_client_provider(client) +# TODO where does this live? +def get_supported_versions( + client: str, cache_provider=CacheProvider(), get_client_provider_fn=get_client_provider +): + client_provider = get_client_provider_fn(client) if cache_provider.cache_refresh_required(client_provider.get_reference()): supported_versions = client_provider.get_supported_versions() cache_provider.update_cache(client_provider.get_reference(), supported_versions) diff --git a/dbt_platform_helper/domain/database_copy.py b/dbt_platform_helper/domain/database_copy.py index 9bfd45414..9676391d3 100644 --- a/dbt_platform_helper/domain/database_copy.py +++ b/dbt_platform_helper/domain/database_copy.py @@ -9,7 +9,7 @@ from dbt_platform_helper.constants import PLATFORM_CONFIG_FILE from dbt_platform_helper.domain.config_validator import ConfigValidator from dbt_platform_helper.domain.maintenance_page import MaintenancePageProvider -from dbt_platform_helper.providers.aws import AWSException +from dbt_platform_helper.providers.aws.exceptions import AWSException from dbt_platform_helper.providers.config import ConfigProvider from dbt_platform_helper.utils.application import Application from dbt_platform_helper.utils.application import ApplicationNotFoundException diff --git a/dbt_platform_helper/providers/aws/__init__.py b/dbt_platform_helper/providers/aws/__init__.py new file mode 100644 index 000000000..9a6fa1b62 --- /dev/null +++ b/dbt_platform_helper/providers/aws/__init__.py @@ -0,0 +1,14 @@ +from dbt_platform_helper.providers.aws.exceptions import InvalidAWSClient +from dbt_platform_helper.providers.aws.interfaces import ClientProvider +from dbt_platform_helper.providers.aws.opensearch import OpensearchProviderV2 +from dbt_platform_helper.providers.aws.redis import RedisProviderV2 + + +# TODO think of a way of stubbing ClientProvider's to improve testing and local development. +def get_client_provider(client: str) -> ClientProvider: + if client == "elasticache": + return RedisProviderV2() + elif client == "opensearch": + return OpensearchProviderV2() + else: + raise InvalidAWSClient(client) diff --git a/dbt_platform_helper/providers/aws.py b/dbt_platform_helper/providers/aws/exceptions.py similarity index 100% rename from dbt_platform_helper/providers/aws.py rename to dbt_platform_helper/providers/aws/exceptions.py diff --git a/dbt_platform_helper/providers/aws/interfaces.py b/dbt_platform_helper/providers/aws/interfaces.py new file mode 100644 index 000000000..eeb33f59c --- /dev/null +++ b/dbt_platform_helper/providers/aws/interfaces.py @@ -0,0 +1,17 @@ +from abc import ABC +from abc import abstractmethod + + +class ClientProvider(ABC): + + def __init__(self, client): + self.client = client + self.engine = None + + @abstractmethod + def get_reference(self): + raise NotImplementedError() + + @abstractmethod + def get_supported_versions(self): + raise NotImplementedError() diff --git a/dbt_platform_helper/providers/opensearch.py b/dbt_platform_helper/providers/aws/opensearch.py similarity index 94% rename from dbt_platform_helper/providers/opensearch.py rename to dbt_platform_helper/providers/aws/opensearch.py index a88785c78..e0f53796f 100644 --- a/dbt_platform_helper/providers/opensearch.py +++ b/dbt_platform_helper/providers/aws/opensearch.py @@ -1,5 +1,6 @@ import boto3 +from dbt_platform_helper.providers.aws.interfaces import ClientProvider from dbt_platform_helper.providers.cache import CacheProvider @@ -38,7 +39,7 @@ def __get_cache_provider(): return CacheProvider() -class OpensearchProviderV2: +class OpensearchProviderV2(ClientProvider): def __init__(self, client: boto3.client = boto3.client("opensearch")): self.client = client diff --git a/dbt_platform_helper/providers/redis.py b/dbt_platform_helper/providers/aws/redis.py similarity index 100% rename from dbt_platform_helper/providers/redis.py rename to dbt_platform_helper/providers/aws/redis.py diff --git a/dbt_platform_helper/providers/copilot.py b/dbt_platform_helper/providers/copilot.py index 30085f346..9b44a4c1c 100644 --- a/dbt_platform_helper/providers/copilot.py +++ b/dbt_platform_helper/providers/copilot.py @@ -4,7 +4,7 @@ from botocore.exceptions import ClientError from dbt_platform_helper.constants import CONDUIT_DOCKER_IMAGE_LOCATION -from dbt_platform_helper.providers.aws import CreateTaskTimeoutException +from dbt_platform_helper.providers.aws.exceptions import CreateTaskTimeoutException from dbt_platform_helper.providers.secrets import Secrets from dbt_platform_helper.utils.application import Application from dbt_platform_helper.utils.messages import abort_with_error diff --git a/dbt_platform_helper/utils/aws.py b/dbt_platform_helper/utils/aws.py index e7ed476a3..cf907f26c 100644 --- a/dbt_platform_helper/utils/aws.py +++ b/dbt_platform_helper/utils/aws.py @@ -14,10 +14,12 @@ from boto3 import Session from dbt_platform_helper.platform_exception import PlatformException -from dbt_platform_helper.providers.aws import AWSException -from dbt_platform_helper.providers.aws import CopilotCodebaseNotFoundException -from dbt_platform_helper.providers.aws import ImageNotFoundException -from dbt_platform_helper.providers.aws import LogGroupNotFoundException +from dbt_platform_helper.providers.aws.exceptions import AWSException +from dbt_platform_helper.providers.aws.exceptions import ( + CopilotCodebaseNotFoundException, +) +from dbt_platform_helper.providers.aws.exceptions import ImageNotFoundException +from dbt_platform_helper.providers.aws.exceptions import LogGroupNotFoundException from dbt_platform_helper.providers.validation import ValidationException SSM_BASE_PATH = "/copilot/{app}/{env}/secrets/" diff --git a/tests/platform_helper/conftest.py b/tests/platform_helper/conftest.py index 79d2c3b60..c9c614b96 100644 --- a/tests/platform_helper/conftest.py +++ b/tests/platform_helper/conftest.py @@ -14,8 +14,8 @@ from moto.ec2 import utils as ec2_utils from dbt_platform_helper.constants import PLATFORM_CONFIG_FILE -from dbt_platform_helper.providers.opensearch import OpensearchProvider -from dbt_platform_helper.providers.redis import RedisProvider +from dbt_platform_helper.providers.aws.opensearch import OpensearchProvider +from dbt_platform_helper.providers.aws.redis import RedisProvider from dbt_platform_helper.utils.aws import AWS_SESSION_CACHE from dbt_platform_helper.utils.versioning import PlatformHelperVersions diff --git a/tests/platform_helper/domain/test_codebase.py b/tests/platform_helper/domain/test_codebase.py index b31f5ad85..53c7e5758 100644 --- a/tests/platform_helper/domain/test_codebase.py +++ b/tests/platform_helper/domain/test_codebase.py @@ -17,8 +17,10 @@ from dbt_platform_helper.domain.codebase import ApplicationEnvironmentNotFoundException from dbt_platform_helper.domain.codebase import Codebase from dbt_platform_helper.domain.codebase import NotInCodeBaseRepositoryException -from dbt_platform_helper.providers.aws import CopilotCodebaseNotFoundException -from dbt_platform_helper.providers.aws import ImageNotFoundException +from dbt_platform_helper.providers.aws.exceptions import ( + CopilotCodebaseNotFoundException, +) +from dbt_platform_helper.providers.aws.exceptions import ImageNotFoundException from dbt_platform_helper.utils.application import ApplicationNotFoundException from dbt_platform_helper.utils.application import Environment from dbt_platform_helper.utils.git import CommitNotFoundException diff --git a/tests/platform_helper/domain/test_conduit.py b/tests/platform_helper/domain/test_conduit.py index 0be677254..bc32b7c57 100644 --- a/tests/platform_helper/domain/test_conduit.py +++ b/tests/platform_helper/domain/test_conduit.py @@ -4,7 +4,7 @@ import pytest from dbt_platform_helper.domain.conduit import Conduit -from dbt_platform_helper.providers.aws import CreateTaskTimeoutException +from dbt_platform_helper.providers.aws.exceptions import CreateTaskTimeoutException from dbt_platform_helper.providers.ecs import ECSAgentNotRunningException from dbt_platform_helper.providers.ecs import NoClusterException from dbt_platform_helper.providers.secrets import AddonNotFoundException diff --git a/tests/platform_helper/domain/test_database_copy.py b/tests/platform_helper/domain/test_database_copy.py index 55f031709..9e394871d 100644 --- a/tests/platform_helper/domain/test_database_copy.py +++ b/tests/platform_helper/domain/test_database_copy.py @@ -6,7 +6,7 @@ from dbt_platform_helper.constants import PLATFORM_CONFIG_FILE from dbt_platform_helper.domain.database_copy import DatabaseCopy -from dbt_platform_helper.providers.aws import AWSException +from dbt_platform_helper.providers.aws.exceptions import AWSException from dbt_platform_helper.providers.config import ConfigProvider from dbt_platform_helper.utils.application import Application from dbt_platform_helper.utils.application import ApplicationNotFoundException diff --git a/tests/platform_helper/providers/test_config_validator.py b/tests/platform_helper/providers/test_config_validator.py index b0437a79a..82eadf2b7 100644 --- a/tests/platform_helper/providers/test_config_validator.py +++ b/tests/platform_helper/providers/test_config_validator.py @@ -1,11 +1,13 @@ from unittest.mock import MagicMock +from unittest.mock import Mock import pytest from dbt_platform_helper.domain.config_validator import ConfigValidator -from dbt_platform_helper.domain.config_validator import get_client_provider -from dbt_platform_helper.providers.opensearch import OpensearchProviderV2 -from dbt_platform_helper.providers.redis import RedisProviderV2 +from dbt_platform_helper.domain.config_validator import get_supported_versions +from dbt_platform_helper.providers.aws import get_client_provider +from dbt_platform_helper.providers.aws.opensearch import OpensearchProviderV2 +from dbt_platform_helper.providers.aws.redis import RedisProviderV2 @pytest.mark.parametrize( @@ -360,6 +362,7 @@ def test_validate_extension_supported_versions(config, expected_response, capsys assert captured.err == "" +# TODO move. This shouldn't be tested here @pytest.mark.parametrize( "client, valid, client_type", [ @@ -375,3 +378,32 @@ def test_get_client_provider(client, valid, client_type): else: with pytest.raises(Exception, match=f"The client {client} was not found."): response_provider = get_client_provider(client) + + +# TODO add test for invalid client exception from get_client_provider_fn +# TODO add test for cache_refresh_required false +# TODO add test for exception from get_supported_versions +# TODO add test for exception from update_cache +# TODO add test for exception from read_supported_versions_from_cache +@pytest.mark.parametrize( + "client, get_reference, get_supported_versions_return_value", + [ + ("elasticache", "redis", ["4.0.10", "5.0.6"]), + # "invalid-client", + ], +) +def test_get_supported_versions(client, get_reference, get_supported_versions_return_value): + mock_cache_provider = MagicMock() + mock_client_provider = MagicMock() + + mock_cache_provider.cache_refresh_required.return_value = True + mock_client_provider.get_reference.return_value = get_reference + mock_client_provider.get_supported_versions.return_value = get_supported_versions_return_value + get_client_provider_fn = Mock(return_value=mock_client_provider) + + versions = get_supported_versions(client, mock_cache_provider, get_client_provider_fn) + + mock_cache_provider.update_cache.assert_called() # TODO update to assert called with + mock_cache_provider.read_supported_versions_from_cache.assert_not_called() + + assert versions == get_supported_versions_return_value diff --git a/tests/platform_helper/providers/test_copilot.py b/tests/platform_helper/providers/test_copilot.py index d1ee53bab..723420d4a 100644 --- a/tests/platform_helper/providers/test_copilot.py +++ b/tests/platform_helper/providers/test_copilot.py @@ -6,7 +6,7 @@ from botocore.exceptions import ClientError from moto import mock_aws -from dbt_platform_helper.providers.aws import CreateTaskTimeoutException +from dbt_platform_helper.providers.aws.exceptions import CreateTaskTimeoutException from dbt_platform_helper.providers.copilot import connect_to_addon_client_task from dbt_platform_helper.providers.copilot import create_addon_client_task from dbt_platform_helper.providers.copilot import create_postgres_admin_task diff --git a/tests/platform_helper/providers/test_opensearch.py b/tests/platform_helper/providers/test_opensearch.py index e1328c7ba..92d76bfdf 100644 --- a/tests/platform_helper/providers/test_opensearch.py +++ b/tests/platform_helper/providers/test_opensearch.py @@ -2,8 +2,8 @@ import pytest -from dbt_platform_helper.providers.opensearch import OpensearchProvider -from dbt_platform_helper.providers.opensearch import OpensearchProviderV2 +from dbt_platform_helper.providers.aws.opensearch import OpensearchProvider +from dbt_platform_helper.providers.aws.opensearch import OpensearchProviderV2 @pytest.mark.skip_opensearch_fixture diff --git a/tests/platform_helper/providers/test_redis.py b/tests/platform_helper/providers/test_redis.py index 30360ab11..2484440c2 100644 --- a/tests/platform_helper/providers/test_redis.py +++ b/tests/platform_helper/providers/test_redis.py @@ -2,8 +2,8 @@ import pytest -from dbt_platform_helper.providers.redis import RedisProvider -from dbt_platform_helper.providers.redis import RedisProviderV2 +from dbt_platform_helper.providers.aws.redis import RedisProvider +from dbt_platform_helper.providers.aws.redis import RedisProviderV2 # TODO - we don't want to use the fixtures from conftest since one applies get_supported_redis_versions diff --git a/tests/platform_helper/test_command_codebase.py b/tests/platform_helper/test_command_codebase.py index 33e9adf34..43e650b20 100644 --- a/tests/platform_helper/test_command_codebase.py +++ b/tests/platform_helper/test_command_codebase.py @@ -10,8 +10,10 @@ from dbt_platform_helper.commands.codebase import prepare as prepare_command from dbt_platform_helper.domain.codebase import ApplicationEnvironmentNotFoundException from dbt_platform_helper.domain.codebase import NotInCodeBaseRepositoryException -from dbt_platform_helper.providers.aws import CopilotCodebaseNotFoundException -from dbt_platform_helper.providers.aws import ImageNotFoundException +from dbt_platform_helper.providers.aws.exceptions import ( + CopilotCodebaseNotFoundException, +) +from dbt_platform_helper.providers.aws.exceptions import ImageNotFoundException from dbt_platform_helper.utils.application import ApplicationNotFoundException from dbt_platform_helper.utils.git import CommitNotFoundException diff --git a/tests/platform_helper/test_exceptions.py b/tests/platform_helper/test_exceptions.py index 7145fb42c..2404a66f6 100644 --- a/tests/platform_helper/test_exceptions.py +++ b/tests/platform_helper/test_exceptions.py @@ -5,10 +5,12 @@ from dbt_platform_helper.domain.codebase import ApplicationDeploymentNotTriggered from dbt_platform_helper.domain.codebase import ApplicationEnvironmentNotFoundException from dbt_platform_helper.domain.codebase import NotInCodeBaseRepositoryException -from dbt_platform_helper.providers.aws import CopilotCodebaseNotFoundException -from dbt_platform_helper.providers.aws import CreateTaskTimeoutException -from dbt_platform_helper.providers.aws import ImageNotFoundException -from dbt_platform_helper.providers.aws import LogGroupNotFoundException +from dbt_platform_helper.providers.aws.exceptions import ( + CopilotCodebaseNotFoundException, +) +from dbt_platform_helper.providers.aws.exceptions import CreateTaskTimeoutException +from dbt_platform_helper.providers.aws.exceptions import ImageNotFoundException +from dbt_platform_helper.providers.aws.exceptions import LogGroupNotFoundException from dbt_platform_helper.providers.ecs import ECSAgentNotRunningException from dbt_platform_helper.providers.ecs import NoClusterException from dbt_platform_helper.providers.secrets import AddonNotFoundException diff --git a/tests/platform_helper/utils/test_aws.py b/tests/platform_helper/utils/test_aws.py index df047d93f..e1b2bf6ef 100644 --- a/tests/platform_helper/utils/test_aws.py +++ b/tests/platform_helper/utils/test_aws.py @@ -10,9 +10,11 @@ import pytest from moto import mock_aws -from dbt_platform_helper.providers.aws import AWSException -from dbt_platform_helper.providers.aws import CopilotCodebaseNotFoundException -from dbt_platform_helper.providers.aws import LogGroupNotFoundException +from dbt_platform_helper.providers.aws.exceptions import AWSException +from dbt_platform_helper.providers.aws.exceptions import ( + CopilotCodebaseNotFoundException, +) +from dbt_platform_helper.providers.aws.exceptions import LogGroupNotFoundException from dbt_platform_helper.providers.validation import ValidationException from dbt_platform_helper.utils.aws import NoProfileForAccountIdException from dbt_platform_helper.utils.aws import Vpc From 66ed62a096f5a1708d2c601b8ca9830e8f0fad53 Mon Sep 17 00:00:00 2001 From: Anthoni Gleeson Date: Thu, 9 Jan 2025 13:58:05 +0000 Subject: [PATCH 07/14] WIP initial ducking typing impl --- .../domain/config_validator.py | 46 +++++++++------- dbt_platform_helper/domain/versions.py | 25 +++++++++ dbt_platform_helper/providers/aws/__init__.py | 30 ++++++----- .../providers/aws/interfaces.py | 18 ++----- .../providers/aws/opensearch.py | 9 ++-- dbt_platform_helper/providers/aws/redis.py | 8 +-- .../domain/test_get_supported_aws_versions.py | 50 ++++++++++++++++++ .../providers/aws/test_base.py | 38 ++++++++++++++ .../providers/{ => aws}/test_opensearch.py | 10 ++-- .../providers/{ => aws}/test_redis.py | 10 ++-- .../providers/test_config_validator.py | 52 ------------------- 11 files changed, 179 insertions(+), 117 deletions(-) create mode 100644 dbt_platform_helper/domain/versions.py create mode 100644 tests/platform_helper/domain/test_get_supported_aws_versions.py create mode 100644 tests/platform_helper/providers/aws/test_base.py rename tests/platform_helper/providers/{ => aws}/test_opensearch.py (89%) rename tests/platform_helper/providers/{ => aws}/test_redis.py (92%) diff --git a/dbt_platform_helper/domain/config_validator.py b/dbt_platform_helper/domain/config_validator.py index ea98cd928..ca0b0589f 100644 --- a/dbt_platform_helper/domain/config_validator.py +++ b/dbt_platform_helper/domain/config_validator.py @@ -4,24 +4,30 @@ from dbt_platform_helper.constants import CODEBASE_PIPELINES_KEY from dbt_platform_helper.constants import ENVIRONMENTS_KEY from dbt_platform_helper.constants import PLATFORM_CONFIG_FILE -from dbt_platform_helper.providers.aws import get_client_provider from dbt_platform_helper.providers.aws.opensearch import OpensearchProvider from dbt_platform_helper.providers.aws.redis import RedisProvider -from dbt_platform_helper.providers.cache import CacheProvider from dbt_platform_helper.utils.messages import abort_with_error +""" + get_supported_versions=get_supported_aws_versions( + RedisProviderDuck( + boto3.client("elasticache") + ) + ), + ) -# TODO where does this live? Inside the config validator? -def get_supported_versions( - client: str, cache_provider=CacheProvider(), get_client_provider_fn=get_client_provider -): - client_provider = get_client_provider_fn(client) - if cache_provider.cache_refresh_required(client_provider.get_reference()): - supported_versions = client_provider.get_supported_versions() - cache_provider.update_cache(client_provider.get_reference(), supported_versions) - return supported_versions - else: - return cache_provider.read_supported_versions_from_cache(client_provider.get_reference()) + def validate_supported_opensearch_versions(self, config): + return self._validate_extension_supported_versions( + config=config, + extension_type="opensearch", + version_key="engine", + get_supported_versions=get_supported_aws_versions( + OpensearchProviderDuck( + boto3.client("opensearch") + ) + ), + ) +""" class ConfigValidator: @@ -87,9 +93,10 @@ def validate_supported_redis_versions(self, config): config=config, extension_type="redis", version_key="engine", - # get_supported_versions=get_supported_versions( - # "elasticache" - # ), + # get_supported_versions=get_supported_aws_versions( + # RedisProviderDuck( + # boto3.client("opensearch") + # )), get_supported_versions=RedisProvider( boto3.client("elasticache") ).get_supported_redis_versions, @@ -100,9 +107,10 @@ def validate_supported_opensearch_versions(self, config): config=config, extension_type="opensearch", version_key="engine", - # get_supported_versions=get_supported_versions( - # "opensearch" - # ), + # get_supported_versions=get_supported_aws_versions( + # OpensearchProviderDuck( + # boto3.client("opensearch") + # )), get_supported_versions=OpensearchProvider( boto3.client("opensearch") ).get_supported_opensearch_versions, diff --git a/dbt_platform_helper/domain/versions.py b/dbt_platform_helper/domain/versions.py new file mode 100644 index 000000000..716e8410e --- /dev/null +++ b/dbt_platform_helper/domain/versions.py @@ -0,0 +1,25 @@ +from dbt_platform_helper.providers.aws import get_reference +from dbt_platform_helper.providers.aws import get_supported_versions +from dbt_platform_helper.providers.cache import CacheProvider + + +def get_supported_aws_versions( + client_provider, + cache_provider=CacheProvider(), +) -> list[str]: + """ + For a given AWS client provider get the supported versions if the operation + is supported. + + The cache value is retrieved if it exists. + """ + supported_versions = [] + if cache_provider.cache_refresh_required(get_reference(client_provider)): + supported_versions = get_supported_versions(client_provider) + cache_provider.update_cache(get_reference(client_provider), supported_versions) + else: + supported_versions = cache_provider.read_supported_versions_from_cache( + get_reference(client_provider) + ) + + return supported_versions diff --git a/dbt_platform_helper/providers/aws/__init__.py b/dbt_platform_helper/providers/aws/__init__.py index 9a6fa1b62..3afc74a74 100644 --- a/dbt_platform_helper/providers/aws/__init__.py +++ b/dbt_platform_helper/providers/aws/__init__.py @@ -1,14 +1,16 @@ -from dbt_platform_helper.providers.aws.exceptions import InvalidAWSClient -from dbt_platform_helper.providers.aws.interfaces import ClientProvider -from dbt_platform_helper.providers.aws.opensearch import OpensearchProviderV2 -from dbt_platform_helper.providers.aws.redis import RedisProviderV2 - - -# TODO think of a way of stubbing ClientProvider's to improve testing and local development. -def get_client_provider(client: str) -> ClientProvider: - if client == "elasticache": - return RedisProviderV2() - elif client == "opensearch": - return OpensearchProviderV2() - else: - raise InvalidAWSClient(client) +from dbt_platform_helper.providers.aws.interfaces import GetReferenceProtocal +from dbt_platform_helper.providers.aws.interfaces import GetVersionsProtocol + + +def get_supported_versions(obj: GetVersionsProtocol) -> list[str]: + if hasattr(obj, "__get_supported_versions__"): + return obj.__get_supported_versions__() + raise AttributeError( + f"Object of type {type(obj).__name__} does not support get_supported_versions" + ) + + +def get_reference(obj: GetReferenceProtocal) -> str: + if hasattr(obj, "__get_reference__"): + return obj.__get_reference__() + raise AttributeError(f"Object of type {type(obj).__name__} does not support get_reference") diff --git a/dbt_platform_helper/providers/aws/interfaces.py b/dbt_platform_helper/providers/aws/interfaces.py index eeb33f59c..8d90b34b0 100644 --- a/dbt_platform_helper/providers/aws/interfaces.py +++ b/dbt_platform_helper/providers/aws/interfaces.py @@ -1,17 +1,9 @@ -from abc import ABC -from abc import abstractmethod +from typing import Protocol -class ClientProvider(ABC): +class GetVersionsProtocol(Protocol): + def __get_support_versions__(self) -> list[str]: ... - def __init__(self, client): - self.client = client - self.engine = None - @abstractmethod - def get_reference(self): - raise NotImplementedError() - - @abstractmethod - def get_supported_versions(self): - raise NotImplementedError() +class GetReferenceProtocal(Protocol): + def __get_reference__(self) -> str: ... diff --git a/dbt_platform_helper/providers/aws/opensearch.py b/dbt_platform_helper/providers/aws/opensearch.py index e0f53796f..fcf580fad 100644 --- a/dbt_platform_helper/providers/aws/opensearch.py +++ b/dbt_platform_helper/providers/aws/opensearch.py @@ -1,6 +1,5 @@ import boto3 -from dbt_platform_helper.providers.aws.interfaces import ClientProvider from dbt_platform_helper.providers.cache import CacheProvider @@ -39,17 +38,17 @@ def __get_cache_provider(): return CacheProvider() -class OpensearchProviderV2(ClientProvider): +class OpensearchProviderDuck: - def __init__(self, client: boto3.client = boto3.client("opensearch")): + def __init__(self, client: boto3.client): self.client = client # TODO extract engine so you could swap between opensearch and elastic in the same provider self.engine = "OpenSearch" - def get_reference(self) -> str: + def __get_reference__(self) -> str: return self.engine.lower() - def get_supported_versions(self): + def __get_supported_versions__(self) -> list[str]: response = self.client.list_versions() all_versions = response["Versions"] diff --git a/dbt_platform_helper/providers/aws/redis.py b/dbt_platform_helper/providers/aws/redis.py index 1a2126e02..f7ad47987 100644 --- a/dbt_platform_helper/providers/aws/redis.py +++ b/dbt_platform_helper/providers/aws/redis.py @@ -36,16 +36,16 @@ def __get_cache_provider(): return CacheProvider() -class RedisProviderV2: +class RedisProviderDuck: - def __init__(self, client: boto3.client = boto3.client("elasticache")): + def __init__(self, client: boto3.client): self.client = client self.engine = "redis" - def get_reference(self) -> str: + def __get_reference__(self) -> str: return self.engine.lower() - def get_supported_versions(self): + def __get_supported_versions__(self) -> list[str]: supported_versions_response = self.client.describe_cache_engine_versions(Engine=self.engine) supported_versions = [ diff --git a/tests/platform_helper/domain/test_get_supported_aws_versions.py b/tests/platform_helper/domain/test_get_supported_aws_versions.py new file mode 100644 index 000000000..93a318b7c --- /dev/null +++ b/tests/platform_helper/domain/test_get_supported_aws_versions.py @@ -0,0 +1,50 @@ +from unittest.mock import MagicMock + +from dbt_platform_helper.domain.versions import get_supported_aws_versions + + +def test_get_supported_versions_cache_refresh(): + mock_cache_provider = MagicMock() + mock_aws_provider = MagicMock() + setattr(mock_aws_provider, "__get_reference__", MagicMock(return_value="doesnt-matter")) + setattr( + mock_aws_provider, + "__get_supported_versions__", + MagicMock(return_value=["doesnt", "matter"]), + ) + mock_cache_provider.cache_refresh_required.return_value = True + + versions = get_supported_aws_versions(mock_aws_provider, mock_cache_provider) + + mock_aws_provider.__get_reference__.assert_called() + mock_aws_provider.__get_supported_versions__.assert_called() + mock_cache_provider.update_cache.assert_called_with("doesnt-matter", ["doesnt", "matter"]) + mock_cache_provider.read_supported_versions_from_cache.assert_not_called() + + assert versions == ["doesnt", "matter"] + + +def test_get_supported_versions_no_cache_refresh(): + mock_cache_provider = MagicMock() + mock_aws_provider = MagicMock() + setattr(mock_aws_provider, "__get_reference__", MagicMock(return_value="doesnt-matter")) + setattr( + mock_aws_provider, + "__get_supported_versions__", + MagicMock(return_value=["doesnt", "matter"]), + ) + mock_cache_provider.cache_refresh_required.return_value = False + mock_cache_provider.read_supported_versions_from_cache.return_value = [ + "cache", + "doesnt", + "matter", + ] + + versions = get_supported_aws_versions(mock_aws_provider, mock_cache_provider) + + mock_aws_provider.__get_reference__.assert_called() + mock_aws_provider.__get_supported_versions__.assert_not_called() + mock_cache_provider.update_cache.assert_not_called() + mock_cache_provider.read_supported_versions_from_cache.assert_called_with("doesnt-matter") + + assert versions == ["cache", "doesnt", "matter"] diff --git a/tests/platform_helper/providers/aws/test_base.py b/tests/platform_helper/providers/aws/test_base.py new file mode 100644 index 000000000..3f66fbe04 --- /dev/null +++ b/tests/platform_helper/providers/aws/test_base.py @@ -0,0 +1,38 @@ +from unittest.mock import MagicMock + +import pytest + +from dbt_platform_helper.providers.aws import get_reference +from dbt_platform_helper.providers.aws import get_supported_versions + + +def test_get_reference_raises_attribute_exception(): + mock_aws_provider = MagicMock() + with pytest.raises( + AttributeError, match="Object of type MagicMock does not support get_reference" + ): + get_reference(mock_aws_provider) + + +def test_get_reference(): + mock_aws_provider = MagicMock() + setattr(mock_aws_provider, "__get_reference__", MagicMock(return_value="doesnt-matter")) + assert "doesnt-matter" == get_reference(mock_aws_provider) + + +def test_get_supported_versions(): + mock_aws_provider = MagicMock() + setattr( + mock_aws_provider, + "__get_supported_versions__", + MagicMock(return_value=["doesnt", "matter"]), + ) + assert ["doesnt", "matter"] == get_supported_versions(mock_aws_provider) + + +def test_get_supported_versions_raises_attribute_exception(): + mock_aws_provider = MagicMock() + with pytest.raises( + Exception, match="Object of type MagicMock does not support get_supported_versions" + ): + get_supported_versions(mock_aws_provider) diff --git a/tests/platform_helper/providers/test_opensearch.py b/tests/platform_helper/providers/aws/test_opensearch.py similarity index 89% rename from tests/platform_helper/providers/test_opensearch.py rename to tests/platform_helper/providers/aws/test_opensearch.py index 92d76bfdf..1fba04dfe 100644 --- a/tests/platform_helper/providers/test_opensearch.py +++ b/tests/platform_helper/providers/aws/test_opensearch.py @@ -3,7 +3,7 @@ import pytest from dbt_platform_helper.providers.aws.opensearch import OpensearchProvider -from dbt_platform_helper.providers.aws.opensearch import OpensearchProviderV2 +from dbt_platform_helper.providers.aws.opensearch import OpensearchProviderDuck @pytest.mark.skip_opensearch_fixture @@ -41,9 +41,9 @@ def test_get_supported_opensearch_versions_when_cache_refresh_required(): def test_opensearch_provider_get_reference(): opensearch_client = MagicMock() - opensearch_provider = OpensearchProviderV2(opensearch_client) + opensearch_provider = OpensearchProviderDuck(opensearch_client) - reference = opensearch_provider.get_reference() + reference = opensearch_provider.__get_reference__() assert reference == "opensearch" @@ -61,9 +61,9 @@ def test_opensearch_provider_get_supported_versions(): "Elasticsearch_7.9", ] } - opensearch_provider = OpensearchProviderV2(opensearch_client) + opensearch_provider = OpensearchProviderDuck(opensearch_client) - supported_opensearch_versions_response = opensearch_provider.get_supported_versions() + supported_opensearch_versions_response = opensearch_provider.__get_supported_versions__() opensearch_client.list_versions.assert_called_with() assert supported_opensearch_versions_response == ["2.15", "2.13", "2.11", "2.9"] diff --git a/tests/platform_helper/providers/test_redis.py b/tests/platform_helper/providers/aws/test_redis.py similarity index 92% rename from tests/platform_helper/providers/test_redis.py rename to tests/platform_helper/providers/aws/test_redis.py index 2484440c2..4ddb9bef9 100644 --- a/tests/platform_helper/providers/test_redis.py +++ b/tests/platform_helper/providers/aws/test_redis.py @@ -3,7 +3,7 @@ import pytest from dbt_platform_helper.providers.aws.redis import RedisProvider -from dbt_platform_helper.providers.aws.redis import RedisProviderV2 +from dbt_platform_helper.providers.aws.redis import RedisProviderDuck # TODO - we don't want to use the fixtures from conftest since one applies get_supported_redis_versions @@ -47,9 +47,9 @@ def test_get_supported_redis_versions_when_cache_refresh_required(): def test_redis_provider_get_reference(): elasticache_client = MagicMock() - redis_provider = RedisProviderV2(elasticache_client) + redis_provider = RedisProviderDuck(elasticache_client) - reference = redis_provider.get_reference() + reference = redis_provider.__get_reference__() assert reference == "redis" @@ -76,9 +76,9 @@ def test_redis_provider_get_supported_versions(): ] } - redis_provider = RedisProviderV2(elasticache_client) + redis_provider = RedisProviderDuck(elasticache_client) - supported_versions_response = redis_provider.get_supported_versions() + supported_versions_response = redis_provider.__get_supported_versions__() elasticache_client.describe_cache_engine_versions.assert_called_with(Engine="redis") assert supported_versions_response == ["4.0.10", "5.0.6"] diff --git a/tests/platform_helper/providers/test_config_validator.py b/tests/platform_helper/providers/test_config_validator.py index 82eadf2b7..903857efc 100644 --- a/tests/platform_helper/providers/test_config_validator.py +++ b/tests/platform_helper/providers/test_config_validator.py @@ -1,13 +1,8 @@ from unittest.mock import MagicMock -from unittest.mock import Mock import pytest from dbt_platform_helper.domain.config_validator import ConfigValidator -from dbt_platform_helper.domain.config_validator import get_supported_versions -from dbt_platform_helper.providers.aws import get_client_provider -from dbt_platform_helper.providers.aws.opensearch import OpensearchProviderV2 -from dbt_platform_helper.providers.aws.redis import RedisProviderV2 @pytest.mark.parametrize( @@ -360,50 +355,3 @@ def test_validate_extension_supported_versions(config, expected_response, capsys assert expected_response in captured.out assert captured.err == "" - - -# TODO move. This shouldn't be tested here -@pytest.mark.parametrize( - "client, valid, client_type", - [ - ("elasticache", True, RedisProviderV2), - ("opensearch", True, OpensearchProviderV2), - ("invalid-client", False, None), - ], -) -def test_get_client_provider(client, valid, client_type): - if valid: - response_provider = get_client_provider(client) - assert isinstance(response_provider, client_type) - else: - with pytest.raises(Exception, match=f"The client {client} was not found."): - response_provider = get_client_provider(client) - - -# TODO add test for invalid client exception from get_client_provider_fn -# TODO add test for cache_refresh_required false -# TODO add test for exception from get_supported_versions -# TODO add test for exception from update_cache -# TODO add test for exception from read_supported_versions_from_cache -@pytest.mark.parametrize( - "client, get_reference, get_supported_versions_return_value", - [ - ("elasticache", "redis", ["4.0.10", "5.0.6"]), - # "invalid-client", - ], -) -def test_get_supported_versions(client, get_reference, get_supported_versions_return_value): - mock_cache_provider = MagicMock() - mock_client_provider = MagicMock() - - mock_cache_provider.cache_refresh_required.return_value = True - mock_client_provider.get_reference.return_value = get_reference - mock_client_provider.get_supported_versions.return_value = get_supported_versions_return_value - get_client_provider_fn = Mock(return_value=mock_client_provider) - - versions = get_supported_versions(client, mock_cache_provider, get_client_provider_fn) - - mock_cache_provider.update_cache.assert_called() # TODO update to assert called with - mock_cache_provider.read_supported_versions_from_cache.assert_not_called() - - assert versions == get_supported_versions_return_value From 02aabc19d3e7479230fabafc8a573539f82e3e2f Mon Sep 17 00:00:00 2001 From: Anthoni Gleeson Date: Thu, 9 Jan 2025 14:53:06 +0000 Subject: [PATCH 08/14] fix spelling --- dbt_platform_helper/providers/aws/__init__.py | 4 ++-- dbt_platform_helper/providers/aws/interfaces.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dbt_platform_helper/providers/aws/__init__.py b/dbt_platform_helper/providers/aws/__init__.py index 3afc74a74..b87109011 100644 --- a/dbt_platform_helper/providers/aws/__init__.py +++ b/dbt_platform_helper/providers/aws/__init__.py @@ -1,4 +1,4 @@ -from dbt_platform_helper.providers.aws.interfaces import GetReferenceProtocal +from dbt_platform_helper.providers.aws.interfaces import GetReferenceProtocol from dbt_platform_helper.providers.aws.interfaces import GetVersionsProtocol @@ -10,7 +10,7 @@ def get_supported_versions(obj: GetVersionsProtocol) -> list[str]: ) -def get_reference(obj: GetReferenceProtocal) -> str: +def get_reference(obj: GetReferenceProtocol) -> str: if hasattr(obj, "__get_reference__"): return obj.__get_reference__() raise AttributeError(f"Object of type {type(obj).__name__} does not support get_reference") diff --git a/dbt_platform_helper/providers/aws/interfaces.py b/dbt_platform_helper/providers/aws/interfaces.py index 8d90b34b0..8751d97ec 100644 --- a/dbt_platform_helper/providers/aws/interfaces.py +++ b/dbt_platform_helper/providers/aws/interfaces.py @@ -2,8 +2,8 @@ class GetVersionsProtocol(Protocol): - def __get_support_versions__(self) -> list[str]: ... + def __get_supported_versions__(self) -> list[str]: ... -class GetReferenceProtocal(Protocol): +class GetReferenceProtocol(Protocol): def __get_reference__(self) -> str: ... From 77d02cd0342be1d20c8496e4089f10bbdea5ee3f Mon Sep 17 00:00:00 2001 From: Anthoni Gleeson Date: Thu, 9 Jan 2025 14:54:19 +0000 Subject: [PATCH 09/14] store get_reference in local variable --- dbt_platform_helper/domain/versions.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/dbt_platform_helper/domain/versions.py b/dbt_platform_helper/domain/versions.py index 716e8410e..d107c42fa 100644 --- a/dbt_platform_helper/domain/versions.py +++ b/dbt_platform_helper/domain/versions.py @@ -1,10 +1,14 @@ from dbt_platform_helper.providers.aws import get_reference from dbt_platform_helper.providers.aws import get_supported_versions +from dbt_platform_helper.providers.aws.interfaces import GetReferenceProtocol +from dbt_platform_helper.providers.aws.interfaces import GetVersionsProtocol from dbt_platform_helper.providers.cache import CacheProvider def get_supported_aws_versions( - client_provider, + client_provider: ( + GetReferenceProtocol | GetVersionsProtocol + ), # TODO how to interface required functions of object cache_provider=CacheProvider(), ) -> list[str]: """ @@ -14,12 +18,11 @@ def get_supported_aws_versions( The cache value is retrieved if it exists. """ supported_versions = [] - if cache_provider.cache_refresh_required(get_reference(client_provider)): + aws_reference = get_reference(client_provider) + if cache_provider.cache_refresh_required(aws_reference): supported_versions = get_supported_versions(client_provider) - cache_provider.update_cache(get_reference(client_provider), supported_versions) + cache_provider.update_cache(aws_reference, supported_versions) else: - supported_versions = cache_provider.read_supported_versions_from_cache( - get_reference(client_provider) - ) + supported_versions = cache_provider.read_supported_versions_from_cache(aws_reference) return supported_versions From ead018b603d6b86087c7a50151f5ccfc582adeeb Mon Sep 17 00:00:00 2001 From: Anthoni Gleeson Date: Thu, 9 Jan 2025 14:56:01 +0000 Subject: [PATCH 10/14] get_supported_aws_versions protocol --- dbt_platform_helper/domain/versions.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dbt_platform_helper/domain/versions.py b/dbt_platform_helper/domain/versions.py index d107c42fa..03afbcfb1 100644 --- a/dbt_platform_helper/domain/versions.py +++ b/dbt_platform_helper/domain/versions.py @@ -5,10 +5,12 @@ from dbt_platform_helper.providers.cache import CacheProvider +class AwsGetVersionProtocol(GetReferenceProtocol, GetVersionsProtocol): + pass + + def get_supported_aws_versions( - client_provider: ( - GetReferenceProtocol | GetVersionsProtocol - ), # TODO how to interface required functions of object + client_provider: AwsGetVersionProtocol, cache_provider=CacheProvider(), ) -> list[str]: """ From 5e6587953aed8b89ba6691852abf1b72506c4c78 Mon Sep 17 00:00:00 2001 From: Anthoni Gleeson Date: Fri, 10 Jan 2025 11:08:25 +0000 Subject: [PATCH 11/14] fixed patching of new versions function --- .../domain/config_validator.py | 55 ++++--------------- tests/platform_helper/conftest.py | 16 ++++++ .../providers/test_config_validator.py | 5 +- 3 files changed, 30 insertions(+), 46 deletions(-) diff --git a/dbt_platform_helper/domain/config_validator.py b/dbt_platform_helper/domain/config_validator.py index 0162f0057..c6e001d06 100644 --- a/dbt_platform_helper/domain/config_validator.py +++ b/dbt_platform_helper/domain/config_validator.py @@ -3,34 +3,14 @@ import boto3 import click +import dbt_platform_helper.domain.versions as versions from dbt_platform_helper.constants import CODEBASE_PIPELINES_KEY from dbt_platform_helper.constants import ENVIRONMENTS_KEY from dbt_platform_helper.constants import PLATFORM_CONFIG_FILE -from dbt_platform_helper.providers.aws.opensearch import OpensearchProvider -from dbt_platform_helper.providers.aws.redis import RedisProvider +from dbt_platform_helper.providers.aws.opensearch import OpensearchProviderDuck +from dbt_platform_helper.providers.aws.redis import RedisProviderDuck from dbt_platform_helper.utils.messages import abort_with_error -""" - get_supported_versions=get_supported_aws_versions( - RedisProviderDuck( - boto3.client("elasticache") - ) - ), - ) - - def validate_supported_opensearch_versions(self, config): - return self._validate_extension_supported_versions( - config=config, - extension_type="opensearch", - version_key="engine", - get_supported_versions=get_supported_aws_versions( - OpensearchProviderDuck( - boto3.client("opensearch") - ) - ), - ) -""" - class ConfigValidator: @@ -49,7 +29,7 @@ def run_validations(self, config: dict): validation(config) def _validate_extension_supported_versions( - self, config, extension_type, version_key, get_supported_versions + self, config, aws_provider, extension_type, version_key ): extensions = config.get("extensions", {}) if not extensions: @@ -61,7 +41,8 @@ def _validate_extension_supported_versions( if extension.get("type") == extension_type ] - supported_extension_versions = get_supported_versions() + # In this format so it can be monkey patched initially via mock_get_aws_supported_versions fixture + supported_extension_versions = versions.get_supported_aws_versions(aws_provider) extensions_with_invalid_version = [] for extension in extensions_for_type: @@ -93,29 +74,17 @@ def _validate_extension_supported_versions( def validate_supported_redis_versions(self, config): return self._validate_extension_supported_versions( config=config, - extension_type="redis", - version_key="engine", - # get_supported_versions=get_supported_aws_versions( - # RedisProviderDuck( - # boto3.client("opensearch") - # )), - get_supported_versions=RedisProvider( - boto3.client("elasticache") - ).get_supported_redis_versions, + aws_provider=RedisProviderDuck(boto3.client("elasticache")), + extension_type="redis", # TODO this is information which can live in the RedisProvider + version_key="engine", # TODO this is information which can live in the RedisProvider ) def validate_supported_opensearch_versions(self, config): return self._validate_extension_supported_versions( config=config, - extension_type="opensearch", - version_key="engine", - # get_supported_versions=get_supported_aws_versions( - # OpensearchProviderDuck( - # boto3.client("opensearch") - # )), - get_supported_versions=OpensearchProvider( - boto3.client("opensearch") - ).get_supported_opensearch_versions, + aws_provider=OpensearchProviderDuck(boto3.client("opensearch")), + extension_type="opensearch", # TODO this is information which can live in the OpensearchProvider + version_key="engine", # TODO this is information which can live in the OpensearchProvider ) def validate_environment_pipelines(self, config): diff --git a/tests/platform_helper/conftest.py b/tests/platform_helper/conftest.py index c9c614b96..3d0b303f1 100644 --- a/tests/platform_helper/conftest.py +++ b/tests/platform_helper/conftest.py @@ -728,3 +728,19 @@ def mock_return_value(self): return ["6.2", "7.0", "7.1"] monkeypatch.setattr(RedisProvider, "get_supported_redis_versions", mock_return_value) + + +# TODO - stop gap until validation.py is refactored into a class, then it will be an easier job of just passing in a mock_redis_provider into the constructor for the config_provider. For now autouse is needed. + +import dbt_platform_helper.domain.versions as versions + + +@pytest.fixture(autouse=True) +def mock_get_aws_supported_versions(request, monkeypatch): + if "skip_supported_versions_fixture" in request.keywords: + return + + def mock_return_value(self): + return ["6.2", "7.0", "7.1"] + + monkeypatch.setattr(versions, "get_supported_aws_versions", mock_return_value) diff --git a/tests/platform_helper/providers/test_config_validator.py b/tests/platform_helper/providers/test_config_validator.py index 903857efc..e69bbf990 100644 --- a/tests/platform_helper/providers/test_config_validator.py +++ b/tests/platform_helper/providers/test_config_validator.py @@ -335,20 +335,19 @@ def test_validate_database_copy_fails_if_cross_account_with_incorrect_account_id } }, }, - "redis version for environment prod is not in the list of supported redis versions: ['7.1']. Provided Version: invalid", + "redis version for environment prod is not in the list of supported redis versions: ['6.2', '7.0', '7.1']. Provided Version: invalid", ), ], ) def test_validate_extension_supported_versions(config, expected_response, capsys): mock_redis_provider = MagicMock() - mock_redis_provider.get_supported_redis_versions.return_value = ["7.1"] ConfigValidator()._validate_extension_supported_versions( config=config, + aws_provider=mock_redis_provider, extension_type="redis", version_key="engine", - get_supported_versions=mock_redis_provider.get_supported_redis_versions, ) captured = capsys.readouterr() From 151e8b3c3294bfaeaf0e2a616af33dfe7f88c9cf Mon Sep 17 00:00:00 2001 From: Anthoni Gleeson Date: Fri, 10 Jan 2025 11:09:26 +0000 Subject: [PATCH 12/14] move import to top --- tests/platform_helper/conftest.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/platform_helper/conftest.py b/tests/platform_helper/conftest.py index 3d0b303f1..4edeaebe6 100644 --- a/tests/platform_helper/conftest.py +++ b/tests/platform_helper/conftest.py @@ -13,6 +13,7 @@ from moto import mock_aws from moto.ec2 import utils as ec2_utils +import dbt_platform_helper.domain.versions as versions from dbt_platform_helper.constants import PLATFORM_CONFIG_FILE from dbt_platform_helper.providers.aws.opensearch import OpensearchProvider from dbt_platform_helper.providers.aws.redis import RedisProvider @@ -731,10 +732,6 @@ def mock_return_value(self): # TODO - stop gap until validation.py is refactored into a class, then it will be an easier job of just passing in a mock_redis_provider into the constructor for the config_provider. For now autouse is needed. - -import dbt_platform_helper.domain.versions as versions - - @pytest.fixture(autouse=True) def mock_get_aws_supported_versions(request, monkeypatch): if "skip_supported_versions_fixture" in request.keywords: From 40e9651661d8d8163ec677e7ffb510e41bff652f Mon Sep 17 00:00:00 2001 From: Anthoni Gleeson Date: Fri, 10 Jan 2025 11:18:05 +0000 Subject: [PATCH 13/14] remove old provider logic --- .../domain/config_validator.py | 8 ++-- .../providers/aws/opensearch.py | 37 --------------- dbt_platform_helper/providers/aws/redis.py | 35 -------------- tests/platform_helper/conftest.py | 26 ----------- .../providers/aws/test_opensearch.py | 40 +--------------- .../providers/aws/test_redis.py | 46 +------------------ 6 files changed, 8 insertions(+), 184 deletions(-) diff --git a/dbt_platform_helper/domain/config_validator.py b/dbt_platform_helper/domain/config_validator.py index c6e001d06..f142a22fd 100644 --- a/dbt_platform_helper/domain/config_validator.py +++ b/dbt_platform_helper/domain/config_validator.py @@ -7,8 +7,8 @@ from dbt_platform_helper.constants import CODEBASE_PIPELINES_KEY from dbt_platform_helper.constants import ENVIRONMENTS_KEY from dbt_platform_helper.constants import PLATFORM_CONFIG_FILE -from dbt_platform_helper.providers.aws.opensearch import OpensearchProviderDuck -from dbt_platform_helper.providers.aws.redis import RedisProviderDuck +from dbt_platform_helper.providers.aws.opensearch import OpensearchProvider +from dbt_platform_helper.providers.aws.redis import RedisProvider from dbt_platform_helper.utils.messages import abort_with_error @@ -74,7 +74,7 @@ def _validate_extension_supported_versions( def validate_supported_redis_versions(self, config): return self._validate_extension_supported_versions( config=config, - aws_provider=RedisProviderDuck(boto3.client("elasticache")), + aws_provider=RedisProvider(boto3.client("elasticache")), extension_type="redis", # TODO this is information which can live in the RedisProvider version_key="engine", # TODO this is information which can live in the RedisProvider ) @@ -82,7 +82,7 @@ def validate_supported_redis_versions(self, config): def validate_supported_opensearch_versions(self, config): return self._validate_extension_supported_versions( config=config, - aws_provider=OpensearchProviderDuck(boto3.client("opensearch")), + aws_provider=OpensearchProvider(boto3.client("opensearch")), extension_type="opensearch", # TODO this is information which can live in the OpensearchProvider version_key="engine", # TODO this is information which can live in the OpensearchProvider ) diff --git a/dbt_platform_helper/providers/aws/opensearch.py b/dbt_platform_helper/providers/aws/opensearch.py index fcf580fad..2d1967ed1 100644 --- a/dbt_platform_helper/providers/aws/opensearch.py +++ b/dbt_platform_helper/providers/aws/opensearch.py @@ -1,45 +1,8 @@ import boto3 -from dbt_platform_helper.providers.cache import CacheProvider - class OpensearchProvider: - def __init__(self, opensearch_client): - self.opensearch_client = opensearch_client - - def get_supported_opensearch_versions(self) -> list[str]: - - cache_provider = self.__get_cache_provider() - - if cache_provider.cache_refresh_required("opensearch"): - - response = self.opensearch_client.list_versions() - all_versions = response["Versions"] - - opensearch_versions = [ - version for version in all_versions if not version.startswith("Elasticsearch_") - ] - supported_versions = [ - version.removeprefix("OpenSearch_") for version in opensearch_versions - ] - - cache_provider.update_cache("opensearch", supported_versions) - - return supported_versions - - else: - return cache_provider.read_supported_versions_from_cache("opensearch") - - # TODO - cache provider instantiated here rather than via dependancy injection since it will likely only be used in the get_supported_opensearch_versions method. - # If another method is added which needs a CacheProvider, it should be injected into the constructor instead. - @staticmethod - def __get_cache_provider(): - return CacheProvider() - - -class OpensearchProviderDuck: - def __init__(self, client: boto3.client): self.client = client # TODO extract engine so you could swap between opensearch and elastic in the same provider diff --git a/dbt_platform_helper/providers/aws/redis.py b/dbt_platform_helper/providers/aws/redis.py index f7ad47987..22de6997b 100644 --- a/dbt_platform_helper/providers/aws/redis.py +++ b/dbt_platform_helper/providers/aws/redis.py @@ -1,42 +1,7 @@ import boto3 -from dbt_platform_helper.providers.cache import CacheProvider - class RedisProvider: - def __init__(self, elasticache_client): - self.elasticache_client = elasticache_client - - def get_supported_redis_versions(self): - - cache_provider = self.__get_cache_provider() - - if cache_provider.cache_refresh_required("redis"): - - supported_versions_response = self.elasticache_client.describe_cache_engine_versions( - Engine="redis" - ) - - supported_versions = [ - version["EngineVersion"] - for version in supported_versions_response["CacheEngineVersions"] - ] - - cache_provider.update_cache("redis", supported_versions) - - return supported_versions - - else: - return cache_provider.read_supported_versions_from_cache("redis") - - # TODO - cache provider instantiated here rather than via dependancy injection since it will likely only be used in the get_supported_redis_versions method. - # If another method is added which needs a CacheProvider, it should be injected into the constructor instead. - @staticmethod - def __get_cache_provider(): - return CacheProvider() - - -class RedisProviderDuck: def __init__(self, client: boto3.client): self.client = client diff --git a/tests/platform_helper/conftest.py b/tests/platform_helper/conftest.py index 4edeaebe6..0fb52c15f 100644 --- a/tests/platform_helper/conftest.py +++ b/tests/platform_helper/conftest.py @@ -15,8 +15,6 @@ import dbt_platform_helper.domain.versions as versions from dbt_platform_helper.constants import PLATFORM_CONFIG_FILE -from dbt_platform_helper.providers.aws.opensearch import OpensearchProvider -from dbt_platform_helper.providers.aws.redis import RedisProvider from dbt_platform_helper.utils.aws import AWS_SESSION_CACHE from dbt_platform_helper.utils.versioning import PlatformHelperVersions @@ -707,30 +705,6 @@ def create_invalid_platform_config_file(fakefs): ) -# TODO - stop gap until validation.py is refactored into a class, then it will be an easier job of just passing in a mock_redis_provider into the constructor for the config_provider. For now autouse is needed. -@pytest.fixture(autouse=True) -def mock_get_supported_opensearch_versions(request, monkeypatch): - if "skip_opensearch_fixture" in request.keywords: - return - - def mock_return_value(self): - return ["1.0", "1.1", "1.2"] - - monkeypatch.setattr(OpensearchProvider, "get_supported_opensearch_versions", mock_return_value) - - -# TODO - stop gap until validation.py is refactored into a class, then it will be an easier job of just passing in a mock_redis_provider into the constructor for the config_provider. For now autouse is needed. -@pytest.fixture(autouse=True) -def mock_get_supported_redis_versions(request, monkeypatch): - if "skip_redis_fixture" in request.keywords: - return - - def mock_return_value(self): - return ["6.2", "7.0", "7.1"] - - monkeypatch.setattr(RedisProvider, "get_supported_redis_versions", mock_return_value) - - # TODO - stop gap until validation.py is refactored into a class, then it will be an easier job of just passing in a mock_redis_provider into the constructor for the config_provider. For now autouse is needed. @pytest.fixture(autouse=True) def mock_get_aws_supported_versions(request, monkeypatch): diff --git a/tests/platform_helper/providers/aws/test_opensearch.py b/tests/platform_helper/providers/aws/test_opensearch.py index 1fba04dfe..b3c77c9ad 100644 --- a/tests/platform_helper/providers/aws/test_opensearch.py +++ b/tests/platform_helper/providers/aws/test_opensearch.py @@ -1,47 +1,11 @@ from unittest.mock import MagicMock -import pytest - from dbt_platform_helper.providers.aws.opensearch import OpensearchProvider -from dbt_platform_helper.providers.aws.opensearch import OpensearchProviderDuck - - -@pytest.mark.skip_opensearch_fixture -def test_get_supported_opensearch_versions_when_cache_refresh_required(): - - opensearch_client = MagicMock() - opensearch_client.list_versions.return_value = { - "Versions": [ - "OpenSearch_2.15", - "OpenSearch_2.13", - "OpenSearch_2.11", - "OpenSearch_2.9", - "Elasticsearch_7.10", - "Elasticsearch_7.9", - ] - } - - opensearch_provider = OpensearchProvider(opensearch_client) - - mock_cache_provider = MagicMock() - mock_cache_provider.cache_refresh_required.return_value = True - opensearch_provider._OpensearchProvider__get_cache_provider = MagicMock( - return_value=mock_cache_provider - ) - - supported_opensearch_versions_response = opensearch_provider.get_supported_opensearch_versions() - - mock_cache_provider.cache_refresh_required.assert_called_with("opensearch") - opensearch_client.list_versions.assert_called_with() - mock_cache_provider.update_cache.assert_called_with( - "opensearch", ["2.15", "2.13", "2.11", "2.9"] - ) - assert supported_opensearch_versions_response == ["2.15", "2.13", "2.11", "2.9"] def test_opensearch_provider_get_reference(): opensearch_client = MagicMock() - opensearch_provider = OpensearchProviderDuck(opensearch_client) + opensearch_provider = OpensearchProvider(opensearch_client) reference = opensearch_provider.__get_reference__() @@ -61,7 +25,7 @@ def test_opensearch_provider_get_supported_versions(): "Elasticsearch_7.9", ] } - opensearch_provider = OpensearchProviderDuck(opensearch_client) + opensearch_provider = OpensearchProvider(opensearch_client) supported_opensearch_versions_response = opensearch_provider.__get_supported_versions__() diff --git a/tests/platform_helper/providers/aws/test_redis.py b/tests/platform_helper/providers/aws/test_redis.py index 4ddb9bef9..1de0d43a9 100644 --- a/tests/platform_helper/providers/aws/test_redis.py +++ b/tests/platform_helper/providers/aws/test_redis.py @@ -1,53 +1,11 @@ from unittest.mock import MagicMock -import pytest - from dbt_platform_helper.providers.aws.redis import RedisProvider -from dbt_platform_helper.providers.aws.redis import RedisProviderDuck - - -# TODO - we don't want to use the fixtures from conftest since one applies get_supported_redis_versions -# However we will remove that autoused fixture once the validation stuff is moved to ConfigProvider, so this line needs to go too. -@pytest.mark.skip_redis_fixture -def test_get_supported_redis_versions_when_cache_refresh_required(): - - elasticache_client = MagicMock() - elasticache_client.describe_cache_engine_versions.return_value = { - "CacheEngineVersions": [ - { - "Engine": "redis", - "EngineVersion": "4.0.10", - "CacheParameterGroupFamily": "redis4.0", - "CacheEngineDescription": "Redis", - "CacheEngineVersionDescription": "redis version 4.0.10", - }, - { - "Engine": "redis", - "EngineVersion": "5.0.6", - "CacheParameterGroupFamily": "redis5.0", - "CacheEngineDescription": "Redis", - "CacheEngineVersionDescription": "redis version 5.0.6", - }, - ] - } - - redis_provider = RedisProvider(elasticache_client) - - mock_cache_provider = MagicMock() - mock_cache_provider.cache_refresh_required.return_value = True - redis_provider._RedisProvider__get_cache_provider = MagicMock(return_value=mock_cache_provider) - - supported_redis_versions_response = redis_provider.get_supported_redis_versions() - - mock_cache_provider.cache_refresh_required.assert_called_with("redis") - elasticache_client.describe_cache_engine_versions.assert_called_with(Engine="redis") - mock_cache_provider.update_cache.assert_called_with("redis", ["4.0.10", "5.0.6"]) - assert supported_redis_versions_response == ["4.0.10", "5.0.6"] def test_redis_provider_get_reference(): elasticache_client = MagicMock() - redis_provider = RedisProviderDuck(elasticache_client) + redis_provider = RedisProvider(elasticache_client) reference = redis_provider.__get_reference__() @@ -76,7 +34,7 @@ def test_redis_provider_get_supported_versions(): ] } - redis_provider = RedisProviderDuck(elasticache_client) + redis_provider = RedisProvider(elasticache_client) supported_versions_response = redis_provider.__get_supported_versions__() From 996418b06457c5fd2f97ccdf701688cf9fb9111d Mon Sep 17 00:00:00 2001 From: Anthoni Gleeson Date: Mon, 3 Feb 2025 14:15:34 +0000 Subject: [PATCH 14/14] simplify by removing descriptor methods --- dbt_platform_helper/COMMANDS.md | 856 ------------------ dbt_platform_helper/domain/versions.py | 11 +- dbt_platform_helper/providers/aws/__init__.py | 16 - .../providers/aws/interfaces.py | 4 +- .../providers/aws/opensearch.py | 4 +- dbt_platform_helper/providers/aws/redis.py | 4 +- .../domain/test_get_supported_aws_versions.py | 16 +- .../providers/aws/test_base.py | 38 - .../providers/aws/test_opensearch.py | 4 +- .../providers/aws/test_redis.py | 4 +- 10 files changed, 24 insertions(+), 933 deletions(-) delete mode 100644 dbt_platform_helper/providers/aws/__init__.py delete mode 100644 tests/platform_helper/providers/aws/test_base.py diff --git a/dbt_platform_helper/COMMANDS.md b/dbt_platform_helper/COMMANDS.md index 4fc9e97cc..80ee923cf 100644 --- a/dbt_platform_helper/COMMANDS.md +++ b/dbt_platform_helper/COMMANDS.md @@ -35,859 +35,3 @@ - [platform-helper database copy](#platform-helper-database-copy) - [platform-helper version](#platform-helper-version) - [platform-helper version get-platform-helper-for-project](#platform-helper-version-get-platform-helper-for-project) - -# platform-helper - -## Usage - -``` -platform-helper [--version] -``` - -## Options - -- `--version ` _Defaults to False._ - - Show the version and exit. -- `--help ` _Defaults to False._ - - Show this message and exit. - -## Commands - -- [`application` ↪](#platform-helper-application) -- [`codebase` ↪](#platform-helper-codebase) -- [`conduit` ↪](#platform-helper-conduit) -- [`config` ↪](#platform-helper-config) -- [`copilot` ↪](#platform-helper-copilot) -- [`database` ↪](#platform-helper-database) -- [`environment` ↪](#platform-helper-environment) -- [`generate` ↪](#platform-helper-generate) -- [`notify` ↪](#platform-helper-notify) -- [`pipeline` ↪](#platform-helper-pipeline) -- [`secrets` ↪](#platform-helper-secrets) -- [`version` ↪](#platform-helper-version) - -# platform-helper application - -[↩ Parent](#platform-helper) - - [DEPRECATED] Application metrics. - -## Usage - -``` -platform-helper application (container-stats|task-stats) -``` - -## Options - -- `--help ` _Defaults to False._ - - Show this message and exit. - -## Commands - -- [`container-stats` ↪](#platform-helper-application-container-stats) -- [`task-stats` ↪](#platform-helper-application-task-stats) - -# platform-helper application container-stats - -[↩ Parent](#platform-helper-application) - - [DEPRECATED] Command to get application container level metrics. - -## Usage - -``` -platform-helper application container-stats --env --app - [--storage] [--network] -``` - -## Options - -- `--env ` - -- `--app ` - -- `--storage ` _Defaults to False._ - -- `--network ` _Defaults to False._ - -- `--help ` _Defaults to False._ - - Show this message and exit. - -# platform-helper application task-stats - -[↩ Parent](#platform-helper-application) - - [DEPRECATED] Command to get application task level metrics. - -## Usage - -``` -platform-helper application task-stats --env --app [--disk] - [--storage] [--network] -``` - -## Options - -- `--env ` - -- `--app ` - -- `--disk ` _Defaults to False._ - -- `--storage ` _Defaults to False._ - -- `--network ` _Defaults to False._ - -- `--help ` _Defaults to False._ - - Show this message and exit. - -# platform-helper codebase - -[↩ Parent](#platform-helper) - - Codebase commands. - -## Usage - -``` -platform-helper codebase (prepare|list|build|deploy) -``` - -## Options - -- `--help ` _Defaults to False._ - - Show this message and exit. - -## Commands - -- [`build` ↪](#platform-helper-codebase-build) -- [`deploy` ↪](#platform-helper-codebase-deploy) -- [`list` ↪](#platform-helper-codebase-list) -- [`prepare` ↪](#platform-helper-codebase-prepare) - -# platform-helper codebase prepare - -[↩ Parent](#platform-helper-codebase) - - Sets up an application codebase for use within a DBT platform project. - -## Usage - -``` -platform-helper codebase prepare -``` - -## Options - -- `--help ` _Defaults to False._ - - Show this message and exit. - -# platform-helper codebase list - -[↩ Parent](#platform-helper-codebase) - - List available codebases for the application. - -## Usage - -``` -platform-helper codebase list --app [--with-images] -``` - -## Options - -- `--app ` - - AWS application name -- `--with-images ` _Defaults to False._ - - List up to the last 10 images tagged for this codebase -- `--help ` _Defaults to False._ - - Show this message and exit. - -# platform-helper codebase build - -[↩ Parent](#platform-helper-codebase) - - Trigger a CodePipeline pipeline based build. - -## Usage - -``` -platform-helper codebase build --app --codebase - --commit -``` - -## Options - -- `--app ` - - AWS application name -- `--codebase ` - - The codebase name as specified in the platform-config.yml file -- `--commit ` - - GitHub commit hash -- `--help ` _Defaults to False._ - - Show this message and exit. - -# platform-helper codebase deploy - -[↩ Parent](#platform-helper-codebase) - -## Usage - -``` -platform-helper codebase deploy --app --env --codebase - --commit -``` - -## Options - -- `--app ` - - AWS application name -- `--env ` - - AWS Copilot environment -- `--codebase ` - - The codebase name as specified in the platform-config.yml file -- `--commit ` - - GitHub commit hash -- `--help ` _Defaults to False._ - - Show this message and exit. - -# platform-helper conduit - -[↩ Parent](#platform-helper) - - Opens a shell for a given addon_name create a conduit connection to - interact with postgres, opensearch or redis. - -## Usage - -``` -platform-helper conduit - --app --env [--access (read|write|admin)] -``` - -## Arguments - -- `addon_name ` - -## Options - -- `--app ` - - Application name -- `--env ` - - Environment name -- `--access ` _Defaults to read._ - - Allow read, write or admin access to the database addons. -- `--help ` _Defaults to False._ - - Show this message and exit. - -# platform-helper config - -[↩ Parent](#platform-helper) - - Perform actions on configuration files. - -## Usage - -``` -platform-helper config (validate|aws) -``` - -## Options - -- `--help ` _Defaults to False._ - - Show this message and exit. - -## Commands - -- [`aws` ↪](#platform-helper-config-aws) -- [`validate` ↪](#platform-helper-config-validate) - -# platform-helper config validate - -[↩ Parent](#platform-helper-config) - - Validate deployment or application configuration. - -## Usage - -``` -platform-helper config validate -``` - -## Options - -- `--help ` _Defaults to False._ - - Show this message and exit. - -# platform-helper config aws - -[↩ Parent](#platform-helper-config) - - Writes a local config file containing all the AWS profiles to which the - logged in user has access. - - If no `--file-path` is specified, defaults to `~/.aws/config`. - -## Usage - -``` -platform-helper config aws [--file-path ] -``` - -## Options - -- `--file-path --fp ` _Defaults to ~/.aws/config._ - -- `--help ` _Defaults to False._ - - Show this message and exit. - -# platform-helper copilot - -[↩ Parent](#platform-helper) - -## Usage - -``` -platform-helper copilot make-addons -``` - -## Options - -- `--help ` _Defaults to False._ - - Show this message and exit. - -## Commands - -- [`make-addons` ↪](#platform-helper-copilot-make-addons) - -# platform-helper copilot make-addons - -[↩ Parent](#platform-helper-copilot) - - Generate addons CloudFormation for each environment. - -## Usage - -``` -platform-helper copilot make-addons -``` - -## Options - -- `--help ` _Defaults to False._ - - Show this message and exit. - -# platform-helper environment - -[↩ Parent](#platform-helper) - - Commands affecting environments. - -## Usage - -``` -platform-helper environment (offline|online|generate|generate-terraform) -``` - -## Options - -- `--help ` _Defaults to False._ - - Show this message and exit. - -## Commands - -- [`generate` ↪](#platform-helper-environment-generate) -- [`generate-terraform` ↪](#platform-helper-environment-generate-terraform) -- [`offline` ↪](#platform-helper-environment-offline) -- [`online` ↪](#platform-helper-environment-online) - -# platform-helper environment offline - -[↩ Parent](#platform-helper-environment) - - Take load-balanced web services offline with a maintenance page. - -## Usage - -``` -platform-helper environment offline --app --env --svc - [--template (default|migration|dmas-migration)] - [--vpc ] -``` - -## Options - -- `--app ` - -- `--env ` - -- `--svc ` _Defaults to ['web']._ - -- `--template ` _Defaults to default._ - - The maintenance page you wish to put up. -- `--vpc ` - -- `--help ` _Defaults to False._ - - Show this message and exit. - -# platform-helper environment online - -[↩ Parent](#platform-helper-environment) - - Remove a maintenance page from an environment. - -## Usage - -``` -platform-helper environment online --app --env -``` - -## Options - -- `--app ` - -- `--env ` - -- `--help ` _Defaults to False._ - - Show this message and exit. - -# platform-helper environment generate - -[↩ Parent](#platform-helper-environment) - -## Usage - -``` -platform-helper environment generate --name [--vpc-name ] -``` - -## Options - -- `--vpc-name ` - -- `--name --n ` - -- `--help ` _Defaults to False._ - - Show this message and exit. - -# platform-helper environment generate-terraform - -[↩ Parent](#platform-helper-environment) - - Generate terraform manifest for the specified environment. - -## Usage - -``` -platform-helper environment generate-terraform --name [--terraform-platform-modules-version ] -``` - -## Options - -- `--name --n ` - - The name of the environment to generate a manifest for. -- `--terraform-platform-modules-version ` - - Override the default version of terraform-platform-modules. (Default version is '5'). -- `--help ` _Defaults to False._ - - Show this message and exit. - -# platform-helper generate - -[↩ Parent](#platform-helper) - - Generate deployment pipeline configuration files and generate addons - CloudFormation template files for each environment. - - Wraps pipeline generate and make-addons. - -## Usage - -``` -platform-helper generate -``` - -## Options - -- `--help ` _Defaults to False._ - - Show this message and exit. - -# platform-helper pipeline - -[↩ Parent](#platform-helper) - - Pipeline commands. - -## Usage - -``` -platform-helper pipeline generate -``` - -## Options - -- `--help ` _Defaults to False._ - - Show this message and exit. - -## Commands - -- [`generate` ↪](#platform-helper-pipeline-generate) - -# platform-helper pipeline generate - -[↩ Parent](#platform-helper-pipeline) - - Given a platform-config.yml file, generate environment and service - deployment pipelines. - - This command does the following in relation to the environment pipelines: - - Reads contents of `platform-config.yml/environment-pipelines` configuration. - The `terraform/environment-pipelines//main.tf` file is generated using this configuration. - The `main.tf` file is then used to generate Terraform for creating an environment pipeline resource. - - This command does the following in relation to the codebase pipelines: - - Generates the copilot pipeline manifest.yml for copilot/pipelines/ - -## Usage - -``` -platform-helper pipeline generate [--terraform-platform-modules-version ] - [--deploy-branch ] -``` - -## Options - -- `--terraform-platform-modules-version ` - - Override the default version of terraform-platform-modules with a specific version or branch. -Precedence of version used is version supplied via CLI, then the version found in -platform-config.yml/default_versions/terraform-platform-modules. -In absence of these inputs, defaults to version '5'. -- `--deploy-branch ` - - Specify the branch of -deploy used to configure the source stage in the environment-pipeline resource. -This is generated from the terraform/environments-pipeline//main.tf file. -(Default -deploy branch is specified in --deploy/platform-config.yml/environment_pipelines//branch). -- `--help ` _Defaults to False._ - - Show this message and exit. - -# platform-helper secrets - -[↩ Parent](#platform-helper) - -## Usage - -``` -platform-helper secrets (copy|list) -``` - -## Options - -- `--help ` _Defaults to False._ - - Show this message and exit. - -## Commands - -- [`copy` ↪](#platform-helper-secrets-copy) -- [`list` ↪](#platform-helper-secrets-list) - -# platform-helper secrets copy - -[↩ Parent](#platform-helper-secrets) - - Copy secrets from one environment to a new environment. - -## Usage - -``` -platform-helper secrets copy - --project-profile -``` - -## Arguments - -- `source_environment ` -- `target_environment ` - -## Options - -- `--project-profile ` - - AWS account profile name -- `--help ` _Defaults to False._ - - Show this message and exit. - -# platform-helper secrets list - -[↩ Parent](#platform-helper-secrets) - - List secret names and values for an environment. - -## Usage - -``` -platform-helper secrets list -``` - -## Arguments - -- `app ` -- `env ` - -## Options - -- `--help ` _Defaults to False._ - - Show this message and exit. - -# platform-helper notify - -[↩ Parent](#platform-helper) - - Send Slack notifications - -## Usage - -``` -platform-helper notify (environment-progress|add-comment) -``` - -## Options - -- `--help ` _Defaults to False._ - - Show this message and exit. - -## Commands - -- [`add-comment` ↪](#platform-helper-notify-add-comment) -- [`environment-progress` ↪](#platform-helper-notify-environment-progress) - -# platform-helper notify environment-progress - -[↩ Parent](#platform-helper-notify) - - Send environment progress notifications - -## Usage - -``` -platform-helper notify environment-progress - - [--build-arn ] - [--repository ] - [--commit-sha ] - [--slack-ref ] -``` - -## Arguments - -- `slack-channel-id ` -- `slack-token ` -- `message ` - -## Options - -- `--build-arn ` - -- `--repository ` - -- `--commit-sha ` - -- `--slack-ref ` - - Slack message reference -- `--help ` _Defaults to False._ - - Show this message and exit. - -# platform-helper notify add-comment - -[↩ Parent](#platform-helper-notify) - - Add comment to a notification - -## Usage - -``` -platform-helper notify add-comment - - [--title ] [--send-to-main-channel <send_to_main_channel>] -``` - -## Arguments - -- `slack-channel-id <text>` -- `slack-token <text>` -- `slack-ref <text>` -- `message <text>` - -## Options - -- `--title <text>` - - Message title -- `--send-to-main-channel <boolean>` _Defaults to False._ - - Send to main channel -- `--help <boolean>` _Defaults to False._ - - Show this message and exit. - -# platform-helper database - -[↩ Parent](#platform-helper) - - Commands to copy data between databases. - -## Usage - -``` -platform-helper database (dump|load|copy) -``` - -## Options - -- `--help <boolean>` _Defaults to False._ - - Show this message and exit. - -## Commands - -- [`copy` ↪](#platform-helper-database-copy) -- [`dump` ↪](#platform-helper-database-dump) -- [`load` ↪](#platform-helper-database-load) - -# platform-helper database dump - -[↩ Parent](#platform-helper-database) - - Dump a database into an S3 bucket. - -## Usage - -``` -platform-helper database dump --from <from_env> --database <database> - [--app <application>] [--from-vpc <from_vpc>] - [--filename <filename>] -``` - -## Options - -- `--app <text>` - - The application name. Required unless you are running the command from your deploy repo -- `--from <text>` - - The environment you are dumping data from -- `--database <text>` - - The name of the database you are dumping data from -- `--from-vpc <text>` - - The vpc the specified environment is running in. Required unless you are running the command from your deploy repo -- `--filename <text>` - - Specify a name for the database dump file. Recommended if the same dump database is being used for multiple load environments -- `--help <boolean>` _Defaults to False._ - - Show this message and exit. - -# platform-helper database load - -[↩ Parent](#platform-helper-database) - - Load a database from an S3 bucket. - -## Usage - -``` -platform-helper database load --to <to_env> --database <database> - [--app <application>] [--to-vpc <to_vpc>] - [--filename <filename>] [--auto-approve] -``` - -## Options - -- `--app <text>` - - The application name. Required unless you are running the command from your deploy repo -- `--to <text>` - - The environment you are loading data into -- `--database <text>` - - The name of the database you are loading data into -- `--to-vpc <text>` - - The vpc the specified environment is running in. Required unless you are running the command from your deploy repo -- `--auto-approve <boolean>` _Defaults to False._ - -- `--filename <text>` - - Specify a name for the database dump file. Recommended if the same dump database is being used for multiple load environments -- `--help <boolean>` _Defaults to False._ - - Show this message and exit. - -# platform-helper database copy - -[↩ Parent](#platform-helper-database) - - Copy a database between environments. - -## Usage - -``` -platform-helper database copy --from <from_env> --to <to_env> --database <database> - --svc <service> [--app <application>] [--from-vpc <from_vpc>] - [--to-vpc <to_vpc>] [--template (default|migration|dmas-migration)] - [--auto-approve] [--no-maintenance-page] -``` - -## Options - -- `--app <text>` - - The application name. Required unless you are running the command from your deploy repo -- `--from <text>` - - The environment you are copying data from -- `--to <text>` - - The environment you are copying data into -- `--database <text>` - - The name of the database you are copying -- `--from-vpc <text>` - - The vpc the environment you are copying from is running in. Required unless you are running the command from your deploy repo -- `--to-vpc <text>` - - The vpc the environment you are copying into is running in. Required unless you are running the command from your deploy repo -- `--auto-approve <boolean>` _Defaults to False._ - -- `--svc <text>` _Defaults to ['web']._ - -- `--template <choice>` _Defaults to default._ - - The maintenance page you wish to put up. -- `--no-maintenance-page <boolean>` _Defaults to False._ - -- `--help <boolean>` _Defaults to False._ - - Show this message and exit. - -# platform-helper version - -[↩ Parent](#platform-helper) - - Contains subcommands for getting version information about the - current project. - -## Usage - -``` -platform-helper version get-platform-helper-for-project -``` - -## Options - -- `--help <boolean>` _Defaults to False._ - - Show this message and exit. - -## Commands - -- [`get-platform-helper-for-project` ↪](#platform-helper-version-get-platform-helper-for-project) - -# platform-helper version get-platform-helper-for-project - -[↩ Parent](#platform-helper-version) - - Print the version of platform-tools required by the current project - -## Usage - -``` -platform-helper version get-platform-helper-for-project [--pipeline <pipeline>] -``` - -## Options - -- `--pipeline <text>` - - Take into account platform-tools version overrides in the specified pipeline -- `--help <boolean>` _Defaults to False._ - - Show this message and exit. diff --git a/dbt_platform_helper/domain/versions.py b/dbt_platform_helper/domain/versions.py index 03afbcfb1..9250b468e 100644 --- a/dbt_platform_helper/domain/versions.py +++ b/dbt_platform_helper/domain/versions.py @@ -1,5 +1,5 @@ -from dbt_platform_helper.providers.aws import get_reference -from dbt_platform_helper.providers.aws import get_supported_versions +from typing import List + from dbt_platform_helper.providers.aws.interfaces import GetReferenceProtocol from dbt_platform_helper.providers.aws.interfaces import GetVersionsProtocol from dbt_platform_helper.providers.cache import CacheProvider @@ -9,10 +9,11 @@ class AwsGetVersionProtocol(GetReferenceProtocol, GetVersionsProtocol): pass +# TODO this will be set up within the caching provider using the stragegy pattern def get_supported_aws_versions( client_provider: AwsGetVersionProtocol, cache_provider=CacheProvider(), -) -> list[str]: +) -> List[str]: """ For a given AWS client provider get the supported versions if the operation is supported. @@ -20,9 +21,9 @@ def get_supported_aws_versions( The cache value is retrieved if it exists. """ supported_versions = [] - aws_reference = get_reference(client_provider) + aws_reference = client_provider.get_reference() if cache_provider.cache_refresh_required(aws_reference): - supported_versions = get_supported_versions(client_provider) + supported_versions = client_provider.get_supported_versions() cache_provider.update_cache(aws_reference, supported_versions) else: supported_versions = cache_provider.read_supported_versions_from_cache(aws_reference) diff --git a/dbt_platform_helper/providers/aws/__init__.py b/dbt_platform_helper/providers/aws/__init__.py deleted file mode 100644 index b87109011..000000000 --- a/dbt_platform_helper/providers/aws/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -from dbt_platform_helper.providers.aws.interfaces import GetReferenceProtocol -from dbt_platform_helper.providers.aws.interfaces import GetVersionsProtocol - - -def get_supported_versions(obj: GetVersionsProtocol) -> list[str]: - if hasattr(obj, "__get_supported_versions__"): - return obj.__get_supported_versions__() - raise AttributeError( - f"Object of type {type(obj).__name__} does not support get_supported_versions" - ) - - -def get_reference(obj: GetReferenceProtocol) -> str: - if hasattr(obj, "__get_reference__"): - return obj.__get_reference__() - raise AttributeError(f"Object of type {type(obj).__name__} does not support get_reference") diff --git a/dbt_platform_helper/providers/aws/interfaces.py b/dbt_platform_helper/providers/aws/interfaces.py index 8751d97ec..d83bafc84 100644 --- a/dbt_platform_helper/providers/aws/interfaces.py +++ b/dbt_platform_helper/providers/aws/interfaces.py @@ -2,8 +2,8 @@ class GetVersionsProtocol(Protocol): - def __get_supported_versions__(self) -> list[str]: ... + def get_supported_versions(self) -> list[str]: ... class GetReferenceProtocol(Protocol): - def __get_reference__(self) -> str: ... + def get_reference(self) -> str: ... diff --git a/dbt_platform_helper/providers/aws/opensearch.py b/dbt_platform_helper/providers/aws/opensearch.py index 2d1967ed1..0b4aa6776 100644 --- a/dbt_platform_helper/providers/aws/opensearch.py +++ b/dbt_platform_helper/providers/aws/opensearch.py @@ -8,10 +8,10 @@ def __init__(self, client: boto3.client): # TODO extract engine so you could swap between opensearch and elastic in the same provider self.engine = "OpenSearch" - def __get_reference__(self) -> str: + def get_reference(self) -> str: return self.engine.lower() - def __get_supported_versions__(self) -> list[str]: + def get_supported_versions(self) -> list[str]: response = self.client.list_versions() all_versions = response["Versions"] diff --git a/dbt_platform_helper/providers/aws/redis.py b/dbt_platform_helper/providers/aws/redis.py index 22de6997b..c34414298 100644 --- a/dbt_platform_helper/providers/aws/redis.py +++ b/dbt_platform_helper/providers/aws/redis.py @@ -7,10 +7,10 @@ def __init__(self, client: boto3.client): self.client = client self.engine = "redis" - def __get_reference__(self) -> str: + def get_reference(self) -> str: return self.engine.lower() - def __get_supported_versions__(self) -> list[str]: + def get_supported_versions(self) -> list[str]: supported_versions_response = self.client.describe_cache_engine_versions(Engine=self.engine) supported_versions = [ diff --git a/tests/platform_helper/domain/test_get_supported_aws_versions.py b/tests/platform_helper/domain/test_get_supported_aws_versions.py index 93a318b7c..2a7aa6b0b 100644 --- a/tests/platform_helper/domain/test_get_supported_aws_versions.py +++ b/tests/platform_helper/domain/test_get_supported_aws_versions.py @@ -6,18 +6,18 @@ def test_get_supported_versions_cache_refresh(): mock_cache_provider = MagicMock() mock_aws_provider = MagicMock() - setattr(mock_aws_provider, "__get_reference__", MagicMock(return_value="doesnt-matter")) + setattr(mock_aws_provider, "get_reference", MagicMock(return_value="doesnt-matter")) setattr( mock_aws_provider, - "__get_supported_versions__", + "get_supported_versions", MagicMock(return_value=["doesnt", "matter"]), ) mock_cache_provider.cache_refresh_required.return_value = True versions = get_supported_aws_versions(mock_aws_provider, mock_cache_provider) - mock_aws_provider.__get_reference__.assert_called() - mock_aws_provider.__get_supported_versions__.assert_called() + mock_aws_provider.get_reference.assert_called() + mock_aws_provider.get_supported_versions.assert_called() mock_cache_provider.update_cache.assert_called_with("doesnt-matter", ["doesnt", "matter"]) mock_cache_provider.read_supported_versions_from_cache.assert_not_called() @@ -27,10 +27,10 @@ def test_get_supported_versions_cache_refresh(): def test_get_supported_versions_no_cache_refresh(): mock_cache_provider = MagicMock() mock_aws_provider = MagicMock() - setattr(mock_aws_provider, "__get_reference__", MagicMock(return_value="doesnt-matter")) + setattr(mock_aws_provider, "get_reference", MagicMock(return_value="doesnt-matter")) setattr( mock_aws_provider, - "__get_supported_versions__", + "get_supported_versions", MagicMock(return_value=["doesnt", "matter"]), ) mock_cache_provider.cache_refresh_required.return_value = False @@ -42,8 +42,8 @@ def test_get_supported_versions_no_cache_refresh(): versions = get_supported_aws_versions(mock_aws_provider, mock_cache_provider) - mock_aws_provider.__get_reference__.assert_called() - mock_aws_provider.__get_supported_versions__.assert_not_called() + mock_aws_provider.get_reference.assert_called() + mock_aws_provider.get_supported_versions.assert_not_called() mock_cache_provider.update_cache.assert_not_called() mock_cache_provider.read_supported_versions_from_cache.assert_called_with("doesnt-matter") diff --git a/tests/platform_helper/providers/aws/test_base.py b/tests/platform_helper/providers/aws/test_base.py deleted file mode 100644 index 3f66fbe04..000000000 --- a/tests/platform_helper/providers/aws/test_base.py +++ /dev/null @@ -1,38 +0,0 @@ -from unittest.mock import MagicMock - -import pytest - -from dbt_platform_helper.providers.aws import get_reference -from dbt_platform_helper.providers.aws import get_supported_versions - - -def test_get_reference_raises_attribute_exception(): - mock_aws_provider = MagicMock() - with pytest.raises( - AttributeError, match="Object of type MagicMock does not support get_reference" - ): - get_reference(mock_aws_provider) - - -def test_get_reference(): - mock_aws_provider = MagicMock() - setattr(mock_aws_provider, "__get_reference__", MagicMock(return_value="doesnt-matter")) - assert "doesnt-matter" == get_reference(mock_aws_provider) - - -def test_get_supported_versions(): - mock_aws_provider = MagicMock() - setattr( - mock_aws_provider, - "__get_supported_versions__", - MagicMock(return_value=["doesnt", "matter"]), - ) - assert ["doesnt", "matter"] == get_supported_versions(mock_aws_provider) - - -def test_get_supported_versions_raises_attribute_exception(): - mock_aws_provider = MagicMock() - with pytest.raises( - Exception, match="Object of type MagicMock does not support get_supported_versions" - ): - get_supported_versions(mock_aws_provider) diff --git a/tests/platform_helper/providers/aws/test_opensearch.py b/tests/platform_helper/providers/aws/test_opensearch.py index b3c77c9ad..5595676fa 100644 --- a/tests/platform_helper/providers/aws/test_opensearch.py +++ b/tests/platform_helper/providers/aws/test_opensearch.py @@ -7,7 +7,7 @@ def test_opensearch_provider_get_reference(): opensearch_client = MagicMock() opensearch_provider = OpensearchProvider(opensearch_client) - reference = opensearch_provider.__get_reference__() + reference = opensearch_provider.get_reference() assert reference == "opensearch" @@ -27,7 +27,7 @@ def test_opensearch_provider_get_supported_versions(): } opensearch_provider = OpensearchProvider(opensearch_client) - supported_opensearch_versions_response = opensearch_provider.__get_supported_versions__() + supported_opensearch_versions_response = opensearch_provider.get_supported_versions() opensearch_client.list_versions.assert_called_with() assert supported_opensearch_versions_response == ["2.15", "2.13", "2.11", "2.9"] diff --git a/tests/platform_helper/providers/aws/test_redis.py b/tests/platform_helper/providers/aws/test_redis.py index 1de0d43a9..b6a2c2d0c 100644 --- a/tests/platform_helper/providers/aws/test_redis.py +++ b/tests/platform_helper/providers/aws/test_redis.py @@ -7,7 +7,7 @@ def test_redis_provider_get_reference(): elasticache_client = MagicMock() redis_provider = RedisProvider(elasticache_client) - reference = redis_provider.__get_reference__() + reference = redis_provider.get_reference() assert reference == "redis" @@ -36,7 +36,7 @@ def test_redis_provider_get_supported_versions(): redis_provider = RedisProvider(elasticache_client) - supported_versions_response = redis_provider.__get_supported_versions__() + supported_versions_response = redis_provider.get_supported_versions() elasticache_client.describe_cache_engine_versions.assert_called_with(Engine="redis") assert supported_versions_response == ["4.0.10", "5.0.6"]