Skip to content

Commit

Permalink
[Framework] Port 8572 ocean startup when saas (#697)
Browse files Browse the repository at this point in the history
# Description

What - handle startup when running as saas

## Type of change

Please leave one option from the following and delete the rest:

- [ ] Bug fix (non-breaking change which fixes an issue)
- [X] New feature (non-breaking change which adds functionality)
- [ ] New Integration (non-breaking change which adds a new integration)
- [ ] Breaking change (fix or feature that would cause existing
functionality to not work as expected)
- [ ] Non-breaking change (fix of existing functionality that will not
change current behavior)
- [ ] Documentation (added/updated documentation)

## Screenshots

Include screenshots from your environment showing how the resources of
the integration will look.

## API Documentation

Provide links to the API documentation used for this integration.
  • Loading branch information
omby8888 authored Jun 19, 2024
1 parent f1ed5c0 commit 935071b
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 7 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,22 @@ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

<!-- towncrier release notes start -->

## 0.9.0 (2024-06-19)


### Features

- Added validation of whether the integration can run in the desired runtime


## 0.8.0 (2024-06-16)


### Improvements

- Add search relation support (Allow to to run a search query to find the relation to the entity as part of the mapping)


## 0.7.1 (2024-06-13)


Expand Down
8 changes: 7 additions & 1 deletion port_ocean/cli/commands/sail.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,10 @@ def sail(
console.print("Setting event listener to Once")
override["event_listener"] = {"type": "ONCE"}

run(path, log_level, port, initialize_port_resources, override)
run(
path,
log_level,
port,
initialize_port_resources=initialize_port_resources,
config_override=override,
)
22 changes: 20 additions & 2 deletions port_ocean/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

from port_ocean.config.base import BaseOceanSettings, BaseOceanModel
from port_ocean.core.event_listener import EventListenerSettingsType
from port_ocean.utils.misc import get_integration_name
from port_ocean.core.models import Runtime
from port_ocean.utils.misc import get_integration_name, get_spec_file
from pydantic import Extra, AnyHttpUrl, parse_obj_as
from pydantic.class_validators import root_validator
from pydantic.class_validators import root_validator, validator
from pydantic.env_settings import InitSettingsSource, EnvSettingsSource, BaseSettings
from pydantic.fields import Field
from pydantic.main import BaseModel
Expand Down Expand Up @@ -69,3 +70,20 @@ class IntegrationConfiguration(BaseOceanSettings, extra=Extra.allow):
event_listener: EventListenerSettingsType
# If an identifier or type is not provided, it will be generated based on the integration name
integration: IntegrationSettings = IntegrationSettings(type="", identifier="")
runtime: Runtime = "OnPrem"

@validator("runtime")
def validate_runtime(cls, runtime: Literal["OnPrem", "Saas"]) -> Runtime:
if runtime == "Saas":
spec = get_spec_file()
if spec is None:
raise ValueError(
"Could not determine whether it's safe to run "
"the integration due to not found spec.yaml."
)

saas_config = spec.get("saas")
if saas_config and not saas_config["enabled"]:
raise ValueError("This integration can't be ran as Saas")

return runtime
5 changes: 4 additions & 1 deletion port_ocean/core/models.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from dataclasses import dataclass, field
from typing import Any
from typing import Any, Literal

from pydantic import BaseModel
from pydantic.fields import Field


Runtime = Literal["OnPrem", "Saas"]


class Entity(BaseModel):
identifier: Any
blueprint: Any
Expand Down
21 changes: 19 additions & 2 deletions port_ocean/core/utils.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import asyncio
from typing import Iterable, Any, TypeVar, Callable, Awaitable

from loguru import logger
from pydantic import parse_obj_as, ValidationError

from port_ocean.core.models import Entity
from port_ocean.clients.port.client import PortClient
from port_ocean.core.models import Entity, Runtime
from port_ocean.core.models import EntityPortDiff
from port_ocean.core.ocean_types import RAW_RESULT
from port_ocean.exceptions.core import RawObjectValidationException
from port_ocean.exceptions.core import (
RawObjectValidationException,
IntegrationRuntimeException,
)

T = TypeVar("T", bound=tuple[list[Any], ...])

Expand All @@ -29,6 +34,18 @@ def is_same_entity(first_entity: Entity, second_entity: Entity) -> bool:
)


async def validate_integration_runtime(
port_client: PortClient, requested_runtime: Runtime
) -> None:
logger.debug("Validating integration runtime")
current_integration = await port_client.get_current_integration(should_raise=False)
current_runtime = current_integration.get("installationType", "OnPrem")
if current_integration and current_runtime != requested_runtime:
raise IntegrationRuntimeException(
f"Invalid Runtime! Requested to run existing {current_runtime} integration in {requested_runtime} runtime."
)


Q = TypeVar("Q")


Expand Down
4 changes: 4 additions & 0 deletions port_ocean/exceptions/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,7 @@ class IntegrationAlreadyStartedException(BaseOceanException):

class IntegrationNotStartedException(BaseOceanException):
pass


class IntegrationRuntimeException(BaseOceanException):
pass
7 changes: 7 additions & 0 deletions port_ocean/run.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import asyncio
from inspect import getmembers
from typing import Dict, Any, Type

Expand All @@ -8,6 +9,7 @@
from port_ocean.config.dynamic import default_config_factory
from port_ocean.config.settings import ApplicationSettings, LogLevelType
from port_ocean.core.defaults.initialize import initialize_defaults
from port_ocean.core.utils import validate_integration_runtime
from port_ocean.log.logger_setup import setup_logger
from port_ocean.ocean import Ocean
from port_ocean.utils.misc import get_spec_file, load_module
Expand Down Expand Up @@ -45,6 +47,11 @@ def run(
"app", default_app
)

# Validate that the current integration's runtime matches the execution parameters
asyncio.get_event_loop().run_until_complete(
validate_integration_runtime(app.port_client, app.config.runtime)
)

# Override config with arguments
if initialize_port_resources is not None:
app.config.initialize_port_resources = initialize_port_resources
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "port-ocean"
version = "0.8.0"
version = "0.9.0"
description = "Port Ocean is a CLI tool for managing your Port projects."
readme = "README.md"
homepage = "https://app.getport.io"
Expand Down

0 comments on commit 935071b

Please sign in to comment.