port-ocean 0.8.0__py3-none-any.whl → 0.9.1__py3-none-any.whl

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.

@@ -71,4 +71,10 @@ def sail(
71
71
  console.print("Setting event listener to Once")
72
72
  override["event_listener"] = {"type": "ONCE"}
73
73
 
74
- run(path, log_level, port, initialize_port_resources, override)
74
+ run(
75
+ path,
76
+ log_level,
77
+ port,
78
+ initialize_port_resources=initialize_port_resources,
79
+ config_override=override,
80
+ )
@@ -2,9 +2,10 @@ from typing import Any, Literal
2
2
 
3
3
  from port_ocean.config.base import BaseOceanSettings, BaseOceanModel
4
4
  from port_ocean.core.event_listener import EventListenerSettingsType
5
- from port_ocean.utils.misc import get_integration_name
5
+ from port_ocean.core.models import Runtime
6
+ from port_ocean.utils.misc import get_integration_name, get_spec_file
6
7
  from pydantic import Extra, AnyHttpUrl, parse_obj_as
7
- from pydantic.class_validators import root_validator
8
+ from pydantic.class_validators import root_validator, validator
8
9
  from pydantic.env_settings import InitSettingsSource, EnvSettingsSource, BaseSettings
9
10
  from pydantic.fields import Field
10
11
  from pydantic.main import BaseModel
@@ -69,3 +70,20 @@ class IntegrationConfiguration(BaseOceanSettings, extra=Extra.allow):
69
70
  event_listener: EventListenerSettingsType
70
71
  # If an identifier or type is not provided, it will be generated based on the integration name
71
72
  integration: IntegrationSettings = IntegrationSettings(type="", identifier="")
73
+ runtime: Runtime = "OnPrem"
74
+
75
+ @validator("runtime")
76
+ def validate_runtime(cls, runtime: Literal["OnPrem", "Saas"]) -> Runtime:
77
+ if runtime == "Saas":
78
+ spec = get_spec_file()
79
+ if spec is None:
80
+ raise ValueError(
81
+ "Could not determine whether it's safe to run "
82
+ "the integration due to not found spec.yaml."
83
+ )
84
+
85
+ saas_config = spec.get("saas")
86
+ if saas_config and not saas_config["enabled"]:
87
+ raise ValueError("This integration can't be ran as Saas")
88
+
89
+ return runtime
@@ -89,8 +89,8 @@ async def _initialize_required_integration_settings(
89
89
  "changelog_destination"
90
90
  )
91
91
  if (
92
- integration["changelogDestination"] != changelog_destination
93
- or integration["installationAppType"] != integration_config.integration.type
92
+ integration.get("changelogDestination") != changelog_destination
93
+ or integration.get("installationAppType") != integration_config.integration.type
94
94
  or integration.get("version") != port_client.integration_version
95
95
  ):
96
96
  await port_client.patch_integration(
@@ -71,11 +71,15 @@ class JQEntityProcessor(BaseEntityProcessor):
71
71
  async def _search_as_object(
72
72
  self, data: dict[str, Any], obj: dict[str, Any]
73
73
  ) -> dict[str, Any | None]:
74
- search_tasks: dict[str,Task[dict[str,Any | None]] | list[Task[dict[str,Any | None]]]] = {}
74
+ search_tasks: dict[
75
+ str, Task[dict[str, Any | None]] | list[Task[dict[str, Any | None]]]
76
+ ] = {}
75
77
  for key, value in obj.items():
76
-
77
- if isinstance(value,list):
78
- search_tasks[key] = [asyncio.create_task(self._search_as_object(data,obj)) for obj in value]
78
+ if isinstance(value, list):
79
+ search_tasks[key] = [
80
+ asyncio.create_task(self._search_as_object(data, obj))
81
+ for obj in value
82
+ ]
79
83
 
80
84
  elif isinstance(value, dict):
81
85
  search_tasks[key] = asyncio.create_task(
@@ -87,7 +91,7 @@ class JQEntityProcessor(BaseEntityProcessor):
87
91
  result: dict[str, Any | None] = {}
88
92
  for key, task in search_tasks.items():
89
93
  try:
90
- if isinstance(task,list):
94
+ if isinstance(task, list):
91
95
  result[key] = [await task for task in task]
92
96
  else:
93
97
  result[key] = await task
port_ocean/core/models.py CHANGED
@@ -1,10 +1,13 @@
1
1
  from dataclasses import dataclass, field
2
- from typing import Any
2
+ from typing import Any, Literal
3
3
 
4
4
  from pydantic import BaseModel
5
5
  from pydantic.fields import Field
6
6
 
7
7
 
8
+ Runtime = Literal["OnPrem", "Saas"]
9
+
10
+
8
11
  class Entity(BaseModel):
9
12
  identifier: Any
10
13
  blueprint: Any
port_ocean/core/utils.py CHANGED
@@ -1,12 +1,17 @@
1
1
  import asyncio
2
2
  from typing import Iterable, Any, TypeVar, Callable, Awaitable
3
3
 
4
+ from loguru import logger
4
5
  from pydantic import parse_obj_as, ValidationError
5
6
 
6
- from port_ocean.core.models import Entity
7
+ from port_ocean.clients.port.client import PortClient
8
+ from port_ocean.core.models import Entity, Runtime
7
9
  from port_ocean.core.models import EntityPortDiff
8
10
  from port_ocean.core.ocean_types import RAW_RESULT
9
- from port_ocean.exceptions.core import RawObjectValidationException
11
+ from port_ocean.exceptions.core import (
12
+ RawObjectValidationException,
13
+ IntegrationRuntimeException,
14
+ )
10
15
 
11
16
  T = TypeVar("T", bound=tuple[list[Any], ...])
12
17
 
@@ -29,6 +34,18 @@ def is_same_entity(first_entity: Entity, second_entity: Entity) -> bool:
29
34
  )
30
35
 
31
36
 
37
+ async def validate_integration_runtime(
38
+ port_client: PortClient, requested_runtime: Runtime
39
+ ) -> None:
40
+ logger.debug("Validating integration runtime")
41
+ current_integration = await port_client.get_current_integration(should_raise=False)
42
+ current_runtime = current_integration.get("installationType", "OnPrem")
43
+ if current_integration and current_runtime != requested_runtime:
44
+ raise IntegrationRuntimeException(
45
+ f"Invalid Runtime! Requested to run existing {current_runtime} integration in {requested_runtime} runtime."
46
+ )
47
+
48
+
32
49
  Q = TypeVar("Q")
33
50
 
34
51
 
@@ -33,3 +33,7 @@ class IntegrationAlreadyStartedException(BaseOceanException):
33
33
 
34
34
  class IntegrationNotStartedException(BaseOceanException):
35
35
  pass
36
+
37
+
38
+ class IntegrationRuntimeException(BaseOceanException):
39
+ pass
port_ocean/run.py CHANGED
@@ -1,3 +1,4 @@
1
+ import asyncio
1
2
  from inspect import getmembers
2
3
  from typing import Dict, Any, Type
3
4
 
@@ -8,6 +9,7 @@ from port_ocean.bootstrap import create_default_app
8
9
  from port_ocean.config.dynamic import default_config_factory
9
10
  from port_ocean.config.settings import ApplicationSettings, LogLevelType
10
11
  from port_ocean.core.defaults.initialize import initialize_defaults
12
+ from port_ocean.core.utils import validate_integration_runtime
11
13
  from port_ocean.log.logger_setup import setup_logger
12
14
  from port_ocean.ocean import Ocean
13
15
  from port_ocean.utils.misc import get_spec_file, load_module
@@ -45,6 +47,11 @@ def run(
45
47
  "app", default_app
46
48
  )
47
49
 
50
+ # Validate that the current integration's runtime matches the execution parameters
51
+ asyncio.get_event_loop().run_until_complete(
52
+ validate_integration_runtime(app.port_client, app.config.runtime)
53
+ )
54
+
48
55
  # Override config with arguments
49
56
  if initialize_port_resources is not None:
50
57
  app.config.initialize_port_resources = initialize_port_resources
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: port-ocean
3
- Version: 0.8.0
3
+ Version: 0.9.1
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
@@ -11,7 +11,7 @@ port_ocean/cli/commands/list_integrations.py,sha256=DVVioFruGUE-_v6UUHlcemWNN6Rl
11
11
  port_ocean/cli/commands/main.py,sha256=gj0lmuLep2XeLNuabB7Wk0UVYPT7_CD_rAw5AoUQWSE,1057
12
12
  port_ocean/cli/commands/new.py,sha256=y8QFeISoXb31a4RqMhXCDIPa3gJSYz2NPMGEI5p0Hxc,2074
13
13
  port_ocean/cli/commands/pull.py,sha256=VvrRjLNlfPuLIf7KzeIcbzzdi98Z0M9wCRpXC3QPxdI,2306
14
- port_ocean/cli/commands/sail.py,sha256=rv_lKFITsV5ta9ng3g4eR5H6AtlAsrvBQpAvH_p2DaA,2193
14
+ port_ocean/cli/commands/sail.py,sha256=rY7rEMjfy_KXiWvtL0T72TTLgeQ3HW4SOzKkz9wL9nI,2282
15
15
  port_ocean/cli/commands/version.py,sha256=hEuIEIcm6Zkamz41Z9nxeSM_4g3oNlAgWwQyDGboh-E,536
16
16
  port_ocean/cli/cookiecutter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  port_ocean/cli/cookiecutter/cookiecutter.json,sha256=N5UrAP2e5JbgEDz_WTQFIZlzSveME6x32sHeA7idjh0,481
@@ -48,7 +48,7 @@ port_ocean/clients/port/utils.py,sha256=O9mBu6zp4TfpS4SQ3qCPpn9ZVyYF8GKnji4UnYhM
48
48
  port_ocean/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
49
  port_ocean/config/base.py,sha256=J_FUvlo0D4FbEbr4mgJsbGB5JjW9I7zMwfekj6T30KY,6389
50
50
  port_ocean/config/dynamic.py,sha256=qOFkRoJsn_BW7581omi_AoMxoHqasf_foxDQ_G11_SI,2030
51
- port_ocean/config/settings.py,sha256=f6BXxFyu92WYhfPw4wlRaZ6jhkEsxhjw_BiWN9RERZg,2441
51
+ port_ocean/config/settings.py,sha256=qGdJUvRTpYv8EOFFlr7xiKXrrA4v9nuhg5EuDevNfqY,3128
52
52
  port_ocean/consumers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
53
  port_ocean/consumers/kafka_consumer.py,sha256=N8KocjBi9aR0BOPG8hgKovg-ns_ggpEjrSxqSqF_BSo,4710
54
54
  port_ocean/context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -59,7 +59,7 @@ port_ocean/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
59
  port_ocean/core/defaults/__init__.py,sha256=8qCZg8n06WAdMu9s_FiRtDYLGPGHbOuS60vapeUoAks,142
60
60
  port_ocean/core/defaults/clean.py,sha256=S3UAfca-oU89WJKIB4OgGjGjPr0vxBQ2aRZsLTZhQ04,2185
61
61
  port_ocean/core/defaults/common.py,sha256=QnLFTkT3yIWIRtLQb7fUvvfe5AfInYJy0q5LjlzHkOw,3553
62
- port_ocean/core/defaults/initialize.py,sha256=uq7gnsx2uHpWRuyYbQWGrPY6jbjXfmSWGc6myOQ8CVQ,8853
62
+ port_ocean/core/defaults/initialize.py,sha256=FXaxDWHBQtRWUKAKNivrLYeV_YIXWHW8TjjMufXjp38,8861
63
63
  port_ocean/core/event_listener/__init__.py,sha256=mzJ33wRq0kh60fpVdOHVmvMTUQIvz3vxmifyBgwDn0E,889
64
64
  port_ocean/core/event_listener/base.py,sha256=4RujgPz4VfDFlviu4qLGJFnJougSCL-Ewf0rfTQfwgc,1133
65
65
  port_ocean/core/event_listener/factory.py,sha256=AYYfSHPAF7P5H-uQECXT0JVJjKDHrYkWJJBSL4mGkg8,3697
@@ -77,7 +77,7 @@ port_ocean/core/handlers/entities_state_applier/port/get_related_entities.py,sha
77
77
  port_ocean/core/handlers/entities_state_applier/port/order_by_entities_dependencies.py,sha256=82BvU8t5w9uhsxX8hbnwuRPuWhW3cMeuT_5sVIkip1I,1550
78
78
  port_ocean/core/handlers/entity_processor/__init__.py,sha256=FvFCunFg44wNQoqlybem9MthOs7p1Wawac87uSXz9U8,156
79
79
  port_ocean/core/handlers/entity_processor/base.py,sha256=udR0w5TstTOS5xOfTjAZIEdldn4xr6Oyb3DylatYX3Q,1869
80
- port_ocean/core/handlers/entity_processor/jq_entity_processor.py,sha256=BU-kRUDnTVJNpa-B_Z6LQFuHanh9J9-2NluHavniYDM,7712
80
+ port_ocean/core/handlers/entity_processor/jq_entity_processor.py,sha256=uVHclCctUS3FGSCBLWD8Mesqttv-ege-X6K5o94zVOc,7797
81
81
  port_ocean/core/handlers/port_app_config/__init__.py,sha256=8AAT5OthiVM7KCcM34iEgEeXtn2pRMrT4Dze5r1Ixbk,134
82
82
  port_ocean/core/handlers/port_app_config/api.py,sha256=6VbKPwFzsWG0IYsVD81hxSmfqtHUFqrfUuj1DBX5g4w,853
83
83
  port_ocean/core/handlers/port_app_config/base.py,sha256=oufdNLzUmEgJY5PgIz75zDlowWrjA-y8WR4UnM58E58,2897
@@ -90,15 +90,15 @@ port_ocean/core/integrations/mixins/handler.py,sha256=mZ7-0UlG3LcrwJttFbMe-R4xcO
90
90
  port_ocean/core/integrations/mixins/sync.py,sha256=TKqRytxXONVhuCo3CB3rDvWNbITnZz33TYTDs3SWWVk,3880
91
91
  port_ocean/core/integrations/mixins/sync_raw.py,sha256=yFORznT6TXX7SXP1sSoHAjLxmjDzXIr3Vu-plbhLBoA,18017
92
92
  port_ocean/core/integrations/mixins/utils.py,sha256=7y1rGETZIjOQadyIjFJXIHKkQFKx_SwiP-TrAIsyyLY,2303
93
- port_ocean/core/models.py,sha256=YPIU7V3GKeDXIVkNzZn0w17YN2Akl-D8nFs-l4bEKcU,1143
93
+ port_ocean/core/models.py,sha256=4bDvMeydlSpG0YSXjE1Bo2AcZC0aQ2zqFhpsOvZat_A,1190
94
94
  port_ocean/core/ocean_types.py,sha256=3_d8-n626f1kWLQ_Jxw194LEyrOVupz05qs_Y1pvB-A,990
95
- port_ocean/core/utils.py,sha256=5ISNJ90xxK4Nf_suGEZ2ZPBKsoOqL7khU0MuA0q5zmE,2891
95
+ port_ocean/core/utils.py,sha256=WNtU7eqlFzq57PM8b2XVhVYcnjeByBovMuoeG502YGY,3588
96
96
  port_ocean/exceptions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
97
97
  port_ocean/exceptions/api.py,sha256=TLmTMqn4uHGaHgZK8PMIJ0TVJlPB4iP7xl9rx7GtCyY,426
98
98
  port_ocean/exceptions/base.py,sha256=uY4DX7fIITDFfemCJDWpaZi3bD51lcANc5swpoNvMJA,46
99
99
  port_ocean/exceptions/clients.py,sha256=LKLLs-Zy3caNG85rwxfOw2rMr8qqVV6SHUq4fRCZ99U,180
100
100
  port_ocean/exceptions/context.py,sha256=mA8HII6Rl4QxKUz98ppy1zX3kaziaen21h1ZWuU3ADc,372
101
- port_ocean/exceptions/core.py,sha256=ygxtPQ9IG8NzIrzZok5OqkefVrqcC4bjZ-2Vf9IPZuA,790
101
+ port_ocean/exceptions/core.py,sha256=Zmb1m6NnkSPWpAiQA5tgejm3zpDMt1WQEN47OJNo54A,856
102
102
  port_ocean/exceptions/port_defaults.py,sha256=pJ5im06ziDX2IVstSlYIjVHhs4JW-N0Vr0PqlDNhAb4,541
103
103
  port_ocean/exceptions/utils.py,sha256=gjOqpi-HpY1l4WlMFsGA9yzhxDhajhoGGdDDyGbLnqI,197
104
104
  port_ocean/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -111,7 +111,7 @@ port_ocean/log/sensetive.py,sha256=wkyvkKMbyLTjZDSbvvLHL9bv4RvD0DPAyL3uWSttUOA,2
111
111
  port_ocean/middlewares.py,sha256=6GrhldYAazxSwK2TbS-J28XdZ-9wO3PgCcyIMhnnJvI,2480
112
112
  port_ocean/ocean.py,sha256=nRTTh6faPrt77ozvKBFk6eCNxwzKcTDzJ4KPgpO4VRk,4304
113
113
  port_ocean/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
114
- port_ocean/run.py,sha256=IYo3R0DChb0-Uqs_WU8f5sk_ZBrv1Xjb-PHyE5IRAYw,1835
114
+ port_ocean/run.py,sha256=_5wwATpjQWQS19Dr8A-x8NOMslChMNc-So7sFqcZ74U,2130
115
115
  port_ocean/sonar-project.properties,sha256=X_wLzDOkEVmpGLRMb2fg9Rb0DxWwUFSvESId8qpvrPI,73
116
116
  port_ocean/utils/__init__.py,sha256=KMGnCPXZJbNwtgxtyMycapkDz8tpSyw23MSYT3iVeHs,91
117
117
  port_ocean/utils/async_http.py,sha256=arnH458TExn2Dju_Sy6pHas_vF5RMWnOp-jBz5WAAcE,1226
@@ -122,8 +122,8 @@ port_ocean/utils/queue_utils.py,sha256=KWWl8YVnG-glcfIHhM6nefY-2sou_C6DVP1VynQwz
122
122
  port_ocean/utils/repeat.py,sha256=0EFWM9d8lLXAhZmAyczY20LAnijw6UbIECf5lpGbOas,3231
123
123
  port_ocean/utils/signal.py,sha256=K-6kKFQTltcmKDhtyZAcn0IMa3sUpOHGOAUdWKgx0_E,1369
124
124
  port_ocean/version.py,sha256=UsuJdvdQlazzKGD3Hd5-U7N69STh8Dq9ggJzQFnu9fU,177
125
- port_ocean-0.8.0.dist-info/LICENSE.md,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
126
- port_ocean-0.8.0.dist-info/METADATA,sha256=b12SkmpuVSjxM8ASdLd4VBJS1h1igcll5UInwEggHNY,6561
127
- port_ocean-0.8.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
128
- port_ocean-0.8.0.dist-info/entry_points.txt,sha256=F_DNUmGZU2Kme-8NsWM5LLE8piGMafYZygRYhOVtcjA,54
129
- port_ocean-0.8.0.dist-info/RECORD,,
125
+ port_ocean-0.9.1.dist-info/LICENSE.md,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
126
+ port_ocean-0.9.1.dist-info/METADATA,sha256=PRjfspeABVsgg4gcPiaSSNnBITeqLQS3mzYKE9J7Ldk,6561
127
+ port_ocean-0.9.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
128
+ port_ocean-0.9.1.dist-info/entry_points.txt,sha256=F_DNUmGZU2Kme-8NsWM5LLE8piGMafYZygRYhOVtcjA,54
129
+ port_ocean-0.9.1.dist-info/RECORD,,