remove the old snapshot store; tombstone its options
This commit is contained in:
parent
de3c5cbb65
commit
20d286f06a
2 changed files with 97 additions and 1308 deletions
|
|
@ -2049,6 +2049,43 @@ let
|
|||
})
|
||||
&& !(refused allLocal);
|
||||
}
|
||||
{
|
||||
# One host defining all five removed paths. Each message names its own
|
||||
# path (`services.hyperhive.swarm.snapshotStore.port` does not contain
|
||||
# `services.hyperhive.snapshotStore.port`), so each lookup finds only
|
||||
# its option. The control is a host that defines none.
|
||||
name = "a definition of a removed snapshot store option fails evaluation, naming the option and swarm-archive";
|
||||
ok =
|
||||
let
|
||||
paths = [
|
||||
"swarm.snapshotStore.address"
|
||||
"swarm.snapshotStore.port"
|
||||
"snapshotStore.enable"
|
||||
"snapshotStore.path"
|
||||
"snapshotStore.port"
|
||||
];
|
||||
refused =
|
||||
m: path:
|
||||
lib.any (
|
||||
a:
|
||||
!a.assertion
|
||||
&& lib.hasInfix "services.hyperhive.${path}" a.message
|
||||
&& lib.hasInfix "agent-state backups are being rebuilt as swarm-archive" a.message
|
||||
) m.assertions;
|
||||
old = hive {
|
||||
swarm.snapshotStore = {
|
||||
address = "10.100.0.1";
|
||||
port = 51821;
|
||||
};
|
||||
snapshotStore = {
|
||||
enable = true;
|
||||
path = "/var/lib/hyperhive-snapshots";
|
||||
port = 51821;
|
||||
};
|
||||
};
|
||||
in
|
||||
lib.all (path: refused old path) paths && !(lib.any (path: refused bare path) paths);
|
||||
}
|
||||
{
|
||||
# Refused wherever any hyperhive service runs, the hive or a swarm
|
||||
# service alone. The host enabling nothing is the control that it is
|
||||
|
|
|
|||
|
|
@ -1,102 +0,0 @@
|
|||
# `checks.module-eval-snapshot-store` — see ./lib.nix for the shared
|
||||
# rationale (why this suite exists, naming convention, "evaluates not
|
||||
# executes").
|
||||
#
|
||||
# The snapshot store's receiver socket: where it listens, that it can bind
|
||||
# before the mesh interface is up, that it refuses a wildcard, and that a
|
||||
# silent or stalled transfer is bounded.
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
self,
|
||||
nixosSystem,
|
||||
}:
|
||||
let
|
||||
inherit
|
||||
(import ./lib.nix {
|
||||
inherit
|
||||
pkgs
|
||||
lib
|
||||
self
|
||||
nixosSystem
|
||||
;
|
||||
})
|
||||
hive
|
||||
runGroup
|
||||
;
|
||||
|
||||
# Bare hive: the store and the mesh it needs, nothing else.
|
||||
store = hive {
|
||||
deploy.wireguard.enable = true;
|
||||
deploy.wireguard.address = "10.100.0.1/24";
|
||||
snapshotStore.enable = true;
|
||||
snapshotStore.port = 51822;
|
||||
};
|
||||
|
||||
# The same with a wildcard where the mesh address goes.
|
||||
storeOnWildcard = hive {
|
||||
deploy.wireguard.enable = true;
|
||||
deploy.wireguard.address = "0.0.0.0/24";
|
||||
snapshotStore.enable = true;
|
||||
};
|
||||
|
||||
# The IPv6 wildcard.
|
||||
storeOnWildcardV6 = hive {
|
||||
deploy.wireguard.enable = true;
|
||||
deploy.wireguard.address = "::/64";
|
||||
snapshotStore.enable = true;
|
||||
};
|
||||
|
||||
unit = store.systemd.services."swarm-snapshot-store@";
|
||||
|
||||
moduleSource = builtins.readFile ../host-modules/swarm-snapshot-store.nix;
|
||||
|
||||
socket = store.systemd.sockets.swarm-snapshot-store.socketConfig;
|
||||
|
||||
refusedAsWildcard =
|
||||
m:
|
||||
lib.any (
|
||||
a: !a.assertion && lib.hasInfix "refuses a wildcard listen address" a.message
|
||||
) m.assertions;
|
||||
|
||||
cases = [
|
||||
{
|
||||
# The wg-hive address does not exist when sockets.target binds, so
|
||||
# without FreeBind the bind fails with EADDRNOTAVAIL and the receiver
|
||||
# never listens. The unit still renders and evaluates either way, which
|
||||
# is why only a rendered-config check can see it.
|
||||
name = "the receiver socket may bind before the mesh interface has its address";
|
||||
ok = socket.FreeBind or false == true;
|
||||
}
|
||||
{
|
||||
# The bare IP and the configured port: the prefix length on
|
||||
# `deploy.wireguard.address` must not leak into the listen address.
|
||||
name = "the receiver socket listens on the mesh address and the configured port";
|
||||
ok = socket.ListenStream == "10.100.0.1:51822";
|
||||
}
|
||||
{
|
||||
# The control for the case below: it is the wildcard that trips the
|
||||
# assertion, not the store being on.
|
||||
name = "a mesh address on the store raises no wildcard refusal";
|
||||
ok = !(refusedAsWildcard store);
|
||||
}
|
||||
{
|
||||
# A wildcard bind is an unauthenticated remote write into agent state.
|
||||
name = "a wildcard mesh address, IPv4 or IPv6, is refused";
|
||||
ok = refusedAsWildcard storeOnWildcard && refusedAsWildcard storeOnWildcardV6;
|
||||
}
|
||||
{
|
||||
# Without it a stalled `btrfs receive` holds a root instance forever.
|
||||
name = "the receiver unit has a runtime ceiling";
|
||||
ok = unit.serviceConfig.RuntimeMaxSec or null == "6h";
|
||||
}
|
||||
{
|
||||
# The script is a store path, so its text is not evaluable without
|
||||
# building it; the module source is the nearest thing to read. A
|
||||
# silent peer must not hold the root instance past the header read.
|
||||
name = "the receiver script bounds its header read";
|
||||
ok = lib.hasInfix "read -r -t \${toString headerTimeoutSeconds} keyword agent" moduleSource;
|
||||
}
|
||||
];
|
||||
in
|
||||
runGroup "snapshot-store" cases
|
||||
Loading…
Reference in a new issue