port-ocean 0.21.2__tar.gz → 0.29.5__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.
Files changed (235) hide show
  1. {port_ocean-0.21.2 → port_ocean-0.29.5}/PKG-INFO +14 -6
  2. {port_ocean-0.21.2 → port_ocean-0.29.5}/README.md +1 -0
  3. {port_ocean-0.21.2 → port_ocean-0.29.5}/integrations/_infra/Dockerfile.Deb +37 -2
  4. {port_ocean-0.21.2 → port_ocean-0.29.5}/integrations/_infra/Dockerfile.alpine +2 -2
  5. {port_ocean-0.21.2 → port_ocean-0.29.5}/integrations/_infra/Dockerfile.base.builder +7 -4
  6. {port_ocean-0.21.2 → port_ocean-0.29.5}/integrations/_infra/Dockerfile.base.runner +4 -3
  7. port_ocean-0.29.5/integrations/_infra/Dockerfile.local +65 -0
  8. {port_ocean-0.21.2 → port_ocean-0.29.5}/integrations/_infra/Makefile +3 -1
  9. port_ocean-0.29.5/integrations/_infra/README.md +30 -0
  10. port_ocean-0.29.5/integrations/_infra/entry_local.sh +26 -0
  11. {port_ocean-0.21.2 → port_ocean-0.29.5}/integrations/_infra/init.sh +2 -2
  12. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/__init__.py +6 -1
  13. port_ocean-0.29.5/port_ocean/cache/base.py +25 -0
  14. port_ocean-0.29.5/port_ocean/cache/disk.py +61 -0
  15. port_ocean-0.29.5/port_ocean/cache/errors.py +10 -0
  16. port_ocean-0.29.5/port_ocean/cache/memory.py +36 -0
  17. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/cookiecutter/cookiecutter.json +2 -2
  18. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/README.md +1 -1
  19. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/clients/auth/oauth_client.py +1 -1
  20. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/clients/port/authentication.py +23 -2
  21. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/clients/port/client.py +11 -5
  22. port_ocean-0.29.5/port_ocean/clients/port/mixins/actions.py +93 -0
  23. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/clients/port/mixins/blueprints.py +9 -21
  24. port_ocean-0.29.5/port_ocean/clients/port/mixins/entities.py +628 -0
  25. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/clients/port/mixins/integrations.py +81 -12
  26. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/clients/port/mixins/migrations.py +2 -2
  27. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/clients/port/mixins/organization.py +2 -2
  28. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/clients/port/utils.py +9 -4
  29. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/config/dynamic.py +28 -3
  30. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/config/settings.py +97 -4
  31. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/context/event.py +1 -0
  32. port_ocean-0.29.5/port_ocean/context/metric_resource.py +63 -0
  33. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/context/ocean.py +12 -5
  34. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/context/resource.py +3 -4
  35. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/defaults/common.py +1 -0
  36. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/defaults/initialize.py +13 -6
  37. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/event_listener/__init__.py +7 -0
  38. port_ocean-0.29.5/port_ocean/core/event_listener/actions_only.py +42 -0
  39. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/event_listener/base.py +10 -4
  40. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/event_listener/factory.py +18 -9
  41. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/event_listener/http.py +4 -3
  42. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/event_listener/kafka.py +17 -2
  43. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/event_listener/once.py +5 -2
  44. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/event_listener/polling.py +4 -3
  45. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/event_listener/webhooks_only.py +3 -2
  46. port_ocean-0.29.5/port_ocean/core/handlers/actions/__init__.py +7 -0
  47. port_ocean-0.29.5/port_ocean/core/handlers/actions/abstract_executor.py +150 -0
  48. port_ocean-0.29.5/port_ocean/core/handlers/actions/execution_manager.py +469 -0
  49. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/handlers/entities_state_applier/port/applier.py +39 -16
  50. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/handlers/entities_state_applier/port/get_related_entities.py +7 -0
  51. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/handlers/entity_processor/base.py +0 -2
  52. port_ocean-0.29.5/port_ocean/core/handlers/entity_processor/jq_entity_processor.py +819 -0
  53. port_ocean-0.29.5/port_ocean/core/handlers/entity_processor/jq_input_evaluator.py +137 -0
  54. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/handlers/port_app_config/base.py +2 -4
  55. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/handlers/port_app_config/models.py +18 -5
  56. port_ocean-0.29.5/port_ocean/core/handlers/queue/__init__.py +5 -0
  57. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/handlers/queue/abstract_queue.py +8 -0
  58. port_ocean-0.29.5/port_ocean/core/handlers/queue/group_queue.py +138 -0
  59. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/handlers/queue/local_queue.py +3 -0
  60. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/handlers/resync_state_updater/updater.py +21 -1
  61. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/handlers/webhook/abstract_webhook_processor.py +16 -0
  62. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/handlers/webhook/processor_manager.py +146 -89
  63. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/handlers/webhook/webhook_event.py +2 -5
  64. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/integrations/base.py +15 -7
  65. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/integrations/mixins/live_events.py +4 -2
  66. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/integrations/mixins/sync.py +1 -1
  67. port_ocean-0.29.5/port_ocean/core/integrations/mixins/sync_raw.py +1081 -0
  68. port_ocean-0.29.5/port_ocean/core/integrations/mixins/utils.py +326 -0
  69. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/models.py +71 -4
  70. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/ocean_types.py +2 -1
  71. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/utils/utils.py +26 -7
  72. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/exceptions/core.py +4 -0
  73. port_ocean-0.29.5/port_ocean/exceptions/execution_manager.py +22 -0
  74. port_ocean-0.29.5/port_ocean/exceptions/webhook_processor.py +17 -0
  75. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/helpers/async_client.py +17 -12
  76. port_ocean-0.29.5/port_ocean/helpers/metric/metric.py +425 -0
  77. port_ocean-0.29.5/port_ocean/helpers/metric/utils.py +52 -0
  78. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/helpers/retry.py +195 -73
  79. port_ocean-0.29.5/port_ocean/helpers/stream.py +71 -0
  80. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/log/handlers.py +3 -4
  81. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/log/logger_setup.py +16 -2
  82. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/ocean.py +119 -20
  83. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/run.py +0 -1
  84. port_ocean-0.29.5/port_ocean/tests/cache/__init__.py +1 -0
  85. port_ocean-0.29.5/port_ocean/tests/cache/test_disk_cache.py +92 -0
  86. port_ocean-0.29.5/port_ocean/tests/cache/test_memory_cache.py +59 -0
  87. port_ocean-0.29.5/port_ocean/tests/clients/port/mixins/test_entities.py +281 -0
  88. port_ocean-0.29.5/port_ocean/tests/clients/port/mixins/test_integrations.py +205 -0
  89. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/clients/port/mixins/test_organization_mixin.py +1 -0
  90. port_ocean-0.29.5/port_ocean/tests/config/test_config.py +38 -0
  91. port_ocean-0.29.5/port_ocean/tests/core/conftest.py +239 -0
  92. port_ocean-0.29.5/port_ocean/tests/core/event_listener/test_kafka.py +77 -0
  93. port_ocean-0.29.5/port_ocean/tests/core/handlers/actions/test_execution_manager.py +837 -0
  94. port_ocean-0.29.5/port_ocean/tests/core/handlers/entities_state_applier/test_applier.py +288 -0
  95. port_ocean-0.29.5/port_ocean/tests/core/handlers/entity_processor/test_jq_entity_processor.py +1290 -0
  96. port_ocean-0.29.5/port_ocean/tests/core/handlers/entity_processor/test_jq_input_evaluator.py +932 -0
  97. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/core/handlers/mixins/test_live_events.py +25 -15
  98. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/core/handlers/mixins/test_sync_raw.py +299 -188
  99. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/core/handlers/port_app_config/test_base.py +82 -0
  100. port_ocean-0.29.5/port_ocean/tests/core/handlers/queue/test_group_queue.py +681 -0
  101. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/core/handlers/webhook/test_processor_manager.py +199 -73
  102. port_ocean-0.29.5/port_ocean/tests/core/utils/test_get_port_diff.py +164 -0
  103. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/core/utils/test_resolve_entities_diff.py +52 -0
  104. port_ocean-0.29.5/port_ocean/tests/helpers/__init__.py +0 -0
  105. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/helpers/fixtures.py +2 -3
  106. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/helpers/port_client.py +1 -0
  107. port_ocean-0.29.5/port_ocean/tests/helpers/test_retry.py +549 -0
  108. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/log/test_handlers.py +2 -1
  109. port_ocean-0.29.5/port_ocean/tests/test_metric.py +180 -0
  110. port_ocean-0.29.5/port_ocean/tests/utils/test_cache.py +514 -0
  111. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/utils/async_http.py +4 -1
  112. port_ocean-0.29.5/port_ocean/utils/cache.py +156 -0
  113. port_ocean-0.29.5/port_ocean/utils/ipc.py +30 -0
  114. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/utils/misc.py +5 -3
  115. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/utils/signal.py +23 -8
  116. {port_ocean-0.21.2 → port_ocean-0.29.5}/pyproject.toml +20 -9
  117. port_ocean-0.21.2/port_ocean/clients/port/mixins/entities.py +0 -288
  118. port_ocean-0.21.2/port_ocean/core/handlers/entity_processor/jq_entity_processor.py +0 -313
  119. port_ocean-0.21.2/port_ocean/core/handlers/queue/__init__.py +0 -4
  120. port_ocean-0.21.2/port_ocean/core/integrations/mixins/sync_raw.py +0 -633
  121. port_ocean-0.21.2/port_ocean/core/integrations/mixins/utils.py +0 -74
  122. port_ocean-0.21.2/port_ocean/exceptions/webhook_processor.py +0 -4
  123. port_ocean-0.21.2/port_ocean/tests/clients/port/mixins/test_entities.py +0 -53
  124. port_ocean-0.21.2/port_ocean/tests/core/handlers/entities_state_applier/test_applier.py +0 -86
  125. port_ocean-0.21.2/port_ocean/tests/core/handlers/entity_processor/test_jq_entity_processor.py +0 -350
  126. port_ocean-0.21.2/port_ocean/tests/utils/test_cache.py +0 -189
  127. port_ocean-0.21.2/port_ocean/utils/cache.py +0 -97
  128. {port_ocean-0.21.2 → port_ocean-0.29.5}/LICENSE.md +0 -0
  129. {port_ocean-0.21.2 → port_ocean-0.29.5}/integrations/_infra/Dockerfile.dockerignore +0 -0
  130. {port_ocean-0.21.2 → port_ocean-0.29.5}/integrations/_infra/grpcio.sh +0 -0
  131. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/bootstrap.py +0 -0
  132. {port_ocean-0.21.2/port_ocean/cli/cookiecutter → port_ocean-0.29.5/port_ocean/cache}/__init__.py +0 -0
  133. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/__init__.py +0 -0
  134. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/cli.py +0 -0
  135. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/commands/__init__.py +0 -0
  136. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/commands/defaults/__init___.py +0 -0
  137. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/commands/defaults/clean.py +0 -0
  138. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/commands/defaults/dock.py +0 -0
  139. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/commands/defaults/group.py +0 -0
  140. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/commands/list_integrations.py +0 -0
  141. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/commands/main.py +0 -0
  142. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/commands/new.py +0 -0
  143. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/commands/pull.py +0 -0
  144. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/commands/sail.py +0 -0
  145. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/commands/version.py +0 -0
  146. {port_ocean-0.21.2/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/tests → port_ocean-0.29.5/port_ocean/cli/cookiecutter}/__init__.py +0 -0
  147. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/cookiecutter/extensions.py +0 -0
  148. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/cookiecutter/hooks/post_gen_project.py +0 -0
  149. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.env.example +0 -0
  150. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.gitignore +0 -0
  151. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/.gitignore +0 -0
  152. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/blueprints.json +0 -0
  153. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/port-app-config.yml +0 -0
  154. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/spec.yaml +0 -0
  155. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/CHANGELOG.md +0 -0
  156. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/CONTRIBUTING.md +0 -0
  157. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/changelog/.gitignore +0 -0
  158. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/debug.py +0 -0
  159. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/main.py +0 -0
  160. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/poetry.toml +0 -0
  161. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/pyproject.toml +0 -0
  162. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/sonar-project.properties +0 -0
  163. {port_ocean-0.21.2/port_ocean/clients → port_ocean-0.29.5/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/tests}/__init__.py +0 -0
  164. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/tests/test_sample.py +0 -0
  165. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/cli/utils.py +0 -0
  166. {port_ocean-0.21.2/port_ocean/clients/auth → port_ocean-0.29.5/port_ocean/clients}/__init__.py +0 -0
  167. {port_ocean-0.21.2/port_ocean/clients/port → port_ocean-0.29.5/port_ocean/clients/auth}/__init__.py +0 -0
  168. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/clients/auth/auth_client.py +0 -0
  169. {port_ocean-0.21.2/port_ocean/clients/port/mixins → port_ocean-0.29.5/port_ocean/clients/port}/__init__.py +0 -0
  170. {port_ocean-0.21.2/port_ocean/config → port_ocean-0.29.5/port_ocean/clients/port/mixins}/__init__.py +0 -0
  171. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/clients/port/retry_transport.py +0 -0
  172. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/clients/port/types.py +0 -0
  173. {port_ocean-0.21.2/port_ocean/consumers → port_ocean-0.29.5/port_ocean/config}/__init__.py +0 -0
  174. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/config/base.py +0 -0
  175. {port_ocean-0.21.2/port_ocean/context → port_ocean-0.29.5/port_ocean/consumers}/__init__.py +0 -0
  176. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/consumers/kafka_consumer.py +0 -0
  177. {port_ocean-0.21.2/port_ocean/core → port_ocean-0.29.5/port_ocean/context}/__init__.py +0 -0
  178. {port_ocean-0.21.2/port_ocean/core/handlers/entities_state_applier/port → port_ocean-0.29.5/port_ocean/core}/__init__.py +0 -0
  179. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/defaults/__init__.py +0 -0
  180. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/defaults/clean.py +0 -0
  181. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/handlers/__init__.py +0 -0
  182. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/handlers/base.py +0 -0
  183. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/handlers/entities_state_applier/__init__.py +0 -0
  184. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/handlers/entities_state_applier/base.py +0 -0
  185. {port_ocean-0.21.2/port_ocean/core/handlers/webhook → port_ocean-0.29.5/port_ocean/core/handlers/entities_state_applier/port}/__init__.py +0 -0
  186. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/handlers/entities_state_applier/port/order_by_entities_dependencies.py +0 -0
  187. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/handlers/entity_processor/__init__.py +0 -0
  188. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/handlers/port_app_config/__init__.py +0 -0
  189. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/handlers/port_app_config/api.py +0 -0
  190. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/handlers/resync_state_updater/__init__.py +0 -0
  191. {port_ocean-0.21.2/port_ocean/core/integrations → port_ocean-0.29.5/port_ocean/core/handlers/webhook}/__init__.py +0 -0
  192. {port_ocean-0.21.2/port_ocean/exceptions → port_ocean-0.29.5/port_ocean/core/integrations}/__init__.py +0 -0
  193. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/integrations/mixins/__init__.py +0 -0
  194. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/integrations/mixins/events.py +0 -0
  195. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/integrations/mixins/handler.py +0 -0
  196. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/core/utils/entity_topological_sorter.py +0 -0
  197. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/debug_cli.py +0 -0
  198. {port_ocean-0.21.2/port_ocean/helpers → port_ocean-0.29.5/port_ocean/exceptions}/__init__.py +0 -0
  199. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/exceptions/api.py +0 -0
  200. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/exceptions/base.py +0 -0
  201. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/exceptions/clients.py +0 -0
  202. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/exceptions/context.py +0 -0
  203. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/exceptions/port_defaults.py +0 -0
  204. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/exceptions/utils.py +0 -0
  205. {port_ocean-0.21.2/port_ocean/log → port_ocean-0.29.5/port_ocean/helpers}/__init__.py +0 -0
  206. {port_ocean-0.21.2/port_ocean/tests → port_ocean-0.29.5/port_ocean/log}/__init__.py +0 -0
  207. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/log/sensetive.py +0 -0
  208. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/middlewares.py +0 -0
  209. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/py.typed +0 -0
  210. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/sonar-project.properties +0 -0
  211. {port_ocean-0.21.2/port_ocean/tests/clients → port_ocean-0.29.5/port_ocean/tests}/__init__.py +0 -0
  212. {port_ocean-0.21.2/port_ocean/tests/clients/oauth → port_ocean-0.29.5/port_ocean/tests/clients}/__init__.py +0 -0
  213. {port_ocean-0.21.2/port_ocean/tests/helpers → port_ocean-0.29.5/port_ocean/tests/clients/oauth}/__init__.py +0 -0
  214. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/clients/oauth/test_oauth_client.py +0 -0
  215. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/conftest.py +0 -0
  216. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/core/defaults/test_common.py +0 -0
  217. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/core/handlers/port_app_config/test_api.py +0 -0
  218. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/core/handlers/queue/test_local_queue.py +0 -0
  219. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/core/handlers/webhook/test_abstract_webhook_processor.py +0 -0
  220. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/core/handlers/webhook/test_webhook_event.py +0 -0
  221. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/core/test_utils.py +0 -0
  222. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/core/utils/test_entity_topological_sorter.py +0 -0
  223. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/helpers/fake_port_api.py +0 -0
  224. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/helpers/integration.py +0 -0
  225. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/helpers/ocean_app.py +0 -0
  226. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/helpers/smoke_test.py +0 -0
  227. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/test_ocean.py +0 -0
  228. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/test_smoke.py +0 -0
  229. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/tests/utils/test_async_iterators.py +0 -0
  230. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/utils/__init__.py +0 -0
  231. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/utils/async_iterators.py +0 -0
  232. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/utils/queue_utils.py +0 -0
  233. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/utils/repeat.py +0 -0
  234. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/utils/time.py +0 -0
  235. {port_ocean-0.21.2 → port_ocean-0.29.5}/port_ocean/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: port-ocean
