NixOS / nixops

NixOps is a tool for deploying to NixOS machines in a network or cloud.
https://nixos.org/nixops
GNU Lesser General Public License v3.0
1.84k stars 363 forks source link

manual: Explain which resources accept { resources, nodes, ... } #1172

Open nh2 opened 5 years ago

nh2 commented 5 years ago

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 get error: 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, but resources.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

nh2 commented 5 years ago

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.

roberth commented 3 years ago

explanations on what's currently not possible (like resources depending on nodes machine config values)

I've used #1456 to do this successfully.