utils.networks package

Submodules

utils.networks.address module

Derive an address-matching regex from a role’s local subnet.

A swarm task is attached to several site-local networks at once, so a service that must bind to one specific network cannot be told “pick a site-local address” - it needs a matcher for the one subnet it owns.

utils.networks.address.subnet_address_regex(subnet: str) → str

Return a regex matching every address inside subnet, and no other.

A prefix mask leaves a contiguous run of low bits free, so per octet the addresses span exactly network_address to broadcast_address. The cross product of those four ranges is the network, which makes the octet decomposition exact for any prefix length, aligned or not.

Parameters:

subnet – IPv4 network in CIDR notation, e.g. 192.168.24.0/24.

Returns:

A regex over dotted octets, e.g. 192\.168\.24\.\d+ for a /24 or 192\.168\.(24|25)\.\d+ for a /23.

Raises:

ValueError – the notation is malformed or carries host bits.

utils.networks.address.subnet_gateway(subnet: str) → str

Return the address Docker assigns as the gateway of subnet.

Parameters:

subnet – IPv4 network in CIDR notation, e.g. 192.168.24.0/24.

Returns:

The first usable address, e.g. 192.168.24.1.

Raises:

ValueError – the notation is malformed, carries host bits, or the network is too small to hold a gateway.

utils.networks.attachments module

Attachment computation for the compose networks renderers.

Which provider overlays a role attaches to, and which proxy aliases the default network harvests, derived from the service_registry. Kept apart from the emitters in utils.networks.render so a change to the consumer rules cannot be confused with a change to the YAML they produce.

utils.networks.lookup_context module

Shared Ansible-side assembly for the network lookup plugins.

Every one of them needs the same four things before it can call into utils.networks.render: the resolved variables, the deployment mode, a service registry built from the merged applications, and closures over the config and database lookups. Building that once means a change to how the registry or the closures are obtained cannot reach one lookup and miss another.

Args of build_context() are documented on the function.

class utils.networks.lookup_context.NetworkLookupContext(vars: dict[str, Any], templar: Any, deployment_mode: str, registry: dict[str, dict[str, Any]], lookup_config: Callable[[str, str, Any], Any], lookup_database: Callable[[str, str], Any])

Bases: object

What a network lookup needs to call the renderers.

deployment_mode: str
lookup_config: Callable[[str, str, Any], Any]
lookup_database: Callable[[str, str], Any]
registry: dict[str, dict[str, Any]]
templar: Any
vars: dict[str, Any]
utils.networks.lookup_context.build_context(lookup: Any, variables: dict[str, Any] | None, *, honour_mode_force: bool = True) → NetworkLookupContext

Assemble the shared context for a network lookup.

Parameters:
  • lookup – the LookupModule instance, for its templar and loader.

  • variables – the variables Ansible passed to run.

  • honour_mode_force – let compose_mode_force override DEPLOYMENT_MODE.

utils.networks.lookup_context.resolve_var(templar: Any, value: Any) → Any

Template value when a templar is available, else pass it through.

Parameters:
  • templar – the plugin’s templar, or None.

  • value – raw variable value.

utils.networks.mesh module

utils.networks.mesh.address_on(applications: Any, host: str, mesh: str) → str
utils.networks.mesh.declared_meshes(applications: Any) → list[Mapping[str, Any]]
utils.networks.mesh.dialled_peers(interface: Mapping[str, Any]) → list[Mapping[str, Any]]
utils.networks.mesh.interfaces(applications: Any) → list[Mapping[str, Any]]
utils.networks.mesh.is_full(interface: Mapping[str, Any]) → bool
utils.networks.mesh.joined_meshes(applications: Any, roles: Iterable[str]) → dict[str, list[str]]

Mesh name to the roles that put the host into it.

Parameters:
  • applications – the host’s applications block.

  • roles – the role groups the host belongs to.

utils.networks.mesh.listens(interface: Mapping[str, Any]) → bool
utils.networks.mesh.owned_interface(applications: Any, host: str, mesh: str) → Mapping[str, Any] | None
utils.networks.mesh.primary_address(applications: Any, host: str) → str

utils.networks.proxy module

Mode-aware nginx proxy_pass directive renderer (compose/swarm), SPOT.

Trip-wire: the swarm oauth2 endpoint must forward $uri$is_args$args, not $request_uri — during error_page 401 = /oauth2/start the original $request_uri stays / and oauth2-proxy 403s instead of redirecting.

utils.networks.proxy.render_proxy_pass(authority: str, deployment_mode: str, tail: str = 'request', location: str = '/', host_gateway: bool = False) → str

proxy_pass directive; swarm prepends a set line (request-time DNS).

