require both attic options, follow attic's cache-name rule, read the token from a file
This commit is contained in:
parent
0849afec80
commit
bd214b9f3e
3 changed files with 156 additions and 41 deletions
|
|
@ -12,7 +12,8 @@
|
|||
Name of the attic server, with no scheme: the swarm builder pushes to
|
||||
`https://<domain>`, and trusts the certificate the system roots do, so
|
||||
a Let's Encrypt certificate works and none is pinned. Set together with
|
||||
{option}`services.hyperhive.swarm.attic.cache`.
|
||||
{option}`services.hyperhive.swarm.attic.cache`; evaluation fails when only
|
||||
one is set.
|
||||
|
||||
Null pushes nothing: the swarm builder does not push, and the closure
|
||||
record says it is not cached.
|
||||
|
|
@ -24,13 +25,15 @@
|
|||
};
|
||||
|
||||
cache = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
# attic's own rule for a cache name; the builder checks the same at start.
|
||||
type = lib.types.nullOr (lib.types.strMatching "^[A-Za-z0-9][A-Za-z0-9_+-]{0,49}$");
|
||||
default = null;
|
||||
example = "grid";
|
||||
description = ''
|
||||
Name of the cache on {option}`services.hyperhive.swarm.attic.domain`
|
||||
that the swarm builder pushes closures to. The push token must be
|
||||
allowed to push to it.
|
||||
allowed to push to it. The name follows attic's rule: 1 to 50 letters,
|
||||
digits, `-`, `_` or `+`, starting with a letter or digit.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -90,8 +90,8 @@ let
|
|||
hyperhiveFlake = hyperhiveCfg.c0re.hyperhiveFlake;
|
||||
nixpkgsFlake = hyperhiveCfg.c0re.nixpkgsFlake;
|
||||
|
||||
# Either half alone reaches the daemon too, which refuses to start on it.
|
||||
pushesToCache = atticCfg.domain != null || atticCfg.cache != null;
|
||||
# The assertion below keeps the two options together.
|
||||
pushesToCache = atticCfg.domain != null;
|
||||
|
||||
privateNetwork = true;
|
||||
in
|
||||
|
|
@ -133,6 +133,14 @@ in
|
|||
host's /var/lib/swarm-bao-pki/ and name them in those two options.
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = (atticCfg.domain == null) == (atticCfg.cache == null);
|
||||
message = ''
|
||||
services.hyperhive.swarm.attic.domain and services.hyperhive.swarm.attic.cache
|
||||
must be set together: the swarm builder pushes to a cache on a server, and
|
||||
either alone names nothing to push to.
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = lib.all oneWord (lib.attrValues storeFiles);
|
||||
message = ''
|
||||
|
|
@ -257,10 +265,8 @@ in
|
|||
SWARM_BUILDER_FORGE_URL = "https://${forgeCfg.domain}";
|
||||
SWARM_BUILDER_CONFIG_ORG = "agent-configs";
|
||||
}
|
||||
// lib.optionalAttrs (atticCfg.domain != null) {
|
||||
// lib.optionalAttrs pushesToCache {
|
||||
SWARM_BUILDER_ATTIC_DOMAIN = atticCfg.domain;
|
||||
}
|
||||
// lib.optionalAttrs (atticCfg.cache != null) {
|
||||
SWARM_BUILDER_ATTIC_CACHE = atticCfg.cache;
|
||||
}
|
||||
// lib.optionalAttrs (storeFiles ? builder-bao-server-ca) {
|
||||
|
|
@ -276,7 +282,7 @@ in
|
|||
DynamicUser = true;
|
||||
CacheDirectory = unit;
|
||||
# /run/swarm-builder, mode 0700 and owned by the dynamic user: the
|
||||
# push writes its token-bearing `attic` config under it.
|
||||
# push writes its token file and `attic` config under it.
|
||||
RuntimeDirectory = unit;
|
||||
RuntimeDirectoryMode = "0700";
|
||||
# Bare ids: the system credentials nspawn handed in.
|
||||
|
|
|
|||
|
|
@ -39,6 +39,21 @@ let
|
|||
m:
|
||||
lib.any (a: !a.assertion && lib.hasInfix "deploy.builder.enable requires" a.message) m.assertions;
|
||||
|
||||
# The one fixture that fires the cache assertion: a domain with no cache name.
|
||||
halfCache = hive {
|
||||
deploy.bao.enable = true;
|
||||
deploy.builder.enable = true;
|
||||
swarm.attic.domain = "cache.example.org";
|
||||
};
|
||||
refusedHalfCache =
|
||||
m:
|
||||
lib.any (
|
||||
a:
|
||||
!a.assertion && lib.hasInfix "swarm.attic.domain and services.hyperhive.swarm.attic.cache" a.message
|
||||
) m.assertions;
|
||||
# Only the option is read, so the host around it is never evaluated.
|
||||
cacheNamed = name: (hive { swarm.attic.cache = name; }).services.hyperhive.swarm.attic.cache;
|
||||
|
||||
natsHere = shared.natsQueueOnly;
|
||||
|
||||
autheliaHere = hive {
|
||||
|
|
@ -139,6 +154,30 @@ let
|
|||
&& !(withoutCache.environment ? SWARM_BUILDER_ATTIC_DOMAIN)
|
||||
&& !(withoutCache.environment ? SWARM_BUILDER_ATTIC_CACHE);
|
||||
}
|
||||
{
|
||||
# A domain with no cache name would crash-loop the builder at start, so
|
||||
# evaluation refuses it. `withBuilder`, with both set, is the control: the
|
||||
# same assertion list holds the entry and it passes.
|
||||
name = "the builder refuses a cache domain without a cache name";
|
||||
ok =
|
||||
refusedHalfCache halfCache
|
||||
&& !(refusedHalfCache withBuilder)
|
||||
&& lib.any (a: lib.hasInfix "swarm.attic.domain and" a.message) withBuilder.assertions;
|
||||
}
|
||||
{
|
||||
# attic refuses a cache name outside its rule, which would fail every push.
|
||||
# `grid` is the control that the lookup reads a name.
|
||||
name = "the cache name must follow attic's rule";
|
||||
ok =
|
||||
cacheNamed "grid" == "grid"
|
||||
&& cacheNamed "A-b_c+d" == "A-b_c+d"
|
||||
&& lib.all (n: !(builtins.tryEval (cacheNamed n)).success) [
|
||||
"grid.v2"
|
||||
"-grid"
|
||||
""
|
||||
(lib.concatStrings (lib.genList (_: "a") 51))
|
||||
];
|
||||
}
|
||||
{
|
||||
# The minting unit goes inactive after each run, so a start that pulls it
|
||||
# runs it again and mints a leaf that is missing; an active
|
||||
|
|
|
|||
Loading…
Reference in a new issue