port-ocean 0.9.8__tar.gz → 0.9.12__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of port-ocean might be problematic. Click here for more details.
- {port_ocean-0.9.8 → port_ocean-0.9.12}/PKG-INFO +1 -1
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/cookiecutter/hooks/post_gen_project.py +3 -2
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/pyproject.toml +2 -1
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/clients/port/mixins/entities.py +21 -4
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/config/base.py +14 -12
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/config/settings.py +31 -7
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/handlers/entities_state_applier/base.py +4 -1
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/handlers/entities_state_applier/port/applier.py +13 -10
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/integrations/mixins/sync.py +4 -2
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/integrations/mixins/sync_raw.py +8 -5
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/ocean.py +5 -10
- {port_ocean-0.9.8 → port_ocean-0.9.12}/pyproject.toml +1 -1
- {port_ocean-0.9.8 → port_ocean-0.9.12}/LICENSE.md +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/README.md +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/bootstrap.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/cli.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/commands/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/commands/defaults/__init___.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/commands/defaults/clean.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/commands/defaults/dock.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/commands/defaults/group.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/commands/list_integrations.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/commands/main.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/commands/new.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/commands/pull.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/commands/sail.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/commands/version.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/cookiecutter/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/cookiecutter/cookiecutter.json +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/cookiecutter/extensions.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.dockerignore +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.gitignore +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/.gitignore +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/spec.yaml +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/CHANGELOG.md +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/Dockerfile +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/Makefile +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/README.md +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/changelog/.gitignore +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/debug.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/main.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/poetry.toml +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/sonar-project.properties +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/tests/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/utils.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/clients/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/clients/port/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/clients/port/authentication.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/clients/port/client.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/clients/port/mixins/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/clients/port/mixins/blueprints.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/clients/port/mixins/integrations.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/clients/port/mixins/migrations.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/clients/port/retry_transport.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/clients/port/types.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/clients/port/utils.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/config/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/config/dynamic.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/consumers/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/consumers/kafka_consumer.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/context/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/context/event.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/context/ocean.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/context/resource.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/defaults/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/defaults/clean.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/defaults/common.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/defaults/initialize.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/event_listener/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/event_listener/base.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/event_listener/factory.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/event_listener/http.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/event_listener/kafka.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/event_listener/once.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/event_listener/polling.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/handlers/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/handlers/base.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/handlers/entities_state_applier/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/handlers/entities_state_applier/port/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/handlers/entities_state_applier/port/get_related_entities.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/handlers/entities_state_applier/port/order_by_entities_dependencies.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/handlers/entity_processor/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/handlers/entity_processor/base.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/handlers/entity_processor/jq_entity_processor.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/handlers/port_app_config/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/handlers/port_app_config/api.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/handlers/port_app_config/base.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/handlers/port_app_config/models.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/integrations/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/integrations/base.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/integrations/mixins/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/integrations/mixins/events.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/integrations/mixins/handler.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/integrations/mixins/utils.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/models.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/ocean_types.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/utils.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/exceptions/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/exceptions/api.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/exceptions/base.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/exceptions/clients.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/exceptions/context.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/exceptions/core.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/exceptions/port_defaults.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/exceptions/utils.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/helpers/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/helpers/async_client.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/helpers/retry.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/log/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/log/handlers.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/log/logger_setup.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/log/sensetive.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/middlewares.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/py.typed +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/run.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/sonar-project.properties +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/utils/__init__.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/utils/async_http.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/utils/async_iterators.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/utils/cache.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/utils/misc.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/utils/queue_utils.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/utils/repeat.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/utils/signal.py +0 -0
- {port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/version.py +0 -0
{port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/cli/cookiecutter/hooks/post_gen_project.py
RENAMED
|
@@ -2,11 +2,12 @@ import os
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
def handle_private_integration_flags():
|
|
5
|
+
print("{{ cookiecutter.is_private_integration }}")
|
|
5
6
|
if "{{ cookiecutter.is_private_integration }}" == "True":
|
|
7
|
+
os.remove("sonar-project.properties")
|
|
8
|
+
if "{{ cookiecutter.is_private_integration }}" == "False":
|
|
6
9
|
os.remove("Dockerfile")
|
|
7
10
|
os.remove(".dockerignore")
|
|
8
|
-
if "{{ cookiecutter.is_private_integration }}" == "False":
|
|
9
|
-
os.remove("sonar-project.properties")
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
if __name__ == "__main__":
|
|
@@ -29,7 +29,7 @@ class EntityClientMixin:
|
|
|
29
29
|
request_options: RequestOptions,
|
|
30
30
|
user_agent_type: UserAgentType | None = None,
|
|
31
31
|
should_raise: bool = True,
|
|
32
|
-
) ->
|
|
32
|
+
) -> Entity:
|
|
33
33
|
validation_only = request_options["validation_only"]
|
|
34
34
|
async with self.semaphore:
|
|
35
35
|
logger.debug(
|
|
@@ -57,6 +57,12 @@ class EntityClientMixin:
|
|
|
57
57
|
f"blueprint: {entity.blueprint}"
|
|
58
58
|
)
|
|
59
59
|
handle_status_code(response, should_raise)
|
|
60
|
+
result = response.json()
|
|
61
|
+
result_entity = Entity.parse_obj(result)
|
|
62
|
+
# Set the results of the search relation and identifier to the entity
|
|
63
|
+
entity.identifier = result_entity.identifier or entity.identifier
|
|
64
|
+
entity.relations = result_entity.relations or entity.relations
|
|
65
|
+
return entity
|
|
60
66
|
|
|
61
67
|
async def batch_upsert_entities(
|
|
62
68
|
self,
|
|
@@ -64,8 +70,8 @@ class EntityClientMixin:
|
|
|
64
70
|
request_options: RequestOptions,
|
|
65
71
|
user_agent_type: UserAgentType | None = None,
|
|
66
72
|
should_raise: bool = True,
|
|
67
|
-
) ->
|
|
68
|
-
await asyncio.gather(
|
|
73
|
+
) -> list[Entity]:
|
|
74
|
+
modified_entities_results = await asyncio.gather(
|
|
69
75
|
*(
|
|
70
76
|
self.upsert_entity(
|
|
71
77
|
entity,
|
|
@@ -75,8 +81,19 @@ class EntityClientMixin:
|
|
|
75
81
|
)
|
|
76
82
|
for entity in entities
|
|
77
83
|
),
|
|
78
|
-
return_exceptions=
|
|
84
|
+
return_exceptions=should_raise,
|
|
79
85
|
)
|
|
86
|
+
entity_results = [
|
|
87
|
+
entity for entity in modified_entities_results if isinstance(entity, Entity)
|
|
88
|
+
]
|
|
89
|
+
if not should_raise:
|
|
90
|
+
return entity_results
|
|
91
|
+
|
|
92
|
+
for entity_result in modified_entities_results:
|
|
93
|
+
if isinstance(entity_result, Exception):
|
|
94
|
+
raise entity_result
|
|
95
|
+
|
|
96
|
+
return entity_results
|
|
80
97
|
|
|
81
98
|
async def delete_entity(
|
|
82
99
|
self,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import re
|
|
3
|
-
from pathlib import Path
|
|
4
3
|
from types import GenericAlias
|
|
5
4
|
from typing import Any
|
|
6
5
|
|
|
7
6
|
import yaml
|
|
8
7
|
from humps import decamelize
|
|
8
|
+
from pathlib import Path
|
|
9
9
|
from pydantic import BaseSettings
|
|
10
10
|
from pydantic.env_settings import EnvSettingsSource, InitSettingsSource
|
|
11
11
|
from pydantic.main import ModelMetaclass, BaseModel
|
|
@@ -14,13 +14,17 @@ PROVIDER_WRAPPER_PATTERN = r"{{ from (.*) }}"
|
|
|
14
14
|
PROVIDER_CONFIG_PATTERN = r"^[a-zA-Z0-9]+ .*$"
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
def read_yaml_config_settings_source(
|
|
18
|
-
settings
|
|
19
|
-
) -> dict[str, Any]:
|
|
20
|
-
yaml_file = getattr(settings.__config__, "yaml_file", "")
|
|
17
|
+
def read_yaml_config_settings_source(settings: "BaseOceanSettings") -> dict[str, Any]:
|
|
18
|
+
yaml_file = getattr(settings.Config, "yaml_file", "")
|
|
21
19
|
|
|
22
20
|
assert yaml_file, "Settings.yaml_file not properly configured"
|
|
23
|
-
path = Path(
|
|
21
|
+
path = Path(
|
|
22
|
+
getattr(
|
|
23
|
+
settings,
|
|
24
|
+
"_base_path",
|
|
25
|
+
),
|
|
26
|
+
yaml_file,
|
|
27
|
+
)
|
|
24
28
|
|
|
25
29
|
if not path.exists():
|
|
26
30
|
return {}
|
|
@@ -119,15 +123,15 @@ def decamelize_config(
|
|
|
119
123
|
|
|
120
124
|
|
|
121
125
|
def load_providers(
|
|
122
|
-
settings: "BaseOceanSettings", existing_values: dict[str, Any]
|
|
126
|
+
settings: "BaseOceanSettings", existing_values: dict[str, Any]
|
|
123
127
|
) -> dict[str, Any]:
|
|
124
|
-
data = read_yaml_config_settings_source(settings
|
|
128
|
+
data = read_yaml_config_settings_source(settings)
|
|
125
129
|
snake_case_config = decamelize_config(settings, data)
|
|
126
130
|
return parse_providers(settings, snake_case_config, existing_values)
|
|
127
131
|
|
|
128
132
|
|
|
129
133
|
class BaseOceanSettings(BaseSettings):
|
|
130
|
-
|
|
134
|
+
_base_path: str = "./"
|
|
131
135
|
|
|
132
136
|
def get_sensitive_fields_data(self) -> set[str]:
|
|
133
137
|
return _get_sensitive_information(self)
|
|
@@ -150,9 +154,7 @@ class BaseOceanSettings(BaseSettings):
|
|
|
150
154
|
return (
|
|
151
155
|
init_settings,
|
|
152
156
|
env_settings,
|
|
153
|
-
lambda s: load_providers(
|
|
154
|
-
s, env_settings(s), init_settings.init_kwargs["base_path"]
|
|
155
|
-
),
|
|
157
|
+
lambda s: load_providers(s, {**env_settings(s), **init_settings(s)}),
|
|
156
158
|
)
|
|
157
159
|
|
|
158
160
|
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
from typing import Any, Literal
|
|
1
|
+
from typing import Any, Literal, Type
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
from port_ocean.core.event_listener import EventListenerSettingsType
|
|
5
|
-
from port_ocean.core.models import Runtime
|
|
6
|
-
from port_ocean.utils.misc import get_integration_name, get_spec_file
|
|
7
|
-
from pydantic import Extra, AnyHttpUrl, parse_obj_as
|
|
3
|
+
from pydantic import Extra, AnyHttpUrl, parse_obj_as, parse_raw_as
|
|
8
4
|
from pydantic.class_validators import root_validator, validator
|
|
9
5
|
from pydantic.env_settings import InitSettingsSource, EnvSettingsSource, BaseSettings
|
|
10
6
|
from pydantic.fields import Field
|
|
11
7
|
from pydantic.main import BaseModel
|
|
12
8
|
|
|
9
|
+
from port_ocean.config.base import BaseOceanSettings, BaseOceanModel
|
|
10
|
+
from port_ocean.core.event_listener import EventListenerSettingsType
|
|
11
|
+
from port_ocean.core.models import Runtime
|
|
12
|
+
from port_ocean.utils.misc import get_integration_name, get_spec_file
|
|
13
|
+
|
|
13
14
|
LogLevelType = Literal["ERROR", "WARNING", "INFO", "DEBUG", "CRITICAL"]
|
|
14
15
|
|
|
15
16
|
|
|
@@ -44,7 +45,7 @@ class PortSettings(BaseOceanModel, extra=Extra.allow):
|
|
|
44
45
|
class IntegrationSettings(BaseOceanModel, extra=Extra.allow):
|
|
45
46
|
identifier: str
|
|
46
47
|
type: str
|
|
47
|
-
config:
|
|
48
|
+
config: Any = Field(default_factory=dict)
|
|
48
49
|
|
|
49
50
|
@root_validator(pre=True)
|
|
50
51
|
def root_validator(cls, values: dict[str, Any]) -> dict[str, Any]:
|
|
@@ -62,6 +63,8 @@ class IntegrationSettings(BaseOceanModel, extra=Extra.allow):
|
|
|
62
63
|
|
|
63
64
|
|
|
64
65
|
class IntegrationConfiguration(BaseOceanSettings, extra=Extra.allow):
|
|
66
|
+
_integration_config_model: BaseModel | None = None
|
|
67
|
+
|
|
65
68
|
allow_environment_variables_jq_access: bool = True
|
|
66
69
|
initialize_port_resources: bool = True
|
|
67
70
|
scheduled_resync_interval: int | None = None
|
|
@@ -73,6 +76,27 @@ class IntegrationConfiguration(BaseOceanSettings, extra=Extra.allow):
|
|
|
73
76
|
integration: IntegrationSettings = IntegrationSettings(type="", identifier="")
|
|
74
77
|
runtime: Runtime = "OnPrem"
|
|
75
78
|
|
|
79
|
+
@root_validator()
|
|
80
|
+
def validate_integration_config(cls, values: dict[str, Any]) -> dict[str, Any]:
|
|
81
|
+
if not (config_model := values.get("_integration_config_model")):
|
|
82
|
+
return values
|
|
83
|
+
|
|
84
|
+
# Using the integration dynamic config model to parse the config
|
|
85
|
+
def parse_config(model: Type[BaseModel], config: Any) -> BaseModel:
|
|
86
|
+
# In some cases, the config is parsed as a string so we need to handle it
|
|
87
|
+
# Example: when the config is loaded from the environment variables and there is an object inside the config
|
|
88
|
+
if isinstance(config, str):
|
|
89
|
+
return parse_raw_as(model, config)
|
|
90
|
+
else:
|
|
91
|
+
return parse_obj_as(model, config)
|
|
92
|
+
|
|
93
|
+
integration_config = values["integration"]
|
|
94
|
+
integration_config.config = parse_config(
|
|
95
|
+
config_model, integration_config.config
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
return values
|
|
99
|
+
|
|
76
100
|
@validator("runtime")
|
|
77
101
|
def validate_runtime(cls, runtime: Literal["OnPrem", "Saas"]) -> Runtime:
|
|
78
102
|
if runtime == "Saas":
|
{port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/handlers/entities_state_applier/base.py
RENAMED
|
@@ -47,12 +47,15 @@ class BaseEntitiesStateApplier(BaseHandler):
|
|
|
47
47
|
@abstractmethod
|
|
48
48
|
async def upsert(
|
|
49
49
|
self, entities: list[Entity], user_agent_type: UserAgentType
|
|
50
|
-
) ->
|
|
50
|
+
) -> list[Entity]:
|
|
51
51
|
"""Upsert (insert or update) the given entities into the state.
|
|
52
52
|
|
|
53
53
|
Args:
|
|
54
54
|
entities (list[Entity]): The entities to be upserted.
|
|
55
55
|
user_agent_type (UserAgentType): The user agent responsible for the upsert.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
list[Entity]: The upserted entities.
|
|
56
59
|
"""
|
|
57
60
|
pass
|
|
58
61
|
|
|
@@ -71,9 +71,9 @@ class HttpEntitiesStateApplier(BaseEntitiesStateApplier):
|
|
|
71
71
|
logger.info(
|
|
72
72
|
f"Updating entity diff (created: {len(diff.created)}, deleted: {len(diff.deleted)}, modified: {len(diff.modified)})"
|
|
73
73
|
)
|
|
74
|
-
await self.upsert(kept_entities, user_agent_type)
|
|
74
|
+
modified_entities = await self.upsert(kept_entities, user_agent_type)
|
|
75
75
|
|
|
76
|
-
await self._safe_delete(diff.deleted,
|
|
76
|
+
await self._safe_delete(diff.deleted, modified_entities, user_agent_type)
|
|
77
77
|
|
|
78
78
|
async def delete_diff(
|
|
79
79
|
self,
|
|
@@ -95,10 +95,11 @@ class HttpEntitiesStateApplier(BaseEntitiesStateApplier):
|
|
|
95
95
|
|
|
96
96
|
async def upsert(
|
|
97
97
|
self, entities: list[Entity], user_agent_type: UserAgentType
|
|
98
|
-
) ->
|
|
98
|
+
) -> list[Entity]:
|
|
99
99
|
logger.info(f"Upserting {len(entities)} entities")
|
|
100
|
+
modified_entities: list[Entity] = []
|
|
100
101
|
if event.port_app_config.create_missing_related_entities:
|
|
101
|
-
await self.context.port_client.batch_upsert_entities(
|
|
102
|
+
modified_entities = await self.context.port_client.batch_upsert_entities(
|
|
102
103
|
entities,
|
|
103
104
|
event.port_app_config.get_port_request_options(),
|
|
104
105
|
user_agent_type,
|
|
@@ -108,14 +109,16 @@ class HttpEntitiesStateApplier(BaseEntitiesStateApplier):
|
|
|
108
109
|
ordered_created_entities = reversed(
|
|
109
110
|
order_by_entities_dependencies(entities)
|
|
110
111
|
)
|
|
111
|
-
|
|
112
112
|
for entity in ordered_created_entities:
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
113
|
+
modified_entities.append(
|
|
114
|
+
await self.context.port_client.upsert_entity(
|
|
115
|
+
entity,
|
|
116
|
+
event.port_app_config.get_port_request_options(),
|
|
117
|
+
user_agent_type,
|
|
118
|
+
should_raise=False,
|
|
119
|
+
)
|
|
118
120
|
)
|
|
121
|
+
return modified_entities
|
|
119
122
|
|
|
120
123
|
async def delete(
|
|
121
124
|
self, entities: list[Entity], user_agent_type: UserAgentType
|
|
@@ -97,9 +97,11 @@ class SyncMixin(HandlerMixin):
|
|
|
97
97
|
"""
|
|
98
98
|
entities_at_port = await ocean.port_client.search_entities(user_agent_type)
|
|
99
99
|
|
|
100
|
-
await self.entities_state_applier.upsert(
|
|
100
|
+
modified_entities = await self.entities_state_applier.upsert(
|
|
101
|
+
entities, user_agent_type
|
|
102
|
+
)
|
|
101
103
|
await self.entities_state_applier.delete_diff(
|
|
102
|
-
{"before": entities_at_port, "after":
|
|
104
|
+
{"before": entities_at_port, "after": modified_entities}, user_agent_type
|
|
103
105
|
)
|
|
104
106
|
|
|
105
107
|
logger.info("Finished syncing change")
|
|
@@ -140,11 +140,13 @@ class SyncRawMixin(HandlerMixin, EventsMixin):
|
|
|
140
140
|
objects_diff = await self._calculate_raw(
|
|
141
141
|
[(resource, results)], parse_all, send_raw_data_examples_amount
|
|
142
142
|
)
|
|
143
|
-
await self.entities_state_applier.upsert(
|
|
143
|
+
modified_objects = await self.entities_state_applier.upsert(
|
|
144
144
|
objects_diff[0].entity_selector_diff.passed, user_agent_type
|
|
145
145
|
)
|
|
146
|
-
|
|
147
|
-
|
|
146
|
+
return CalculationResult(
|
|
147
|
+
objects_diff[0].entity_selector_diff._replace(passed=modified_objects),
|
|
148
|
+
errors=objects_diff[0].errors,
|
|
149
|
+
)
|
|
148
150
|
|
|
149
151
|
async def _unregister_resource_raw(
|
|
150
152
|
self,
|
|
@@ -418,6 +420,7 @@ class SyncRawMixin(HandlerMixin, EventsMixin):
|
|
|
418
420
|
)
|
|
419
421
|
logger.info(f"Resync will use the following mappings: {app_config.dict()}")
|
|
420
422
|
try:
|
|
423
|
+
did_fetched_current_state = True
|
|
421
424
|
entities_at_port = await ocean.port_client.search_entities(
|
|
422
425
|
user_agent_type
|
|
423
426
|
)
|
|
@@ -429,7 +432,7 @@ class SyncRawMixin(HandlerMixin, EventsMixin):
|
|
|
429
432
|
f"Response status code: {e.response.status_code if isinstance(e, httpx.HTTPStatusError) else None}\n"
|
|
430
433
|
f"Response content: {e.response.text if isinstance(e, httpx.HTTPStatusError) else None}\n"
|
|
431
434
|
)
|
|
432
|
-
|
|
435
|
+
did_fetched_current_state = False
|
|
433
436
|
|
|
434
437
|
creation_results: list[tuple[list[Entity], list[Exception]]] = []
|
|
435
438
|
|
|
@@ -448,7 +451,7 @@ class SyncRawMixin(HandlerMixin, EventsMixin):
|
|
|
448
451
|
except asyncio.CancelledError as e:
|
|
449
452
|
logger.warning("Resync aborted successfully")
|
|
450
453
|
else:
|
|
451
|
-
if not
|
|
454
|
+
if not did_fetched_current_state:
|
|
452
455
|
logger.warning(
|
|
453
456
|
"Due to an error before the resync, the previous state of entities at Port is unknown."
|
|
454
457
|
" Skipping delete phase due to unknown initial state."
|
|
@@ -2,7 +2,7 @@ import asyncio
|
|
|
2
2
|
import sys
|
|
3
3
|
import threading
|
|
4
4
|
from contextlib import asynccontextmanager
|
|
5
|
-
from typing import Callable, Any, Dict, AsyncIterator
|
|
5
|
+
from typing import Callable, Any, Dict, AsyncIterator, Type
|
|
6
6
|
|
|
7
7
|
from fastapi import FastAPI, APIRouter
|
|
8
8
|
from loguru import logger
|
|
@@ -32,7 +32,7 @@ class Ocean:
|
|
|
32
32
|
app: FastAPI | None = None,
|
|
33
33
|
integration_class: Callable[[PortOceanContext], BaseIntegration] | None = None,
|
|
34
34
|
integration_router: APIRouter | None = None,
|
|
35
|
-
config_factory:
|
|
35
|
+
config_factory: Type[BaseModel] | None = None,
|
|
36
36
|
config_override: Dict[str, Any] | None = None,
|
|
37
37
|
):
|
|
38
38
|
initialize_port_ocean_context(self)
|
|
@@ -40,16 +40,11 @@ class Ocean:
|
|
|
40
40
|
self.fast_api_app.middleware("http")(request_handler)
|
|
41
41
|
|
|
42
42
|
self.config = IntegrationConfiguration(
|
|
43
|
-
|
|
43
|
+
# type: ignore
|
|
44
|
+
_integration_config_model=config_factory,
|
|
45
|
+
**(config_override or {}),
|
|
44
46
|
)
|
|
45
47
|
|
|
46
|
-
if config_factory:
|
|
47
|
-
raw_config = (
|
|
48
|
-
self.config.integration.config
|
|
49
|
-
if isinstance(self.config.integration.config, dict)
|
|
50
|
-
else self.config.integration.config.dict()
|
|
51
|
-
)
|
|
52
|
-
self.config.integration.config = config_factory(**raw_config)
|
|
53
48
|
# add the integration sensitive configuration to the sensitive patterns to mask out
|
|
54
49
|
sensitive_log_filter.hide_sensitive_strings(
|
|
55
50
|
*self.config.get_sensitive_fields_data()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/handlers/entities_state_applier/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{port_ocean-0.9.8 → port_ocean-0.9.12}/port_ocean/core/handlers/entity_processor/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|