diff --git a/CHANGELOG.md b/CHANGELOG.md index d6a0a5fd29..292aad97b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm +## 0.15.2 (2024-12-15) + +### Improvements + +- Add handling for different installation types compatibility + + ## 0.15.1 (2024-12-15) ### Bug Fixes diff --git a/port_ocean/core/models.py b/port_ocean/core/models.py index 1ba98fb530..c5906f41aa 100644 --- a/port_ocean/core/models.py +++ b/port_ocean/core/models.py @@ -8,12 +8,23 @@ class Runtime(Enum): Saas = "Saas" - SaasOauth2 = "SaasOauth2" OnPrem = "OnPrem" @property def is_saas_runtime(self) -> bool: - return self in [Runtime.Saas, Runtime.SaasOauth2] + return self in [Runtime.Saas] + + def is_installation_type_compatible(self, installation_type: str) -> bool: + """ + Check if the installation type is compatible with the runtime + + if the runtime is Saas, the installation type should start with Saas + else the installation type should be OnPrem + """ + return ( + self.value == Runtime.Saas.value + and installation_type.startswith(self.value) + ) or installation_type == self.value class Entity(BaseModel): diff --git a/port_ocean/core/utils.py b/port_ocean/core/utils.py index 0c6ffc6f10..dbbfea8a3b 100644 --- a/port_ocean/core/utils.py +++ b/port_ocean/core/utils.py @@ -42,10 +42,12 @@ async def validate_integration_runtime( current_integration = await port_client.get_current_integration( should_raise=False, should_log=False ) - current_runtime = current_integration.get("installationType", "OnPrem") - if current_integration and current_runtime != requested_runtime.value: + current_installation_type = current_integration.get("installationType", "OnPrem") + if current_integration and not requested_runtime.is_installation_type_compatible( + current_installation_type + ): raise IntegrationRuntimeException( - f"Invalid Runtime! Requested to run existing {current_runtime} integration in {requested_runtime} runtime." + f"Invalid Runtime! Requested to run existing {current_installation_type} integration in {requested_runtime} runtime." ) diff --git a/port_ocean/tests/core/test_utils.py b/port_ocean/tests/core/test_utils.py new file mode 100644 index 0000000000..c291778c0c --- /dev/null +++ b/port_ocean/tests/core/test_utils.py @@ -0,0 +1,73 @@ +from unittest.mock import AsyncMock, patch + +import pytest + +from port_ocean.core.utils import validate_integration_runtime +from port_ocean.clients.port.client import PortClient +from port_ocean.core.models import Runtime +from port_ocean.tests.helpers.port_client import get_port_client_for_integration +from port_ocean.exceptions.core import IntegrationRuntimeException + + +class TestValidateIntegrationRuntime: + + @pytest.mark.asyncio + @pytest.mark.parametrize( + "requested_runtime, installation_type, should_raise", + [ + (Runtime.Saas, "Saas", False), + (Runtime.Saas, "SaasOauth2", False), + (Runtime.Saas, "OnPrem", True), + (Runtime.OnPrem, "OnPrem", False), + (Runtime.OnPrem, "SaasOauth2", True), + ], + ) + @patch.object(PortClient, "get_current_integration", new_callable=AsyncMock) + async def test_validate_integration_runtime( + self, + mock_get_current_integration: AsyncMock, + requested_runtime: Runtime, + installation_type: str, + should_raise: bool, + ) -> None: + # Arrange + port_client = get_port_client_for_integration( + client_id="mock-client-id", + client_secret="mock-client-secret", + integration_identifier="mock-integration-identifier", + integration_type="mock-integration-type", + integration_version="mock-integration-version", + base_url="mock-base-url", + ) + + # Mock the return value of get_current_integration + mock_get_current_integration.return_value = { + "installationType": installation_type + } + + # Act & Assert + if should_raise: + with pytest.raises(IntegrationRuntimeException): + await validate_integration_runtime(port_client, requested_runtime) + else: + await validate_integration_runtime(port_client, requested_runtime) + + # Verify that get_current_integration was called once + mock_get_current_integration.assert_called_once() + + @pytest.mark.parametrize( + "requested_runtime, installation_type, expected", + [ + (Runtime.Saas, "SaasOauth2", True), + (Runtime.Saas, "OnPrem", False), + (Runtime.OnPrem, "OnPrem", True), + (Runtime.OnPrem, "SaasCloud", False), + ], + ) + def test_runtime_installation_compatibility( + self, requested_runtime: Runtime, installation_type: str, expected: bool + ) -> None: + assert ( + requested_runtime.is_installation_type_compatible(installation_type) + == expected + ) diff --git a/pyproject.toml b/pyproject.toml index 702442f5f9..e94fed2990 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "port-ocean" -version = "0.15.1" +version = "0.15.2" description = "Port Ocean is a CLI tool for managing your Port projects." readme = "README.md" homepage = "https://app.getport.io"