-
-
Couldn't load subscription status.
- Fork 364
Description
I believe a custom require feature was chosen in order to solve a bootstrapping problem.
This custom mechanism is not ideal because it adds to the growing list of "override", "overlay", "module", etc. It'd be better to reuse the module system. I suggest the following bootstrapping
- Load the raw network expressions as Nix functions
- Call them with bogus auto-arguments as in
module (mapAttrs (k: v: throw k) (functionArgs module) - This should give us module attrsets containing a few attributes of interest that we'll evaluated and a bunch of things we don't need and can't evaluate at this stage. That's ok.
- Use these partial modules to determine what
libshould be. - Call
lib.evalModuleson the network expressions. - Have the module system at our disposal
A more radical approach, suitable for flakes, is to let the user inject lib manually. This would change the flake format to require a call like nixopsConfigurations.default = inputs.nixops.lib.mkNetwork { inherit lib; configuration = /* ... */; }, which is more robust than step 3 and 4. For non-flake nixops.nix we'll still want something like step 3 and 4 I think.
Pros:
- module system is more familiar
- module system is more powerful a custom composition method will be
- allows the user to define network-wide options to capture the variability of environments (dtap, etc)
- allows the user to define network-wide options to represent cross-machine concepts such as groups of machines
- network arguments can become option values
- familiar infrastructure for deprecations
- replace custom, buggy network expression merging code
Cons:
- breaks pre-release version (not that bad)
- step 3 and 4 are somewhat fragile. I am confident that this can be mitigated
Myths:
- "the module system is slow; look at NixOS": the module system scales with the number of options. It is very fast for small configuration systems. It is also quite lazy, so it is possible to avoid evaluating the machines for example. I see no reason for performance to degrade because of this change.
Note to self: requires is not a recent addition; compatibility is needed and can be provided at next to no cost, because the module system still supports requires as a hardly known legacy feature.