Skip to content

Commit ea658b8

Browse files
committed
chore: remove the use of RenkuUserServer2
This only removes the large class from the new sessions endpoints that talk to the new amalthea.
1 parent 2a1ff6f commit ea658b8

File tree

5 files changed

+105
-85
lines changed

5 files changed

+105
-85
lines changed

components/renku_data_services/notebooks/api/amalthea_patches/git_proxy.py

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,48 +6,53 @@
66

77
from kubernetes import client
88

9+
from renku_data_services.base_models.core import AnonymousAPIUser, AuthenticatedAPIUser
910
from renku_data_services.notebooks.api.amalthea_patches.utils import get_certificates_volume_mounts
11+
from renku_data_services.notebooks.api.classes.repository import GitProvider, Repository
12+
from renku_data_services.notebooks.config import _NotebooksConfig
1013

1114
if TYPE_CHECKING:
1215
# NOTE: If these are directly imported then you get circular imports.
1316
from renku_data_services.notebooks.api.classes.server import UserServer
1417

1518

16-
async def main_container(server: "UserServer") -> client.V1Container | None:
19+
async def main_container(
20+
user: AnonymousAPIUser | AuthenticatedAPIUser,
21+
config: _NotebooksConfig,
22+
repositories: list[Repository],
23+
git_providers: list[GitProvider],
24+
) -> client.V1Container | None:
1725
"""The patch that adds the git proxy container to a session statefulset."""
18-
repositories = await server.repositories()
19-
if not server.user.is_authenticated or not repositories:
26+
if not user.is_authenticated or not repositories or user.access_token is None or user.refresh_token is None:
2027
return None
2128

2229
etc_cert_volume_mount = get_certificates_volume_mounts(
23-
server.config,
30+
config,
2431
custom_certs=False,
2532
etc_certs=True,
2633
read_only_etc_certs=True,
2734
)
2835

