nix: drop module-eval rename/removal shim tests
mkRenamedOptionModule/mkRemovedOptionModule are nixpkgs' own tested machinery; proving each call site resolves is redundant with what the library already guarantees. Removes 10 of the ~79 full nixosSystem fixtures (wireguard/forge/matrix/controller/ui/stores/statusPublish/ peers old-path + matrixMovedAppserviceToken/matrixRemovedToken) and their 15 dedicated cases. Fixtures still exercised by genuine behavioral cases (natsOldPath, autheliaOldPath, grafanaOldPath) are kept, minus their now-redundant rename-only case.
This commit is contained in:
parent
15424d3e49
commit
27803e9b97
1 changed files with 0 additions and 338 deletions
|
|
@ -120,73 +120,6 @@ let
|
||||||
|
|
||||||
withCi = hive { deploy.forgejo.ci.enable = true; };
|
withCi = hive { deploy.forgejo.ci.enable = true; };
|
||||||
|
|
||||||
# A host configured against the pre-rename option path. `mkRenamedOptionModule`
|
|
||||||
# is the only thing carrying it, and nothing else in this suite would notice
|
|
||||||
# if it were dropped: the new path evaluates fine on its own, so a missing
|
|
||||||
# shim reads as a clean tree and breaks every existing operator config.
|
|
||||||
wireguardOldPath = hive {
|
|
||||||
swarm.wireguard.enable = true;
|
|
||||||
swarm.wireguard.address = "10.100.0.1/24";
|
|
||||||
swarm.wireguard.privateKeyFile = "/etc/wireguard/hive.key";
|
|
||||||
};
|
|
||||||
|
|
||||||
# Same shape for the forge, which SPLIT rather than moving whole: the six
|
|
||||||
# host-side options are set here through their pre-rename paths while the
|
|
||||||
# rest of `swarm.forge` stays put. All six are defined so that dropping any
|
|
||||||
# single shim entry fails the eval, not just the two the assertion reads.
|
|
||||||
forgeOldPath = hive {
|
|
||||||
swarm.forge.package = pkgs.emptyDirectory;
|
|
||||||
swarm.forge.behindGateway = true;
|
|
||||||
swarm.forge.openFirewall = true;
|
|
||||||
swarm.forge.hostSwarmControllerTokenFile = "/etc/forge/sc.token";
|
|
||||||
swarm.forge.sso.clientSecretFile = "/etc/forge/oidc.secret";
|
|
||||||
swarm.forge.mirrors = [
|
|
||||||
{
|
|
||||||
upstream = "https://example.invalid/tool";
|
|
||||||
dest = "mirrors/tool";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
# The homeserver's turn to split. All seven remaining host-side options are
|
|
||||||
# set through their pre-rename paths — including `gui.enable`, whose value is
|
|
||||||
# deliberately the opposite of its default so the definition has to actually
|
|
||||||
# land, and both packages, stubbed to a derivation neither option defaults to
|
|
||||||
# for the same reason. All seven so that dropping any single shim entry fails
|
|
||||||
# the eval, not just the ones the assertions read.
|
|
||||||
#
|
|
||||||
# `registrationTokenFile` used to be the eighth: both spellings of it are now
|
|
||||||
# `mkRemovedOptionModule`, exercised by `matrixRemovedToken` below instead —
|
|
||||||
# setting it here would make every case that reads this fixture fail on that
|
|
||||||
# one removed option.
|
|
||||||
matrixOldPath = hive {
|
|
||||||
deploy.matrix.enable = true;
|
|
||||||
swarm.matrix.openFirewall = true;
|
|
||||||
swarm.matrix.trustedServers = [ "matrix.example.invalid" ];
|
|
||||||
swarm.matrix.maxRequestSize = 31457280;
|
|
||||||
swarm.matrix.gui.enable = false;
|
|
||||||
swarm.matrix.package = pkgs.emptyDirectory;
|
|
||||||
swarm.matrix.gui.package = pkgs.emptyDirectory;
|
|
||||||
swarm.matrix.sso.clientSecretFile = "/etc/matrix/oidc.secret";
|
|
||||||
};
|
|
||||||
|
|
||||||
# Moving the appservice token, which desyncs hive-c0re's independently
|
|
||||||
# derived path from the homeserver's. Its own fixture because the assertion
|
|
||||||
# it trips would otherwise fire for every case reading `matrixOldPath`.
|
|
||||||
matrixMovedAppserviceToken = hive {
|
|
||||||
deploy.matrix.enable = true;
|
|
||||||
deploy.matrix.appserviceTokenFile = "/etc/matrix/as.token";
|
|
||||||
swarm.matrix.sso.clientSecretFile = "/etc/matrix/oidc.secret";
|
|
||||||
};
|
|
||||||
|
|
||||||
# A config still naming the removed registration token, through the
|
|
||||||
# pre-rename spelling — the one an old deployment is most likely to carry.
|
|
||||||
matrixRemovedToken = hive {
|
|
||||||
deploy.matrix.enable = true;
|
|
||||||
swarm.matrix.registrationTokenFile = "/etc/matrix/register.token";
|
|
||||||
swarm.matrix.sso.clientSecretFile = "/etc/matrix/oidc.secret";
|
|
||||||
};
|
|
||||||
|
|
||||||
# The queue's callout identity, fourth split slice. `autoGenerateCallout` is
|
# The queue's callout identity, fourth split slice. `autoGenerateCallout` is
|
||||||
# left FALSE on purpose: that is what makes the seed paths the thing deciding
|
# left FALSE on purpose: that is what makes the seed paths the thing deciding
|
||||||
# `responderConfigured`, so the assertion below is about the seeds rather
|
# `responderConfigured`, so the assertion below is about the seeds rather
|
||||||
|
|
@ -233,39 +166,6 @@ let
|
||||||
deploy.matrix.maxRequestSize = 99000000;
|
deploy.matrix.maxRequestSize = 99000000;
|
||||||
};
|
};
|
||||||
|
|
||||||
# `enable` is spelled the OLD way like everything else here, so all six
|
|
||||||
# of the controller's shims are exercised rather than five.
|
|
||||||
controllerOldPath = hive {
|
|
||||||
swarm.controller.enable = true;
|
|
||||||
swarm.controller.package = pkgs.emptyDirectory;
|
|
||||||
swarm.controller.swarmctlPackage = pkgs.emptyDirectory;
|
|
||||||
swarm.controller.forgeTokenFile = "/run/secrets/ctrl-forge.token";
|
|
||||||
swarm.controller.authBridgeUrl = "http://127.0.0.1:19097";
|
|
||||||
swarm.controller.queue.clientSecretFile = "/run/secrets/ctrl-queue.secret";
|
|
||||||
};
|
|
||||||
|
|
||||||
# The swarm UI, whose namespace this slice empties: `swarm.ui` had exactly
|
|
||||||
# two options and both have moved, so BOTH old paths are set here and the
|
|
||||||
# whole namespace now lives or dies by its two rename entries.
|
|
||||||
uiOldPath = hive {
|
|
||||||
swarm.ui.enable = true;
|
|
||||||
swarm.ui.package = pkgs.emptyDirectory;
|
|
||||||
};
|
|
||||||
|
|
||||||
# The two stores, which had NO old-path fixture at all until this slice —
|
|
||||||
# their `enable` and `retentionPeriod` shims have been uncovered since they
|
|
||||||
# landed, which is precisely the "a missing shim reads as a clean tree"
|
|
||||||
# failure ./module-eval.nix's wireguard fixture was written to catch. All six
|
|
||||||
# old paths are set, so dropping any single entry fails the eval.
|
|
||||||
storesOldPath = hive {
|
|
||||||
swarm.victoriametrics.enable = true;
|
|
||||||
swarm.victorialogs.enable = true;
|
|
||||||
swarm.victoriametrics.retentionPeriod = "3d";
|
|
||||||
swarm.victorialogs.retentionPeriod = "5d";
|
|
||||||
swarm.victoriametrics.package = pkgs.emptyDirectory;
|
|
||||||
swarm.victorialogs.package = pkgs.emptyDirectory;
|
|
||||||
};
|
|
||||||
|
|
||||||
grafanaOldPath = hive {
|
grafanaOldPath = hive {
|
||||||
deploy.grafana.enable = true;
|
deploy.grafana.enable = true;
|
||||||
swarm.grafana.socketDir = "/run/test-grafana-sock";
|
swarm.grafana.socketDir = "/run/test-grafana-sock";
|
||||||
|
|
@ -342,37 +242,6 @@ let
|
||||||
&& lib.hasInfix option a.message
|
&& lib.hasInfix option a.message
|
||||||
) m.assertions;
|
) m.assertions;
|
||||||
|
|
||||||
# The first slice to leave options on BOTH sides of the split, so the
|
|
||||||
# fixture sets all three of them through the paths an existing config uses:
|
|
||||||
# the two movers via their rename entries, `tokenEndpoint` via the path it
|
|
||||||
# kept. That is also what the all-or-nothing assertion wants, so this hive
|
|
||||||
# is a valid one rather than one that only evaluates because nothing forced
|
|
||||||
# the assertion.
|
|
||||||
statusPublishOldPath = hive {
|
|
||||||
swarm.statusPublish.natsUrl = "nats://10.0.0.9:4222";
|
|
||||||
swarm.statusPublish.tokenEndpoint = "https://auth.example.invalid/api/oidc/token";
|
|
||||||
swarm.statusPublish.clientSecretFile = "/run/secrets/status-client.secret";
|
|
||||||
};
|
|
||||||
|
|
||||||
# The eleventh migration, and the only one of the eleven with no old-path
|
|
||||||
# fixture. It differs from its ten siblings in what a shim DOES: the others
|
|
||||||
# re-route a value, so a broken one shows up as a wrong rendered config. This
|
|
||||||
# one's entire deliverable is a warning, which nothing reads back — so an
|
|
||||||
# unevaluated shim is a warning nobody sees, and it fails silently onto the
|
|
||||||
# one operator who needed it.
|
|
||||||
#
|
|
||||||
# Two peers, only ONE carrying `caCert`, because the module emits a SECOND
|
|
||||||
# warning filtered on exactly that attribute. With a single peer the filtered
|
|
||||||
# list and `attrNames` are the same list, and a `withCaCert` that had
|
|
||||||
# collapsed into `attrNames` would still read green.
|
|
||||||
peersOldPath = hive {
|
|
||||||
swarm.peers.old-one.domain = "old-one.t.local";
|
|
||||||
swarm.peers.old-two = {
|
|
||||||
domain = "old-two.t.local";
|
|
||||||
caCert = "/etc/ssl/old-two-ca.pem";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
baoPkcs11 = hive {
|
baoPkcs11 = hive {
|
||||||
deploy.bao.enable = true;
|
deploy.bao.enable = true;
|
||||||
deploy.bao.seal = "pkcs11";
|
deploy.bao.seal = "pkcs11";
|
||||||
|
|
@ -996,83 +865,6 @@ let
|
||||||
name = "the all-local mode turns the swarm controller on";
|
name = "the all-local mode turns the swarm controller on";
|
||||||
ok = allLocal.services.hyperhive.deploy.swarm-controller.enable;
|
ok = allLocal.services.hyperhive.deploy.swarm-controller.enable;
|
||||||
}
|
}
|
||||||
{
|
|
||||||
# The mesh moved namespace wholesale, so an existing config sets paths
|
|
||||||
# that no longer exist. Reading the *rendered interface* rather than the
|
|
||||||
# option: a rename that resolved but stopped reaching the module would
|
|
||||||
# satisfy an option-level check and still bring up no tunnel.
|
|
||||||
name = "a config written against the pre-rename wireguard path still configures the interface";
|
|
||||||
ok =
|
|
||||||
let
|
|
||||||
wg = wireguardOldPath.networking.wireguard.interfaces.wg-hive;
|
|
||||||
in
|
|
||||||
wg.ips == [ "10.100.0.1/24" ] && wg.privateKeyFile == "/etc/wireguard/hive.key";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
# Same reasoning one namespace over, plus the shape the mesh did not
|
|
||||||
# have: `mirrors` is a single option of a list-of-submodule type, so its
|
|
||||||
# one rename entry has to carry a whole compound value rather than a
|
|
||||||
# scalar. Both arms read a rendered effect — the host firewall and the
|
|
||||||
# env var c0re seeds mirrors from — not the option.
|
|
||||||
name = "a config written against the pre-rename forge paths still opens the firewall and seeds the mirror";
|
|
||||||
ok =
|
|
||||||
let
|
|
||||||
ports = forgeOldPath.networking.firewall.allowedTCPPorts;
|
|
||||||
seeded = builtins.fromJSON forgeOldPath.systemd.services.hive-c0re.environment.HYPERHIVE_FORGE_MIRRORS;
|
|
||||||
in
|
|
||||||
builtins.elem 3000 ports && builtins.any (m: m.dest == "mirrors/tool") seeded;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
# Third split, and the one whose readers were hardest to see: the
|
|
||||||
# appservice token is read only through a `let` alias in another
|
|
||||||
# module, so no full path names it anywhere. Both arms read a rendered
|
|
||||||
# effect — the host firewall and the container's bind-mount table — so a
|
|
||||||
# rename that resolves but stops reaching the module still fails.
|
|
||||||
name = "a config written against the pre-rename matrix paths still opens the port and mounts the appservice registration";
|
|
||||||
ok =
|
|
||||||
let
|
|
||||||
ports = matrixOldPath.networking.firewall.allowedTCPPorts;
|
|
||||||
httpPort = matrixOldPath.services.hyperhive.swarm.matrix.httpPort;
|
|
||||||
in
|
|
||||||
builtins.elem httpPort ports
|
|
||||||
&& matrixOldPath.containers.hive-matrix.bindMounts ? "/var/lib/hyperhive/matrix-appservice";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
# appserviceTokenFile has no override capability (a store-delivered
|
|
||||||
# secret doesn't need one — glue-matrix-bao-token.nix writes into the
|
|
||||||
# fixed path instead of moving it), unlike its siblings in the same
|
|
||||||
# rename. The fixture proves the override still *resolves* (mkDefault,
|
|
||||||
# not a crash); this proves it also gets *rejected*, by a named
|
|
||||||
# assertion rather than nixpkgs' generic conflicting-definition text.
|
|
||||||
# Reads `.assertions` directly (cheap: a list of `{assertion;
|
|
||||||
# message;}`, not `system.build.toplevel`) rather than forcing a real
|
|
||||||
# build just to observe a boolean.
|
|
||||||
name = "moving appserviceTokenFile trips a named assertion, not a silent desync";
|
|
||||||
ok = lib.any (
|
|
||||||
a: !a.assertion && lib.hasInfix "appserviceTokenFile" a.message
|
|
||||||
) matrixMovedAppserviceToken.assertions;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
# The removal has to SAY so. A config carrying the old option through
|
|
||||||
# an upgrade is the common case, and nixpkgs' bare "option does not
|
|
||||||
# exist" would name neither what replaced the token nor where to read
|
|
||||||
# about it.
|
|
||||||
name = "a config still setting registrationTokenFile is refused with a message naming the appservice";
|
|
||||||
ok = lib.any (a: !a.assertion && lib.hasInfix "appservice" a.message) matrixRemovedToken.assertions;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
# Reads the DELIVERY UNIT, not the options: `responderConfigured` gates
|
|
||||||
# whether it exists at all, and the seed path is interpolated into its
|
|
||||||
# script. A rename that resolved but stopped reaching the module would
|
|
||||||
# leave the responder with no credentials and this case would catch it.
|
|
||||||
name = "a config written against the pre-rename nats paths still delivers the responder's seeds";
|
|
||||||
ok =
|
|
||||||
let
|
|
||||||
units = natsOldPath.systemd.services;
|
|
||||||
in
|
|
||||||
units ? swarm-nats-auth-secrets
|
|
||||||
&& lib.hasInfix "/run/secrets/nats-user.seed" units.swarm-nats-auth-secrets.script;
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
# Reads the RENDERED settings, not the option: `calloutBlocks {…} // {
|
# Reads the RENDERED settings, not the option: `calloutBlocks {…} // {
|
||||||
# … }` is a shallow merge, and a future edit that dropped or shadowed
|
# … }` is a shallow merge, and a future edit that dropped or shadowed
|
||||||
|
|
@ -1121,39 +913,6 @@ let
|
||||||
in
|
in
|
||||||
lib.hasInfix "--agent-publish-subject '$$SWARM.agent-state.{hive}.>'" exec;
|
lib.hasInfix "--agent-publish-subject '$$SWARM.agent-state.{hive}.>'" exec;
|
||||||
}
|
}
|
||||||
{
|
|
||||||
# Reads the host's tmpfiles rules, not the options: the socket directory
|
|
||||||
# nginx and the container share is created there, so a rename that
|
|
||||||
# resolved but stopped reaching the module would leave the gateway
|
|
||||||
# proxying to a path nothing creates. All three old paths are defined
|
|
||||||
# in the fixture, so removing any single shim fails the eval rather
|
|
||||||
# than only the one this assertion reads.
|
|
||||||
# THREE movers (authBridgeUrl, forgeTokenFile, queue.clientSecretFile)
|
|
||||||
# are asserted as rendered effects rather than as option values, so a
|
|
||||||
# rename that resolved but stopped reaching the module is caught
|
|
||||||
# per-option instead of only where one assertion happens to look.
|
|
||||||
# socketPath is no longer one of them: it went readOnly and lost its
|
|
||||||
# shim in the same slice, so it has no pre-rename path left to prove
|
|
||||||
# reaches the unit — the SOCKET line below instead pins the one value
|
|
||||||
# it can ever hold, the default, so the env var vanishing or being
|
|
||||||
# misspelled still fails this arm.
|
|
||||||
name = "a config written against the pre-rename swarm-controller paths still reaches the unit";
|
|
||||||
ok =
|
|
||||||
let
|
|
||||||
u = controllerOldPath.systemd.services.swarm-controller;
|
|
||||||
creds = u.serviceConfig.LoadCredential;
|
|
||||||
in
|
|
||||||
u.environment.SWARM_CONTROLLER_SOCKET == "/run/swarm-controller/controller.sock"
|
|
||||||
&& u.environment.SWARM_CONTROLLER_AUTH_BRIDGE_URL == "http://127.0.0.1:19097"
|
|
||||||
&& lib.any (c: lib.hasInfix "/run/secrets/ctrl-queue.secret" c) creds
|
|
||||||
&& lib.any (c: lib.hasInfix "/run/secrets/ctrl-forge.token" c) creds;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "a config written against the pre-rename grafana paths still creates the socket directory";
|
|
||||||
ok = lib.any (
|
|
||||||
rule: lib.hasInfix "/run/test-grafana-sock" rule
|
|
||||||
) grafanaOldPath.systemd.tmpfiles.rules;
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
# This fixture enables grafana and NOT authelia, which is the shape the
|
# This fixture enables grafana and NOT authelia, which is the shape the
|
||||||
# login form used to stay enabled in: the toggle read "both services are
|
# login form used to stay enabled in: the toggle read "both services are
|
||||||
|
|
@ -1360,25 +1119,6 @@ let
|
||||||
&& otelNoIdentity.services.hyperhive.deploy.swarm-otel.clientSecretFile == null
|
&& otelNoIdentity.services.hyperhive.deploy.swarm-otel.clientSecretFile == null
|
||||||
&& !(lib.any (a: !a.assertion) otelNoIdentity.assertions);
|
&& !(lib.any (a: !a.assertion) otelNoIdentity.assertions);
|
||||||
}
|
}
|
||||||
{
|
|
||||||
# Reads the daemon's rendered unit, not the options: the queue address
|
|
||||||
# arrives as an env var whose whole attrset is guarded on `natsUrl`, and
|
|
||||||
# the secret as a systemd credential. A rename that resolved but stopped
|
|
||||||
# reaching the module leaves hive-c0re coming up perfectly and reporting
|
|
||||||
# to nobody, which is the one failure this option set exists to prevent.
|
|
||||||
# The third arm is the option that did NOT move, read out of the same
|
|
||||||
# attrset: the guard and the value beside it now come from different
|
|
||||||
# namespaces, so a hive that renders one and drops the other is exactly
|
|
||||||
# what a split can silently produce.
|
|
||||||
name = "a config written against the pre-rename statusPublish paths still reaches the daemon";
|
|
||||||
ok =
|
|
||||||
let
|
|
||||||
u = statusPublishOldPath.systemd.services.hive-c0re;
|
|
||||||
in
|
|
||||||
u.environment.HIVE_C0RE_NATS_URL == "nats://10.0.0.9:4222"
|
|
||||||
&& u.environment.HIVE_C0RE_OIDC_TOKEN_ENDPOINT == "https://auth.example.invalid/api/oidc/token"
|
|
||||||
&& lib.any (c: lib.hasInfix "/run/secrets/status-client.secret" c) u.serviceConfig.LoadCredential;
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
# The collector's half of the same split, and a different arm from the
|
# The collector's half of the same split, and a different arm from the
|
||||||
# authenticator case below: this one reads the PATH the unit loads, so a
|
# authenticator case below: this one reads the PATH the unit loads, so a
|
||||||
|
|
@ -2343,43 +2083,6 @@ let
|
||||||
# steps live in the same script and one indentation level decides it.
|
# steps live in the same script and one indentation level decides it.
|
||||||
&& lib.hasInfix "bao secrets enable -path=secret kv-v2" s;
|
&& lib.hasInfix "bao secrets enable -path=secret kv-v2" s;
|
||||||
}
|
}
|
||||||
{
|
|
||||||
# Reads the vhost's rendered `root`, not the option: the UI is served
|
|
||||||
# straight out of a store path, so a shim that resolves but stops
|
|
||||||
# reaching the module would leave nginx pointing at the default build.
|
|
||||||
name = "a config written against the pre-rename swarm-ui paths still serves the operator's build";
|
|
||||||
#
|
|
||||||
# ⚠️ `unsafeDiscardStringContext` on both sides, load-bearing rather than
|
|
||||||
# tidy: interpolating a derivation carries string *context*, and this
|
|
||||||
# suite renders its results into a `buildCommand` that may not reference
|
|
||||||
# store paths. Comparing the paths as plain text is the intent — the case
|
|
||||||
# asks "does nginx point HERE", not "depend on what it points at".
|
|
||||||
ok =
|
|
||||||
let
|
|
||||||
want = builtins.unsafeDiscardStringContext "${pkgs.emptyDirectory}";
|
|
||||||
# `or ""` is NOT enough: nginx's `locations.<l>.root` is `nullOr`, so
|
|
||||||
# a vhost that HAS the attribute set to null skips the default and
|
|
||||||
# reaches the coercion. Filter nulls, then discard context.
|
|
||||||
roots = map builtins.unsafeDiscardStringContext (
|
|
||||||
lib.filter (r: r != null) (
|
|
||||||
map (v: v.locations."/".root or null) (builtins.attrValues uiOldPath.services.nginx.virtualHosts)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
in
|
|
||||||
builtins.elem want roots;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
# Reads the package the CONTAINER renders, not the option: a shim that
|
|
||||||
# resolves but stops reaching the module would leave the store running
|
|
||||||
# nixpkgs' default while the operator's override read back fine.
|
|
||||||
name = "a config written against the pre-rename store paths still picks the operator's package";
|
|
||||||
ok =
|
|
||||||
storesOldPath.containers.swarm-victorialogs.config.services.victorialogs.package
|
|
||||||
== pkgs.emptyDirectory
|
|
||||||
&&
|
|
||||||
storesOldPath.containers.swarm-victoriametrics.config.services.victoriametrics.package
|
|
||||||
== pkgs.emptyDirectory;
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
# What makes the granting-unit cases mean something, and the property
|
# What makes the granting-unit cases mean something, and the property
|
||||||
# the host-side half depends on: no store here, so no bind mount and no
|
# the host-side half depends on: no store here, so no bind mount and no
|
||||||
|
|
@ -2388,47 +2091,6 @@ let
|
||||||
name = "a bootstrap token on a host that runs no store grants nothing";
|
name = "a bootstrap token on a host that runs no store grants nothing";
|
||||||
ok = !(baoGrantNoStore.systemd.services ? swarm-bao-bootstrap-dir);
|
ok = !(baoGrantNoStore.systemd.services ? swarm-bao-bootstrap-dir);
|
||||||
}
|
}
|
||||||
{
|
|
||||||
# Matches the option path, not the surrounding prose: the warning should
|
|
||||||
# stay rewordable, but it must not stop naming what was set or where it
|
|
||||||
# went.
|
|
||||||
name = "a config still setting the removed swarm.peers is told where the entries moved";
|
|
||||||
ok =
|
|
||||||
let
|
|
||||||
hit = lib.filter (
|
|
||||||
w: lib.hasInfix "services.hyperhive.swarm.peers is removed" w
|
|
||||||
) peersOldPath.warnings;
|
|
||||||
in
|
|
||||||
lib.length hit == 1
|
|
||||||
&& lib.hasInfix "services.hyperhive.swarm.hives" (lib.head hit)
|
|
||||||
&& lib.hasInfix "old-one, old-two" (lib.head hit);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
# The caCert half is a separately filtered warning, so it has to name
|
|
||||||
# ONLY the peer that set one. Asserting the peer that did NOT is absent
|
|
||||||
# is what distinguishes the filter from `attrNames`.
|
|
||||||
name = "the removed peers.caCert warns about only the peers that set one";
|
|
||||||
ok =
|
|
||||||
let
|
|
||||||
hit = lib.filter (w: lib.hasInfix "caCert is removed" w) peersOldPath.warnings;
|
|
||||||
in
|
|
||||||
lib.length hit == 1
|
|
||||||
&& lib.hasInfix "Still set on: old-two" (lib.head hit)
|
|
||||||
&& !(lib.hasInfix "old-one" (lib.head hit));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
# Control for both cases above. Without it they pass on any config whose
|
|
||||||
# warning list happens to carry the string, including one where the shim
|
|
||||||
# fires unconditionally — which is the same defect wearing the other sign.
|
|
||||||
name = "a hive that never set swarm.peers gets neither removal warning";
|
|
||||||
ok = !(lib.any (w: lib.hasInfix "swarm.peers" w) bare.warnings);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "a config written against the pre-rename authelia usersFile still reaches the bridge";
|
|
||||||
ok =
|
|
||||||
autheliaOldPath.containers.swarm-authelia.config.systemd.services.swarm-authelia-bridge.environment.SWARM_AUTHELIA_BRIDGE_USERS_FILE
|
|
||||||
== "/var/lib/test-authelia/users.yml";
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
# Not a rename test. `hostClientSecretDir` is `readOnly`, so the fixture
|
# Not a rename test. `hostClientSecretDir` is `readOnly`, so the fixture
|
||||||
# cannot define it; what can break is a reader left pointing at the
|
# cannot define it; what can break is a reader left pointing at the
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue