diff --git a/renku/core/session/docker.py b/renku/core/session/docker.py index f7a930ef42..129e9e93bb 100644 --- a/renku/core/session/docker.py +++ b/renku/core/session/docker.py @@ -20,7 +20,7 @@ import webbrowser from datetime import datetime from pathlib import Path -from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Tuple, Union, cast +from typing import TYPE_CHECKING, Any, Dict, Iterator, List, Optional, Tuple, Union, cast from uuid import uuid4 import docker @@ -29,8 +29,11 @@ from renku.core import errors from renku.core.config import get_value from renku.core.constant import ProviderPriority +from renku.core.login import read_renku_token from renku.core.plugin import hookimpl +from renku.core.session.utils import get_renku_url from renku.core.util import communication +from renku.core.util.jwt import is_token_expired from renku.domain_model.project_context import project_context from renku.domain_model.session import ISessionProvider, Session, SessionStopStatus @@ -67,11 +70,14 @@ def docker_client(self) -> docker.client.DockerClient: return self._docker_client @staticmethod - def _get_jupyter_urls(ports: Dict[str, Any], auth_token: str, jupyter_port: int = 8888) -> Iterable[str]: + def _get_jupyter_urls(ports: Dict[str, Any], auth_token: str, jupyter_port: int = 8888) -> Iterator[str]: port_key = f"{jupyter_port}/tcp" if port_key not in ports: - return list() - return map(lambda x: f"http://{x['HostIp']}:{x['HostPort']}/?token={auth_token}", ports[port_key]) + return list() # type: ignore + default_url = get_value("interactive", "default_url") + if not default_url: + default_url = "/lab" + return map(lambda x: f"http://{x['HostIp']}:{x['HostPort']}{default_url}?token={auth_token}", ports[port_key]) def _get_docker_containers(self, project_name: str) -> List[docker.models.containers.Container]: return self.docker_client().containers.list(filters={"label": f"renku_project={project_name}"}) @@ -92,9 +98,22 @@ def build_image(self, image_descriptor: Path, image_name: str, config: Optional[ def find_image(self, image_name: str, config: Optional[Dict[str, Any]]) -> bool: """Find the given container image.""" with communication.busy(msg=f"Checking for image {image_name}"): + renku_url = get_renku_url() + + # only search remote image if a user is logged in + find_remote = True + if renku_url is None: + find_remote = False + else: + token = read_renku_token(endpoint=renku_url) + if not token or is_token_expired(token): + find_remote = False + try: self.docker_client().images.get(image_name) except docker.errors.ImageNotFound: + if not find_remote: + return False try: self.docker_client().images.get_registry_data(image_name) except docker.errors.APIError: @@ -454,13 +473,23 @@ def session_open(self, project_name: str, session_name: Optional[str], **kwargs) def session_url(self, session_name: Optional[str]) -> Optional[str]: """Get the URL of the interactive session.""" sessions = self.docker_client().containers.list() + default_url = get_value("interactive", "default_url") + if not default_url: + default_url = "/lab" for c in sessions: if ( c.short_id == session_name or (not session_name and len(sessions) == 1) ) and f"{DockerSessionProvider.JUPYTER_PORT}/tcp" in c.ports: - host = c.ports[f"{DockerSessionProvider.JUPYTER_PORT}/tcp"][0] - return f'http://{host["HostIp"]}:{host["HostPort"]}/?token={c.labels["jupyter_token"]}' + url = next( + DockerSessionProvider._get_jupyter_urls( + c.ports, c.labels["jupyter_token"], DockerSessionProvider.JUPYTER_PORT + ), + None, + ) + if not url: + continue + return url return None def force_build_image(self, force_build: bool = False, **kwargs) -> bool: diff --git a/renku/core/session/utils.py b/renku/core/session/utils.py index c6f16de97c..078271a9d2 100644 --- a/renku/core/session/utils.py +++ b/renku/core/session/utils.py @@ -18,7 +18,9 @@ import urllib from typing import Optional +from renku.core.login import read_renku_token from renku.core.util.git import get_remote +from renku.core.util.jwt import is_token_expired from renku.core.util.urls import parse_authentication_endpoint from renku.domain_model.project_context import project_context @@ -54,4 +56,8 @@ def get_image_repository_host() -> Optional[str]: renku_url = get_renku_url() if not renku_url: return None + token = read_renku_token(endpoint=renku_url) + if not token or is_token_expired(token): + # only guess host if user is logged in + return None return "registry." + urllib.parse.urlparse(renku_url).netloc