Skip to content

Commit 5e6c418

Browse files
committed
feat: add command and args to environments
1 parent 1a9d3ca commit 5e6c418

9 files changed

Lines changed: 115 additions & 9 deletions

File tree

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""Add command and args to environment
2+
3+
Revision ID: 1ef98b967767
4+
Revises: 584598f3b769
5+
Create Date: 2024-08-25 21:05:02.158021
6+
7+
"""
8+
import sqlalchemy as sa
9+
from alembic import op
10+
from sqlalchemy.dialects import postgresql
11+
12+
# revision identifiers, used by Alembic.
13+
revision = '1ef98b967767'
14+
down_revision = '584598f3b769'
15+
branch_labels = None
16+
depends_on = None
17+
18+
19+
def upgrade() -> None:
20+
# ### commands auto generated by Alembic - please adjust! ###
21+
op.add_column('environments', sa.Column('args', sa.JSON().with_variant(postgresql.JSONB(astext_type=sa.Text()), 'postgresql'), nullable=True), schema='sessions')
22+
op.add_column('environments', sa.Column('command', sa.JSON().with_variant(postgresql.JSONB(astext_type=sa.Text()), 'postgresql'), nullable=True), schema='sessions')
23+
# ### end Alembic commands ###
24+
25+
26+
def downgrade() -> None:
27+
# ### commands auto generated by Alembic - please adjust! ###
28+
op.drop_column('environments', 'command', schema='sessions')
29+
op.drop_column('environments', 'args', schema='sessions')
30+
# ### end Alembic commands ###

components/renku_data_services/migrations/versions/584598f3b769_expand_and_separate_environments_from_.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""expand and separate environments from session launchers
22
33
Revision ID: 584598f3b769
4-
Revises: 17eea03f938e
4+
Revises: 9058bf0a1a12
55
Create Date: 2024-08-12 14:25:24.292285
66
77
"""
@@ -12,7 +12,7 @@
1212

1313
# revision identifiers, used by Alembic.
1414
revision = "584598f3b769"
15-
down_revision = "17eea03f938e"
15+
down_revision = "9058bf0a1a12"
1616
branch_labels = None
1717
depends_on = None
1818

components/renku_data_services/repositories/apispec_base.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ class Config:
1717

1818
@field_validator("connection_id", mode="before", check_fields=False)
1919
@classmethod
20-
def serialize_connection_id(cls, connection_id: str | ULID) -> str:
20+
def serialize_connection_id(cls, connection_id: str | ULID | None) -> str | None:
2121
"""Custom serializer that can handle ULIDs."""
22+
if connection_id is None:
23+
return None
2224
return str(connection_id)
2325

2426

components/renku_data_services/session/api.spec.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,10 @@ components:
274274
$ref: "#/components/schemas/EnvironmentMountDirectory"
275275
port:
276276
$ref: "#/components/schemas/EnvironmentPort"
277+
command:
278+
$ref: "#/components/schemas/EnvironmentCommand"
279+
args:
280+
$ref: "#/components/schemas/EnvironmentArgs"
277281
required:
278282
- id
279283
- name
@@ -359,6 +363,10 @@ components:
359363
- $ref: "#/components/schemas/EnvironmentPort"
360364
- default: 8080
361365
default: 8080
366+
command:
367+
$ref: "#/components/schemas/EnvironmentCommand"
368+
args:
369+
$ref: "#/components/schemas/EnvironmentArgs"
362370
required:
363371
- name
364372
- container_image
@@ -392,6 +400,10 @@ components:
392400
$ref: "#/components/schemas/EnvironmentMountDirectory"
393401
port:
394402
$ref: "#/components/schemas/EnvironmentPort"
403+
command:
404+
$ref: "#/components/schemas/EnvironmentCommand"
405+
args:
406+
$ref: "#/components/schemas/EnvironmentArgs"
395407
SessionLaunchersList:
396408
description: A list of Renku session launchers
397409
type: array
@@ -571,6 +583,18 @@ components:
571583
type: string
572584
description: The location where the persistent storage for the session will be mounted, usually it should be identical to or a parent of the working directory
573585
minLength: 1
586+
EnvironmentCommand:
587+
type: array
588+
items:
589+
type: string
590+
description: The command that will be run i.e. will overwrite the image Dockerfile ENTRYPOINT, equivalent to command in Kubernetes
591+
minLength: 1
592+
EnvironmentArgs:
593+
type: array
594+
items:
595+
type: string
596+
description: The arguments that will follow the command, i.e. will overwrite the image Dockerfile CMD, equivalent to args in Kubernetes
597+
minLength: 1
574598
ErrorResponse:
575599
type: object
576600
properties:

