mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 02:54:26 +00:00
The private blocks were written out wherever something needed to say "this is us": NETWORK_TRUSTED_PROXY_CIDRS listed all three, Tor's SocksPolicy repeated them, unbound's access-control repeated them again. Four copies of a fact, and nothing tying them together, so narrowing one narrows nothing else. Worse, the block role networks are carved from was never declared at all. The allocator behind 'infinito contributing network address suggest' derives its umbrella from the subnets already in use, so the tree defined the rule instead of the rule defining the tree. Anything consuming "our own address space" had to guess it, and a guess that is one role out of date silently excludes that role. Measured: 106 of 107 role subnets sit in 192.168.0.0/16 and one does not, so a firewall range derived from the pool by eye would have cut BigBlueButton off. The blocks are now named once and everything else is derived, NETWORK_TRUSTED_PROXY_CIDRS included, which renders byte-identically to before for its four consumers. BigBlueButton stays outside because its upstream pins both the block and its gateway, which meta/services.yml repeats as upstream_host 10.7.7.1. The exception list therefore carries the role id rather than the CIDR: the block is already declared in that role's meta/networks.yml, and repeating it here would be the same duplication one layer up. The role_subnets lookup resolves the ids and raises on a role that declares no subnet, because a silently dropped entry would narrow whatever firewall or trust list consumes the result. A lint keeps the declaration honest in both directions: every role subnet must sit in the declared space, and an exception whose block the pool already admits is rejected so it cannot outlive its reason. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
65 lines
2.2 KiB
Python
65 lines
2.2 KiB
Python
"""Lookup `role_subnets`: the local subnets other roles declare.
|
|
|
|
Single SPOT for "which address block does role X own". The block is declared
|
|
once, in that role's ``meta/networks.yml``; anything that has to reason about
|
|
the deployment's own address space reads it from here instead of repeating the
|
|
literal, which is how a CIDR ends up stated twice and then drifts.
|
|
|
|
Usage:
|
|
|
|
{{ lookup('role_subnets', 'web-app-bigbluebutton') }} # ['10.7.7.0/24']
|
|
{{ lookup('role_subnets', SOME_ROLE_LIST) }} # one entry per role
|
|
|
|
Terms may be role ids or lists of them, mixed. A role that declares no local
|
|
subnet raises, because a silently dropped entry would narrow whatever firewall
|
|
or trust list consumes the result.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from ansible.errors import AnsibleError
|
|
from ansible.plugins.loader import lookup_loader
|
|
from ansible.plugins.lookup import LookupBase
|
|
|
|
_SUBNET_PATH = "networks.local.subnet"
|
|
|
|
|
|
def _flattened(terms: list[Any]) -> list[str]:
|
|
roles: list[str] = []
|
|
for term in terms:
|
|
if isinstance(term, (list, tuple)):
|
|
roles.extend(str(entry).strip() for entry in term)
|
|
else:
|
|
roles.append(str(term).strip())
|
|
return [role for role in roles if role]
|
|
|
|
|
|
class LookupModule(LookupBase):
|
|
def run(
|
|
self,
|
|
terms: list[Any] | None,
|
|
variables: dict[str, Any] | None = None,
|
|
**kwargs: Any,
|
|
) -> list[Any]:
|
|
roles = _flattened(terms or [])
|
|
if not roles:
|
|
raise AnsibleError(
|
|
"lookup('role_subnets', <role id or list of role ids>) expects "
|
|
"at least one role id"
|
|
)
|
|
config = lookup_loader.get(
|
|
"config",
|
|
loader=getattr(self, "_loader", None),
|
|
templar=getattr(self, "_templar", None),
|
|
)
|
|
subnets: list[str] = []
|
|
for role in roles:
|
|
value = config.run([role, _SUBNET_PATH], variables=variables)[0]
|
|
text = "" if value is None else str(value).strip()
|
|
if not text:
|
|
raise AnsibleError(f"role_subnets: '{role}' declares no {_SUBNET_PATH}")
|
|
subnets.append(text)
|
|
return [subnets]
|