nix: split statusPublish and the otel secret into deploy.*
Slices 8 and 9 of the swarm/deploy split, and the last two. statusPublish had three coordinates under one namespace. Two of them are this machine's — where the queue listens *as seen from here*, and where its client secret sits on this disk — so they move to `deploy.hive-controller.statusPublish.*`, the namespace of the daemon that is their only reader. `tokenEndpoint` is the swarm's one address, so it stays. That leaves `swarm.statusPublish` holding a single option: a legitimate split, not a botched move. The all-or-nothing assertion now spans both namespaces. It is repointed in both its condition and its message, and the message spells all three paths in full so an operator is never told to set two options under a path that only has one. `environment.nix`'s guard and the value beside it likewise read different namespaces on purpose. The collector's secret moves the same way, for the same reason, to `deploy.swarm-otel.*` — `enable` already lives there. That also retires one of the eight cross-namespace assignments tracked in #4048: the delivery unit set a `swarm.*` value under a `deploy.*` gate, and now sets a `deploy.*` value under one. module-eval gets a fixture per slice. `otelRemoteAuthelia` already set the collector secret through its pre-rename path, so it becomes slice 9's old-path case as it stands — left spelled that way deliberately, with a comment, so it is not read later as a missed site. That fixture also turned out to be describing an impossible hive: it said authelia lives elsewhere without saying where, so the authenticator interpolated a null `swarm.authelia.url` into its `token_url`. Nothing to do with the rename, and invisible to the existing case over the same fixture, which reads `? auth` and `elem` — both stop at names and never force the extension's value. Given the address a remote-IdP deployment has. Verified: 49 -> 51 properties, all holding.
This commit is contained in:
parent
2e1c15dc98
commit
01ce968fb6
8 changed files with 154 additions and 48 deletions
|
|
@ -356,24 +356,32 @@ in
|
|||
# genuinely cannot publish with two of three coordinates — which
|
||||
# is the distinction the `serviceDomains'` comment at the top of
|
||||
# this file was written about.
|
||||
#
|
||||
# The three coordinates live in two namespaces now: the token
|
||||
# endpoint is the swarm's one address, the other two are this
|
||||
# machine's. The message spells all three paths out, because an
|
||||
# operator told only the option names would look for them under
|
||||
# one prefix and find one of them.
|
||||
assertion =
|
||||
let
|
||||
set = lib.filter (v: v != null) [
|
||||
swarmCfg.statusPublish.natsUrl
|
||||
deployCfg.hive-controller.statusPublish.natsUrl
|
||||
swarmCfg.statusPublish.tokenEndpoint
|
||||
swarmCfg.statusPublish.clientSecretFile
|
||||
deployCfg.hive-controller.statusPublish.clientSecretFile
|
||||
];
|
||||
in
|
||||
builtins.length set == 0 || builtins.length set == 3;
|
||||
message = ''
|
||||
services.hyperhive.swarm.statusPublish needs natsUrl,
|
||||
tokenEndpoint and clientSecretFile set together or not at all
|
||||
— this hive has only some of them.
|
||||
This hive's status-publishing coordinates have to be set
|
||||
together or not at all — it has only some of them.
|
||||
|
||||
Currently:
|
||||
natsUrl = ${toString swarmCfg.statusPublish.natsUrl}
|
||||
tokenEndpoint = ${toString swarmCfg.statusPublish.tokenEndpoint}
|
||||
clientSecretFile = ${toString swarmCfg.statusPublish.clientSecretFile}
|
||||
deploy.hive-controller.statusPublish.natsUrl
|
||||
= ${toString deployCfg.hive-controller.statusPublish.natsUrl}
|
||||
swarm.statusPublish.tokenEndpoint
|
||||
= ${toString swarmCfg.statusPublish.tokenEndpoint}
|
||||
deploy.hive-controller.statusPublish.clientSecretFile
|
||||
= ${toString deployCfg.hive-controller.statusPublish.clientSecretFile}
|
||||
|
||||
Set the missing ones to publish this hive's status to the
|
||||
swarm, or set all three to null to turn publishing off.
|
||||
|
|
@ -440,6 +448,38 @@ in
|
|||
# enable. An extra flag would let a hive be configured-but-off, which
|
||||
# is one more state to explain and one more way to be silently quiet.
|
||||
options.services.hyperhive.swarm.statusPublish = {
|
||||
tokenEndpoint = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default =
|
||||
if queueLocal && swarmCfg.authelia.url != null then
|
||||
"${swarmCfg.authelia.url}/api/oidc/token"
|
||||
else
|
||||
null;
|
||||
defaultText = lib.literalExpression ''"''${swarm.authelia.url}/api/oidc/token" when this host runs both the queue and the IdP, else null'';
|
||||
example = "https://auth.example.com/api/oidc/token";
|
||||
description = ''
|
||||
The swarm IdP's OAuth2 token endpoint. This hive mints a
|
||||
`client_credentials` access token there and presents it when
|
||||
connecting to the queue, which authenticates it as
|
||||
`hive-<hiveName>` — the client
|
||||
{file}`nix/host-modules/swarm-authelia.nix` already declares for
|
||||
every entry in {option}`services.hyperhive.swarm.hives`.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
# What stays above is the one thing every hive shares: the address of the
|
||||
# swarm's token endpoint. The other two coordinates are this machine's —
|
||||
# where the queue is *as seen from here*, and where its secret sits on this
|
||||
# disk — so they hang off the daemon that uses them. `hive-controller` is
|
||||
# hive-c0re's new name, which is why the namespace is the daemon's rather
|
||||
# than a `deploy.statusPublish` of its own.
|
||||
#
|
||||
# ⚠️ The all-or-nothing assertion above now spans both namespaces. That is
|
||||
# one service's own options either side of the split, not a service reaching
|
||||
# into a foreign `deploy.*`; its message names all three paths so an operator
|
||||
# is not told to set two options under a path that has one.
|
||||
options.services.hyperhive.deploy.hive-controller.statusPublish = {
|
||||
natsUrl = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = if queueLocal then "nats://127.0.0.1:${toString swarmCfg.nats.port}" else null;
|
||||
|
|
@ -461,25 +501,6 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
tokenEndpoint = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default =
|
||||
if queueLocal && swarmCfg.authelia.url != null then
|
||||
"${swarmCfg.authelia.url}/api/oidc/token"
|
||||
else
|
||||
null;
|
||||
defaultText = lib.literalExpression ''"''${swarm.authelia.url}/api/oidc/token" when this host runs both the queue and the IdP, else null'';
|
||||
example = "https://auth.example.com/api/oidc/token";
|
||||
description = ''
|
||||
The swarm IdP's OAuth2 token endpoint. This hive mints a
|
||||
`client_credentials` access token there and presents it when
|
||||
connecting to the queue, which authenticates it as
|
||||
`hive-<hiveName>` — the client
|
||||
{file}`nix/host-modules/swarm-authelia.nix` already declares for
|
||||
every entry in {option}`services.hyperhive.swarm.hives`.
|
||||
'';
|
||||
};
|
||||
|
||||
clientSecretFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default =
|
||||
|
|
|
|||
Loading…
Reference in a new issue