components/renku_data_services/session/apispec.py

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# generated by datamodel-codegen:
22
# filename: api.spec.yaml
3-
# timestamp: 2024-08-12T14:34:54+00:00
3+
# timestamp: 2024-08-25T21:01:41+00:00
44

55
from __future__ import annotations
66

@@ -35,7 +35,7 @@ class Environment(BaseAPISpec):
3535
description="ULID identifier",
3636
max_length=26,
3737
min_length=26,
38-
pattern="^[A-Z0-9]{26}$",
38+
pattern="^[0-7][0-9A-HJKMNP-TV-Z]{25}$",
3939
)
4040
name: str = Field(
4141
...,
@@ -84,6 +84,16 @@ class Environment(BaseAPISpec):
8484
gt=0,
8585
lt=65400,
8686
)
87+
command: Optional[List[str]] = Field(
88+
None,
89+
description="The command that will be run i.e. will overwrite the image Dockerfile ENTRYPOINT, equivalent to command in Kubernetes",
90+
min_length=1,
91+
)
92+
args: Optional[List[str]] = Field(
93+
None,
94+
description="The arguments that will follow the command, i.e. will overwrite the image Dockerfile CMD, equivalent to args in Kubernetes",
95+
min_length=1,
96+
)
8797

8898

8999
class EnvironmentGetInLauncher(Environment):
@@ -135,6 +145,16 @@ class EnvironmentPost(BaseAPISpec):
135145
gt=0,
136146
lt=65400,
137147
)
148+
command: Optional[List[str]] = Field(
149+
None,
150+
description="The command that will be run i.e. will overwrite the image Dockerfile ENTRYPOINT, equivalent to command in Kubernetes",
151+
min_length=1,
152+
)
153+
args: Optional[List[str]] = Field(
154+
None,
155+
description="The arguments that will follow the command, i.e. will overwrite the image Dockerfile CMD, equivalent to args in Kubernetes",
156+
min_length=1,
157+
)
138158

139159

140160
class EnvironmentPatch(BaseAPISpec):
@@ -183,6 +203,16 @@ class EnvironmentPatch(BaseAPISpec):
183203
gt=0,
184204
lt=65400,
185205
)
206+
command: Optional[List[str]] = Field(
207+
None,
208+
description="The command that will be run i.e. will overwrite the image Dockerfile ENTRYPOINT, equivalent to command in Kubernetes",
209+
min_length=1,
210+
)
211+
args: Optional[List[str]] = Field(
212+
None,
213+
description="The arguments that will follow the command, i.e. will overwrite the image Dockerfile CMD, equivalent to args in Kubernetes",
214+
min_length=1,
215+
)
186216

187217

