Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Expose additional ports for sessions internally #2084

Merged
merged 1 commit into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion backend/capellacollab/sessions/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from capellacollab.tools import exceptions as tools_exceptions
from capellacollab.tools import injectables as tools_injectables
from capellacollab.tools import models as tools_models
from capellacollab.tools import util as tools_util
from capellacollab.users import crud as users_crud
from capellacollab.users import exceptions as users_exceptions
from capellacollab.users import injectables as users_injectables
Expand Down Expand Up @@ -205,7 +206,7 @@ async def request_session(
tool=tool,
environment=environment,
init_environment=init_environment,
ports=connection_method.ports.model_dump(),
ports=tools_util.resolve_tool_ports(connection_method.ports),
volumes=volumes,
init_volumes=init_volumes,
annotations=annotations,
Expand Down
23 changes: 23 additions & 0 deletions backend/capellacollab/tools/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,29 @@ class SessionPorts(core_pydantic.BaseModel):
default=9118,
description="Port of the metrics endpoint in the container.",
)
additional: dict[str, int] = pydantic.Field(
default={},
description="Additional ports in a identifier/port mapping.",
)

@pydantic.model_validator(mode="after")
def check_additional_ports(self) -> t.Self:
if len(self.additional) != len(set(self.additional.values())):
raise ValueError("All additional ports must be unique.")
for identifier, port in self.additional.items():
if identifier in ("http", "metrics"):
raise ValueError(
f"Identifier '{identifier}' is reserved and can't be used as additional identifier."
)
if port in (self.model_dump().values()):
raise ValueError(
f"Port '{port}' of the identifier '{identifier}' is already in use."
)
if port == 80:
raise ValueError(
f"Port '{port}' is reserved and can't be used as additional port."
)
return self


class RDPPorts(SessionPorts):
Expand Down
15 changes: 15 additions & 0 deletions backend/capellacollab/tools/util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# SPDX-FileCopyrightText: Copyright DB InfraGO AG and contributors
# SPDX-License-Identifier: Apache-2.0

import typing as t

if t.TYPE_CHECKING:
from . import models


def resolve_tool_ports(ports: "models.SessionPorts") -> dict[str, int]:
model = ports.model_dump()
additional = model["additional"]
del model["additional"]

return model | additional
56 changes: 56 additions & 0 deletions backend/tests/tools/test_tools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# SPDX-FileCopyrightText: Copyright DB InfraGO AG and contributors
# SPDX-License-Identifier: Apache-2.0

import pytest

from capellacollab.tools import models as tools_models
from capellacollab.tools import util as tools_util


def test_additional_ports_are_unique():
with pytest.raises(ValueError):
tools_models.HTTPPorts(
metrics=9118,
http=8080,
additional={"restapi": 5007, "restapi2": 5007},
)


def test_additional_ports_not_reserved_keys():
with pytest.raises(ValueError):
tools_models.HTTPPorts(
metrics=9118,
http=8080,
additional={"http": 5007},
)


def test_additional_port_already_in_use():
with pytest.raises(ValueError):
tools_models.HTTPPorts(
metrics=9118,
http=8080,
additional={"restapi": 8080},
)


def test_additional_ports_reserved_port():
with pytest.raises(ValueError):
tools_models.HTTPPorts(
metrics=9118,
http=8080,
additional={"test": 80},
)


def test_environment_resolution():
ports = tools_models.HTTPPorts(
metrics=9118,
http=8080,
additional={"restapi": 5007},
)
assert tools_util.resolve_tool_ports(ports) == {
"metrics": 9118,
"http": 8080,
"restapi": 5007,
}
4 changes: 4 additions & 0 deletions frontend/src/app/openapi/model/http-ports-input.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions frontend/src/app/openapi/model/http-ports-output.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions frontend/src/app/openapi/model/rdp-ports-input.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions frontend/src/app/openapi/model/rdp-ports-output.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions frontend/src/app/openapi/model/session-ports.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/src/storybook/tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const mockHttpConnectionMethod: Readonly<HTTPConnectionMethodOutput> = {
ports: {
http: 0,
metrics: 0,
additional: {},
},
environment: {},
redirect_url: 'https://example.com',
Expand Down
Loading