3
- Version: 0.21.2
3
+ Version: 0.29.5
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
@@ -22,25 +22,32 @@ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
22
22
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
23
  Classifier: Topic :: Utilities
24
24
  Provides-Extra: cli
25
+ Requires-Dist: aiofiles (>=24.1.0,<25.0.0)
25
26
  Requires-Dist: aiostream (>=0.5.2,<0.7.0)
26
27
  Requires-Dist: click (>=8.1.3,<9.0.0) ; extra == "cli"
27
- Requires-Dist: confluent-kafka (>=2.1.1,<3.0.0)
28
+ Requires-Dist: confluent-kafka (>=2.10.1,<3.0.0)
28
29
  Requires-Dist: cookiecutter (>=2.1.1,<3.0.0) ; extra == "cli"
29
- Requires-Dist: fastapi (>=0.115.3,<0.116.0)
30
- Requires-Dist: httpx (>=0.24.1,<0.28.0)
30
+ Requires-Dist: cryptography (>=44.0.1,<45.0.0)
31
+ Requires-Dist: fastapi (>=0.121.0,<0.122.0)
32
+ Requires-Dist: httpx (>=0.28.1,<0.29.0)
33
+ Requires-Dist: ijson (>=3.4.0,<4.0.0)
34
+ Requires-Dist: jinja2 (>=3.1.6)
31
35
  Requires-Dist: jinja2-time (>=0.2.0,<0.3.0) ; extra == "cli"
