Skip to content

Commit

Permalink
feat: introduce (pointless) vm tests
Browse files Browse the repository at this point in the history
Signed-off-by: Christina Sørensen <[email protected]>
  • Loading branch information
cafkafk committed Aug 6, 2024
1 parent 107f20a commit c3e3abe
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 87 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@
# Generated by nix-pre-commit-hooks
/.pre-commit-config.yaml

.nixos-test-history
150 changes: 80 additions & 70 deletions data/eval-machines.nix
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ let
runCommand =
network.network.runCommand or nwPkgs.runCommand or (import <nixpkgs>
{ }).runCommand;
in with lib;
in
with lib;

let
defaults = network.defaults or {};
defaults = network.defaults or { };

modules = { machineName, nodes, check }:
[
Expand Down Expand Up @@ -58,36 +59,41 @@ let
"_file"
]);

in rec {
in
rec {
# Unchecked configuration of all machines.
# Using unchecked config evaluation allows each machine to access other machines
# configuration without recursing as full evaluation is prevented
uncheckedNodes = listToAttrs (map (machineName: {
name = machineName;
value = import evalConfig {
# Force decide system in module system
system = null;
modules = modules {
inherit machineName;
check = false;
nodes = uncheckedNodes;
uncheckedNodes = listToAttrs (map
(machineName: {
name = machineName;
value = import evalConfig {
# Force decide system in module system
system = null;
modules = modules {
inherit machineName;
check = false;
nodes = uncheckedNodes;
};
};
};
}) machineNames);
})
machineNames);

# Compute the definitions of the machines.
nodes = listToAttrs (map (machineName: {
name = machineName;
value = import evalConfig {
# Force decide system in module system
system = null;
modules = modules {
inherit machineName;
check = true;
nodes = uncheckedNodes;
nodes = listToAttrs (map
(machineName: {
name = machineName;
value = import evalConfig {
# Force decide system in module system
system = null;
modules = modules {
inherit machineName;
check = true;
nodes = uncheckedNodes;
};
};
};
}) machineNames);
})
machineNames);

deploymentInfoModule = {
deployment = {
Expand All @@ -98,58 +104,62 @@ in rec {
};

# Phase 1: evaluate only the deployment attributes.
info = let network' = network;
in rec {

machines = flip mapAttrs nodes (n: v':
let v = scrubOptionValue v';
in {
inherit (v.config.deployment)
targetHost targetPort targetUser secrets healthChecks buildOnly
substituteOnDestination tags;
name = n;
nixosRelease = v.config.system.nixos.release or (removeSuffix
v.config.system.nixos.version.suffix v.config.system.nixos.version);
nixConfig = mapAttrs (n: v:
if builtins.isString v then
v
else
throw "nix option '${n}' must have a string typed value")
(network'.network.nixConfig or { });
});

machineList = map (key: getAttr key machines) (attrNames machines);
network = network'.network or { };
deployment = {
hosts = machineList;
meta = {
description = network.description or "";
ordering = network.ordering or { };
info =
let network' = network;
in rec {

machines = flip mapAttrs nodes (n: v':
let v = scrubOptionValue v';
in {
inherit (v.config.deployment)
targetHost targetPort targetUser secrets healthChecks buildOnly
substituteOnDestination tags;
name = n;
nixosRelease = v.config.system.nixos.release or (removeSuffix
v.config.system.nixos.version.suffix
v.config.system.nixos.version);
nixConfig = mapAttrs
(n: v:
if builtins.isString v then
v
else
throw "nix option '${n}' must have a string typed value")
(network'.network.nixConfig or { });
});

machineList = map (key: getAttr key machines) (attrNames machines);
network = network'.network or { };
deployment = {
hosts = machineList;
meta = {
description = network.description or "";
ordering = network.ordering or { };
};
};
};

buildShell = network.buildShell.drvPath or null;
};
buildShell = network.buildShell.drvPath or null;
};

# Phase 2: build complete machine configurations.
machines = { argsFile, buildTargets ? null }:
let
fileArgs = builtins.fromJSON (builtins.readFile argsFile);
nodes' = filterAttrs (n: _v: elem n fileArgs.Names) nodes;
in runCommand "morph" { preferLocalBuild = true; }
(if buildTargets == null then ''
mkdir -p $out
${toString (mapAttrsToList (nodeName: nodeDef: ''
ln -s ${nodeDef.config.system.build.toplevel} $out/${nodeName}
'') nodes')}
'' else ''
mkdir -p $out
${toString (mapAttrsToList (nodeName: nodeDef: ''
mkdir -p $out/${nodeName}
${toString (mapAttrsToList (buildName: buildFn: ''
ln -s ${buildFn nodeDef} $out/${nodeName}/${buildName}
'') buildTargets)}
'') nodes')}
'');
in
runCommand "morph" { preferLocalBuild = true; }
(if buildTargets == null then ''
mkdir -p $out
${toString (mapAttrsToList (nodeName: nodeDef: ''
ln -s ${nodeDef.config.system.build.toplevel} $out/${nodeName}
'') nodes')}
'' else ''
mkdir -p $out
${toString (mapAttrsToList (nodeName: nodeDef: ''
mkdir -p $out/${nodeName}
${toString (mapAttrsToList (buildName: buildFn: ''
ln -s ${buildFn nodeDef} $out/${nodeName}/${buildName}
'') buildTargets)}
'') nodes')}
'');

}
3 changes: 2 additions & 1 deletion data/options.nix
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@ let
};
});

in {
in
{
options.deployment = {

targetHost = mkOption {
Expand Down
30 changes: 17 additions & 13 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -29,26 +29,30 @@

# Eval the treefmt modules from ./treefmt.nix
treefmtEval = treefmt-nix.lib.evalModule pkgs ./treefmt.nix;
in {
in
rec {
# for `nix fmt`
formatter = treefmtEval.config.build.wrapper;

# for `nix flake check`
checks = {
vm_integration_tests = pkgs.callPackage ./nixos/tests/integration_tests.nix { inherit packages; };
formatting = treefmtEval.config.build.check self;
build = self.packages.${system}.morph;
pre-commit-check = let
# some treefmt formatters are not supported in pre-commit-hooks we
# filter them out for now.
toFilter = [ "yamlfmt" ];
filterFn = n: _v: (!builtins.elem n toFilter);
treefmtFormatters =
pkgs.lib.mapAttrs (_n: v: { inherit (v) enable; })
(pkgs.lib.filterAttrs filterFn (import ./treefmt.nix).programs);
in pre-commit-hooks.lib.${system}.run {
src = ./.;
hooks = treefmtFormatters;
};
pre-commit-check =
let
# some treefmt formatters are not supported in pre-commit-hooks we
# filter them out for now.
toFilter = [ "yamlfmt" ];
filterFn = n: _v: (!builtins.elem n toFilter);
treefmtFormatters =
pkgs.lib.mapAttrs (_n: v: { inherit (v) enable; })
(pkgs.lib.filterAttrs filterFn (import ./treefmt.nix).programs);
in
pre-commit-hooks.lib.${system}.run {
src = ./.;
hooks = treefmtFormatters;
};
};

# Acessible through 'nix develop' or 'nix-shell' (legacy)
Expand Down
32 changes: 32 additions & 0 deletions nixos/tests/integration_tests.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{ nixosTest, packages, ... }:


nixosTest {
name = "morph-deployment-test";
nodes =
let
boot.loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
};
services.openssh = {
enable = true;
startWhenNeeded = false;
};
in
{
deployer = _: {
inherit services boot;
environment.systemPackages = [ packages.morph ];
};
target = _: {
inherit services boot;
};
};
testScript = ''
start_all()
deployer.wait_for_unit("sshd")
target.wait_for_unit("sshd")
'';
}
2 changes: 1 addition & 1 deletion nixpkgs.nix
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Intentionally impure for CI against nixos-unstable
builtins.fetchTarball
"https://github.com/NixOS/nixpkgs/archive/nixos-unstable.tar.gz"
"https://github.com/NixOS/nixpkgs/archive/nixos-unstable.tar.gz"
4 changes: 2 additions & 2 deletions treefmt.nix
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
projectRootFile = "flake.nix";
programs = {
nixfmt.enable = true; # nix formatter
nixpkgs-fmt.enable = true; # nix formatter
statix.enable = true; # nix static analysis
deadnix.enable = true; # find dead nix code
shellcheck.enable = true; # bash/shell
Expand All @@ -11,7 +11,7 @@
};
settings = {
formatter = {
nixfmt.includes = [ "*.nix" "./data/*" ];
nixpkgs-fmt.includes = [ "*.nix" "./data/*" ];
statix.includes = [ "*.nix" "./data/*" ];
deadnix.includes = [ "*.nix" "./data/*" ];
};
Expand Down

0 comments on commit c3e3abe

Please sign in to comment.