lib: refactor outputs into toplevel

This commit is contained in:
lassulus 2023-07-13 15:08:20 +02:00 committed by mergify[bot]
parent 7eb0940839
commit cdaff66b57
4 changed files with 166 additions and 81 deletions

View file

@ -10,7 +10,7 @@ let
imports = lib.singleton { disko.devices = cfg.disko.devices; }; imports = lib.singleton { disko.devices = cfg.disko.devices; };
options = { options = {
disko.devices = lib.mkOption { disko.devices = lib.mkOption {
type = diskoLib.devices; type = diskoLib.toplevel;
}; };
}; };
}; };

View file

@ -10,7 +10,7 @@ let
{ {
options.disko = { options.disko = {
devices = lib.mkOption { devices = lib.mkOption {
type = diskoLib.devices; type = diskoLib.toplevel;
default = { }; default = { };
description = "The devices to set up"; description = "The devices to set up";
}; };

View file

@ -250,71 +250,39 @@ let
meta :: lib.types.devices -> AttrSet meta :: lib.types.devices -> AttrSet
*/ */
meta = devices: diskoLib.deepMergeMap (dev: dev._meta) (flatten (map attrValues (attrValues devices))); meta = toplevel: toplevel._meta;
/* Takes a disko device specification and returns a string which formats the disks /* Takes a disko device specification and returns a string which formats the disks
create :: lib.types.devices -> str create :: lib.types.devices -> str
*/ */
create = devices: create = toplevel: toplevel._create;
let
sortedDeviceList = diskoLib.sortDevicesByDependencies ((diskoLib.meta devices).deviceDependencies or { }) devices;
in
''
set -efux
disko_devices_dir=$(mktemp -d)
trap 'rm -rf "$disko_devices_dir"' EXIT
mkdir -p "$disko_devices_dir"
${concatMapStrings (dev: (attrByPath (dev ++ [ "_create" ]) "" devices)) sortedDeviceList}
'';
/* Takes a disko device specification and returns a string which mounts the disks /* Takes a disko device specification and returns a string which mounts the disks
mount :: lib.types.devices -> str mount :: lib.types.devices -> str
*/ */
mount = devices: mount = toplevel: toplevel._mount;
let
fsMounts = diskoLib.deepMergeMap (dev: dev._mount.fs or { }) (flatten (map attrValues (attrValues devices)));
sortedDeviceList = diskoLib.sortDevicesByDependencies ((diskoLib.meta devices).deviceDependencies or { }) devices;
in
''
set -efux
# first create the necessary devices
${concatMapStrings (dev: ((attrByPath (dev ++ [ "_mount" ]) {} devices)).dev or "") sortedDeviceList}
# and then mount the filesystems in alphabetical order
${concatStrings (attrValues fsMounts)}
'';
/* takes a disko device specification and returns a string which unmounts, destroys all disks and then runs create and mount /* takes a disko device specification and returns a string which unmounts, destroys all disks and then runs create and mount
zapCreateMount :: lib.types.devices -> str zapCreateMount :: lib.types.devices -> str
*/ */
zapCreateMount = devices: '' zapCreateMount = toplevel:
''
set -efux set -efux
umount -Rv "${rootMountPoint}" || : ${toplevel._disko}
# shellcheck disable=SC2043
for dev in ${toString (lib.catAttrs "device" (lib.attrValues devices.disk))}; do
${../disk-deactivate}/disk-deactivate "$dev" | bash -x
done
echo 'creating partitions...'
${diskoLib.create devices}
echo 'mounting partitions...'
${diskoLib.mount devices}
''; '';
/* Takes a disko device specification and returns a nixos configuration /* Takes a disko device specification and returns a nixos configuration
config :: lib.types.devices -> nixosConfig config :: lib.types.devices -> nixosConfig
*/ */
config = devices: flatten (map (dev: dev._config) (flatten (map attrValues (attrValues devices)))); config = toplevel: toplevel._config;
/* Takes a disko device specification and returns a function to get the needed packages to format/mount the disks /* Takes a disko device specification and returns a function to get the needed packages to format/mount the disks
packages :: lib.types.devices -> pkgs -> [ derivation ] packages :: lib.types.devices -> pkgs -> [ derivation ]
*/ */
packages = devices: pkgs: unique (flatten (map (dev: dev._pkgs pkgs) (flatten (map attrValues (attrValues devices))))); packages = toplevel: toplevel._packages;
optionTypes = rec { optionTypes = rec {
filename = lib.mkOptionType { filename = lib.mkOptionType {
@ -348,7 +316,9 @@ let
/* topLevel type of the disko config, takes attrsets of disks, mdadms, zpools, nodevs, and lvm vgs. /* topLevel type of the disko config, takes attrsets of disks, mdadms, zpools, nodevs, and lvm vgs.
*/ */
devices = lib.types.submodule { toplevel = lib.types.submodule (cfg: let
devices = { inherit (cfg.config) disk mdadm zpool lvm_vg nodev; };
in {
options = { options = {
disk = lib.mkOption { disk = lib.mkOption {
type = lib.types.attrsOf diskoLib.types.disk; type = lib.types.attrsOf diskoLib.types.disk;
@ -375,8 +345,149 @@ let
default = { }; default = { };
description = "A non-block device"; description = "A non-block device";
}; };
_meta = lib.mkOption {
internal = true;
description = ''
meta informationen generated by disko
currently used for building a dependency list so we know in which order to create the devices
'';
default = diskoLib.deepMergeMap (dev: dev._meta) (flatten (map attrValues (attrValues devices)));
};
_packages = lib.mkOption {
internal = true;
description = ''
packages required by the disko configuration
'';
default = pkgs: unique (flatten (map (dev: dev._pkgs pkgs) (flatten (map attrValues (attrValues devices)))));
};
_scripts = lib.mkOption {
internal = true;
description = ''
The scripts generated by disko
'';
default = { pkgs, checked ? false }: {
umountScript = (diskoLib.writeCheckedBash { inherit pkgs checked; }) "disko-umount" ''
export PATH=${lib.makeBinPath (with pkgs; [
util-linux
e2fsprogs
mdadm
zfs
lvm2
])}:$PATH
${cfg.config._umount}
'';
formatScript = (diskoLib.writeCheckedBash { inherit pkgs checked; }) "disko-format" ''
export PATH=${lib.makeBinPath (cfg.config._packages pkgs)}:$PATH
${cfg.config._create}
'';
mountScript = (diskoLib.writeCheckedBash { inherit pkgs checked; }) "disko-mount" ''
export PATH=${lib.makeBinPath (cfg.config._packages pkgs)}:$PATH
${cfg.config._mount}
'';
diskoScript = (diskoLib.writeCheckedBash { inherit pkgs checked; }) "disko" ''
export PATH=${lib.makeBinPath ((cfg.config._packages pkgs) ++ [ pkgs.bash ])}:$PATH
${cfg.config._disko}
'';
# These are useful to skip copying executables uploading a script to an in-memory installer
umountScriptNoDeps = (diskoLib.writeCheckedBash { inherit pkgs checked; noDeps = true; }) "disko-umount" ''
${cfg.config._umount}
'';
formatScriptNoDeps = (diskoLib.writeCheckedBash { inherit pkgs checked; noDeps = true; }) "disko-format" ''
${cfg.config._create}
'';
system.build.mountScriptNoDeps = (diskoLib.writeCheckedBash { inherit pkgs checked; noDeps = true; }) "disko-mount" ''
${cfg.config._mount}
'';
diskoScriptNoDeps = (diskoLib.writeCheckedBash { inherit pkgs checked; noDeps = true; }) "disko" ''
${cfg.config._disko}
'';
};
};
_umount = lib.mkOption {
internal = true;
type = lib.types.str;
description = ''
The script to unmount (& destroy) all devices defined by disko.devices
'';
default = ''
umount -Rv "${rootMountPoint}" || :
# shellcheck disable=SC2043
for dev in ${toString (lib.catAttrs "device" (lib.attrValues devices.disk))}; do
${../disk-deactivate}/disk-deactivate "$dev" | bash -x
done
'';
};
_create = lib.mkOption {
internal = true;
type = lib.types.str;
description = ''
The script to create all devices defined by disko.devices
'';
default = let
sortedDeviceList = diskoLib.sortDevicesByDependencies (cfg.config._meta.deviceDependencies or { }) devices;
in
''
set -efux
disko_devices_dir=$(mktemp -d)
trap 'rm -rf "$disko_devices_dir"' EXIT
mkdir -p "$disko_devices_dir"
${concatMapStrings (dev: (attrByPath (dev ++ [ "_create" ]) {} devices)) sortedDeviceList}
'';
};
_mount = lib.mkOption {
internal = true;
type = lib.types.str;
description = ''
The script to mount all devices defined by disko.devices
'';
default = let
fsMounts = diskoLib.deepMergeMap (dev: dev._mount.fs or { }) (flatten (map attrValues (attrValues devices)));
sortedDeviceList = diskoLib.sortDevicesByDependencies (cfg.config._meta.deviceDependencies or { }) devices;
in ''
set -efux
# first create the necessary devices
${concatMapStrings (dev: ((attrByPath (dev ++ [ "_mount" ]) {} devices)).dev or "") sortedDeviceList}
# and then mount the filesystems in alphabetical order
${concatStrings (attrValues fsMounts)}
'';
};
_disko = lib.mkOption {
internal = true;
type = lib.types.str;
description = ''
The script to umount, create and mount all devices defined by disko.devices
'';
default = ''
${cfg.config._umount}
${cfg.config._create}
${cfg.config._mount}
'';
};
_config = lib.mkOption {
internal = true;
description = ''
The NixOS config generated by disko
'';
default =
let
configKeys = flatten (map attrNames (flatten (map (dev: dev._config) (flatten (map attrValues (attrValues devices))))));
collectedConfigs = flatten (map (dev: dev._config) (flatten (map attrValues (attrValues devices))));
in
lib.genAttrs configKeys (key: lib.mkMerge (lib.catAttrs key collectedConfigs));
};
}; };
}; });
# import all tge types from the types directory # import all tge types from the types directory
types = lib.listToAttrs ( types = lib.listToAttrs (

View file

@ -5,12 +5,11 @@ let
rootMountPoint = config.disko.rootMountPoint; rootMountPoint = config.disko.rootMountPoint;
}; };
cfg = config.disko; cfg = config.disko;
checked = cfg.checkScripts;
in in
{ {
options.disko = { options.disko = {
devices = lib.mkOption { devices = lib.mkOption {
type = diskoLib.devices; type = diskoLib.toplevel;
default = { }; default = { };
description = "The devices to set up"; description = "The devices to set up";
}; };
@ -37,43 +36,18 @@ in
}; };
}; };
config = lib.mkIf (cfg.devices.disk != { }) { config = lib.mkIf (cfg.devices.disk != { }) {
system.build.formatScript = (diskoLib.writeCheckedBash { inherit pkgs checked; }) "disko-create" '' system.build = (cfg.devices._scripts { inherit pkgs; checked = cfg.checkScripts; }) // {
export PATH=${lib.makeBinPath (diskoLib.packages cfg.devices pkgs)}:$PATH
${diskoLib.create cfg.devices}
'';
system.build.mountScript = (diskoLib.writeCheckedBash { inherit pkgs checked; }) "disko-mount" '' # we keep this old outputs for compatibility
export PATH=${lib.makeBinPath (diskoLib.packages cfg.devices pkgs)}:$PATH disko = builtins.trace "the .disko output is deprecated, plase use .diskoScript instead" cfg.devices._scripts.diskoScript;
${diskoLib.mount cfg.devices} diskoNoDeps = builtins.trace "the .diskoNoDeps output is deprecated, plase use .diskoScriptNoDeps instead" cfg.devices._scripts.diskoScriptNoDeps;
''; };
# we keep this old output for compatibility
system.build.disko = builtins.trace "the .disko output is deprecated, plase use .diskoScript instead" config.system.build.diskoScript;
system.build.diskoScript = (diskoLib.writeCheckedBash { inherit pkgs checked; }) "disko" ''
export PATH=${lib.makeBinPath ((diskoLib.packages cfg.devices pkgs) ++ [ pkgs.bash ])}:$PATH
${diskoLib.zapCreateMount cfg.devices}
'';
# These are useful to skip copying executables uploading a script to an in-memory installer
system.build.formatScriptNoDeps = (diskoLib.writeCheckedBash { inherit pkgs checked; noDeps = true; }) "disko-create" ''
${diskoLib.create cfg.devices}
'';
system.build.mountScriptNoDeps = (diskoLib.writeCheckedBash { inherit pkgs checked; noDeps = true; }) "disko-mount" ''
${diskoLib.mount cfg.devices}
'';
# we keep this old output for compatibility
system.build.diskoNoDeps = builtins.trace "the .diskoNoDeps output is deprecated, plase use .diskoScriptNoDeps instead" config.system.build.diskoScriptNoDeps;
system.build.diskoScriptNoDeps = (diskoLib.writeCheckedBash { inherit pkgs checked; noDeps = true; }) "disko" ''
${diskoLib.zapCreateMount cfg.devices}
'';
# we need to specify the keys here, so we don't get an infinite recursion error
# Remember to add config keys here if they are added to types # Remember to add config keys here if they are added to types
fileSystems = lib.mkIf cfg.enableConfig (lib.mkMerge (lib.catAttrs "fileSystems" (diskoLib.config cfg.devices))); fileSystems = lib.mkIf cfg.enableConfig cfg.devices._config.fileSystems or {};
boot = lib.mkIf cfg.enableConfig (lib.mkMerge (lib.catAttrs "boot" (diskoLib.config cfg.devices))); boot = lib.mkIf cfg.enableConfig cfg.devices._config.boot or {};
swapDevices = lib.mkIf cfg.enableConfig (lib.mkMerge (lib.catAttrs "swapDevices" (diskoLib.config cfg.devices))); swapDevices = lib.mkIf cfg.enableConfig cfg.devices._config.swapDevices or [];
}; };
} }