nixops
nixops copied to clipboard
Pass inputs in addition to nodes/resources to NixOS modules when using Flake
Hey!
When using flakes, it would be convenient to have access to inputs, like this is the case for nodes. Currently, we need to pass it to every module manually. There is modulesPath as an alternative for some case. When using NixOS directly, this can be done by using pkgs.lib.nixosSystem { specialArgs = { inherit inputs; }; }.
NixOS 22.05 introduced something that might help: _module.args
I can't try it myself, my infrastructure is still stuck on 21.11, but I'd be curious if anyone else has success with it.
_module.args is older than specialArgs, so you can already use it. https://github.com/NixOS/nixpkgs/pull/8204
This should work
{ /* network attrset */
defaults = { /* a NixOS module */
_module.args.inputs = inputs;
}
}
After https://github.com/NixOS/nixops/pull/1508, you can expose them at the network level as well
{ /* network module */
_module.args.inputs = inputs;
}
We should consider setting inputs by default when evaluating a flake.
I got some time to try it. You were right @roberth, that works perfectly. Thanks for the tip!
Using _module.args to inject inputs goes a long way, but ultimately I feel it would be insufficient. _module.args is evaluated as part of the config and thus values injected by this mechanism cannot be used in imports (since imports happen statically before evaluation of the main config value). This is precisely what specialArgs is for. Unfortunately, so far as I can tell, there is not currently a mechanism to pass specialArgs into module evaluation call.
Using NixOps 2.0.0-pre-fc9b55c, I'm unable to get this to work passing inputs via _module.args, I'm assuming because I'm using inputs in a function that is called as part of calculating imports (though I expected an infinite recursion error, and instead it's just not finding inputs).
The module is working fine for nixosConfigurations but fails for nixops:
{
config,
pkgs,
lib,
...
} @ args: {
imports = let
defaultModulesFrom = map (input: args.inputs.${input}.nixosModules.default);
in
[
../.
./services
]
++ (defaultModulesFrom [
"agenix"
"home-manager"
]);
}
# flake.nix
nixopsConfigurations.default = {
inherit nixpkgs;
network.storage.legacy = {};
defaults._module.args.inputs = inputs;
myMachine = { imports = [ ./the-module-above.nix ]; ...};
};
$ nixops deploy
...
error: attribute 'inputs' missing
at /nix/store/bl7rfpl59r40idj093ap5bgi1dli1p44-source/modules/linux/default.nix:14:38:
13| imports = let
14| defaultModulesFrom = map (input: args.inputs.${input}.nixosModules.default);
| ^
15| in
error: evaluation of the deployment specification failed
I've tried putting the defaults._module.args.inputs = inputs; at a few different levels in that attrset, but I think this is correct (based on this), and none of the others worked.