Module system improvements for NixOS as a submodule#75031
Module system improvements for NixOS as a submodule#75031infinisil merged 8 commits intoNixOS:masterfrom
Conversation
This will be useful for doing more complicated module evaluations
Because why not
8384fe7 to
7f9a0ef
Compare
|
I wonder if this changes #70638 |
|
@domenkozar Very relevant issue indeed! While this PR doesn't change that behavior, it does allow you to turn it off for specific submodules by replacing This |
|
Some more documentation will be helpful. |
|
This is nice. Finally a coment left by @nbp makes sense. Here I've tried to apply this I've also made the needed adjustments to As for performance, everything is not better than before. I've collected stats, and found out that instantiation is worse than before: Maybe I made a mistake somewhere? |
|
@danbst After investigating, it seems to have to do with the manual. Before your change with defaulting After your change also with Patch to disable documentation: diff --git a/nixos/modules/misc/documentation.nix b/nixos/modules/misc/documentation.nix
index deecb005270..28f686e2ad8 100644
--- a/nixos/modules/misc/documentation.nix
+++ b/nixos/modules/misc/documentation.nix
@@ -74,7 +74,7 @@ in
enable = mkOption {
type = types.bool;
- default = true;
+ default = false;
description = ''
Whether to install documentation of packages from
<option>environment.systemPackages</option> into the generated system path.Also, trying to actually build the manual with the changes, I get This probably comes from the fact that the mkOption { default = pkgs.foo; } to not refer to pkgs.foo), and that module seems to cause the slowdown in general too. I have a feeling that potentially also all NixOS options are duplicated in the manual in containers.<name?>.*.
|
|
@infinisil However it is still of same performance as previous approach. It uses same amount of memory. I doubt now if it had previously used O(n²) time to instantiate n machines. From my experiments it seems to be linear, with both approaches. Though it is much cleaner API (for containers example), which is nice! |
|
@danbst Ah yeah, the |
|
@danbst Looking it into your container rewrite a bit more, I figured out some problems:
You can then do something like this to get it to work with the same performance as before (the first xml docs patch shouldn't be necessary anymore once the second point above is done): diff --git a/nixos/doc/manual/administration/declarative-containers.xml b/nixos/doc/manual/administration/declarative-containers.xml
index d03dbc4d705..8cff2c97c3a 100644
--- a/nixos/doc/manual/administration/declarative-containers.xml
+++ b/nixos/doc/manual/administration/declarative-containers.xml
@@ -33,9 +33,9 @@ containers.database =
follows:
<programlisting>
containers.database = {
- <link linkend="opt-containers._name_.privateNetwork">privateNetwork</link> = true;
- <link linkend="opt-containers._name_.hostAddress">hostAddress</link> = "192.168.100.10";
- <link linkend="opt-containers._name_.localAddress">localAddress</link> = "192.168.100.11";
+ privateNetwork = true;
+ hostAddress = "192.168.100.10";
+ localAddress = "192.168.100.11";
};
</programlisting>
This gives the container a private virtual Ethernet interface with IP address
diff --git a/nixos/modules/misc/documentation.nix b/nixos/modules/misc/documentation.nix
index deecb005270..8445b75f6bb 100644
--- a/nixos/modules/misc/documentation.nix
+++ b/nixos/modules/misc/documentation.nix
@@ -20,7 +20,10 @@ let
options =
let
scrubbedEval = evalModules {
- modules = [ { nixpkgs.localSystem = config.nixpkgs.localSystem; } ] ++ manualModules;
+ modules = [ {
+ nixpkgs.localSystem = config.nixpkgs.localSystem;
+ documentation.isDocumentationEval = true;
+ } ] ++ manualModules;
args = (config._module.args) // { modules = [ ]; };
specialArgs = { pkgs = scrubDerivations "pkgs" pkgs; };
};
@@ -84,6 +87,15 @@ in
# which is at ../../../doc/multiple-output.xml
};
+ isDocumentationEval = mkOption {
+ type = types.bool;
+ default = false;
+ internal = true;
+ description = ''
+ Whether this module system evaluation is purely to get an options listing
+ '';
+ };
+
man.enable = mkOption {
type = types.bool;
default = true;
diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix
index bbeebdb9db8..8a755e872ff 100644
--- a/nixos/modules/virtualisation/containers.nix
+++ b/nixos/modules/virtualisation/containers.nix
@@ -635,6 +635,7 @@ in
type = types.attrsOf (types.fullSubmodule {
modules = [ containerDefaults containerParamsModule ] ++ baseModules;
specialArgs.modulesPath = builtins.toString ../.;
+ hideSubOptions = config.documentation.isDocumentationEval;
});
default = {};
example = literalExampleEdit: Instead of 571c7da, it would also be possible to inline this type modification into the container module, but that gets ugly because of |
|
@infinisil what about this danbst@cd74159 ? This solves the containers options problems. I have just verified that generated manual includes only extra options. BTW, I've just recalled that submodule types are mergeable. #24653 (comment) for insights. I wonder if |
|
@danbst I think separating the container options from NixOS options is cleaner, because they're like on a higher level than just a standard NixOS configuration. Similarly I'd like for nixops to not use |
093768c to
6e521fa
Compare
|
Pushed code with @roberth's suggestions and rebased for a clean history. I'll do some final tests with this and if it looks good to both of you too, this should be ready to merge. |
|
Great work! |
This has the beneficial side effect of allowing paths to be used as modules in
types.{submodule,submoduleWith}
ea7ef12 to
a2e42df
Compare
|
Changes:
From my side this is ready to be merged now! |
roberth
left a comment
There was a problem hiding this comment.
Found a documentation improvement (see review comment) and a question/idea.
I was thinking about the difference between options.x = submoduleWith { modules } and config.x = modules.
Did you or @danbst try hiding option docs by adding them through a config definition instead of the modules parameter?
I haven't checked this, but assuming you can use option priority (mkForce etc) to override the set of config modules, that may be a reason to pick the one or the other.
Perhaps these questions can also be addressed in the documentation.
|
Ah yes that does work, confirmed with this: Details{ lib, ... }: {
options.test = lib.mkOption {
type = lib.types.submoduleWith {
modules = [{
options.foo = lib.mkOption {};
}];
};
};
config = {
test.options.bar = lib.mkOption {};
documentation.nixos.includeAllModules = true;
boot.loader.grub.device = "nodev";
fileSystems."/".device = "test";
};
}$ cat $(nix-build nixos --arg configuration ./config.nix -A config.system.build.manual.optionsJSON)/share/doc/nixos/options.json | grep test.barBut yeah the fact that modules defined in the |
Module arguments should be taken from the arguments directly. This allows evalModule's specialArgs to override them if necessary
a2e42df to
cc81320
Compare
|
@roberth Done did that |
This fixes the dhcpcd issue in NixOS#76969, which was exposed by NixOS#75031 introducing changes in the module ordering and therefore option ordering too. The dhcpcd issue would also be fixable by explicitly putting dhcpcd's paths before others, however it makes more sense for systemd's default paths to be after all others by default, since they should only be a fallback, which is how binary finding will work if they come after.
This fixes the dhcpcd issue in NixOS#76969, which was exposed by NixOS#75031 introducing changes in the module ordering and therefore option ordering too. The dhcpcd issue would also be fixable by explicitly putting dhcpcd's paths before others, however it makes more sense for systemd's default paths to be after all others by default, since they should only be a fallback, which is how binary finding will work if they come after. (cherry picked from commit 9327e1c)
Motivation for this change
All these changes are there to allow NixOS to be used as submodule, which I'm doing tests with right now. This will allow things like:
Ping @Profpatsch @rycee @kreisys @nbp @edolstra @oxij @danbst @roberth
Best reviewed commit by commit
Things done
submoduleWithfullSubmodule-> Now namedsubmoduleWithconfigDefault-> Now namedshorthandOnlyDefinesConfigshorthandOnlyDefinesConfigdoes -> It's in the docsFor idempotentNothing needs this behavior directly, so no tests necessaryunifyModuleSyntaxsubmoduleWithtestedset gives smaller numbers for all valuesMaybe deprecateRemoving them seems fine, it's really just an artifact from the module system implementation, there never should've been a need to expose this anyways.packSubmoduleandunpackSubmoduleinstead of removing, though they very very likely aren't used in the wild, so probably not worth keeping them aroundtestedset evaluates still