nixops
nixops copied to clipboard
eval-machine-info.nix: ported to modules
Fixes https://github.com/NixOS/nixops/issues/1486 Done:
- [X] Made
requires
an error. - [X] Implemented the
nodes
option. - [X] Made a fallback for the old way of writing nodes to the
- [X] Added
network.nodesExtraArgs
To do: - [ ] Implemented all
resources
options - [x] Implemented all
network
options - [x] Tested it
- [ ] Wire up the NixOS
assertions
andwarnings
- [ ] Declare lock and storage with plugin (assigned @roberth)
Heads up about the resources; just a merged a PR that touches that.
what pr @roberth ?
https://github.com/NixOS/nixops/pull/1506
So do I have to rebase on master?
Ok I did rebase on master
Ok I've tried and failed to build a network, it goes in infinite recursion while evaluating scrubOptionValues
in info.machines
It still goes in infinite recursion, I need to know what nixops expects exactly from this file and what can be safely removed.
it goes in infinite recursion
Maybe the attrsOf
s need to be lazyAttrsOf
s.
attrsOf
can only return its attrset by inspecting the children for mkIf false
values and filtering out those attributes. That makes it more strict than lazyAttrsOf
, which will return the spine of the attribute set (attr names + thunks) without inspecting those thunks.
I need to know what nixops expects exactly
I don't expect this to be documented anywhere.
I need to know what nixops expects exactly
I don't expect this to be documented anywhere.
I don't need to be fully documented,only to tell me what the nixops cli and plugins take from the eval-machine-info.nix
file right now. If, after merging this, you go and change that I would not care abut it.
it goes in infinite recursion
Maybe the
attrsOf
s need to belazyAttrsOf
s.attrsOf
can only return its attrset by inspecting the children formkIf false
values and filtering out those attributes. That makes it more strict thanlazyAttrsOf
, which will return the spine of the attribute set (attr names + thunks) without inspecting those thunks.
Tried with lazyAttrsOf
but it still gives me the same problems.
Ok it was an error on my part, I forgot network.nodesExtraArgs = { inherit inputs; };
in my config. 🤦🤦🤦🤦
Ok now the error I get is
; nixops list
error: The option `resources' is used but not defined.
Which I don't know where even to begin
; nixops list error: The option `resources' is used but not defined.
Just add a default = { };
to the resources
option.
It's some silly ux :/
Ok latest error is definetly on the python side
; nixops list
def-matcher: command not found
Traceback (most recent call last):
File "/nix/store/nbrhfv3wcdsiish3y3k64jgs9826k2xc-python3.8-nixops-2.0.0/bin/.nixops-wrapped", line 9, in <module>
sys.exit(main())
File "/nix/store/nbrhfv3wcdsiish3y3k64jgs9826k2xc-python3.8-nixops-2.0.0/lib/python3.8/site-packages/nixops/__main__.py", line 56, in main
args.op(args)
File "/nix/store/nbrhfv3wcdsiish3y3k64jgs9826k2xc-python3.8-nixops-2.0.0/lib/python3.8/site-packages/nixops/script_defs.py", line 200, in op_list_deployments
depl.evaluate()
File "/nix/store/nbrhfv3wcdsiish3y3k64jgs9826k2xc-python3.8-nixops-2.0.0/lib/python3.8/site-packages/nixops/deployment.py", line 431, in evaluate
self.evaluate_network()
File "/nix/store/nbrhfv3wcdsiish3y3k64jgs9826k2xc-python3.8-nixops-2.0.0/lib/python3.8/site-packages/nixops/deployment.py", line 423, in evaluate_network
self.description = config.get("description", self.default_description)
File "/nix/store/nbrhfv3wcdsiish3y3k64jgs9826k2xc-python3.8-nixops-2.0.0/lib/python3.8/site-packages/nixops/util.py", line 493, in set
self._set_attr(name, x)
File "/nix/store/nbrhfv3wcdsiish3y3k64jgs9826k2xc-python3.8-nixops-2.0.0/lib/python3.8/site-packages/nixops/deployment.py", line 250, in _set_attr
self._set_attrs({name: value})
File "/nix/store/nbrhfv3wcdsiish3y3k64jgs9826k2xc-python3.8-nixops-2.0.0/lib/python3.8/site-packages/nixops/deployment.py", line 243, in _set_attrs
c.execute(
sqlite3.OperationalError: attempt to write a readonly database
sqlite3.OperationalError: attempt to write a readonly database
This is a known issue. https://github.com/NixOS/nixops/issues/1490
At this time, nixops deploy
is more suitable for testing, as this command does request write access to the db.
; nixops deploy
def-matcher: command not found
flatwoody> generating new SSH key pair... done
Password:
flatwoody> setting state version to 22.05
flatwoody> waiting for SSH...
building all machine configurations...
trace: warning: Please use the actual nodes.* option instead of assigning machines to the config's top level
error: 'flatwoody' at /tmp/nixops-tmpnvee6p43/physical.nix:2:15 called without required argument 'pkgs'
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/types.nix:199:25:
198| file = def.file;
199| value = def.value arg;
| ^
200| }) defs);
… while evaluating the attribute 'value'
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/types.nix:199:17:
198| file = def.file;
199| value = def.value arg;
| ^
200| }) defs);
… while evaluating 'getType'
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/types.nix:171:21:
170| let
171| getType = value:
| ^
172| if isAttrs value && isCoercibleToString value
… from call site
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/types.nix:179:16:
178| commonType = foldl' (type: def:
179| if getType def.value == type
| ^
180| then type
… while evaluating anonymous lambda
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/types.nix:178:38:
177| # don't have the same type
178| commonType = foldl' (type: def:
| ^
179| if getType def.value == type
… from call site
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/types.nix:178:24:
177| # don't have the same type
178| commonType = foldl' (type: def:
| ^
179| if getType def.value == type
… while evaluating 'merge'
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/types.nix:169:20:
168| check = value: true;
169| merge = loc: defs:
| ^
170| let
… from call site
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/types.nix:195:38:
194| stringCoercibleSet = mergeOneOption;
195| lambda = loc: defs: arg: anything.merge
| ^
196| (loc ++ [ "<function body>" ])
… while evaluating 'lambda'
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/types.nix:195:33:
194| stringCoercibleSet = mergeOneOption;
195| lambda = loc: defs: arg: anything.merge
| ^
196| (loc ++ [ "<function body>" ])
… from call site
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/types.nix:530:46:
529| coerce = unify: value: if isFunction value
530| then setFunctionArgs (args: unify (value args)) (functionArgs value)
| ^
531| else unify (if shorthandOnlyDefinesConfig then { config = value; } else value);
… while evaluating 'unifyModuleSyntax'
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/modules.nix:343:34:
342| of ‘options’, ‘config’ and ‘imports’ attributes. */
343| unifyModuleSyntax = file: key: m:
| ^
344| let
… from call site
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/types.nix:530:39:
529| coerce = unify: value: if isFunction value
530| then setFunctionArgs (args: unify (value args)) (functionArgs value)
| ^
531| else unify (if shorthandOnlyDefinesConfig then { config = value; } else value);
… while evaluating anonymous lambda
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/types.nix:530:33:
529| coerce = unify: value: if isFunction value
530| then setFunctionArgs (args: unify (value args)) (functionArgs value)
| ^
531| else unify (if shorthandOnlyDefinesConfig then { config = value; } else value);
… from call site
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/modules.nix:397:8:
396| # works.
397| in f (args // extraArgs)
| ^
398| else
… while evaluating 'applyIfFunction'
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/modules.nix:373:29:
372|
373| applyIfFunction = key: f: args@{ config, options, lib, ... }: if isFunction f then
| ^
374| let
… from call site
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/modules.nix:272:55:
271| if isFunction m || isAttrs m then
272| unifyModuleSyntax fallbackFile fallbackKey (applyIfFunction fallbackKey m args)
| ^
273| else if isList m then
… while evaluating 'unifyModuleSyntax'
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/modules.nix:343:34:
342| of ‘options’, ‘config’ and ‘imports’ attributes. */
343| unifyModuleSyntax = file: key: m:
| ^
344| let
… from call site
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/modules.nix:272:11:
271| if isFunction m || isAttrs m then
272| unifyModuleSyntax fallbackFile fallbackKey (applyIfFunction fallbackKey m args)
| ^
273| else if isList m then
… while evaluating 'loadModule'
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/modules.nix:270:53:
269| # Like unifyModuleSyntax, but also imports paths and calls functions if necessary
270| loadModule = args: fallbackFile: fallbackKey: m:
| ^
271| if isFunction m || isAttrs m then
… from call site
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/modules.nix:311:22:
310| let
311| module = loadModule args parentFile "${parentKey}:anon-${toString n}" x;
| ^
312| collectedImports = collectStructuredModules module._file module.key module.imports args;
… while evaluating anonymous lambda
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/modules.nix:328:31:
327| disabledKeys = map moduleKey disabled;
328| keyFilter = filter (attrs: ! elem attrs.key disabledKeys);
| ^
329| in map (attrs: attrs.module) (builtins.genericClosure {
… from call site
… while evaluating 'filterModules'
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/modules.nix:324:36:
323| # modules recursively. It returns the final list of unique-by-key modules
324| filterModules = modulesPath: { disabled, modules }:
| ^
325| let
… from call site
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/modules.nix:335:7:
334| in modulesPath: initialModules: args:
335| filterModules modulesPath (collectStructuredModules unknownModule "" initialModules args);
| ^
336|
… while evaluating anonymous lambda
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/modules.nix:334:37:
333|
334| in modulesPath: initialModules: args:
| ^
335| filterModules modulesPath (collectStructuredModules unknownModule "" initialModules args);
… from call site
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/modules.nix:180:25:
179| merged =
180| let collected = collectModules
| ^
181| (specialArgs.modulesPath or "")
… while evaluating 'reverseList'
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/lists.nix:393:17:
392| */
393| reverseList = xs:
| ^
394| let l = length xs; in genList (n: elemAt xs (l - n - 1)) l;
… from call site
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/modules.nix:184:33:
183| ({ inherit lib options config specialArgs; } // specialArgs);
184| in mergeModules prefix (reverseList collected);
| ^
185|
… while evaluating 'byName'
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/modules.nix:449:25:
448| */
449| byName = attr: f: modules:
| ^
450| zipAttrsWith (n: concatLists)
… from call site
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/modules.nix:466:21:
465| # an attrset 'name' => list of submodules that declare ‘name’.
466| declsByName = byName "options" (module: option:
| ^
467| [{ inherit (module) _file; options = option; }]
… while evaluating the attribute 'matchedOptions'
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/modules.nix:510:14:
509| in {
510| inherit matchedOptions;
| ^
511|
… while evaluating 'mapAttrsRecursiveCond'
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/attrsets.nix:296:36:
295| */
296| mapAttrsRecursiveCond = cond: f: set:
| ^
297| let
… from call site
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/modules.nix:192:28:
191| # For definitions that have an associated option
192| declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options;
| ^
193|
… while evaluating the attribute 'config'
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/modules.nix:257:9:
256| options = checked options;
257| config = checked (removeAttrs config [ "_module" ]);
| ^
258| _module = checked (config._module);
… while evaluating 'merge'
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/types.nix:569:22:
568| check = x: isAttrs x || isFunction x || path.check x;
569| merge = loc: defs:
| ^
570| (base.extendModules {
… from call site
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/modules.nix:649:59:
648| if isDefined then
649| if all (def: type.check def.value) defsFinal then type.merge loc defsFinal
| ^
650| else let allInvalid = filter (def: ! type.check def.value) defsFinal;
… while evaluating the attribute 'value'
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/modules.nix:660:27:
659| optionalValue =
660| if isDefined then { value = mergedValue; }
| ^
661| else {};
… while evaluating anonymous lambda
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/lib/types.nix:413:22:
412| merge = loc: defs:
413| mapAttrs (n: v: v.value) (filterAttrs (n: v: v ? value) (zipAttrsWith (name: defs:
| ^
414| (mergeDefinitions (loc ++ [name]) elemType defs).optionalValue
… from call site
… while evaluating the attribute 'config.system.build.toplevel'
at /nix/store/kxlj5h6jss1szi1rs0lkccggr18g0lza-python3.8-nixops-2.0.0/lib/python3.8/site-packages/nix/eval-machine-info.nix:161:32:
160| #TODO: take options and auter modules outputs for each node
161| nodes = lib.mapAttrs (n: v: {config = v;}) net.config.nodes;
| ^
162|
… while evaluating anonymous lambda
at /nix/store/kxlj5h6jss1szi1rs0lkccggr18g0lza-python3.8-nixops-2.0.0/lib/python3.8/site-packages/nix/eval-machine-info.nix:309:54:
308| mkdir -p $out
309| ${toString (lib.attrValues (lib.mapAttrs (n: v: ''
| ^
310| ln -s ${v.config.system.build.toplevel} $out/${n}
… from call site
… while evaluating the attribute 'buildCommand' of the derivation 'nixops-machines'
at /nix/store/531v6sf2db04x3xqphfkh7zg2dgw135k-source/pkgs/stdenv/generic/make-derivation.nix:205:7:
204| // (lib.optionalAttrs (attrs ? name || (attrs ? pname && attrs ? version)) {
205| name =
| ^
206| let
error: evaluation of the deployment specification failed
Where it would ask for a pkgs param?
The error seems to originate from the "physical" expression that's generated by nixops. You can see that expression with nixops show-physical
.
; nixops show-physical
def-matcher: command not found
Traceback (most recent call last):
File "/nix/store/3y06h6hsw56r0bszn9pl7cdpz91qjbh1-python3.8-nixops-2.0.0/bin/.nixops-wrapped", line 9, in <module>
sys.exit(main())
File "/nix/store/3y06h6hsw56r0bszn9pl7cdpz91qjbh1-python3.8-nixops-2.0.0/lib/python3.8/site-packages/nixops/__main__.py", line 56, in main
args.op(args)
File "/nix/store/3y06h6hsw56r0bszn9pl7cdpz91qjbh1-python3.8-nixops-2.0.0/lib/python3.8/site-packages/nixops/script_defs.py", line 813, in op_show_physical
depl.evaluate()
File "/nix/store/3y06h6hsw56r0bszn9pl7cdpz91qjbh1-python3.8-nixops-2.0.0/lib/python3.8/site-packages/nixops/deployment.py", line 431, in evaluate
self.evaluate_network()
File "/nix/store/3y06h6hsw56r0bszn9pl7cdpz91qjbh1-python3.8-nixops-2.0.0/lib/python3.8/site-packages/nixops/deployment.py", line 423, in evaluate_network
self.description = config.get("description", self.default_description)
File "/nix/store/3y06h6hsw56r0bszn9pl7cdpz91qjbh1-python3.8-nixops-2.0.0/lib/python3.8/site-packages/nixops/util.py", line 493, in set
self._set_attr(name, x)
File "/nix/store/3y06h6hsw56r0bszn9pl7cdpz91qjbh1-python3.8-nixops-2.0.0/lib/python3.8/site-packages/nixops/deployment.py", line 250, in _set_attr
self._set_attrs({name: value})
File "/nix/store/3y06h6hsw56r0bszn9pl7cdpz91qjbh1-python3.8-nixops-2.0.0/lib/python3.8/site-packages/nixops/deployment.py", line 243, in _set_attrs
c.execute(
sqlite3.OperationalError: attempt to write a readonly database
https://github.com/NixOS/nixops/issues/1490 strikes again☹
#1490 strikes againfrowning_face
https://github.com/NixOS/nixops/pull/1511 should work around it.
; nixops show-physical
def-matcher: command not found
{
flatwoody = { config, lib, pkgs, ... }: {
config = {
boot.kernelModules = [];
networking = { extraHosts = "\n"; firewall.trustedInterfaces = []; };
system.stateVersion = ( lib.mkDefault "22.05" );
};
imports = [
{
config.users.extraUsers.root.openssh.authorizedKeys.keys = [
"ssh-ed25519 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX NixOps client key for flatwoody"
];
}
];
};
}
The worst thing is that pkgs
is not even used …
It seems that the "physical" expression is using the legacy format compatibility which isn't working correctly.
trace: warning: Please use the actual nodes.* option instead of assigning machines to the config's top level
It seems that the "physical" expression is using the legacy format compatibility which isn't working correctly.
trace: warning: Please use the actual nodes.* option instead of assigning machines to the config's top level
No, I just have written the warning incorrectly
It seems that the "physical" expression is using the legacy format compatibility which isn't working correctly.
trace: warning: Please use the actual nodes.* option instead of assigning machines to the config's top level
No, I just have written the warning incorrectly
To pick out the legacy nodes from the freeformtype more easily, you can postcompose a function that puts the all the freeform stuff in a separate attribute.
Here's what that looks like (crux: freeformItems
), although it shouldn't use // { merge = ... }
.
https://github.com/NixOS/nixpkgs/pull/163597/files#diff-619679c9f04a185497c93f14a481d1fe65cc75298f422169128a902ba907ffa2
It'd be better to use a copy of postTransform
(https://github.com/NixOS/nixpkgs/pull/163601) instead of // { merge = ... }
.
Using your proposed deferredModule
instead of anything
in freeformType
will give me:
; nixops create -n net.nix
def-matcher: command not found
WARNING: NixOps 1.0 -> 2.0 conversion step required
NixOps 2.0 added support for multiple storage backends.
Upgrade steps:
1. Open /home/me/src/my-nixos-conf
2. Add:
network.storage.legacy = {
databasefile = "~/.nixops/deployments.nixops";
};
3. Rerun
See https://nixops.readthedocs.io/en/latest/manual/migrating.html#state-location for more guidance.
I suspect other storage backends would have similar problems as they would not be written with modules in mind.
Even after making defaults.type = deferredModules
it still does the same error.
Where is the code evaluating physical.nix
?