| 26 May 2022 |
David Arnold (blaggacao) | In my opinion, maintaining legacy nix support in-tree is a bit of a stretch and reduces the ability to innovate. Maby there can be a 2-tree solution that is not 100% mutually compatible | 19:23:47 |
David Arnold (blaggacao) | * In my opinion, maintaining legacy nix support in-tree is a bit of a stretch and reduces the ability to innovate. Maby there can be a 2-tree solution that is not 100% mutually compatible . | 19:24:05 |
David Arnold (blaggacao) | Looks like this iface should be enough, we could yants-ify it as it may become a (semi-public) contract:
in rec {
deploymentConfig = l.mapAttrs (name: eval: eval.config.deployment) nodes;
deploymentConfigSelected = names: listToAttrs (map (name: { inherit name; value = nodes.${name}.config.deployment; }) names);
evalAll = evalSelected nodeNames;
evalSelectedDrvPaths = names: l.mapAttrs (k: v: v.drvPath) (evalSelected names);
evalSelected = names: let selected = l.filterAttrs (name: _: elem name names) toplevel; in selected;
introspect = function: function { inherit nixpkgs lib; nodes = uncheckedNodes; };
nodes = listToAttrs (map (name: { inherit name; value = evalNode name (configsFor name); }) nodeNames);
toplevel = l.mapAttrs (name: eval: eval.config.system.build.toplevel) nodes;
}
| 21:46:33 |
David Arnold (blaggacao) | The actual inteface seems even less:
❯ rg 'hive\.(deploymentConfig|evalSelected|evalAll|nodes|toplevel|introspect)' src/nix/hive/mod.rs
257: self.nix_instantiate("attrNames hive.nodes").eval()
263: let configs: HashMap<NodeName, NodeConfig> = self.nix_instantiate("hive.deploymentConfig").eval_with_builders().await?
278: let expr = format!("hive.nodes.\"{}\".config.deployment or null", node.as_str());
287: let configs: HashMap<NodeName, NodeConfig> = self.nix_instantiate(&format!("hive.deploymentConfigSelected {}", nodes_expr.expression()))
309: let expr = format!("hive.evalSelectedDrvPaths {}", nodes_expr.expression());
339: let expression = format!("hive.introspect ({})", expression);
343: let expression = format!("toJSON (hive.introspect ({}))", expression);
480: "{} hive.evalSelected {}",
| 21:55:35 |
David Arnold (blaggacao) | I reduced the iface surface a little which seems to be pure cleanup refactoring since it doesn't break any tests... https://github.com/zhaofengli/colmena/pull/89 | 22:28:04 |
David Arnold (blaggacao) | ( the guiding principle has been: nothing except src/nix/hive/* should be allowed to consume the eval.nix contract) | 22:29:28 |
| 27 May 2022 |
David Arnold (blaggacao) | quick question: is unchecked module evaluation lazy? | 00:32:58 |
David Arnold (blaggacao) | Not sure if anyone noticed and I don't know how to explain properly due to the spaghetti, but this is actually the only place where the invoking system would bleed into the nixosConfiguration other than that, I beleive that system can be completely encapsulated into the configuration.
https://github.com/NixOS/nixpkgs/pull/174829
| 01:02:23 |
David Arnold (blaggacao) | And that would be the final cleanup to completely encapsulate instantiating nixpkgs within the config and would make things like meta.nixpkgs et al. not needed any more... | 01:03:31 |
David Arnold (blaggacao) | So I hope this new eval.nix would work, testing tomorrow, let me know if you have comments / ideas:
{ flakeUri # Nix Flake URI with `outputs.colmena`
, hermetic ? true # Whether we are allowed to use <nixpkgs>
, colmenaOptions
, colmenaModules
}: let
flake = builtins.getFlake flakeUri;
nixpkgs =
if builtins.hasAttr "nixpkgs" flake.inputs
then inputs.nixpkgs
else throw ''
In order to be able to use 'colmena', an input
named 'nixpkgs' must be defined in the flake.
'';
l = nixpkgs.lib // builtins;
in
# The final hive will always have the meta key instead of network.
# system.name.colmenaConfigurations.target
hive = let
op1 = l.filterAttrs (_: v: v ? colmenaConfigurations ); # contains colmena configs?
op2 = l.mapAttrs (n: v: v.colmenaConfigurations); # lift colmena configs one level up
op3 = l.mapAttrsToList (n: l.mapAttrs' (t: c: l.nameValuePair "${n}-${t}" c)); # prefix with cell name -> unique names
in
l.listToAttrs (l.flatten (op3 (op2 (op1 flake.x86_64-linux))));
evalPkgs = name: config: nixpkgs.lib.evalModules {
modules = [ config {_module.check = false;} {imports = [ "${nixpkgs}/nixos/misc/nixpkgs.nix" ];} ];
}.config.nixpkgs.pkgs;
evalNode = check: name: config: let
pkgs = evalPkgs name config;
evalConfig = import "${pkgs.path}/nixos/lib/eval-config.nix";
in evalConfig {
inherit (pkgs) system;
modules = [
colmenaModules.assertionModule
colmenaModules.keyChownModule
colmenaModules.keyServiceModule
colmenaOptions.deploymentOptions
config
{_module.check = check;}
];
specialArgs = {
inherit name;
nodes = evalNode false hive;
};
};
in rec {
# Exported attributes
#
# Functions are intended to be called with `nix-instantiate --eval --json`
nodes = l.mapAttrs (evalNode true) hive;
toplevel = l.mapAttrs (_: v: v.config.system.build.toplevel) nodes;
deploymentConfig = l.mapAttrs (_: v: v.config.deployment) nodes;
deploymentConfigSelected = names: l.filterAttrs (name: _: l.elem name names) deploymentConfig;
evalSelected = names: l.filterAttrs (name: _: l.elem name names) toplevel;
evalSelectedDrvPaths = names: l.mapAttrs (_: v: v.drvPath) (evalSelected names);
introspect = f: f { inherit nixpkgs; inherit (nixpkgs) lib; nodes = evalNode false hive; };
machinesFile = null;
}
| 01:23:51 |
David Arnold (blaggacao) | * So I hope this new eval.nix would work, testing tomorrow, let me know if you have comments / ideas:
{ flakeUri # Nix Flake URI with `outputs.colmena`
, hermetic ? true # Whether we are allowed to use <nixpkgs>
, colmenaOptions
, colmenaModules
}: let
flake = builtins.getFlake flakeUri;
nixpkgs =
if builtins.hasAttr "nixpkgs" flake.inputs
then inputs.nixpkgs
else throw ''
In order to be able to use 'colmena', an input
named 'nixpkgs' must be defined in the flake.
'';
l = nixpkgs.lib // builtins;
in
# The final hive will always have the meta key instead of network.
# system.name.colmenaConfigurations.target
hive = let
op1 = l.filterAttrs (_: v: v ? colmenaConfigurations ); # contains colmena configs?
op2 = l.mapAttrs (n: v: v.colmenaConfigurations); # lift colmena configs one level up
op3 = l.mapAttrsToList (n: l.mapAttrs' (t: c: l.nameValuePair "${n}-${t}" c)); # prefix with cell name -> unique names
in
l.listToAttrs (l.flatten (op3 (op2 (op1 flake.x86_64-linux))));
evalPkgs = name: config: nixpkgs.lib.nixos.evalModules {
modules = [ config {_module.check = false;} {imports = [ "${nixpkgs}/nixos/misc/nixpkgs.nix" ];} ];
}.config.nixpkgs.pkgs;
evalNode = check: name: config: let
pkgs = evalPkgs name config;
evalConfig = import "${pkgs.path}/nixos/lib/eval-config.nix";
in evalConfig {
inherit (pkgs) system;
modules = [
colmenaModules.assertionModule
colmenaModules.keyChownModule
colmenaModules.keyServiceModule
colmenaOptions.deploymentOptions
config
{_module.check = check;}
];
specialArgs = {
inherit name;
nodes = evalNode false hive;
};
};
in rec {
# Exported attributes
#
# Functions are intended to be called with `nix-instantiate --eval --json`
nodes = l.mapAttrs (evalNode true) hive;
toplevel = l.mapAttrs (_: v: v.config.system.build.toplevel) nodes;
deploymentConfig = l.mapAttrs (_: v: v.config.deployment) nodes;
deploymentConfigSelected = names: l.filterAttrs (name: _: l.elem name names) deploymentConfig;
evalSelected = names: l.filterAttrs (name: _: l.elem name names) toplevel;
evalSelectedDrvPaths = names: l.mapAttrs (_: v: v.drvPath) (evalSelected names);
introspect = f: f { inherit nixpkgs; inherit (nixpkgs) lib; nodes = evalNode false hive; };
machinesFile = null;
}
| 01:24:37 |
David Arnold (blaggacao) | If it's not hermetically defined in the config, I think this would then fall back to inputs.nixpkgs which is roughly what we want anyways. | 01:26:06 |
David Arnold (blaggacao) | * So I hope this new eval.nix would work, testing tomorrow, let me know if you have comments / ideas:
{ flakeUri # Nix Flake URI with `outputs.colmena`
, hermetic ? true # Whether we are allowed to use <nixpkgs>
, colmenaOptions
, colmenaModules
}: let
flake = builtins.getFlake flakeUri;
nixpkgs =
if builtins.hasAttr "nixpkgs" flake.inputs
then inputs.nixpkgs
else throw ''
In order to be able to use 'colmena', an input
named 'nixpkgs' must be defined in the flake.
'';
l = nixpkgs.lib // builtins;
in
# system.name.colmenaConfigurations.target
hive = let
op1 = l.filterAttrs (_: v: v ? colmenaConfigurations ); # contains colmena configs?
op2 = l.mapAttrs (n: v: v.colmenaConfigurations); # lift colmena configs one level up
op3 = l.mapAttrsToList (n: l.mapAttrs' (t: c: l.nameValuePair "${n}-${t}" c)); # prefix with cell name -> unique names
in
l.listToAttrs (l.flatten (op3 (op2 (op1 flake.x86_64-linux))));
evalPkgs = name: config: nixpkgs.lib.nixos.evalModules {
modules = [ config {_module.check = false;} {imports = [ "${nixpkgs}/nixos/misc/nixpkgs.nix" ];} ];
}.config.nixpkgs.pkgs;
evalNode = check: name: config: let
pkgs = evalPkgs name config;
evalConfig = import "${pkgs.path}/nixos/lib/eval-config.nix";
in evalConfig {
inherit (pkgs) system;
modules = [
colmenaModules.assertionModule
colmenaModules.keyChownModule
colmenaModules.keyServiceModule
colmenaOptions.deploymentOptions
config
{_module.check = check;}
];
specialArgs = {
inherit name;
nodes = evalNode false hive;
};
};
in rec {
# Exported attributes
#
# Functions are intended to be called with `nix-instantiate --eval --json`
nodes = l.mapAttrs (evalNode true) hive;
toplevel = l.mapAttrs (_: v: v.config.system.build.toplevel) nodes;
deploymentConfig = l.mapAttrs (_: v: v.config.deployment) nodes;
deploymentConfigSelected = names: l.filterAttrs (name: _: l.elem name names) deploymentConfig;
evalSelected = names: l.filterAttrs (name: _: l.elem name names) toplevel;
evalSelectedDrvPaths = names: l.mapAttrs (_: v: v.drvPath) (evalSelected names);
introspect = f: f { inherit nixpkgs; inherit (nixpkgs) lib; nodes = evalNode false hive; };
machinesFile = null;
}
| 01:26:50 |
David Arnold (blaggacao) | Zhaofeng Li: the collateral benefit to have this in-tree downstream (with hidden --eval flag):
- it's easy enough to read
- therefore, it's self documenting
| 01:31:15 |
David Arnold (blaggacao) | * Zhaofeng Li: the collateral benefit to have this in-tree downstream (with hidden --eval flag):
- it's easy enough to read
- therefore, it's self documenting (the magic parts of
colmena)
| 01:31:34 |
David Arnold (blaggacao) | nixpkgs.lib.nixos.evalModules is relatively recent so inputs.nixpkgs would have to satisfy that contract, ofc. | 01:35:58 |
hexa | ❯ colmena build
[INFO ] Using configuration: /home/hexa/git/hexa/nixos-servers/config/hive.nix
[INFO ] Enumerating nodes...
error: attribute 'lib' missing
at /run/user/1000/.tmpaIJWby:388:9:
387|
388| lib = pkgs.lib;
| ^
389| reservedNames = [ "defaults" "network" "meta" ];
(use '--show-trace' to show detailed location information)
[ERROR] -----
[ERROR] Operation failed with error: Child process exited with error code: 1
| 14:59:50 |
hexa | (...) | 15:02:39 |
hexa | let
# niv sources
sources = import ../nix/sources.nix;
defaultArch = "x86_64-linux";
defaultPkgs = sources."nixos-22.05";
lib = import (defaultPkgs + "/lib");
machines = {
"foo.example.com" = {
};
"bar.example.com" = {
packages = source."nixos-21.11";
};
};
mkMachine = hostName: { system ? defaultArch, packages ? defaultPkgs, tags ? [] }:
{
imports = [
(./machines + "/${hostName}")
];
nixpkgs = {
inherit system;
};
};
in
{
meta = {
nixpkgs = defaultPkgs;
nodeNixpkgs = lib.mapAttrs
(hostName: { packages? defaultPkgs, ... }: packages)
machines;
};
} // (lib.mapAttrs mkMachine machines)
| 15:03:29 |
hexa | can anybody shed some light on that error? | 15:04:00 |
hexa | I'm slowly trying to migrate from morph, so some of the boilerplate is from that era | 15:04:27 |
Linux Hackerman | meta.nixpkgs should be an imported nixpkgs, not the path to a nixpkgs | 15:04:57 |
hexa | according to https://colmena.cli.rs/unstable/tutorial/index.html it can be … everything? | 15:05:15 |
hexa | although that may be something new from "unstable" | 15:05:25 |
hexa | {
meta = {
# Override to pin the Nixpkgs version (recommended). This option
# accepts one of the following:
# - A path to a Nixpkgs checkout
# - The Nixpkgs lambda (e.g., import <nixpkgs>)
# - An initialized Nixpkgs attribute set
nixpkgs = <nixpkgs>;
| 15:05:44 |
hexa | from the 0.3 docs | 15:06:01 |
Linux Hackerman | oh, hm. Might have been broken accidentally? | 15:06:06 |
Linux Hackerman | It definitely doesn't support passing a path when using flakes | 15:06:55 |
Linux Hackerman | Try using an imported nixpkgs anyway maybe | 15:07:31 |
hexa | passed nixpkgs = import defaultPkgs {}; | 15:08:45 |