mirror of
https://github.com/nix-community/disko
synced 2024-11-13 23:57:12 +00:00
disko2: Add basic config evaluation via nushell
You can call it like so: ./disko.nu mount example/simple-efi.nix ./disko.nu mount -f .#testmachine and it will output a JSON representation of the evaluated disko configuration. eval-config.nix is based on cli.nix The test script is a first attempt.
This commit is contained in:
parent
d7d57edb72
commit
3d67130ff3
4 changed files with 421 additions and 0 deletions
|
@ -17,6 +17,7 @@ let
|
|||
};
|
||||
in
|
||||
{
|
||||
inherit eval;
|
||||
lib = lib.warn "the .lib.lib output is deprecated" diskoLib;
|
||||
|
||||
# legacy alias
|
||||
|
|
96
disko.nu
Executable file
96
disko.nu
Executable file
|
@ -0,0 +1,96 @@
|
|||
#!/usr/bin/env nu
|
||||
|
||||
use std log
|
||||
|
||||
alias nix = ^nix --extra-experimental-features nix-command --extra-experimental-features flakes
|
||||
alias nix-eval-expr = nix eval --impure --json --expr
|
||||
|
||||
def eval-config [args: record]: nothing -> record {
|
||||
do { nix-eval-expr $"import ./eval-config.nix \(builtins.fromJSON ''($args | to json -r)'')" }
|
||||
| complete
|
||||
| if $in.exit_code != 0 {
|
||||
{
|
||||
success: false
|
||||
messages: [
|
||||
$"Failed to evaluate disko config with args ($args)!"
|
||||
$"Error from nix eval: ($in.stderr)"
|
||||
]
|
||||
}
|
||||
} else {
|
||||
$in.stdout
|
||||
| from json
|
||||
| {
|
||||
success: true
|
||||
value: $in
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export def eval-disko-file []: path -> record {
|
||||
let config = $in
|
||||
# If the file is valid JSON, parse and return it
|
||||
open $config | try { into record } | if $in != null {
|
||||
return {
|
||||
success: true
|
||||
value: $in
|
||||
}
|
||||
}
|
||||
|
||||
eval-config { diskoFile: $config }
|
||||
}
|
||||
|
||||
export def eval-flake []: string -> record {
|
||||
let flakeUri = $in
|
||||
let parseResult = $flakeUri | parse "{flake}#{flakeAttr}" | if not ( $in | is-empty ) {
|
||||
$in
|
||||
} else {
|
||||
return {
|
||||
success: false
|
||||
messages: [
|
||||
$"Flake-uri ($flakeUri) does not contain an attribute."
|
||||
"Please append an attribute like \"#foo\" to the flake-uri."
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
let flake = $parseResult.0.flake | if ($in | path exists) { $in | path expand } else { $in }
|
||||
let flakeAttr = $parseResult.0.flakeAttr
|
||||
|
||||
eval-config { flake: $flake, flakeAttr: $flakeAttr }
|
||||
}
|
||||
|
||||
def exit-on-error [context: string] {
|
||||
if $in.success {
|
||||
log debug $"Success: ($context)"
|
||||
log debug $"Return value: ($in.value)"
|
||||
return $in.value
|
||||
}
|
||||
|
||||
log error $"Failed: ($context)"
|
||||
for msg in $in.messages {
|
||||
log error $msg
|
||||
}
|
||||
exit 1
|
||||
}
|
||||
|
||||
def modes [] { ["destroy", "format", "mount", "format,mount", "destroy,format,mount"]}
|
||||
|
||||
def main [
|
||||
mode: string@modes, # Mode to use. Allowed values are 'destroy', 'format', 'mount', 'format,mount', 'destroy,format,mount'
|
||||
disko_file?: path, # File to read the disko configuration from. Can be a .nix file or a .json file
|
||||
--flake (-f): string # Flake URI to search for the disko configuration
|
||||
] {
|
||||
|
||||
if not ($flake != null xor $disko_file != null) {
|
||||
log error "Either --flake or disko_file must be provided"
|
||||
exit 1
|
||||
}
|
||||
|
||||
let config = if $disko_file != null {
|
||||
$disko_file | eval-disko-file | exit-on-error "eval-config"
|
||||
} else {
|
||||
$flake | eval-flake | exit-on-error "eval-flake"
|
||||
}
|
||||
|
||||
$config | to json | print
|
||||
}
|
275
disko.test.nu
Executable file
275
disko.test.nu
Executable file
|
@ -0,0 +1,275 @@
|
|||
#!/usr/bin/env nu
|
||||
|
||||
use disko.nu
|
||||
|
||||
use std assert
|
||||
|
||||
assert equal ("example/simple-efi.nix" | path expand | disko eval-disko-file) {
|
||||
success: true,
|
||||
value: {
|
||||
"disk": {
|
||||
"main": {
|
||||
"content": {
|
||||
"device": "/dev/disk/by-id/some-disk-id",
|
||||
"efiGptPartitionFirst": true,
|
||||
"partitions": {
|
||||
"ESP": {
|
||||
"alignment": 0,
|
||||
"content": {
|
||||
"device": "/dev/disk/by-partlabel/disk-main-ESP",
|
||||
"extraArgs": [],
|
||||
"format": "vfat",
|
||||
"mountOptions": [
|
||||
"umask=0077"
|
||||
],
|
||||
"mountpoint": "/boot",
|
||||
"postCreateHook": "",
|
||||
"postMountHook": "",
|
||||
"preCreateHook": "",
|
||||
"preMountHook": "",
|
||||
"type": "filesystem"
|
||||
},
|
||||
"device": "/dev/disk/by-partlabel/disk-main-ESP",
|
||||
"end": "+500M",
|
||||
"hybrid": null,
|
||||
"label": "disk-main-ESP",
|
||||
"name": "ESP",
|
||||
"priority": 1000,
|
||||
"size": "500M",
|
||||
"start": "0",
|
||||
"type": "EF00"
|
||||
},
|
||||
"root": {
|
||||
"alignment": 0,
|
||||
"content": {
|
||||
"device": "/dev/disk/by-partlabel/disk-main-root",
|
||||
"extraArgs": [],
|
||||
"format": "ext4",
|
||||
"mountOptions": [
|
||||
"defaults"
|
||||
],
|
||||
"mountpoint": "/",
|
||||
"postCreateHook": "",
|
||||
"postMountHook": "",
|
||||
"preCreateHook": "",
|
||||
"preMountHook": "",
|
||||
"type": "filesystem"
|
||||
},
|
||||
"device": "/dev/disk/by-partlabel/disk-main-root",
|
||||
"end": "-0",
|
||||
"hybrid": null,
|
||||
"label": "disk-main-root",
|
||||
"name": "root",
|
||||
"priority": 9001,
|
||||
"size": "100%",
|
||||
"start": "0",
|
||||
"type": "8300"
|
||||
}
|
||||
},
|
||||
"postCreateHook": "",
|
||||
"postMountHook": "",
|
||||
"preCreateHook": "",
|
||||
"preMountHook": "",
|
||||
"type": "gpt"
|
||||
},
|
||||
"device": "/dev/disk/by-id/some-disk-id",
|
||||
"imageName": "main",
|
||||
"imageSize": "2G",
|
||||
"name": "main",
|
||||
"postCreateHook": "",
|
||||
"postMountHook": "",
|
||||
"preCreateHook": "",
|
||||
"preMountHook": "",
|
||||
"type": "disk"
|
||||
}
|
||||
},
|
||||
"lvm_vg": {},
|
||||
"mdadm": {},
|
||||
"nodev": {},
|
||||
"zpool": {}
|
||||
}
|
||||
}
|
||||
|
||||
assert equal ("example/with-lib.nix" | path expand | disko eval-disko-file) {
|
||||
success: true,
|
||||
value: {
|
||||
"disk": {
|
||||
"/dev/vdb": {
|
||||
"content": {
|
||||
"device": "/dev/vdb",
|
||||
"efiGptPartitionFirst": true,
|
||||
"partitions": {
|
||||
"boot": {
|
||||
"alignment": 0,
|
||||
"content": null,
|
||||
"device": "/dev/disk/by-partlabel/disk-_dev_vdb-boot",
|
||||
"end": "+1M",
|
||||
"hybrid": null,
|
||||
"label": "disk-_dev_vdb-boot",
|
||||
"name": "boot",
|
||||
"priority": 100,
|
||||
"size": "1M",
|
||||
"start": "0",
|
||||
"type": "EF02"
|
||||
},
|
||||
"root": {
|
||||
"alignment": 0,
|
||||
"content": {
|
||||
"device": "/dev/disk/by-partlabel/disk-_dev_vdb-root",
|
||||
"extraArgs": [],
|
||||
"format": "ext4",
|
||||
"mountOptions": [
|
||||
"defaults"
|
||||
],
|
||||
"mountpoint": "/",
|
||||
"postCreateHook": "",
|
||||
"postMountHook": "",
|
||||
"preCreateHook": "",
|
||||
"preMountHook": "",
|
||||
"type": "filesystem"
|
||||
},
|
||||
"device": "/dev/disk/by-partlabel/disk-_dev_vdb-root",
|
||||
"end": "-0",
|
||||
"hybrid": null,
|
||||
"label": "disk-_dev_vdb-root",
|
||||
"name": "root",
|
||||
"priority": 9001,
|
||||
"size": "100%",
|
||||
"start": "0",
|
||||
"type": "8300"
|
||||
}
|
||||
},
|
||||
"postCreateHook": "",
|
||||
"postMountHook": "",
|
||||
"preCreateHook": "",
|
||||
"preMountHook": "",
|
||||
"type": "gpt"
|
||||
},
|
||||
"device": "/dev/vdb",
|
||||
"imageName": "_dev_vdb",
|
||||
"imageSize": "2G",
|
||||
"name": "_dev_vdb",
|
||||
"postCreateHook": "",
|
||||
"postMountHook": "",
|
||||
"preCreateHook": "",
|
||||
"preMountHook": "",
|
||||
"type": "disk"
|
||||
}
|
||||
},
|
||||
"lvm_vg": {},
|
||||
"mdadm": {},
|
||||
"nodev": {},
|
||||
"zpool": {}
|
||||
}
|
||||
}
|
||||
|
||||
assert equal (".#testmachine" | disko eval-flake) {
|
||||
success: true,
|
||||
value: {
|
||||
"disk": {
|
||||
"main": {
|
||||
"content": {
|
||||
"device": "/dev/disk/by-id/ata-Samsung_SSD_850_EVO_250GB_S21PNXAGB12345",
|
||||
"efiGptPartitionFirst": true,
|
||||
"partitions": {
|
||||
"ESP": {
|
||||
"alignment": 0,
|
||||
"content": {
|
||||
"device": "/dev/disk/by-partlabel/disk-main-ESP",
|
||||
"extraArgs": [],
|
||||
"format": "vfat",
|
||||
"mountOptions": [
|
||||
"umask=0077"
|
||||
],
|
||||
"mountpoint": "/boot",
|
||||
"postCreateHook": "",
|
||||
"postMountHook": "",
|
||||
"preCreateHook": "",
|
||||
"preMountHook": "",
|
||||
"type": "filesystem"
|
||||
},
|
||||
"device": "/dev/disk/by-partlabel/disk-main-ESP",
|
||||
"end": "+512M",
|
||||
"hybrid": null,
|
||||
"label": "disk-main-ESP",
|
||||
"name": "ESP",
|
||||
"priority": 1000,
|
||||
"size": "512M",
|
||||
"start": "0",
|
||||
"type": "EF00"
|
||||
},
|
||||
"boot": {
|
||||
"alignment": 0,
|
||||
"content": null,
|
||||
"device": "/dev/disk/by-partlabel/disk-main-boot",
|
||||
"end": "+1M",
|
||||
"hybrid": null,
|
||||
"label": "disk-main-boot",
|
||||
"name": "boot",
|
||||
"priority": 100,
|
||||
"size": "1M",
|
||||
"start": "0",
|
||||
"type": "EF02"
|
||||
},
|
||||
"root": {
|
||||
"alignment": 0,
|
||||
"content": {
|
||||
"device": "/dev/disk/by-partlabel/disk-main-root",
|
||||
"extraArgs": [],
|
||||
"format": "ext4",
|
||||
"mountOptions": [
|
||||
"defaults"
|
||||
],
|
||||
"mountpoint": "/",
|
||||
"postCreateHook": "",
|
||||
"postMountHook": "",
|
||||
"preCreateHook": "",
|
||||
"preMountHook": "",
|
||||
"type": "filesystem"
|
||||
},
|
||||
"device": "/dev/disk/by-partlabel/disk-main-root",
|
||||
"end": "-0",
|
||||
"hybrid": null,
|
||||
"label": "disk-main-root",
|
||||
"name": "root",
|
||||
"priority": 9001,
|
||||
"size": "100%",
|
||||
"start": "0",
|
||||
"type": "8300"
|
||||
}
|
||||
},
|
||||
"postCreateHook": "",
|
||||
"postMountHook": "",
|
||||
"preCreateHook": "",
|
||||
"preMountHook": "",
|
||||
"type": "gpt"
|
||||
},
|
||||
"device": "/dev/disk/by-id/ata-Samsung_SSD_850_EVO_250GB_S21PNXAGB12345",
|
||||
"imageName": "main",
|
||||
"imageSize": "2G",
|
||||
"name": "main",
|
||||
"postCreateHook": "",
|
||||
"postMountHook": "",
|
||||
"preCreateHook": "",
|
||||
"preMountHook": "",
|
||||
"type": "disk"
|
||||
}
|
||||
},
|
||||
"lvm_vg": {},
|
||||
"mdadm": {},
|
||||
"nodev": {},
|
||||
"zpool": {}
|
||||
}
|
||||
}
|
||||
|
||||
assert equal ("." | disko eval-flake) {
|
||||
success: false,
|
||||
messages: [
|
||||
"Flake-uri . does not contain an attribute.",
|
||||
"Please append an attribute like \"#foo\" to the flake-uri."
|
||||
]
|
||||
}
|
||||
|
||||
def main [] {
|
||||
echo "All tests passed"
|
||||
}
|
49
eval-config.nix
Normal file
49
eval-config.nix
Normal file
|
@ -0,0 +1,49 @@
|
|||
{ pkgs ? import <nixpkgs> { }
|
||||
, lib ? pkgs.lib
|
||||
, flake ? null
|
||||
, flakeAttr ? null
|
||||
, diskoFile ? null
|
||||
, rootMountPoint ? "/mnt"
|
||||
, ...
|
||||
}@args:
|
||||
let
|
||||
disko = import ./. {
|
||||
inherit rootMountPoint;
|
||||
inherit lib;
|
||||
};
|
||||
|
||||
flake' = (builtins.getFlake flake);
|
||||
|
||||
hasDiskoFile = diskoFile != null;
|
||||
|
||||
hasFlakeDiskoConfig = lib.hasAttrByPath [ "diskoConfigurations" flakeAttr ] flake';
|
||||
|
||||
hasFlakeDiskoModule =
|
||||
lib.hasAttrByPath [ "nixosConfigurations" flakeAttr "config" "disko" "devices" ] flake';
|
||||
|
||||
diskFormat =
|
||||
let
|
||||
diskoConfig =
|
||||
if hasDiskoFile then
|
||||
import diskoFile
|
||||
else
|
||||
flake'.diskoConfigurations.${flakeAttr};
|
||||
in
|
||||
if builtins.isFunction diskoConfig then
|
||||
diskoConfig ({ inherit lib; } // args)
|
||||
else
|
||||
diskoConfig;
|
||||
|
||||
evaluatedConfig =
|
||||
if hasDiskoFile || hasFlakeDiskoConfig then
|
||||
disko.eval diskFormat
|
||||
else if (lib.traceValSeq hasFlakeDiskoModule) then
|
||||
flake'.nixosConfigurations.${flakeAttr}
|
||||
else
|
||||
(builtins.abort "couldn't find `diskoConfigurations.${flakeAttr}` or `nixosConfigurations.${flakeAttr}.config.disko.devices`");
|
||||
|
||||
diskoConfig = evaluatedConfig.config.disko.devices;
|
||||
|
||||
finalConfig = lib.filterAttrsRecursive (name: value: !lib.hasPrefix "_" name) diskoConfig;
|
||||
in
|
||||
finalConfig
|
Loading…
Reference in a new issue