forked from Fediversity/Fediversity
This PR builds on top of #447 and will be subject to the same discussion. Let's discuss there whether it makes sense to get rid of the `flake-parts` and `git-hooks` flake inputs. Reviewed-on: Fediversity/Fediversity#448 Reviewed-by: kiara Grouwstra <kiara@procolix.eu> Co-authored-by: Nicolas “Niols” Jeannerod <nicolas.jeannerod@moduscreate.com> Co-committed-by: Nicolas “Niols” Jeannerod <nicolas.jeannerod@moduscreate.com>
163 lines
5.1 KiB
Nix
163 lines
5.1 KiB
Nix
{
|
|
inputs,
|
|
lib,
|
|
config,
|
|
hostPkgs,
|
|
sources,
|
|
...
|
|
}:
|
|
|
|
let
|
|
inherit (builtins)
|
|
concatStringsSep
|
|
toJSON
|
|
;
|
|
inherit (lib)
|
|
fileset
|
|
mkOption
|
|
genAttrs
|
|
attrNames
|
|
optionalString
|
|
;
|
|
inherit (hostPkgs)
|
|
runCommandNoCC
|
|
writeText
|
|
system
|
|
;
|
|
|
|
forConcat = xs: f: concatStringsSep "\n" (map f xs);
|
|
|
|
## The whole repository, with the flake at its root.
|
|
## FIXME: We could probably have fileset be the union of ./. with flake.nix
|
|
## and flake.lock - I doubt we need anything else.
|
|
src = fileset.toSource {
|
|
fileset = config.pathToRoot;
|
|
root = config.pathToRoot;
|
|
};
|
|
|
|
## We will need to override some inputs by the empty flake, so we make one.
|
|
emptyFlake = runCommandNoCC "empty-flake" { } ''
|
|
mkdir $out
|
|
echo "{ outputs = { self }: {}; }" > $out/flake.nix
|
|
'';
|
|
|
|
in
|
|
{
|
|
_class = "nixosTest";
|
|
|
|
imports = [
|
|
./sharedOptions.nix
|
|
];
|
|
|
|
options = {
|
|
## FIXME: I wish I could just use `testScript` but with something like
|
|
## `mkOrder` to put this module's string before something else.
|
|
extraTestScript = mkOption { };
|
|
};
|
|
|
|
config = {
|
|
acmeNodeIP = config.nodes.acme.networking.primaryIPAddress;
|
|
|
|
nodes =
|
|
{
|
|
deployer = {
|
|
imports = [ ./deployerNode.nix ];
|
|
_module.args = { inherit inputs sources; };
|
|
enableAcme = config.enableAcme;
|
|
acmeNodeIP = config.nodes.acme.networking.primaryIPAddress;
|
|
};
|
|
}
|
|
|
|
//
|
|
|
|
(
|
|
if config.enableAcme then
|
|
{
|
|
acme = {
|
|
## FIXME: This makes `nodes.acme` into a local resolver. Maybe this will
|
|
## break things once we play with DNS?
|
|
imports = [ "${inputs.nixpkgs}/nixos/tests/common/acme/server" ];
|
|
## We aren't testing ACME - we just want certificates.
|
|
systemd.services.pebble.environment.PEBBLE_VA_ALWAYS_VALID = "1";
|
|
};
|
|
}
|
|
else
|
|
{ }
|
|
)
|
|
|
|
//
|
|
|
|
genAttrs config.targetMachines (_: {
|
|
imports = [ ./targetNode.nix ];
|
|
_module.args = { inherit inputs sources; };
|
|
enableAcme = config.enableAcme;
|
|
acmeNodeIP = if config.enableAcme then config.nodes.acme.networking.primaryIPAddress else null;
|
|
});
|
|
|
|
testScript = ''
|
|
${forConcat (attrNames config.nodes) (n: ''
|
|
${n}.start()
|
|
'')}
|
|
|
|
${forConcat (attrNames config.nodes) (n: ''
|
|
${n}.wait_for_unit("multi-user.target")
|
|
'')}
|
|
|
|
with subtest("Unpacking"):
|
|
deployer.succeed("cp -r --no-preserve=mode ${src}/* .")
|
|
|
|
with subtest("Configure the network"):
|
|
${forConcat config.targetMachines (
|
|
tm:
|
|
let
|
|
targetNetworkJSON = writeText "target-network.json" (
|
|
toJSON config.nodes.${tm}.system.build.networkConfig
|
|
);
|
|
in
|
|
''
|
|
deployer.copy_from_host("${targetNetworkJSON}", "${config.pathFromRoot}/${tm}-network.json")
|
|
''
|
|
)}
|
|
|
|
with subtest("Configure the deployer key"):
|
|
deployer.succeed("""mkdir -p ~/.ssh && ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa""")
|
|
deployer_key = deployer.succeed("cat ~/.ssh/id_rsa.pub").strip()
|
|
${forConcat config.targetMachines (tm: ''
|
|
${tm}.succeed(f"mkdir -p /root/.ssh && echo '{deployer_key}' >> /root/.ssh/authorized_keys")
|
|
'')}
|
|
|
|
with subtest("Configure the target host key"):
|
|
${forConcat config.targetMachines (tm: ''
|
|
host_key = ${tm}.succeed("ssh-keyscan ${tm} | grep -v '^#' | cut -f 2- -d ' ' | head -n 1")
|
|
deployer.succeed(f"echo '{host_key}' > ${config.pathFromRoot}/${tm}_host_key.pub")
|
|
'')}
|
|
|
|
## NOTE: This is super slow. It could probably be optimised in Nix, for
|
|
## instance by allowing to grab things directly from the host's store.
|
|
with subtest("Override the lock"):
|
|
deployer.succeed("""
|
|
nix flake lock --extra-experimental-features 'flakes nix-command' \
|
|
--offline -v \
|
|
--override-input nixops4 ${inputs.nixops4.packages.${system}.flake-in-a-bottle} \
|
|
\
|
|
--override-input nixops4-nixos ${inputs.nixops4-nixos} \
|
|
--override-input nixops4-nixos/flake-parts ${inputs.nixops4-nixos.inputs.flake-parts} \
|
|
--override-input nixops4-nixos/flake-parts/nixpkgs-lib ${inputs.nixops4-nixos.inputs.flake-parts.inputs.nixpkgs-lib} \
|
|
--override-input nixops4-nixos/nixops4-nixos ${emptyFlake} \
|
|
--override-input nixops4-nixos/nixpkgs ${inputs.nixops4-nixos.inputs.nixpkgs} \
|
|
--override-input nixops4-nixos/nixops4 ${
|
|
inputs.nixops4-nixos.inputs.nixops4.packages.${system}.flake-in-a-bottle
|
|
} \
|
|
--override-input nixops4-nixos/git-hooks-nix ${emptyFlake} \
|
|
;
|
|
""")
|
|
|
|
${optionalString config.enableAcme ''
|
|
with subtest("Set up handmade DNS"):
|
|
deployer.succeed("echo '${config.nodes.acme.networking.primaryIPAddress}' > ${config.pathFromRoot}/acme_server_ip")
|
|
''}
|
|
|
|
${config.extraTestScript}
|
|
'';
|
|
};
|
|
}
|