Skip to content

Commit 97799ed

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 edccde5 commit 97799ed

5 files changed

Lines changed: 105 additions & 85 deletions

File tree

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
@@ -811,13 +811,11 @@ async def _handler(
811811
image = environment.container_image
812812
default_resource_class = await self.rp_repo.get_default_resource_class()
813813
if default_resource_class.id is None:
814-
raise errors.ProgrammingError(message="The default reosurce class has to have an ID", quiet=True)
814+
raise errors.ProgrammingError(message="The default resource class has to have an ID", quiet=True)
815815
resource_class_id = body.resource_class_id or default_resource_class.id
816-
parsed_server_options = await self.nb_config.crc_validator.validate_class_storage(
817-
user, resource_class_id, body.disk_storage
818-
)
816+
await self.nb_config.crc_validator.validate_class_storage(user, resource_class_id, body.disk_storage)
819817
work_dir = environment.working_directory
820-
user_secrets: K8sUserSecrets | None = None
818+
# user_secrets: K8sUserSecrets | None = None
821819
# if body.user_secrets:
822820
# user_secrets = K8sUserSecrets(
823821
# name=server_name,
@@ -860,33 +858,13 @@ async def _handler(
860858
quiet=True,
861859
)
862860
cloud_storage[csr_id] = csr
863-
# repositories = [Repository(i.url, branch=i.branch, commit_sha=i.commit_sha) for i in body.repositories]
864861
repositories = [Repository(url=i) for i in project.repositories]
865862
secrets_to_create: list[V1Secret] = []
866-
server = Renku2UserServer(
867-
user=user,
868-
image=image,
869-
project_id=str(launcher.project_id),
870-
launcher_id=body.launcher_id,
871-
server_name=server_name,
872-
server_options=parsed_server_options,
873-
environment_variables={},
874-
user_secrets=user_secrets,
875-
cloudstorage=[i for i in cloud_storage.values()],
876-
k8s_client=self.nb_config.k8s_v2_client,
877-
workspace_mount_path=work_dir,
878-
work_dir=work_dir,
879-
repositories=repositories,
880-
config=self.nb_config,
881-
using_default_image=self.nb_config.sessions.default_image == image,
882-
is_image_private=False,
883-
internal_gitlab_user=internal_gitlab_user,
884-
)
885-
# Generate the cloud storage secrets
863+
# Generate the cloud starge secrets
886864
data_sources: list[DataSource] = []
887865
for ics, cs in enumerate(cloud_storage.values()):
888866
secret_name = f"{server_name}-ds-{ics}"
889-
secrets_to_create.append(cs.secret(secret_name, server.k8s_client.preferred_namespace))
867+
secrets_to_create.append(cs.secret(secret_name, self.nb_config.k8s_client.preferred_namespace))
890868
data_sources.append(
891869
DataSource(mountPath=cs.mount_folder, secretRef=SecretRefWhole(name=secret_name, adopt=True))
892870
)
@@ -905,17 +883,26 @@ async def _handler(
905883
),
906884
)
907885
)
908-
git_clone = await init_containers.git_clone_container_v2(server)
886+
git_providers = await self.nb_config.git_provider_helper.get_providers(user)
887+
git_clone = await init_containers.git_clone_container_v2(
888+
user,
889+
self.nb_config,
890+
repositories,
891+
git_providers,
892+
launcher.environment.mount_directory,
893+
launcher.environment.working_directory,
894+
)
909895
if git_clone is not None:
910896
session_init_containers.append(InitContainer.model_validate(git_clone))
911897
extra_containers: list[ExtraContainer] = []
912-
git_proxy_container = await git_proxy.main_container(server)
898+
git_proxy_container = await git_proxy.main_container(user, self.nb_config, repositories, git_providers)
913899
if git_proxy_container is not None:
914900
extra_containers.append(
915901
ExtraContainer.model_validate(self.nb_config.k8s_v2_client.sanitize(git_proxy_container))
916902
)
917903

918-
parsed_server_url = urlparse(server.server_url)
904+
base_server_url = self.nb_config.sessions.ingress.base_url(server_name)
905+
base_server_path = self.nb_config.sessions.ingress.base_path(server_name)
919906
annotations: dict[str, str] = {
920907
"renku.io/project_id": str(launcher.project_id),
921908
"renku.io/launcher_id": body.launcher_id,
@@ -928,7 +915,7 @@ async def _handler(
928915
hibernated=False,
929916
session=Session(
930917
image=image,
931-
urlPath=parsed_server_url.path,
918+
urlPath=base_server_path,
932919
port=environment.port,
933920
storage=Storage(
934921
className=self.nb_config.sessions.storage.pvs_storage_class,
@@ -944,8 +931,8 @@ async def _handler(
944931
args=environment.args,
945932
shmSize="1G",
946933
env=[
947-
SessionEnvItem(name="RENKU_BASE_URL_PATH", value=parsed_server_url.path),
948-
SessionEnvItem(name="RENKU_BASE_URL", value=server.server_url),
934+
SessionEnvItem(name="RENKU_BASE_URL_PATH", value=base_server_url),
935+
SessionEnvItem(name="RENKU_BASE_URL", value=base_server_path),
949936
],
950937
),
951938
ingress=Ingress(
@@ -981,7 +968,7 @@ async def _handler(
981968
dataSources=data_sources,
982969
),
983970
)
984-
parsed_proxy_url = urlparse(urljoin(server.server_url + "/", "oauth2"))
971+
parsed_proxy_url = urlparse(urljoin(base_server_url + "/", "oauth2"))
985972
secret_data = {}
986973
if isinstance(user, AuthenticatedAPIUser):
987974
secret_data["auth"] = dumps(
@@ -991,8 +978,8 @@ async def _handler(
991978
"oidc_issuer_url": self.nb_config.sessions.oidc.issuer_url,
992979
"session_cookie_minimal": True,
993980
"skip_provider_button": True,
994-
"redirect_url": urljoin(server.server_url + "/", "oauth2/callback"),
995-
"cookie_path": parsed_server_url.path,
981+
"redirect_url": urljoin(base_server_url + "/", "oauth2/callback"),
982+
"cookie_path": base_server_path,
996983
"proxy_prefix": parsed_proxy_url.path,
997984
"authenticated_emails_file": "/authorized_emails/authorized_emails",
998985
"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)