types: refactor topLevel into devices, move output generators to lib

This commit is contained in:
lassulus 2022-10-22 23:35:16 +02:00
parent 271b00593f
commit 5aa3ebcb99
2 changed files with 66 additions and 83 deletions

View File

@ -4,18 +4,18 @@ let
eval = cfg: lib.evalModules { eval = cfg: lib.evalModules {
modules = lib.singleton { modules = lib.singleton {
# _file = toString input; # _file = toString input;
imports = lib.singleton { topLevel.devices = cfg; }; imports = lib.singleton { devices = cfg; };
options = { options = {
topLevel = lib.mkOption { devices = lib.mkOption {
type = types.topLevel; type = types.devices;
}; };
}; };
}; };
}; };
in { in {
types = types; types = types;
create = cfg: (eval cfg).config.topLevel.create; create = cfg: types.diskoLib.create (eval cfg).config.devices;
mount = cfg: (eval cfg).config.topLevel.mount; mount = cfg: types.diskoLib.mount (eval cfg).config.devices;
config = cfg: (eval cfg).config.topLevel.config; config = cfg: types.diskoLib.config (eval cfg).config.devices;
packages = cfg: (eval cfg).config.topLevel.packages; packages = cfg: types.diskoLib.packages (eval cfg).config.devices;
} }

135
types.nix
View File

@ -119,6 +119,51 @@ rec {
=> "hello world" => "hello world"
*/ */
maybeStr = x: optionalString (!isNull x) x; maybeStr = x: optionalString (!isNull x) x;
/* Takes a disko device specification, returns an attrset with metadata
meta :: types.devices -> AttrSet
*/
meta = devices: diskoLib.deepMergeMap (dev: dev._meta) (flatten (map attrValues (attrValues devices)));
/* Takes a disko device specification and returns a string which formats the disks
create :: types.devices -> str
*/
create = devices: let
sortedDeviceList = diskoLib.sortDevicesByDependencies (diskoLib.meta devices).deviceDependencies devices;
in ''
set -efux
${concatStrings (map (dev: attrByPath (dev ++ [ "_create" ]) "" devices) sortedDeviceList)}
'';
/* Takes a disko device specification and returns a string which mounts the disks
mount :: types.devices -> str
*/
mount = devices: let
fsMounts = diskoLib.deepMergeMap (dev: dev._mount.fs or {}) (flatten (map attrValues (attrValues devices)));
sortedDeviceList = diskoLib.sortDevicesByDependencies (diskoLib.meta devices).deviceDependencies devices;
in ''
set -efux
# first create the neccessary devices
${concatStrings (map (dev: attrByPath (dev ++ [ "_mount" "dev" ]) "" devices) sortedDeviceList)}
# and then mount the filesystems in alphabetical order
# attrValues returns values sorted by name. This is important, because it
# ensures that "/" is processed before "/foo" etc.
${concatStrings (attrValues fsMounts)}
'';
/* Takes a disko device specification and returns a nixos configuration
config :: types.devices -> nixosConfig
*/
config = devices: {
imports = flatten (map (dev: dev._config) (flatten (map attrValues (attrValues devices))));
};
/* Takes a disko device specification and returns a function to get the needed packages to format/mount the disks
packages :: types.devices -> pkgs -> [ derivation ]
*/
packages = devices: pkgs: unique (flatten (map (dev: dev._pkgs pkgs) (flatten (map attrValues (attrValues devices)))));
}; };
optionTypes = rec { optionTypes = rec {
@ -152,89 +197,27 @@ rec {
}; };
/* topLevel type of the disko config, takes attrsets of disks mdadms zpools and lvm vgs. /* topLevel type of the disko config, takes attrsets of disks mdadms zpools and lvm vgs.
exports create, mount, meta and config
*/ */
topLevel = types.submodule ({ config, ... }: { devices = types.submodule {
options = { options = {
devices = { disk = mkOption {
disk = mkOption { type = types.attrsOf disk;
type = types.attrsOf disk; default = {};
default = {};
};
mdadm = mkOption {
type = types.attrsOf mdadm;
default = {};
};
zpool = mkOption {
type = types.attrsOf zpool;
default = {};
};
lvm_vg = mkOption {
type = types.attrsOf lvm_vg;
default = {};
};
}; };
meta = mkOption { mdadm = mkOption {
readOnly = true; type = types.attrsOf mdadm;
default = diskoLib.deepMergeMap (dev: dev._meta) (flatten (map attrValues [ default = {};
config.devices.disk
config.devices.lvm_vg
config.devices.mdadm
config.devices.zpool
])) // {
sortedDeviceList = diskoLib.sortDevicesByDependencies config.meta.deviceDependencies config.devices;
};
}; };
create = mkOption { zpool = mkOption {
readOnly = true; type = types.attrsOf zpool;
type = types.str; default = {};
default = ''
set -efux
${concatStrings (map (dev: attrByPath (dev ++ [ "_create" ]) "" config.devices) config.meta.sortedDeviceList)}
'';
}; };
mount = mkOption { lvm_vg = mkOption {
readOnly = true; type = types.attrsOf lvm_vg;
type = types.str; default = {};
default = let
fsMounts = diskoLib.deepMergeMap (dev: dev._mount.fs or {}) (flatten (map attrValues [
config.devices.disk
config.devices.lvm_vg
config.devices.mdadm
config.devices.zpool
]));
in ''
set -efux
# first create the neccessary devices
${concatStrings (map (dev: attrByPath (dev ++ [ "_mount" "dev" ]) "" config.devices) config.meta.sortedDeviceList)}
# and then mount the filesystems in alphabetical order
# attrValues returns values sorted by name. This is important, because it
# ensures that "/" is processed before "/foo" etc.
${concatStrings (attrValues fsMounts)}
'';
};
config = mkOption {
readOnly = true;
default = { imports = flatten (map (dev: dev._config) (flatten (map attrValues [
config.devices.disk
config.devices.lvm_vg
config.devices.mdadm
config.devices.zpool
])));};
};
packages = mkOption {
readOnly = true;
# type = types.functionTo (types.listOf types.package);
default = pkgs: unique (flatten (map (dev: dev._pkgs pkgs) (flatten (map attrValues [
config.devices.disk
config.devices.lvm_vg
config.devices.mdadm
config.devices.zpool
]))));
}; };
}; };
}); };
btrfs = types.submodule ({ config, ... }: { btrfs = types.submodule ({ config, ... }: {
options = { options = {