32
36
  Requires-Dist: jq (>=1.8.0,<2.0.0)
33
37
  Requires-Dist: loguru (>=0.7.0,<0.8.0)
38
+ Requires-Dist: prometheus-client (>=0.21.1,<0.22.0)
34
39
  Requires-Dist: pydantic[dotenv] (>=1.10.8,<2.0.0)
35
40
  Requires-Dist: pydispatcher (>=2.0.7,<3.0.0)
36
41
  Requires-Dist: pyhumps (>=3.8.0,<4.0.0)
42
+ Requires-Dist: pyjwt (>=2.10.1,<3.0.0)
43
+ Requires-Dist: pytest-cov (>=6.0.0,<7.0.0)
37
44
  Requires-Dist: python-dateutil (>=2.9.0.post0,<3.0.0)
38
45
  Requires-Dist: pyyaml (>=6.0,<7.0)
39
46
  Requires-Dist: rich (>=13.4.1,<14.0.0) ; extra == "cli"
40
47
  Requires-Dist: six (>=1.16.0,<2.0.0)
41
48
  Requires-Dist: tomli (>=2.0.1,<3.0.0)
42
- Requires-Dist: urllib3 (>=1.26.16,<3.0.0)
43
- Requires-Dist: uvicorn (>=0.22,<0.31)
49
+ Requires-Dist: urllib3 (>=2.5.0,<3.0.0)
50
+ Requires-Dist: uvicorn (>=0.34.3,<0.35.0)
44
51
  Requires-Dist: werkzeug (>=2.3.4,<4.0.0)
