lib/values: fix submodule definition merging

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

View File

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

View File

@@ -40,7 +40,7 @@ export const MachineListItem = (props: MachineListItemProps) => {
}
if (!info?.deploy?.targetHost) {
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;
}
@@ -63,7 +63,7 @@ export const MachineListItem = (props: MachineListItemProps) => {
loading: "Installing...",
success: "Installed",
error: "Failed to install",
}
},
);
setInstalling(false);
};
@@ -80,7 +80,7 @@ export const MachineListItem = (props: MachineListItemProps) => {
}
if (!info?.deploy.targetHost) {
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;
}
@@ -101,7 +101,7 @@ export const MachineListItem = (props: MachineListItemProps) => {
loading: "Updating...",
success: "Updated",
error: "Failed to update",
}
},
);
setUpdating(false);
};

View File

@@ -65,7 +65,7 @@ const InstallMachine = (props: InstallMachineProps) => {
}
const loading_toast = toast.loading(
"Installing machine. Grab coffee (15min)..."
"Installing machine. Grab coffee (15min)...",
);
const r = await callApi("install_machine", {
opts: {
@@ -248,13 +248,13 @@ const MachineForm = (props: MachineDetailsProps) => {
...values.machine,
// TODO: Remove this workaround
tags: Array.from(
values.machine.tags || props.initialData.machine.tags || []
values.machine.tags || props.initialData.machine.tags || [],
),
},
});
if (machine_response.status === "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") {
@@ -455,7 +455,7 @@ const MachineForm = (props: MachineDetailsProps) => {
// disabled={!online()}
onClick={() => {
const modal = document.getElementById(
"install_modal"
"install_modal",
) as HTMLDialogElement | null;
modal?.showModal();
}}
@@ -561,7 +561,7 @@ function WifiModule(props: MachineWifiProps) {
});
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) => {
@@ -572,7 +572,7 @@ function WifiModule(props: MachineWifiProps) {
...acc,
[curr.ssid || ""]: { ssid: curr.ssid, password: curr.password },
}),
{}
{},
);
console.log("submitting", values, networks);