Open pasqui23 opened 2 years ago
Heads up about the resources; just a merged a PR that touches that.
what pr @roberth ?
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
?
Where is the code evaluating
physical.nix
?
Roughly here it seems https://github.com/NixOS/nixops/blob/9b3ac919d87db872854fb528064821b959ac38c1/nixops/deployment.py#L639-L660
I suspect other storage backends would have similar problems as they would not be written with modules in mind.
Probably the network
attr is treated as a legacy node instead of options?
Probably the
network
attr is treated as a legacy node instead of options?
What do you mean? nodes = removeAttrs config (builtins.attrNames options);
was written specifically to remove network
and other from the legacy nodes.
However the network.storage.legacy
,as it is not defined by our config, it fall through to freeformType
and gets merged as [{storage.legacy=...;}]
.
Again without actual options to configure the storage options it still would not be merged without the anything
type.
Where is the code evaluating
physical.nix
?Roughly here it seems
That is the part that seems to generate the file. I mean what part in the nixops deploy
command that runs nix-instantiate
with the generated physical.nix
?
nix-instantiate
That'd be nixops/evaluation.py
However the
network.storage.legacy
,as it is not defined by our config, it fall through tofreeformType
and gets merged as[{storage.legacy=...;}]
. Again without actual options to configure the storage options it still would not be merged without theanything
type.
I don't think I fully understand this problem as it relates to the code. Did you intend to rename this option?
Perhaps you could define only storage
as an empty submodule with an anything
freeformType
?
Sorry if I can only throw ideas at you now. I'll have a more thorough look later.
Perhaps you could define only
storage
as an empty submodule with ananything
freeformType
?
Tried that but I get:
; nixops create -n net.nix
error: The option `network.storage' is used but not defined.
And yes adding default ={}
did not solve it.
Ok I've only tested it as the world's worst replacement for nixos-rebuild
but it works!
@roberth is there anything I have to do change about this pr?
Also when I try to deploy my test it always ask me for password even if deployment.provisionSSHKey
is defaulted to true. Is that related to https://github.com/NixOS/nixops/issues/1429 ?
Hi @pasqui23,
I've tried your PR and made some followup changes in #1515 (and accidentally pushed here; reverted that)
Also when I try to deploy my test it always ask me for password even if
deployment.provisionSSHKey
is defaulted to true. Is that related to #1429 ?
I don't know. Did you try without this PR? It's possible that recent changes to ssh flags handling haven't been fixed completely yet. #1464 (ssh keys for remote state) caused #1493 and subsequently #1509.
is there anything I have to do change about this pr?
I will test it some more and see if can find anything else. Perhaps you could review my additions in #1515?
I don't know. Did you try without this PR?
I can't, my config relies on networking.nodesExtraArgs
@roberth I've added a simplified way to define resources with defineResources
.
ok updated to only single import.
@roberth What do you think about defineResource
?
@roberth also why don't we contribute both on this branch instead of duplicating the work?
ok updated to only single import. @roberth What do you think about
defineResource
?
That looks really useful. Defining one was a little cumbersome. DRY-ing this also puts the nixops core in charge of precisely how resources are defined, which might prove useful one day.
@roberth also why don't we contribute both on this branch instead of duplicating the work?
:+1:
@roberth what is about that mypy-ratchet
failing test?
Fixes https://github.com/NixOS/nixops/issues/1486 Done:
requires
an error.nodes
option.network.nodesExtraArgs
To do:resources
optionsnetwork
optionsassertions
andwarnings