From 1ac05c7f84406a05557f2babbdc395a8916a4447 Mon Sep 17 00:00:00 2001 From: Jvst Me Date: Thu, 16 Oct 2025 14:53:08 +0200 Subject: [PATCH] Fix CLI incompatibility with older `/get_my_user` --- src/dstack/api/_public/runs.py | 3 ++- src/dstack/api/server/_users.py | 21 ++++++++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/dstack/api/_public/runs.py b/src/dstack/api/_public/runs.py index 5ebc8c2c4..c51c899d3 100644 --- a/src/dstack/api/_public/runs.py +++ b/src/dstack/api/_public/runs.py @@ -48,6 +48,7 @@ get_service_port, ) from dstack._internal.core.models.runs import Run as RunModel +from dstack._internal.core.models.users import UserWithCreds from dstack._internal.core.services.configs import ConfigManager from dstack._internal.core.services.logs import URLReplacer from dstack._internal.core.services.ssh.attach import SSHAttach @@ -283,7 +284,7 @@ def attach( user = self._api_client.users.get_my_user() run_ssh_key_pub = self._run.run_spec.ssh_key_pub config_manager = ConfigManager() - if user.ssh_public_key == run_ssh_key_pub: + if isinstance(user, UserWithCreds) and user.ssh_public_key == run_ssh_key_pub: token_hash = hashlib.sha1(user.creds.token.encode()).hexdigest()[:8] config_manager.dstack_ssh_dir.mkdir(parents=True, exist_ok=True) ssh_identity_file = config_manager.dstack_ssh_dir / token_hash diff --git a/src/dstack/api/server/_users.py b/src/dstack/api/server/_users.py index 6082636c4..08dd118b4 100644 --- a/src/dstack/api/server/_users.py +++ b/src/dstack/api/server/_users.py @@ -1,6 +1,6 @@ from typing import List -from pydantic import parse_obj_as +from pydantic import ValidationError, parse_obj_as from dstack._internal.core.models.users import GlobalRole, User, UserWithCreds from dstack._internal.server.schemas.users import ( @@ -17,9 +17,24 @@ def list(self) -> List[User]: resp = self._request("/api/users/list") return parse_obj_as(List[User.__response__], resp.json()) - def get_my_user(self) -> UserWithCreds: + def get_my_user(self) -> User: + """ + Returns `User` with pre-0.19.33 servers, or `UserWithCreds` with newer servers. + """ + resp = self._request("/api/users/get_my_user") - return parse_obj_as(UserWithCreds.__response__, resp.json()) + try: + return parse_obj_as(UserWithCreds.__response__, resp.json()) + except ValidationError as e: + # Compatibility with pre-0.19.33 server + if ( + len(e.errors()) == 1 + and e.errors()[0]["loc"] == ("__root__", "creds") + and e.errors()[0]["type"] == "value_error.missing" + ): + return parse_obj_as(User.__response__, resp.json()) + else: + raise def get_user(self, username: str) -> User: body = GetUserRequest(username=username)