refactor(nix): a hive's domain comes out of the swarm directory
`services.hyperhive.domain` and `swarm.hives.<hiveName>.domain` were two
homes for one value with nothing asserting they agreed. The failure that
buys is the worst shape a config defect has: it evaluates cleanly, and
the symptom ("the other hives can't reach me") appears on a machine
other than the misconfigured one.
The directory is now the single source. `hives.<name>.domain` gains the
`<name>.<swarm.domain>` default -- a derivation from two values an
operator had to state explicitly, not a guess -- so a conventional swarm
is a list of names and a hive addressed by something else says so in the
one place every other hive reads. `services.hyperhive.domain` reads its
own entry; the direct formula is deleted rather than kept as a fallback,
which would have restored the second path (and, reading `swarm.domain`
itself, a second path that can disagree).
Setting it directly still wins, with a deprecation warning: nothing
breaks today, but a value written only there is invisible to the swarm.
The self-entry assertion now fires on an EMPTY directory too. Since
`swarm.domain` became required, every hive is in a swarm -- a swarm of
one is still a swarm -- and this host's address is read out of the
directory, so the entry is missing either way and the precise message
should be the one that fires.
Upgrading costs one line on hives that never listed themselves:
`services.hyperhive.swarm.hives.<hiveName> = { };`, no value.
This commit is contained in:
parent
30551464c1
commit
3b6576faee
5 changed files with 221 additions and 122 deletions
|
|
@ -5,6 +5,7 @@
|
|||
{
|
||||
lib,
|
||||
config,
|
||||
options,
|
||||
...
|
||||
}:
|
||||
let
|
||||
|
|
@ -36,19 +37,24 @@ in
|
|||
# Hive identity (label + domain + display names).
|
||||
options.services.hyperhive.domain = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
# Every hive in a swarm lives at its own sub-domain of the swarm's,
|
||||
# so this is derivable rather than something each hive repeats. It
|
||||
# stays a DEFAULT and not a rename: an alias would reinterpret the
|
||||
# domains hives have already deployed, whereas a default only fills
|
||||
# in the ones that never set it. Null (both parts unset) keeps the
|
||||
# existing "required" assertion in hive-network.nix as the single
|
||||
# place this can fail.
|
||||
# Read out of the swarm directory rather than derived here. The
|
||||
# directory is what every OTHER hive reads this hive's address from,
|
||||
# so deriving it separately gave two homes for one value with
|
||||
# nothing asserting they agreed — and a disagreement surfaces as
|
||||
# "the other hives can't reach me", on a machine other than the
|
||||
# misconfigured one.
|
||||
#
|
||||
# ⚠️ The `<hiveName>.<swarm.domain>` formula did NOT move here from
|
||||
# there and back: it lives once, on `hives.<name>.domain`, which
|
||||
# this reads. Restoring a direct fallback here would recreate the
|
||||
# second path (and, since that default reads `swarm.domain` too, a
|
||||
# value that can differ from the directory's).
|
||||
default =
|
||||
if hiveCfg.swarm.domain != null && hiveCfg.hiveName != null then
|
||||
"${hiveCfg.hiveName}.${hiveCfg.swarm.domain}"
|
||||
if hiveCfg.hiveName != null && hiveCfg.swarm.hives ? ${hiveCfg.hiveName} then
|
||||
hiveCfg.swarm.hives.${hiveCfg.hiveName}.domain
|
||||
else
|
||||
null;
|
||||
defaultText = lib.literalExpression ''"''${hiveName}.''${swarm.domain}", or null when either is unset'';
|
||||
defaultText = lib.literalExpression "services.hyperhive.swarm.hives.\${hiveName}.domain, or null when there is no entry for this hive";
|
||||
example = "darkest.space";
|
||||
description = ''
|
||||
Canonical host domain for hyperhive subsystems that need a
|
||||
|
|
@ -63,12 +69,44 @@ in
|
|||
`hive-agent::identity::hive_domain()` for `<name>@<domain>`
|
||||
qualified labels.
|
||||
|
||||
Defaults to `<hiveName>.<swarm.domain>` when both of those are
|
||||
set, so a hive in a swarm does not restate its own address.
|
||||
Setting this explicitly always wins.
|
||||
**Deprecated as a place to write.** It is read from this hive's
|
||||
own entry in `services.hyperhive.swarm.hives`, whose `domain`
|
||||
defaults to `<hiveName>.<swarm.domain>` — so a conventional hive
|
||||
states nothing at all, and a non-conventional one states its
|
||||
address in the directory every other hive reads. Setting it here
|
||||
still wins and still works, with a warning: the directory is
|
||||
shared, this option is not, so a value written only here is
|
||||
invisible to the rest of the swarm.
|
||||
'';
|
||||
};
|
||||
|
||||
# Deprecation warning for the shorthand above, fired on PRIORITY.
|
||||
#
|
||||
# ⚠️ Not `isDefined`, and not `files`: the module system injects an
|
||||
# option's own `default` as a definition attributed to the declaring
|
||||
# file, so both say "defined, in hyperhive.nix" for a config that set
|
||||
# nothing — measured, after this warning fired on the conventional
|
||||
# case. `mkOptionDefault` is priority 1500, so anything lower is a
|
||||
# definition someone actually wrote (100 plain, 1000 mkDefault).
|
||||
config.warnings =
|
||||
lib.optional (hiveCfg.enable && options.services.hyperhive.domain.highestPrio < 1500)
|
||||
''
|
||||
services.hyperhive.domain is set explicitly and is deprecated. This
|
||||
hive's address belongs in the swarm directory, which every hive in
|
||||
the swarm shares a copy of:
|
||||
|
||||
services.hyperhive.swarm.hives."${toString hiveCfg.hiveName}".domain = "${toString hiveCfg.domain}";
|
||||
|
||||
(Or drop the value entirely if it is the conventional
|
||||
`<hiveName>.<swarm.domain>` — that is the directory entry's own
|
||||
default.)
|
||||
|
||||
Setting it here still wins, so nothing is broken right now. What it
|
||||
does not do is tell the other hives: they read this hive's address
|
||||
out of their copy of the directory, so a value written only here
|
||||
leaves them pointing somewhere else with nothing detecting it.
|
||||
'';
|
||||
|
||||
# Where the swarm lives. Declared beside the hive's own identity
|
||||
# because it is what that identity is derived FROM — every hive in a
|
||||
# swarm is a sub-domain of it. Unlike the renamed options nearby, this
|
||||
|
|
@ -79,11 +117,11 @@ in
|
|||
example = "darkest.space";
|
||||
description = ''
|
||||
DNS domain of the wider swarm this hive belongs to. Each hive
|
||||
occupies its own sub-domain of it, which is why
|
||||
`services.hyperhive.domain` defaults to
|
||||
`<hiveName>.<swarm.domain>` — set this plus
|
||||
`services.hyperhive.hiveName` and a hive needs no domain of its
|
||||
own.
|
||||
occupies its own sub-domain of it, which is why every entry in
|
||||
`services.hyperhive.swarm.hives` defaults its `domain` to
|
||||
`<name>.<swarm.domain>` — set this plus
|
||||
`services.hyperhive.hiveName`, list the hives by name, and no
|
||||
hive in the swarm states an address at all.
|
||||
|
||||
**Required** when `services.hyperhive.enable`, and deliberately
|
||||
not defaulted: there is no fallback worth having. A guessed
|
||||
|
|
|
|||
Loading…
Reference in a new issue