188218
class SessionLauncher(BaseAPISpec):
@@ -191,14 +221,14 @@ class SessionLauncher(BaseAPISpec):
191221
description="ULID identifier",
192222
max_length=26,
193223
min_length=26,
194-
pattern="^[A-Z0-9]{26}$",
224+
pattern="^[0-7][0-9A-HJKMNP-TV-Z]{25}$",
195225
)
196226
project_id: str = Field(
197227
...,
198228
description="ULID identifier",
199229
max_length=26,
200230
min_length=26,
201-
pattern="^[A-Z0-9]{26}$",
231+
pattern="^[0-7][0-9A-HJKMNP-TV-Z]{25}$",
202232
)
203233
name: str = Field(
204234
...,
@@ -273,7 +303,7 @@ class SessionLauncherPost(BaseAPISpec):
273303
description="ULID identifier",
274304
max_length=26,
275305
min_length=26,
276-
pattern="^[A-Z0-9]{26}$",
306+
pattern="^[0-7][0-9A-HJKMNP-TV-Z]{25}$",
277307
)
278308
description: Optional[str] = Field(
279309
None, description="A description for the resource", max_length=500

components/renku_data_services/session/blueprints.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ async def _post(_: Request, user: base_models.APIUser, body: apispec.Environment
5959
uid=body.uid,
6060
gid=body.gid,
6161
environment_kind=models.EnvironmentKind.GLOBAL,
62+
command=body.command,
63+
args=body.args,
6264
)
6365
environment = await self.session_repo.insert_environment(user=user, new_environment=unsaved_environment)
6466
return json(apispec.Environment.model_validate(environment).model_dump(exclude_none=True, mode="json"), 201)
@@ -145,6 +147,8 @@ async def _post(_: Request, user: base_models.APIUser, body: apispec.SessionLaun
145147
uid=body.environment.uid,
146148
gid=body.environment.gid,
147149
environment_kind=models.EnvironmentKind(body.environment.environment_kind.value),
150+
args=body.environment.args,
151+
command=body.environment.command,
148152
)
149153
new_launcher = models.UnsavedSessionLauncher(
150154
project_id=body.project_id,

components/renku_data_services/session/db.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ async def __insert_environment(
7979
uid=new_environment.uid,
8080
gid=new_environment.gid,
8181
environment_kind=new_environment.environment_kind,
82+
command=new_environment.command,
83+
args=new_environment.args,
8284
)
8385

8486
session.add(environment)
@@ -128,6 +130,8 @@ async def __update_environment(
128130
"mount_directory",
129131
"uid",
130132
"gid",
133+
"args",
134+
"command",
131135
]:
132136
setattr(environment, key, value)
133137

@@ -397,6 +401,8 @@ async def update_launcher(
397401
uid=env_payload_valid.uid,
398402
gid=env_payload_valid.gid,
399403
environment_kind=models.EnvironmentKind(env_payload_valid.environment_kind.value),
404+
args=env_payload_valid.args,
405+
command=env_payload_valid.command,
400406
)
401407
new_env = await self.__insert_environment(user, session, new_unsaved_env)
402408
launcher.environment = new_env
@@ -414,6 +420,8 @@ async def update_launcher(
414420
"mount_directory",
415421
"uid",
416422
"gid",
423+
"args",
424+
"command",
417425
]:
418426
setattr(launcher.environment, key, val)
419427

components/renku_data_services/session/models.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ class BaseEnvironment:
3232
uid: int
3333
gid: int
3434
environment_kind: EnvironmentKind
35+
args: list[str] | None = None
36+
command: list[str] | None = None
3537

3638

3739
@dataclass(kw_only=True, frozen=True, eq=True)

components/renku_data_services/session/orm.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
from datetime import datetime
44
from pathlib import PurePosixPath
55

6-
from sqlalchemy import DateTime, MetaData, String
6+
from sqlalchemy import JSON, DateTime, MetaData, String
7+
from sqlalchemy.dialects.postgresql import JSONB
78
from sqlalchemy.orm import DeclarativeBase, Mapped, MappedAsDataclass, mapped_column, relationship
89
from sqlalchemy.schema import ForeignKey
910
from ulid import ULID
@@ -13,6 +14,7 @@
1314
from renku_data_services.session import models
1415

1516
metadata_obj = MetaData(schema="sessions") # Has to match alembic ini section name
17+
JSONVariant = JSON().with_variant(JSONB(), "postgresql")
1618

1719

1820
class BaseORM(MappedAsDataclass, DeclarativeBase):
@@ -53,6 +55,8 @@ class EnvironmentORM(BaseORM):
5355
uid: Mapped[int] = mapped_column("uid")
5456
gid: Mapped[int] = mapped_column("gid")
5557
environment_kind: Mapped[models.EnvironmentKind] = mapped_column("environment_kind")
58+
args: Mapped[list[str] | None] = mapped_column("args", JSONVariant, nullable=True)
59+
command: Mapped[list[str] | None] = mapped_column("command", JSONVariant, nullable=True)
5660

5761
def dump(self) -> models.Environment:
5862
"""Create a session environment model from the EnvironmentORM."""
@@ -70,6 +74,8 @@ def dump(self) -> models.Environment:
7074
mount_directory=PurePosixPath(self.mount_directory),
7175
working_directory=PurePosixPath(self.working_directory),
7276
port=self.port,
77+
args=self.args,
78+
command=self.command,
7379
)
7480

7581

0 commit comments

Comments
 (0)