fix compatibility with nixos-containers

This commit is contained in:
Niklas Gollenstede 2023-07-05 14:55:58 +02:00
parent 1a47c3fa75
commit 192dd6f179
2 changed files with 21 additions and 17 deletions

View File

@ -24,19 +24,19 @@ in rec {
mainModule, name, mainModule, name,
# See »mkSystemsFlake« for documentation of the following arguments: # See »mkSystemsFlake« for documentation of the following arguments:
inputs ? { }, modules ? (getModulesFromInputs inputs), overlays ? (getOverlaysFromInputs inputs), inputs ? { }, modules ? (getModulesFromInputs inputs), overlays ? (getOverlaysFromInputs inputs),
extraModules ? [ ], moduleArgs ? { }, extraModules ? [ ], moduleArgs ? { }, nixosArgs ? { },
nixosSystem ? inputs.nixpkgs.lib.nixosSystem, nixosSystem ? inputs.nixpkgs.lib.nixosSystem,
buildPlatform ? null, buildPlatform ? null,
}: nixosSystem { }: nixosSystem (nixosArgs // {
#system = null; # (This actually does nothing more than setting »config.nixpkgs.system« (which is the same as »config.nixpkgs.buildPlatform.system«) and can be null/unset here.) #system = null; # (This actually does nothing more than setting »config.nixpkgs.system« (which is the same as »config.nixpkgs.buildPlatform.system«) and can be null/unset here.)
modules = [ { imports = [ # Anything specific to only this evaluation of the module tree should go here. modules = (nixosArgs.modules or [ ]) ++ [ { imports = [ # Anything specific to only this evaluation of the module tree should go here.
(if (builtins.isPath mainModule) || (builtins.isString mainModule) then (importWrapped inputs mainModule).module else mainModule) (if (builtins.isPath mainModule) || (builtins.isString mainModule) then (importWrapped inputs mainModule).module else mainModule)
{ _module.args.name = lib.mkOverride 99 name; } # (specialisations can somehow end up with the name »configuration«, which is very incorrect) { _module.args.name = lib.mkOverride 99 name; } # (specialisations can somehow end up with the name »configuration«, which is very incorrect)
{ networking.hostName = name; } { networking.hostName = name; }
]; _file = "${dirname}/nixos.nix#modules"; } ]; ]; _file = "${dirname}/nixos.nix#modules"; } ];
extraModules = modules ++ extraModules ++ [ ({ config, ... }: { imports = [ ({ extraModules = (nixosArgs.extraModules or [ ]) ++ modules ++ extraModules ++ [ ({ config, ... }: { imports = [ ({
# These are passed as »extraModules« module argument and can thus be reused when defining containers and such (so define as much stuff as possible here). # These are passed as »extraModules« module argument and can thus be reused when defining containers and such (so define as much stuff as possible here).
# There is, unfortunately, no way to directly pass modules into all containers. Each container will need to be defined with »config.containers."${name}".config.imports = extraModules«. # There is, unfortunately, no way to directly pass modules into all containers. Each container will need to be defined with »config.containers."${name}".config.imports = extraModules«.
# (One could do that automatically by defining »options.security.containers = lib.mkOption { type = lib.types.submodule (cfg: { options.config = lib.mkOption { apply = _:_.extendModules { modules = extraModules; }; }); }«.) # (One could do that automatically by defining »options.security.containers = lib.mkOption { type = lib.types.submodule (cfg: { options.config = lib.mkOption { apply = _:_.extendModules { modules = extraModules; }; }); }«.)
@ -49,10 +49,10 @@ in rec {
}) ]; _file = "${dirname}/nixos.nix#mkNixosConfiguration-extraModule"; }) ]; }) ]; _file = "${dirname}/nixos.nix#mkNixosConfiguration-extraModule"; }) ];
specialArgs = { inherit inputs; }; specialArgs = (nixosArgs.specialArgs or { }) // { inherit inputs; };
# (This is already set during module import, while »_module.args« only becomes available during module evaluation (before that, using it causes infinite recursion). Since it can't be ensured that this is set in every circumstance where »extraModules« are being used, it should generally not be used to set custom arguments.) # (This is already set during module import, while »_module.args« only becomes available during module evaluation (before that, using it causes infinite recursion). Since it can't be ensured that this is set in every circumstance where »extraModules« are being used, it should generally not be used to set custom arguments.)
}; });
# Given either a list (or attr set) of »files« (paths to ».nix« or ».nix.md« files for dirs with »default.nix« files in them) or a »dir« path (and optionally a list of base names to »exclude« from it), this builds the NixOS configuration for each host (per file) in the context of all configs provided. # Given either a list (or attr set) of »files« (paths to ».nix« or ».nix.md« files for dirs with »default.nix« files in them) or a »dir« path (and optionally a list of base names to »exclude« from it), this builds the NixOS configuration for each host (per file) in the context of all configs provided.
# If »files« is an attr set, exactly one host with the attribute's name as hostname is built for each attribute. Otherwise the default is to build for one host per configuration file, named as the file name without extension or the sub-directory name. Setting »${preface'}.instances« can override this to build the same configuration for those multiple names instead (the specific »name« is passed as additional »moduleArgs« to the modules and can thus be used to adjust the config per instance). # If »files« is an attr set, exactly one host with the attribute's name as hostname is built for each attribute. Otherwise the default is to build for one host per configuration file, named as the file name without extension or the sub-directory name. Setting »${preface'}.instances« can override this to build the same configuration for those multiple names instead (the specific »name« is passed as additional »moduleArgs« to the modules and can thus be used to adjust the config per instance).
@ -67,14 +67,17 @@ in rec {
configs = mapMergeUnique (prelimName: mainModule: (let configs = mapMergeUnique (prelimName: mainModule: (let
instances = let instances = let
preface = getPreface inputs moduleArgs mainModule null; # (we don't yet know the final name) preface = getPreface inputs (moduleArgs // { inherit preface; }) mainModule null; # (we don't yet know the final name)
in if !(args?files && builtins.isAttrs files) && preface?instances then preface.instances else [ prelimName ]; in if !(args?files && builtins.isAttrs files) && preface?instances then preface.instances else [ prelimName ];
in (mapMergeUnique (name: { "${name}" = let in (mapMergeUnique (name: { "${name}" = let
preface = getPreface inputs moduleArgs mainModule name; # (call again, with name) preface = getPreface inputs (moduleArgs // { inherit preface; }) mainModule name; # (call again, with name)
in { inherit preface; } // (mkNixosConfiguration (( in { inherit preface; } // (mkNixosConfiguration ((
builtins.removeAttrs args [ "files" "dir" "exclude" ] builtins.removeAttrs args [ "files" "dir" "exclude" ]
) // { ) // {
inherit name mainModule moduleArgs; extraModules = (args.extraModules or [ ]) ++ [ { imports = [ ({ inherit name mainModule;
moduleArgs = (moduleArgs // { inherit preface; });
nixosArgs = (args.nixosArgs or { }) // { specialArgs = (args.nixosArgs.specialArgs or { }) // { inherit preface; }; }; # make this available early, and only for the main evaluation (+specialisations, -containers)
extraModules = (args.extraModules or [ ]) ++ [ { imports = [ ({
options.${preface'} = { options.${preface'} = {
instances = lib.mkOption { description = "List of host names to instantiate this host config for, instead of just for the file name."; type = lib.types.listOf lib.types.str; readOnly = true; } // (lib.optionalAttrs (!preface?instances) { default = instances; }); instances = lib.mkOption { description = "List of host names to instantiate this host config for, instead of just for the file name."; type = lib.types.listOf lib.types.str; readOnly = true; } // (lib.optionalAttrs (!preface?instances) { default = instances; });
id = lib.mkOption { description = "This system's ID. If set, »mkSystemsFlake« will ensure that the ID is unique among all »moduleArgs.nodes«."; type = lib.types.nullOr (lib.types.either lib.types.int lib.types.str); readOnly = true; apply = id: if id == null then null else toString id; } // (lib.optionalAttrs (!preface?id) { default = null; }); id = lib.mkOption { description = "This system's ID. If set, »mkSystemsFlake« will ensure that the ID is unique among all »moduleArgs.nodes«."; type = lib.types.nullOr (lib.types.either lib.types.int lib.types.str); readOnly = true; apply = id: if id == null then null else toString id; } // (lib.optionalAttrs (!preface?id) { default = null; });
@ -118,11 +121,11 @@ in rec {
renameOutputs ? false, renameOutputs ? false,
... }: let ... }: let
getName = if renameOutputs == false then (name: name) else renameOutputs; getName = if renameOutputs == false then (name: name) else renameOutputs;
otherArgs = (builtins.removeAttrs args [ "renameOutputs" ]) // { otherArgs = (builtins.removeAttrs args [ "renameOutputs" "systems" ]) // {
inherit inputs modules overlays moduleArgs nixosSystem buildPlatform; inherit inputs modules overlays moduleArgs nixosSystem buildPlatform extraModules;
extraModules = (args.extraModules or [ ]) ++ [ { imports = [ ({ name, ... }/**/: { nixosArgs = (args.nixosArgs or { }) // { modules = (args.nixosArgs.modules or [ ]) ++ [ { imports = [ (args: {
${installer}.outputName = getName name; ${installer}.outputName = getName args.config._module.args.name;
}) ]; _file = "${dirname}/nixos.nix#mkSystemsFlake-extraModule"; } ]; }) ]; _file = "${dirname}/nixos.nix#mkSystemsFlake-extraModule"; } ]; };
}; };
nixosConfigurations = if builtins.isList systems then mergeAttrsUnique (map (systems: mkNixosConfigurations (otherArgs // systems)) systems) else mkNixosConfigurations (otherArgs // systems); nixosConfigurations = if builtins.isList systems then mergeAttrsUnique (map (systems: mkNixosConfigurations (otherArgs // systems)) systems) else mkNixosConfigurations (otherArgs // systems);
in let outputs = { in let outputs = {
@ -168,12 +171,12 @@ in rec {
description = '' description = ''
Call per-host setup and maintenance commands. Most importantly, »install-system«. Call per-host setup and maintenance commands. Most importantly, »install-system«.
''; '';
ownPath = if (system.options.${installer}.outputName != null) then "nix run REPO#${system.config.${installer}.outputName} --" else "$0"; ownPath = if (system.config.${installer}.outputName != null) then "nix run REPO#${system.config.${installer}.outputName} --" else "$0";
usageLine = '' usageLine = ''
Usage: Usage:
%s [sudo] [bash] [--FLAG[=value]]... [--] [COMMAND [ARG]...] %s [sudo] [bash] [--FLAG[=value]]... [--] [COMMAND [ARG]...]
${lib.optionalString (system.options.${installer}.outputName != null) '' ${lib.optionalString (system.config.${installer}.outputName != null) ''
Where »REPO« is the path to the flake repo exporting this system (»${system.config.${installer}.outputName}«) using »mkSystemsFlake«. Where »REPO« is the path to the flake repo exporting this system (»${system.config.${installer}.outputName}«) using »mkSystemsFlake«.
''} If the first argument (after the first »--«) is »sudo«, then the program will re-execute itself as root using sudo (minus that »sudo« argument). ''} If the first argument (after the first »--«) is »sudo«, then the program will re-execute itself as root using sudo (minus that »sudo« argument).
If the (then) first argument is »bash«, or if there are no (more) arguments, it will execute an interactive shell with the »COMMAND«s (bash functions and exported Nix values used by them) sourced. If the (then) first argument is »bash«, or if there are no (more) arguments, it will execute an interactive shell with the »COMMAND«s (bash functions and exported Nix values used by them) sourced.

View File

@ -157,8 +157,9 @@ in let module = {
poolNames = filterBy: lib.attrNames (lib.filterAttrs (name: pool: pool.${filterBy}) cfg.pools); poolNames = filterBy: lib.attrNames (lib.filterAttrs (name: pool: pool.${filterBy}) cfg.pools);
filter = pool: "^${pool}($|[/])"; filter = pool: "^${pool}($|[/])";
ensure-datasets = zfsPackage: pkgs.writeShellScript "ensure-datasets" '' ensure-datasets = zfsPackage: pkgs.writeShellScript "ensure-datasets" ''
set -o pipefail -o nounset ; declare-command () { : ; } ; declare-flag () { : ; } ;
${lib.fun.substituteImplicit { inherit pkgs; scripts = lib.attrValues { inherit (lib.self.setup-scripts) zfs utils; }; context = { inherit config; native = pkgs // { zfs = zfsPackage; }; }; }} ${lib.fun.substituteImplicit { inherit pkgs; scripts = lib.attrValues { inherit (lib.self.setup-scripts) zfs utils; }; context = { inherit config; native = pkgs // { zfs = zfsPackage; }; }; }}
set -eu ; ensure-datasets "$@" ensure-datasets "$@"
''; '';
ensure-datasets-for = filterBy: zfsPackage: ''( if [ ! "''${IN_NIXOS_ENTER:-}" ] && [ -e ${zfsPackage}/bin/zfs ] ; then ensure-datasets-for = filterBy: zfsPackage: ''( if [ ! "''${IN_NIXOS_ENTER:-}" ] && [ -e ${zfsPackage}/bin/zfs ] ; then
${lib.concatStrings (map (pool: '' ${lib.concatStrings (map (pool: ''