2936
prefix = "GIT_PROXY_"
30-
git_providers = await server.git_providers()
31-
repositories = await server.repositories()
3237
env = [
33-
client.V1EnvVar(name=f"{prefix}PORT", value=str(server.config.sessions.git_proxy.port)),
34-
client.V1EnvVar(name=f"{prefix}HEALTH_PORT", value=str(server.config.sessions.git_proxy.health_port)),
38+
client.V1EnvVar(name=f"{prefix}PORT", value=str(config.sessions.git_proxy.port)),
39+
client.V1EnvVar(name=f"{prefix}HEALTH_PORT", value=str(config.sessions.git_proxy.health_port)),
3540
client.V1EnvVar(
3641
name=f"{prefix}ANONYMOUS_SESSION",
37-
value="false" if server.user.is_authenticated else "true",
42+
value="false" if user.is_authenticated else "true",
3843
),
39-
client.V1EnvVar(name=f"{prefix}RENKU_ACCESS_TOKEN", value=str(server.user.access_token)),
40-
client.V1EnvVar(name=f"{prefix}RENKU_REFRESH_TOKEN", value=str(server.user.refresh_token)),
41-
client.V1EnvVar(name=f"{prefix}RENKU_REALM", value=server.config.keycloak_realm),
44+
client.V1EnvVar(name=f"{prefix}RENKU_ACCESS_TOKEN", value=str(user.access_token)),
45+
client.V1EnvVar(name=f"{prefix}RENKU_REFRESH_TOKEN", value=str(user.refresh_token)),
46+
client.V1EnvVar(name=f"{prefix}RENKU_REALM", value=config.keycloak_realm),
4247
client.V1EnvVar(
4348
name=f"{prefix}RENKU_CLIENT_ID",
44-
value=str(server.config.sessions.git_proxy.renku_client_id),
49+
value=str(config.sessions.git_proxy.renku_client_id),
4550
),
4651
client.V1EnvVar(
4752
name=f"{prefix}RENKU_CLIENT_SECRET",
48-
value=str(server.config.sessions.git_proxy.renku_client_secret),
53+
value=str(config.sessions.git_proxy.renku_client_secret),
4954
),
50-
client.V1EnvVar(name=f"{prefix}RENKU_URL", value="https://" + server.config.sessions.ingress.host),
55+
client.V1EnvVar(name=f"{prefix}RENKU_URL", value="https://" + config.sessions.ingress.host),
5156
client.V1EnvVar(
5257
name=f"{prefix}REPOSITORIES",
5358
value=json.dumps([asdict(repo) for repo in repositories]),
@@ -60,7 +65,7 @@ async def main_container(server: "UserServer") -> client.V1Container | None:
6065
),
6166
]
6267
container = client.V1Container(
63-
image=server.config.sessions.git_proxy.image,
68+
image=config.sessions.git_proxy.image,
6469
security_context={
6570
"fsGroup": 100,
6671
"runAsGroup": 1000,
@@ -73,14 +78,14 @@ async def main_container(server: "UserServer") -> client.V1Container | None:
7378
liveness_probe={
7479
"httpGet": {
7580
"path": "/health",
76-
"port": server.config.sessions.git_proxy.health_port,
81+
"port": config.sessions.git_proxy.health_port,
7782
},
7883
"initialDelaySeconds": 3,
7984
},
8085
readiness_probe={
8186
"httpGet": {
8287
"path": "/health",
83-
"port": server.config.sessions.git_proxy.health_port,
88+
"port": config.sessions.git_proxy.health_port,
8489
},
8590
"initialDelaySeconds": 3,
8691
},
@@ -98,7 +103,8 @@ async def main(server: "UserServer") -> list[dict[str, Any]]:
98103
if not server.user.is_authenticated or not repositories:
99104
return []
100105

101-
container = await main_container(server)
106+
git_providers = await server.git_providers()
107+
container = await main_container(server.user, server.config, repositories, git_providers)
102108
if not container:
103109
return []
104110

components/renku_data_services/notebooks/api/amalthea_patches/init_containers.py

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,72 +3,78 @@
33
import json
44
import os
55
from dataclasses import asdict
6-
from pathlib import Path
6+
from pathlib import Path, PurePosixPath
77
from typing import TYPE_CHECKING, Any
88

99
from kubernetes import client
1010

11+
from renku_data_services.base_models.core import AnonymousAPIUser, AuthenticatedAPIUser
1112
from renku_data_services.notebooks.api.amalthea_patches.utils import get_certificates_volume_mounts
13+
from renku_data_services.notebooks.api.classes.repository import GitProvider, Repository
1214
from renku_data_services.notebooks.config import _NotebooksConfig
1315

1416
if TYPE_CHECKING:
1517
# NOTE: If these are directly imported then you get circular imports.
1618
from renku_data_services.notebooks.api.classes.server import UserServer
1719

1820

19-
async def git_clone_container_v2(server: "UserServer") -> dict[str, Any] | None:
21+
async def git_clone_container_v2(
22+
user: AuthenticatedAPIUser | AnonymousAPIUser,
23+
config: _NotebooksConfig,
24+
repositories: list[Repository],
25+
git_providers: list[GitProvider],
26+
workspace_mount_path: PurePosixPath,
27+
work_dir: PurePosixPath,
28+
lfs_auto_fetch: bool = False,
29+
) -> dict[str, Any] | None:
2030
"""Returns the specification for the container that clones the user's repositories for new operator."""
2131
amalthea_session_work_volume: str = "amalthea-volume"
22-
repositories = await server.repositories()
2332
if not repositories:
2433
return None
2534

2635
etc_cert_volume_mount = get_certificates_volume_mounts(
27-
server.config,
36+
config,
2837
custom_certs=False,
2938
etc_certs=True,
3039
read_only_etc_certs=True,
3140
)
3241

33-
user_is_anonymous = not server.user.is_authenticated
42+
user_is_anonymous = isinstance(user, AnonymousAPIUser)
3443
prefix = "GIT_CLONE_"
3544
env = [
36-
{
37-
"name": f"{prefix}WORKSPACE_MOUNT_PATH",
38-
"value": server.workspace_mount_path.as_posix(),
39-
},
45+
{"name": f"{prefix}WORKSPACE_MOUNT_PATH", "value": workspace_mount_path.as_posix()},
4046
{
4147
"name": f"{prefix}MOUNT_PATH",
42-
"value": server.work_dir.as_posix(),
48+
"value": work_dir.as_posix(),
4349
},
4450
{
4551
"name": f"{prefix}LFS_AUTO_FETCH",
46-
"value": "1" if server.server_options.lfs_auto_fetch else "0",
52+
"value": "1" if lfs_auto_fetch else "0",
4753
},
4854
{
4955
"name": f"{prefix}USER__USERNAME",
50-
"value": server.user.email,
56+
"value": user.email,
5157
},
5258
{
5359
"name": f"{prefix}USER__RENKU_TOKEN",
54-
"value": str(server.user.access_token),
60+
"value": str(user.access_token),
5561
},
5662
{"name": f"{prefix}IS_GIT_PROXY_ENABLED", "value": "0" if user_is_anonymous else "1"},
5763
{
5864
"name": f"{prefix}SENTRY__ENABLED",
59-
"value": str(server.config.sessions.git_clone.sentry.enabled).lower(),
65+
"value": str(config.sessions.git_clone.sentry.enabled).lower(),
6066
},
6167
{
6268
"name": f"{prefix}SENTRY__DSN",
63-
"value": server.config.sessions.git_clone.sentry.dsn,
69+
"value": config.sessions.git_clone.sentry.dsn,
6470
},
6571
{
6672
"name": f"{prefix}SENTRY__ENVIRONMENT",
67-
"value": server.config.sessions.git_clone.sentry.env,
73+
"value": config.sessions.git_clone.sentry.env,
6874
},
6975
{
7076
"name": f"{prefix}SENTRY__SAMPLE_RATE",
71-
"value": str(server.config.sessions.git_clone.sentry.sample_rate),
77+
"value": str(config.sessions.git_clone.sentry.sample_rate),
7278
},
7379
{"name": "SENTRY_RELEASE", "value": os.environ.get("SENTRY_RELEASE")},
7480
{
@@ -80,10 +86,10 @@ async def git_clone_container_v2(server: "UserServer") -> dict[str, Any] | None:
8086
"value": str(Path(etc_cert_volume_mount[0]["mountPath"]) / "ca-certificates.crt"),
8187
},
8288
]
83-
if server.user.is_authenticated:
84-
if server.user.email:
89+
if user.is_authenticated:
90+
if user.email:
8591
env.append(
86-
{"name": f"{prefix}USER__EMAIL", "value": server.user.email},
92+
{"name": f"{prefix}USER__EMAIL", "value": user.email},
8793
)
8894
full_name = server.user.get_full_name()
8995
if full_name:
@@ -105,7 +111,8 @@ async def git_clone_container_v2(server: "UserServer") -> dict[str, Any] | None:
105111
)
106112

107113
# Set up git providers
108-
required_git_providers = await server.required_git_providers()
114+
required_provider_ids: set[str] = set(r.provider for r in repositories if r.provider)
115+
required_git_providers = [p for p in git_providers if p.id in required_provider_ids]
109116
for idx, provider in enumerate(required_git_providers):
110117
obj_env = f"{prefix}GIT_PROVIDERS_{idx}_"
111118
data = dict(id=provider.id, access_token_url=provider.access_token_url)
@@ -117,7 +124,7 @@ async def git_clone_container_v2(server: "UserServer") -> dict[str, Any] | None:
117124
)
118125

