test(inventory/instances): add tests for per machine resolution
This commit is contained in:
@@ -59,4 +59,269 @@ in
|
||||
expr = res.evals ? "self-simple-module";
|
||||
expected = true;
|
||||
};
|
||||
|
||||
# A module can be imported multiple times
|
||||
# A module can also have multiple instances within the same module
|
||||
# This mean modules must be grouped together, imported once
|
||||
# All instances should be included within one evaluation to make all of them available
|
||||
test_module_grouping =
|
||||
let
|
||||
res = callInventoryAdapter {
|
||||
# Authored module
|
||||
# A minimal module looks like this
|
||||
# It isn't exactly doing anything but it's a valid module that produces an output
|
||||
modules."A" = {
|
||||
_class = "clan.service";
|
||||
manifest = {
|
||||
name = "A-name";
|
||||
};
|
||||
|
||||
perMachine = { }: { };
|
||||
};
|
||||
modules."B" = {
|
||||
_class = "clan.service";
|
||||
manifest = {
|
||||
name = "B-name";
|
||||
};
|
||||
|
||||
perMachine = { }: { };
|
||||
};
|
||||
# User config
|
||||
instances."instance_foo" = {
|
||||
module = {
|
||||
name = "A";
|
||||
};
|
||||
};
|
||||
instances."instance_bar" = {
|
||||
module = {
|
||||
name = "B";
|
||||
};
|
||||
};
|
||||
instances."instance_baz" = {
|
||||
module = {
|
||||
name = "A";
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
# Test that the module is mapped into the output
|
||||
# We might change the attribute name in the future
|
||||
expr = lib.mapAttrs (_n: v: builtins.length v) res.grouped;
|
||||
expected = {
|
||||
self-A = 2;
|
||||
self-B = 1;
|
||||
};
|
||||
};
|
||||
|
||||
test_creates_all_instances =
|
||||
let
|
||||
res = callInventoryAdapter {
|
||||
# Authored module
|
||||
# A minimal module looks like this
|
||||
# It isn't exactly doing anything but it's a valid module that produces an output
|
||||
modules."A" = {
|
||||
_class = "clan.service";
|
||||
manifest = {
|
||||
name = "network";
|
||||
};
|
||||
|
||||
perMachine = { }: { };
|
||||
};
|
||||
instances."instance_foo" = {
|
||||
module = {
|
||||
name = "A";
|
||||
};
|
||||
};
|
||||
instances."instance_bar" = {
|
||||
module = {
|
||||
name = "A";
|
||||
};
|
||||
};
|
||||
instances."instance_zaza" = {
|
||||
module = {
|
||||
name = "B";
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
# Test that the module is mapped into the output
|
||||
# We might change the attribute name in the future
|
||||
expr = lib.attrNames res.evals.self-A.config.instances;
|
||||
expected = [
|
||||
"instance_bar"
|
||||
"instance_foo"
|
||||
];
|
||||
};
|
||||
|
||||
# Membership via roles
|
||||
test_add_machines_directly =
|
||||
let
|
||||
res = callInventoryAdapter {
|
||||
# Authored module
|
||||
# A minimal module looks like this
|
||||
# It isn't exactly doing anything but it's a valid module that produces an output
|
||||
modules."A" = {
|
||||
_class = "clan.service";
|
||||
manifest = {
|
||||
name = "network";
|
||||
};
|
||||
# Define a role without special behavior
|
||||
roles.peer = { };
|
||||
|
||||
# perMachine = {}: {};
|
||||
};
|
||||
machines = {
|
||||
jon = { };
|
||||
sara = { };
|
||||
hxi = { };
|
||||
};
|
||||
instances."instance_foo" = {
|
||||
module = {
|
||||
name = "A";
|
||||
};
|
||||
roles.peer.machines.jon = { };
|
||||
};
|
||||
instances."instance_bar" = {
|
||||
module = {
|
||||
name = "A";
|
||||
};
|
||||
roles.peer.machines.sara = { };
|
||||
};
|
||||
instances."instance_zaza" = {
|
||||
module = {
|
||||
name = "B";
|
||||
};
|
||||
roles.peer.tags.all = { };
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
# Test that the module is mapped into the output
|
||||
# We might change the attribute name in the future
|
||||
expr = lib.attrNames res.evals.self-A.config.result.allMachines;
|
||||
expected = [
|
||||
"jon"
|
||||
"sara"
|
||||
];
|
||||
};
|
||||
|
||||
# Membership via tags
|
||||
test_add_machines_via_tags =
|
||||
let
|
||||
res = callInventoryAdapter {
|
||||
# Authored module
|
||||
# A minimal module looks like this
|
||||
# It isn't exactly doing anything but it's a valid module that produces an output
|
||||
modules."A" = {
|
||||
_class = "clan.service";
|
||||
manifest = {
|
||||
name = "network";
|
||||
};
|
||||
# Define a role without special behavior
|
||||
roles.peer = { };
|
||||
|
||||
# perMachine = {}: {};
|
||||
};
|
||||
machines = {
|
||||
jon = {
|
||||
tags = [ "foo" ];
|
||||
};
|
||||
sara = {
|
||||
tags = [ "foo" ];
|
||||
};
|
||||
hxi = { };
|
||||
};
|
||||
instances."instance_foo" = {
|
||||
module = {
|
||||
name = "A";
|
||||
};
|
||||
roles.peer.tags.foo = { };
|
||||
};
|
||||
instances."instance_zaza" = {
|
||||
module = {
|
||||
name = "B";
|
||||
};
|
||||
roles.peer.tags.all = { };
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
# Test that the module is mapped into the output
|
||||
# We might change the attribute name in the future
|
||||
expr = lib.attrNames res.evals.self-A.config.result.allMachines;
|
||||
expected = [
|
||||
"jon"
|
||||
"sara"
|
||||
];
|
||||
};
|
||||
|
||||
per_machine_args = import ./per_machine_args.nix { inherit lib callInventoryAdapter; };
|
||||
# test_per_machine_receives_instances =
|
||||
# let
|
||||
# res = callInventoryAdapter {
|
||||
# # Authored module
|
||||
# # A minimal module looks like this
|
||||
# # It isn't exactly doing anything but it's a valid module that produces an output
|
||||
# modules."A" = {
|
||||
# _class = "clan.service";
|
||||
# manifest = {
|
||||
# name = "network";
|
||||
# };
|
||||
# # Define a role without special behavior
|
||||
# roles.peer = { };
|
||||
|
||||
# perMachine =
|
||||
# { instances, ... }:
|
||||
# {
|
||||
# nixosModule = instances;
|
||||
# };
|
||||
# };
|
||||
# machines = {
|
||||
# jon = { };
|
||||
# sara = { };
|
||||
# };
|
||||
# instances."instance_foo" = {
|
||||
# module = {
|
||||
# name = "A";
|
||||
# };
|
||||
# roles.peer.machines.jon = { };
|
||||
# };
|
||||
# instances."instance_bar" = {
|
||||
# module = {
|
||||
# name = "A";
|
||||
# };
|
||||
# roles.peer.machines.sara = { };
|
||||
# };
|
||||
# instances."instance_zaza" = {
|
||||
# module = {
|
||||
# name = "B";
|
||||
# };
|
||||
# roles.peer.tags.all = { };
|
||||
# };
|
||||
# };
|
||||
# in
|
||||
# {
|
||||
# expr = {
|
||||
# hasMachineSettings =
|
||||
# res.evals.self-A.config.result.allMachines.jon.nixosModule. # { {instanceName} :: { roles :: { {roleName} :: { machines :: { {machineName} :: { settings :: {} } } } } } }
|
||||
# instance_foo.roles.peer.machines.jon ? settings;
|
||||
# machineSettingsEmpty =
|
||||
# lib.filterAttrs (n: _v: n != "__functor" ) res.evals.self-A.config.result.allMachines.jon.nixosModule. # { {instanceName} :: { roles :: { {roleName} :: { machines :: { {machineName} :: { settings :: {} } } } } } }
|
||||
# instance_foo.roles.peer.machines.jon.settings;
|
||||
# hasRoleSettings =
|
||||
# res.evals.self-A.config.result.allMachines.jon.nixosModule. # { {instanceName} :: { roles :: { {roleName} :: { machines :: { {machineName} :: { settings :: {} } } } } } }
|
||||
# instance_foo.roles.peer ? settings;
|
||||
# roleSettingsEmpty =
|
||||
# lib.filterAttrs (n: _v: n != "__functor" ) res.evals.self-A.config.result.allMachines.jon.nixosModule. # { {instanceName} :: { roles :: { {roleName} :: { machines :: { {machineName} :: { settings :: {} } } } } } }
|
||||
# instance_foo.roles.peer.settings;
|
||||
# };
|
||||
# expected = {
|
||||
# hasMachineSettings = true;
|
||||
# machineSettingsEmpty = {};
|
||||
# hasRoleSettings = true;
|
||||
# roleSettingsEmpty = {};
|
||||
# };
|
||||
# };
|
||||
}
|
||||
|
||||
107
lib/distributed-service/tests/per_machine_args.nix
Normal file
107
lib/distributed-service/tests/per_machine_args.nix
Normal file
@@ -0,0 +1,107 @@
|
||||
{ lib, callInventoryAdapter }:
|
||||
|
||||
let # Authored module
|
||||
# A minimal module looks like this
|
||||
# It isn't exactly doing anything but it's a valid module that produces an output
|
||||
modules."A" = {
|
||||
_class = "clan.service";
|
||||
manifest = {
|
||||
name = "network";
|
||||
};
|
||||
# Define two roles with unmergeable interfaces
|
||||
# Both define some 'timeout' but with completely different types.
|
||||
roles.peer.interface =
|
||||
{ lib, ... }:
|
||||
{
|
||||
options.timeout = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
};
|
||||
roles.server.interface =
|
||||
{ lib, ... }:
|
||||
{
|
||||
options.timeout = lib.mkOption {
|
||||
type = lib.types.submodule;
|
||||
};
|
||||
};
|
||||
|
||||
perMachine =
|
||||
{ instances, ... }:
|
||||
{
|
||||
nixosModule = instances;
|
||||
};
|
||||
};
|
||||
machines = {
|
||||
jon = { };
|
||||
sara = { };
|
||||
};
|
||||
res = callInventoryAdapter {
|
||||
inherit modules machines;
|
||||
instances."instance_foo" = {
|
||||
module = {
|
||||
name = "A";
|
||||
};
|
||||
roles.peer.machines.jon = {
|
||||
settings.timeout = lib.mkForce "foo-peer-jon";
|
||||
};
|
||||
roles.peer = {
|
||||
settings.timeout = "foo-peer";
|
||||
};
|
||||
};
|
||||
instances."instance_bar" = {
|
||||
module = {
|
||||
name = "A";
|
||||
};
|
||||
roles.peer.machines.jon = {
|
||||
settings.timeout = "bar-peer-jon";
|
||||
};
|
||||
};
|
||||
instances."instance_zaza" = {
|
||||
module = {
|
||||
name = "B";
|
||||
};
|
||||
roles.peer.tags.all = { };
|
||||
};
|
||||
};
|
||||
|
||||
filterInternals = lib.filterAttrs (n: _v: !lib.hasPrefix "_" n);
|
||||
in
|
||||
|
||||
{
|
||||
|
||||
# settings should evaluate
|
||||
test_per_machine_receives_instance_settings = {
|
||||
expr = {
|
||||
hasMachineSettings =
|
||||
res.evals.self-A.config.result.allMachines.jon.nixosModule.instance_foo.roles.peer.machines.jon
|
||||
? settings;
|
||||
|
||||
# settings are specific.
|
||||
# Below we access:
|
||||
# instance = instance_foo
|
||||
# roles = peer
|
||||
# machines = jon
|
||||
specificMachineSettings = filterInternals res.evals.self-A.config.result.allMachines.jon.nixosModule.instance_foo.roles.peer.machines.jon.settings;
|
||||
|
||||
hasRoleSettings =
|
||||
res.evals.self-A.config.result.allMachines.jon.nixosModule.instance_foo.roles.peer ? settings;
|
||||
|
||||
# settings are specific.
|
||||
# Below we access:
|
||||
# instance = instance_foo
|
||||
# roles = peer
|
||||
# machines = *
|
||||
specificRoleSettings = filterInternals res.evals.self-A.config.result.allMachines.jon.nixosModule.instance_foo.roles.peer.settings;
|
||||
};
|
||||
expected = {
|
||||
hasMachineSettings = true;
|
||||
specificMachineSettings = {
|
||||
timeout = "foo-peer-jon";
|
||||
};
|
||||
hasRoleSettings = true;
|
||||
specificRoleSettings = {
|
||||
timeout = "foo-peer";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user