-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Core] Add support for choosing default resources integration will cr…
…eate dynamically (#1129) # Description What - Add the option to create custom type of resources for an integration Why - Ocean Saas is the only type of Ocean integrations that can use secrets How - added a new config parameter to the integration settings ## Type of change Please leave one option from the following and delete the rest: - [ ] Bug fix (non-breaking change which fixes an issue) - [X] New feature (non-breaking change which adds functionality) - [ ] New Integration (non-breaking change which adds a new integration) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] Non-breaking change (fix of existing functionality that will not change current behavior) - [ ] Documentation (added/updated documentation) <h4> All tests should be run against the port production environment(using a testing org). </h4> ### Core testing checklist - [x] Integration able to create all default resources from scratch - [x] Resync finishes successfully - [x] Resync able to create entities - [x] Resync able to update entities - [x] Resync able to detect and delete entities - [ ] Scheduled resync able to abort existing resync and start a new one - [ ] Tested with at least 2 integrations from scratch - [ ] Tested with Kafka and Polling event listeners - [ ] Tested deletion of entities that don't pass the selector ### Integration testing checklist - [ ] Integration able to create all default resources from scratch - [ ] Resync able to create entities - [ ] Resync able to update entities - [ ] Resync able to detect and delete entities - [ ] Resync finishes successfully - [ ] If new resource kind is added or updated in the integration, add example raw data, mapping and expected result to the `examples` folder in the integration directory. - [ ] If resource kind is updated, run the integration with the example data and check if the expected result is achieved - [ ] If new resource kind is added or updated, validate that live-events for that resource are working as expected - [ ] Docs PR link [here](#) ### Preflight checklist - [ ] Handled rate limiting - [ ] Handled pagination - [ ] Implemented the code in async - [ ] Support Multi account ## Screenshots Include screenshots from your environment showing how the resources of the integration will look. ## API Documentation Provide links to the API documentation used for this integration. --------- Co-authored-by: Shalev Avhar <[email protected]> Co-authored-by: Tom Tankilevitch <[email protected]>
- Loading branch information
1 parent
9e6591b
commit 9fae538
Showing
8 changed files
with
215 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
import pytest | ||
import json | ||
from unittest.mock import patch | ||
from pathlib import Path | ||
from port_ocean.core.handlers.port_app_config.models import PortAppConfig | ||
from port_ocean.core.defaults.common import ( | ||
get_port_integration_defaults, | ||
Defaults, | ||
) | ||
|
||
|
||
@pytest.fixture | ||
def setup_mock_directories(tmp_path: Path) -> tuple[Path, Path, Path]: | ||
# Create .port/resources with sample files | ||
default_dir = tmp_path / ".port/resources" | ||
default_dir.mkdir(parents=True, exist_ok=True) | ||
|
||
# Create mock JSON and YAML files with expected content | ||
(default_dir / "blueprints.json").write_text( | ||
json.dumps( | ||
[ | ||
{ | ||
"identifier": "mock-identifier", | ||
"title": "mock-title", | ||
"icon": "mock-icon", | ||
"schema": { | ||
"type": "object", | ||
"properties": {"key": {"type": "string"}}, | ||
}, | ||
} | ||
] | ||
) | ||
) | ||
(default_dir / "port-app-config.json").write_text( | ||
json.dumps( | ||
{ | ||
"resources": [ | ||
{ | ||
"kind": "mock-kind", | ||
"selector": {"query": "true"}, | ||
"port": { | ||
"entity": { | ||
"mappings": { | ||
"identifier": ".id", | ||
"title": ".title", | ||
"blueprint": '"mock-identifier"', | ||
} | ||
} | ||
}, | ||
} | ||
] | ||
} | ||
) | ||
) | ||
|
||
# Create .port/custom_resources with different sample files | ||
custom_resources_dir = tmp_path / ".port/custom_resources" | ||
custom_resources_dir.mkdir(parents=True, exist_ok=True) | ||
|
||
# Create mock JSON and YAML files with expected content | ||
(custom_resources_dir / "blueprints.json").write_text( | ||
json.dumps( | ||
[ | ||
{ | ||
"identifier": "mock-custom-identifier", | ||
"title": "mock-custom-title", | ||
"icon": "mock-custom-icon", | ||
"schema": { | ||
"type": "object", | ||
"properties": {"key": {"type": "string"}}, | ||
}, | ||
} | ||
] | ||
) | ||
) | ||
(custom_resources_dir / "port-app-config.json").write_text( | ||
json.dumps( | ||
{ | ||
"resources": [ | ||
{ | ||
"kind": "mock-custom-kind", | ||
"selector": {"query": "true"}, | ||
"port": { | ||
"entity": { | ||
"mappings": { | ||
"identifier": ".id", | ||
"title": ".title", | ||
"blueprint": '"mock-custom-identifier"', | ||
} | ||
} | ||
}, | ||
} | ||
] | ||
} | ||
) | ||
) | ||
|
||
# Define the non-existing directory path | ||
non_existing_dir = tmp_path / ".port/do_not_exist" | ||
|
||
return default_dir, custom_resources_dir, non_existing_dir | ||
|
||
|
||
def test_custom_defaults_dir_used_if_valid( | ||
setup_mock_directories: tuple[Path, Path, Path] | ||
) -> None: | ||
# Arrange | ||
_, custom_resources_dir, _ = setup_mock_directories | ||
|
||
with ( | ||
patch("port_ocean.core.defaults.common.is_valid_dir") as mock_is_valid_dir, | ||
patch( | ||
"pathlib.Path.iterdir", | ||
return_value=custom_resources_dir.iterdir(), | ||
), | ||
): | ||
mock_is_valid_dir.side_effect = lambda path: path == custom_resources_dir | ||
|
||
# Act | ||
defaults = get_port_integration_defaults( | ||
port_app_config_class=PortAppConfig, | ||
custom_defaults_dir=".port/custom_resources", | ||
base_path=custom_resources_dir.parent.parent, | ||
) | ||
|
||
# Assert | ||
assert isinstance(defaults, Defaults) | ||
assert defaults.blueprints[0].get("identifier") == "mock-custom-identifier" | ||
assert defaults.port_app_config is not None | ||
assert defaults.port_app_config.resources[0].kind == "mock-custom-kind" | ||
|
||
|
||
def test_fallback_to_default_dir_if_custom_dir_invalid( | ||
setup_mock_directories: tuple[Path, Path, Path] | ||
) -> None: | ||
resources_dir, _, non_existing_dir = setup_mock_directories | ||
|
||
# Arrange | ||
with ( | ||
patch("port_ocean.core.defaults.common.is_valid_dir") as mock_is_valid_dir, | ||
patch("pathlib.Path.iterdir", return_value=resources_dir.iterdir()), | ||
): | ||
|
||
mock_is_valid_dir.side_effect = lambda path: path == resources_dir | ||
|
||
# Act | ||
custom_defaults_dir = str(non_existing_dir.relative_to(resources_dir.parent)) | ||
defaults = get_port_integration_defaults( | ||
port_app_config_class=PortAppConfig, | ||
custom_defaults_dir=custom_defaults_dir, | ||
base_path=resources_dir.parent.parent, | ||
) | ||
|
||
# Assert | ||
assert isinstance(defaults, Defaults) | ||
assert defaults.blueprints[0].get("identifier") == "mock-identifier" | ||
assert defaults.port_app_config is not None | ||
assert defaults.port_app_config.resources[0].kind == "mock-kind" | ||
|
||
|
||
def test_default_resources_path_does_not_exist() -> None: | ||
# Act | ||
defaults = get_port_integration_defaults(port_app_config_class=PortAppConfig) | ||
|
||
# Assert | ||
assert defaults is None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters