# `checks.module-eval-swarm-services-switch` — see ./lib.nix for the shared # rationale (why this suite exists, naming convention, "evaluates # not executes"). { pkgs, lib, self, nixosSystem, }: let inherit (import ./lib.nix { inherit pkgs lib self nixosSystem ; }) hive runGroup bridgePortsOrNone swarmServiceEnables ; # The swarm-services toggle with the central one off, so the only thing # that can enable the gateway/resolver/bridge here is that toggle's own # module — every other module that asserts them is behind `enable`. swarmServicesOnly = hive { enable = false; deploy.allSwarmServices = true; }; # Ports asked for on such a host. The request is the whole condition: the # firewall hole exists because an operator named a port, not because the # hive is running, and an agent reaching a host service is a claim about # the host's own listeners either way. exposedPortsNoHive = hive { enable = false; network.exposeHostPorts = [ 5432 ]; }; # The swarm UI where its own toggle is on — the control the absence arm # needs, since nothing else in this suite renders this vhost and an arm # saying "it is not there" would hold just as well if it were never there. # Package stubbed per this file's header: the vhost roots at it. swarmUiHere = hive { deploy.swarm-ui.enable = true; deploy.swarm-ui.package = pkgs.emptyDirectory; }; # The swarm's shared services hosted HERE without the all-local mode — a # services box with hives elsewhere, the shape ./host-modules/ # swarm-required-services.nix documents the switch for. swarmServicesHere = hive { deploy.allSwarmServices = true; }; # Same, with one of those services placed on another host. Every derivation # in that module is `mkDefault` so this stays expressible. swarmServicesBaoElsewhere = hive { deploy.allSwarmServices = true; deploy.bao.enable = false; }; cases = [ { # `lib.all` over an empty set holds vacuously, so the roster is counted # before it is read: a helper that lost a member would otherwise turn # this case green by measuring nothing. name = "hosting the swarm's shared services turns on every service that switch owns"; ok = let es = swarmServiceEnables swarmServicesHere; in lib.length (lib.attrNames es) == 9 && lib.all lib.id (lib.attrValues es); } { # The switch fills in for an operator who has not spoken and yields to # one who has — that is what keeps a shared service placeable on a host # of its own. A plain assignment or `mkForce` would satisfy both cases # above and break this one. `nats` is the control: without it the case # also passes on a fixture where nothing came on at all. name = "placing one shared service elsewhere survives the switch that would enable it"; ok = let es = swarmServiceEnables swarmServicesBaoElsewhere; in !es.bao && es.nats; } { # The controller sits on the OTHER tier: `singleHostSwarm` places it # (./host-modules/local-defaults.nix) and swarm-ui follows the # controller. Pinned so that moving a service between tiers is a # decision someone makes rather than a merge nobody reads. name = "hosting the swarm's shared services does not make a hive the swarm's control plane"; ok = !swarmServicesHere.services.hyperhive.deploy.swarm-controller.enable && !swarmServicesHere.services.hyperhive.deploy.swarm-ui.enable; } { # Control for the arm above, and the one place this slice is not inert: # the ports are opened because they were named, on a host that never # turned the hive on. The bridge firewall is the host's own, so there is # nothing here for the hive toggle to have been protecting. name = "a named exposeHostPorts opens its bridge port on the host's own say-so"; ok = builtins.elem 5432 (bridgePortsOrNone exposedPortsNoHive); } { name = "the swarm UI claims the swarm apex where this host serves it"; ok = swarmUiHere.services.nginx.virtualHosts ? "t.local"; } { # The swarm-services toggle enables them explicitly, from its own # module rather than from any of their defaults. name = "the swarm-services toggle turns on the gateway, resolver and bridge by itself"; ok = swarmServicesOnly.services.hyperhive.gateway.enable && swarmServicesOnly.services.hyperhive.gateway.dns.enable && swarmServicesOnly.services.hyperhive.network.enable; } { # An operator's explicit `false` beats every `mkDefault` assertion, # which is what keeps "asserted by whoever needs it" from being a # setting the operator cannot turn off. name = "an explicit gateway.enable = false wins over the modules asserting it"; ok = !(hive { gateway.enable = false; }).services.nginx.enable; } ]; in runGroup "swarm-services-switch" cases