fix(fleet): defer DecnetConfig build until deckies are expanded
Stateless /api/v1/deckies/deploy previously instantiated DecnetConfig with deckies=[] so it could merge entries later — but DecnetConfig.deckies is min_length=1, so Pydantic raised and the global handler mapped it to 422 'Internal data consistency error'. Construct the config after build_deckies_from_ini returns at least one DeckyConfig.
This commit is contained in:
@@ -43,16 +43,20 @@ async def api_deploy_deckies(req: DeployIniRequest, admin: dict = Depends(requir
|
|||||||
state_dict = await repo.get_state("deployment")
|
state_dict = await repo.get_state("deployment")
|
||||||
ingest_log_file = os.environ.get("DECNET_INGEST_LOG_FILE")
|
ingest_log_file = os.environ.get("DECNET_INGEST_LOG_FILE")
|
||||||
|
|
||||||
|
config: DecnetConfig | None = None
|
||||||
if state_dict:
|
if state_dict:
|
||||||
config = DecnetConfig(**state_dict["config"])
|
config = DecnetConfig(**state_dict["config"])
|
||||||
subnet_cidr = ini.subnet or config.subnet
|
subnet_cidr = ini.subnet or config.subnet
|
||||||
gateway = ini.gateway or config.gateway
|
gateway = ini.gateway or config.gateway
|
||||||
host_ip = get_host_ip(config.interface)
|
iface = config.interface
|
||||||
|
host_ip = get_host_ip(iface)
|
||||||
# Always sync config log_file with current API ingestion target
|
# Always sync config log_file with current API ingestion target
|
||||||
if ingest_log_file:
|
if ingest_log_file:
|
||||||
config.log_file = ingest_log_file
|
config.log_file = ingest_log_file
|
||||||
else:
|
else:
|
||||||
# If no state exists, we need to infer network details from the INI or the host.
|
# No state yet — infer network details from the INI or the host. We
|
||||||
|
# defer instantiating DecnetConfig until after build_deckies_from_ini
|
||||||
|
# because DecnetConfig.deckies has min_length=1.
|
||||||
try:
|
try:
|
||||||
iface = ini.interface or detect_interface()
|
iface = ini.interface or detect_interface()
|
||||||
subnet_cidr, gateway = ini.subnet, ini.gateway
|
subnet_cidr, gateway = ini.subnet, ini.gateway
|
||||||
@@ -67,16 +71,6 @@ async def api_deploy_deckies(req: DeployIniRequest, admin: dict = Depends(requir
|
|||||||
detail=f"Network configuration conflict: {e}. "
|
detail=f"Network configuration conflict: {e}. "
|
||||||
"Add a [general] section with interface=, net=, and gw= to the INI."
|
"Add a [general] section with interface=, net=, and gw= to the INI."
|
||||||
)
|
)
|
||||||
config = DecnetConfig(
|
|
||||||
mode="unihost",
|
|
||||||
interface=iface,
|
|
||||||
subnet=subnet_cidr,
|
|
||||||
gateway=gateway,
|
|
||||||
deckies=[],
|
|
||||||
log_file=ingest_log_file,
|
|
||||||
ipvlan=False,
|
|
||||||
mutate_interval=ini.mutate_interval or DEFAULT_MUTATE_INTERVAL
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
new_decky_configs = build_deckies_from_ini(
|
new_decky_configs = build_deckies_from_ini(
|
||||||
@@ -86,6 +80,18 @@ async def api_deploy_deckies(req: DeployIniRequest, admin: dict = Depends(requir
|
|||||||
log.debug("deploy: build_deckies_from_ini rejected input: %s", e)
|
log.debug("deploy: build_deckies_from_ini rejected input: %s", e)
|
||||||
raise HTTPException(status_code=409, detail=str(e))
|
raise HTTPException(status_code=409, detail=str(e))
|
||||||
|
|
||||||
|
if config is None:
|
||||||
|
config = DecnetConfig(
|
||||||
|
mode="unihost",
|
||||||
|
interface=iface,
|
||||||
|
subnet=subnet_cidr,
|
||||||
|
gateway=gateway,
|
||||||
|
deckies=new_decky_configs,
|
||||||
|
log_file=ingest_log_file,
|
||||||
|
ipvlan=False,
|
||||||
|
mutate_interval=ini.mutate_interval or DEFAULT_MUTATE_INTERVAL,
|
||||||
|
)
|
||||||
|
|
||||||
# Merge deckies
|
# Merge deckies
|
||||||
existing_deckies_map = {d.name: d for d in config.deckies}
|
existing_deckies_map = {d.name: d for d in config.deckies}
|
||||||
for new_decky in new_decky_configs:
|
for new_decky in new_decky_configs:
|
||||||
|
|||||||
Reference in New Issue
Block a user