port-ocean 0.5.10__tar.gz → 0.5.13__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.5.10 → port_ocean-0.5.13}/PKG-INFO +4 -3
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/clients/port/authentication.py +3 -1
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/clients/port/mixins/entities.py +33 -50
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/clients/port/retry_transport.py +0 -5
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/handlers/entities_state_applier/port/applier.py +13 -75
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/handlers/entity_processor/base.py +17 -7
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/handlers/entity_processor/jq_entity_processor.py +42 -41
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/integrations/mixins/sync_raw.py +56 -41
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/ocean_types.py +10 -2
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/helpers/retry.py +49 -4
- port_ocean-0.5.13/port_ocean/utils/async_iterators.py +49 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/pyproject.toml +5 -4
- port_ocean-0.5.10/port_ocean/core/handlers/entities_state_applier/port/validate_entity_relations.py +0 -40
- {port_ocean-0.5.10 → port_ocean-0.5.13}/LICENSE.md +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/README.md +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/bootstrap.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/cli.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/commands/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/commands/defaults/__init___.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/commands/defaults/clean.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/commands/defaults/dock.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/commands/defaults/group.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/commands/list_integrations.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/commands/main.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/commands/new.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/commands/pull.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/commands/sail.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/commands/version.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/cookiecutter/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/cookiecutter/cookiecutter.json +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/cookiecutter/extensions.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/cookiecutter/hooks/post_gen_project.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.dockerignore +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.gitignore +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/.gitignore +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/spec.yaml +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/CHANGELOG.md +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/Dockerfile +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/Makefile +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/README.md +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/changelog/.gitignore +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/config.yaml +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/debug.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/main.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/poetry.toml +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/pyproject.toml +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/sonar-project.properties +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/tests/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/cli/utils.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/clients/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/clients/port/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/clients/port/client.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/clients/port/mixins/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/clients/port/mixins/blueprints.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/clients/port/mixins/integrations.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/clients/port/mixins/migrations.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/clients/port/types.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/clients/port/utils.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/config/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/config/base.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/config/dynamic.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/config/settings.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/consumers/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/consumers/kafka_consumer.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/context/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/context/event.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/context/ocean.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/context/resource.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/defaults/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/defaults/clean.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/defaults/common.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/defaults/initialize.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/event_listener/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/event_listener/base.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/event_listener/factory.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/event_listener/http.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/event_listener/kafka.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/event_listener/once.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/event_listener/polling.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/handlers/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/handlers/base.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/handlers/entities_state_applier/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/handlers/entities_state_applier/base.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/handlers/entities_state_applier/port/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/handlers/entities_state_applier/port/get_related_entities.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/handlers/entities_state_applier/port/order_by_entities_dependencies.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/handlers/entity_processor/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/handlers/port_app_config/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/handlers/port_app_config/api.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/handlers/port_app_config/base.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/handlers/port_app_config/models.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/integrations/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/integrations/base.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/integrations/mixins/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/integrations/mixins/events.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/integrations/mixins/handler.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/integrations/mixins/sync.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/integrations/mixins/utils.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/models.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/core/utils.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/exceptions/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/exceptions/api.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/exceptions/base.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/exceptions/clients.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/exceptions/context.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/exceptions/core.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/exceptions/port_defaults.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/exceptions/utils.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/helpers/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/helpers/async_client.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/log/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/log/handlers.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/log/logger_setup.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/log/sensetive.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/middlewares.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/ocean.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/py.typed +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/run.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/sonar-project.properties +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/utils/__init__.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/utils/async_http.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/utils/cache.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/utils/misc.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/utils/repeat.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/utils/signal.py +0 -0
- {port_ocean-0.5.10 → port_ocean-0.5.13}/port_ocean/version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: port-ocean
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.13
|
|
4
4
|
Summary: Port Ocean is a CLI tool for managing your Port projects.
|
|
5
5
|
Home-page: https://app.getport.io
|
|
6
6
|
Keywords: ocean,port-ocean,port
|
|
@@ -21,11 +21,12 @@ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
|
21
21
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
22
|
Classifier: Topic :: Utilities
|
|
23
23
|
Provides-Extra: cli
|
|
24
|
+
Requires-Dist: aiostream (>=0.5.2,<0.6.0)
|
|
24
25
|
Requires-Dist: click (>=8.1.3,<9.0.0) ; extra == "cli"
|
|
25
26
|
Requires-Dist: confluent-kafka (>=2.1.1,<3.0.0)
|
|
26
27
|
Requires-Dist: cookiecutter (>=2.1.1,<3.0.0) ; extra == "cli"
|
|
27
28
|
Requires-Dist: fastapi (>=0.100,<0.110)
|
|
28
|
-
Requires-Dist: httpx (>=0.24.1,<0.
|
|
29
|
+
Requires-Dist: httpx (>=0.24.1,<0.28.0)
|
|
29
30
|
Requires-Dist: jinja2-time (>=0.2.0,<0.3.0) ; extra == "cli"
|
|
30
31
|
Requires-Dist: loguru (>=0.7.0,<0.8.0)
|
|
31
32
|
Requires-Dist: pydantic (>=1.10.8,<2.0.0)
|
|
@@ -37,7 +38,7 @@ Requires-Dist: rich (>=13.4.1,<14.0.0) ; extra == "cli"
|
|
|
37
38
|
Requires-Dist: six (>=1.16.0,<2.0.0)
|
|
38
39
|
Requires-Dist: tomli (>=2.0.1,<3.0.0)
|
|
39
40
|
Requires-Dist: urllib3 (>=1.26.16,<2.0.0)
|
|
40
|
-
Requires-Dist: uvicorn (>=0.22
|
|
41
|
+
Requires-Dist: uvicorn (>=0.22,<0.30)
|
|
41
42
|
Requires-Dist: werkzeug (>=2.3.4,<4.0.0)
|
|
42
43
|
Project-URL: Repository, https://github.com/port-labs/Port-Ocean
|
|
43
44
|
Description-Content-Type: text/markdown
|
|
@@ -49,7 +49,9 @@ class PortAuthentication:
|
|
|
49
49
|
|
|
50
50
|
credentials = {"clientId": client_id, "clientSecret": client_secret}
|
|
51
51
|
response = await self.client.post(
|
|
52
|
-
f"{self.api_url}/auth/access_token",
|
|
52
|
+
f"{self.api_url}/auth/access_token",
|
|
53
|
+
json=credentials,
|
|
54
|
+
extensions={"retryable": True},
|
|
53
55
|
)
|
|
54
56
|
handle_status_code(response)
|
|
55
57
|
return TokenResponse(**response.json())
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
from typing import Any
|
|
2
3
|
from urllib.parse import quote_plus
|
|
3
4
|
|
|
4
5
|
import httpx
|
|
@@ -133,23 +134,10 @@ class EntityClientMixin:
|
|
|
133
134
|
return_exceptions=True,
|
|
134
135
|
)
|
|
135
136
|
|
|
136
|
-
async def
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
f"{self.auth.api_url}/blueprints/{blueprint}/entities/{identifier}",
|
|
141
|
-
headers=await self.auth.headers(),
|
|
142
|
-
)
|
|
143
|
-
if response.is_error:
|
|
144
|
-
logger.error(
|
|
145
|
-
f"Error validating "
|
|
146
|
-
f"entity: {identifier} of "
|
|
147
|
-
f"blueprint: {blueprint}"
|
|
148
|
-
)
|
|
149
|
-
handle_status_code(response)
|
|
150
|
-
|
|
151
|
-
async def search_entities(self, user_agent_type: UserAgentType) -> list[Entity]:
|
|
152
|
-
query = {
|
|
137
|
+
async def search_entities(
|
|
138
|
+
self, user_agent_type: UserAgentType, query: dict[Any, Any] | None = None
|
|
139
|
+
) -> list[Entity]:
|
|
140
|
+
default_query = {
|
|
153
141
|
"combinator": "and",
|
|
154
142
|
"rules": [
|
|
155
143
|
{
|
|
@@ -165,6 +153,11 @@ class EntityClientMixin:
|
|
|
165
153
|
],
|
|
166
154
|
}
|
|
167
155
|
|
|
156
|
+
if query is None:
|
|
157
|
+
query = default_query
|
|
158
|
+
elif query.get("rules"):
|
|
159
|
+
query["rules"].append(default_query)
|
|
160
|
+
|
|
168
161
|
logger.info(f"Searching entities with query {query}")
|
|
169
162
|
response = await self.client.post(
|
|
170
163
|
f"{self.auth.api_url}/entities/search",
|
|
@@ -174,43 +167,33 @@ class EntityClientMixin:
|
|
|
174
167
|
"exclude_calculated_properties": "true",
|
|
175
168
|
"include": ["blueprint", "identifier"],
|
|
176
169
|
},
|
|
170
|
+
extensions={"retryable": True},
|
|
171
|
+
timeout=30,
|
|
177
172
|
)
|
|
178
173
|
handle_status_code(response)
|
|
179
174
|
return [Entity.parse_obj(result) for result in response.json()["entities"]]
|
|
180
175
|
|
|
181
|
-
async def
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
"blueprint": entity.blueprint,
|
|
188
|
-
"value": entity.identifier,
|
|
189
|
-
"direction": "downstream",
|
|
190
|
-
}
|
|
191
|
-
],
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
logger.info(f"Searching dependent entity with body {body}")
|
|
195
|
-
response = await self.client.post(
|
|
196
|
-
f"{self.auth.api_url}/entities/search",
|
|
197
|
-
headers=await self.auth.headers(),
|
|
198
|
-
json=body,
|
|
199
|
-
)
|
|
200
|
-
handle_status_code(response)
|
|
201
|
-
|
|
202
|
-
return [Entity.parse_obj(result) for result in response.json()["entities"]]
|
|
203
|
-
|
|
204
|
-
async def validate_entity_payload(
|
|
205
|
-
self, entity: Entity, merge: bool, create_missing_related_entities: bool
|
|
206
|
-
) -> None:
|
|
207
|
-
logger.info(f"Validating entity {entity.identifier}")
|
|
208
|
-
await self.upsert_entity(
|
|
209
|
-
entity,
|
|
176
|
+
async def does_integration_has_ownership_over_entity(
|
|
177
|
+
self, entity: Entity, user_agent_type: UserAgentType
|
|
178
|
+
) -> bool:
|
|
179
|
+
logger.info(f"Validating ownership on entity {entity.identifier}")
|
|
180
|
+
found_entities: list[Entity] = await self.search_entities(
|
|
181
|
+
user_agent_type,
|
|
210
182
|
{
|
|
211
|
-
"
|
|
212
|
-
"
|
|
213
|
-
|
|
214
|
-
|
|
183
|
+
"combinator": "and",
|
|
184
|
+
"rules": [
|
|
185
|
+
{
|
|
186
|
+
"property": "$identifier",
|
|
187
|
+
"operator": "contains",
|
|
188
|
+
"value": entity.identifier,
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
"property": "$blueprint",
|
|
192
|
+
"operator": "contains",
|
|
193
|
+
"value": entity.blueprint,
|
|
194
|
+
},
|
|
195
|
+
],
|
|
215
196
|
},
|
|
216
197
|
)
|
|
198
|
+
|
|
199
|
+
return len(found_entities) > 0
|
|
@@ -15,11 +15,6 @@ class TokenRetryTransport(RetryTransport):
|
|
|
15
15
|
super().__init__(**kwargs)
|
|
16
16
|
self.port_client = port_client
|
|
17
17
|
|
|
18
|
-
def _is_retryable_method(self, request: httpx.Request) -> bool:
|
|
19
|
-
return super()._is_retryable_method(request) or request.url.path.endswith(
|
|
20
|
-
"/auth/access_token"
|
|
21
|
-
)
|
|
22
|
-
|
|
23
18
|
async def _handle_unauthorized(self, response: httpx.Response) -> None:
|
|
24
19
|
token = await self.port_client.auth.token
|
|
25
20
|
response.headers["Authorization"] = f"Bearer {token}"
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
from itertools import chain
|
|
3
|
-
|
|
4
1
|
from loguru import logger
|
|
5
2
|
|
|
6
3
|
from port_ocean.clients.port.types import UserAgentType
|
|
@@ -14,14 +11,9 @@ from port_ocean.core.handlers.entities_state_applier.port.get_related_entities i
|
|
|
14
11
|
from port_ocean.core.handlers.entities_state_applier.port.order_by_entities_dependencies import (
|
|
15
12
|
order_by_entities_dependencies,
|
|
16
13
|
)
|
|
17
|
-
from port_ocean.core.handlers.entities_state_applier.port.validate_entity_relations import (
|
|
18
|
-
validate_entity_relations,
|
|
19
|
-
)
|
|
20
|
-
from port_ocean.core.handlers.entity_processor.base import EntityPortDiff
|
|
21
14
|
from port_ocean.core.models import Entity
|
|
22
15
|
from port_ocean.core.ocean_types import EntityDiff
|
|
23
|
-
from port_ocean.core.utils import is_same_entity,
|
|
24
|
-
from port_ocean.exceptions.core import RelationValidationException
|
|
16
|
+
from port_ocean.core.utils import is_same_entity, get_port_diff
|
|
25
17
|
|
|
26
18
|
|
|
27
19
|
class HttpEntitiesStateApplier(BaseEntitiesStateApplier):
|
|
@@ -32,63 +24,17 @@ class HttpEntitiesStateApplier(BaseEntitiesStateApplier):
|
|
|
32
24
|
through HTTP requests.
|
|
33
25
|
"""
|
|
34
26
|
|
|
35
|
-
async def
|
|
36
|
-
logger.info("Validated deleted entities")
|
|
37
|
-
if not event.port_app_config.delete_dependent_entities:
|
|
38
|
-
dependent_entities = await asyncio.gather(
|
|
39
|
-
*(
|
|
40
|
-
self.context.port_client.search_dependent_entities(entity)
|
|
41
|
-
for entity in entities
|
|
42
|
-
)
|
|
43
|
-
)
|
|
44
|
-
new_dependent_entities = get_unique(
|
|
45
|
-
[
|
|
46
|
-
entity
|
|
47
|
-
for entity in chain.from_iterable(dependent_entities)
|
|
48
|
-
if not any(is_same_entity(item, entity) for item in entities)
|
|
49
|
-
]
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
if new_dependent_entities:
|
|
53
|
-
raise RelationValidationException(
|
|
54
|
-
f"Must enable delete_dependent_entities flag or delete all dependent entities: "
|
|
55
|
-
f" {[(dep.blueprint, dep.identifier) for dep in new_dependent_entities]}"
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
async def _validate_entity_diff(self, diff: EntityPortDiff) -> None:
|
|
59
|
-
config = event.port_app_config
|
|
60
|
-
await self._validate_delete_dependent_entities(diff.deleted)
|
|
61
|
-
modified_or_created_entities = diff.modified + diff.created
|
|
62
|
-
|
|
63
|
-
if modified_or_created_entities and not config.create_missing_related_entities:
|
|
64
|
-
logger.info("Validating modified or created entities")
|
|
65
|
-
|
|
66
|
-
await asyncio.gather(
|
|
67
|
-
*(
|
|
68
|
-
self.context.port_client.validate_entity_payload(
|
|
69
|
-
entity,
|
|
70
|
-
config.enable_merge_entity,
|
|
71
|
-
create_missing_related_entities=config.create_missing_related_entities,
|
|
72
|
-
)
|
|
73
|
-
for entity in modified_or_created_entities
|
|
74
|
-
)
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
if not event.port_app_config.delete_dependent_entities:
|
|
78
|
-
logger.info("Validating no relation blocks the operation")
|
|
79
|
-
await validate_entity_relations(diff, self.context.port_client)
|
|
80
|
-
|
|
81
|
-
async def _delete_diff(
|
|
27
|
+
async def _safe_delete(
|
|
82
28
|
self,
|
|
83
29
|
entities_to_delete: list[Entity],
|
|
84
|
-
|
|
30
|
+
entities_to_protect: list[Entity],
|
|
85
31
|
user_agent_type: UserAgentType,
|
|
86
32
|
) -> None:
|
|
87
33
|
if not entities_to_delete:
|
|
88
34
|
return
|
|
89
35
|
|
|
90
36
|
related_entities = await get_related_entities(
|
|
91
|
-
|
|
37
|
+
entities_to_protect, self.context.port_client
|
|
92
38
|
)
|
|
93
39
|
|
|
94
40
|
allowed_entities_to_delete = []
|
|
@@ -98,7 +44,8 @@ class HttpEntitiesStateApplier(BaseEntitiesStateApplier):
|
|
|
98
44
|
is_same_entity(entity, entity_to_delete) for entity in related_entities
|
|
99
45
|
)
|
|
100
46
|
is_part_of_created = any(
|
|
101
|
-
is_same_entity(entity, entity_to_delete)
|
|
47
|
+
is_same_entity(entity, entity_to_delete)
|
|
48
|
+
for entity in entities_to_protect
|
|
102
49
|
)
|
|
103
50
|
if is_part_of_related:
|
|
104
51
|
if event.port_app_config.create_missing_related_entities:
|
|
@@ -119,21 +66,14 @@ class HttpEntitiesStateApplier(BaseEntitiesStateApplier):
|
|
|
119
66
|
user_agent_type: UserAgentType,
|
|
120
67
|
) -> None:
|
|
121
68
|
diff = get_port_diff(entities["before"], entities["after"])
|
|
69
|
+
kept_entities = diff.created + diff.modified
|
|
122
70
|
|
|
123
71
|
logger.info(
|
|
124
72
|
f"Updating entity diff (created: {len(diff.created)}, deleted: {len(diff.deleted)}, modified: {len(diff.modified)})"
|
|
125
73
|
)
|
|
126
|
-
await self.
|
|
74
|
+
await self.upsert(kept_entities, user_agent_type)
|
|
127
75
|
|
|
128
|
-
|
|
129
|
-
await self.upsert(diff.created, user_agent_type)
|
|
130
|
-
logger.info("Upserting modified entities")
|
|
131
|
-
await self.upsert(diff.modified, user_agent_type)
|
|
132
|
-
|
|
133
|
-
logger.info("Deleting diff entities")
|
|
134
|
-
await self._delete_diff(
|
|
135
|
-
diff.deleted, diff.created + diff.modified, user_agent_type
|
|
136
|
-
)
|
|
76
|
+
await self._safe_delete(diff.deleted, kept_entities, user_agent_type)
|
|
137
77
|
|
|
138
78
|
async def delete_diff(
|
|
139
79
|
self,
|
|
@@ -145,15 +85,13 @@ class HttpEntitiesStateApplier(BaseEntitiesStateApplier):
|
|
|
145
85
|
if not diff.deleted:
|
|
146
86
|
return
|
|
147
87
|
|
|
88
|
+
kept_entities = diff.created + diff.modified
|
|
89
|
+
|
|
148
90
|
logger.info(
|
|
149
|
-
f"
|
|
91
|
+
f"Determining entities to delete ({len(diff.deleted)}/{len(kept_entities)})"
|
|
150
92
|
)
|
|
151
|
-
await self._validate_entity_diff(diff)
|
|
152
93
|
|
|
153
|
-
|
|
154
|
-
await self._delete_diff(
|
|
155
|
-
diff.deleted, diff.created + diff.modified, user_agent_type
|
|
156
|
-
)
|
|
94
|
+
await self._safe_delete(diff.deleted, kept_entities, user_agent_type)
|
|
157
95
|
|
|
158
96
|
async def upsert(
|
|
159
97
|
self, entities: list[Entity], user_agent_type: UserAgentType
|
|
@@ -6,7 +6,10 @@ from loguru import logger
|
|
|
6
6
|
from port_ocean.core.handlers.base import BaseHandler
|
|
7
7
|
from port_ocean.core.handlers.port_app_config.models import ResourceConfig
|
|
8
8
|
from port_ocean.core.models import Entity
|
|
9
|
-
from port_ocean.core.ocean_types import
|
|
9
|
+
from port_ocean.core.ocean_types import (
|
|
10
|
+
RawEntity,
|
|
11
|
+
EntitySelectorDiff,
|
|
12
|
+
)
|
|
10
13
|
|
|
11
14
|
|
|
12
15
|
@dataclass
|
|
@@ -33,21 +36,28 @@ class BaseEntityProcessor(BaseHandler):
|
|
|
33
36
|
|
|
34
37
|
@abstractmethod
|
|
35
38
|
async def _parse_items(
|
|
36
|
-
self,
|
|
37
|
-
|
|
39
|
+
self,
|
|
40
|
+
mapping: ResourceConfig,
|
|
41
|
+
raw_data: list[RawEntity],
|
|
42
|
+
parse_all: bool = False,
|
|
43
|
+
) -> EntitySelectorDiff:
|
|
38
44
|
pass
|
|
39
45
|
|
|
40
46
|
async def parse_items(
|
|
41
|
-
self,
|
|
42
|
-
|
|
47
|
+
self,
|
|
48
|
+
mapping: ResourceConfig,
|
|
49
|
+
raw_data: list[RawEntity],
|
|
50
|
+
parse_all: bool = False,
|
|
51
|
+
) -> EntitySelectorDiff:
|
|
43
52
|
"""Public method to parse raw entity data and map it to an EntityDiff.
|
|
44
53
|
|
|
45
54
|
Args:
|
|
46
55
|
mapping (ResourceConfig): The configuration for entity mapping.
|
|
47
|
-
raw_data (
|
|
56
|
+
raw_data (list[RawEntity]): The raw data to be parsed.
|
|
57
|
+
parse_all (bool): Whether to parse all data or just data that passed the selector.
|
|
48
58
|
|
|
49
59
|
Returns:
|
|
50
60
|
EntityDiff: The parsed entity differences.
|
|
51
61
|
"""
|
|
52
62
|
with logger.contextualize(kind=mapping.kind):
|
|
53
|
-
return await self._parse_items(mapping, raw_data)
|
|
63
|
+
return await self._parse_items(mapping, raw_data, parse_all)
|
|
@@ -9,7 +9,10 @@ import pyjq as jq # type: ignore
|
|
|
9
9
|
from port_ocean.core.handlers.entity_processor.base import BaseEntityProcessor
|
|
10
10
|
from port_ocean.core.handlers.port_app_config.models import ResourceConfig
|
|
11
11
|
from port_ocean.core.models import Entity
|
|
12
|
-
from port_ocean.core.ocean_types import
|
|
12
|
+
from port_ocean.core.ocean_types import (
|
|
13
|
+
RawEntity,
|
|
14
|
+
EntitySelectorDiff,
|
|
15
|
+
)
|
|
13
16
|
from port_ocean.exceptions.core import EntityProcessorException
|
|
14
17
|
|
|
15
18
|
|
|
@@ -68,16 +71,19 @@ class JQEntityProcessor(BaseEntityProcessor):
|
|
|
68
71
|
|
|
69
72
|
return result
|
|
70
73
|
|
|
71
|
-
async def
|
|
74
|
+
async def _get_mapped_entity(
|
|
72
75
|
self,
|
|
73
76
|
data: dict[str, Any],
|
|
74
77
|
raw_entity_mappings: dict[str, Any],
|
|
75
78
|
selector_query: str,
|
|
76
|
-
|
|
79
|
+
parse_all: bool = False,
|
|
80
|
+
) -> tuple[dict[str, Any], bool]:
|
|
77
81
|
should_run = await self._search_as_bool(data, selector_query)
|
|
78
|
-
if should_run:
|
|
79
|
-
|
|
80
|
-
|
|
82
|
+
if parse_all or should_run:
|
|
83
|
+
mapped_entity = await self._search_as_object(data, raw_entity_mappings)
|
|
84
|
+
return mapped_entity, should_run
|
|
85
|
+
|
|
86
|
+
return {}, False
|
|
81
87
|
|
|
82
88
|
async def _calculate_entity(
|
|
83
89
|
self,
|
|
@@ -85,16 +91,18 @@ class JQEntityProcessor(BaseEntityProcessor):
|
|
|
85
91
|
raw_entity_mappings: dict[str, Any],
|
|
86
92
|
items_to_parse: str | None,
|
|
87
93
|
selector_query: str,
|
|
88
|
-
|
|
94
|
+
parse_all: bool = False,
|
|
95
|
+
) -> list[tuple[dict[str, Any], bool]]:
|
|
89
96
|
if items_to_parse:
|
|
90
97
|
items = await self._search(data, items_to_parse)
|
|
91
98
|
if isinstance(items, list):
|
|
92
99
|
return await asyncio.gather(
|
|
93
100
|
*[
|
|
94
|
-
self.
|
|
101
|
+
self._get_mapped_entity(
|
|
95
102
|
{"item": item, **data},
|
|
96
103
|
raw_entity_mappings,
|
|
97
104
|
selector_query,
|
|
105
|
+
parse_all,
|
|
98
106
|
)
|
|
99
107
|
for item in items
|
|
100
108
|
]
|
|
@@ -105,51 +113,44 @@ class JQEntityProcessor(BaseEntityProcessor):
|
|
|
105
113
|
)
|
|
106
114
|
else:
|
|
107
115
|
return [
|
|
108
|
-
await self.
|
|
109
|
-
data, raw_entity_mappings, selector_query
|
|
116
|
+
await self._get_mapped_entity(
|
|
117
|
+
data, raw_entity_mappings, selector_query, parse_all
|
|
110
118
|
)
|
|
111
119
|
]
|
|
112
|
-
return [{}]
|
|
120
|
+
return [({}, False)]
|
|
113
121
|
|
|
114
|
-
async def
|
|
115
|
-
self,
|
|
116
|
-
|
|
122
|
+
async def _parse_items(
|
|
123
|
+
self,
|
|
124
|
+
mapping: ResourceConfig,
|
|
125
|
+
raw_results: list[RawEntity],
|
|
126
|
+
parse_all: bool = False,
|
|
127
|
+
) -> EntitySelectorDiff:
|
|
117
128
|
raw_entity_mappings: dict[str, Any] = mapping.port.entity.mappings.dict(
|
|
118
129
|
exclude_unset=True
|
|
119
130
|
)
|
|
120
|
-
|
|
131
|
+
calculate_entities_tasks = [
|
|
121
132
|
asyncio.create_task(
|
|
122
133
|
self._calculate_entity(
|
|
123
134
|
data,
|
|
124
135
|
raw_entity_mappings,
|
|
125
136
|
mapping.port.items_to_parse,
|
|
126
137
|
mapping.selector.query,
|
|
138
|
+
parse_all,
|
|
127
139
|
)
|
|
128
140
|
)
|
|
129
|
-
for data in
|
|
130
|
-
]
|
|
131
|
-
entities = await asyncio.gather(*entities_tasks)
|
|
132
|
-
|
|
133
|
-
return [
|
|
134
|
-
Entity.parse_obj(entity_data)
|
|
135
|
-
for flatten in entities
|
|
136
|
-
for entity_data in filter(
|
|
137
|
-
lambda entity: entity.get("identifier") and entity.get("blueprint"),
|
|
138
|
-
flatten,
|
|
139
|
-
)
|
|
141
|
+
for data in raw_results
|
|
140
142
|
]
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}
|
|
143
|
+
calculate_entities_results = await asyncio.gather(*calculate_entities_tasks)
|
|
144
|
+
|
|
145
|
+
passed_entities = []
|
|
146
|
+
failed_entities = []
|
|
147
|
+
for entities_results in calculate_entities_results:
|
|
148
|
+
for entity, did_entity_pass_selector in entities_results:
|
|
149
|
+
if entity.get("identifier") and entity.get("blueprint"):
|
|
150
|
+
parsed_entity = Entity.parse_obj(entity)
|
|
151
|
+
if did_entity_pass_selector:
|
|
152
|
+
passed_entities.append(parsed_entity)
|
|
153
|
+
else:
|
|
154
|
+
failed_entities.append(parsed_entity)
|
|
155
|
+
|
|
156
|
+
return {"passed": passed_entities, "failed": failed_entities}
|
|
@@ -24,6 +24,8 @@ from port_ocean.core.ocean_types import (
|
|
|
24
24
|
RawEntityDiff,
|
|
25
25
|
EntityDiff,
|
|
26
26
|
ASYNC_GENERATOR_RESYNC_TYPE,
|
|
27
|
+
RawEntity,
|
|
28
|
+
EntitySelectorDiff,
|
|
27
29
|
)
|
|
28
30
|
from port_ocean.core.utils import zip_and_sum
|
|
29
31
|
from port_ocean.exceptions.core import OceanAbortException
|
|
@@ -120,12 +122,13 @@ class SyncRawMixin(HandlerMixin, EventsMixin):
|
|
|
120
122
|
return results, errors
|
|
121
123
|
|
|
122
124
|
async def _calculate_raw(
|
|
123
|
-
self,
|
|
124
|
-
|
|
125
|
-
|
|
125
|
+
self,
|
|
126
|
+
raw_diff: list[tuple[ResourceConfig, list[RawEntity]]],
|
|
127
|
+
parse_all: bool = False,
|
|
128
|
+
) -> list[EntitySelectorDiff]:
|
|
126
129
|
return await asyncio.gather(
|
|
127
130
|
*(
|
|
128
|
-
self.entity_processor.parse_items(mapping, results)
|
|
131
|
+
self.entity_processor.parse_items(mapping, results, parse_all)
|
|
129
132
|
for mapping, results in raw_diff
|
|
130
133
|
)
|
|
131
134
|
)
|
|
@@ -135,42 +138,41 @@ class SyncRawMixin(HandlerMixin, EventsMixin):
|
|
|
135
138
|
resource: ResourceConfig,
|
|
136
139
|
results: list[dict[Any, Any]],
|
|
137
140
|
user_agent_type: UserAgentType,
|
|
141
|
+
parse_all: bool = False,
|
|
138
142
|
) -> list[Entity]:
|
|
139
|
-
objects_diff = await self._calculate_raw(
|
|
140
|
-
[
|
|
141
|
-
(
|
|
142
|
-
resource,
|
|
143
|
-
{
|
|
144
|
-
"before": [],
|
|
145
|
-
"after": results,
|
|
146
|
-
},
|
|
147
|
-
)
|
|
148
|
-
]
|
|
149
|
-
)
|
|
143
|
+
objects_diff = await self._calculate_raw([(resource, results)], parse_all)
|
|
150
144
|
|
|
151
|
-
entities_after: list[Entity] = objects_diff[0]["
|
|
145
|
+
entities_after: list[Entity] = objects_diff[0]["passed"]
|
|
152
146
|
await self.entities_state_applier.upsert(entities_after, user_agent_type)
|
|
147
|
+
|
|
148
|
+
# If an entity didn't pass the JQ selector, we want to delete it if it exists in Port
|
|
149
|
+
for entity_to_delete in objects_diff[0]["failed"]:
|
|
150
|
+
is_owner = (
|
|
151
|
+
await ocean.port_client.does_integration_has_ownership_over_entity(
|
|
152
|
+
entity_to_delete, user_agent_type
|
|
153
|
+
)
|
|
154
|
+
)
|
|
155
|
+
if not is_owner:
|
|
156
|
+
logger.info(
|
|
157
|
+
f"Skipping deletion of entity {entity_to_delete.identifier}, "
|
|
158
|
+
f"Couldn't find an entity that's related to the current integration."
|
|
159
|
+
)
|
|
160
|
+
continue
|
|
161
|
+
await self.entities_state_applier.delete(
|
|
162
|
+
objects_diff[0]["failed"], user_agent_type
|
|
163
|
+
)
|
|
164
|
+
|
|
153
165
|
return entities_after
|
|
154
166
|
|
|
155
167
|
async def _unregister_resource_raw(
|
|
156
168
|
self,
|
|
157
169
|
resource: ResourceConfig,
|
|
158
|
-
results: list[
|
|
170
|
+
results: list[RawEntity],
|
|
159
171
|
user_agent_type: UserAgentType,
|
|
160
172
|
) -> list[Entity]:
|
|
161
|
-
objects_diff = await self._calculate_raw(
|
|
162
|
-
[
|
|
163
|
-
(
|
|
164
|
-
resource,
|
|
165
|
-
{
|
|
166
|
-
"before": results,
|
|
167
|
-
"after": [],
|
|
168
|
-
},
|
|
169
|
-
)
|
|
170
|
-
]
|
|
171
|
-
)
|
|
173
|
+
objects_diff = await self._calculate_raw([(resource, results)])
|
|
172
174
|
|
|
173
|
-
entities_after: list[Entity] = objects_diff[0]["
|
|
175
|
+
entities_after: list[Entity] = objects_diff[0]["passed"]
|
|
174
176
|
await self.entities_state_applier.delete(entities_after, user_agent_type)
|
|
175
177
|
logger.info("Finished unregistering change")
|
|
176
178
|
return entities_after
|
|
@@ -233,7 +235,7 @@ class SyncRawMixin(HandlerMixin, EventsMixin):
|
|
|
233
235
|
|
|
234
236
|
return await asyncio.gather(
|
|
235
237
|
*(
|
|
236
|
-
self._register_resource_raw(resource, results, user_agent_type)
|
|
238
|
+
self._register_resource_raw(resource, results, user_agent_type, True)
|
|
237
239
|
for resource in resource_mappings
|
|
238
240
|
)
|
|
239
241
|
)
|
|
@@ -293,19 +295,31 @@ class SyncRawMixin(HandlerMixin, EventsMixin):
|
|
|
293
295
|
with logger.contextualize(kind=kind):
|
|
294
296
|
logger.info(f"Found {len(resource_mappings)} resources for {kind}")
|
|
295
297
|
|
|
296
|
-
|
|
297
|
-
[
|
|
298
|
+
entities_before = await self._calculate_raw(
|
|
299
|
+
[
|
|
300
|
+
(mapping, raw_desired_state["before"])
|
|
301
|
+
for mapping in resource_mappings
|
|
302
|
+
]
|
|
298
303
|
)
|
|
299
304
|
|
|
300
|
-
|
|
301
|
-
(
|
|
302
|
-
(entities_change["before"], entities_change["after"])
|
|
303
|
-
for entities_change in objects_diff
|
|
304
|
-
)
|
|
305
|
+
entities_after = await self._calculate_raw(
|
|
306
|
+
[(mapping, raw_desired_state["after"]) for mapping in resource_mappings]
|
|
305
307
|
)
|
|
306
308
|
|
|
309
|
+
entities_before_flatten = [
|
|
310
|
+
item
|
|
311
|
+
for sublist in [d["passed"] for d in entities_before]
|
|
312
|
+
for item in sublist
|
|
313
|
+
]
|
|
314
|
+
entities_after_flatten = [
|
|
315
|
+
item
|
|
316
|
+
for sublist in [d["passed"] for d in entities_after]
|
|
317
|
+
for item in sublist
|
|
318
|
+
]
|
|
319
|
+
|
|
307
320
|
await self.entities_state_applier.apply_diff(
|
|
308
|
-
{"before":
|
|
321
|
+
{"before": entities_before_flatten, "after": entities_after_flatten},
|
|
322
|
+
user_agent_type,
|
|
309
323
|
)
|
|
310
324
|
|
|
311
325
|
async def sync_raw_all(
|
|
@@ -333,8 +347,6 @@ class SyncRawMixin(HandlerMixin, EventsMixin):
|
|
|
333
347
|
):
|
|
334
348
|
app_config = await self.port_app_config_handler.get_port_app_config()
|
|
335
349
|
|
|
336
|
-
entities_at_port = await ocean.port_client.search_entities(user_agent_type)
|
|
337
|
-
|
|
338
350
|
creation_results: list[tuple[list[Entity], list[Exception]]] = []
|
|
339
351
|
|
|
340
352
|
try:
|
|
@@ -369,8 +381,11 @@ class SyncRawMixin(HandlerMixin, EventsMixin):
|
|
|
369
381
|
|
|
370
382
|
logger.error(message, exc_info=error_group)
|
|
371
383
|
else:
|
|
384
|
+
entities_at_port = await ocean.port_client.search_entities(
|
|
385
|
+
user_agent_type
|
|
386
|
+
)
|
|
372
387
|
logger.info(
|
|
373
|
-
f"Running resync diff calculation, number of entities at Port
|
|
388
|
+
f"Running resync diff calculation, number of entities found at Port: {len(entities_at_port)}, number of entities found during sync: {len(flat_created_entities)}"
|
|
374
389
|
)
|
|
375
390
|
await self.entities_state_applier.delete_diff(
|
|
376
391
|
{"before": entities_at_port, "after": flat_created_entities},
|