deploy: separate "what this host deploys" from swarm-wide truth
`services.hyperhive.swarm.*` is meant to be identical on every host in a swarm — it describes the swarm, and every hive needs all of it to be a client. But it also carried the `enable` toggles, which are precisely the values that must differ per machine. The namespace that should be the same everywhere held the one thing that cannot be. Adds `services.hyperhive.deploy.*` for a host's deployment decisions, and moves the first of them (`swarm.grafana.enable` -> `deploy.grafana`) as the pattern for the rest. Flat and named for the thing deployed rather than grouped under a "swarm services" attribute: from the deploy side it does not matter what kind of thing each one is, and a grouping by service kind would re-encode the service-side taxonomy into a layer that does not care about it. Behaviour is unchanged. The move is a rename in the strict sense — same type, same meaning, new path — so `mkRenamedOptionModule` carries it and existing configs keep evaluating with one warning naming both paths. The renames live in the new module rather than the service modules, so the whole migration has a single home and a single file to delete when the deprecation window closes.
This commit is contained in:
parent
9a01906275
commit
b422367942
6 changed files with 73 additions and 16 deletions
|
|
@ -75,7 +75,7 @@ empty. To run one without the other, set it directly:
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
services.hyperhive.swarm.victoriametrics.enable = true;
|
services.hyperhive.swarm.victoriametrics.enable = true;
|
||||||
services.hyperhive.swarm.grafana.enable = false;
|
services.hyperhive.deploy.grafana = false;
|
||||||
```
|
```
|
||||||
|
|
||||||
⚠️ **This starts a database that grows for as long as the swarm runs.**
|
⚠️ **This starts a database that grows for as long as the swarm runs.**
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./hyperhive.nix
|
./hyperhive.nix
|
||||||
|
./deploy.nix
|
||||||
./local-defaults.nix
|
./local-defaults.nix
|
||||||
./hive-c0re
|
./hive-c0re
|
||||||
./hive-ci.nix
|
./hive-ci.nix
|
||||||
|
|
|
||||||
53
nix/host-modules/deploy.nix
Normal file
53
nix/host-modules/deploy.nix
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
# "What does THIS host deploy?"
|
||||||
|
#
|
||||||
|
# Separated from `services.hyperhive.swarm.*` because those are two
|
||||||
|
# different kinds of fact and only one of them varies per machine:
|
||||||
|
#
|
||||||
|
# swarm.* — swarm-wide truth. The swarm's name, domain, hives, peers,
|
||||||
|
# CA, and where each service lives. **Identical on every
|
||||||
|
# host**, byte for byte; a hive needs all of it to be a
|
||||||
|
# *client* of the swarm.
|
||||||
|
# deploy.* — this machine's deployment decisions. Necessarily different
|
||||||
|
# on every host, because that is what a deployment is.
|
||||||
|
#
|
||||||
|
# The `enable` toggles used to live under `swarm.*`, which made the
|
||||||
|
# namespace that is supposed to be identical everywhere carry the one
|
||||||
|
# thing that must differ.
|
||||||
|
#
|
||||||
|
# Flat and named for the thing deployed — `deploy.forgejo`, not
|
||||||
|
# `deploy.swarmServices.forgejo`. Grouping by "swarm service" would
|
||||||
|
# re-encode the service-side taxonomy into a layer that does not care
|
||||||
|
# about it: from here, a host deploys forgejo, or a hive, or the lot, and
|
||||||
|
# what *kind* of thing each one is belongs to the service module.
|
||||||
|
#
|
||||||
|
# ⚠️ The renames below are deliberately in this one file rather than
|
||||||
|
# spread across the service modules, so the whole move has a single home
|
||||||
|
# and a single file to delete when the deprecation window closes — the
|
||||||
|
# shape ./swarm-peers-removed.nix already uses.
|
||||||
|
{ lib, ... }:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
# Same type, same meaning, new path — so a rename carries it exactly
|
||||||
|
# and existing configs keep evaluating with one warning naming both
|
||||||
|
# paths. Precedent: ./hive-forge/default.nix, ./hive-matrix.nix.
|
||||||
|
(lib.mkRenamedOptionModule
|
||||||
|
[ "services" "hyperhive" "swarm" "grafana" "enable" ]
|
||||||
|
[ "services" "hyperhive" "deploy" "grafana" ]
|
||||||
|
)
|
||||||
|
];
|
||||||
|
|
||||||
|
options.services.hyperhive.deploy = {
|
||||||
|
grafana = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Run the swarm's metrics UI on this host.
|
||||||
|
|
||||||
|
Off by default and not derived from
|
||||||
|
{option}`services.hyperhive.enable`: a swarm has one Grafana, so
|
||||||
|
running it is a decision about this host rather than about
|
||||||
|
whether hyperhive is installed.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
cfg = config.services.hyperhive.swarm.grafana;
|
cfg = config.services.hyperhive.swarm.grafana;
|
||||||
|
deployCfg = config.services.hyperhive.deploy;
|
||||||
networkCfg = config.services.hyperhive.network;
|
networkCfg = config.services.hyperhive.network;
|
||||||
hyperhiveCfg = config.services.hyperhive;
|
hyperhiveCfg = config.services.hyperhive;
|
||||||
gatewayCfg = hyperhiveCfg.gateway;
|
gatewayCfg = hyperhiveCfg.gateway;
|
||||||
|
|
@ -106,18 +107,12 @@ let
|
||||||
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
# `enable` moved to `services.hyperhive.deploy.grafana` — see
|
||||||
|
# ./deploy.nix. Whether this host runs the swarm's Grafana is a
|
||||||
|
# deployment decision, and `swarm.*` has to be identical on every host.
|
||||||
|
# What stays here is what the service IS: its package, domain, and
|
||||||
|
# wiring.
|
||||||
options.services.hyperhive.swarm.grafana = {
|
options.services.hyperhive.swarm.grafana = {
|
||||||
enable = lib.mkOption {
|
|
||||||
type = lib.types.bool;
|
|
||||||
default = false;
|
|
||||||
description = ''
|
|
||||||
Run the swarm's metrics UI on this host. Off by default and not
|
|
||||||
derived from {option}`services.hyperhive.enable`: a swarm has one
|
|
||||||
Grafana, so enabling it is a decision about swarm topology rather
|
|
||||||
than about whether hyperhive is installed.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
package = lib.mkOption {
|
package = lib.mkOption {
|
||||||
type = lib.types.package;
|
type = lib.types.package;
|
||||||
default = pkgs.grafana;
|
default = pkgs.grafana;
|
||||||
|
|
@ -312,8 +307,8 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf (hyperhiveCfg.enable && cfg.enable) {
|
config = lib.mkIf (hyperhiveCfg.enable && deployCfg.grafana) {
|
||||||
# The gateway name and the quick-link, both inside `cfg.enable` — that
|
# The gateway name and the quick-link, both inside `deploy.grafana` — that
|
||||||
# guard is the load-bearing part. Every hive in a swarm may know this UI
|
# guard is the load-bearing part. Every hive in a swarm may know this UI
|
||||||
# exists, but only the host that RUNS it may claim the name; a client
|
# exists, but only the host that RUNS it may claim the name; a client
|
||||||
# hive declaring the vhost would answer for a service it does not have.
|
# hive declaring the vhost would answer for a service it does not have.
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,8 @@ in
|
||||||
# takes one and not the other from this switch. An operator who wants
|
# takes one and not the other from this switch. An operator who wants
|
||||||
# exactly one still sets it directly, which `mkDefault` allows.
|
# exactly one still sets it directly, which `mkDefault` allows.
|
||||||
victoriametrics.enable = lib.mkDefault swarmCfg.enableRequiredServices;
|
victoriametrics.enable = lib.mkDefault swarmCfg.enableRequiredServices;
|
||||||
grafana.enable = lib.mkDefault swarmCfg.enableRequiredServices;
|
# (grafana's half of the pair derives below — it lives in `deploy.*`
|
||||||
|
# now, which is a different attribute path, not a different rule.)
|
||||||
|
|
||||||
# The log store, deriving from the same switch for the same reason —
|
# The log store, deriving from the same switch for the same reason —
|
||||||
# and deliberately in the same commit as the collector pipeline that
|
# and deliberately in the same commit as the collector pipeline that
|
||||||
|
|
@ -88,4 +89,10 @@ in
|
||||||
# The collector that feeds the pair above (note: no `swarm.` prefix,
|
# The collector that feeds the pair above (note: no `swarm.` prefix,
|
||||||
# this is ./otel.nix's existing per-hive option).
|
# this is ./otel.nix's existing per-hive option).
|
||||||
config.services.hyperhive.otel.enable = lib.mkDefault swarmCfg.enableRequiredServices;
|
config.services.hyperhive.otel.enable = lib.mkDefault swarmCfg.enableRequiredServices;
|
||||||
|
|
||||||
|
# Grafana, the UI half of the metrics pair. Same derivation and the same
|
||||||
|
# reasoning as `victoriametrics.enable` above; it reads differently only
|
||||||
|
# because "does this host run it" now lives in `deploy.*` (./deploy.nix)
|
||||||
|
# rather than under `swarm.*`, which has to be identical on every host.
|
||||||
|
config.services.hyperhive.deploy.grafana = lib.mkDefault swarmCfg.enableRequiredServices;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
let
|
let
|
||||||
cfg = config.services.hyperhive;
|
cfg = config.services.hyperhive;
|
||||||
swarmCfg = cfg.swarm;
|
swarmCfg = cfg.swarm;
|
||||||
|
deployCfg = cfg.deploy;
|
||||||
|
|
||||||
# Public hostnames of the swarm's own services, in declaration order.
|
# Public hostnames of the swarm's own services, in declaration order.
|
||||||
# `serviceDomains` below is this set sorted + deduplicated.
|
# `serviceDomains` below is this set sorted + deduplicated.
|
||||||
|
|
@ -57,7 +58,7 @@ let
|
||||||
# metrics UI and store looked fine for as long as only people opened
|
# metrics UI and store looked fine for as long as only people opened
|
||||||
# them; the collector's exporter — same defect, no human in the loop —
|
# them; the collector's exporter — same defect, no human in the loop —
|
||||||
# failed every POST and dropped the samples.
|
# failed every POST and dropped the samples.
|
||||||
++ lib.optional swarmCfg.grafana.enable swarmCfg.grafana.domain
|
++ lib.optional deployCfg.grafana swarmCfg.grafana.domain
|
||||||
++ lib.optional swarmCfg.victoriametrics.enable swarmCfg.victoriametrics.domain
|
++ lib.optional swarmCfg.victoriametrics.enable swarmCfg.victoriametrics.domain
|
||||||
++ lib.optional swarmCfg.otel.enable swarmCfg.otel.domain
|
++ lib.optional swarmCfg.otel.enable swarmCfg.otel.domain
|
||||||
# VictoriaLogs' vhost is new (was previously unpublished entirely — see
|
# VictoriaLogs' vhost is new (was previously unpublished entirely — see
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue