feat: SSH card UX, agent version sync, persistent ssh_admin_ok (0.11.5)
Silent SSH probe on host card open; manual test feedback auto-hides. Persist ssh_admin_ok in DB (migration 019). After agent update read version from host and refresh UI.
This commit is contained in:
@@ -3,6 +3,8 @@ from pydantic import BaseModel
|
||||
from sqlalchemy import func, select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from app.auth.jwt_auth import get_current_user, require_admin
|
||||
from app.config import get_settings
|
||||
from app.database import get_db
|
||||
@@ -151,9 +153,16 @@ def _host_detail_from_model(
|
||||
inventory=host.inventory if isinstance(host.inventory, dict) else None,
|
||||
inventory_updated_at=host.inventory_updated_at,
|
||||
created_at=host.created_at,
|
||||
ssh_admin_ok=host.ssh_admin_ok,
|
||||
ssh_admin_checked_at=host.ssh_admin_checked_at,
|
||||
)
|
||||
|
||||
|
||||
def _set_ssh_admin_status(host: Host, ok: bool) -> None:
|
||||
host.ssh_admin_ok = ok
|
||||
host.ssh_admin_checked_at = datetime.now(timezone.utc)
|
||||
|
||||
|
||||
@router.get("/{host_id}", response_model=HostDetail)
|
||||
def get_host(
|
||||
host_id: int,
|
||||
@@ -189,9 +198,16 @@ class HostSshActionResponse(BaseModel):
|
||||
stdout: str | None = None
|
||||
stderr: str | None = None
|
||||
exit_code: int | None = None
|
||||
product_version: str | None = None
|
||||
ssh_admin_ok: bool | None = None
|
||||
|
||||
|
||||
def _ssh_action_response(result: SshCommandResult, *, attempts: list[str] | None = None) -> HostSshActionResponse:
|
||||
def _ssh_action_response(
|
||||
result: SshCommandResult,
|
||||
*,
|
||||
attempts: list[str] | None = None,
|
||||
ssh_admin_ok: bool | None = None,
|
||||
) -> HostSshActionResponse:
|
||||
message = result.message
|
||||
if attempts:
|
||||
message = f"{message} (пробовали: {', '.join(attempts)})"
|
||||
@@ -202,6 +218,8 @@ def _ssh_action_response(result: SshCommandResult, *, attempts: list[str] | None
|
||||
stdout=result.stdout or None,
|
||||
stderr=result.stderr or None,
|
||||
exit_code=result.exit_code,
|
||||
product_version=result.agent_version,
|
||||
ssh_admin_ok=ssh_admin_ok,
|
||||
)
|
||||
|
||||
|
||||
@@ -313,7 +331,10 @@ def test_host_ssh(
|
||||
if not cfg.configured:
|
||||
raise HTTPException(status_code=400, detail="Linux SSH admin is not configured")
|
||||
|
||||
return _run_ssh_action_on_host(host, cfg, action=test_ssh_connection)
|
||||
response = _run_ssh_action_on_host(host, cfg, action=test_ssh_connection)
|
||||
_set_ssh_admin_status(host, response.ok)
|
||||
db.commit()
|
||||
return response.model_copy(update={"ssh_admin_ok": host.ssh_admin_ok})
|
||||
|
||||
|
||||
@router.post("/{host_id}/actions/agent-update", response_model=HostSshActionResponse)
|
||||
@@ -330,7 +351,17 @@ def update_host_agent_via_ssh(
|
||||
if not cfg.configured:
|
||||
raise HTTPException(status_code=400, detail="Linux SSH admin is not configured")
|
||||
|
||||
return _run_ssh_action_on_host(host, cfg, action=run_ssh_monitor_update)
|
||||
response = _run_ssh_action_on_host(host, cfg, action=run_ssh_monitor_update)
|
||||
_set_ssh_admin_status(host, response.ok)
|
||||
if response.ok and response.product_version:
|
||||
host.product_version = response.product_version
|
||||
db.commit()
|
||||
return response.model_copy(
|
||||
update={
|
||||
"product_version": host.product_version if response.ok else response.product_version,
|
||||
"ssh_admin_ok": host.ssh_admin_ok,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@router.delete("/{host_id}", response_model=HostDeleteResponse)
|
||||
|
||||
Reference in New Issue
Block a user