Refactor UCI

Convert all options that go to UCI as an intermediate attrset
at config.uci.settings before generating the batch script.
This commit is contained in:
Ehmry - 2022-06-23 18:09:16 -05:00
parent a4cd619f69
commit a30a724a0f
5 changed files with 48 additions and 33 deletions

View File

@ -9,8 +9,8 @@ in {
See <link xlink:href="https://openwrt.org/docs/guide-user/base-system/dropbear"/>'';
};
config.uci.batch = lib.toUciBatch {
config = "dropbear";
config.uci.settings.dropbear."" = {
type = "dropbear";
} cfg.settings;
inherit (cfg) settings;
};
}

View File

@ -24,9 +24,9 @@ in {
};
config.uci.batch = lib.toUciBatch {
config = "system";
config.uci.settings.system."" = {
type = "system";
} cfg.settings;
inherit (cfg) settings;
};
}

View File

@ -2,19 +2,30 @@
with lib;
let cfg = config.uci;
in {
options.uci.batch = mkOption {
type = types.lines;
description = "UCI script to execute on first boot.";
example = ''
set system.@system[0].hostname='testap'
set dropbear.@dropbear[0].RootPasswordAuth='off'
options.uci.settings = mkOption {
default = { };
description = ''
See <link xlink:href="https://openwrt.org/docs/guide-user/base-system/uci#uci_dataobject_model"/>.
'';
type = with types;
attrsOf (attrsOf (submodule {
options = {
type = mkOption { type = str; };
settings = mkOption { type = uciSection; };
};
}));
};
config.extraFiles."/etc/uci-defaults/99-config.uci.batch".text =
mkIf (cfg.batch != "") ''
mkIf (cfg.settings != { }) ''
uci -q batch << NIX_EOI
${cfg.batch}
uci commit
${ # Flatten all the UCI settings into a batch script.
lib.strings.concatStringsSep "\n" (lib.lists.flatten
(lib.attrsets.mapAttrsToList (config: attrs:
(lib.attrsets.mapAttrsToList (section:
{ type, settings }:
lib.toUciBatch { inherit config section type settings; }) attrs)
++ [ "commit ${config}" ]) cfg.settings))}
NIX_EOI
'';
}

View File

@ -36,16 +36,12 @@ in {
};
};
# TODO: assert that device and interfaces name are mutually unique.
};
config.uci.batch = let
config.uci.settings.wireless = let
toUci' = type:
(lib.attrsets.mapAttrsToList (section: settings:
lib.toUciBatch {
config = "wireless";
inherit section type;
} settings));
in lib.strings.concatStringsSep "\n"
((toUci' "wifi-device" cfg.devices) ++ (toUci' "wifi-iface" cfg.interfaces));
lib.attrsets.mapAttrs (_: settings: { inherit type settings; });
in (toUci' "wifi-device" cfg.devices) // (toUci' "wifi-iface" cfg.interfaces);
}

View File

@ -2,17 +2,25 @@ final: prev:
let lib = prev;
in {
types = lib.types
// (with lib.types; { uciSection = attrsOf (oneOf [ bool int str ]); });
types = lib.types // (with lib.types; {
uciSection = let atom = oneOf [ bool int str ];
in attrsOf (either atom (listOf atom));
});
toUciBatch = with builtins;
let toAtom = v: if isBool v then (if v then "0" else "1") else (toString v);
in { config, type, section ? "@${type}[0]" }:
attrs:
toUciBatch = { config, type, section, settings }:
with builtins;
let
cmds = [ "set ${config}.${section}=${type}" ]
++ (lib.attrsets.mapAttrsToList (option: value:
"set ${config}.${section}.${option}='${toAtom value}'") attrs);
section' = if section == "" then "@${type}[0]" else section;
toAtom = v: if isBool v then (if v then "1" else "0") else (toString v);
toCmd = option: value:
if isList value then
map
(elem: "add_list '${config}.${section'}.${option}'='${toAtom elem}'")
value
else
"set '${config}.${section'}.${option}'='${toAtom value}'";
cmds = [ "set '${config}.${section'}'='${type}'" ]
++ (lib.attrsets.mapAttrsToList toCmd settings);
in lib.strings.concatStringsSep "\n" cmds;
in lib.strings.concatStringsSep "\n" (lib.lists.flatten cmds);
}