Add filter discovery endpoints with active/inactive status (Task 2.1)
- Add list_filters() and get_filter() to config_file_service.py:
scans filter.d/, parses [Definition] + [Init] sections, merges .local
overrides, and cross-references running jails to set active/used_by_jails
- Add FilterConfig.active, used_by_jails, source_file, has_local_override
fields to the Pydantic model; add FilterListResponse and FilterNotFoundError
- Add GET /api/config/filters and GET /api/config/filters/{name} to config.py
- Remove the shadowed GET /api/config/filters list route from file_config.py;
rename GET /api/config/filters/{name} raw variant to /filters/{name}/raw
- Update frontend: fetchFilterFiles() adapts FilterListResponse -> ConfFilesResponse;
add fetchFilters() and fetchFilter() to api/config.ts; remove unused
fetchFilterFiles/fetchActionFiles calls from useConfigActiveStatus
- Fix ConfigPageLogPath test mock to include fetchInactiveJails and related
exports introduced by Stage 1
- Backend: 169 tests pass, mypy --strict clean, ruff clean
- Frontend: 63 tests pass, tsc --noEmit clean, eslint clean
This commit is contained in:
@@ -275,7 +275,15 @@ class MapColorThresholdsUpdate(BaseModel):
|
||||
|
||||
|
||||
class FilterConfig(BaseModel):
|
||||
"""Structured representation of a ``filter.d/*.conf`` file."""
|
||||
"""Structured representation of a ``filter.d/*.conf`` file.
|
||||
|
||||
The ``active``, ``used_by_jails``, ``source_file``, and
|
||||
``has_local_override`` fields are populated by
|
||||
:func:`~app.services.config_file_service.list_filters` and
|
||||
:func:`~app.services.config_file_service.get_filter`. When the model is
|
||||
returned from the raw file-based endpoints (``/filters/{name}/parsed``),
|
||||
these fields carry their default values.
|
||||
"""
|
||||
|
||||
model_config = ConfigDict(strict=True)
|
||||
|
||||
@@ -314,6 +322,33 @@ class FilterConfig(BaseModel):
|
||||
default=None,
|
||||
description="Systemd journal match expression.",
|
||||
)
|
||||
# Active-status fields — populated by config_file_service.list_filters /
|
||||
# get_filter; default to safe "inactive" values when not computed.
|
||||
active: bool = Field(
|
||||
default=False,
|
||||
description=(
|
||||
"``True`` when this filter is referenced by at least one currently "
|
||||
"enabled (running) jail."
|
||||
),
|
||||
)
|
||||
used_by_jails: list[str] = Field(
|
||||
default_factory=list,
|
||||
description=(
|
||||
"Names of currently enabled jails that reference this filter. "
|
||||
"Empty when ``active`` is ``False``."
|
||||
),
|
||||
)
|
||||
source_file: str = Field(
|
||||
default="",
|
||||
description="Absolute path to the ``.conf`` source file for this filter.",
|
||||
)
|
||||
has_local_override: bool = Field(
|
||||
default=False,
|
||||
description=(
|
||||
"``True`` when a ``.local`` override file exists alongside the "
|
||||
"base ``.conf`` file."
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class FilterConfigUpdate(BaseModel):
|
||||
@@ -335,6 +370,21 @@ class FilterConfigUpdate(BaseModel):
|
||||
journalmatch: str | None = Field(default=None)
|
||||
|
||||
|
||||
class FilterListResponse(BaseModel):
|
||||
"""Response for ``GET /api/config/filters``."""
|
||||
|
||||
model_config = ConfigDict(strict=True)
|
||||
|
||||
filters: list[FilterConfig] = Field(
|
||||
default_factory=list,
|
||||
description=(
|
||||
"All discovered filters, each annotated with active/inactive status "
|
||||
"and the jails that reference them."
|
||||
),
|
||||
)
|
||||
total: int = Field(..., ge=0, description="Total number of filters found.")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Parsed action file models
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user