119126
return {
120-
"image": server.config.sessions.git_clone.image,
127+
"image": config.sessions.git_clone.image,
121128
"name": "git-clone",
122129
"resources": {
123130
"requests": {
@@ -134,7 +141,7 @@ async def git_clone_container_v2(server: "UserServer") -> dict[str, Any] | None:
134141
},
135142
"volumeMounts": [
136143
{
137-
"mountPath": server.workspace_mount_path.as_posix(),
144+
"mountPath": workspace_mount_path.as_posix(),
138145
"name": amalthea_session_work_volume,
139146
},
140147
*etc_cert_volume_mount,

components/renku_data_services/notebooks/blueprints.py

Lines changed: 23 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -798,13 +798,11 @@ async def _handler(
798798
image = environment.container_image
799799
default_resource_class = await self.rp_repo.get_default_resource_class()
800800
if default_resource_class.id is None:
801-
raise errors.ProgrammingError(message="The default reosurce class has to have an ID", quiet=True)
801+
raise errors.ProgrammingError(message="The default resource class has to have an ID", quiet=True)
802802
resource_class_id = body.resource_class_id or default_resource_class.id
803-
parsed_server_options = await self.nb_config.crc_validator.validate_class_storage(
804-
user, resource_class_id, body.disk_storage
805-
)
803+
await self.nb_config.crc_validator.validate_class_storage(user, resource_class_id, body.disk_storage)
806804
work_dir = environment.working_directory
807-
user_secrets: K8sUserSecrets | None = None
805+
# user_secrets: K8sUserSecrets | None = None
808806
# if body.user_secrets:
809807
# user_secrets = K8sUserSecrets(
810808
# name=server_name,
@@ -847,33 +845,13 @@ async def _handler(
847845
quiet=True,
848846
)
849847
cloud_storage[csr_id] = csr
850-
# repositories = [Repository(i.url, branch=i.branch, commit_sha=i.commit_sha) for i in body.repositories]
851848
repositories = [Repository(url=i) for i in project.repositories]
852849
secrets_to_create: list[V1Secret] = []
853-
server = Renku2UserServer(
854-
user=user,
855-
image=image,
856-
project_id=str(launcher.project_id),
857-
launcher_id=body.launcher_id,
858-
server_name=server_name,
859-
server_options=parsed_server_options,
860-
environment_variables={},
861-
user_secrets=user_secrets,
862-
cloudstorage=[i for i in cloud_storage.values()],
863-
k8s_client=self.nb_config.k8s_v2_client,
864-
workspace_mount_path=work_dir,
865-
work_dir=work_dir,
866-
repositories=repositories,
867-
config=self.nb_config,
868-
using_default_image=self.nb_config.sessions.default_image == image,
869-
is_image_private=False,
870-
internal_gitlab_user=internal_gitlab_user,
871-
)
872-
# Generate the cloud storage secrets
850+
# Generate the cloud starge secrets
873851
data_sources: list[DataSource] = []
874852
for ics, cs in enumerate(cloud_storage.values()):
875853
secret_name = f"{server_name}-ds-{ics}"
876-
secrets_to_create.append(cs.secret(secret_name, server.k8s_client.preferred_namespace))
854+
secrets_to_create.append(cs.secret(secret_name, self.nb_config.k8s_client.preferred_namespace))
877855
data_sources.append(
878856
DataSource(mountPath=cs.mount_folder, secretRef=SecretRefWhole(name=secret_name, adopt=True))
879857
)
@@ -890,17 +868,26 @@ async def _handler(
890868
),
891869
)
892870
)
893-
git_clone = await init_containers.git_clone_container_v2(server)
871+
git_providers = await self.nb_config.git_provider_helper.get_providers(user)
872+
git_clone = await init_containers.git_clone_container_v2(
873+
user,
874+
self.nb_config,
875+
repositories,
876+
git_providers,
877+
launcher.environment.mount_directory,
878+
launcher.environment.working_directory,
879+
)
894880
if git_clone is not None:
895881
session_init_containers.append(InitContainer.model_validate(git_clone))
896882
extra_containers: list[ExtraContainer] = []
897-
git_proxy_container = await git_proxy.main_container(server)
883+
git_proxy_container = await git_proxy.main_container(user, self.nb_config, repositories, git_providers)
898884
if git_proxy_container is not None:
899885
extra_containers.append(
900886
ExtraContainer.model_validate(self.nb_config.k8s_v2_client.sanitize(git_proxy_container))
901887
)
902888

903-
parsed_server_url = urlparse(server.server_url)
889+
base_server_url = self.nb_config.sessions.ingress.base_url(server_name)
890+
base_server_path = self.nb_config.sessions.ingress.base_path(server_name)
904891
annotations: dict[str, str] = {
905892
"renku.io/project_id": str(launcher.project_id),
906893
"renku.io/launcher_id": body.launcher_id,
@@ -913,7 +900,7 @@ async def _handler(
913900
hibernated=False,
914901
session=Session(
915902
image=image,
916-
urlPath=parsed_server_url.path,
903+
urlPath=base_server_path,
917904
port=environment.port,
918905
storage=Storage(
919906
className=self.nb_config.sessions.storage.pvs_storage_class,
@@ -929,8 +916,8 @@ async def _handler(
929916
args=environment.args,
930917
shmSize="1G",
931918
env=[
932-
SessionEnvItem(name="RENKU_BASE_URL_PATH", value=parsed_server_url.path),
933-
SessionEnvItem(name="RENKU_BASE_URL", value=server.server_url),
919+
SessionEnvItem(name="RENKU_BASE_URL_PATH", value=base_server_url),
920+
SessionEnvItem(name="RENKU_BASE_URL", value=base_server_path),
934921
],
935922
),
936923
ingress=Ingress(
@@ -966,7 +953,7 @@ async def _handler(
966953
dataSources=data_sources,
967954
),
968955
)
969-
parsed_proxy_url = urlparse(urljoin(server.server_url + "/", "oauth2"))
956+
parsed_proxy_url = urlparse(urljoin(base_server_url + "/", "oauth2"))
970957
secret_data = {}
971958
if isinstance(user, AuthenticatedAPIUser):
972959
secret_data["auth"] = dumps(
@@ -976,8 +963,8 @@ async def _handler(
976963
"oidc_issuer_url": self.nb_config.sessions.oidc.issuer_url,
977964
"session_cookie_minimal": True,
978965
"skip_provider_button": True,
979-
"redirect_url": urljoin(server.server_url + "/", "oauth2/callback"),
980-
"cookie_path": parsed_server_url.path,
966+
"redirect_url": urljoin(base_server_url + "/", "oauth2/callback"),
967+
"cookie_path": base_server_path,
981968
"proxy_prefix": parsed_proxy_url.path,
982969
"authenticated_emails_file": "/authorized_emails/authorized_emails",
983970
"client_secret": self.nb_config.sessions.oidc.client_secret,

components/renku_data_services/notebooks/config/dynamic.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from enum import Enum
77
from io import StringIO
88
from typing import Any, ClassVar, Optional, Self, Union
9+
from urllib.parse import urlunparse
910

1011
import yaml
1112

@@ -257,6 +258,13 @@ def from_env(cls) -> Self:
257258
annotations=yaml.safe_load(StringIO(os.environ.get("NB_SESSIONS__INGRESS__ANNOTATIONS", "{}"))),
258259
)
259260

261+
def base_path(self, server_name: str) -> str:
262+
return f"/sessions/{server_name}"
263+
264+
def base_url(self, server_name: str) -> str:
265+
scheme = "https" if self.tls_secret else "http"
266+
return urlunparse((scheme, self.host, self.base_path(server_name), None, None, None))
267+
260268

261269
@dataclass
262270
class _GenericCullingConfig:

0 commit comments

Comments
 (0)