1testModuleArgs@{ config, lib, hostPkgs, nodes, ... }:
2
3let
4 inherit (lib)
5 literalExpression
6 literalMD
7 mapAttrs
8 mkDefault
9 mkIf
10 mkOption mkForce
11 optional
12 optionalAttrs
13 types
14 ;
15
16 inherit (hostPkgs) hostPlatform;
17
18 guestSystem =
19 if hostPlatform.isLinux
20 then hostPlatform.system
21 else
22 let
23 hostToGuest = {
24 "x86_64-darwin" = "x86_64-linux";
25 "aarch64-darwin" = "aarch64-linux";
26 };
27
28 supportedHosts = lib.concatStringsSep ", " (lib.attrNames hostToGuest);
29
30 message =
31 "NixOS Test: don't know which VM guest system to pair with VM host system: ${hostPlatform.system}. Perhaps you intended to run the tests on a Linux host, or one of the following systems that may run NixOS tests: ${supportedHosts}";
32 in
33 hostToGuest.${hostPlatform.system} or (throw message);
34
35 baseOS =
36 import ../eval-config.nix {
37 inherit lib;
38 system = null; # use modularly defined system
39 inherit (config.node) specialArgs;
40 modules = [ config.defaults ];
41 baseModules = (import ../../modules/module-list.nix) ++
42 [
43 ./nixos-test-base.nix
44 { key = "nodes"; _module.args.nodes = config.nodesCompat; }
45 ({ config, ... }:
46 {
47 virtualisation.qemu.package = testModuleArgs.config.qemu.package;
48 virtualisation.host.pkgs = hostPkgs;
49 })
50 ({ options, ... }: {
51 key = "nodes.nix-pkgs";
52 config = optionalAttrs (!config.node.pkgsReadOnly) (
53 mkIf (!options.nixpkgs.pkgs.isDefined) {
54 # TODO: switch to nixpkgs.hostPlatform and make sure containers-imperative test still evaluates.
55 nixpkgs.system = guestSystem;
56 }
57 );
58 })
59 testModuleArgs.config.extraBaseModules
60 ];
61 };
62
63
64in
65
66{
67
68 options = {
69 node.type = mkOption {
70 type = types.raw;
71 default = baseOS.type;
72 internal = true;
73 };
74
75 nodes = mkOption {
76 type = types.lazyAttrsOf config.node.type;
77 visible = "shallow";
78 description = ''
79 An attribute set of NixOS configuration modules.
80
81 The configurations are augmented by the [`defaults`](#test-opt-defaults) option.
82
83 They are assigned network addresses according to the `nixos/lib/testing/network.nix` module.
84
85 A few special options are available, that aren't in a plain NixOS configuration. See [Configuring the nodes](#sec-nixos-test-nodes)
86 '';
87 };
88
89 defaults = mkOption {
90 description = ''
91 NixOS configuration that is applied to all [{option}`nodes`](#test-opt-nodes).
92 '';
93 type = types.deferredModule;
94 default = { };
95 };
96
97 extraBaseModules = mkOption {
98 description = ''
99 NixOS configuration that, like [{option}`defaults`](#test-opt-defaults), is applied to all [{option}`nodes`](#test-opt-nodes) and can not be undone with [`specialisation.<name>.inheritParentConfig`](https://search.nixos.org/options?show=specialisation.%3Cname%3E.inheritParentConfig&from=0&size=50&sort=relevance&type=packages&query=specialisation).
100 '';
101 type = types.deferredModule;
102 default = { };
103 };
104
105 node.pkgs = mkOption {
106 description = ''
107 The Nixpkgs to use for the nodes.
108
109 Setting this will make the `nixpkgs.*` options read-only, to avoid mistakenly testing with a Nixpkgs configuration that diverges from regular use.
110 '';
111 type = types.nullOr types.pkgs;
112 default = null;
113 defaultText = literalMD ''
114 `null`, so construct `pkgs` according to the `nixpkgs.*` options as usual.
115 '';
116 };
117
118 node.pkgsReadOnly = mkOption {
119 description = ''
120 Whether to make the `nixpkgs.*` options read-only. This is only relevant when [`node.pkgs`](#test-opt-node.pkgs) is set.
121
122 Set this to `false` when any of the [`nodes`](#test-opt-nodes) needs to configure any of the `nixpkgs.*` options. This will slow down evaluation of your test a bit.
123 '';
124 type = types.bool;
125 default = config.node.pkgs != null;
126 defaultText = literalExpression ''node.pkgs != null'';
127 };
128
129 node.specialArgs = mkOption {
130 type = types.lazyAttrsOf types.raw;
131 default = { };
132 description = ''
133 An attribute set of arbitrary values that will be made available as module arguments during the resolution of module `imports`.
134
135 Note that it is not possible to override these from within the NixOS configurations. If you argument is not relevant to `imports`, consider setting {option}`defaults._module.args.<name>` instead.
136 '';
137 };
138
139 nodesCompat = mkOption {
140 internal = true;
141 description = ''
142 Basically `_module.args.nodes`, but with backcompat and warnings added.
143
144 This will go away.
145 '';
146 };
147 };
148
149 config = {
150 _module.args.nodes = config.nodesCompat;
151 nodesCompat =
152 mapAttrs
153 (name: config: config // {
154 config = lib.warnIf (lib.isInOldestRelease 2211)
155 "Module argument `nodes.${name}.config` is deprecated. Use `nodes.${name}` instead."
156 config;
157 })
158 config.nodes;
159
160 passthru.nodes = config.nodesCompat;
161
162 defaults = mkIf config.node.pkgsReadOnly {
163 nixpkgs.pkgs = config.node.pkgs;
164 imports = [ ../../modules/misc/nixpkgs/read-only.nix ];
165 };
166
167 };
168}