!UKDpaKNNsBpOPfLWfX:zhaofeng.li

Colmena

319 Members
A simple, stateless NixOS deployment tool - https://github.com/zhaofengli/colmena108 Servers

Load older messages


SenderMessageTime
26 May 2022
@blaggacao:matrix.org@blaggacao:matrix.org For example, to build a DAG of std targets: drv // { after = [ "othertarget" ]; } 19:09:27
@blaggacao:matrix.org@blaggacao:matrix.org Iiirc, the bundler interface, in reality is any -> drv. drv -> drv just being the "common" case 19:11:28
@blaggacao:matrix.org@blaggacao:matrix.org Ah, and https://github.com/kamadorueda/toros is taking slowly shape. 🚀 The name of the game seems to add all the builtins, now. But then it could be used for parallel eval and also better eval cache strategies could be implemented akin to numtide/nix-eval-cache. 19:13:54
@blaggacao:matrix.org@blaggacao:matrix.org 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
@blaggacao:matrix.org@blaggacao:matrix.org* 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
@blaggacao:matrix.org@blaggacao:matrix.org

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
@blaggacao:matrix.org@blaggacao:matrix.org

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
@blaggacao:matrix.org@blaggacao:matrix.org 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
@blaggacao:matrix.org@blaggacao:matrix.org ( 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
@blaggacao:matrix.org@blaggacao:matrix.orgquick question: is unchecked module evaluation lazy?00:32:58
@blaggacao:matrix.org@blaggacao:matrix.org

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
@blaggacao:matrix.org@blaggacao:matrix.org 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
@blaggacao:matrix.org@blaggacao:matrix.org

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
@blaggacao:matrix.org@blaggacao:matrix.org *

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
@blaggacao:matrix.org@blaggacao:matrix.org 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
@blaggacao:matrix.org@blaggacao:matrix.org *

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
@blaggacao:matrix.org@blaggacao:matrix.org

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
@blaggacao:matrix.org@blaggacao:matrix.org *

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
@blaggacao:matrix.org@blaggacao:matrix.org nixpkgs.lib.nixos.evalModules is relatively recent so inputs.nixpkgs would have to satisfy that contract, ofc. 01:35:58
@hexa:lossy.networkhexa
❯ 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:lossy.networkhexa(...)15:02:39
@hexa:lossy.networkhexa
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:lossy.networkhexacan anybody shed some light on that error?15:04:00
@hexa:lossy.networkhexaI'm slowly trying to migrate from morph, so some of the boilerplate is from that era15:04:27
@linus:schreibt.jetzt@linus:schreibt.jetztmeta.nixpkgs should be an imported nixpkgs, not the path to a nixpkgs15:04:57
@hexa:lossy.networkhexaaccording to https://colmena.cli.rs/unstable/tutorial/index.html it can be … everything?15:05:15
@hexa:lossy.networkhexaalthough that may be something new from "unstable"15:05:25
@hexa:lossy.networkhexa
{
  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:lossy.networkhexafrom the 0.3 docs15:06:01
@linus:schreibt.jetzt@linus:schreibt.jetztoh, hm. Might have been broken accidentally?15:06:06

Show newer messages


Back to Room ListRoom Version: 6