From 485372107b9e3258e6848f8700a3b23da07404b1 Mon Sep 17 00:00:00 2001 From: paki23 Date: Sun, 20 Feb 2022 23:59:55 +0100 Subject: [PATCH 01/38] eval-machine-info.nix: ported to modules --- doc/release-notes/index.rst | 4 + flake.nix | 5 + nix/eval-machine-info.nix | 208 ++++++++++++++++++++---------------- 3 files changed, 125 insertions(+), 92 deletions(-) diff --git a/doc/release-notes/index.rst b/doc/release-notes/index.rst index af96ee319..0d3a35ba4 100644 --- a/doc/release-notes/index.rst +++ b/doc/release-notes/index.rst @@ -16,6 +16,10 @@ Release 2.0 - Major code cleanups. +- Now the network specification is using the module system from ``nixpkgs.lib`` + - Now network specification files can import other files via ``imports``. + - We have a ``nodes.*`` option where we put every NixOS configuration for the configured nodes. We suggest to use it instead of defining nodes in the top level. + - Removed NixOS Options - ``deployment.autoLuks.*`` - moved to `nixos-modules-contrib`_. diff --git a/flake.nix b/flake.nix index 250725be1..8257ef2d3 100644 --- a/flake.nix +++ b/flake.nix @@ -45,6 +45,7 @@ git_root=$(${pkgs.git}/bin/git rev-parse --show-toplevel) export PYTHONPATH=$git_root:$PYTHONPATH export PATH=$git_root/scripts:$PATH + export NIX_PATH="nixpkgs=${toString nixpkgs}:$NIX_PATH" ''; }; @@ -73,6 +74,10 @@ overrides ]; + postPatch = '' + substituteInPlace nix/eval-machine-info.nix --replace "" "${toString nixpkgs}" + ''; + # TODO: Re-add manual build }; diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index f92d34bad..78b4b200b 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -11,104 +11,140 @@ let call = x: if builtins.isFunction x then x args else x; - # Copied from nixpkgs to avoid import - optional = cond: elem: if cond then [elem] else []; - zipAttrs = set: builtins.listToAttrs ( map (name: { inherit name; value = builtins.catAttrs name set; }) (builtins.concatMap builtins.attrNames set)); - flakeExpr = (builtins.getFlake flakeUri).outputs.nixopsConfigurations.default; - - networks = - let - getNetworkFromExpr = networkExpr: - (call (import networkExpr)) // { _file = networkExpr; }; + flake = builtins.getFlake flakeUri; + flakeExpr = (builtins.tryEval flake.outputs.nixopsConfigurations.default).value or { }; - exprToKey = key: { key = toString key; }; + nixpkgsBoot = toString ; # this will be replaced on install by nixops' nixpkgs input + libBoot = import "${nixpkgsBoot}/lib"; - networkExprClosure = builtins.genericClosure { - startSet = map exprToKey networkExprs; - operator = { key }: map exprToKey ((getNetworkFromExpr key).require or []); + baseMods = lib: [ + { + options.nixpkgs = lib.mkOption { + type = lib.types.path; + description = "Path to the nixpkgs instance used to buld the machines."; + defaultText = lib.literalDocBook "The 'nixpkgs' input to either the provided flake or nixops' own."; + default = (builtins.tryEval flake.inputs.nixpkgs).value or nixpkgsBoot; }; - in - map ({ key }: getNetworkFromExpr key) networkExprClosure - ++ optional (flakeUri != null) - ((call flakeExpr) // { _file = "<${flakeUri}>"; }); + config._module.freeformType = with lib.types;attrsOf anything; + } + flakeExpr + ] ++ networkExprs; - network = zipAttrs networks; + evalBoot = libBoot.evalModules { + specialArgs = args; + modules = baseMods libBoot; + }; - evalConfig = - if flakeUri != null - then - if network ? nixpkgs - then (builtins.head (network.nixpkgs)).lib.nixosSystem - else throw "NixOps network must have a 'nixpkgs' attribute" - else import (pkgs.path + "/nixos/lib/eval-config.nix"); + inherit (evalBoot.config) nixpkgs; - pkgs = if flakeUri != null - then - if network ? nixpkgs - then (builtins.head network.nixpkgs).legacyPackages.${system} - else throw "NixOps network must have a 'nixpkgs' attribute" - else (builtins.head (network.network)).nixpkgs or (import { inherit system; }); + pkgs = nixpkgs.legacyPackages.${system} or import nixpkgs { inherit system; }; + lib = nixpkgs.lib or pkgs.lib or libBoot; + inherit (lib) mkOption types; + inherit (builtins) removeAttrs; - inherit (pkgs) lib; +in +rec { + inherit nixpkgs; - # Expose path to imported nixpkgs (currently only used to find version suffix) - nixpkgs = builtins.unsafeDiscardStringContext pkgs.path; + netConfig = (lib.evalModules { + specialArgs = args; + modules = baseMods lib ++ [ + ({ config, options, ... }: { + options = { + network = { + enableRollback = lib.mkEnableOption "network wide rollback"; + description = mkOption { + type = types.str; + description = "A description of the entire network."; + default = ""; + }; + nodesExtraArgs = mkOption { + description = "Extra inputs to be passed to every node."; + type = with types;attrsOf anything; + default = {}; + }; + }; + resources = mkOption { + type = types.submoduleWith { + modules = [{ + # so what is this trying to do? + sshKeyPairs = evalResources ./ssh-keypair.nix (lib.zipAttrs resourcesByType.sshKeyPairs or [ ]); + commandOutput = evalResources ./command-output.nix (lib.zipAttrs resourcesByType.commandOutput or [ ]); + machines = config.nodes; + _module.check = false; + }] ++ pluginResources; + specialArgs = { + inherit evalResources resourcesByType; + inherit (lib) zipAttrs; + }; + }; + }; + # Compute the definitions of the machines. + nodes = mkOption { + type = types.attrsOf (types.submoduleWith { + specialArgs = { + inherit uuid deploymentName; + inherit (config) nodes resources; + } // config.network.nodesExtraArgs; + modules = (import "${nixpkgs}/nixos/modules/module-list.nix") ++ + # Make NixOps's deployment.* options available. + pluginOptions ++ + [ + ./options.nix + ./resource.nix + deploymentInfoModule + config.defaults + ({ name, ... }: rec{ + _file = ./eval-machine-info.nix; + key = _file; + # Provide a default hostname and deployment target equal + # to the attribute name of the machine in the model. + networking.hostName = lib.mkOverride 900 name; + deployment.targetHost = lib.mkOverride 900 name; + environment.checkConfigurationOptions = lib.mkOverride 900 checkConfigurationOptions; + nixpkgs.system = lib.mkDefault system; + }) + ]; + }); + }; + defaults = mkOption { + type = types.anything; + default = { }; + description = '' + Extra NixOS options to add to all nodes. + ''; + }; + }; + config = let + nodes = removeAttrs config (builtins.attrNames options); + in lib.mkIf ({} != nodes) { #TODO: actual warning/assert module impl. + nodes = lib.warn "Please use the actual nodes.* option instead of assigning machines to the config's top level" nodes; + }; + }) + ]; + }).config; -in rec { + inherit (netConfig) resources nodes; + defaults = [ netConfig.defaults ]; - inherit networks network; - inherit nixpkgs; + # for backward compatibility + network = lib.mapAttrs (n: v: [v]) netConfig; + networks = [ netConfig ]; importedPluginNixExprs = map (expr: import expr) pluginNixExprs; - pluginOptions = { imports = (lib.foldl (a: e: a ++ e.options) [] importedPluginNixExprs); }; + pluginOptions = lib.foldl (a: e: a ++ e.options) [ ] importedPluginNixExprs; pluginResources = map (e: e.resources) importedPluginNixExprs; - pluginDeploymentConfigExporters = (lib.foldl (a: e: a ++ (e.config_exporters { - inherit pkgs; - inherit (lib) optionalAttrs; - })) [] importedPluginNixExprs); - - defaults = network.defaults or []; - - # Compute the definitions of the machines. - nodes = - lib.listToAttrs (map (machineName: - let - # Get the configuration of this machine from each network - # expression, attaching _file attributes so the NixOS module - # system can give sensible error messages. - modules = - lib.concatMap (n: lib.optional (lib.hasAttr machineName n) - { imports = [(lib.getAttr machineName n)]; inherit (n) _file; }) - networks; - in - { name = machineName; - value = evalConfig { - modules = - modules ++ - defaults ++ - [ deploymentInfoModule ] ++ - [ { key = "nixops-stuff"; - # Make NixOps's deployment.* options available. - imports = [ ./options.nix ./resource.nix pluginOptions ]; - # Provide a default hostname and deployment target equal - # to the attribute name of the machine in the model. - networking.hostName = lib.mkOverride 900 machineName; - deployment.targetHost = lib.mkOverride 900 machineName; - environment.checkConfigurationOptions = lib.mkOverride 900 checkConfigurationOptions; - - nixpkgs.system = lib.mkDefault system; - - _module.args = { inherit nodes resources uuid deploymentName; name = machineName; }; - } - ]; - }; - } - ) (lib.attrNames (removeAttrs network [ "network" "defaults" "resources" "require" "nixpkgs" "_file" ]))); + pluginDeploymentConfigExporters = (lib.foldl + (a: e: a ++ (e.config_exporters { + inherit pkgs; + inherit (lib) optionalAttrs; + })) [ ] + importedPluginNixExprs); # Compute the definitions of the non-machine resources. resourcesByType = lib.zipAttrs (network.resources or []); @@ -158,18 +194,6 @@ in rec { publicIPv4 = "config.networking.publicIPv4"; }.${key} or "config.deployment.${key}"; - resources = lib.foldl - (a: b: a // (b { - inherit evalResources resourcesByType; - inherit (lib) zipAttrs; - })) - { - sshKeyPairs = evalResources ./ssh-keypair.nix (lib.zipAttrs resourcesByType.sshKeyPairs or []); - commandOutput = evalResources ./command-output.nix (lib.zipAttrs resourcesByType.commandOutput or []); - machines = lib.mapAttrs (n: v: v.config) nodes; - } - pluginResources; - # check if there are duplicate elements in a sorted list noDups = l: if lib.length l > 1 From 8d067ed0c67c26c8899be7959cccfb6fb283684f Mon Sep 17 00:00:00 2001 From: paki23 Date: Wed, 23 Feb 2022 00:03:10 +0100 Subject: [PATCH 02/38] Fixing resources submodules --- nix/eval-machine-info.nix | 43 +++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index 78b4b200b..63840a120 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -70,11 +70,36 @@ rec { resources = mkOption { type = types.submoduleWith { modules = [{ - # so what is this trying to do? - sshKeyPairs = evalResources ./ssh-keypair.nix (lib.zipAttrs resourcesByType.sshKeyPairs or [ ]); - commandOutput = evalResources ./command-output.nix (lib.zipAttrs resourcesByType.commandOutput or [ ]); - machines = config.nodes; - _module.check = false; + options = let + resOpt = mainModule: mkOption { + type = types.attrsOf (types.submodule (r:{ + _module.args = { + inherit pkgs uuid; + resources = r.config; + # inherit nodes, essentially + nodes = + lib.mapAttrs + (nodeName: node: + lib.mapAttrs + (key: lib.warn "Resource ${r.name} accesses nodes.${nodeName}.${key}, which is deprecated. Use the equivalent option instead: nodes.${nodeName}.${newOpt key}.") + config.nodes.${nodeName}) + config.nodes; + }; + imports = [ + mainModule + deploymentInfoModule + ./resource.nix + ]; + })); + }; + in { + sshKeyPairs = resOpt ./ssh-keypair.nix; + commandOutput = resOpt ./command-output.nix; + }; + config = { + machines = config.nodes; + _module.check = false; + }; }] ++ pluginResources; specialArgs = { inherit evalResources resourcesByType; @@ -84,13 +109,13 @@ rec { }; # Compute the definitions of the machines. nodes = mkOption { - type = types.attrsOf (types.submoduleWith { + type = types.attrsOf (import "${nixpkgs}/nixos/lib/eval-config.nix" { + inherit lib system; specialArgs = { inherit uuid deploymentName; inherit (config) nodes resources; } // config.network.nodesExtraArgs; - modules = (import "${nixpkgs}/nixos/modules/module-list.nix") ++ - # Make NixOps's deployment.* options available. + modules = # Make NixOps's deployment.* options available. pluginOptions ++ [ ./options.nix @@ -108,7 +133,7 @@ rec { nixpkgs.system = lib.mkDefault system; }) ]; - }); + }).type; }; defaults = mkOption { type = types.anything; From 845e9c0f2825d9d5b2f837eeb45c8df62ddb5313 Mon Sep 17 00:00:00 2001 From: paki23 Date: Wed, 23 Feb 2022 19:38:25 +0100 Subject: [PATCH 03/38] Fixing nodes evaluation --- nix/eval-machine-info.nix | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index 63840a120..24c098aef 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -49,7 +49,7 @@ in rec { inherit nixpkgs; - netConfig = (lib.evalModules { + net = lib.evalModules { specialArgs = args; modules = baseMods lib ++ [ ({ config, options, ... }: { @@ -150,14 +150,16 @@ rec { }; }) ]; - }).config; + }; - inherit (netConfig) resources nodes; - defaults = [ netConfig.defaults ]; + inherit (net.config) resources; + defaults = [ net.config.defaults ]; + #TODO: take options and auter modules outputs for each node + nodes = lib.mapAttrs (n: v: {config = v;}) net.config.nodes; # for backward compatibility - network = lib.mapAttrs (n: v: [v]) netConfig; - networks = [ netConfig ]; + network = lib.mapAttrs (n: v: [v]) net.config; + networks = [ net.config ]; importedPluginNixExprs = map (expr: import expr) From a652e29b6710faf22e9d0353afbebe2f552c61be Mon Sep 17 00:00:00 2001 From: paki23 Date: Wed, 23 Feb 2022 21:24:40 +0100 Subject: [PATCH 04/38] Added defaults to resources --- nix/eval-machine-info.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index 24c098aef..1252b29a0 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -68,10 +68,12 @@ rec { }; }; resources = mkOption { + default = {}; type = types.submoduleWith { modules = [{ options = let resOpt = mainModule: mkOption { + default = {}; type = types.attrsOf (types.submodule (r:{ _module.args = { inherit pkgs uuid; @@ -109,6 +111,7 @@ rec { }; # Compute the definitions of the machines. nodes = mkOption { + description = "The NixOS configurations for the nodes in the network."; type = types.attrsOf (import "${nixpkgs}/nixos/lib/eval-config.nix" { inherit lib system; specialArgs = { From 1f6233446058ea5242d915c2748aea0532e26fd0 Mon Sep 17 00:00:00 2001 From: paki23 Date: Sun, 6 Mar 2022 02:32:22 +0100 Subject: [PATCH 05/38] eval-machine-info: fix parenthesis --- nix/eval-machine-info.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index 1252b29a0..6d141fc8b 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -40,7 +40,7 @@ let inherit (evalBoot.config) nixpkgs; - pkgs = nixpkgs.legacyPackages.${system} or import nixpkgs { inherit system; }; + pkgs = nixpkgs.legacyPackages.${system} or (import nixpkgs { inherit system; }); lib = nixpkgs.lib or pkgs.lib or libBoot; inherit (lib) mkOption types; inherit (builtins) removeAttrs; From da8126d33dfdcb8ff65574fd4b9baf6d569c8418 Mon Sep 17 00:00:00 2001 From: paki23 Date: Fri, 11 Mar 2022 23:34:52 +0100 Subject: [PATCH 06/38] defaults.type = defferredModules --- nix/eval-machine-info.nix | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index 6d141fc8b..eae75dd79 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -40,13 +40,11 @@ let inherit (evalBoot.config) nixpkgs; - pkgs = nixpkgs.legacyPackages.${system} or (import nixpkgs { inherit system; }); - lib = nixpkgs.lib or pkgs.lib or libBoot; - inherit (lib) mkOption types; - inherit (builtins) removeAttrs; + pkgs = (builtins.tryEval nixpkgs.legacyPackages.${system}).value or (import nixpkgs { inherit system; }); + lib = nixpkgs.lib or pkgs.lib or (builtins.tryEval (import "${nixpkgs}/lib")).value or libBoot; -in -rec { + inherit (lib) mkOption types; +in rec { inherit nixpkgs; net = lib.evalModules { @@ -104,7 +102,7 @@ rec { }; }] ++ pluginResources; specialArgs = { - inherit evalResources resourcesByType; + inherit evalResources resourcesByType lib; inherit (lib) zipAttrs; }; }; @@ -113,18 +111,18 @@ rec { nodes = mkOption { description = "The NixOS configurations for the nodes in the network."; type = types.attrsOf (import "${nixpkgs}/nixos/lib/eval-config.nix" { - inherit lib system; specialArgs = { inherit uuid deploymentName; inherit (config) nodes resources; } // config.network.nodesExtraArgs; - modules = # Make NixOps's deployment.* options available. + modules = + config.defaults ++ + # Make NixOps's deployment.* options available. pluginOptions ++ [ ./options.nix ./resource.nix deploymentInfoModule - config.defaults ({ name, ... }: rec{ _file = ./eval-machine-info.nix; key = _file; @@ -139,7 +137,13 @@ rec { }).type; }; defaults = mkOption { - type = types.anything; + type = with lib; mkOptionType {#TODO: remove after merging https://github.com/NixOS/nixpkgs/pull/163617 + name = "deferredModule"; + description = "module"; + check = t: isAttrs t || isFunction t || builtins.isPath t; + merge = loc: defs: map (def: lib.setDefaultModuleLocation "${showOption loc} from ${def.file}" def.value) defs; + }; + # type = types.deferredModule; default = { }; description = '' Extra NixOS options to add to all nodes. @@ -157,8 +161,13 @@ rec { inherit (net.config) resources; defaults = [ net.config.defaults ]; - #TODO: take options and auter modules outputs for each node - nodes = lib.mapAttrs (n: v: {config = v;}) net.config.nodes; + #TODO: take options and other modules outputs for each node + nodes = + lib.mapAttrs (n: v: { + config = v; + options = net.options.nodes.${n}; + inherit (v.nixpkgs) pkgs; + }) net.config.nodes; # for backward compatibility network = lib.mapAttrs (n: v: [v]) net.config; From 81282e8468d9b45a6f66f6702a660481b92d185e Mon Sep 17 00:00:00 2001 From: paki23 Date: Sun, 13 Mar 2022 19:13:37 +0100 Subject: [PATCH 07/38] network.storage option is now defined --- nix/eval-machine-info.nix | 62 ++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index eae75dd79..1c472081a 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -15,7 +15,7 @@ let map (name: { inherit name; value = builtins.catAttrs name set; }) (builtins.concatMap builtins.attrNames set)); flake = builtins.getFlake flakeUri; - flakeExpr = (builtins.tryEval flake.outputs.nixopsConfigurations.default).value or { }; + flakeExpr = flake.outputs.nixopsConfigurations.default or { }; nixpkgsBoot = toString ; # this will be replaced on install by nixops' nixpkgs input libBoot = import "${nixpkgsBoot}/lib"; @@ -26,24 +26,31 @@ let type = lib.types.path; description = "Path to the nixpkgs instance used to buld the machines."; defaultText = lib.literalDocBook "The 'nixpkgs' input to either the provided flake or nixops' own."; - default = (builtins.tryEval flake.inputs.nixpkgs).value or nixpkgsBoot; + default = flake.inputs.nixpkgs or nixpkgsBoot; }; - config._module.freeformType = with lib.types;attrsOf anything; } flakeExpr ] ++ networkExprs; - evalBoot = libBoot.evalModules { + inherit ((libBoot.evalModules { specialArgs = args; - modules = baseMods libBoot; - }; - - inherit (evalBoot.config) nixpkgs; + modules = baseMods libBoot ++ [{ + _module.freeformType = with libBoot.types;attrsOf anything; + }]; + }).config) nixpkgs; - pkgs = (builtins.tryEval nixpkgs.legacyPackages.${system}).value or (import nixpkgs { inherit system; }); + pkgs = nixpkgs.legacyPackages.${system} or (import nixpkgs { inherit system; }); lib = nixpkgs.lib or pkgs.lib or (builtins.tryEval (import "${nixpkgs}/lib")).value or libBoot; inherit (lib) mkOption types; + + deferredModule = with lib; mkOptionType {#TODO: remove after merging https://github.com/NixOS/nixpkgs/pull/163617 + name = "deferredModule"; + description = "module"; + check = t: isAttrs t || isFunction t || builtins.isPath t; + merge = loc: defs: map (def: lib.setDefaultModuleLocation "${showOption loc} from ${def.file}" def.value) defs; + }; + # inherit (types) deferredModule; in rec { inherit nixpkgs; @@ -64,6 +71,13 @@ in rec { type = with types;attrsOf anything; default = {}; }; + storage = mkOption { + description = "Configuring how to store the network state."; + default = {}; + type = with types; submodule { + _module.freeformType = attrsOf anything; + }; + }; }; resources = mkOption { default = {}; @@ -111,6 +125,7 @@ in rec { nodes = mkOption { description = "The NixOS configurations for the nodes in the network."; type = types.attrsOf (import "${nixpkgs}/nixos/lib/eval-config.nix" { + inherit system lib; specialArgs = { inherit uuid deploymentName; inherit (config) nodes resources; @@ -131,48 +146,41 @@ in rec { networking.hostName = lib.mkOverride 900 name; deployment.targetHost = lib.mkOverride 900 name; environment.checkConfigurationOptions = lib.mkOverride 900 checkConfigurationOptions; - nixpkgs.system = lib.mkDefault system; }) ]; }).type; }; defaults = mkOption { - type = with lib; mkOptionType {#TODO: remove after merging https://github.com/NixOS/nixpkgs/pull/163617 - name = "deferredModule"; - description = "module"; - check = t: isAttrs t || isFunction t || builtins.isPath t; - merge = loc: defs: map (def: lib.setDefaultModuleLocation "${showOption loc} from ${def.file}" def.value) defs; - }; - # type = types.deferredModule; + type = deferredModule; default = { }; description = '' Extra NixOS options to add to all nodes. ''; }; }; - config = let + config.nodes = let nodes = removeAttrs config (builtins.attrNames options); - in lib.mkIf ({} != nodes) { #TODO: actual warning/assert module impl. - nodes = lib.warn "Please use the actual nodes.* option instead of assigning machines to the config's top level" nodes; - }; + in lib.mkIf ({} != nodes) (lib.mapAttrs (n: imports:#TODO: actual warning/assert module impl. + lib.warn "Please use nodes.${n} option instead of assigning machines to the config's top level" + { inherit imports; }) nodes); }) + { _module.freeformType = types.attrsOf deferredModule; } ]; }; + # for backward compatibility + network = lib.mapAttrs (n: v: [v]) net.config; + networks = [ net.config ]; + inherit (net.config) resources; defaults = [ net.config.defaults ]; - #TODO: take options and other modules outputs for each node - nodes = + nodes = #TODO: take options and other modules outputs for each node lib.mapAttrs (n: v: { config = v; options = net.options.nodes.${n}; inherit (v.nixpkgs) pkgs; }) net.config.nodes; - # for backward compatibility - network = lib.mapAttrs (n: v: [v]) net.config; - networks = [ net.config ]; - importedPluginNixExprs = map (expr: import expr) pluginNixExprs; From 2b036d266cf8f009563d27bb803851337f38db2e Mon Sep 17 00:00:00 2001 From: paki23 Date: Sun, 13 Mar 2022 19:37:55 +0100 Subject: [PATCH 08/38] Split most of net's module system in separate file --- nix/eval-machine-info.nix | 120 ++++++++++---------------------------- nix/net.nix | 80 +++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 90 deletions(-) create mode 100644 nix/net.nix diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index 1c472081a..9b0ddeb09 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -20,6 +20,7 @@ let nixpkgsBoot = toString ; # this will be replaced on install by nixops' nixpkgs input libBoot = import "${nixpkgsBoot}/lib"; + specialArgs = lib: args // { inherit lib system; }; baseMods = lib: [ { options.nixpkgs = lib.mkOption { @@ -33,7 +34,7 @@ let ] ++ networkExprs; inherit ((libBoot.evalModules { - specialArgs = args; + specialArgs = specialArgs libBoot; modules = baseMods libBoot ++ [{ _module.freeformType = with libBoot.types;attrsOf anything; }]; @@ -41,52 +42,25 @@ let pkgs = nixpkgs.legacyPackages.${system} or (import nixpkgs { inherit system; }); lib = nixpkgs.lib or pkgs.lib or (builtins.tryEval (import "${nixpkgs}/lib")).value or libBoot; - inherit (lib) mkOption types; - deferredModule = with lib; mkOptionType {#TODO: remove after merging https://github.com/NixOS/nixpkgs/pull/163617 - name = "deferredModule"; - description = "module"; - check = t: isAttrs t || isFunction t || builtins.isPath t; - merge = loc: defs: map (def: lib.setDefaultModuleLocation "${showOption loc} from ${def.file}" def.value) defs; - }; - # inherit (types) deferredModule; in rec { inherit nixpkgs; net = lib.evalModules { - specialArgs = args; + specialArgs = specialArgs lib; modules = baseMods lib ++ [ - ({ config, options, ... }: { - options = { - network = { - enableRollback = lib.mkEnableOption "network wide rollback"; - description = mkOption { - type = types.str; - description = "A description of the entire network."; - default = ""; - }; - nodesExtraArgs = mkOption { - description = "Extra inputs to be passed to every node."; - type = with types;attrsOf anything; - default = {}; - }; - storage = mkOption { - description = "Configuring how to store the network state."; - default = {}; - type = with types; submodule { - _module.freeformType = attrsOf anything; - }; - }; - }; - resources = mkOption { - default = {}; - type = types.submoduleWith { - modules = [{ - options = let + ./net.nix + ({config, ...}:{ + options.resources = mkOption { + default = { }; + type = types.submoduleWith { + modules = [{ + options = + let resOpt = mainModule: mkOption { - default = {}; - type = types.attrsOf (types.submodule (r:{ + default = { }; + type = types.attrsOf (types.submodule (r: { _module.args = { inherit pkgs uuid; resources = r.config; @@ -106,65 +80,31 @@ in rec { ]; })); }; - in { + in + { sshKeyPairs = resOpt ./ssh-keypair.nix; commandOutput = resOpt ./command-output.nix; }; - config = { - machines = config.nodes; - _module.check = false; - }; - }] ++ pluginResources; - specialArgs = { - inherit evalResources resourcesByType lib; - inherit (lib) zipAttrs; + config = { + machines = config.nodes; + _module.check = false; }; + }] ++ pluginResources; + specialArgs = { + inherit evalResources resourcesByType lib; + inherit (lib) zipAttrs; }; }; - # Compute the definitions of the machines. - nodes = mkOption { - description = "The NixOS configurations for the nodes in the network."; - type = types.attrsOf (import "${nixpkgs}/nixos/lib/eval-config.nix" { - inherit system lib; - specialArgs = { - inherit uuid deploymentName; - inherit (config) nodes resources; - } // config.network.nodesExtraArgs; - modules = - config.defaults ++ - # Make NixOps's deployment.* options available. - pluginOptions ++ - [ - ./options.nix - ./resource.nix - deploymentInfoModule - ({ name, ... }: rec{ - _file = ./eval-machine-info.nix; - key = _file; - # Provide a default hostname and deployment target equal - # to the attribute name of the machine in the model. - networking.hostName = lib.mkOverride 900 name; - deployment.targetHost = lib.mkOverride 900 name; - environment.checkConfigurationOptions = lib.mkOverride 900 checkConfigurationOptions; - }) - ]; - }).type; - }; - defaults = mkOption { - type = deferredModule; - default = { }; - description = '' - Extra NixOS options to add to all nodes. - ''; - }; }; - config.nodes = let - nodes = removeAttrs config (builtins.attrNames options); - in lib.mkIf ({} != nodes) (lib.mapAttrs (n: imports:#TODO: actual warning/assert module impl. - lib.warn "Please use nodes.${n} option instead of assigning machines to the config's top level" - { inherit imports; }) nodes); }) - { _module.freeformType = types.attrsOf deferredModule; } + { + network.nodeExtraArgs = { + inherit uuid deploymentName; + }; + defaults.environment.checkConfigurationOptions = lib.mkOverride 900 checkConfigurationOptions; + # Make NixOps's deployment.* options available. + defaults.imports = pluginOptions ++ [ deploymentInfoModule ]; + } ]; }; diff --git a/nix/net.nix b/nix/net.nix new file mode 100644 index 000000000..b8722569b --- /dev/null +++ b/nix/net.nix @@ -0,0 +1,80 @@ +{ config, options, lib, system, ... }: +let + inherit (lib) mkOption types; + #TODO: remove after merging https://github.com/NixOS/nixpkgs/pull/163617 + deferredModule = with lib; mkOptionType { + name = "deferredModule"; + description = "module"; + check = t: isAttrs t || isFunction t || builtins.isPath t; + merge = loc: defs: map (def: lib.setDefaultModuleLocation "${showOption loc} from ${def.file}" def.value) defs; + }; + # inherit (types) deferredModule; +in +{ + options = { + network = { + enableRollback = lib.mkEnableOption "network wide rollback"; + description = mkOption { + type = types.str; + description = "A description of the entire network."; + default = ""; + }; + nodesExtraArgs = mkOption { + description = "Extra inputs to be passed to every node."; + type = with types;attrsOf anything; + default = { }; + }; + storage = mkOption { + description = "Configuring how to store the network state."; + default = { }; + type = with types; submodule { + _module.freeformType = attrsOf anything; + }; + }; + }; + # Compute the definitions of the machines. + nodes = mkOption { + description = "The NixOS configurations for the nodes in the network."; + type = types.attrsOf (import "${config.nixpkgs}/nixos/lib/eval-config.nix" { + inherit system lib; + specialArgs = { + inherit (config) nodes resources; + } // config.network.nodesExtraArgs; + modules = + config.defaults ++ + # Make NixOps's deployment.* options available. + [ + ./options.nix + ./resource.nix + ({ name, ... }: rec{ + _file = ./net.nix; + key = _file; + # Provide a default hostname and deployment target equal + # to the attribute name of the machine in the model. + networking.hostName = lib.mkOverride 900 name; + deployment.targetHost = lib.mkOverride 900 name; + }) + ]; + }).type; + }; + defaults = mkOption { + type = deferredModule; + default = { }; + description = '' + Extra NixOS options to add to all nodes. + ''; + }; + }; + config = { + nodes = + let + nodes = removeAttrs config (builtins.attrNames options); + in + lib.mkIf ({ } != nodes) (lib.mapAttrs + (n: imports: #TODO: actual warning/assert module impl. + lib.warn "Please use nodes.${n} option instead of assigning machines to the config's top level" + { inherit imports; }) + nodes); + _module.freeformType = types.attrsOf deferredModule; + }; +} From 33af8f8010ed83ba892a3b89053df616efd9e200 Mon Sep 17 00:00:00 2001 From: paki23 Date: Sun, 13 Mar 2022 20:17:17 +0100 Subject: [PATCH 09/38] Updated docs to use new nodes option --- doc/guides/deploy-without-root.rst | 2 +- doc/manual/nixops.rst | 6 +-- doc/manual/overview.rst | 70 ++++++++++++++++-------------- doc/overview.rst | 54 ++++++++++++----------- nix/eval-machine-info.nix | 8 ++-- 5 files changed, 73 insertions(+), 67 deletions(-) diff --git a/doc/guides/deploy-without-root.rst b/doc/guides/deploy-without-root.rst index dd53fa4a8..73eecc554 100644 --- a/doc/guides/deploy-without-root.rst +++ b/doc/guides/deploy-without-root.rst @@ -69,7 +69,7 @@ Edit your nixops.nix to specify the machine's { network.description = "Non-root deployment"; - hermes = + nodes.hermes = { resources, ... }: { deployment.targetUser = "deployer"; diff --git a/doc/manual/nixops.rst b/doc/manual/nixops.rst index 280a3808d..caa946edc 100644 --- a/doc/manual/nixops.rst +++ b/doc/manual/nixops.rst @@ -1067,9 +1067,9 @@ Consider the following deployment specification (``servers.nix``): :: - { nrMachines, active }: + { nrMachines, active, lib }: - with import ; + with lib; let @@ -1080,7 +1080,7 @@ Consider the following deployment specification (``servers.nix``): services.httpd.adminAddr = "foo@example.org"; }); - in listToAttrs (map makeMachine (range 1 nrMachines)) + in { nodes = listToAttrs (map makeMachine (range 1 nrMachines)); } This specifies a network of nrMachines identical VirtualBox VMs that run the Apache web server if active is set. To create 10 machines without diff --git a/doc/manual/overview.rst b/doc/manual/overview.rst index eae9168d4..7617242c1 100644 --- a/doc/manual/overview.rst +++ b/doc/manual/overview.rst @@ -18,7 +18,7 @@ and leave ``deployment.targetEnv`` undefined. See :: { - webserver = + nodes.webserver = { config, pkgs, ... }: { deployment.targetHost = "1.2.3.4"; }; @@ -87,11 +87,14 @@ example: imports = [ ./common.nix ]; }; - machine = { ... }: {}; + nodes.machine = { ... }: {}; } Each attribute is explained below: +``nodes.*`` + Applies the given NixOS configuration to the corresponding node. + ``defaults`` Applies given NixOS module to all machines defined in the network. @@ -118,7 +121,7 @@ Here is an example of a network with network arguments: { maintenance ? false }: { - machine = + nodes.machine = { config, pkgs, ... }: { services.httpd.enable = maintenance; ... @@ -172,7 +175,7 @@ Add a key to a machine like so. :: { - machine = + nodes.machine = { config, pkgs, ... }: { deployment.keys.my-secret.text = "shhh this is a secret"; @@ -181,7 +184,7 @@ Add a key to a machine like so. deployment.keys.my-secret.permissions = "0640"; }; } - + This will create a file ``/run/keys/my-secret`` with the specified contents, ownership, and permissions. @@ -208,7 +211,7 @@ and otherwise inactive when the key is absent. See :: { - machine = + nodes.machine = { config, pkgs, ... }: { deployment.keys.my-secret.text = "shhh this is a secret"; @@ -223,7 +226,7 @@ and otherwise inactive when the key is absent. See }; }; } - + These dependencies will ensure that the service is only started when the keys it requires are present. For example, after a reboot, the services @@ -243,33 +246,34 @@ This is possible by using the extra NixOS module input ``nodes``. { network.description = "Gollum server and reverse proxy"; + nodes = { + + gollum = + { config, pkgs, ... }: + { + services.gollum = { + enable = true; + port = 40273; + }; + networking.firewall.allowedTCPPorts = [ config.services.gollum.port ]; + }; + + reverseproxy = + { config, pkgs, nodes, ... }: + let + gollumPort = nodes.gollum.config.services.gollum.port; + in + { + services.nginx = { + enable = true; + virtualHosts."wiki.example.net".locations."/" = { + proxyPass = "http://gollum:${toString gollumPort}"; + }; + }; + networking.firewall.allowedTCPPorts = [ 80 ]; + };}; + }; - gollum = - { config, pkgs, ... }: - { - services.gollum = { - enable = true; - port = 40273; - }; - networking.firewall.allowedTCPPorts = [ config.services.gollum.port ]; - }; - - reverseproxy = - { config, pkgs, nodes, ... }: - let - gollumPort = nodes.gollum.config.services.gollum.port; - in - { - services.nginx = { - enable = true; - virtualHosts."wiki.example.net".locations."/" = { - proxyPass = "http://gollum:${toString gollumPort}"; - }; - }; - networking.firewall.allowedTCPPorts = [ 80 ]; - }; - } - Moving the port number to a different value is now without the risk of an inconsistent deployment. diff --git a/doc/overview.rst b/doc/overview.rst index 8a48f5a29..435503edd 100644 --- a/doc/overview.rst +++ b/doc/overview.rst @@ -21,7 +21,7 @@ machine, and leave ``deployment.targetEnv`` undefined. See :: { - webserver = + nodes.webserver = { config, pkgs, ... }: { deployment.targetHost = "1.2.3.4"; }; @@ -92,7 +92,7 @@ example: imports = [ ./common.nix ]; }; - machine = { ... }: {}; + nodes.machine = { ... }: {}; } Each attribute is explained below: @@ -122,7 +122,7 @@ Here is an example of a network with network arguments: { maintenance ? false }: { - machine = + nodes.machine = { config, pkgs, ... }: { services.httpd.enable = maintenance; ... @@ -175,7 +175,7 @@ Add a key to a machine like so. :: { - machine = + nodes.machine = { config, pkgs, ... }: { deployment.keys.my-secret.text = "shhh this is a secret"; @@ -216,7 +216,7 @@ and otherwise inactive when the key is absent. See :: { - machine = + nodes.machine = { config, pkgs, ... }: { deployment.keys.my-secret.text = "shhh this is a secret"; @@ -250,31 +250,33 @@ This is possible by using the extra NixOS module input ``nodes``. { network.description = "Gollum server and reverse proxy"; - - gollum = - { config, pkgs, ... }: - { - services.gollum = { - enable = true; - port = 40273; + + nodes = { + gollum = + { config, pkgs, ... }: + { + services.gollum = { + enable = true; + port = 40273; + }; + networking.firewall.allowedTCPPorts = [ config.services.gollum.port ]; }; - networking.firewall.allowedTCPPorts = [ config.services.gollum.port ]; - }; - reverseproxy = - { config, pkgs, nodes, ... }: - let - gollumPort = nodes.gollum.config.services.gollum.port; - in - { - services.nginx = { - enable = true; - virtualHosts."wiki.example.net".locations."/" = { - proxyPass = "http://gollum:${toString gollumPort}"; + reverseproxy = + { config, pkgs, nodes, ... }: + let + gollumPort = nodes.gollum.config.services.gollum.port; + in + { + services.nginx = { + enable = true; + virtualHosts."wiki.example.net".locations."/" = { + proxyPass = "http://gollum:${toString gollumPort}"; + }; }; + networking.firewall.allowedTCPPorts = [ 80 ]; }; - networking.firewall.allowedTCPPorts = [ 80 ]; - }; + }; } Moving the port number to a different value is now without the risk of diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index 9b0ddeb09..4c85f6b42 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -55,12 +55,12 @@ in rec { options.resources = mkOption { default = { }; type = types.submoduleWith { - modules = [{ + modules = [(r:{ options = let resOpt = mainModule: mkOption { default = { }; - type = types.attrsOf (types.submodule (r: { + type = types.attrsOf (types.submodule { _module.args = { inherit pkgs uuid; resources = r.config; @@ -78,7 +78,7 @@ in rec { deploymentInfoModule ./resource.nix ]; - })); + }); }; in { @@ -89,7 +89,7 @@ in rec { machines = config.nodes; _module.check = false; }; - }] ++ pluginResources; + })] ++ pluginResources; specialArgs = { inherit evalResources resourcesByType lib; inherit (lib) zipAttrs; From bda08d7cb1bdd8322002dce48ed00e21f3832b59 Mon Sep 17 00:00:00 2001 From: paki23 Date: Sun, 13 Mar 2022 21:15:20 +0100 Subject: [PATCH 10/38] remove indentation from net expression --- nix/eval-machine-info.nix | 143 +++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 73 deletions(-) diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index 4c85f6b42..f1a5c03b1 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -20,25 +20,24 @@ let nixpkgsBoot = toString ; # this will be replaced on install by nixops' nixpkgs input libBoot = import "${nixpkgsBoot}/lib"; - specialArgs = lib: args // { inherit lib system; }; - baseMods = lib: [ - { - options.nixpkgs = lib.mkOption { - type = lib.types.path; - description = "Path to the nixpkgs instance used to buld the machines."; - defaultText = lib.literalDocBook "The 'nixpkgs' input to either the provided flake or nixops' own."; - default = flake.inputs.nixpkgs or nixpkgsBoot; - }; - } - flakeExpr - ] ++ networkExprs; + evalModules = lib: modules: lib.evalModules { + specialArgs = args // { inherit lib system; }; + modules = modules ++ networkExprs ++ [ + flakeExpr + { + options.nixpkgs = lib.mkOption { + type = lib.types.path; + description = "Path to the nixpkgs instance used to buld the machines."; + defaultText = lib.literalDocBook "The 'nixpkgs' input to either the provided flake or nixops' own."; + default = flake.inputs.nixpkgs or nixpkgsBoot; + }; + } + ]; + }; - inherit ((libBoot.evalModules { - specialArgs = specialArgs libBoot; - modules = baseMods libBoot ++ [{ - _module.freeformType = with libBoot.types;attrsOf anything; - }]; - }).config) nixpkgs; + inherit ((evalModules libBoot [{ + _module.freeformType = with libBoot.types;attrsOf anything; + }]).config) nixpkgs; pkgs = nixpkgs.legacyPackages.${system} or (import nixpkgs { inherit system; }); lib = nixpkgs.lib or pkgs.lib or (builtins.tryEval (import "${nixpkgs}/lib")).value or libBoot; @@ -47,66 +46,64 @@ let in rec { inherit nixpkgs; - net = lib.evalModules { - specialArgs = specialArgs lib; - modules = baseMods lib ++ [ - ./net.nix - ({config, ...}:{ - options.resources = mkOption { - default = { }; - type = types.submoduleWith { - modules = [(r:{ - options = - let - resOpt = mainModule: mkOption { - default = { }; - type = types.attrsOf (types.submodule { - _module.args = { - inherit pkgs uuid; - resources = r.config; - # inherit nodes, essentially - nodes = - lib.mapAttrs - (nodeName: node: - lib.mapAttrs - (key: lib.warn "Resource ${r.name} accesses nodes.${nodeName}.${key}, which is deprecated. Use the equivalent option instead: nodes.${nodeName}.${newOpt key}.") - config.nodes.${nodeName}) - config.nodes; - }; - imports = [ - mainModule - deploymentInfoModule - ./resource.nix - ]; - }); - }; - in - { - sshKeyPairs = resOpt ./ssh-keypair.nix; - commandOutput = resOpt ./command-output.nix; + net = evalModules lib [ + ./net.nix + ({config, ...}:{ + options.resources = mkOption { + default = { }; + type = types.submoduleWith { + modules = [(r:{ + options = + let + resOpt = mainModule: mkOption { + default = { }; + type = types.attrsOf (types.submodule { + _module.args = { + inherit pkgs uuid; + resources = r.config; + # inherit nodes, essentially + nodes = + lib.mapAttrs + (nodeName: node: + lib.mapAttrs + (key: lib.warn + "Resource ${r.name} accesses nodes.${nodeName}.${key}, which is deprecated. Use the equivalent option instead: nodes.${nodeName}.${newOpt key}.") + config.nodes.${nodeName}) + config.nodes; + }; + imports = [ + mainModule + deploymentInfoModule + ./resource.nix + ]; + }); }; - config = { - machines = config.nodes; - _module.check = false; + in + { + sshKeyPairs = resOpt ./ssh-keypair.nix; + commandOutput = resOpt ./command-output.nix; }; - })] ++ pluginResources; - specialArgs = { - inherit evalResources resourcesByType lib; - inherit (lib) zipAttrs; + config = { + machines = config.nodes; + _module.check = false; }; + })] ++ pluginResources; + specialArgs = { + inherit evalResources resourcesByType lib; + inherit (lib) zipAttrs; }; }; - }) - { - network.nodeExtraArgs = { - inherit uuid deploymentName; - }; - defaults.environment.checkConfigurationOptions = lib.mkOverride 900 checkConfigurationOptions; - # Make NixOps's deployment.* options available. - defaults.imports = pluginOptions ++ [ deploymentInfoModule ]; - } - ]; - }; + }; + }) + { + network.nodeExtraArgs = { + inherit uuid deploymentName; + }; + defaults.environment.checkConfigurationOptions = lib.mkOverride 900 checkConfigurationOptions; + # Make NixOps's deployment.* options available. + defaults.imports = pluginOptions ++ [ deploymentInfoModule ]; + } + ]; # for backward compatibility network = lib.mapAttrs (n: v: [v]) net.config; From 82934a278d45b94448e9ab637be737099aa51356 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 6 Apr 2022 18:24:04 +0200 Subject: [PATCH 11/38] eval-machine-info: Allow flakeUri to be unset --- nix/eval-machine-info.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index f1a5c03b1..736e6bd53 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -1,6 +1,7 @@ { system ? builtins.currentSystem , networkExprs , flakeUri ? null +, flake ? if flakeUri == null then null else builtins.getFlake flakeUri , checkConfigurationOptions ? true , uuid , deploymentName @@ -14,7 +15,6 @@ let zipAttrs = set: builtins.listToAttrs ( map (name: { inherit name; value = builtins.catAttrs name set; }) (builtins.concatMap builtins.attrNames set)); - flake = builtins.getFlake flakeUri; flakeExpr = flake.outputs.nixopsConfigurations.default or { }; nixpkgsBoot = toString ; # this will be replaced on install by nixops' nixpkgs input From 8d1cb81138b3ab45d91ec1a2bd69073fa115e987 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 6 Apr 2022 18:25:20 +0200 Subject: [PATCH 12/38] eval-machine-info: Backcompat for nodes..config parameter --- nix/net.nix | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/nix/net.nix b/nix/net.nix index b8722569b..c198cd0fb 100644 --- a/nix/net.nix +++ b/nix/net.nix @@ -1,6 +1,6 @@ { config, options, lib, system, ... }: let - inherit (lib) mkOption types; + inherit (lib) mkOption types mapAttrs warn; #TODO: remove after merging https://github.com/NixOS/nixpkgs/pull/163617 deferredModule = with lib; mkOptionType { name = "deferredModule"; @@ -9,6 +9,15 @@ let merge = loc: defs: map (def: lib.setDefaultModuleLocation "${showOption loc} from ${def.file}" def.value) defs; }; # inherit (types) deferredModule; + + nodesConfigCompat = k: n: + n // { + config = + warn + "The module parameter `nodes.${lib.strings.escapeNixIdentifier k}.config' has been renamed to `nodes.${lib.strings.escapeNixIdentifier k}'" + n; + options = throw "nodes..options is not available anymore. You can access options information by writing a node-level module that extracts the options information and assigns it to a new option of your choosing."; + }; in { options = { @@ -38,7 +47,8 @@ in type = types.attrsOf (import "${config.nixpkgs}/nixos/lib/eval-config.nix" { inherit system lib; specialArgs = { - inherit (config) nodes resources; + inherit (config) resources; + nodes = mapAttrs nodesConfigCompat config.nodes; } // config.network.nodesExtraArgs; modules = config.defaults ++ From 148270e552b29fe603f4914dea3f9530de3bcd4e Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 6 Apr 2022 18:25:47 +0200 Subject: [PATCH 13/38] nix/net.nix: Adjust legacy node notation message --- nix/net.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/net.nix b/nix/net.nix index c198cd0fb..9a5fa6f02 100644 --- a/nix/net.nix +++ b/nix/net.nix @@ -82,7 +82,7 @@ in in lib.mkIf ({ } != nodes) (lib.mapAttrs (n: imports: #TODO: actual warning/assert module impl. - lib.warn "Please use nodes.${n} option instead of assigning machines to the config's top level" + lib.warn "Please write to `nodes.${n}' instead of a top-level `${n}' config." { inherit imports; }) nodes); _module.freeformType = types.attrsOf deferredModule; From 51bdc5c39bf3c0dfb7fb47f1c1661065d4d6dc72 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 6 Apr 2022 23:04:27 +0200 Subject: [PATCH 14/38] eval-machine-info: Make resources proper submodules --- nix/eval-machine-info.nix | 110 ++++++++++++++++++++++++++------------ 1 file changed, 75 insertions(+), 35 deletions(-) diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index 736e6bd53..9b5815fd8 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -87,11 +87,7 @@ in rec { machines = config.nodes; _module.check = false; }; - })] ++ pluginResources; - specialArgs = { - inherit evalResources resourcesByType lib; - inherit (lib) zipAttrs; - }; + })] ++ pluginResourceModules; }; }; }) @@ -141,37 +137,81 @@ in rec { }; }; - evalResources = mainModule: _resources: - lib.mapAttrs - (name: defs: - let - # Arguments fed to all modules - moduleArgs = { - _module.args = { - inherit pkgs uuid name resources; - - # inherit nodes, essentially - nodes = - lib.mapAttrs - (nodeName: node: - lib.mapAttrs - (key: lib.warn "Resource ${name} accesses nodes.${nodeName}.${key}, which is deprecated. Use the equivalent option instead: nodes.${nodeName}.${newOpt key}.") - info.machines.${nodeName} - // node) - nodes; - }; - }; + defaultResourceModule = { + imports = [ + ./resource.nix + resourceModuleArgs + deploymentInfoModule + ]; + }; + + pluginResourceModules = lib.lists.concatMap (lib.mapAttrsToList toResourceModule) pluginResourceLegacyReprs; + + toResourceModule = k: { _type, resourceModule }: + { + options.${k} = lib.mkOption { + type = lib.types.attrsOf (lib.types.submoduleWith { modules = [ - moduleArgs - mainModule - deploymentInfoModule - ./resource.nix - ] ++ defs; - in - builtins.removeAttrs - (lib.evalModules { inherit modules; }).config - ["_module"]) - _resources; + defaultResourceModule + resourceModule + ]; + }); + default = { /* no resources configured */ }; + }; + }; + + pluginResourceLegacyReprs = + (map + (f: + lib.mapAttrs + validateLegacyRepr + (f { + inherit evalResources resourcesByType lib; + inherit (lib) zipAttrs; + }) + ) + pluginResources + ); + + validateLegacyRepr = k: v: + if v._type or null == "legacyResourceRepresentation" then + v + else + throw + ''Legacy plugin resources are only supported if they follow the pattern: + + resources = { evalResources, zipAttrs, resourcesByType, ... }: { + foos = evalResources ./foo.nix (zipAttrs resourcesByType.foos or []); + # ... + }; + + The resource ${k} did not follow that pattern. Please update the + corresponding plugin to declare the resource submodule directly instead. + ''; + + resourceModuleArgs = { name, ... }: { + _module.args = { + inherit pkgs uuid resources; + + # inherit nodes, essentially + nodes = + lib.mapAttrs + (nodeName: node: + lib.mapAttrs + (key: lib.warn "Resource ${name} accesses nodes.${nodeName}.${key}, which is deprecated. Use the equivalent option instead: nodes.${nodeName}.${newOpt key}.") + info.machines.${nodeName} + // node) + nodes; + }; + }; + + # NOTE: this is a legacy name. It does not invoke the module system, + # but rather preserves one argument, so that it can be turned + # into a proper submodule later. + evalResources = resourceModule: _: { + _type = "legacyResourceRepresentation"; + inherit resourceModule; + }; newOpt = key: { nixosRelease = "config.system.nixos.release and make sure it is set properly"; From a2724b1cf7b593c1fb61a82dedf23dc418a3b1dc Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 7 Apr 2022 15:06:36 +0200 Subject: [PATCH 15/38] eval-machine-info: Re-add machine resource --- nix/eval-machine-info.nix | 1 + nix/machine-resource.nix | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 nix/machine-resource.nix diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index 9b5815fd8..fc9dff975 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -82,6 +82,7 @@ in rec { { sshKeyPairs = resOpt ./ssh-keypair.nix; commandOutput = resOpt ./command-output.nix; + machines = resOpt ./machine-resource.nix; }; config = { machines = config.nodes; diff --git a/nix/machine-resource.nix b/nix/machine-resource.nix new file mode 100644 index 000000000..82a45a929 --- /dev/null +++ b/nix/machine-resource.nix @@ -0,0 +1,13 @@ + +# Machine resource + +{ config, lib, uuid, name, ... }: + +with lib; + +{ + freeformType = lib.types.raw or lib.types.unspecified; + options = { + + }; +} From 4d27834af38a2e92e988124ffbf8e179ec4c4c53 Mon Sep 17 00:00:00 2001 From: paki23 Date: Sun, 15 May 2022 13:53:53 +0200 Subject: [PATCH 16/38] merge --- nix/net.nix | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/nix/net.nix b/nix/net.nix index 9a5fa6f02..d71649032 100644 --- a/nix/net.nix +++ b/nix/net.nix @@ -81,9 +81,10 @@ in nodes = removeAttrs config (builtins.attrNames options); in lib.mkIf ({ } != nodes) (lib.mapAttrs - (n: imports: #TODO: actual warning/assert module impl. - lib.warn "Please write to `nodes.${n}' instead of a top-level `${n}' config." - { inherit imports; }) + (n: imports: { + inherit imports; + warnings = [ "Please use nodes.${n} option instead of assigning machines to the config's top level" ]; + }) nodes); _module.freeformType = types.attrsOf deferredModule; }; From 5a225f7ea8ae73b6178c5e3c4ca910711e7a50f9 Mon Sep 17 00:00:00 2001 From: paki23 Date: Sun, 15 May 2022 18:35:26 +0200 Subject: [PATCH 17/38] Adding defineResource to quickly define a resource type --- .vscode/settings.json | 3 ++ nix/eval-machine-info.nix | 71 ++++++++++----------------------------- nix/net.nix | 35 +++++++++++++++++++ nixops/deployment.py | 3 ++ 4 files changed, 59 insertions(+), 53 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..44aef9f94 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.formatting.provider": "black" +} \ No newline at end of file diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index fc9dff975..832070489 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -41,65 +41,25 @@ let pkgs = nixpkgs.legacyPackages.${system} or (import nixpkgs { inherit system; }); lib = nixpkgs.lib or pkgs.lib or (builtins.tryEval (import "${nixpkgs}/lib")).value or libBoot; - inherit (lib) mkOption types; in rec { inherit nixpkgs; net = evalModules lib [ ./net.nix - ({config, ...}:{ - options.resources = mkOption { - default = { }; - type = types.submoduleWith { - modules = [(r:{ - options = - let - resOpt = mainModule: mkOption { - default = { }; - type = types.attrsOf (types.submodule { - _module.args = { - inherit pkgs uuid; - resources = r.config; - # inherit nodes, essentially - nodes = - lib.mapAttrs - (nodeName: node: - lib.mapAttrs - (key: lib.warn - "Resource ${r.name} accesses nodes.${nodeName}.${key}, which is deprecated. Use the equivalent option instead: nodes.${nodeName}.${newOpt key}.") - config.nodes.${nodeName}) - config.nodes; - }; - imports = [ - mainModule - deploymentInfoModule - ./resource.nix - ]; - }); - }; - in - { - sshKeyPairs = resOpt ./ssh-keypair.nix; - commandOutput = resOpt ./command-output.nix; - machines = resOpt ./machine-resource.nix; - }; - config = { - machines = config.nodes; - _module.check = false; - }; - })] ++ pluginResourceModules; - }; - }; - }) - { - network.nodeExtraArgs = { - inherit uuid deploymentName; - }; + ({ config, ... }: { + resources.imports = pluginResourceModules ++ [ deploymentInfoModule ]; + network.resourcesDefaults.imports = [ + (resourceModuleArgs_ rec{ + inherit (config) nodes resources; + machines = nodes; + }) + ]; + network.nodeExtraArgs = { inherit uuid deploymentName; }; defaults.environment.checkConfigurationOptions = lib.mkOverride 900 checkConfigurationOptions; # Make NixOps's deployment.* options available. defaults.imports = pluginOptions ++ [ deploymentInfoModule ]; - } + }) ]; # for backward compatibility @@ -190,7 +150,12 @@ in rec { corresponding plugin to declare the resource submodule directly instead. ''; - resourceModuleArgs = { name, ... }: { + resourceModuleArgs = resourceModuleArgs_ { + inherit nodes resources; + inherit (info) machines; + }; + + resourceModuleArgs_ = { nodes, resources, machines }: { name, ... }: { _module.args = { inherit pkgs uuid resources; @@ -200,7 +165,7 @@ in rec { (nodeName: node: lib.mapAttrs (key: lib.warn "Resource ${name} accesses nodes.${nodeName}.${key}, which is deprecated. Use the equivalent option instead: nodes.${nodeName}.${newOpt key}.") - info.machines.${nodeName} + machines.${nodeName} // node) nodes; }; @@ -263,7 +228,7 @@ in rec { network = builtins.removeAttrs (lib.fold (as: bs: as // bs) {} (network'.network or [])) - [ "nixpkgs" ] # Not serialisable + [ "nixpkgs" "resourcesDefaults" "nodesExtraArgs" ] # Not serialisable ; resources = diff --git a/nix/net.nix b/nix/net.nix index d71649032..afb3898fc 100644 --- a/nix/net.nix +++ b/nix/net.nix @@ -40,6 +40,41 @@ in _module.freeformType = attrsOf anything; }; }; + resourcesDefaults = mkOption { + type = deferredModule; + internal = true; + default = { }; + description = '' + Extra configurations to add to all resources. + ''; + }; + }; + resources = mkOption { + default = { }; + type = types.submoduleWith { + specialArgs.defineResource = name: mainModule: { + options.${name} = mkOption { + default = { }; + type = types.attrsOf (types.submoduleWith { + modules = config.network.resourcesDefaults ++ [ mainModule ]; + }); + }; + }; + modules = [ + ./resource.nix + ({ defineResource, ... }: { + imports = [ + (defineResource "sshKeyPairs" ./ssh-keypair.nix) + (defineResource "commandOutput" ./command-output.nix) + (defineResource "machines" ./machine-resource.nix) + ]; + }) + { + machines = config.nodes; + _module.check = false; + } + ]; + }; }; # Compute the definitions of the machines. nodes = mkOption { diff --git a/nixops/deployment.py b/nixops/deployment.py index 42facaba5..5ccff8cda 100644 --- a/nixops/deployment.py +++ b/nixops/deployment.py @@ -447,6 +447,9 @@ def evaluate(self) -> None: # Extract info about other kinds of resources. for res_type, cfg in config["resources"].items(): + # skip problematic resources entries + if res_type in ["deployment", "_name", "_type"]: + continue for name, y in cfg.items(): defn = _create_definition( name, config["resources"][res_type][name], res_type From 115d0a6cb81087a94d97ee8e5bbee874bc8f9886 Mon Sep 17 00:00:00 2001 From: paki23 Date: Tue, 14 Jun 2022 23:30:08 +0200 Subject: [PATCH 18/38] net.nix: deferredModules now import a single module --- nix/net.nix | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/nix/net.nix b/nix/net.nix index afb3898fc..deada4a29 100644 --- a/nix/net.nix +++ b/nix/net.nix @@ -6,7 +6,7 @@ let name = "deferredModule"; description = "module"; check = t: isAttrs t || isFunction t || builtins.isPath t; - merge = loc: defs: map (def: lib.setDefaultModuleLocation "${showOption loc} from ${def.file}" def.value) defs; + merge = loc: defs: { imports = map (def: lib.setDefaultModuleLocation "${showOption loc} from ${def.file}" def.value) defs; }; }; # inherit (types) deferredModule; @@ -56,7 +56,10 @@ in options.${name} = mkOption { default = { }; type = types.attrsOf (types.submoduleWith { - modules = config.network.resourcesDefaults ++ [ mainModule ]; + modules = [ + config.network.resourcesDefaults + mainModule + ]; }); }; }; @@ -68,11 +71,9 @@ in (defineResource "commandOutput" ./command-output.nix) (defineResource "machines" ./machine-resource.nix) ]; - }) - { machines = config.nodes; _module.check = false; - } + }) ]; }; }; @@ -85,21 +86,20 @@ in inherit (config) resources; nodes = mapAttrs nodesConfigCompat config.nodes; } // config.network.nodesExtraArgs; - modules = - config.defaults ++ + modules = [ + config.defaults # Make NixOps's deployment.* options available. - [ - ./options.nix - ./resource.nix - ({ name, ... }: rec{ - _file = ./net.nix; - key = _file; - # Provide a default hostname and deployment target equal - # to the attribute name of the machine in the model. - networking.hostName = lib.mkOverride 900 name; - deployment.targetHost = lib.mkOverride 900 name; - }) - ]; + ./options.nix + ./resource.nix + ({ name, ... }: rec{ + _file = ./net.nix; + key = _file; + # Provide a default hostname and deployment target equal + # to the attribute name of the machine in the model. + networking.hostName = lib.mkOverride 900 name; + deployment.targetHost = lib.mkOverride 900 name; + }) + ]; }).type; }; defaults = mkOption { @@ -116,9 +116,9 @@ in nodes = removeAttrs config (builtins.attrNames options); in lib.mkIf ({ } != nodes) (lib.mapAttrs - (n: imports: { - inherit imports; - warnings = [ "Please use nodes.${n} option instead of assigning machines to the config's top level" ]; + (name: node: { + imports = [ node ]; + warnings = [ "Please use nodes.${name} option instead of assigning machines to the config's top level" ]; }) nodes); _module.freeformType = types.attrsOf deferredModule; From 533d34874418bda0eae435c899b2ffc155ba1719 Mon Sep 17 00:00:00 2001 From: paki23 Date: Sun, 19 Jun 2022 14:36:26 +0200 Subject: [PATCH 19/38] resource filtering now done in eval-machine.nix to make mypy-rachet.py happy --- nix/eval-machine-info.nix | 3 ++- nixops/deployment.py | 3 --- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index 832070489..043bf231c 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -66,7 +66,8 @@ in rec { network = lib.mapAttrs (n: v: [v]) net.config; networks = [ net.config ]; - inherit (net.config) resources; + # skip problematic resources entries + resources = lib.attrsets.filterAttrs(n: v: lib.lists.all(e: e!=n)["deployment" "_name" "_type"]) net.config.resources; defaults = [ net.config.defaults ]; nodes = #TODO: take options and other modules outputs for each node lib.mapAttrs (n: v: { diff --git a/nixops/deployment.py b/nixops/deployment.py index 5ccff8cda..42facaba5 100644 --- a/nixops/deployment.py +++ b/nixops/deployment.py @@ -447,9 +447,6 @@ def evaluate(self) -> None: # Extract info about other kinds of resources. for res_type, cfg in config["resources"].items(): - # skip problematic resources entries - if res_type in ["deployment", "_name", "_type"]: - continue for name, y in cfg.items(): defn = _create_definition( name, config["resources"][res_type][name], res_type From 7eba0d0608c437d60eadcc92a852191e7d2c03cf Mon Sep 17 00:00:00 2001 From: paki23 Date: Thu, 1 Dec 2022 19:50:56 +0100 Subject: [PATCH 20/38] net.nix: deferredModules has been merged in nixpkgs --- nix/net.nix | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/nix/net.nix b/nix/net.nix index deada4a29..a93c146a7 100644 --- a/nix/net.nix +++ b/nix/net.nix @@ -1,14 +1,7 @@ { config, options, lib, system, ... }: let inherit (lib) mkOption types mapAttrs warn; - #TODO: remove after merging https://github.com/NixOS/nixpkgs/pull/163617 - deferredModule = with lib; mkOptionType { - name = "deferredModule"; - description = "module"; - check = t: isAttrs t || isFunction t || builtins.isPath t; - merge = loc: defs: { imports = map (def: lib.setDefaultModuleLocation "${showOption loc} from ${def.file}" def.value) defs; }; - }; - # inherit (types) deferredModule; + inherit (types) deferredModule; nodesConfigCompat = k: n: n // { From 5182ff4ed9b29f5db666079f04b97332ea45450c Mon Sep 17 00:00:00 2001 From: paki23 Date: Thu, 2 Feb 2023 17:43:25 +0100 Subject: [PATCH 21/38] eval-machine-info: a bit of cleanup --- nix/eval-machine-info.nix | 55 ++++++++++++++------------------------- 1 file changed, 20 insertions(+), 35 deletions(-) diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index 043bf231c..47d2458bb 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -10,11 +10,6 @@ }: let - call = x: if builtins.isFunction x then x args else x; - - zipAttrs = set: builtins.listToAttrs ( - map (name: { inherit name; value = builtins.catAttrs name set; }) (builtins.concatMap builtins.attrNames set)); - flakeExpr = flake.outputs.nixopsConfigurations.default or { }; nixpkgsBoot = toString ; # this will be replaced on install by nixops' nixpkgs input @@ -49,12 +44,10 @@ in rec { ./net.nix ({ config, ... }: { resources.imports = pluginResourceModules ++ [ deploymentInfoModule ]; - network.resourcesDefaults.imports = [ - (resourceModuleArgs_ rec{ - inherit (config) nodes resources; - machines = nodes; - }) - ]; + network.resourcesDefaults = resourceModuleArgs_ rec{ + inherit (config) nodes resources; + machines = nodes; + }; network.nodeExtraArgs = { inherit uuid deploymentName; }; defaults.environment.checkConfigurationOptions = lib.mkOverride 900 checkConfigurationOptions; # Make NixOps's deployment.* options available. @@ -67,7 +60,7 @@ in rec { networks = [ net.config ]; # skip problematic resources entries - resources = lib.attrsets.filterAttrs(n: v: lib.lists.all(e: e!=n)["deployment" "_name" "_type"]) net.config.resources; + resources = removeAttrs net.config.resources ["deployment" "_name" "_type"]; defaults = [ net.config.defaults ]; nodes = #TODO: take options and other modules outputs for each node lib.mapAttrs (n: v: { @@ -76,36 +69,28 @@ in rec { inherit (v.nixpkgs) pkgs; }) net.config.nodes; - importedPluginNixExprs = map - (expr: import expr) - pluginNixExprs; - pluginOptions = lib.foldl (a: e: a ++ e.options) [ ] importedPluginNixExprs; + importedPluginNixExprs = map import pluginNixExprs; + pluginOptions = lib.lists.concatMap (e: e.options) importedPluginNixExprs; pluginResources = map (e: e.resources) importedPluginNixExprs; - pluginDeploymentConfigExporters = (lib.foldl - (a: e: a ++ (e.config_exporters { - inherit pkgs; - inherit (lib) optionalAttrs; - })) [ ] - importedPluginNixExprs); + pluginDeploymentConfigExporters = lib.lists.concatMap (e: e.config_exporters { + inherit pkgs; + inherit (lib) optionalAttrs; + }) importedPluginNixExprs; # Compute the definitions of the non-machine resources. resourcesByType = lib.zipAttrs (network.resources or []); - deploymentInfoModule = { - deployment = { - name = deploymentName; - arguments = args; - inherit uuid; - }; + deploymentInfoModule.deployment = { + name = deploymentName; + arguments = args; + inherit uuid; }; - defaultResourceModule = { - imports = [ - ./resource.nix - resourceModuleArgs - deploymentInfoModule - ]; - }; + defaultResourceModule.imports = [ + ./resource.nix + resourceModuleArgs + deploymentInfoModule + ]; pluginResourceModules = lib.lists.concatMap (lib.mapAttrsToList toResourceModule) pluginResourceLegacyReprs; From 9c534fe3507ad3b19295e6f9e41d7429c7047a62 Mon Sep 17 00:00:00 2001 From: paki23 Date: Sat, 4 Feb 2023 21:12:59 +0100 Subject: [PATCH 22/38] eval-machine-info: move net.nix import in 1st module evaluation --- nix/eval-machine-info.nix | 50 ++++++++++++++++----------------------- nix/net.nix | 5 ++++ 2 files changed, 25 insertions(+), 30 deletions(-) diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index 47d2458bb..5caab91a0 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -12,48 +12,38 @@ let flakeExpr = flake.outputs.nixopsConfigurations.default or { }; - nixpkgsBoot = toString ; # this will be replaced on install by nixops' nixpkgs input - libBoot = import "${nixpkgsBoot}/lib"; + nixpkgsBoot = ; # this will be replaced on install by nixops' nixpkgs input + libOf = nixpkgs: import /${nixpkgs}/lib; + libBoot = libOf nixpkgsBoot; - evalModules = lib: modules: lib.evalModules { + evalMod = lib: mod: lib.evalModules { specialArgs = args // { inherit lib system; }; - modules = modules ++ networkExprs ++ [ - flakeExpr + modules = networkExprs ++ [ + ./net.nix mod flakeExpr { - options.nixpkgs = lib.mkOption { - type = lib.types.path; - description = "Path to the nixpkgs instance used to buld the machines."; - defaultText = lib.literalDocBook "The 'nixpkgs' input to either the provided flake or nixops' own."; - default = flake.inputs.nixpkgs or nixpkgsBoot; - }; + nixpkgs = lib.mkDefault flake.inputs.nixpkgs or nixpkgsBoot; + network.nodeExtraArgs = { inherit uuid deploymentName; }; + defaults.environment.checkConfigurationOptions = lib.mkOverride 900 checkConfigurationOptions; } ]; }; - inherit ((evalModules libBoot [{ - _module.freeformType = with libBoot.types;attrsOf anything; - }]).config) nixpkgs; - + inherit ((evalMod libBoot { _module.check = false; }).config) nixpkgs; pkgs = nixpkgs.legacyPackages.${system} or (import nixpkgs { inherit system; }); - lib = nixpkgs.lib or pkgs.lib or (builtins.tryEval (import "${nixpkgs}/lib")).value or libBoot; + lib = nixpkgs.lib or pkgs.lib or (builtins.tryEval (libOf nixpkgs)).value or libBoot; in rec { inherit nixpkgs; - net = evalModules lib [ - ./net.nix - ({ config, ... }: { - resources.imports = pluginResourceModules ++ [ deploymentInfoModule ]; - network.resourcesDefaults = resourceModuleArgs_ rec{ - inherit (config) nodes resources; - machines = nodes; - }; - network.nodeExtraArgs = { inherit uuid deploymentName; }; - defaults.environment.checkConfigurationOptions = lib.mkOverride 900 checkConfigurationOptions; - # Make NixOps's deployment.* options available. - defaults.imports = pluginOptions ++ [ deploymentInfoModule ]; - }) - ]; + net = evalMod lib ({ config, ... }: { + resources.imports = pluginResourceModules ++ [ deploymentInfoModule ]; + network.resourcesDefaults = resourceModuleArgs_ rec{ + inherit (config) nodes resources; + machines = nodes; + }; + # Make NixOps's deployment.* options available. + defaults.imports = pluginOptions ++ [ deploymentInfoModule ]; + }); # for backward compatibility network = lib.mapAttrs (n: v: [v]) net.config; diff --git a/nix/net.nix b/nix/net.nix index a93c146a7..c1365b1fa 100644 --- a/nix/net.nix +++ b/nix/net.nix @@ -14,6 +14,11 @@ let in { options = { + nixpkgs = lib.mkOption { + type = types.path; + description = "Path to the nixpkgs instance used to buld the machines."; + defaultText = lib.literalDocBook "The 'nixpkgs' input to either the provided flake or nixops' own."; + }; network = { enableRollback = lib.mkEnableOption "network wide rollback"; description = mkOption { From 0ca1faafaa6a5872756b07c105f2df3d8cc2b26d Mon Sep 17 00:00:00 2001 From: paki23 Date: Sat, 4 Feb 2023 22:04:10 +0100 Subject: [PATCH 23/38] net.nix: allow no nodes net --- nix/net.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nix/net.nix b/nix/net.nix index c1365b1fa..b543e9a69 100644 --- a/nix/net.nix +++ b/nix/net.nix @@ -78,7 +78,9 @@ in # Compute the definitions of the machines. nodes = mkOption { description = "The NixOS configurations for the nodes in the network."; - type = types.attrsOf (import "${config.nixpkgs}/nixos/lib/eval-config.nix" { + default = { }; + # on 1st eval nodes is not read and on 2nd lib is taken from config.nixpkgs + type = types.attrsOf (lib.nixosSystem or (import /${config.nixpkgs}/nixos/lib/eval-config.nix) { inherit system lib; specialArgs = { inherit (config) resources; From 38f27a5a4292febc508fbcb5d628bb21d6b67123 Mon Sep 17 00:00:00 2001 From: paki23 Date: Sat, 4 Feb 2023 22:55:37 +0100 Subject: [PATCH 24/38] net.nix: unify source of default hostname --- nix/net.nix | 8 -------- nix/options.nix | 5 ++++- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/nix/net.nix b/nix/net.nix index b543e9a69..30c43e402 100644 --- a/nix/net.nix +++ b/nix/net.nix @@ -91,14 +91,6 @@ in # Make NixOps's deployment.* options available. ./options.nix ./resource.nix - ({ name, ... }: rec{ - _file = ./net.nix; - key = _file; - # Provide a default hostname and deployment target equal - # to the attribute name of the machine in the model. - networking.hostName = lib.mkOverride 900 name; - deployment.targetHost = lib.mkOverride 900 name; - }) ]; }).type; }; diff --git a/nix/options.nix b/nix/options.nix index 1df9b8e18..b5594037a 100644 --- a/nix/options.nix +++ b/nix/options.nix @@ -1,4 +1,4 @@ -{ config, lib, ... }: +{ name, config, lib, ... }: with lib; @@ -167,6 +167,9 @@ in _type = "machine"; + # Provide a default hostname and deployment target equal + # to the attribute name of the machine in the model. + networking.hostName = lib.mkOverride 900 name; deployment.targetHost = mkDefault config.networking.hostName; deployment.targetPort = mkDefault (head config.services.openssh.ports); From 49d5f5ce74910b80e6116a577c4aa4771a6e0d1e Mon Sep 17 00:00:00 2001 From: paki23 Date: Sat, 4 Feb 2023 23:13:00 +0100 Subject: [PATCH 25/38] eval-machine-info: removing problematic resources entries better --- nix/eval-machine-info.nix | 8 +++++--- nix/resource.nix | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index 5caab91a0..a6a2a8de1 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -48,9 +48,6 @@ in rec { # for backward compatibility network = lib.mapAttrs (n: v: [v]) net.config; networks = [ net.config ]; - - # skip problematic resources entries - resources = removeAttrs net.config.resources ["deployment" "_name" "_type"]; defaults = [ net.config.defaults ]; nodes = #TODO: take options and other modules outputs for each node lib.mapAttrs (n: v: { @@ -59,6 +56,11 @@ in rec { inherit (v.nixpkgs) pkgs; }) net.config.nodes; + # ./resource.nix is imported in resource opt but does not define resource types + # we have to remove those entries as they do not otherwise conform to the resource schema + resources = removeAttrs net.config.resources (lib.attrNames (import ./resource.nix { + name = ""; inherit lib; }).options); + importedPluginNixExprs = map import pluginNixExprs; pluginOptions = lib.lists.concatMap (e: e.options) importedPluginNixExprs; pluginResources = map (e: e.resources) importedPluginNixExprs; diff --git a/nix/resource.nix b/nix/resource.nix index 8e04aa98a..ba0e0cc90 100644 --- a/nix/resource.nix +++ b/nix/resource.nix @@ -1,4 +1,4 @@ -{ config, lib, name, ... }: +{ lib, name, ... }: with lib; From 19e74b8edb6a39f556f1cbdb7039c41b9900d5a7 Mon Sep 17 00:00:00 2001 From: paki23 Date: Sat, 4 Feb 2023 23:47:10 +0100 Subject: [PATCH 26/38] simplified resource defaults logic --- nix/eval-machine-info.nix | 53 +++++++++++++-------------------------- nix/net.nix | 1 + 2 files changed, 18 insertions(+), 36 deletions(-) diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index a6a2a8de1..67c9cb877 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -37,9 +37,22 @@ in rec { net = evalMod lib ({ config, ... }: { resources.imports = pluginResourceModules ++ [ deploymentInfoModule ]; - network.resourcesDefaults = resourceModuleArgs_ rec{ - inherit (config) nodes resources; - machines = nodes; + network.resourcesDefaults = { name, ... }: { + imports = [ deploymentInfoModule ]; + _module.args = { + inherit pkgs uuid; + inherit (config) resources; + + # inherit nodes, essentially + nodes = + lib.mapAttrs + (nodeName: node: + lib.mapAttrs + (key: lib.warn "Resource ${name} accesses nodes.${nodeName}.${key}, which is deprecated. Use the equivalent option instead: nodes.${nodeName}.${newOpt key}.") + config.nodes.${nodeName} + // node) + config.nodes; + }; }; # Make NixOps's deployment.* options available. defaults.imports = pluginOptions ++ [ deploymentInfoModule ]; @@ -78,23 +91,12 @@ in rec { inherit uuid; }; - defaultResourceModule.imports = [ - ./resource.nix - resourceModuleArgs - deploymentInfoModule - ]; - pluginResourceModules = lib.lists.concatMap (lib.mapAttrsToList toResourceModule) pluginResourceLegacyReprs; toResourceModule = k: { _type, resourceModule }: { options.${k} = lib.mkOption { - type = lib.types.attrsOf (lib.types.submoduleWith { - modules = [ - defaultResourceModule - resourceModule - ]; - }); + type = lib.types.attrsOf (lib.types.submodule resourceModule); default = { /* no resources configured */ }; }; }; @@ -128,27 +130,6 @@ in rec { corresponding plugin to declare the resource submodule directly instead. ''; - resourceModuleArgs = resourceModuleArgs_ { - inherit nodes resources; - inherit (info) machines; - }; - - resourceModuleArgs_ = { nodes, resources, machines }: { name, ... }: { - _module.args = { - inherit pkgs uuid resources; - - # inherit nodes, essentially - nodes = - lib.mapAttrs - (nodeName: node: - lib.mapAttrs - (key: lib.warn "Resource ${name} accesses nodes.${nodeName}.${key}, which is deprecated. Use the equivalent option instead: nodes.${nodeName}.${newOpt key}.") - machines.${nodeName} - // node) - nodes; - }; - }; - # NOTE: this is a legacy name. It does not invoke the module system, # but rather preserves one argument, so that it can be turned # into a proper submodule later. diff --git a/nix/net.nix b/nix/net.nix index 30c43e402..5020f130b 100644 --- a/nix/net.nix +++ b/nix/net.nix @@ -55,6 +55,7 @@ in default = { }; type = types.attrsOf (types.submoduleWith { modules = [ + ./resource.nix config.network.resourcesDefaults mainModule ]; From 736d837f4d4197a85929edcc053d1706bd5e9804 Mon Sep 17 00:00:00 2001 From: paki23 Date: Sun, 5 Feb 2023 00:09:28 +0100 Subject: [PATCH 27/38] clarified logic defaultDeploymentModule --- nix/default-deployment.nix | 26 ++++++++++++++++++++++++++ nix/eval-machine-info.nix | 23 +++++++++++------------ nix/net.nix | 12 +++++++++--- nix/resource.nix | 21 --------------------- 4 files changed, 46 insertions(+), 36 deletions(-) create mode 100644 nix/default-deployment.nix diff --git a/nix/default-deployment.nix b/nix/default-deployment.nix new file mode 100644 index 000000000..732299663 --- /dev/null +++ b/nix/default-deployment.nix @@ -0,0 +1,26 @@ +{ lib, ... }: let + inherit (lib) mkOption types; +in { + options.deployment = { + + name = mkOption { + type = types.str; + description = '' + The name of the NixOps deployment. This is set by NixOps. + ''; + }; + + uuid = mkOption { + type = types.str; + description = '' + The UUID of the NixOps deployment. This is set by NixOps. + ''; + }; + + arguments = mkOption { + description = '' + Attribute set representing the NixOps arguments. This is set by NixOps. + ''; + }; + }; +} \ No newline at end of file diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index 67c9cb877..0b544b2ba 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -21,6 +21,12 @@ let modules = networkExprs ++ [ ./net.nix mod flakeExpr { + # Make NixOps's deployment.* options available. + deployment = { + name = deploymentName; + arguments = args; + inherit uuid; + }; nixpkgs = lib.mkDefault flake.inputs.nixpkgs or nixpkgsBoot; network.nodeExtraArgs = { inherit uuid deploymentName; }; defaults.environment.checkConfigurationOptions = lib.mkOverride 900 checkConfigurationOptions; @@ -36,9 +42,8 @@ in rec { inherit nixpkgs; net = evalMod lib ({ config, ... }: { - resources.imports = pluginResourceModules ++ [ deploymentInfoModule ]; + resources.imports = pluginResourceModules; network.resourcesDefaults = { name, ... }: { - imports = [ deploymentInfoModule ]; _module.args = { inherit pkgs uuid; inherit (config) resources; @@ -54,8 +59,7 @@ in rec { config.nodes; }; }; - # Make NixOps's deployment.* options available. - defaults.imports = pluginOptions ++ [ deploymentInfoModule ]; + defaults.imports = pluginOptions; }); # for backward compatibility @@ -71,8 +75,9 @@ in rec { # ./resource.nix is imported in resource opt but does not define resource types # we have to remove those entries as they do not otherwise conform to the resource schema - resources = removeAttrs net.config.resources (lib.attrNames (import ./resource.nix { - name = ""; inherit lib; }).options); + resources = removeAttrs net.config.resources (lib.concatMap + (e: lib.attrNames (import e { name = ""; inherit lib; }).options) + [ ./resource.nix ./default-deployment.nix ]); importedPluginNixExprs = map import pluginNixExprs; pluginOptions = lib.lists.concatMap (e: e.options) importedPluginNixExprs; @@ -85,12 +90,6 @@ in rec { # Compute the definitions of the non-machine resources. resourcesByType = lib.zipAttrs (network.resources or []); - deploymentInfoModule.deployment = { - name = deploymentName; - arguments = args; - inherit uuid; - }; - pluginResourceModules = lib.lists.concatMap (lib.mapAttrsToList toResourceModule) pluginResourceLegacyReprs; toResourceModule = k: { _type, resourceModule }: diff --git a/nix/net.nix b/nix/net.nix index 5020f130b..8597a79e0 100644 --- a/nix/net.nix +++ b/nix/net.nix @@ -11,8 +11,14 @@ let n; options = throw "nodes..options is not available anymore. You can access options information by writing a node-level module that extracts the options information and assigns it to a new option of your choosing."; }; + + deploymentDefault = { + imports = [ ./resource.nix ./default-deployment.nix ]; + inherit (config) deployment; + }; in { + imports = [ ./default-deployment.nix ]; options = { nixpkgs = lib.mkOption { type = types.path; @@ -55,7 +61,7 @@ in default = { }; type = types.attrsOf (types.submoduleWith { modules = [ - ./resource.nix + deploymentDefault config.network.resourcesDefaults mainModule ]; @@ -63,7 +69,7 @@ in }; }; modules = [ - ./resource.nix + deploymentDefault ({ defineResource, ... }: { imports = [ (defineResource "sshKeyPairs" ./ssh-keypair.nix) @@ -91,7 +97,7 @@ in config.defaults # Make NixOps's deployment.* options available. ./options.nix - ./resource.nix + deploymentDefault ]; }).type; }; diff --git a/nix/resource.nix b/nix/resource.nix index ba0e0cc90..2063899d7 100644 --- a/nix/resource.nix +++ b/nix/resource.nix @@ -19,27 +19,6 @@ with lib; visible = false; description = "Type of the resource."; }; - - deployment.name = mkOption { - type = types.str; - description = '' - The name of the NixOps deployment. This is set by NixOps. - ''; - }; - - deployment.uuid = mkOption { - type = types.str; - description = '' - The UUID of the NixOps deployment. This is set by NixOps. - ''; - }; - - deployment.arguments = mkOption { - description = '' - Attribute set representing the NixOps arguments. This is set by NixOps. - ''; - }; - }; } From 7b755c71196814d6493050b1c3dd421b16c37d08 Mon Sep 17 00:00:00 2001 From: paki23 Date: Sun, 5 Feb 2023 00:24:04 +0100 Subject: [PATCH 28/38] moving resource defaults in net.nix --- nix/eval-machine-info.nix | 27 +++------------------------ nix/net.nix | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index 0b544b2ba..642a53cda 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -40,27 +40,11 @@ let in rec { inherit nixpkgs; - - net = evalMod lib ({ config, ... }: { + net = evalMod lib { resources.imports = pluginResourceModules; - network.resourcesDefaults = { name, ... }: { - _module.args = { - inherit pkgs uuid; - inherit (config) resources; - - # inherit nodes, essentially - nodes = - lib.mapAttrs - (nodeName: node: - lib.mapAttrs - (key: lib.warn "Resource ${name} accesses nodes.${nodeName}.${key}, which is deprecated. Use the equivalent option instead: nodes.${nodeName}.${newOpt key}.") - config.nodes.${nodeName} - // node) - config.nodes; - }; - }; + network.resourcesDefaults._module.args = { inherit pkgs uuid; }; defaults.imports = pluginOptions; - }); + }; # for backward compatibility network = lib.mapAttrs (n: v: [v]) net.config; @@ -137,11 +121,6 @@ in rec { inherit resourceModule; }; - newOpt = key: { - nixosRelease = "config.system.nixos.release and make sure it is set properly"; - publicIPv4 = "config.networking.publicIPv4"; - }.${key} or "config.deployment.${key}"; - # check if there are duplicate elements in a sorted list noDups = l: if lib.length l > 1 diff --git a/nix/net.nix b/nix/net.nix index 8597a79e0..768feeee7 100644 --- a/nix/net.nix +++ b/nix/net.nix @@ -64,6 +64,23 @@ in deploymentDefault config.network.resourcesDefaults mainModule + ({ name, ... }: { + _module.args = { + inherit (config) resources; + # inherit nodes, essentially + nodes = + lib.mapAttrs + (nodeName: node: + lib.mapAttrs + (key: lib.warn "Resource ${name} accesses nodes.${nodeName}.${key}, which is deprecated. Use the equivalent option instead: nodes.${nodeName}.${{ + nixosRelease = "config.system.nixos.release and make sure it is set properly"; + publicIPv4 = "config.networking.publicIPv4"; + }.${key} or "config.deployment.${key}"}.") + config.nodes.${nodeName} + // node) + config.nodes; + }; + }) ]; }); }; From f72d03adcae17a676f96f5fefca3a844af876b33 Mon Sep 17 00:00:00 2001 From: paki23 Date: Sun, 5 Feb 2023 01:20:07 +0100 Subject: [PATCH 29/38] Fix typo --- nix/net.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/net.nix b/nix/net.nix index 768feeee7..428ad0abb 100644 --- a/nix/net.nix +++ b/nix/net.nix @@ -22,7 +22,7 @@ in options = { nixpkgs = lib.mkOption { type = types.path; - description = "Path to the nixpkgs instance used to buld the machines."; + description = "Path to the nixpkgs instance used to build the machines."; defaultText = lib.literalDocBook "The 'nixpkgs' input to either the provided flake or nixops' own."; }; network = { From 9c9423e4000bf10d24e52c1ed69acfb735753bae Mon Sep 17 00:00:00 2001 From: paki23 Date: Sun, 5 Feb 2023 02:30:21 +0100 Subject: [PATCH 30/38] net.nix: shorten defineResource definition --- nix/net.nix | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/nix/net.nix b/nix/net.nix index 428ad0abb..d6b6bf5ad 100644 --- a/nix/net.nix +++ b/nix/net.nix @@ -56,33 +56,30 @@ in resources = mkOption { default = { }; type = types.submoduleWith { - specialArgs.defineResource = name: mainModule: { - options.${name} = mkOption { + specialArgs.defineResource = resName: resMod: { + options.${resName} = mkOption { default = { }; - type = types.attrsOf (types.submoduleWith { - modules = [ + type = types.attrsOf (types.submodule ({ name, ... }: { + imports=[ deploymentDefault config.network.resourcesDefaults - mainModule - ({ name, ... }: { - _module.args = { - inherit (config) resources; - # inherit nodes, essentially - nodes = - lib.mapAttrs - (nodeName: node: - lib.mapAttrs - (key: lib.warn "Resource ${name} accesses nodes.${nodeName}.${key}, which is deprecated. Use the equivalent option instead: nodes.${nodeName}.${{ - nixosRelease = "config.system.nixos.release and make sure it is set properly"; - publicIPv4 = "config.networking.publicIPv4"; - }.${key} or "config.deployment.${key}"}.") - config.nodes.${nodeName} - // node) - config.nodes; - }; - }) + resMod ]; - }); + _module.args = { + inherit (config) resources; + nodes = # inherit nodes, essentially + lib.mapAttrs + (nodeName: node: + lib.mapAttrs + (key: lib.warn "Resource ${name} accesses nodes.${nodeName}.${key}, which is deprecated. Use the equivalent option instead: nodes.${nodeName}.${{ + nixosRelease = "config.system.nixos.release and make sure it is set properly"; + publicIPv4 = "config.networking.publicIPv4"; + }.${key} or "config.deployment.${key}"}.") + config.nodes.${nodeName} + // node) + config.nodes; + }; + })); }; }; modules = [ From c796a68a44682a0d01d6c17c5951978d202fac55 Mon Sep 17 00:00:00 2001 From: paki23 Date: Sun, 5 Feb 2023 14:55:37 +0100 Subject: [PATCH 31/38] eval-machines:inportedOptions eval earlier --- nix/eval-machine-info.nix | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index 642a53cda..072a96ac5 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -10,6 +10,7 @@ }: let + importedPluginNixExprs = map import pluginNixExprs; flakeExpr = flake.outputs.nixopsConfigurations.default or { }; nixpkgsBoot = ; # this will be replaced on install by nixops' nixpkgs input @@ -21,15 +22,18 @@ let modules = networkExprs ++ [ ./net.nix mod flakeExpr { + nixpkgs = lib.mkDefault flake.inputs.nixpkgs or nixpkgsBoot; + network.nodeExtraArgs = { inherit uuid deploymentName; }; # Make NixOps's deployment.* options available. deployment = { name = deploymentName; arguments = args; inherit uuid; }; - nixpkgs = lib.mkDefault flake.inputs.nixpkgs or nixpkgsBoot; - network.nodeExtraArgs = { inherit uuid deploymentName; }; - defaults.environment.checkConfigurationOptions = lib.mkOverride 900 checkConfigurationOptions; + defaults = { + imports = lib.lists.concatMap (e: e.options) importedPluginNixExprs; + environment.checkConfigurationOptions = lib.mkOverride 900 checkConfigurationOptions; + }; } ]; }; @@ -43,7 +47,6 @@ in rec { net = evalMod lib { resources.imports = pluginResourceModules; network.resourcesDefaults._module.args = { inherit pkgs uuid; }; - defaults.imports = pluginOptions; }; # for backward compatibility @@ -63,8 +66,6 @@ in rec { (e: lib.attrNames (import e { name = ""; inherit lib; }).options) [ ./resource.nix ./default-deployment.nix ]); - importedPluginNixExprs = map import pluginNixExprs; - pluginOptions = lib.lists.concatMap (e: e.options) importedPluginNixExprs; pluginResources = map (e: e.resources) importedPluginNixExprs; pluginDeploymentConfigExporters = lib.lists.concatMap (e: e.config_exporters { inherit pkgs; From b3a578b78b7283393d9e1edbe69fc8453c021e22 Mon Sep 17 00:00:00 2001 From: paki23 Date: Sun, 5 Feb 2023 21:52:31 +0100 Subject: [PATCH 32/38] eval-machine-info: rm unused bindings --- nix/eval-machine-info.nix | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index 072a96ac5..bae938149 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -136,7 +136,7 @@ in rec { let network' = network; resources' = resources; - in rec { + in { machines = lib.flip lib.mapAttrs nodes (n: v': let v = lib.scrubOptionValue v'; in @@ -169,31 +169,7 @@ in rec { [ "nixpkgs" "resourcesDefaults" "nodesExtraArgs" ] # Not serialisable ; - resources = - let - resource_referenced = list: check: recurse: - lib.any lib.id (map (value: (check value) || - ((lib.isAttrs value) && (!(value ? _type) || recurse) - && (resource_referenced (lib.attrValues value) check false))) - list); - - flatten_resources = resources: lib.flatten ( map lib.attrValues (lib.attrValues resources) ); - - resource_used = res_set: resource: - resource_referenced - (flatten_resources res_set) - (value: value == resource ) - true; - - resources_without_defaults = res_class: defaults: res_set: - let - missing = lib.filter (res: !(resource_used (removeAttrs res_set [res_class]) - res_set."${res_class}"."${res}")) - (lib.attrNames defaults); - in - res_set // { "${res_class}" = ( removeAttrs res_set."${res_class}" missing ); }; - - in (removeAttrs resources' [ "machines" ]); + resources = (removeAttrs resources' [ "machines" ]); }; From 5f5b25b11ed5f3ca59de32941e72d29732b70594 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 1 Mar 2023 14:23:11 +0100 Subject: [PATCH 33/38] eval-machine-info: Fix typo --- nix/eval-machine-info.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index bae938149..4d08ad2a3 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -23,7 +23,7 @@ let ./net.nix mod flakeExpr { nixpkgs = lib.mkDefault flake.inputs.nixpkgs or nixpkgsBoot; - network.nodeExtraArgs = { inherit uuid deploymentName; }; + network.nodesExtraArgs = { inherit uuid deploymentName; }; # Make NixOps's deployment.* options available. deployment = { name = deploymentName; From 553fa6379363467a6be05ee8c95a2090d1adf4cc Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 1 Mar 2023 14:23:58 +0100 Subject: [PATCH 34/38] eval-machine-info: Add resource.nix to legacy resources --- nix/eval-machine-info.nix | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index 4d08ad2a3..1473ca8c0 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -80,7 +80,12 @@ in rec { toResourceModule = k: { _type, resourceModule }: { options.${k} = lib.mkOption { - type = lib.types.attrsOf (lib.types.submodule resourceModule); + type = lib.types.attrsOf (lib.types.submoduleWith { + specialArgs = { + inherit resources uuid nodes; + }; + modules = [ resourceModule ./resource.nix ]; + }); default = { /* no resources configured */ }; }; }; From 8fd2cff50cecefc917d0052a5d3268b1f6ab64ea Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 1 Mar 2023 14:26:18 +0100 Subject: [PATCH 35/38] net.nix: Add placeholder for network.lock --- nix/machine-resource.nix | 5 ++++- nix/net.nix | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/nix/machine-resource.nix b/nix/machine-resource.nix index 82a45a929..1a16198d0 100644 --- a/nix/machine-resource.nix +++ b/nix/machine-resource.nix @@ -6,7 +6,10 @@ with lib; { - freeformType = lib.types.raw or lib.types.unspecified; + # A freeformType is probably not helpful because it may traverse into a + # machine config, triggering errors in attributes that should never be accessed, + # which results in very obscure errors. + # freeformType = lib.types.raw or lib.types.unspecified; options = { }; diff --git a/nix/net.nix b/nix/net.nix index d6b6bf5ad..1ce5eb1bd 100644 --- a/nix/net.nix +++ b/nix/net.nix @@ -52,6 +52,11 @@ in Extra configurations to add to all resources. ''; }; + lock = mkOption { + # TBD + type = types.raw; + default = {}; + }; }; resources = mkOption { default = { }; From b3c793c15747221c2f84a540695849a0a8d9a4a1 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 1 Mar 2023 14:29:09 +0100 Subject: [PATCH 36/38] net.nix: Turn resources.machines into an alias for the nodes --- nix/net.nix | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/nix/net.nix b/nix/net.nix index 1ce5eb1bd..e11757a14 100644 --- a/nix/net.nix +++ b/nix/net.nix @@ -93,10 +93,18 @@ in imports = [ (defineResource "sshKeyPairs" ./ssh-keypair.nix) (defineResource "commandOutput" ./command-output.nix) - (defineResource "machines" ./machine-resource.nix) ]; - machines = config.nodes; - _module.check = false; + options.machines = lib.mkOption { + description = '' + An alias for the `nodes`. + ''; + readOnly = true; + type = types.raw; + }; + config = { + machines = config.nodes; + _module.check = false; + }; }) ]; }; From 891724ace55bd71ed73354738e9d87993726ddc5 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Wed, 1 Mar 2023 14:32:08 +0100 Subject: [PATCH 37/38] net.nix: Add TODO to consider for improving error messages --- nix/net.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/nix/net.nix b/nix/net.nix index e11757a14..6a1a99129 100644 --- a/nix/net.nix +++ b/nix/net.nix @@ -147,6 +147,13 @@ in warnings = [ "Please use nodes.${name} option instead of assigning machines to the config's top level" ]; }) nodes); + + # Provides compatibility for old style node definitions outside in the root, + # outside the `nodes` option. + # TODO: interpreting arbitrary _mistaken_ configs as machines leads to + # obscure errors, so we should consider removing this backcompat + # solution, or perhaps eagerly throw an appropriate error as soon as + # we encounter an unknown key. The warning may not be encountered. _module.freeformType = types.attrsOf deferredModule; }; } From 12f87a4e9302585d8a1e2dfeb17c4acd12eceaaa Mon Sep 17 00:00:00 2001 From: paki23 Date: Sun, 19 Mar 2023 16:31:59 +0100 Subject: [PATCH 38/38] net.nix: removed nodes options, all network nodes are now defined in resources.machines --- doc/guides/deploy-without-root.rst | 2 +- doc/manual/nixops.rst | 2 +- doc/manual/overview.rst | 14 ++--- doc/overview.rst | 14 ++--- doc/release-notes/index.rst | 2 +- nix/eval-machine-info.nix | 14 ++--- nix/machine-resource.nix | 16 ------ nix/net.nix | 86 +++++++++++------------------- nix/options.nix | 21 ++------ 9 files changed, 59 insertions(+), 112 deletions(-) delete mode 100644 nix/machine-resource.nix diff --git a/doc/guides/deploy-without-root.rst b/doc/guides/deploy-without-root.rst index 73eecc554..38e710418 100644 --- a/doc/guides/deploy-without-root.rst +++ b/doc/guides/deploy-without-root.rst @@ -69,7 +69,7 @@ Edit your nixops.nix to specify the machine's { network.description = "Non-root deployment"; - nodes.hermes = + resources.machines.hermes = { resources, ... }: { deployment.targetUser = "deployer"; diff --git a/doc/manual/nixops.rst b/doc/manual/nixops.rst index caa946edc..21400d3c5 100644 --- a/doc/manual/nixops.rst +++ b/doc/manual/nixops.rst @@ -1080,7 +1080,7 @@ Consider the following deployment specification (``servers.nix``): services.httpd.adminAddr = "foo@example.org"; }); - in { nodes = listToAttrs (map makeMachine (range 1 nrMachines)); } + in { resources.machines = listToAttrs (map makeMachine (range 1 nrMachines)); } This specifies a network of nrMachines identical VirtualBox VMs that run the Apache web server if active is set. To create 10 machines without diff --git a/doc/manual/overview.rst b/doc/manual/overview.rst index 7617242c1..955e6e8be 100644 --- a/doc/manual/overview.rst +++ b/doc/manual/overview.rst @@ -18,7 +18,7 @@ and leave ``deployment.targetEnv`` undefined. See :: { - nodes.webserver = + resources.machines.webserver = { config, pkgs, ... }: { deployment.targetHost = "1.2.3.4"; }; @@ -87,12 +87,12 @@ example: imports = [ ./common.nix ]; }; - nodes.machine = { ... }: {}; + resources.machines.machine = { ... }: {}; } Each attribute is explained below: -``nodes.*`` +``resources.machines.*`` Applies the given NixOS configuration to the corresponding node. ``defaults`` @@ -121,7 +121,7 @@ Here is an example of a network with network arguments: { maintenance ? false }: { - nodes.machine = + resources.machines.machine = { config, pkgs, ... }: { services.httpd.enable = maintenance; ... @@ -175,7 +175,7 @@ Add a key to a machine like so. :: { - nodes.machine = + resources.machines.machine = { config, pkgs, ... }: { deployment.keys.my-secret.text = "shhh this is a secret"; @@ -211,7 +211,7 @@ and otherwise inactive when the key is absent. See :: { - nodes.machine = + resources.machines.machine = { config, pkgs, ... }: { deployment.keys.my-secret.text = "shhh this is a secret"; @@ -246,7 +246,7 @@ This is possible by using the extra NixOS module input ``nodes``. { network.description = "Gollum server and reverse proxy"; - nodes = { + resources.machines = { gollum = { config, pkgs, ... }: diff --git a/doc/overview.rst b/doc/overview.rst index 435503edd..26bc2d4f4 100644 --- a/doc/overview.rst +++ b/doc/overview.rst @@ -21,7 +21,7 @@ machine, and leave ``deployment.targetEnv`` undefined. See :: { - nodes.webserver = + resources.machines.webserver = { config, pkgs, ... }: { deployment.targetHost = "1.2.3.4"; }; @@ -92,7 +92,7 @@ example: imports = [ ./common.nix ]; }; - nodes.machine = { ... }: {}; + resources.machines.machine = { ... }: {}; } Each attribute is explained below: @@ -122,7 +122,7 @@ Here is an example of a network with network arguments: { maintenance ? false }: { - nodes.machine = + resources.machines.machine = { config, pkgs, ... }: { services.httpd.enable = maintenance; ... @@ -175,7 +175,7 @@ Add a key to a machine like so. :: { - nodes.machine = + resources.machines.machine = { config, pkgs, ... }: { deployment.keys.my-secret.text = "shhh this is a secret"; @@ -216,7 +216,7 @@ and otherwise inactive when the key is absent. See :: { - nodes.machine = + resources.machines.machine = { config, pkgs, ... }: { deployment.keys.my-secret.text = "shhh this is a secret"; @@ -250,8 +250,8 @@ This is possible by using the extra NixOS module input ``nodes``. { network.description = "Gollum server and reverse proxy"; - - nodes = { + + resources.machines = { gollum = { config, pkgs, ... }: { diff --git a/doc/release-notes/index.rst b/doc/release-notes/index.rst index 0d3a35ba4..c2e66793c 100644 --- a/doc/release-notes/index.rst +++ b/doc/release-notes/index.rst @@ -18,7 +18,7 @@ Release 2.0 - Now the network specification is using the module system from ``nixpkgs.lib`` - Now network specification files can import other files via ``imports``. - - We have a ``nodes.*`` option where we put every NixOS configuration for the configured nodes. We suggest to use it instead of defining nodes in the top level. + - We have a ``resources.machines.*`` option where we put every NixOS configuration for the configured nodes. We suggest to use it instead of defining nodes in the top level. - Removed NixOS Options diff --git a/nix/eval-machine-info.nix b/nix/eval-machine-info.nix index 1473ca8c0..bfb13d952 100644 --- a/nix/eval-machine-info.nix +++ b/nix/eval-machine-info.nix @@ -23,7 +23,7 @@ let ./net.nix mod flakeExpr { nixpkgs = lib.mkDefault flake.inputs.nixpkgs or nixpkgsBoot; - network.nodesExtraArgs = { inherit uuid deploymentName; }; + network.nodesExtraArgs = { inherit deploymentName; }; # Make NixOps's deployment.* options available. deployment = { name = deploymentName; @@ -46,19 +46,21 @@ in rec { inherit nixpkgs; net = evalMod lib { resources.imports = pluginResourceModules; - network.resourcesDefaults._module.args = { inherit pkgs uuid; }; + network.resourcesDefaults._module.args.pkgs = lib.mkOptionDefault pkgs; }; # for backward compatibility - network = lib.mapAttrs (n: v: [v]) net.config; + network = lib.mapAttrs (n: v: [ v ]) net.config; networks = [ net.config ]; defaults = [ net.config.defaults ]; nodes = #TODO: take options and other modules outputs for each node - lib.mapAttrs (n: v: { + lib.mapAttrs + (n: v: { config = v; - options = net.options.nodes.${n}; + options = net.options.resources.machines.${n}; inherit (v.nixpkgs) pkgs; - }) net.config.nodes; + }) + net.config.resources.machines; # ./resource.nix is imported in resource opt but does not define resource types # we have to remove those entries as they do not otherwise conform to the resource schema diff --git a/nix/machine-resource.nix b/nix/machine-resource.nix deleted file mode 100644 index 1a16198d0..000000000 --- a/nix/machine-resource.nix +++ /dev/null @@ -1,16 +0,0 @@ - -# Machine resource - -{ config, lib, uuid, name, ... }: - -with lib; - -{ - # A freeformType is probably not helpful because it may traverse into a - # machine config, triggering errors in attributes that should never be accessed, - # which results in very obscure errors. - # freeformType = lib.types.raw or lib.types.unspecified; - options = { - - }; -} diff --git a/nix/net.nix b/nix/net.nix index 6a1a99129..8c70d3bfb 100644 --- a/nix/net.nix +++ b/nix/net.nix @@ -3,15 +3,6 @@ let inherit (lib) mkOption types mapAttrs warn; inherit (types) deferredModule; - nodesConfigCompat = k: n: - n // { - config = - warn - "The module parameter `nodes.${lib.strings.escapeNixIdentifier k}.config' has been renamed to `nodes.${lib.strings.escapeNixIdentifier k}'" - n; - options = throw "nodes..options is not available anymore. You can access options information by writing a node-level module that extracts the options information and assigns it to a new option of your choosing."; - }; - deploymentDefault = { imports = [ ./resource.nix ./default-deployment.nix ]; inherit (config) deployment; @@ -55,7 +46,7 @@ in lock = mkOption { # TBD type = types.raw; - default = {}; + default = { }; }; }; resources = mkOption { @@ -64,27 +55,30 @@ in specialArgs.defineResource = resName: resMod: { options.${resName} = mkOption { default = { }; - type = types.attrsOf (types.submodule ({ name, ... }: { - imports=[ + type = types.attrsOf (types.submoduleWith { + specialArgs = { + inherit (config) resources; + inherit (config.deployment) uuid; + }; + modules = [ deploymentDefault config.network.resourcesDefaults resMod - ]; - _module.args = { - inherit (config) resources; - nodes = # inherit nodes, essentially - lib.mapAttrs - (nodeName: node: - lib.mapAttrs - (key: lib.warn "Resource ${name} accesses nodes.${nodeName}.${key}, which is deprecated. Use the equivalent option instead: nodes.${nodeName}.${{ + ({ name, ... }: { + _module.args.nodes = # inherit nodes, essentially + lib.mapAttrs + (nodeName: node: + lib.mapAttrs + (key: lib.warn "Resource ${name} accesses nodes.${nodeName}.${key}, which is deprecated. Use the equivalent option instead: nodes.${nodeName}.${{ nixosRelease = "config.system.nixos.release and make sure it is set properly"; publicIPv4 = "config.networking.publicIPv4"; }.${key} or "config.deployment.${key}"}.") - config.nodes.${nodeName} - // node) - config.nodes; - }; - })); + config.resources.machines.${nodeName} + // node) + config.resources.machines; + }) + ]; + }); }; }; modules = [ @@ -93,41 +87,23 @@ in imports = [ (defineResource "sshKeyPairs" ./ssh-keypair.nix) (defineResource "commandOutput" ./command-output.nix) + (defineResource "machines" ./options.nix) ]; - options.machines = lib.mkOption { - description = '' - An alias for the `nodes`. - ''; - readOnly = true; - type = types.raw; - }; - config = { - machines = config.nodes; - _module.check = false; + # Compute the definitions of the machines. + options.machines = mkOption { + description = "The NixOS configurations for the nodes in the network."; + # on 1st eval nodes is not read and on 2nd lib is taken from config.nixpkgs + type = types.attrsOf (lib.nixosSystem or (import /${config.nixpkgs}/nixos/lib/eval-config.nix) { + inherit system lib; + specialArgs = config.network.nodesExtraArgs; + modules = [ config.defaults { _module.check = true; } ]; + }).type; }; + config._module.check = false; }) ]; }; }; - # Compute the definitions of the machines. - nodes = mkOption { - description = "The NixOS configurations for the nodes in the network."; - default = { }; - # on 1st eval nodes is not read and on 2nd lib is taken from config.nixpkgs - type = types.attrsOf (lib.nixosSystem or (import /${config.nixpkgs}/nixos/lib/eval-config.nix) { - inherit system lib; - specialArgs = { - inherit (config) resources; - nodes = mapAttrs nodesConfigCompat config.nodes; - } // config.network.nodesExtraArgs; - modules = [ - config.defaults - # Make NixOps's deployment.* options available. - ./options.nix - deploymentDefault - ]; - }).type; - }; defaults = mkOption { type = deferredModule; default = { }; @@ -137,7 +113,7 @@ in }; }; config = { - nodes = + resources.machines = let nodes = removeAttrs config (builtins.attrNames options); in diff --git a/nix/options.nix b/nix/options.nix index b5594037a..4adfadd6d 100644 --- a/nix/options.nix +++ b/nix/options.nix @@ -1,23 +1,8 @@ { name, config, lib, ... }: - with lib; - -let - - cfg = config.deployment; - -in - { - - imports = - [ - ./keys.nix - ]; - - + imports = [ ./keys.nix ]; options = { - deployment.targetEnv = mkOption { default = "none"; example = "ec2"; @@ -74,7 +59,7 @@ in deployment.sshOptions = mkOption { type = types.listOf types.str; - default = []; + default = [ ]; description = '' Extra options passed to the OpenSSH client verbatim, and are not executed by a shell. ''; @@ -109,7 +94,7 @@ in }; deployment.owners = mkOption { - default = []; + default = [ ]; type = types.listOf types.str; description = '' List of email addresses of the owners of the machines. Used