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"/>''; See <link xlink:href="https://openwrt.org/docs/guide-user/base-system/dropbear"/>'';
}; };
config.uci.batch = lib.toUciBatch { config.uci.settings.dropbear."" = {
config = "dropbear";
type = "dropbear"; type = "dropbear";
} cfg.settings; inherit (cfg) settings;
};
} }

View File

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

View File

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

View File

@ -2,17 +2,25 @@ final: prev:
let lib = prev; let lib = prev;
in { in {
types = lib.types types = lib.types // (with lib.types; {
// (with lib.types; { uciSection = attrsOf (oneOf [ bool int str ]); }); uciSection = let atom = oneOf [ bool int str ];
in attrsOf (either atom (listOf atom));
});
toUciBatch = with builtins; toUciBatch = { config, type, section, settings }:
let toAtom = v: if isBool v then (if v then "0" else "1") else (toString v); with builtins;
in { config, type, section ? "@${type}[0]" }:
attrs:
let let
cmds = [ "set ${config}.${section}=${type}" ] section' = if section == "" then "@${type}[0]" else section;
++ (lib.attrsets.mapAttrsToList (option: value: toAtom = v: if isBool v then (if v then "1" else "0") else (toString v);
"set ${config}.${section}.${option}='${toAtom value}'") attrs); 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);
} }