Skip to content

Data is queried, not merged

The NixOS module system merges every definition into one value, then reads it. yen does not merge. A read of a path is one query on the files that answer that path.

Here two feature files declare settings at two paths of one field. Neither file knows the other:

modules/features/zfs.nix
# Each feature declares its own setting, at its own path, in its own file.
{ yen, lib, ... }:
{
yen.kinds.host.fields.settings.zfs.arcMax = yen.lib.maybe lib.types.int;
yen.kinds.environment.fields.settings.zfs.arcMax = yen.lib.maybe lib.types.int;
}

A read of host.settings.k3s.role looks at the instance, then at the type default. It never reads zfs.nix. r.declaredIn answers which files declare a path:

result
[
"k3s.nix"
"zfs.nix"
]

A cascade is a list in your order. yen.lib.cascade path xs gives the first non-null value along xs. nas sets its own arcMax; node falls back to its environment:

modules/hosts.nix
{ yen, ... }:
{
yen.kinds.host.fields.environment = yen.kinds.environment;
yen.environment.prod.settings.zfs.arcMax = 8;
yen.host.nas = {
environment = yen.environment.prod;
settings.zfs.arcMax = 32;
};
yen.host.node = {
environment = yen.environment.prod;
settings.k3s.role = "server";
};
}
modules/report.nix
# `cascade path xs`: the first non-null value along a list, in your order.
{ yen, ... }:
{
yen.aspects.report = {
at = yen.kinds.host;
report =
{ host, ... }:
{
${host.name} = {
arcMax = yen.lib.cascade [ "settings" "zfs" "arcMax" ] [ host host.environment ];
k3s = host.settings.k3s.role;
};
};
};
}
result
{
nas = {
arcMax = 32;
k3s = "agent";
};
node = {
arcMax = 8;
k3s = "server";
};
}

One leaf with two different values is not an override. It is an error record, and you keep one answer:

variants/override.nix
# A second, different answer for one leaf. Data never overrides data.
{ yen, ... }:
{
yen.host.nas.settings.zfs.arcMax = 16;
}
result
[
{
class = "fixable";
code = "two-answers";
error = "two answers for host.nas.settings.zfs.arcMax";
fix = "keep one answer for host.nas.settings.zfs.arcMax: data never overrides data";
from = "declarations";
got = 2;
path = [
"host"
"nas"
"settings"
"zfs"
"arcMax"
];
}
]
Contribute Community Sponsor