manual: Explain which resources accept { resources, nodes, ... }
In nixops each machine in a network configuration gets passed in resources and nodes to observe the entire network. Example:
{
proxy = { config, pkgs, nodes, ... }: {
services.httpd.enable = true;
};
}
It appears that other resources also do this.
E.g. ~it possible to write a resources.ec2SecurityGroups that collects all the networking.firewall.allowedTCPPorts from all machines and opens ports in the AWS firewall for them~ Edit: this is not actually possible: For resources.ec2SecurityGroups.mygroup = { nodes, ... }, the nodes."mymachine".config.networking does not evaluate because attribute 'config' missing. It seems that works only for machines :disappointed:
The manual does not show many examples of that. Most of the time it shows things like
resources.ec2SecurityGroups = { simple attrset here };
There is only 1 example that shows something more sophisticated, and it's in a very specialised section without any explanation:
resources.gceTargetPools.backends = { resources, nodes, ...}: credentials // {
region = "europe-west1";
healthCheck = resources.gceHTTPHealthChecks.plain-hc;
machines = with nodes; [ backend1 backend2 ];
};
I often have trouble figuring out which things are allowed to be a function accepting resources, nodes etc. and which ones not.
I think we're not doing a good job yet explaining this general concept.
IRC discussion
Here's a discussion between @cleverca22 and me on IRC that sheds some more light into the workings
clever
https://github.com/NixOS/nixops/blob/master/nix/eval-machine-info.nix#L78-L83 resourcesByType will gather all of the ec2SecurityGroups from your deployment files
nh2
if I do
resources.ec2SecurityGroups.nixops = args@{ resources, ... }: builtins.trace args {I even just geterror: invalid value-- never seen that before
clever
line 93 then runs evalResources, and passes it that list so _resources is the set of security groups 79 then runs mapAttrs over that set of groups so defs is a list of definitions for a given group (so you can define options on the same group in 2 files) fixMergeModules is then ran, over all definitions, ec2-security-group.nix, and 2 other things and fixMergeModules is given a set containing pkgs, uuid, name, resources, and nodes https://github.com/NixOS/nixpkgs/blob/60e8fcf0e56ce881294b06bd1f40069016308162/lib/modules.nix#L577 and that just calls evalModules so, you can do `resources.ec2SecurityGroups.nixops = { pkgs, uuid, name, resources, nodes, ... }: { stuff }; it should just work...
nh2
Ah, I see the difference.
resources.ec2SecurityGroups.nixops = { nodes, ... }: builtins.trace (builtins.attrNames nodes) { ...stuff... };does not work, butresources.ec2SecurityGroups.nixops = { nodes, ... }: { stuff = builtins.trace (builtins.attrNames nodes) ...more stuff... };does work if I trace inside the attrset, then it works. But outside does not
clever
nh2: its likely part of lazyness, it needs to know the keys of the set, before it can know what nodes contains
nh2
the whole knot-tying is very tricky business. Unfortunately I haven't come up with a nice alternative
Goal
Let's document this properly, with
- explicit examples on how to write networks and use info across machine declarations,
resources, usingnodesetc - some background on how it works
- explanations on what's currently not possible (like resources depending on
nodesmachine config values) - some caveats on when one can run into infinite recursion, like I did above
The fact that it's
resources.ec2SecurityGroups.mygroup = { nodes, ... }:
and not
resources.ec2SecurityGroups = { nodes, ... }: { mygroup = ... }
also means I can't even inspect nodes to generate security groups for all the regions I use in the network with map, but instead have to declare them manually.
explanations on what's currently not possible (like resources depending on nodes machine config values)
I've used #1456 to do this successfully.