feat: git-based agent version reference and unified outdated badge (0.20.0)
SAC reads latest RDP/ssh-monitor versions from configured git repos for outdated detection, update targets, and settings test-git.
This commit is contained in:
@@ -10,7 +10,11 @@ from app.config import get_settings
|
||||
from app.database import get_db
|
||||
from app.models import Event, Host
|
||||
from app.schemas.list_models import HostDetail, HostListResponse, HostSummary
|
||||
from app.services.agent_version import latest_agent_versions_by_product
|
||||
from app.services.agent_version import (
|
||||
latest_agent_versions_by_product,
|
||||
reference_agent_versions_by_product,
|
||||
)
|
||||
from app.services.agent_git_release import get_git_release_versions
|
||||
from app.services.agent_update import (
|
||||
AgentUpdateNotAllowedError,
|
||||
execute_agent_update_fallback,
|
||||
@@ -92,6 +96,12 @@ def list_hosts(
|
||||
report_map = max_daily_report_time_by_host(db)
|
||||
latest_map = latest_agent_versions_by_product(db)
|
||||
update_cfg = get_effective_agent_update_config(db)
|
||||
git_release = get_git_release_versions(update_cfg, db=db)
|
||||
reference_map = reference_agent_versions_by_product(
|
||||
update_cfg,
|
||||
latest_map,
|
||||
git_versions=git_release.versions,
|
||||
)
|
||||
|
||||
items: list[HostSummary] = []
|
||||
for host in rows:
|
||||
@@ -117,7 +127,12 @@ def list_hosts(
|
||||
agent_status=compute_agent_status(
|
||||
last_hb, stale_minutes=settings.sac_heartbeat_stale_minutes
|
||||
),
|
||||
version_status=host_version_status(host, cfg=update_cfg, latest_map=latest_map),
|
||||
version_status=host_version_status(
|
||||
host,
|
||||
cfg=update_cfg,
|
||||
latest_map=latest_map,
|
||||
git_versions=git_release.versions,
|
||||
),
|
||||
pending_agent_update=bool(host.pending_agent_update),
|
||||
)
|
||||
)
|
||||
@@ -127,7 +142,8 @@ def list_hosts(
|
||||
total=total,
|
||||
page=page,
|
||||
page_size=page_size,
|
||||
latest_agent_versions=latest_agent_versions_by_product(db),
|
||||
latest_agent_versions=latest_map,
|
||||
reference_agent_versions=reference_map,
|
||||
)
|
||||
|
||||
|
||||
@@ -145,6 +161,7 @@ def _host_detail_from_model(
|
||||
last_hb = hb_map.get(host.id)
|
||||
latest_map = latest_agent_versions_by_product(db)
|
||||
update_cfg = get_effective_agent_update_config(db)
|
||||
git_release = get_git_release_versions(update_cfg, db=db)
|
||||
return HostDetail(
|
||||
id=host.id,
|
||||
hostname=host.hostname,
|
||||
@@ -161,7 +178,12 @@ def _host_detail_from_model(
|
||||
last_daily_report_at=report_map.get(host.id),
|
||||
last_inventory_at=host.inventory_updated_at,
|
||||
agent_status=compute_agent_status(last_hb, stale_minutes=settings.sac_heartbeat_stale_minutes),
|
||||
version_status=host_version_status(host, cfg=update_cfg, latest_map=latest_map),
|
||||
version_status=host_version_status(
|
||||
host,
|
||||
cfg=update_cfg,
|
||||
latest_map=latest_map,
|
||||
git_versions=git_release.versions,
|
||||
),
|
||||
pending_agent_update=bool(host.pending_agent_update),
|
||||
agent_instance_id=host.agent_instance_id,
|
||||
tags=host.tags if isinstance(host.tags, list) else [],
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from datetime import datetime
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from pydantic import BaseModel, Field
|
||||
from sqlalchemy.orm import Session
|
||||
@@ -45,6 +47,7 @@ from app.services.win_admin_settings import (
|
||||
get_effective_win_admin_config,
|
||||
upsert_win_admin_settings,
|
||||
)
|
||||
from app.services.agent_git_release import get_git_release_versions
|
||||
from app.services.agent_update_settings import (
|
||||
get_effective_agent_update_config,
|
||||
upsert_agent_update_settings,
|
||||
@@ -555,6 +558,13 @@ class AgentUpdateSettingsResponse(BaseModel):
|
||||
min_rdp_version: str | None = None
|
||||
min_ssh_version: str | None = None
|
||||
win_agent_update_script: str | None = None
|
||||
rdp_git_repo_url: str | None = None
|
||||
ssh_git_repo_url: str | None = None
|
||||
git_branch: str = "main"
|
||||
git_latest_rdp_version: str | None = None
|
||||
git_latest_ssh_version: str | None = None
|
||||
git_fetched_at: datetime | None = None
|
||||
git_errors: dict[str, str] = Field(default_factory=dict)
|
||||
source: str = Field(description="env или db")
|
||||
|
||||
|
||||
@@ -567,9 +577,31 @@ class AgentUpdateSettingsUpdate(BaseModel):
|
||||
min_rdp_version: str | None = None
|
||||
min_ssh_version: str | None = None
|
||||
win_agent_update_script: str | None = None
|
||||
rdp_git_repo_url: str | None = None
|
||||
ssh_git_repo_url: str | None = None
|
||||
git_branch: str | None = None
|
||||
|
||||
|
||||
def _agent_update_to_response(cfg) -> AgentUpdateSettingsResponse:
|
||||
class AgentGitTestResponse(BaseModel):
|
||||
git_latest_rdp_version: str | None = None
|
||||
git_latest_ssh_version: str | None = None
|
||||
git_fetched_at: datetime | None = None
|
||||
git_errors: dict[str, str] = Field(default_factory=dict)
|
||||
from_cache: bool = False
|
||||
|
||||
|
||||
def _agent_update_to_response(cfg, git_release=None) -> AgentUpdateSettingsResponse:
|
||||
git_latest_rdp = None
|
||||
git_latest_ssh = None
|
||||
git_fetched_at = None
|
||||
git_errors: dict[str, str] = {}
|
||||
if git_release is not None:
|
||||
from app.services.agent_update_settings import PRODUCT_RDP, PRODUCT_SSH
|
||||
|
||||
git_latest_rdp = git_release.versions.get(PRODUCT_RDP) or None
|
||||
git_latest_ssh = git_release.versions.get(PRODUCT_SSH) or None
|
||||
git_fetched_at = git_release.fetched_at
|
||||
git_errors = dict(git_release.errors)
|
||||
return AgentUpdateSettingsResponse(
|
||||
mode=cfg.mode,
|
||||
fallback_enabled=cfg.fallback_enabled,
|
||||
@@ -579,6 +611,13 @@ def _agent_update_to_response(cfg) -> AgentUpdateSettingsResponse:
|
||||
min_rdp_version=cfg.min_rdp_version or None,
|
||||
min_ssh_version=cfg.min_ssh_version or None,
|
||||
win_agent_update_script=cfg.win_agent_update_script or None,
|
||||
rdp_git_repo_url=cfg.rdp_git_repo_url or None,
|
||||
ssh_git_repo_url=cfg.ssh_git_repo_url or None,
|
||||
git_branch=cfg.git_branch or "main",
|
||||
git_latest_rdp_version=git_latest_rdp,
|
||||
git_latest_ssh_version=git_latest_ssh,
|
||||
git_fetched_at=git_fetched_at,
|
||||
git_errors=git_errors,
|
||||
source=cfg.source,
|
||||
)
|
||||
|
||||
@@ -588,7 +627,9 @@ def get_agent_update_settings(
|
||||
db: Session = Depends(get_db),
|
||||
_user=Depends(require_admin),
|
||||
) -> AgentUpdateSettingsResponse:
|
||||
return _agent_update_to_response(get_effective_agent_update_config(db))
|
||||
cfg = get_effective_agent_update_config(db)
|
||||
git_release = get_git_release_versions(cfg, db=db)
|
||||
return _agent_update_to_response(cfg, git_release)
|
||||
|
||||
|
||||
@router.put("/agent-updates", response_model=AgentUpdateSettingsResponse)
|
||||
@@ -608,7 +649,29 @@ def update_agent_update_settings(
|
||||
min_rdp_version=body.min_rdp_version,
|
||||
min_ssh_version=body.min_ssh_version,
|
||||
win_agent_update_script=body.win_agent_update_script,
|
||||
rdp_git_repo_url=body.rdp_git_repo_url,
|
||||
ssh_git_repo_url=body.ssh_git_repo_url,
|
||||
git_branch=body.git_branch,
|
||||
)
|
||||
except ValueError as exc:
|
||||
raise HTTPException(status_code=422, detail=str(exc)) from exc
|
||||
return _agent_update_to_response(cfg)
|
||||
git_release = get_git_release_versions(cfg, db=db, force_refresh=True)
|
||||
return _agent_update_to_response(cfg, git_release)
|
||||
|
||||
|
||||
@router.post("/agent-updates/test-git", response_model=AgentGitTestResponse)
|
||||
def test_agent_git_release(
|
||||
db: Session = Depends(get_db),
|
||||
_user=Depends(require_admin),
|
||||
) -> AgentGitTestResponse:
|
||||
cfg = get_effective_agent_update_config(db)
|
||||
git_release = get_git_release_versions(cfg, db=db, force_refresh=True)
|
||||
from app.services.agent_update_settings import PRODUCT_RDP, PRODUCT_SSH
|
||||
|
||||
return AgentGitTestResponse(
|
||||
git_latest_rdp_version=git_release.versions.get(PRODUCT_RDP) or None,
|
||||
git_latest_ssh_version=git_release.versions.get(PRODUCT_SSH) or None,
|
||||
git_fetched_at=git_release.fetched_at,
|
||||
git_errors=dict(git_release.errors),
|
||||
from_cache=git_release.from_cache,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user