|
11 | 11 | let
|
12 | 12 | call = x: if builtins.isFunction x then x args else x;
|
13 | 13 |
|
14 |
| - # Copied from nixpkgs to avoid <nixpkgs> import |
15 |
| - optional = cond: elem: if cond then [elem] else []; |
16 |
| - |
17 | 14 | zipAttrs = set: builtins.listToAttrs (
|
18 | 15 | map (name: { inherit name; value = builtins.catAttrs name set; }) (builtins.concatMap builtins.attrNames set));
|
19 | 16 |
|
20 |
| - flakeExpr = (builtins.getFlake flakeUri).outputs.nixopsConfigurations.default; |
21 |
| - |
22 |
| - networks = |
23 |
| - let |
24 |
| - getNetworkFromExpr = networkExpr: |
25 |
| - (call (import networkExpr)) // { _file = networkExpr; }; |
| 17 | + flake = builtins.getFlake flakeUri; |
| 18 | + flakeExpr = (builtins.tryEval flake.outputs.nixopsConfigurations.default).value or { }; |
26 | 19 |
|
27 |
| - exprToKey = key: { key = toString key; }; |
| 20 | + nixpkgsBoot = <nixpkgs> ; # this will be replaced on install by nixops' nixpkgs input |
| 21 | + libBoot = import "${nixpkgsBoot}/lib"; |
28 | 22 |
|
29 |
| - networkExprClosure = builtins.genericClosure { |
30 |
| - startSet = map exprToKey networkExprs; |
31 |
| - operator = { key }: map exprToKey ((getNetworkFromExpr key).require or []); |
| 23 | + baseMods = lib: [ |
| 24 | + { |
| 25 | + options.nixpkgs = lib.mkOption { |
| 26 | + type = lib.types.path; |
| 27 | + description = "Path to the nixpkgs instance used to buld the machines."; |
| 28 | + defaultText = lib.literalDocBook "The 'nixpkgs' input to either the provided flake or nixops' own."; |
| 29 | + default = (builtins.tryEval flake.inputs.nixpkgs).value or nixpkgsBoot; |
32 | 30 | };
|
33 |
| - in |
34 |
| - map ({ key }: getNetworkFromExpr key) networkExprClosure |
35 |
| - ++ optional (flakeUri != null) |
36 |
| - ((call flakeExpr) // { _file = "<${flakeUri}>"; }); |
| 31 | + config._module.freeformType = with lib.types;attrsOf anything; |
| 32 | + } |
| 33 | + flakeExpr |
| 34 | + ] ++ networkExprs; |
37 | 35 |
|
38 |
| - network = zipAttrs networks; |
| 36 | + evalBoot = libBoot.evalModules { |
| 37 | + specialArgs = args; |
| 38 | + modules = baseMods libBoot; |
| 39 | + }; |
39 | 40 |
|
40 |
| - evalConfig = |
41 |
| - if flakeUri != null |
42 |
| - then |
43 |
| - if network ? nixpkgs |
44 |
| - then (builtins.head (network.nixpkgs)).lib.nixosSystem |
45 |
| - else throw "NixOps network must have a 'nixpkgs' attribute" |
46 |
| - else import (pkgs.path + "/nixos/lib/eval-config.nix"); |
| 41 | + inherit (evalBoot.config) nixpkgs; |
47 | 42 |
|
48 |
| - pkgs = if flakeUri != null |
49 |
| - then |
50 |
| - if network ? nixpkgs |
51 |
| - then (builtins.head network.nixpkgs).legacyPackages.${system} |
52 |
| - else throw "NixOps network must have a 'nixpkgs' attribute" |
53 |
| - else (builtins.head (network.network)).nixpkgs or (import <nixpkgs> { inherit system; }); |
| 43 | + pkgs = nixpkgs.legacyPackages.${system} or import nixpkgs { inherit system; }; |
| 44 | + lib = nixpkgs.lib or pkgs.lib or libBoot; |
| 45 | + inherit (lib) mkOption types removeAttrs; |
54 | 46 |
|
55 |
| - inherit (pkgs) lib; |
| 47 | +in |
| 48 | +rec { |
| 49 | + inherit nixpkgs; |
56 | 50 |
|
57 |
| - # Expose path to imported nixpkgs (currently only used to find version suffix) |
58 |
| - nixpkgs = builtins.unsafeDiscardStringContext pkgs.path; |
| 51 | + netConfig = (lib.evalModules { |
| 52 | + specialArgs = args; |
| 53 | + modules = baseMods lib ++ [ |
| 54 | + ({ config, options, ... }: { |
| 55 | + options = { |
| 56 | + network = { |
| 57 | + enableRollback = lib.mkEnableOption "network wide rollback"; |
| 58 | + description = mkOption { |
| 59 | + type = types.str; |
| 60 | + description = "A description of the entire network."; |
| 61 | + default = ""; |
| 62 | + }; |
| 63 | + nodesExtraArgs = mkOption { |
| 64 | + description = "Extra inputs to be passed to every node."; |
| 65 | + type = with types;attrsOf anything; |
| 66 | + default = {}; |
| 67 | + }; |
| 68 | + }; |
| 69 | + resources = mkOption { |
| 70 | + type = types.submoduleWith { |
| 71 | + modules = [{ |
| 72 | + # so what is this trying to do? |
| 73 | + sshKeyPairs = evalResources ./ssh-keypair.nix (lib.zipAttrs resourcesByType.sshKeyPairs or [ ]); |
| 74 | + commandOutput = evalResources ./command-output.nix (lib.zipAttrs resourcesByType.commandOutput or [ ]); |
| 75 | + machines = config.nodes; |
| 76 | + _module.check = false; |
| 77 | + }] ++ pluginResources; |
| 78 | + specialArgs = { |
| 79 | + inherit evalResources resourcesByType; |
| 80 | + inherit (lib) zipAttrs; |
| 81 | + }; |
| 82 | + }; |
| 83 | + }; |
| 84 | + # Compute the definitions of the machines. |
| 85 | + nodes = mkOption { |
| 86 | + type = types.attrsOf (types.submoduleWith { |
| 87 | + specialArgs = { |
| 88 | + inherit uuid deploymentName; |
| 89 | + inherit (config) nodes resources; |
| 90 | + } // config.network.nodesExtraArgs; |
| 91 | + modules = (import "${nixpkgs}/nixos/modules/module-list.nix") ++ |
| 92 | + config.defaults ++ |
| 93 | + # Make NixOps's deployment.* options available. |
| 94 | + pluginOptions ++ |
| 95 | + [ |
| 96 | + ./options.nix |
| 97 | + ./resource.nix |
| 98 | + deploymentInfoModule |
| 99 | + ({ name, ... }: rec{ |
| 100 | + _file = ./eval-machine-info.nix; |
| 101 | + key = _file; |
| 102 | + # Provide a default hostname and deployment target equal |
| 103 | + # to the attribute name of the machine in the model. |
| 104 | + networking.hostName = lib.mkOverride 900 name; |
| 105 | + deployment.targetHost = lib.mkOverride 900 name; |
| 106 | + environment.checkConfigurationOptions = lib.mkOverride 900 checkConfigurationOptions; |
| 107 | + nixpkgs.system = lib.mkDefault system; |
| 108 | + }) |
| 109 | + ]; |
| 110 | + }); |
| 111 | + }; |
| 112 | + defaults = mkOption { |
| 113 | + type = with types;listOf anything; |
| 114 | + default = [ ]; |
| 115 | + description = '' |
| 116 | + Extra NixOS options to add to all nodes. |
| 117 | + ''; |
| 118 | + }; |
| 119 | + }; |
| 120 | + config = let |
| 121 | + nodes = removeAttrs config (builtins.attrNames options); |
| 122 | + in mkIf ({} != nodes) { #TODO: actual warning/assert module impl. |
| 123 | + nodes = lib.warn "Please use the actual nodes.* option instead of assigning machines to the config's top level" nodes; |
| 124 | + }; |
| 125 | + }) |
| 126 | + ]; |
| 127 | + }).config; |
59 | 128 |
|
60 |
| -in rec { |
| 129 | + inherit (netConfig) resources nodes; |
| 130 | + defaults = [ netConfig.defaults ]; |
61 | 131 |
|
62 |
| - inherit networks network; |
63 |
| - inherit nixpkgs; |
| 132 | + # for backward compatibility |
| 133 | + network = lib.mapAttrs (n: v: [v]) netConfig; |
| 134 | + networks = [ netConfig ]; |
64 | 135 |
|
65 | 136 | importedPluginNixExprs = map
|
66 | 137 | (expr: import expr)
|
67 | 138 | pluginNixExprs;
|
68 |
| - pluginOptions = { imports = (lib.foldl (a: e: a ++ e.options) [] importedPluginNixExprs); }; |
| 139 | + pluginOptions = lib.foldl (a: e: a ++ e.options) [ ] importedPluginNixExprs; |
69 | 140 | pluginResources = map (e: e.resources) importedPluginNixExprs;
|
70 |
| - pluginDeploymentConfigExporters = (lib.foldl (a: e: a ++ (e.config_exporters { |
71 |
| - inherit pkgs; |
72 |
| - inherit (lib) optionalAttrs; |
73 |
| - })) [] importedPluginNixExprs); |
74 |
| - |
75 |
| - defaults = network.defaults or []; |
76 |
| - |
77 |
| - # Compute the definitions of the machines. |
78 |
| - nodes = |
79 |
| - lib.listToAttrs (map (machineName: |
80 |
| - let |
81 |
| - # Get the configuration of this machine from each network |
82 |
| - # expression, attaching _file attributes so the NixOS module |
83 |
| - # system can give sensible error messages. |
84 |
| - modules = |
85 |
| - lib.concatMap (n: lib.optional (lib.hasAttr machineName n) |
86 |
| - { imports = [(lib.getAttr machineName n)]; inherit (n) _file; }) |
87 |
| - networks; |
88 |
| - in |
89 |
| - { name = machineName; |
90 |
| - value = evalConfig { |
91 |
| - modules = |
92 |
| - modules ++ |
93 |
| - defaults ++ |
94 |
| - [ deploymentInfoModule ] ++ |
95 |
| - [ { key = "nixops-stuff"; |
96 |
| - # Make NixOps's deployment.* options available. |
97 |
| - imports = [ ./options.nix ./resource.nix pluginOptions ]; |
98 |
| - # Provide a default hostname and deployment target equal |
99 |
| - # to the attribute name of the machine in the model. |
100 |
| - networking.hostName = lib.mkOverride 900 machineName; |
101 |
| - deployment.targetHost = lib.mkOverride 900 machineName; |
102 |
| - environment.checkConfigurationOptions = lib.mkOverride 900 checkConfigurationOptions; |
103 |
| - |
104 |
| - nixpkgs.system = lib.mkDefault system; |
105 |
| - |
106 |
| - _module.args = { inherit nodes resources uuid deploymentName; name = machineName; }; |
107 |
| - } |
108 |
| - ]; |
109 |
| - }; |
110 |
| - } |
111 |
| - ) (lib.attrNames (removeAttrs network [ "network" "defaults" "resources" "require" "nixpkgs" "_file" ]))); |
| 141 | + pluginDeploymentConfigExporters = (lib.foldl |
| 142 | + (a: e: a ++ (e.config_exporters { |
| 143 | + inherit pkgs; |
| 144 | + inherit (lib) optionalAttrs; |
| 145 | + })) [ ] |
| 146 | + importedPluginNixExprs); |
112 | 147 |
|
113 | 148 | # Compute the definitions of the non-machine resources.
|
114 | 149 | resourcesByType = lib.zipAttrs (network.resources or []);
|
@@ -158,18 +193,6 @@ in rec {
|
158 | 193 | publicIPv4 = "config.networking.publicIPv4";
|
159 | 194 | }.${key} or "config.deployment.${key}";
|
160 | 195 |
|
161 |
| - resources = lib.foldl |
162 |
| - (a: b: a // (b { |
163 |
| - inherit evalResources resourcesByType; |
164 |
| - inherit (lib) zipAttrs; |
165 |
| - })) |
166 |
| - { |
167 |
| - sshKeyPairs = evalResources ./ssh-keypair.nix (lib.zipAttrs resourcesByType.sshKeyPairs or []); |
168 |
| - commandOutput = evalResources ./command-output.nix (lib.zipAttrs resourcesByType.commandOutput or []); |
169 |
| - machines = lib.mapAttrs (n: v: v.config) nodes; |
170 |
| - } |
171 |
| - pluginResources; |
172 |
| - |
173 | 196 | # check if there are duplicate elements in a sorted list
|
174 | 197 | noDups = l:
|
175 | 198 | if lib.length l > 1
|
|
0 commit comments