tests: update inventory tests to use whole clan modules

This commit is contained in:
Johannes Kirschbauer
2025-10-30 13:47:34 +01:00
parent be31b9ce21
commit 1953540d08
6 changed files with 245 additions and 237 deletions

View File

@@ -4,63 +4,53 @@
... ...
}: }:
let let
inherit (lib)
evalModules
;
evalInventory = flakeInputsFixture = {
m: upstream.clan.modules = {
(evalModules { uzzi = {
# Static modules _class = "clan.service";
modules = [ manifest = {
clanLib.inventory.inventoryModule name = "uzzi-from-upstream";
{
_file = "test file";
tags.all = [ ];
tags.nixos = [ ];
tags.darwin = [ ];
}
{
modules.test = { };
}
m
];
}).config;
callInventoryAdapter =
inventoryModule:
let
inventory = evalInventory inventoryModule;
flakeInputsFixture = {
self.clan.modules = inventoryModule.modules or { };
# Example upstream module
upstream.clan.modules = {
uzzi = {
_class = "clan.service";
manifest = {
name = "uzzi-from-upstream";
};
};
}; };
}; };
in
clanLib.inventory.mapInstances {
directory = ./.;
clanCoreModules = { };
flakeInputs = flakeInputsFixture;
inherit inventory;
exportsModule = { };
}; };
};
createTestClan =
testClan:
let
res = clanLib.clan ({
# Static / mocked
specialArgs = {
clan-core = {
clan.modules = { };
};
};
self.inputs = flakeInputsFixture // {
self.clan = res.config;
};
directory = ./.;
exportsModule = { };
imports = [
testClan
];
});
in
res;
in in
{ {
extraModules = import ./extraModules.nix { inherit clanLib; }; extraModules = import ./extraModules.nix { inherit clanLib; };
exports = import ./exports.nix { inherit lib clanLib; }; exports = import ./exports.nix { inherit lib clanLib; };
settings = import ./settings.nix { inherit lib callInventoryAdapter; }; settings = import ./settings.nix { inherit lib createTestClan; };
specialArgs = import ./specialArgs.nix { inherit lib callInventoryAdapter; }; specialArgs = import ./specialArgs.nix { inherit lib createTestClan; };
resolve_module_spec = import ./import_module_spec.nix { inherit lib callInventoryAdapter; }; resolve_module_spec = import ./import_module_spec.nix {
inherit lib createTestClan;
};
test_simple = test_simple =
let let
res = callInventoryAdapter { res = createTestClan {
# Authored module # Authored module
# A minimal module looks like this # A minimal module looks like this
# It isn't exactly doing anything but it's a valid module that produces an output # It isn't exactly doing anything but it's a valid module that produces an output
@@ -71,7 +61,7 @@ in
}; };
}; };
# User config # User config
instances."instance_foo" = { inventory.instances."instance_foo" = {
module = { module = {
name = "simple-module"; name = "simple-module";
}; };
@@ -81,7 +71,7 @@ in
{ {
# Test that the module is mapped into the output # Test that the module is mapped into the output
# We might change the attribute name in the future # We might change the attribute name in the future
expr = res.servicesEval.config.mappedServices ? "<clan-core>-simple-module"; expr = res.config._services.mappedServices ? "<clan-core>-simple-module";
expected = true; expected = true;
inherit res; inherit res;
}; };
@@ -92,7 +82,7 @@ in
# All instances should be included within one evaluation to make all of them available # All instances should be included within one evaluation to make all of them available
test_module_grouping = test_module_grouping =
let let
res = callInventoryAdapter { res = createTestClan {
# Authored module # Authored module
# A minimal module looks like this # A minimal module looks like this
# It isn't exactly doing anything but it's a valid module that produces an output # It isn't exactly doing anything but it's a valid module that produces an output
@@ -112,18 +102,19 @@ in
perMachine = { }: { }; perMachine = { }: { };
}; };
# User config # User config
instances."instance_foo" = { inventory.instances."instance_foo" = {
module = { module = {
name = "A"; name = "A";
}; };
}; };
instances."instance_bar" = { inventory.instances."instance_bar" = {
module = { module = {
name = "B"; name = "B";
}; };
}; };
instances."instance_baz" = { inventory.instances."instance_baz" = {
module = { module = {
name = "A"; name = "A";
}; };
@@ -133,16 +124,16 @@ in
{ {
# Test that the module is mapped into the output # Test that the module is mapped into the output
# We might change the attribute name in the future # We might change the attribute name in the future
expr = lib.mapAttrs (_n: v: builtins.length v) res.grouped; expr = lib.attrNames res.config._services.mappedServices;
expected = { expected = [
"<clan-core>-A" = 2; "<clan-core>-A"
"<clan-core>-B" = 1; "<clan-core>-B"
}; ];
}; };
test_creates_all_instances = test_creates_all_instances =
let let
res = callInventoryAdapter { res = createTestClan {
# Authored module # Authored module
# A minimal module looks like this # A minimal module looks like this
# It isn't exactly doing anything but it's a valid module that produces an output # It isn't exactly doing anything but it's a valid module that produces an output
@@ -154,22 +145,24 @@ in
perMachine = { }: { }; perMachine = { }: { };
}; };
instances."instance_foo" = { inventory = {
module = { instances."instance_foo" = {
name = "A"; module = {
input = "self"; name = "A";
input = "self";
};
}; };
}; instances."instance_bar" = {
instances."instance_bar" = { module = {
module = { name = "A";
name = "A"; input = "self";
input = "self"; };
}; };
}; instances."instance_zaza" = {
instances."instance_zaza" = { module = {
module = { name = "B";
name = "B"; input = null;
input = null; };
}; };
}; };
}; };
@@ -177,7 +170,7 @@ in
{ {
# Test that the module is mapped into the output # Test that the module is mapped into the output
# We might change the attribute name in the future # We might change the attribute name in the future
expr = lib.attrNames res.servicesEval.config.mappedServices.self-A.instances; expr = lib.attrNames res.config._services.mappedServices.self-A.instances;
expected = [ expected = [
"instance_bar" "instance_bar"
"instance_foo" "instance_foo"
@@ -187,7 +180,7 @@ in
# Membership via roles # Membership via roles
test_add_machines_directly = test_add_machines_directly =
let let
res = callInventoryAdapter { res = createTestClan {
# Authored module # Authored module
# A minimal module looks like this # A minimal module looks like this
# It isn't exactly doing anything but it's a valid module that produces an output # It isn't exactly doing anything but it's a valid module that produces an output
@@ -202,38 +195,40 @@ in
# perMachine = {}: {}; # perMachine = {}: {};
}; };
machines = { inventory = {
jon = { }; machines = {
sara = { }; jon = { };
hxi = { }; sara = { };
}; hxi = { };
instances."instance_foo" = {
module = {
name = "A";
input = "self";
}; };
roles.peer.machines.jon = { }; instances."instance_foo" = {
}; module = {
instances."instance_bar" = { name = "A";
module = { input = "self";
name = "A"; };
input = "self"; roles.peer.machines.jon = { };
}; };
roles.peer.machines.sara = { }; instances."instance_bar" = {
}; module = {
instances."instance_zaza" = { name = "A";
module = { input = "self";
name = "B"; };
input = null; roles.peer.machines.sara = { };
};
instances."instance_zaza" = {
module = {
name = "B";
input = null;
};
roles.peer.tags.all = { };
}; };
roles.peer.tags.all = { };
}; };
}; };
in in
{ {
# Test that the module is mapped into the output # Test that the module is mapped into the output
# We might change the attribute name in the future # We might change the attribute name in the future
expr = lib.attrNames res.servicesEval.config.mappedServices.self-A.result.allMachines; expr = lib.attrNames res.config._services.mappedServices.self-A.result.allMachines;
expected = [ expected = [
"jon" "jon"
"sara" "sara"
@@ -243,7 +238,7 @@ in
# Membership via tags # Membership via tags
test_add_machines_via_tags = test_add_machines_via_tags =
let let
res = callInventoryAdapter { res = createTestClan {
# Authored module # Authored module
# A minimal module looks like this # A minimal module looks like this
# It isn't exactly doing anything but it's a valid module that produces an output # It isn't exactly doing anything but it's a valid module that produces an output
@@ -257,35 +252,37 @@ in
# perMachine = {}: {}; # perMachine = {}: {};
}; };
machines = { inventory = {
jon = { machines = {
tags = [ "foo" ]; jon = {
tags = [ "foo" ];
};
sara = {
tags = [ "foo" ];
};
hxi = { };
}; };
sara = { instances."instance_foo" = {
tags = [ "foo" ]; module = {
name = "A";
input = "self";
};
roles.peer.tags.foo = { };
}; };
hxi = { }; instances."instance_zaza" = {
}; module = {
instances."instance_foo" = { name = "B";
module = { input = null;
name = "A"; };
input = "self"; roles.peer.tags.all = { };
}; };
roles.peer.tags.foo = { };
};
instances."instance_zaza" = {
module = {
name = "B";
input = null;
};
roles.peer.tags.all = { };
}; };
}; };
in in
{ {
# Test that the module is mapped into the output # Test that the module is mapped into the output
# We might change the attribute name in the future # We might change the attribute name in the future
expr = lib.attrNames res.servicesEval.config.mappedServices.self-A.result.allMachines; expr = lib.attrNames res.config._services.mappedServices.self-A.result.allMachines;
expected = [ expected = [
"jon" "jon"
"sara" "sara"
@@ -293,6 +290,9 @@ in
}; };
machine_imports = import ./machine_imports.nix { inherit lib clanLib; }; machine_imports = import ./machine_imports.nix { inherit lib clanLib; };
per_machine_args = import ./per_machine_args.nix { inherit lib callInventoryAdapter; }; per_machine_args = import ./per_machine_args.nix { inherit lib createTestClan; };
per_instance_args = import ./per_instance_args.nix { inherit lib callInventoryAdapter; }; per_instance_args = import ./per_instance_args.nix {
inherit lib;
callInventoryAdapter = createTestClan;
};
} }

View File

@@ -1,4 +1,4 @@
{ callInventoryAdapter, ... }: { createTestClan, ... }:
let let
# Authored module # Authored module
# A minimal module looks like this # A minimal module looks like this
@@ -23,10 +23,13 @@ let
resolve = resolve =
spec: spec:
callInventoryAdapter { createTestClan {
inherit modules machines; inherit modules;
instances."instance_foo" = { inventory = {
module = spec; inherit machines;
instances."instance_foo" = {
module = spec;
};
}; };
}; };
in in
@@ -36,25 +39,16 @@ in
(resolve { (resolve {
name = "A"; name = "A";
input = "self"; input = "self";
}).importedModuleWithInstances.instance_foo.resolvedModule; }).config._services.mappedServices.self-A.manifest.name;
expected = { expected = "network";
_class = "clan.service";
manifest = {
name = "network";
};
};
}; };
test_import_remote_module_by_name = { test_import_remote_module_by_name = {
expr = expr =
(resolve { (resolve {
name = "uzzi"; name = "uzzi";
input = "upstream"; input = "upstream";
}).importedModuleWithInstances.instance_foo.resolvedModule; }).config._services.mappedServices.upstream-uzzi.manifest.name;
expected = { expected = "uzzi-from-upstream";
_class = "clan.service";
manifest = {
name = "uzzi-from-upstream";
};
};
}; };
} }

View File

@@ -58,39 +58,43 @@ let
sara = { }; sara = { };
}; };
res = callInventoryAdapter { res = callInventoryAdapter {
inherit modules machines; inherit modules;
instances."instance_foo" = {
module = { inventory = {
name = "A"; inherit machines;
input = "self"; instances."instance_foo" = {
module = {
name = "A";
input = "self";
};
roles.peer.machines.jon = {
settings.timeout = lib.mkForce "foo-peer-jon";
};
roles.peer = {
settings.timeout = "foo-peer";
};
roles.controller.machines.jon = { };
}; };
roles.peer.machines.jon = { instances."instance_bar" = {
settings.timeout = lib.mkForce "foo-peer-jon"; module = {
name = "A";
input = "self";
};
roles.peer.machines.jon = {
settings.timeout = "bar-peer-jon";
};
}; };
roles.peer = { # TODO: move this into a seperate test.
settings.timeout = "foo-peer"; # Seperate out the check that this module is never imported
# import the module "B" (undefined)
# All machines have this instance
instances."instance_zaza" = {
module = {
name = "B";
input = null;
};
roles.peer.tags.all = { };
}; };
roles.controller.machines.jon = { };
};
instances."instance_bar" = {
module = {
name = "A";
input = "self";
};
roles.peer.machines.jon = {
settings.timeout = "bar-peer-jon";
};
};
# TODO: move this into a seperate test.
# Seperate out the check that this module is never imported
# import the module "B" (undefined)
# All machines have this instance
instances."instance_zaza" = {
module = {
name = "B";
input = null;
};
roles.peer.tags.all = { };
}; };
}; };
@@ -105,9 +109,10 @@ in
{ {
# settings should evaluate # settings should evaluate
test_per_instance_arguments = { test_per_instance_arguments = {
inherit res;
expr = { expr = {
instanceName = instanceName =
res.servicesEval.config.mappedServices.self-A.result.allRoles.peer.allInstances."instance_foo".allMachines.jon.passthru.instanceName; res.config._services.mappedServices.self-A.result.allRoles.peer.allInstances."instance_foo".allMachines.jon.passthru.instanceName;
# settings are specific. # settings are specific.
# Below we access: # Below we access:
@@ -115,11 +120,11 @@ in
# roles = peer # roles = peer
# machines = jon # machines = jon
settings = settings =
res.servicesEval.config.mappedServices.self-A.result.allRoles.peer.allInstances.instance_foo.allMachines.jon.passthru.settings; res.config._services.mappedServices.self-A.result.allRoles.peer.allInstances.instance_foo.allMachines.jon.passthru.settings;
machine = machine =
res.servicesEval.config.mappedServices.self-A.result.allRoles.peer.allInstances.instance_foo.allMachines.jon.passthru.machine; res.config._services.mappedServices.self-A.result.allRoles.peer.allInstances.instance_foo.allMachines.jon.passthru.machine;
roles = roles =
res.servicesEval.config.mappedServices.self-A.result.allRoles.peer.allInstances.instance_foo.allMachines.jon.passthru.roles; res.config._services.mappedServices.self-A.result.allRoles.peer.allInstances.instance_foo.allMachines.jon.passthru.roles;
}; };
expected = { expected = {
instanceName = "instance_foo"; instanceName = "instance_foo";
@@ -160,9 +165,9 @@ in
# TODO: Cannot be tested like this anymore # TODO: Cannot be tested like this anymore
test_per_instance_settings_vendoring = { test_per_instance_settings_vendoring = {
x = res.servicesEval.config.mappedServices.self-A; x = res.config._services.mappedServices.self-A;
expr = expr =
res.servicesEval.config.mappedServices.self-A.result.allRoles.peer.allInstances.instance_foo.allMachines.jon.passthru.vendoredSettings; res.config._services.mappedServices.self-A.result.allRoles.peer.allInstances.instance_foo.allMachines.jon.passthru.vendoredSettings;
expected = { expected = {
timeout = "config.thing"; timeout = "config.thing";
}; };

View File

@@ -1,4 +1,4 @@
{ lib, callInventoryAdapter }: { lib, createTestClan }:
let let
# Authored module # Authored module
# A minimal module looks like this # A minimal module looks like this
@@ -39,36 +39,40 @@ let
jon = { }; jon = { };
sara = { }; sara = { };
}; };
res = callInventoryAdapter { res = createTestClan {
inherit modules machines; inherit modules;
instances."instance_foo" = { inventory = {
module = {
name = "A"; inherit machines;
input = "self"; instances."instance_foo" = {
module = {
name = "A";
input = "self";
};
roles.peer.machines.jon = {
settings.timeout = lib.mkForce "foo-peer-jon";
};
roles.peer = {
settings.timeout = "foo-peer";
};
}; };
roles.peer.machines.jon = { instances."instance_bar" = {
settings.timeout = lib.mkForce "foo-peer-jon"; module = {
name = "A";
input = "self";
};
roles.peer.machines.jon = {
settings.timeout = "bar-peer-jon";
};
}; };
roles.peer = { instances."instance_zaza" = {
settings.timeout = "foo-peer"; module = {
name = "B";
input = null;
};
roles.peer.tags.all = { };
}; };
}; };
instances."instance_bar" = {
module = {
name = "A";
input = "self";
};
roles.peer.machines.jon = {
settings.timeout = "bar-peer-jon";
};
};
instances."instance_zaza" = {
module = {
name = "B";
input = null;
};
roles.peer.tags.all = { };
};
}; };
in in
@@ -79,7 +83,7 @@ in
inherit res; inherit res;
expr = { expr = {
hasMachineSettings = hasMachineSettings =
res.servicesEval.config.mappedServices.self-A.result.allMachines.jon.passthru.instances.instance_foo.roles.peer.machines.jon res.config._services.mappedServices.self-A.result.allMachines.jon.passthru.instances.instance_foo.roles.peer.machines.jon
? settings; ? settings;
# settings are specific. # settings are specific.
@@ -88,10 +92,10 @@ in
# roles = peer # roles = peer
# machines = jon # machines = jon
specificMachineSettings = specificMachineSettings =
res.servicesEval.config.mappedServices.self-A.result.allMachines.jon.passthru.instances.instance_foo.roles.peer.machines.jon.settings; res.config._services.mappedServices.self-A.result.allMachines.jon.passthru.instances.instance_foo.roles.peer.machines.jon.settings;
hasRoleSettings = hasRoleSettings =
res.servicesEval.config.mappedServices.self-A.result.allMachines.jon.passthru.instances.instance_foo.roles.peer res.config._services.mappedServices.self-A.result.allMachines.jon.passthru.instances.instance_foo.roles.peer
? settings; ? settings;
# settings are specific. # settings are specific.
@@ -100,7 +104,7 @@ in
# roles = peer # roles = peer
# machines = * # machines = *
specificRoleSettings = specificRoleSettings =
res.servicesEval.config.mappedServices.self-A.result.allMachines.jon.passthru.instances.instance_foo.roles.peer; res.config._services.mappedServices.self-A.result.allMachines.jon.passthru.instances.instance_foo.roles.peer;
}; };
expected = { expected = {
hasMachineSettings = true; hasMachineSettings = true;

View File

@@ -1,6 +1,6 @@
{ callInventoryAdapter, lib, ... }: { createTestClan, lib, ... }:
let let
res = callInventoryAdapter { res = createTestClan {
modules."A" = { modules."A" = {
_class = "clan.service"; _class = "clan.service";
manifest = { manifest = {
@@ -21,28 +21,31 @@ let
}; };
}; };
}; };
machines = { inventory = {
jon = { };
sara = { }; machines = {
}; jon = { };
instances."instance_foo" = { sara = { };
module = {
name = "A";
input = "self";
}; };
# Settings for both jon and sara instances."instance_foo" = {
roles.peer.settings = { module = {
timeout = 40; name = "A";
input = "self";
};
# Settings for both jon and sara
roles.peer.settings = {
timeout = 40;
};
# Jon overrides timeout
roles.peer.machines.jon = {
settings.timeout = lib.mkForce 42;
};
roles.peer.machines.sara = { };
}; };
# Jon overrides timeout
roles.peer.machines.jon = {
settings.timeout = lib.mkForce 42;
};
roles.peer.machines.sara = { };
}; };
}; };
config = res.servicesEval.config.mappedServices.self-A; config = res.config._services.mappedServices.self-A;
# #
applySettings = applySettings =

View File

@@ -1,6 +1,6 @@
{ callInventoryAdapter, lib, ... }: { createTestClan, lib, ... }:
let let
res = callInventoryAdapter { res = createTestClan {
modules."A" = m: { modules."A" = m: {
_class = "clan.service"; _class = "clan.service";
config = { config = {
@@ -14,19 +14,21 @@ let
default = m; default = m;
}; };
}; };
machines = { inventory = {
jon = { }; machines = {
}; jon = { };
instances."instance_foo" = { };
module = { instances."instance_foo" = {
name = "A"; module = {
input = "self"; name = "A";
input = "self";
};
roles.peer.machines.jon = { };
}; };
roles.peer.machines.jon = { };
}; };
}; };
specialArgs = lib.attrNames res.servicesEval.config.mappedServices.self-A.test.specialArgs; specialArgs = lib.attrNames res.config._services.mappedServices.self-A.test.specialArgs;
in in
{ {
test_simple = { test_simple = {