mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-09 12:17:13 +00:00
Every deploy row now takes a node network mode, clearnet, tor or multi, instead of an onion yes or no. The workflow input `network` (auto|clearnet|tor|multi) replaces `tor`, and INFINITO_NETWORK replaces INFINITO_TOR. utils/github/variant/network.py decides which modes a row can take: clearnet only without a Tor bond or when the variant pins Tor off, no multi for a single_mode role, no clearnet for the Tor provider, whose rows are therefore no longer dropped when the rotation lands on clearnet. Priority rows cover every mode and network combination, regular rows rotate the network on sweep // 2, and clearnet rows carry disable=tor. Selection tokens pin the axis with +clearnet, +tor or +multi, and multi rows wear the new glyph. A row hands its mode to the deploy as the variable `network`, which provisioning writes into host_vars as NETWORK_MODE. Without it the node keeps deriving its mode from the deployed providers. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
70 lines
2.5 KiB
Python
70 lines
2.5 KiB
Python
"""Data types for the development inventory matrix.
|
|
|
|
`DevInventorySpec` is the value type `build_dev_inventory` consumes —
|
|
it carries everything `infinito administration inventory provision`
|
|
needs to materialise one development inventory folder. `PlanEntry` is
|
|
the per-round tuple `plan_dev_inventory_matrix` emits and the deploy
|
|
wrapper iterates.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from typing import TYPE_CHECKING, Any
|
|
|
|
if TYPE_CHECKING:
|
|
from collections.abc import Mapping
|
|
|
|
PlanEntry = tuple[int, str, dict[str, int], tuple[str, ...], tuple[str, ...]]
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class DevInventorySpec:
|
|
"""Everything `infinito administration inventory provision` needs to
|
|
materialise one development inventory folder.
|
|
|
|
`extra_vars` wins over the implicit `STORAGE_CONSTRAINED` / `RUNTIME`
|
|
overrides so callers (and tests) keep the documented "user-provided
|
|
vars always win" behaviour without re-implementing the merge.
|
|
|
|
`active_variants` is the per-app variant index for the round this
|
|
folder represents. Apps absent from the mapping (or with an out-of-
|
|
range index) fall back to variant 0. The resolved variant payload
|
|
for every app in `include` is baked into the inventory as an
|
|
`applications.<app>` override, so the deploy stage no longer needs
|
|
a runtime variant selector — the inventory itself is variant-resolved.
|
|
|
|
`network_mode` is the node `NETWORK_MODE` provisioning writes; empty
|
|
leaves it to the derivation from the deployed providers.
|
|
"""
|
|
|
|
inventory_dir: str
|
|
include: tuple[str, ...]
|
|
storage_constrained: bool
|
|
runtime: str
|
|
extra_vars: Mapping[str, Any] | None = None
|
|
services_disabled: str = ""
|
|
active_variants: Mapping[str, int] | None = None
|
|
network_mode: str = ""
|
|
|
|
def __post_init__(self) -> None:
|
|
if not self.include:
|
|
raise ValueError("DevInventorySpec.include must not be empty")
|
|
if not isinstance(self.include, tuple):
|
|
object.__setattr__(self, "include", tuple(self.include))
|
|
|
|
def overrides(self) -> dict[str, Any]:
|
|
merged: dict[str, Any] = {
|
|
"STORAGE_CONSTRAINED": bool(self.storage_constrained),
|
|
"RUNTIME": self.runtime,
|
|
}
|
|
if self.extra_vars:
|
|
merged.update(self.extra_vars)
|
|
return merged
|
|
|
|
def variant_selectors(self) -> dict[str, int]:
|
|
return dict(self.active_variants or {})
|
|
|
|
def inventory_root(self) -> str:
|
|
return str(self.inventory_dir).rstrip("/")
|