lib/values: fix submodule definition merging

This commit is contained in:
Johannes Kirschbauer
2024-12-06 19:53:34 +01:00
parent 388455038a
commit cc1eaf53ae
4 changed files with 84 additions and 28 deletions

View File

@@ -23,11 +23,9 @@ let
prio = { prio = {
__prio = opt.highestPrio; __prio = opt.highestPrio;
}; };
subOptions = opt.type.getSubOptions opt.loc; filteredSubOptions = filterOptions (opt.type.getSubOptions opt.loc);
attrDefinitions = (lib.modules.mergeAttrDefinitionsWithPrio opt); zipDefs = builtins.zipAttrsWith (_: vs: vs);
zipDefs = builtins.zipAttrsWith (_ns: vs: vs);
defs = zipDefs opt.definitions;
prioPerValue = prioPerValue =
{ type, defs }: { type, defs }:
@@ -35,7 +33,7 @@ let
attrName: prioSet: attrName: prioSet:
let let
# Evaluate the submodule # Evaluate the submodule
options = filterOptions subOptions; options = filteredSubOptions;
modules = ( modules = (
[ [
{ inherit options; } { inherit options; }
@@ -48,7 +46,6 @@ let
in in
(lib.optionalAttrs (prioSet ? highestPrio) { (lib.optionalAttrs (prioSet ? highestPrio) {
__prio = prioSet.highestPrio; __prio = prioSet.highestPrio;
# inherit defs options;
}) })
// ( // (
if type.nestedTypes.elemType.name == "submodule" then if type.nestedTypes.elemType.name == "submodule" then
@@ -64,21 +61,30 @@ let
) )
); );
attributePrios = prioPerValue { submodulePrios =
type = opt.type; let
inherit defs; options = filteredSubOptions;
} attrDefinitions; modules = (
[
{ inherit options; }
]
++ opt.definitions
);
submoduleEval = lib.evalModules {
inherit modules;
};
in
getPrios { options = filterOptions submoduleEval.options; };
in in
if opt ? type && opt.type.name == "submodule" then if opt ? type && opt.type.name == "submodule" then
prio // (getPrios { options = subOptions; }) (prio) // submodulePrios
else if opt ? type && opt.type.name == "attrsOf" then else if opt ? type && opt.type.name == "attrsOf" then
# prio // attributePrios prio // (
# else if prioPerValue {
# opt ? type && opt.type.name == "attrsOf" && opt.type.nestedTypes.elemType.name == "attrsOf" type = opt.type;
# then defs = zipDefs opt.definitions;
# prio // attributePrios } (lib.modules.mergeAttrDefinitionsWithPrio opt))
# else if opt ? type && opt.type.name == "attrsOf" then
prio // attributePrios
else if opt ? type && opt._type == "option" then else if opt ? type && opt._type == "option" then
prio prio
else else

View File

@@ -80,6 +80,56 @@ in
}; };
}; };
test_submodule_with_merging =
let
evaluated = (
eval [
{
options.foo = lib.mkOption {
type = lib.types.submodule {
options = {
normal = lib.mkOption {
type = lib.types.bool;
};
default = lib.mkOption {
type = lib.types.bool;
};
optionDefault = lib.mkOption {
type = lib.types.bool;
default = true;
};
unset = lib.mkOption {
type = lib.types.bool;
};
};
};
};
}
{
foo.default = lib.mkDefault true;
}
{
foo.normal = false;
}
]
);
in
{
inherit evaluated;
expr = slib.getPrios {
options = evaluated.options;
};
expected = {
foo = {
__prio = 100;
normal.__prio = 100; # Set via other module
default.__prio = 1000;
optionDefault.__prio = 1500;
unset.__prio = 9999;
};
};
};
# TODO(@hsjobeki): Cover this edge case # TODO(@hsjobeki): Cover this edge case
# test_freeform = # test_freeform =
# let # let

View File

@@ -40,7 +40,7 @@ export const MachineListItem = (props: MachineListItemProps) => {
} }
if (!info?.deploy?.targetHost) { if (!info?.deploy?.targetHost) {
toast.error( toast.error(
"Machine does not have a target host. Specify where the machine should be deployed." "Machine does not have a target host. Specify where the machine should be deployed.",
); );
return; return;
} }
@@ -63,7 +63,7 @@ export const MachineListItem = (props: MachineListItemProps) => {
loading: "Installing...", loading: "Installing...",
success: "Installed", success: "Installed",
error: "Failed to install", error: "Failed to install",
} },
); );
setInstalling(false); setInstalling(false);
}; };
@@ -80,7 +80,7 @@ export const MachineListItem = (props: MachineListItemProps) => {
} }
if (!info?.deploy.targetHost) { if (!info?.deploy.targetHost) {
toast.error( toast.error(
"Machine does not have a target host. Specify where the machine should be deployed." "Machine does not have a target host. Specify where the machine should be deployed.",
); );
return; return;
} }
@@ -101,7 +101,7 @@ export const MachineListItem = (props: MachineListItemProps) => {
loading: "Updating...", loading: "Updating...",
success: "Updated", success: "Updated",
error: "Failed to update", error: "Failed to update",
} },
); );
setUpdating(false); setUpdating(false);
}; };

View File

@@ -65,7 +65,7 @@ const InstallMachine = (props: InstallMachineProps) => {
} }
const loading_toast = toast.loading( const loading_toast = toast.loading(
"Installing machine. Grab coffee (15min)..." "Installing machine. Grab coffee (15min)...",
); );
const r = await callApi("install_machine", { const r = await callApi("install_machine", {
opts: { opts: {
@@ -248,13 +248,13 @@ const MachineForm = (props: MachineDetailsProps) => {
...values.machine, ...values.machine,
// TODO: Remove this workaround // TODO: Remove this workaround
tags: Array.from( tags: Array.from(
values.machine.tags || props.initialData.machine.tags || [] values.machine.tags || props.initialData.machine.tags || [],
), ),
}, },
}); });
if (machine_response.status === "error") { if (machine_response.status === "error") {
toast.error( toast.error(
`Failed to set machine: ${machine_response.errors[0].message}` `Failed to set machine: ${machine_response.errors[0].message}`,
); );
} }
if (machine_response.status === "success") { if (machine_response.status === "success") {
@@ -455,7 +455,7 @@ const MachineForm = (props: MachineDetailsProps) => {
// disabled={!online()} // disabled={!online()}
onClick={() => { onClick={() => {
const modal = document.getElementById( const modal = document.getElementById(
"install_modal" "install_modal",
) as HTMLDialogElement | null; ) as HTMLDialogElement | null;
modal?.showModal(); modal?.showModal();
}} }}
@@ -561,7 +561,7 @@ function WifiModule(props: MachineWifiProps) {
}); });
const [nets, setNets] = createSignal<1[]>( const [nets, setNets] = createSignal<1[]>(
new Array(props.initialData.length || 1).fill(1) new Array(props.initialData.length || 1).fill(1),
); );
const handleSubmit = async (values: WifiForm) => { const handleSubmit = async (values: WifiForm) => {
@@ -572,7 +572,7 @@ function WifiModule(props: MachineWifiProps) {
...acc, ...acc,
[curr.ssid || ""]: { ssid: curr.ssid, password: curr.password }, [curr.ssid || ""]: { ssid: curr.ssid, password: curr.password },
}), }),
{} {},
); );
console.log("submitting", values, networks); console.log("submitting", values, networks);