Refactor LLM runtime handling and enhance CLI documentation

- Updated `resolve_llm_runtime` to prioritize live configuration over legacy notes, ensuring accurate runtime resolution.
- Enhanced `tunnel_forwards` to prefer current configuration for LLM runtime, improving tunnel setup logic.
- Improved idle-killer logic to handle stale markers and provide clearer warnings in the status output.
- Updated CLI documentation in `cli.md` to reflect changes in command behavior and runtime handling.
- Enhanced tests to validate new runtime resolution logic and ensure proper handling of configuration states.
This commit is contained in:
Leonid Pershin
2026-08-21 05:40:22 +03:00
parent 82e36129cd
commit dc1fde9e3e
17 changed files with 464 additions and 152 deletions
+21 -39
View File
@@ -48,56 +48,38 @@ def create_application_credential(conn, cfg: Config, server_id: str, log: Log) -
revoke_old_credentials(conn, log)
secret = secrets.token_urlsafe(32)
name = f"{CRED_NAME_PREFIX}-{server_id[:8]}"
# Only this compute — never /servers/* (would allow deleting any VM in the project).
access_rules = [
{
"service": "compute",
"method": "DELETE",
"path": f"/v2.1/servers/{server_id}",
},
{
"service": "compute",
"method": "GET",
"path": f"/v2.1/servers/{server_id}",
},
]
try:
ac = conn.identity.create_application_credential(
user=user_id,
name=name,
secret=secret,
description="gpu-rent idle-killer: delete this compute",
access_rules=[
{
"service": "compute",
"method": "DELETE",
"path": f"/v2.1/servers/{server_id}",
},
{
"service": "compute",
"method": "DELETE",
"path": "/v2.1/servers/*",
},
# sdk may GET server before delete / confirm status
{
"service": "compute",
"method": "GET",
"path": f"/v2.1/servers/{server_id}",
},
{
"service": "compute",
"method": "GET",
"path": "/v2.1/servers/*",
},
],
description="gpu-rent idle-killer: delete this compute only",
access_rules=access_rules,
)
except Exception as exc:
# Selectel / older Keystone may reject access_rules — fall back unrestricted delete.
log(f"app cred с access_rules не вышло ({exc}); пробуем без правил")
try:
ac = conn.identity.create_application_credential(
user=user_id,
name=name,
secret=secret,
description="gpu-rent idle-killer: delete this compute",
)
except Exception as exc2:
raise CloudError(
f"не создать application credential: {exc2}. "
"Нужны права identity:application_credential_create на сервисного пользователя."
) from exc2
raise CloudError(
f"не создать application credential с access_rules (только этот server): {exc}. "
"Без узких правил idle-killer не вооружаем (fail closed). "
"Нужны права identity:application_credential_create на сервисного пользователя."
) from exc
ac_id = getattr(ac, "id", None) or (ac.get("id") if isinstance(ac, dict) else None)
ac_secret = getattr(ac, "secret", None) or secret
if not ac_id:
raise CloudError("application credential создан без id")
log(f"application credential {name}")
log(f"application credential {name} (DELETE/GET только {server_id[:12]}…)")
return {
"auth_url": cfg.os_auth_url,
"project_id": cfg.os_project_id,