45
52
  Project-URL: Repository, https://github.com/port-labs/Port-Ocean
46
53
  Description-Content-Type: text/markdown
@@ -50,6 +57,7 @@ Description-Content-Type: text/markdown
50
57
  # Ocean <img src="./assets/OceanSymbol.svg" alt="Ocean" width="100" height="100" align="right">
51
58
 
52
59
  [![Lint](https://github.com/port-labs/Port-Ocean/actions/workflows/lint.yml/badge.svg)](https://github.com/port-labs/port-ocean/actions/workflows/lint.yml)
60
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/port-labs/ocean)
53
61
 
54
62
  Ocean is an innovative solution developed by Port to seamlessly integrate various third-party systems with our developer portal product,
55
63
  empowering engineers to effortlessly prioritize key features and streamline the integration process.
@@ -3,6 +3,7 @@
3
3
  # Ocean <img src="./assets/OceanSymbol.svg" alt="Ocean" width="100" height="100" align="right">
4
4
 
5
5
  [![Lint](https://github.com/port-labs/Port-Ocean/actions/workflows/lint.yml/badge.svg)](https://github.com/port-labs/port-ocean/actions/workflows/lint.yml)
6
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/port-labs/ocean)
6
7
 
7
8
  Ocean is an innovative solution developed by Port to seamlessly integrate various third-party systems with our developer portal product,
8
9
  empowering engineers to effortlessly prioritize key features and streamline the integration process.
@@ -6,7 +6,7 @@ FROM ${BASE_BUILDER_PYTHON_IMAGE} AS base
6
6
  ARG BUILD_CONTEXT
7
7
  ARG BUILDPLATFORM
8
8
 
9
- ENV LIBRDKAFKA_VERSION=1.9.2 \
9
+ ENV LIBRDKAFKA_VERSION=2.8.2 \
10
10
  PYTHONUNBUFFERED=1 \
11
11
  POETRY_VIRTUALENVS_IN_PROJECT=1 \
12
12
  PIP_ROOT_USER_ACTION=ignore
@@ -18,17 +18,37 @@ COPY ./${BUILD_CONTEXT}/pyproject.toml ./${BUILD_CONTEXT}/poetry.lock /app/
18
18
  RUN poetry install --without dev --no-root --no-interaction --no-ansi --no-cache
19
19
 
20
20
  FROM ${BASE_RUNNER_PYTHON_IMAGE} AS prod
21
+ ARG OCEAN_USER_ID=999
22
+
23
+ RUN groupadd -r appgroup && useradd -r -g appgroup -m -u ${OCEAN_USER_ID} ocean
24
+
25
+ RUN mkdir -p /tmp/ocean
21
26
 
22
27
  ARG INTEGRATION_VERSION
23
28
  ARG BUILD_CONTEXT
29
+ ARG PROMETHEUS_MULTIPROC_DIR=/tmp/ocean/prometheus/metrics
30
+ ARG OAUTH_CONFIG_DIR=/app/.config
31
+ ARG STREAMING_LOCATION=/tmp/ocean/streaming
32
+
33
+ ENV LIBRDKAFKA_VERSION=2.8.2 \
34
+ PROMETHEUS_MULTIPROC_DIR=${PROMETHEUS_MULTIPROC_DIR} \
35
+ STREAMING_LOCATION=${STREAMING_LOCATION}
24
36
 
25
- ENV LIBRDKAFKA_VERSION=1.9.2
37
+ RUN mkdir -p ${PROMETHEUS_MULTIPROC_DIR}
38
+ RUN mkdir -p ${STREAMING_LOCATION}
39
+ RUN chown -R ocean:appgroup /tmp/ocean && chmod -R 755 /tmp/ocean
40
+
41
+ RUN mkdir -p ${OAUTH_CONFIG_DIR}
42
+ RUN chown -R ocean:appgroup ${OAUTH_CONFIG_DIR}
26
43
 
27
44
  RUN apt-get update \
28
45
  && apt-get install -y \
29
46
  ca-certificates \
30
47
  openssl \
31
48
  curl \
49
+ acl \
50
+ sudo \
51
+ jq \
32
52
  && apt-get clean
33
53
 
34
54
  LABEL INTEGRATION_VERSION=${INTEGRATION_VERSION}
@@ -39,6 +59,8 @@ ENV PIP_ROOT_USER_ACTION=ignore
39
59
 
40
60
  WORKDIR /app
41
61
 
62
+ USER ocean
63
+
42
64
  # Copy the application code
43
65
  COPY ./${BUILD_CONTEXT} /app
44
66
 
@@ -47,10 +69,23 @@ COPY --from=base /app/.venv /app/.venv
47
69
 
48
70
  COPY ./integrations/_infra/init.sh /app/init.sh
49
71
 
72
+ USER root
73
+
50
74
  # Ensure that ocean is available for all in path
51
75
  RUN chmod a+x /app/.venv/bin/ocean
52
76
 
53
77
  RUN chmod a+x /app/init.sh
54
78
  RUN ln -s /app/.venv/bin/ocean /usr/bin/ocean
79
+
80
+ # Add ocean user to ssl certs group
81
+ RUN setfacl -R -m u:ocean:rwX /etc/ssl/certs \
82
+ && setfacl -d -m u:ocean:rwX /etc/ssl/certs
83
+
84
+ # Allow ocean user to run update-ca-certificates without password (secure, limited sudo)
85
+ RUN echo "ocean ALL=(root) NOPASSWD: /usr/sbin/update-ca-certificates" >> /etc/sudoers.d/ocean-certs \
86
+ && chmod 440 /etc/sudoers.d/ocean-certs
87
+
88
+ USER ocean
89
+
55
90
  # Run the application
56
91
  CMD ["bash", "/app/init.sh"]
@@ -5,7 +5,7 @@ FROM ${BASE_PYTHON_IMAGE} AS base
5
5
  ARG BUILD_CONTEXT
6
6
  ARG BUILDPLATFORM
7
7
 
8
- ENV LIBRDKAFKA_VERSION=1.9.2 \
8
+ ENV LIBRDKAFKA_VERSION=2.8.2 \
9
9
  PYTHONUNBUFFERED=1 \
10
10
  PIP_DISABLE_PIP_VERSION_CHECK=on \
11
11
  POETRY_NO_INTERACTION=1 \
@@ -66,7 +66,7 @@ FROM ${BASE_PYTHON_IMAGE} AS prod
66
66
  ARG INTEGRATION_VERSION
67
67
  ARG BUILD_CONTEXT
68
68
 
69
- ENV LIBRDKAFKA_VERSION=1.9.2
69
+ ENV LIBRDKAFKA_VERSION=2.8.2
70
70
 
71
71
  LABEL INTEGRATION_VERSION=${INTEGRATION_VERSION}
72
72
  # Used to ensure that new integrations will be public, see https://docs.github.com/en/packages/learn-github-packages/configuring-a-packages-access-control-and-visibility
@@ -1,13 +1,16 @@
1
- ARG BASE_PYTHON_IMAGE=debian:trixie-slim
2
- # debian:trixie-slim - Python 3.12
1
+ ARG ACCOUNT_ID=1
2
+ ARG BASE_PYTHON_IMAGE=${ACCOUNT_ID}.dkr.ecr.eu-west-1.amazonaws.com/echo/python:3.13
3
+
3
4
  FROM ${BASE_PYTHON_IMAGE}
4
5
 
5
6
  LABEL org.opencontainers.image.source=https://github.com/port-labs/ocean
6
7
 
7
- ENV LIBRDKAFKA_VERSION=1.9.2 \
8
+ ENV LIBRDKAFKA_VERSION=2.8.2 \
8
9
  PYTHONUNBUFFERED=1 \
9
10
  POETRY_VIRTUALENVS_IN_PROJECT=1 \
10
- PIP_ROOT_USER_ACTION=ignore
11
+ PIP_ROOT_USER_ACTION=ignore \
12
+ POETRY_VIRTUALENVS_PREFER_ACTIVE_PYTHON=true \
13
+ POETRY_PYTHON=/usr/local/bin/python3.13
11
14
 
12
15
  RUN apt-get update \
13
16
  && apt-get install -y \
@@ -1,10 +1,11 @@
1
- ARG BASE_PYTHON_IMAGE=debian:trixie-slim
2
- # debian:trixie-slim - Python 3.12
1
+ ARG ACCOUNT_ID=1
2
+ ARG BASE_PYTHON_IMAGE=${ACCOUNT_ID}.dkr.ecr.eu-west-1.amazonaws.com/echo/python:3.13
3
+
3
4
  FROM ${BASE_PYTHON_IMAGE}
4
5
 
5
6
  LABEL org.opencontainers.image.source=https://github.com/port-labs/ocean
6
7
 
7
- ENV LIBRDKAFKA_VERSION=1.9.2
8
+ ENV LIBRDKAFKA_VERSION=2.8.2
8
9
 
9
10
  ENV PIP_ROOT_USER_ACTION=ignore
10
11
 
@@ -0,0 +1,65 @@
1
+ ARG BASE_PYTHON_IMAGE=debian:trixie-slim
2
+ # debian:trixie-slim - Python 3.12
3
+ FROM ${BASE_PYTHON_IMAGE}
4
+
5
+ ARG OCEAN_USER_ID=999
6
+ RUN groupadd -r appgroup && useradd -r -g appgroup -m -u ${OCEAN_USER_ID} ocean
7
+
8
+ RUN mkdir -p /tmp/ocean
9
+
10
+
11
+ RUN apt-get update \
12
+ && apt-get install -y --no-install-recommends librdkafka-dev python3 \
13
+ && apt-get clean
14
+ RUN apt-get update \
15
+ && apt-get install -y \
16
+ --no-install-recommends \
17
+ wget \
18
+ g++ \
19
+ libssl-dev \
20
+ autoconf \
21
+ automake \
22
+ libtool \
23
+ curl \
24
+ librdkafka-dev \
25
+ python3 \
26
+ python3-pip \
27
+ python3-poetry \
28
+ build-essential\
29
+ jq \
30
+ git \
31
+ python3-venv \
32
+ acl \
33
+ && apt-get clean
34
+
35
+ ARG BUILD_CONTEXT
36
+ ARG PROMETHEUS_MULTIPROC_DIR=/tmp/ocean/prometheus/metrics
37
+ ARG STREAMING_LOCATION=/tmp/ocean/streaming
38
+
39
+ ENV PROMETHEUS_MULTIPROC_DIR=${PROMETHEUS_MULTIPROC_DIR}
40
+ ENV STREAMING_LOCATION=${STREAMING_LOCATION}
41
+ # Create /tmp/ocean directory and set permissions
42
+
43
+
44
+ RUN mkdir -p ${PROMETHEUS_MULTIPROC_DIR}
45
+ RUN mkdir -p ${STREAMING_LOCATION}
46
+
47
+ WORKDIR /app
48
+
49
+ COPY . .
50
+ RUN rm -rf .venv-docker ${BUILD_CONTEXT}/.venv-docker
51
+ RUN python3 -m venv .venv-docker
52
+ RUN python3 -m venv ${BUILD_CONTEXT}/.venv-docker
53
+
54
+
55
+ WORKDIR /app/${BUILD_CONTEXT}
56
+
57
+ WORKDIR /app
58
+ RUN chown -R ocean:appgroup /app && chmod -R 755 /app
59
+ RUN chown -R ocean:appgroup /app/${BUILD_CONTEXT} && chmod -R 755 /app/${BUILD_CONTEXT}
60
+ RUN chown -R ocean:appgroup /tmp/ocean && chmod -R 755 /tmp/ocean
61
+ # Add ocean user to ssl certs group
62
+ RUN setfacl -m u:ocean:rwX /etc/ssl/certs
63
+ USER ocean
64
+
65
+ ENTRYPOINT ["./integrations/_infra/entry_local.sh"]
@@ -11,6 +11,8 @@ define run_checks
11
11
  ruff check . || exit_code=$$?; \
12
12
  echo "Running black"; \
13
13
  black --check . || exit_code=$$?; \
14
+ echo "Running yamllint"; \
15
+ yamllint . || exit_code=$$?; \
14
16
  if [ $$exit_code -eq 1 ]; then \
15
17
  echo "\033[0;31mOne or more checks failed with exit code $$exit_code\033[0m"; \
16
18
  else \
@@ -46,7 +48,7 @@ endef
46
48
  install:
47
49
  $(call deactivate_virtualenv) && \
48
50
  $(call install_poetry) && \
49
- poetry install --with dev
51
+ poetry install --with dev --no-root
50
52
 
51
53
  install/local-core: install
52
54
  # NOTE: This is a temporary change that shouldn't be committed
@@ -0,0 +1,30 @@
1
+ # Running the Ocean image locally using vscode / Cursor
2
+
3
+ In order to run the local image of Ocean you need to follow these steps:
4
+
5
+ 1. Build the image:
6
+
7
+ ```bash
8
+ docker build -f integrations/_infra/Dockerfile.local --build-arg BUILD_CONTEXT=integrations/<integration_type> --platform linux/arm64 -t <my-local-image>:<local> .
9
+ ```
10
+
11
+ 2. Run the image
12
+ 1. `5678` is the debugpy port mentioned in the `entry_local.sh` file
13
+ 2. `8000` is the port of the Ocean FastAPI server
14
+ 3. the `-v` option mounts your local Ocean directory to the pod, allowing you not to constantly build the image.
15
+ 1. Make sure to run the command from the root directory of the Ocean repository.
16
+
17
+ ```bash
18
+ docker run --rm -it \
19
+ -v $(pwd):/app \
20
+ -p 5678:5678 \
21
+ -p 8000:8000 \
22
+ -e BUILD_CONTEXT=integrations/<integration_type> \
23
+ -e OCEAN__PORT__CLIENT_ID=<MY_CLIENT_ID> \
24
+ -e OCEAN__PORT__CLIENT_SECRET=<MY_CLIENT_SECRET> \
25
+ -e OCEAN__PORT__MY_OTHER_CONFIGURATION=<MY_OTHER_CONFIGURATION> \
26
+ <my-local-image>:<local>
27
+ ```
28
+
29
+ 3. In vscode/Cursor, run the `Attach to docker fake-integration integration` Running configuration from the `launch.json`.
30
+ 4. Have fun debugging!
@@ -0,0 +1,26 @@
1
+ #!/bin/bash
2
+ if [ -z "$BUILD_CONTEXT" ]; then
3
+ echo "BUILD_CONTEXT is not set"
4
+ exit 1
5
+ fi
6
+
7
+ if [ ! -d ".venv-docker" ]; then
8
+ /usr/bin/python3 -m venv .venv-docker
9
+ source .venv-docker/bin/activate
10
+ python -m pip install poetry
11
+ python -m poetry install
12
+ fi
13
+
14
+ cd $BUILD_CONTEXT
15
+
16
+ if [ ! -d ".venv-docker" ]; then
17
+ /usr/bin/python3 -m venv .venv-docker
18
+ source .venv-docker/bin/activate
19
+ python -m pip install poetry
20
+ python -m poetry install
21
+ fi
22
+ source .venv-docker/bin/activate
23
+ python -m pip install -e ../../
24
+
25
+ python -m pip install debugpy
26
+ python -m debugpy --listen 0.0.0.0:5678 --wait-for-client debug.py
@@ -1,5 +1,5 @@
1
1
  if test -e /usr/local/share/ca-certificates/cert.crt; then
2
- update-ca-certificates
2
+ sudo update-ca-certificates
3
3
  fi
4
4
 
5
- ocean sail
5
+ exec ocean sail
@@ -8,4 +8,9 @@ from .run import run # noqa: E402
8
8
  from .version import __integration_version__, __version__ # noqa: E402
9
9
 
10
10
 
11
- __all__ = ["Ocean", "run", "__version__", "__integration_version__"]
11
+ __all__ = [
12
+ "Ocean",
13
+ "run",
14
+ "__version__",
15
+ "__integration_version__",
16
+ ]
@@ -0,0 +1,25 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any, Optional
3
+
4
+ from port_ocean.core.models import CachingStorageMode
5
+
6
+
7
+ class CacheProvider(ABC):
8
+ """Base class for cache providers that defines the contract for all cache implementations."""
9
+
10
+ STORAGE_TYPE: CachingStorageMode
11
+
12
+ @abstractmethod
13
+ async def get(self, key: str) -> Optional[Any]:
14
+ """Get a value from the cache."""
15
+ pass
16
+
17
+ @abstractmethod
18
+ async def set(self, key: str, value: Any) -> None:
19
+ """Set a value in the cache."""
20
+ pass
21
+
22
+ @abstractmethod
23
+ async def clear(self) -> None:
24
+ """Clear all values from the cache."""
25
+ pass
@@ -0,0 +1,61 @@
1
+ import pickle
2
+ from pathlib import Path
3
+ from typing import Any, Optional
4
+
5
+ from port_ocean.cache.base import CacheProvider
6
+ from port_ocean.cache.errors import FailedToReadCacheError, FailedToWriteCacheError
7
+ from port_ocean.core.models import CachingStorageMode
8
+
9
+
10
+ class FailedToReadCacheFileError(FailedToReadCacheError):
11
+ pass
12
+
13
+
14
+ class FailedToWriteCacheFileError(FailedToWriteCacheError):
15
+ pass
16
+
17
+
18
+ class DiskCacheProvider(CacheProvider):
19
+ STORAGE_TYPE = CachingStorageMode.disk
20
+
21
+ def __init__(self, cache_dir: str | None = None) -> None:
22
+ if cache_dir is None:
23
+ cache_dir = "/tmp/ocean/.ocean_cache"
24
+ self._cache_dir = Path(cache_dir)
25
+ self._cache_dir.mkdir(parents=True, exist_ok=True)
26
+
27
+ def _get_cache_path(self, key: str) -> Path:
28
+ return self._cache_dir / f"{key}.pkl"
29
+
30
+ async def get(self, key: str) -> Optional[Any]:
31
+ cache_path = self._get_cache_path(key)
32
+ if not cache_path.exists():
33
+ return None
34
+
35
+ try:
36
+ with open(cache_path, "rb") as f:
37
+ return pickle.load(f)
38
+ except (pickle.PickleError, EOFError) as e:
39
+ raise FailedToReadCacheFileError(
40
+ f"Failed to read cache file: {cache_path}: {str(e)}"
41
+ )
42
+
43
+ async def set(self, key: str, value: Any) -> None:
44
+ cache_path = self._get_cache_path(key)
45
+ try:
46
+ with open(cache_path, "wb") as f:
47
+ pickle.dump(value, f)
48
+ except (pickle.PickleError, IOError) as e:
49
+ raise FailedToWriteCacheFileError(
50
+ f"Failed to write cache file: {cache_path}: {str(e)}"
51
+ )
52
+
53
+ async def clear(self) -> None:
54
+ try:
55
+ for cache_file in self._cache_dir.glob("*.pkl"):
56
+ try:
57
+ cache_file.unlink()
58
+ except OSError:
59
+ pass
60
+ except OSError:
61
+ pass
@@ -0,0 +1,10 @@
1
+ class CacheError(Exception):
2
+ pass
3
+
4
+
5
+ class FailedToReadCacheError(CacheError):
6
+ pass
7
+
8
+
9
+ class FailedToWriteCacheError(CacheError):
10
+ pass
@@ -0,0 +1,36 @@
1
+ from typing import Any, Optional
2
+ from port_ocean.cache.base import CacheProvider
3
+ from port_ocean.cache.errors import FailedToReadCacheError, FailedToWriteCacheError
4
+ from port_ocean.core.models import CachingStorageMode
5
+
6
+
7
+ class FailedToReadCacheMemoryError(FailedToReadCacheError):
8
+ pass
9
+
10
+
11
+ class FailedToWriteCacheMemoryError(FailedToWriteCacheError):
12
+ pass
13
+
14
+
15
+ class InMemoryCacheProvider(CacheProvider):
16
+ CACHE_KEY = "cache"
17
+ STORAGE_TYPE = CachingStorageMode.memory
18
+
19
+ def __init__(self, caching_storage: dict[str, Any] | None = None) -> None:
20
+ self._storage = caching_storage or {}
21
+ self._storage[self.CACHE_KEY] = self._storage.get(self.CACHE_KEY, {})
22
+
23
+ async def get(self, key: str) -> Optional[Any]:
24
+ try:
25
+ return self._storage.get(self.CACHE_KEY, {}).get(key)
26
+ except KeyError as e:
27
+ raise FailedToReadCacheMemoryError(f"Failed to read cache: {str(e)}")
28
+
29
+ async def set(self, key: str, value: Any) -> None:
30
+ try:
31
+ self._storage[self.CACHE_KEY][key] = value
32
+ except KeyError as e:
33
+ raise FailedToWriteCacheMemoryError(f"Failed to write cache: {str(e)}")
34
+
35
+ async def clear(self) -> None:
36
+ self._storage[self.CACHE_KEY].clear()
@@ -6,8 +6,8 @@
6
6
  "email": "Your address email <you@example.com>",
7
7
  "release_date": "{% now 'local' %}",
8
8
  "is_private_integration": true,
9
- "port_client_id": "you can find it using: https://docs.getport.io/build-your-software-catalog/custom-integration/api/#find-your-port-credentials",
10
- "port_client_secret": "you can find it using: https://docs.getport.io/build-your-software-catalog/custom-integration/api/#find-your-port-credentials",
9
+ "port_client_id": "you can find it using: https://docs.port.io/build-your-software-catalog/custom-integration/api/#find-your-port-credentials",
10
+ "port_client_secret": "you can find it using: https://docs.port.io/build-your-software-catalog/custom-integration/api/#find-your-port-credentials",
11
11
  "is_us_region": false,
12
12
  "_extensions": [
13
13
  "jinja2_time.TimeExtension",
@@ -2,6 +2,6 @@
2
2
 
3
3
  An integration used to import {{cookiecutter.integration_name}} resources into Port.
4
4
 
5
- #### Install & use the integration - [Integration documentation](https://docs.getport.io/build-your-software-catalog/sync-data-to-catalog/) *Replace this link with a link to this integration's documentation*
5
+ #### Install & use the integration - [Integration documentation](https://docs.port.io/build-your-software-catalog/sync-data-to-catalog/) *Replace this link with a link to this integration's documentation*
6
6
 
7
7
  #### Develop & improve the integration - [Ocean integration development documentation](https://ocean.getport.io/develop-an-integration/)
@@ -12,7 +12,7 @@ class OAuthClient(AuthClient):
12
12
  register_on_retry_callback(self.refresh_request_auth_creds)
13
13
 
14
14
  def is_oauth_enabled(self) -> bool:
15
- return ocean.app.load_external_oauth_access_token() is not None
15
+ return ocean.app.config.oauth_access_token_file_path is not None
16
16
 
17
17
  @property
18
18
  def external_access_token(self) -> str:
@@ -1,4 +1,5 @@
1
1
  import re
2
+ import jwt
2
3
  from typing import Any
3
4
 
4
5
  import httpx
@@ -6,7 +7,7 @@ from loguru import logger
6
7
  from pydantic import BaseModel, Field, PrivateAttr
7
8
 
8
9
  from port_ocean.clients.port.types import UserAgentType
9
- from port_ocean.clients.port.utils import handle_status_code
10
+ from port_ocean.clients.port.utils import handle_port_status_code
10
11
  from port_ocean.utils.misc import get_time
11
12
 
12
13
 
@@ -35,6 +36,7 @@ class PortAuthentication:
35
36
  integration_identifier: str,
36
37
  integration_type: str,
37
38
  integration_version: str,
39
+ ingest_url: str,
38
40
  ):
39
41
  self.client = client
40
42
  self.api_url = api_url
@@ -43,6 +45,7 @@ class PortAuthentication:
43
45
  self.integration_identifier = integration_identifier
44
46
  self.integration_type = integration_type
45
47
  self.integration_version = integration_version
48
+ self.ingest_url = ingest_url
46
49
  self.last_token_object: TokenResponse | None = None
47
50
 
48
51
  async def _get_token(self, client_id: str, client_secret: str) -> TokenResponse:
@@ -58,7 +61,7 @@ class PortAuthentication:
58
61
  json=credentials,
59
62
  extensions={"retryable": True},
60
63
  )
61
- handle_status_code(response)
64
+ handle_port_status_code(response)
62
65
  return TokenResponse(**response.json())
63
66
 
64
67
  def user_agent(self, user_agent_type: UserAgentType | None = None) -> str:
@@ -88,6 +91,24 @@ class PortAuthentication:
88
91
  )
89
92
  return self.last_token_object.full_token
90
93
 
94
+ async def is_machine_user(self) -> bool:
95
+ # Ensure self.last_token_object is populated
96
+ await self.token
97
+ if not self.last_token_object:
98
+ raise ValueError("No token found")
99
+
100
+ payload: dict[str, Any] = jwt.decode(
101
+ self.last_token_object.access_token, options={"verify_signature": False}
102
+ )
103
+ is_machine_user = payload.get("isMachine")
104
+ if is_machine_user is None:
105
+ logger.warning(
106
+ "Can not determine if the user is a machine user directly, checking for personal token usage instead"
107
+ )
108
+ return not payload.get("personalToken", True)
109
+
110
+ return is_machine_user
111
+
91
112
  @staticmethod
92
113
  def _is_personal_token(client_id: str) -> bool:
93
114
  email_regex = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"