Files
NexaFabric/backend/app/schemas/domain.py
T
nessi 1802c2cbee feat: add policy deployment status tracking with cluster-level rule state monitoring and live firewall rule version comparison
Add policy_read_payload helper to build policy response with deployment status, implement nexafabric_rule_version to parse policy ID and version from rule comments, add policy_deployment_status to check active/stale/partial/unresolved states by comparing expected rules from preview against live firewall rules per cluster with version matching, extend PolicyRead schema with
2026-07-09 19:52:10 +02:00

365 lines
7.2 KiB
Python

from datetime import datetime
from typing import Any
from pydantic import BaseModel, ConfigDict, Field
class OrmModel(BaseModel):
model_config = ConfigDict(from_attributes=True)
class TokenPair(BaseModel):
access_token: str
refresh_token: str
token_type: str = "bearer"
class LoginRequest(BaseModel):
email: str
password: str
class SetupStatus(BaseModel):
complete: bool
has_users: bool
has_clusters: bool
class SetupCompleteRequest(BaseModel):
admin_email: str
admin_name: str
admin_password: str = Field(min_length=12)
cluster_name: str | None = None
cluster_api_url: str | None = None
cluster_api_token: str | None = None
cluster_provider: str = "proxmox"
cluster_mode: str = "read_only"
verify_tls: bool = True
class UserRead(OrmModel):
id: str
email: str
display_name: str
is_active: bool
class UserCreate(BaseModel):
email: str
display_name: str
password: str = Field(min_length=12)
role_ids: list[str] = []
class RoleCreate(BaseModel):
name: str
permissions: list[str] = []
class RoleRead(OrmModel):
id: str
name: str
permissions: list[str]
class ClusterCreate(BaseModel):
name: str
api_url: str
api_token: str = Field(min_length=8)
provider: str = "proxmox"
mode: str = "read_only"
verify_tls: bool = True
class ClusterUpdate(BaseModel):
name: str
api_url: str
api_token: str | None = Field(default=None, min_length=8)
provider: str = "proxmox"
mode: str = "read_only"
verify_tls: bool = True
class TenantCreate(BaseModel):
name: str
description: str | None = None
class ProjectCreate(BaseModel):
tenant_id: str
name: str
description: str | None = None
class NetworkCreate(BaseModel):
cluster_id: str
project_id: str | None = None
name: str
kind: str = "bridge"
vlan_id: int | None = None
mtu: int = 1500
gateway: str | None = None
dns: list[str] = []
dhcp_enabled: bool = False
tags: list[str] = []
description: str | None = None
class SubnetCreate(BaseModel):
network_id: str
cidr: str
gateway: str | None = None
dns: list[str] = []
dhcp_enabled: bool = False
class SubnetUpdate(BaseModel):
network_id: str | None = None
cidr: str | None = None
gateway: str | None = None
dns: list[str] | None = None
dhcp_enabled: bool | None = None
class SecurityGroupCreate(BaseModel):
project_id: str | None = None
name: str
description: str | None = None
class SecurityRuleCreate(BaseModel):
security_group_id: str
direction: str = "ingress"
action: str = "allow"
protocol: str = "tcp"
source: str = "any"
destination: str = "any"
port: str | None = None
priority: int = 1000
logging: bool = False
description: str | None = None
class PolicyCreate(BaseModel):
project_id: str | None = None
name: str
enabled: bool = True
definition: dict[str, Any]
class IpReservationCreate(BaseModel):
subnet_id: str
address: str
status: str = "reserved"
note: str | None = None
class ServiceCatalogCreate(BaseModel):
name: str
protocol: str
ports: str
editable: bool = True
class FirewallApplyRequest(BaseModel):
policy_id: str
cluster_id: str | None = None
confirm: bool = False
dry_run: bool = True
class ClusterRead(OrmModel):
id: str
name: str
api_url: str
provider: str
mode: str
verify_tls: bool
last_sync_at: datetime | None
last_sync_status: str | None
last_sync_error: str | None
class NodeRead(OrmModel):
id: str
cluster_id: str
name: str
status: str
cpu_count: int
memory_mb: int
class NodeAgentRead(BaseModel):
node_id: str
status: str
version: str | None = None
last_seen_at: datetime | None = None
install_count: int = 0
last_payload: dict[str, Any] | None = None
class NodeWithAgentRead(NodeRead):
agent: NodeAgentRead | None = None
class AgentHeartbeat(BaseModel):
version: str
node_name: str | None = None
collected_at: datetime | None = None
hostname: str | None = None
kernel: str | None = None
uptime_seconds: float | None = None
loadavg: list[float] = []
interfaces: list[dict[str, Any]] = []
interface_traffic: list[dict[str, Any]] = []
flows: list[dict[str, Any]] = []
conntrack: dict[str, Any] = {}
firewall: dict[str, Any] = {}
extra: dict[str, Any] = {}
class WorkloadRead(OrmModel):
id: str
cluster_id: str
node_id: str
project_id: str | None
external_id: str
name: str
kind: str
status: str
tags: list[str]
class NetworkRead(OrmModel):
id: str
cluster_id: str
project_id: str | None
name: str
kind: str
vlan_id: int | None
mtu: int
gateway: str | None
dns: list[str]
dhcp_enabled: bool
tags: list[str]
description: str | None
class SubnetRead(OrmModel):
id: str
network_id: str
cidr: str
gateway: str | None
dns: list[str]
dhcp_enabled: bool
class IpAddressRead(OrmModel):
id: str
subnet_id: str
subnet_cidr: str | None = None
address: str
status: str
workload_id: str | None
workload_name: str | None = None
workload_external_id: str | None = None
note: str | None
class TenantRead(OrmModel):
id: str
name: str
description: str | None
class ProjectRead(OrmModel):
id: str
tenant_id: str
name: str
description: str | None
class SecurityGroupRead(OrmModel):
id: str
project_id: str | None
name: str
description: str | None
class SecurityRuleRead(OrmModel):
id: str
security_group_id: str
direction: str
action: str
protocol: str
source: str
destination: str
port: str | None
priority: int
logging: bool
description: str | None
class PolicyRead(OrmModel):
id: str
project_id: str | None
name: str
version: int
enabled: bool
enforcement_mode: str
definition: dict[str, Any]
last_compiled: dict[str, Any] | None
deployment_status: dict[str, Any] | None = None
class WorkloadInsight(BaseModel):
workload: WorkloadRead
assigned_ips: list[IpAddressRead]
traffic: list[dict[str, Any]]
active_firewall_rules: list[dict[str, Any]] = []
matching_policies: list[PolicyRead]
effective_decision: str
audit_mode_notes: list[str]
class ServiceCatalogRead(OrmModel):
id: str
name: str
protocol: str
ports: str
editable: bool
class FirewallPreview(BaseModel):
policy_id: str
dry_run: bool = True
generated_rules: list[dict[str, Any]]
warnings: list[str]
conflicts: list[str]
class JobRead(OrmModel):
id: str
kind: str
status: str
progress: int
started_at: datetime | None
finished_at: datetime | None
logs: list[str]
error: str | None
class AuditLogRead(OrmModel):
id: str
created_at: datetime
user_id: str | None
action: str
object_type: str
object_id: str | None
old_values: dict[str, Any] | None
new_values: dict[str, Any] | None
ip_address: str | None
user_agent: str | None
result: str
error_text: str | None