A host_gateway upstream resolves through host.docker.internal in /etc/hosts (host gateway), which the request-time resolver cannot see, so it renders as a literal directive like compose.

utils.networks.proxy.resolve_upstream(applications: dict[str, Any], application_id: str, service_key: str, port_kind: str, deployment_mode: str, local_port: str = '', internal_port: str = '', host_gateway: bool = False) → str

Upstream host:port: compose 127.0.0.1:<local>; swarm <entity>:<internal> (shared-overlay alias) for the app frontend, or <entity>_<service_key>:<internal> for named sidecars (sso-proxy). A host_gateway app runs node-local under swarm and publishes its local port to the host, so the overlay-attached proxy reaches it at host.docker.internal:<local> via the host gateway (the caller sets this off the real DEPLOYMENT_MODE, since such apps force a compose-style render). Missing swarm internal port hard-fails.

utils.networks.render module

Pure-Python rendering of compose networks blocks fed by the service_registry.

Two callable surfaces, mirroring what roles/sys-svc-compose/templates/networks.yml.j2 and roles/sys-svc-container/templates/networks.yml.j2 used to emit:

The schema lives at meta/networks.yml.overlay per provider role, discovered into the service_registry by discover_role_services. Keys:

  • modes: list of DEPLOYMENT_MODE values where this overlay applies

  • topology: shared_net | default_net. Absent = beacon-only (no attachment)

  • aliases: list of DNS aliases. Default: [entity_name] for shared_net, [] for default_net

  • consumer: optional override
    • kind: services_flags (default) | database | mcp_client | web_facing | onion_sso. mcp_client admits a role only when its mcp.direction is client or both AND it declares services.<own-entity>.mcp_consumer: true without the provider refusing it through mcp_consumer: false on that same entry, so a provider’s network carries the clients it admitted rather than every client in the deployment. Being a client is not an admission: without the second condition one admission anywhere reaches every provider that opens its overlay.

    • key: services.<key>.* lookup base. Default: provides or entity_name

    • flags: list of flags to AND. Default: [enabled, shared]

      (services_flags only)

    • provider / provider_key: for onion_sso, the app whose

      services.<provider_key>.enabled must also hold. Default provider_key tor

  • proxy_resolvable: beacon flag - the harvested aliases get attached to

    every default_net provider and every collect_proxy_resolvable provider in the same mode.

  • proxy_aliases: aliases the beacon exposes for harvesting; falls back

    to aliases. Set it when the overlay also has a topology whose own aliases (e.g. the entity name) must NOT land on the proxy.

utils.networks.render.compute_external_network_roles(*, application_id: str, deployment_mode: str, registry: dict[str, dict[str, Any]], lookup_config: Callable[[str, str, Any], Any], lookup_database: Callable[[str, str], Any]) → list[str]

Provider role names whose overlay render_compose_networks emits as external: true for application_id. Mirrors the attachment filter in render_compose_networks() (every attachment except a default_net the app provides itself). Used to pre-create those swarm overlays before docker stack deploy: a consumer can reference a shared provider’s network without that provider role having run in the same play, so the overlay would otherwise be missing at deploy time.

utils.networks.render.render_compose_networks(*, application_id: str, deployment_mode: str, registry: dict[str, dict[str, Any]], get_entity_name: Callable[[str], str], lookup_config: Callable[[str, str, Any], Any], lookup_database: Callable[[str, str], Any], swarm_encrypted: bool = True, node_local: bool = False) → str
utils.networks.render.render_container_networks(*, application_id: str, deployment_mode: str, registry: dict[str, dict[str, Any]], get_entity_name: Callable[[str], str], lookup_config: Callable[[str, str, Any], Any], lookup_database: Callable[[str, str], Any], provider_self_alias: bool = True, node_local: bool = False, own_network_only: bool = False) → str
utils.networks.render.shared_network_compose_key(*, application_id: str, deployment_mode: str, registry: dict[str, dict[str, Any]], get_entity_name: Callable[[str], str], lookup_config: Callable[[str, str, Any], Any], lookup_database: Callable[[str, str], Any], node_local: bool = False) → str

Key under which the pre-created <entity> network appears in the rendered compose file, which is what docker compose stores in the com.docker.compose.network label. An app that provides its own shared_net gets that network under its entity key and renders a separate unnamed default; every other app renders default with the entity as its name. render_compose_networks() derives its own branch from this same call, so the label a caller stamps cannot drift from what is rendered.

Parameters:
  • application_id – role the network belongs to.

  • deployment_mode – compose or swarm.

  • registry – service registry built from the merged applications.

  • get_entity_name – role id to entity name.

  • lookup_config – config value accessor.

  • lookup_database – database value accessor.

  • node_local – render as compose regardless of deployment_mode.

Module contents