nixosTests: migrate tests to runTest (#389675)
This commit is contained in:
+43
-46
@@ -1,58 +1,55 @@
|
||||
import ./make-test-python.nix (
|
||||
{ ... }:
|
||||
{
|
||||
name = "acme-dns";
|
||||
{
|
||||
name = "acme-dns";
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
services.acme-dns = {
|
||||
enable = true;
|
||||
settings = {
|
||||
general = rec {
|
||||
domain = "acme-dns.home.arpa";
|
||||
nsname = domain;
|
||||
nsadmin = "admin.home.arpa";
|
||||
records = [
|
||||
"${domain}. A 127.0.0.1"
|
||||
"${domain}. AAAA ::1"
|
||||
"${domain}. NS ${domain}."
|
||||
];
|
||||
};
|
||||
logconfig.loglevel = "debug";
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
services.acme-dns = {
|
||||
enable = true;
|
||||
settings = {
|
||||
general = rec {
|
||||
domain = "acme-dns.home.arpa";
|
||||
nsname = domain;
|
||||
nsadmin = "admin.home.arpa";
|
||||
records = [
|
||||
"${domain}. A 127.0.0.1"
|
||||
"${domain}. AAAA ::1"
|
||||
"${domain}. NS ${domain}."
|
||||
];
|
||||
};
|
||||
logconfig.loglevel = "debug";
|
||||
};
|
||||
environment.systemPackages = with pkgs; [
|
||||
curl
|
||||
bind
|
||||
];
|
||||
};
|
||||
environment.systemPackages = with pkgs; [
|
||||
curl
|
||||
bind
|
||||
];
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
import json
|
||||
testScript = ''
|
||||
import json
|
||||
|
||||
machine.wait_for_unit("acme-dns.service")
|
||||
machine.wait_for_open_port(53) # dns
|
||||
machine.wait_for_open_port(8080) # http api
|
||||
machine.wait_for_unit("acme-dns.service")
|
||||
machine.wait_for_open_port(53) # dns
|
||||
machine.wait_for_open_port(8080) # http api
|
||||
|
||||
result = machine.succeed("curl --fail -X POST http://localhost:8080/register")
|
||||
print(result)
|
||||
result = machine.succeed("curl --fail -X POST http://localhost:8080/register")
|
||||
print(result)
|
||||
|
||||
registration = json.loads(result)
|
||||
registration = json.loads(result)
|
||||
|
||||
machine.succeed(f'dig -t TXT @localhost {registration["fulldomain"]} | grep "SOA" | grep "admin.home.arpa"')
|
||||
machine.succeed(f'dig -t TXT @localhost {registration["fulldomain"]} | grep "SOA" | grep "admin.home.arpa"')
|
||||
|
||||
# acme-dns exspects a TXT value string length of exactly 43 chars
|
||||
txt = "___dummy_validation_token_for_txt_record___"
|
||||
# acme-dns exspects a TXT value string length of exactly 43 chars
|
||||
txt = "___dummy_validation_token_for_txt_record___"
|
||||
|
||||
machine.succeed(
|
||||
"curl --fail -X POST http://localhost:8080/update "
|
||||
+ f' -H "X-Api-User: {registration["username"]}"'
|
||||
+ f' -H "X-Api-Key: {registration["password"]}"'
|
||||
+ f' -d \'{{"subdomain":"{registration["subdomain"]}", "txt":"{txt}"}}\'''
|
||||
)
|
||||
machine.succeed(
|
||||
"curl --fail -X POST http://localhost:8080/update "
|
||||
+ f' -H "X-Api-User: {registration["username"]}"'
|
||||
+ f' -H "X-Api-Key: {registration["password"]}"'
|
||||
+ f' -d \'{{"subdomain":"{registration["subdomain"]}", "txt":"{txt}"}}\'''
|
||||
)
|
||||
|
||||
assert txt in machine.succeed(f'dig -t TXT +short @localhost {registration["fulldomain"]}')
|
||||
'';
|
||||
}
|
||||
)
|
||||
assert txt in machine.succeed(f'dig -t TXT +short @localhost {registration["fulldomain"]}')
|
||||
'';
|
||||
}
|
||||
|
||||
+14
-16
@@ -1,18 +1,16 @@
|
||||
import ./make-test-python.nix (
|
||||
{ lib, ... }:
|
||||
{
|
||||
name = "actual";
|
||||
meta.maintainers = [ lib.maintainers.oddlama ];
|
||||
{ lib, ... }:
|
||||
{
|
||||
name = "actual";
|
||||
meta.maintainers = [ lib.maintainers.oddlama ];
|
||||
|
||||
nodes.machine =
|
||||
{ ... }:
|
||||
{
|
||||
services.actual.enable = true;
|
||||
};
|
||||
nodes.machine =
|
||||
{ ... }:
|
||||
{
|
||||
services.actual.enable = true;
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
machine.wait_for_open_port(3000)
|
||||
machine.succeed("curl -fvvv -Ls http://localhost:3000/ | grep 'Actual'")
|
||||
'';
|
||||
}
|
||||
)
|
||||
testScript = ''
|
||||
machine.wait_for_open_port(3000)
|
||||
machine.succeed("curl -fvvv -Ls http://localhost:3000/ | grep 'Actual'")
|
||||
'';
|
||||
}
|
||||
|
||||
+41
-43
@@ -1,49 +1,47 @@
|
||||
import ./make-test-python.nix (
|
||||
{ pkgs, ... }:
|
||||
{ pkgs, ... }:
|
||||
|
||||
let
|
||||
hello-world = pkgs.writeText "hello-world" ''
|
||||
{-# OPTIONS --guardedness #-}
|
||||
open import IO
|
||||
open import Level
|
||||
let
|
||||
hello-world = pkgs.writeText "hello-world" ''
|
||||
{-# OPTIONS --guardedness #-}
|
||||
open import IO
|
||||
open import Level
|
||||
|
||||
main = run {0ℓ} (putStrLn "Hello World!")
|
||||
'';
|
||||
in
|
||||
{
|
||||
name = "agda";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [
|
||||
alexarice
|
||||
turion
|
||||
main = run {0ℓ} (putStrLn "Hello World!")
|
||||
'';
|
||||
in
|
||||
{
|
||||
name = "agda";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [
|
||||
alexarice
|
||||
turion
|
||||
];
|
||||
};
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = [
|
||||
(pkgs.agda.withPackages {
|
||||
pkgs = p: [ p.standard-library ];
|
||||
})
|
||||
];
|
||||
virtualisation.memorySize = 2000; # Agda uses a lot of memory
|
||||
};
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = [
|
||||
(pkgs.agda.withPackages {
|
||||
pkgs = p: [ p.standard-library ];
|
||||
})
|
||||
];
|
||||
virtualisation.memorySize = 2000; # Agda uses a lot of memory
|
||||
};
|
||||
testScript = ''
|
||||
# Minimal script that typechecks
|
||||
machine.succeed("touch TestEmpty.agda")
|
||||
machine.succeed("agda TestEmpty.agda")
|
||||
|
||||
testScript = ''
|
||||
# Minimal script that typechecks
|
||||
machine.succeed("touch TestEmpty.agda")
|
||||
machine.succeed("agda TestEmpty.agda")
|
||||
|
||||
# Hello world
|
||||
machine.succeed(
|
||||
"cp ${hello-world} HelloWorld.agda"
|
||||
)
|
||||
machine.succeed("agda -l standard-library -i . -c HelloWorld.agda")
|
||||
# Check execution
|
||||
assert "Hello World!" in machine.succeed(
|
||||
"./HelloWorld"
|
||||
), "HelloWorld does not run properly"
|
||||
'';
|
||||
}
|
||||
)
|
||||
# Hello world
|
||||
machine.succeed(
|
||||
"cp ${hello-world} HelloWorld.agda"
|
||||
)
|
||||
machine.succeed("agda -l standard-library -i . -c HelloWorld.agda")
|
||||
# Check execution
|
||||
assert "Hello World!" in machine.succeed(
|
||||
"./HelloWorld"
|
||||
), "HelloWorld does not run properly"
|
||||
'';
|
||||
}
|
||||
|
||||
+25
-27
@@ -1,32 +1,30 @@
|
||||
import ./make-test-python.nix (
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
name = "airsonic";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ sumnerevans ];
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
name = "airsonic";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ sumnerevans ];
|
||||
};
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
services.airsonic = {
|
||||
enable = true;
|
||||
maxMemory = 800;
|
||||
};
|
||||
};
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
services.airsonic = {
|
||||
enable = true;
|
||||
maxMemory = 800;
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
def airsonic_is_up(_) -> bool:
|
||||
status, _ = machine.execute("curl --fail http://localhost:4040/login")
|
||||
return status == 0
|
||||
testScript = ''
|
||||
def airsonic_is_up(_) -> bool:
|
||||
status, _ = machine.execute("curl --fail http://localhost:4040/login")
|
||||
return status == 0
|
||||
|
||||
|
||||
machine.start()
|
||||
machine.wait_for_unit("airsonic.service")
|
||||
machine.wait_for_open_port(4040)
|
||||
machine.start()
|
||||
machine.wait_for_unit("airsonic.service")
|
||||
machine.wait_for_open_port(4040)
|
||||
|
||||
with machine.nested("Waiting for UI to work"):
|
||||
retry(airsonic_is_up)
|
||||
'';
|
||||
}
|
||||
)
|
||||
with machine.nested("Waiting for UI to work"):
|
||||
retry(airsonic_is_up)
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -1,18 +1,10 @@
|
||||
# This test does a basic functionality check for alice-lg
|
||||
|
||||
{
|
||||
system ? builtins.currentSystem,
|
||||
pkgs ? import ../.. {
|
||||
inherit system;
|
||||
config = { };
|
||||
},
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (import ../lib/testing-python.nix { inherit system pkgs; }) makeTest;
|
||||
inherit (pkgs.lib) optionalString;
|
||||
in
|
||||
makeTest {
|
||||
{
|
||||
name = "alice-lg";
|
||||
nodes = {
|
||||
host1 = {
|
||||
|
||||
@@ -1,48 +1,46 @@
|
||||
import ./make-test-python.nix (
|
||||
{ pkgs, ... }:
|
||||
rec {
|
||||
name = "all-terminfo";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ jkarlson ];
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
name = "all-terminfo";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ jkarlson ];
|
||||
};
|
||||
|
||||
nodes.machine =
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
infoFilter =
|
||||
name: drv:
|
||||
let
|
||||
o = builtins.tryEval drv;
|
||||
in
|
||||
o.success
|
||||
&& lib.isDerivation o.value
|
||||
&& o.value ? outputs
|
||||
&& builtins.elem "terminfo" o.value.outputs
|
||||
&& !o.value.meta.broken;
|
||||
terminfos = lib.filterAttrs infoFilter pkgs;
|
||||
excludedTerminfos = lib.filterAttrs (
|
||||
_: drv: !(builtins.elem drv.terminfo config.environment.systemPackages)
|
||||
) terminfos;
|
||||
includedOuts = lib.filterAttrs (
|
||||
_: drv: builtins.elem drv.out config.environment.systemPackages
|
||||
) terminfos;
|
||||
in
|
||||
{
|
||||
environment = {
|
||||
enableAllTerminfo = true;
|
||||
etc."terminfo-missing".text = builtins.concatStringsSep "\n" (builtins.attrNames excludedTerminfos);
|
||||
etc."terminfo-extra-outs".text = builtins.concatStringsSep "\n" (builtins.attrNames includedOuts);
|
||||
};
|
||||
};
|
||||
|
||||
nodes.machine =
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
infoFilter =
|
||||
name: drv:
|
||||
let
|
||||
o = builtins.tryEval drv;
|
||||
in
|
||||
o.success
|
||||
&& lib.isDerivation o.value
|
||||
&& o.value ? outputs
|
||||
&& builtins.elem "terminfo" o.value.outputs
|
||||
&& !o.value.meta.broken;
|
||||
terminfos = lib.filterAttrs infoFilter pkgs;
|
||||
excludedTerminfos = lib.filterAttrs (
|
||||
_: drv: !(builtins.elem drv.terminfo config.environment.systemPackages)
|
||||
) terminfos;
|
||||
includedOuts = lib.filterAttrs (
|
||||
_: drv: builtins.elem drv.out config.environment.systemPackages
|
||||
) terminfos;
|
||||
in
|
||||
{
|
||||
environment = {
|
||||
enableAllTerminfo = true;
|
||||
etc."terminfo-missing".text = builtins.concatStringsSep "\n" (builtins.attrNames excludedTerminfos);
|
||||
etc."terminfo-extra-outs".text = builtins.concatStringsSep "\n" (builtins.attrNames includedOuts);
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
machine.fail("grep . /etc/terminfo-missing >&2")
|
||||
machine.fail("grep . /etc/terminfo-extra-outs >&2")
|
||||
'';
|
||||
}
|
||||
)
|
||||
testScript = ''
|
||||
machine.fail("grep . /etc/terminfo-missing >&2")
|
||||
machine.fail("grep . /etc/terminfo-extra-outs >&2")
|
||||
'';
|
||||
}
|
||||
|
||||
+33
-27
@@ -147,48 +147,54 @@ in {
|
||||
_3proxy = runTest ./3proxy.nix;
|
||||
aaaaxy = runTest ./aaaaxy.nix;
|
||||
acme = import ./acme/default.nix { inherit runTest; };
|
||||
acme-dns = handleTest ./acme-dns.nix {};
|
||||
actual = handleTest ./actual.nix {};
|
||||
acme-dns = runTest ./acme-dns.nix;
|
||||
actual = runTest ./actual.nix;
|
||||
adguardhome = runTest ./adguardhome.nix;
|
||||
aesmd = runTestOn ["x86_64-linux"] ./aesmd.nix;
|
||||
agate = runTest ./web-servers/agate.nix;
|
||||
agda = handleTest ./agda.nix {};
|
||||
agda = runTest ./agda.nix;
|
||||
age-plugin-tpm-decrypt = runTest ./age-plugin-tpm-decrypt.nix;
|
||||
agorakit = runTest ./web-apps/agorakit.nix;
|
||||
airsonic = handleTest ./airsonic.nix {};
|
||||
airsonic = runTest ./airsonic.nix;
|
||||
akkoma = handleTestOn [ "x86_64-linux" "aarch64-linux" ] ./akkoma.nix {};
|
||||
akkoma-confined = handleTestOn [ "x86_64-linux" "aarch64-linux" ] ./akkoma.nix { confined = true; };
|
||||
alice-lg = handleTest ./alice-lg.nix {};
|
||||
alloy = handleTest ./alloy.nix {};
|
||||
allTerminfo = handleTest ./all-terminfo.nix {};
|
||||
alps = handleTest ./alps.nix {};
|
||||
amazon-cloudwatch-agent = handleTest ./amazon-cloudwatch-agent.nix {};
|
||||
amazon-init-shell = handleTest ./amazon-init-shell.nix {};
|
||||
amazon-ssm-agent = handleTest ./amazon-ssm-agent.nix {};
|
||||
alice-lg = runTest ./alice-lg.nix;
|
||||
alloy = runTest ./alloy.nix;
|
||||
allTerminfo = runTest ./all-terminfo.nix;
|
||||
alps = runTest ./alps.nix;
|
||||
amazon-cloudwatch-agent = runTest ./amazon-cloudwatch-agent.nix;
|
||||
amazon-init-shell = runTest ./amazon-init-shell.nix;
|
||||
amazon-ssm-agent = runTest ./amazon-ssm-agent.nix;
|
||||
amd-sev = runTest ./amd-sev.nix;
|
||||
angie-api = handleTest ./angie-api.nix {};
|
||||
anki-sync-server = handleTest ./anki-sync-server.nix {};
|
||||
anuko-time-tracker = handleTest ./anuko-time-tracker.nix {};
|
||||
apcupsd = handleTest ./apcupsd.nix {};
|
||||
angie-api = runTest ./angie-api.nix;
|
||||
anki-sync-server = runTest ./anki-sync-server.nix;
|
||||
anuko-time-tracker = runTest ./anuko-time-tracker.nix;
|
||||
apcupsd = runTest ./apcupsd.nix;
|
||||
apfs = runTest ./apfs.nix;
|
||||
appliance-repart-image = runTest ./appliance-repart-image.nix;
|
||||
appliance-repart-image-verity-store = runTest ./appliance-repart-image-verity-store.nix;
|
||||
apparmor = handleTest ./apparmor {};
|
||||
archi = handleTest ./archi.nix {};
|
||||
aria2 = handleTest ./aria2.nix {};
|
||||
armagetronad = handleTest ./armagetronad.nix {};
|
||||
apparmor = runTest ./apparmor;
|
||||
archi = runTest ./archi.nix;
|
||||
aria2 = runTest ./aria2.nix;
|
||||
armagetronad = runTest ./armagetronad.nix;
|
||||
artalk = runTest ./artalk.nix;
|
||||
atd = handleTest ./atd.nix {};
|
||||
atd = runTest ./atd.nix;
|
||||
atop = handleTest ./atop.nix {};
|
||||
atticd = runTest ./atticd.nix;
|
||||
atuin = runTest ./atuin.nix;
|
||||
audiobookshelf = handleTest ./audiobookshelf.nix {};
|
||||
auth-mysql = handleTest ./auth-mysql.nix {};
|
||||
authelia = handleTest ./authelia.nix {};
|
||||
auto-cpufreq = handleTest ./auto-cpufreq.nix {};
|
||||
autobrr = handleTest ./autobrr.nix {};
|
||||
avahi = handleTest ./avahi.nix {};
|
||||
avahi-with-resolved = handleTest ./avahi.nix { networkd = true; };
|
||||
audiobookshelf = runTest ./audiobookshelf.nix;
|
||||
auth-mysql = runTest ./auth-mysql.nix;
|
||||
authelia = runTest ./authelia.nix;
|
||||
auto-cpufreq = runTest ./auto-cpufreq.nix;
|
||||
autobrr = runTest ./autobrr.nix;
|
||||
avahi = runTest {
|
||||
imports = [ ./avahi.nix ];
|
||||
_module.args.networkd = false;
|
||||
};
|
||||
avahi-with-resolved = runTest {
|
||||
imports = [ ./avahi.nix ];
|
||||
_module.args.networkd = true;
|
||||
};
|
||||
ayatana-indicators = runTest ./ayatana-indicators.nix;
|
||||
babeld = runTest ./babeld.nix;
|
||||
bazarr = handleTest ./bazarr.nix {};
|
||||
|
||||
+28
-30
@@ -1,37 +1,35 @@
|
||||
import ./make-test-python.nix (
|
||||
{ lib, pkgs, ... }:
|
||||
{ lib, ... }:
|
||||
|
||||
let
|
||||
nodes = {
|
||||
machine = {
|
||||
services.alloy = {
|
||||
enable = true;
|
||||
};
|
||||
environment.etc."alloy/config.alloy".text = "";
|
||||
let
|
||||
nodes = {
|
||||
machine = {
|
||||
services.alloy = {
|
||||
enable = true;
|
||||
};
|
||||
environment.etc."alloy/config.alloy".text = "";
|
||||
};
|
||||
in
|
||||
{
|
||||
name = "alloy";
|
||||
};
|
||||
in
|
||||
{
|
||||
name = "alloy";
|
||||
|
||||
meta = with lib.maintainers; {
|
||||
maintainers = [
|
||||
flokli
|
||||
hbjydev
|
||||
];
|
||||
};
|
||||
meta = with lib.maintainers; {
|
||||
maintainers = [
|
||||
flokli
|
||||
hbjydev
|
||||
];
|
||||
};
|
||||
|
||||
inherit nodes;
|
||||
inherit nodes;
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
machine.wait_for_unit("alloy.service")
|
||||
machine.wait_for_open_port(12345)
|
||||
machine.succeed(
|
||||
"curl -sSfN http://127.0.0.1:12345/-/healthy"
|
||||
)
|
||||
machine.shutdown()
|
||||
'';
|
||||
}
|
||||
)
|
||||
machine.wait_for_unit("alloy.service")
|
||||
machine.wait_for_open_port(12345)
|
||||
machine.succeed(
|
||||
"curl -sSfN http://127.0.0.1:12345/-/healthy"
|
||||
)
|
||||
machine.shutdown()
|
||||
'';
|
||||
}
|
||||
|
||||
+101
-103
@@ -2,118 +2,116 @@ let
|
||||
certs = import ./common/acme/server/snakeoil-certs.nix;
|
||||
domain = certs.domain;
|
||||
in
|
||||
import ./make-test-python.nix (
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
name = "alps";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ hmenke ];
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
name = "alps";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ hmenke ];
|
||||
};
|
||||
|
||||
nodes = {
|
||||
server = {
|
||||
imports = [ ./common/user-account.nix ];
|
||||
security.pki.certificateFiles = [
|
||||
certs.ca.cert
|
||||
];
|
||||
networking.extraHosts = ''
|
||||
127.0.0.1 ${domain}
|
||||
'';
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
25
|
||||
465
|
||||
993
|
||||
];
|
||||
services.postfix = {
|
||||
enable = true;
|
||||
enableSubmission = true;
|
||||
enableSubmissions = true;
|
||||
tlsTrustedAuthorities = "${certs.ca.cert}";
|
||||
sslCert = "${certs.${domain}.cert}";
|
||||
sslKey = "${certs.${domain}.key}";
|
||||
};
|
||||
services.dovecot2 = {
|
||||
enable = true;
|
||||
enableImap = true;
|
||||
sslCACert = "${certs.ca.cert}";
|
||||
sslServerCert = "${certs.${domain}.cert}";
|
||||
sslServerKey = "${certs.${domain}.key}";
|
||||
};
|
||||
};
|
||||
|
||||
nodes = {
|
||||
server = {
|
||||
imports = [ ./common/user-account.nix ];
|
||||
client =
|
||||
{ nodes, config, ... }:
|
||||
{
|
||||
security.pki.certificateFiles = [
|
||||
certs.ca.cert
|
||||
];
|
||||
networking.extraHosts = ''
|
||||
127.0.0.1 ${domain}
|
||||
${nodes.server.config.networking.primaryIPAddress} ${domain}
|
||||
'';
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
25
|
||||
465
|
||||
993
|
||||
];
|
||||
services.postfix = {
|
||||
services.alps = {
|
||||
enable = true;
|
||||
enableSubmission = true;
|
||||
enableSubmissions = true;
|
||||
tlsTrustedAuthorities = "${certs.ca.cert}";
|
||||
sslCert = "${certs.${domain}.cert}";
|
||||
sslKey = "${certs.${domain}.key}";
|
||||
};
|
||||
services.dovecot2 = {
|
||||
enable = true;
|
||||
enableImap = true;
|
||||
sslCACert = "${certs.ca.cert}";
|
||||
sslServerCert = "${certs.${domain}.cert}";
|
||||
sslServerKey = "${certs.${domain}.key}";
|
||||
};
|
||||
};
|
||||
|
||||
client =
|
||||
{ nodes, config, ... }:
|
||||
{
|
||||
security.pki.certificateFiles = [
|
||||
certs.ca.cert
|
||||
];
|
||||
networking.extraHosts = ''
|
||||
${nodes.server.config.networking.primaryIPAddress} ${domain}
|
||||
'';
|
||||
services.alps = {
|
||||
enable = true;
|
||||
theme = "alps";
|
||||
imaps = {
|
||||
host = domain;
|
||||
port = 993;
|
||||
};
|
||||
smtps = {
|
||||
host = domain;
|
||||
port = 465;
|
||||
};
|
||||
theme = "alps";
|
||||
imaps = {
|
||||
host = domain;
|
||||
port = 993;
|
||||
};
|
||||
smtps = {
|
||||
host = domain;
|
||||
port = 465;
|
||||
};
|
||||
environment.systemPackages = [
|
||||
(pkgs.writers.writePython3Bin "test-alps-login" { } ''
|
||||
from urllib.request import build_opener, HTTPCookieProcessor, Request
|
||||
from urllib.parse import urlencode, urljoin
|
||||
from http.cookiejar import CookieJar
|
||||
|
||||
baseurl = "http://localhost:${toString config.services.alps.port}"
|
||||
username = "alice"
|
||||
password = "${nodes.server.config.users.users.alice.password}"
|
||||
cookiejar = CookieJar()
|
||||
cookieprocessor = HTTPCookieProcessor(cookiejar)
|
||||
opener = build_opener(cookieprocessor)
|
||||
|
||||
data = urlencode({"username": username, "password": password}).encode()
|
||||
req = Request(urljoin(baseurl, "login"), data=data, method="POST")
|
||||
with opener.open(req) as ret:
|
||||
# Check that the alps_session cookie is set
|
||||
print(cookiejar)
|
||||
assert any(cookie.name == "alps_session" for cookie in cookiejar)
|
||||
|
||||
req = Request(baseurl)
|
||||
with opener.open(req) as ret:
|
||||
# Check that the alps_session cookie is still there...
|
||||
print(cookiejar)
|
||||
assert any(cookie.name == "alps_session" for cookie in cookiejar)
|
||||
# ...and that we have not been redirected back to the login page
|
||||
print(ret.url)
|
||||
assert ret.url == urljoin(baseurl, "mailbox/INBOX")
|
||||
|
||||
req = Request(urljoin(baseurl, "logout"))
|
||||
with opener.open(req) as ret:
|
||||
# Check that the alps_session cookie is now gone
|
||||
print(cookiejar)
|
||||
assert all(cookie.name != "alps_session" for cookie in cookiejar)
|
||||
'')
|
||||
];
|
||||
};
|
||||
};
|
||||
environment.systemPackages = [
|
||||
(pkgs.writers.writePython3Bin "test-alps-login" { } ''
|
||||
from urllib.request import build_opener, HTTPCookieProcessor, Request
|
||||
from urllib.parse import urlencode, urljoin
|
||||
from http.cookiejar import CookieJar
|
||||
|
||||
testScript =
|
||||
{ nodes, ... }:
|
||||
''
|
||||
server.start()
|
||||
server.wait_for_unit("postfix.service")
|
||||
server.wait_for_unit("dovecot2.service")
|
||||
server.wait_for_open_port(465)
|
||||
server.wait_for_open_port(993)
|
||||
baseurl = "http://localhost:${toString config.services.alps.port}"
|
||||
username = "alice"
|
||||
password = "${nodes.server.config.users.users.alice.password}"
|
||||
cookiejar = CookieJar()
|
||||
cookieprocessor = HTTPCookieProcessor(cookiejar)
|
||||
opener = build_opener(cookieprocessor)
|
||||
|
||||
client.start()
|
||||
client.wait_for_unit("alps.service")
|
||||
client.wait_for_open_port(${toString nodes.client.config.services.alps.port})
|
||||
client.succeed("test-alps-login")
|
||||
'';
|
||||
}
|
||||
)
|
||||
data = urlencode({"username": username, "password": password}).encode()
|
||||
req = Request(urljoin(baseurl, "login"), data=data, method="POST")
|
||||
with opener.open(req) as ret:
|
||||
# Check that the alps_session cookie is set
|
||||
print(cookiejar)
|
||||
assert any(cookie.name == "alps_session" for cookie in cookiejar)
|
||||
|
||||
req = Request(baseurl)
|
||||
with opener.open(req) as ret:
|
||||
# Check that the alps_session cookie is still there...
|
||||
print(cookiejar)
|
||||
assert any(cookie.name == "alps_session" for cookie in cookiejar)
|
||||
# ...and that we have not been redirected back to the login page
|
||||
print(ret.url)
|
||||
assert ret.url == urljoin(baseurl, "mailbox/INBOX")
|
||||
|
||||
req = Request(urljoin(baseurl, "logout"))
|
||||
with opener.open(req) as ret:
|
||||
# Check that the alps_session cookie is now gone
|
||||
print(cookiejar)
|
||||
assert all(cookie.name != "alps_session" for cookie in cookiejar)
|
||||
'')
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
testScript =
|
||||
{ nodes, ... }:
|
||||
''
|
||||
server.start()
|
||||
server.wait_for_unit("postfix.service")
|
||||
server.wait_for_unit("dovecot2.service")
|
||||
server.wait_for_open_port(465)
|
||||
server.wait_for_open_port(993)
|
||||
|
||||
client.start()
|
||||
client.wait_for_unit("alps.service")
|
||||
client.wait_for_open_port(${toString nodes.client.config.services.alps.port})
|
||||
client.succeed("test-alps-login")
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -1,92 +1,90 @@
|
||||
import ./make-test-python.nix (
|
||||
{ lib, pkgs, ... }:
|
||||
let
|
||||
# See https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html.
|
||||
iniFormat = pkgs.formats.ini { };
|
||||
{ pkgs, ... }:
|
||||
let
|
||||
# See https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html.
|
||||
iniFormat = pkgs.formats.ini { };
|
||||
|
||||
region = "ap-northeast-1";
|
||||
sharedConfigurationDefaultProfile = "default";
|
||||
sharedConfigurationFile = iniFormat.generate "config" {
|
||||
"${sharedConfigurationDefaultProfile}" = {
|
||||
region = region;
|
||||
};
|
||||
region = "ap-northeast-1";
|
||||
sharedConfigurationDefaultProfile = "default";
|
||||
sharedConfigurationFile = iniFormat.generate "config" {
|
||||
"${sharedConfigurationDefaultProfile}" = {
|
||||
region = region;
|
||||
};
|
||||
sharedCredentialsFile = iniFormat.generate "credentials" {
|
||||
"${sharedConfigurationDefaultProfile}" = {
|
||||
aws_access_key_id = "placeholder";
|
||||
aws_secret_access_key = "placeholder";
|
||||
aws_session_token = "placeholder";
|
||||
};
|
||||
};
|
||||
sharedCredentialsFile = iniFormat.generate "credentials" {
|
||||
"${sharedConfigurationDefaultProfile}" = {
|
||||
aws_access_key_id = "placeholder";
|
||||
aws_secret_access_key = "placeholder";
|
||||
aws_session_token = "placeholder";
|
||||
};
|
||||
sharedConfigurationDirectory = pkgs.runCommand ".aws" { } ''
|
||||
mkdir $out
|
||||
};
|
||||
sharedConfigurationDirectory = pkgs.runCommand ".aws" { } ''
|
||||
mkdir $out
|
||||
|
||||
cp ${sharedConfigurationFile} $out/config
|
||||
cp ${sharedCredentialsFile} $out/credentials
|
||||
'';
|
||||
in
|
||||
{
|
||||
name = "amazon-cloudwatch-agent";
|
||||
cp ${sharedConfigurationFile} $out/config
|
||||
cp ${sharedCredentialsFile} $out/credentials
|
||||
'';
|
||||
in
|
||||
{
|
||||
name = "amazon-cloudwatch-agent";
|
||||
|
||||
nodes.machine =
|
||||
{ config, pkgs, ... }:
|
||||
{
|
||||
services.amazon-cloudwatch-agent = {
|
||||
enable = true;
|
||||
commonConfiguration = {
|
||||
credentials = {
|
||||
shared_credential_profile = sharedConfigurationDefaultProfile;
|
||||
shared_credential_file = "${sharedConfigurationDirectory}/credentials";
|
||||
};
|
||||
nodes.machine =
|
||||
{ config, pkgs, ... }:
|
||||
{
|
||||
services.amazon-cloudwatch-agent = {
|
||||
enable = true;
|
||||
commonConfiguration = {
|
||||
credentials = {
|
||||
shared_credential_profile = sharedConfigurationDefaultProfile;
|
||||
shared_credential_file = "${sharedConfigurationDirectory}/credentials";
|
||||
};
|
||||
configuration = {
|
||||
agent = {
|
||||
# Required despite documentation saying the agent ignores it in "onPremise" mode.
|
||||
region = region;
|
||||
|
||||
# Show debug logs and write to a file for interactive debugging.
|
||||
debug = true;
|
||||
logfile = "/var/log/amazon-cloudwatch-agent/amazon-cloudwatch-agent.log";
|
||||
};
|
||||
logs = {
|
||||
logs_collected = {
|
||||
files = {
|
||||
collect_list = [
|
||||
{
|
||||
file_path = "/var/log/amazon-cloudwatch-agent/amazon-cloudwatch-agent.log";
|
||||
log_group_name = "/var/log/amazon-cloudwatch-agent/amazon-cloudwatch-agent.log";
|
||||
log_stream_name = "{local_hostname}";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
traces = {
|
||||
local_mode = true;
|
||||
traces_collected = {
|
||||
xray = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
mode = "onPremise";
|
||||
};
|
||||
configuration = {
|
||||
agent = {
|
||||
# Required despite documentation saying the agent ignores it in "onPremise" mode.
|
||||
region = region;
|
||||
|
||||
# Keep the runtime directory for interactive debugging.
|
||||
systemd.services.amazon-cloudwatch-agent.serviceConfig.RuntimeDirectoryPreserve = true;
|
||||
# Show debug logs and write to a file for interactive debugging.
|
||||
debug = true;
|
||||
logfile = "/var/log/amazon-cloudwatch-agent/amazon-cloudwatch-agent.log";
|
||||
};
|
||||
logs = {
|
||||
logs_collected = {
|
||||
files = {
|
||||
collect_list = [
|
||||
{
|
||||
file_path = "/var/log/amazon-cloudwatch-agent/amazon-cloudwatch-agent.log";
|
||||
log_group_name = "/var/log/amazon-cloudwatch-agent/amazon-cloudwatch-agent.log";
|
||||
log_stream_name = "{local_hostname}";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
traces = {
|
||||
local_mode = true;
|
||||
traces_collected = {
|
||||
xray = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
mode = "onPremise";
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
# Keep the runtime directory for interactive debugging.
|
||||
systemd.services.amazon-cloudwatch-agent.serviceConfig.RuntimeDirectoryPreserve = true;
|
||||
};
|
||||
|
||||
machine.wait_for_unit("amazon-cloudwatch-agent.service")
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
machine.wait_for_file("/run/amazon-cloudwatch-agent/amazon-cloudwatch-agent.pid")
|
||||
machine.wait_for_file("/run/amazon-cloudwatch-agent/amazon-cloudwatch-agent.toml")
|
||||
# "config-translator" omits this file if no trace configurations are specified.
|
||||
#
|
||||
# See https://github.com/aws/amazon-cloudwatch-agent/issues/1320.
|
||||
machine.wait_for_file("/run/amazon-cloudwatch-agent/amazon-cloudwatch-agent.yaml")
|
||||
machine.wait_for_file("/run/amazon-cloudwatch-agent/env-config.json")
|
||||
'';
|
||||
}
|
||||
)
|
||||
machine.wait_for_unit("amazon-cloudwatch-agent.service")
|
||||
|
||||
machine.wait_for_file("/run/amazon-cloudwatch-agent/amazon-cloudwatch-agent.pid")
|
||||
machine.wait_for_file("/run/amazon-cloudwatch-agent/amazon-cloudwatch-agent.toml")
|
||||
# "config-translator" omits this file if no trace configurations are specified.
|
||||
#
|
||||
# See https://github.com/aws/amazon-cloudwatch-agent/issues/1320.
|
||||
machine.wait_for_file("/run/amazon-cloudwatch-agent/amazon-cloudwatch-agent.yaml")
|
||||
machine.wait_for_file("/run/amazon-cloudwatch-agent/env-config.json")
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -6,41 +6,35 @@
|
||||
# configuration expression.
|
||||
|
||||
{
|
||||
system ? builtins.currentSystem,
|
||||
config ? { },
|
||||
pkgs ? import ../.. { inherit system config; },
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
with import ../lib/testing-python.nix { inherit system pkgs; };
|
||||
with pkgs.lib;
|
||||
|
||||
makeTest {
|
||||
{
|
||||
name = "amazon-init";
|
||||
meta = with maintainers; {
|
||||
meta = with lib.maintainers; {
|
||||
maintainers = [ urbas ];
|
||||
};
|
||||
nodes.machine =
|
||||
{ lib, pkgs, ... }:
|
||||
{
|
||||
imports = [
|
||||
../modules/profiles/headless.nix
|
||||
../modules/virtualisation/amazon-init.nix
|
||||
];
|
||||
services.openssh.enable = true;
|
||||
system.switch.enable = true;
|
||||
networking.hostName = "";
|
||||
environment.etc."ec2-metadata/user-data" = {
|
||||
text = ''
|
||||
#!/usr/bin/bash
|
||||
nodes.machine = {
|
||||
imports = [
|
||||
../modules/profiles/headless.nix
|
||||
../modules/virtualisation/amazon-init.nix
|
||||
];
|
||||
services.openssh.enable = true;
|
||||
system.switch.enable = true;
|
||||
networking.hostName = "";
|
||||
environment.etc."ec2-metadata/user-data" = {
|
||||
text = ''
|
||||
#!/usr/bin/bash
|
||||
|
||||
echo successful > /tmp/evidence
|
||||
echo successful > /tmp/evidence
|
||||
|
||||
# Emulate running nixos-rebuild switch, just without any building.
|
||||
# https://github.com/nixos/nixpkgs/blob/4c62505847d88f16df11eff3c81bf9a453a4979e/nixos/modules/virtualisation/amazon-init.nix#L55
|
||||
/run/current-system/bin/switch-to-configuration test
|
||||
'';
|
||||
};
|
||||
# Emulate running nixos-rebuild switch, just without any building.
|
||||
# https://github.com/nixos/nixpkgs/blob/4c62505847d88f16df11eff3c81bf9a453a4979e/nixos/modules/virtualisation/amazon-init.nix#L55
|
||||
/run/current-system/bin/switch-to-configuration test
|
||||
'';
|
||||
};
|
||||
};
|
||||
testScript = ''
|
||||
# To wait until amazon-init terminates its run
|
||||
unnamed.wait_for_unit("amazon-init.service")
|
||||
|
||||
@@ -1,22 +1,18 @@
|
||||
import ./make-test-python.nix (
|
||||
{ lib, pkgs, ... }:
|
||||
{
|
||||
name = "amazon-ssm-agent";
|
||||
meta.maintainers = [ lib.maintainers.anthonyroussel ];
|
||||
{ lib, ... }:
|
||||
{
|
||||
name = "amazon-ssm-agent";
|
||||
meta.maintainers = [ lib.maintainers.anthonyroussel ];
|
||||
|
||||
nodes.machine =
|
||||
{ config, pkgs, ... }:
|
||||
{
|
||||
services.amazon-ssm-agent.enable = true;
|
||||
};
|
||||
nodes.machine = {
|
||||
services.amazon-ssm-agent.enable = true;
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
machine.wait_for_file("/etc/amazon/ssm/seelog.xml")
|
||||
machine.wait_for_file("/etc/amazon/ssm/amazon-ssm-agent.json")
|
||||
machine.wait_for_file("/etc/amazon/ssm/seelog.xml")
|
||||
machine.wait_for_file("/etc/amazon/ssm/amazon-ssm-agent.json")
|
||||
|
||||
machine.wait_for_unit("amazon-ssm-agent.service")
|
||||
'';
|
||||
}
|
||||
)
|
||||
machine.wait_for_unit("amazon-ssm-agent.service")
|
||||
'';
|
||||
}
|
||||
|
||||
+143
-145
@@ -1,170 +1,168 @@
|
||||
import ./make-test-python.nix (
|
||||
{ lib, pkgs, ... }:
|
||||
let
|
||||
hosts = ''
|
||||
192.168.2.101 example.com
|
||||
192.168.2.101 api.example.com
|
||||
192.168.2.101 backend.example.com
|
||||
'';
|
||||
{ lib, pkgs, ... }:
|
||||
let
|
||||
hosts = ''
|
||||
192.168.2.101 example.com
|
||||
192.168.2.101 api.example.com
|
||||
192.168.2.101 backend.example.com
|
||||
'';
|
||||
|
||||
in
|
||||
{
|
||||
name = "angie-api";
|
||||
meta.maintainers = with pkgs.lib.maintainers; [ izorkin ];
|
||||
in
|
||||
{
|
||||
name = "angie-api";
|
||||
meta.maintainers = with pkgs.lib.maintainers; [ izorkin ];
|
||||
|
||||
nodes = {
|
||||
server =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
networking = {
|
||||
interfaces.eth1 = {
|
||||
ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.2.101";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
nodes = {
|
||||
server =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
networking = {
|
||||
interfaces.eth1 = {
|
||||
ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.2.101";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
};
|
||||
extraHosts = hosts;
|
||||
firewall.allowedTCPPorts = [ 80 ];
|
||||
};
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
package = pkgs.angie;
|
||||
|
||||
upstreams = {
|
||||
"backend-http" = {
|
||||
servers = {
|
||||
"backend.example.com:8080" = {
|
||||
fail_timeout = "0";
|
||||
};
|
||||
};
|
||||
extraConfig = ''
|
||||
zone upstream 256k;
|
||||
'';
|
||||
};
|
||||
"backend-socket" = {
|
||||
servers = {
|
||||
"unix:/run/example.sock" = {
|
||||
fail_timeout = "0";
|
||||
};
|
||||
};
|
||||
extraConfig = ''
|
||||
zone upstream 256k;
|
||||
'';
|
||||
};
|
||||
extraHosts = hosts;
|
||||
firewall.allowedTCPPorts = [ 80 ];
|
||||
};
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
package = pkgs.angie;
|
||||
virtualHosts."api.example.com" = {
|
||||
locations."/console/" = {
|
||||
extraConfig = ''
|
||||
api /status/;
|
||||
|
||||
upstreams = {
|
||||
"backend-http" = {
|
||||
servers = {
|
||||
"backend.example.com:8080" = {
|
||||
fail_timeout = "0";
|
||||
};
|
||||
};
|
||||
extraConfig = ''
|
||||
zone upstream 256k;
|
||||
'';
|
||||
};
|
||||
"backend-socket" = {
|
||||
servers = {
|
||||
"unix:/run/example.sock" = {
|
||||
fail_timeout = "0";
|
||||
};
|
||||
};
|
||||
extraConfig = ''
|
||||
zone upstream 256k;
|
||||
'';
|
||||
};
|
||||
allow 192.168.2.201;
|
||||
deny all;
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
virtualHosts."api.example.com" = {
|
||||
locations."/console/" = {
|
||||
extraConfig = ''
|
||||
api /status/;
|
||||
virtualHosts."example.com" = {
|
||||
locations."/test/" = {
|
||||
root = lib.mkForce (
|
||||
pkgs.runCommandLocal "testdir" { } ''
|
||||
mkdir -p "$out/test"
|
||||
cat > "$out/test/index.html" <<EOF
|
||||
<html><body>Hello World!</body></html>
|
||||
EOF
|
||||
''
|
||||
);
|
||||
extraConfig = ''
|
||||
status_zone test_zone;
|
||||
|
||||
allow 192.168.2.201;
|
||||
deny all;
|
||||
'';
|
||||
};
|
||||
allow 192.168.2.201;
|
||||
deny all;
|
||||
'';
|
||||
};
|
||||
locations."/test/locked/" = {
|
||||
extraConfig = ''
|
||||
status_zone test_zone;
|
||||
|
||||
virtualHosts."example.com" = {
|
||||
locations."/test/" = {
|
||||
root = lib.mkForce (
|
||||
pkgs.runCommandLocal "testdir" { } ''
|
||||
mkdir -p "$out/test"
|
||||
cat > "$out/test/index.html" <<EOF
|
||||
<html><body>Hello World!</body></html>
|
||||
EOF
|
||||
''
|
||||
);
|
||||
extraConfig = ''
|
||||
status_zone test_zone;
|
||||
deny all;
|
||||
'';
|
||||
};
|
||||
locations."/test/error/" = {
|
||||
extraConfig = ''
|
||||
status_zone test_zone;
|
||||
|
||||
allow 192.168.2.201;
|
||||
deny all;
|
||||
'';
|
||||
};
|
||||
locations."/test/locked/" = {
|
||||
extraConfig = ''
|
||||
status_zone test_zone;
|
||||
|
||||
deny all;
|
||||
'';
|
||||
};
|
||||
locations."/test/error/" = {
|
||||
extraConfig = ''
|
||||
status_zone test_zone;
|
||||
|
||||
allow all;
|
||||
'';
|
||||
};
|
||||
locations."/upstream-http/" = {
|
||||
proxyPass = "http://backend-http";
|
||||
};
|
||||
locations."/upstream-socket/" = {
|
||||
proxyPass = "http://backend-socket";
|
||||
};
|
||||
allow all;
|
||||
'';
|
||||
};
|
||||
locations."/upstream-http/" = {
|
||||
proxyPass = "http://backend-http";
|
||||
};
|
||||
locations."/upstream-socket/" = {
|
||||
proxyPass = "http://backend-socket";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
client =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = [ pkgs.jq ];
|
||||
networking = {
|
||||
interfaces.eth1 = {
|
||||
ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.2.201";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
};
|
||||
extraHosts = hosts;
|
||||
client =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = [ pkgs.jq ];
|
||||
networking = {
|
||||
interfaces.eth1 = {
|
||||
ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.2.201";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
};
|
||||
extraHosts = hosts;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
server.wait_for_unit("nginx")
|
||||
server.wait_for_open_port(80)
|
||||
server.wait_for_unit("nginx")
|
||||
server.wait_for_open_port(80)
|
||||
|
||||
# Check Angie version
|
||||
client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.angie.version' | grep '${pkgs.angie.version}'")
|
||||
# Check Angie version
|
||||
client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.angie.version' | grep '${pkgs.angie.version}'")
|
||||
|
||||
# Check access
|
||||
client.succeed("curl --verbose --head http://api.example.com/console/ | grep 'HTTP/1.1 200'")
|
||||
server.succeed("curl --verbose --head http://api.example.com/console/ | grep 'HTTP/1.1 403 Forbidden'")
|
||||
# Check access
|
||||
client.succeed("curl --verbose --head http://api.example.com/console/ | grep 'HTTP/1.1 200'")
|
||||
server.succeed("curl --verbose --head http://api.example.com/console/ | grep 'HTTP/1.1 403 Forbidden'")
|
||||
|
||||
# Check responses and requests
|
||||
client.succeed("curl --verbose http://example.com/test/")
|
||||
client.succeed("curl --verbose http://example.com/test/locked/")
|
||||
client.succeed("curl --verbose http://example.com/test/locked/")
|
||||
client.succeed("curl --verbose http://example.com/test/error/")
|
||||
client.succeed("curl --verbose http://example.com/test/error/")
|
||||
client.succeed("curl --verbose http://example.com/test/error/")
|
||||
server.succeed("curl --verbose http://example.com/test/")
|
||||
client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.location_zones.test_zone.responses.\"200\"' | grep '1'")
|
||||
client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.location_zones.test_zone.responses.\"403\"' | grep '3'")
|
||||
client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.location_zones.test_zone.responses.\"404\"' | grep '3'")
|
||||
client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.location_zones.test_zone.requests.total' | grep '7'")
|
||||
# Check responses and requests
|
||||
client.succeed("curl --verbose http://example.com/test/")
|
||||
client.succeed("curl --verbose http://example.com/test/locked/")
|
||||
client.succeed("curl --verbose http://example.com/test/locked/")
|
||||
client.succeed("curl --verbose http://example.com/test/error/")
|
||||
client.succeed("curl --verbose http://example.com/test/error/")
|
||||
client.succeed("curl --verbose http://example.com/test/error/")
|
||||
server.succeed("curl --verbose http://example.com/test/")
|
||||
client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.location_zones.test_zone.responses.\"200\"' | grep '1'")
|
||||
client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.location_zones.test_zone.responses.\"403\"' | grep '3'")
|
||||
client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.location_zones.test_zone.responses.\"404\"' | grep '3'")
|
||||
client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.location_zones.test_zone.requests.total' | grep '7'")
|
||||
|
||||
# Check upstreams
|
||||
client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.upstreams.\"backend-http\".peers.\"192.168.2.101:8080\".state' | grep 'up'")
|
||||
client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.upstreams.\"backend-http\".peers.\"192.168.2.101:8080\".health.fails' | grep '0'")
|
||||
client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.upstreams.\"backend-socket\".peers.\"unix:/run/example.sock\".state' | grep 'up'")
|
||||
client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.upstreams.\"backend-socket\".peers.\"unix:/run/example.sock\".health.fails' | grep '0'")
|
||||
client.succeed("curl --verbose http://example.com/upstream-http/")
|
||||
client.succeed("curl --verbose http://example.com/upstream-socket/")
|
||||
client.succeed("curl --verbose http://example.com/upstream-socket/")
|
||||
client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.upstreams.\"backend-http\".peers.\"192.168.2.101:8080\".health.fails' | grep '1'")
|
||||
client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.upstreams.\"backend-socket\".peers.\"unix:/run/example.sock\".health.fails' | grep '2'")
|
||||
# Check upstreams
|
||||
client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.upstreams.\"backend-http\".peers.\"192.168.2.101:8080\".state' | grep 'up'")
|
||||
client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.upstreams.\"backend-http\".peers.\"192.168.2.101:8080\".health.fails' | grep '0'")
|
||||
client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.upstreams.\"backend-socket\".peers.\"unix:/run/example.sock\".state' | grep 'up'")
|
||||
client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.upstreams.\"backend-socket\".peers.\"unix:/run/example.sock\".health.fails' | grep '0'")
|
||||
client.succeed("curl --verbose http://example.com/upstream-http/")
|
||||
client.succeed("curl --verbose http://example.com/upstream-socket/")
|
||||
client.succeed("curl --verbose http://example.com/upstream-socket/")
|
||||
client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.upstreams.\"backend-http\".peers.\"192.168.2.101:8080\".health.fails' | grep '1'")
|
||||
client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.upstreams.\"backend-socket\".peers.\"unix:/run/example.sock\".health.fails' | grep '2'")
|
||||
|
||||
server.shutdown()
|
||||
client.shutdown()
|
||||
'';
|
||||
}
|
||||
)
|
||||
server.shutdown()
|
||||
client.shutdown()
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -1,75 +1,71 @@
|
||||
import ./make-test-python.nix (
|
||||
{ pkgs, ... }:
|
||||
let
|
||||
ankiSyncTest = pkgs.writeScript "anki-sync-test.py" ''
|
||||
#!${pkgs.python3}/bin/python
|
||||
{ pkgs, ... }:
|
||||
let
|
||||
ankiSyncTest = pkgs.writeScript "anki-sync-test.py" ''
|
||||
#!${pkgs.python3}/bin/python
|
||||
|
||||
import sys
|
||||
import sys
|
||||
|
||||
# get site paths from anki itself
|
||||
from runpy import run_path
|
||||
run_path("${pkgs.anki}/bin/.anki-wrapped")
|
||||
import anki
|
||||
# get site paths from anki itself
|
||||
from runpy import run_path
|
||||
run_path("${pkgs.anki}/bin/.anki-wrapped")
|
||||
import anki
|
||||
|
||||
col = anki.collection.Collection('test_collection')
|
||||
endpoint = 'http://localhost:27701'
|
||||
col = anki.collection.Collection('test_collection')
|
||||
endpoint = 'http://localhost:27701'
|
||||
|
||||
# Sanity check: verify bad login fails
|
||||
try:
|
||||
col.sync_login('baduser', 'badpass', endpoint)
|
||||
print("bad user login worked?!")
|
||||
sys.exit(1)
|
||||
except anki.errors.SyncError:
|
||||
pass
|
||||
# Sanity check: verify bad login fails
|
||||
try:
|
||||
col.sync_login('baduser', 'badpass', endpoint)
|
||||
print("bad user login worked?!")
|
||||
sys.exit(1)
|
||||
except anki.errors.SyncError:
|
||||
pass
|
||||
|
||||
# test logging in to users
|
||||
col.sync_login('user', 'password', endpoint)
|
||||
col.sync_login('passfileuser', 'passfilepassword', endpoint)
|
||||
# test logging in to users
|
||||
col.sync_login('user', 'password', endpoint)
|
||||
col.sync_login('passfileuser', 'passfilepassword', endpoint)
|
||||
|
||||
# Test actual sync. login apparently doesn't remember the endpoint...
|
||||
login = col.sync_login('user', 'password', endpoint)
|
||||
login.endpoint = endpoint
|
||||
sync = col.sync_collection(login, False)
|
||||
assert sync.required == sync.NO_CHANGES
|
||||
# TODO: create an archive with server content including a test card
|
||||
# and check we got it?
|
||||
'';
|
||||
testPasswordFile = pkgs.writeText "anki-password" "passfilepassword";
|
||||
in
|
||||
{
|
||||
name = "anki-sync-server";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ martinetd ];
|
||||
# Test actual sync. login apparently doesn't remember the endpoint...
|
||||
login = col.sync_login('user', 'password', endpoint)
|
||||
login.endpoint = endpoint
|
||||
sync = col.sync_collection(login, False)
|
||||
assert sync.required == sync.NO_CHANGES
|
||||
# TODO: create an archive with server content including a test card
|
||||
# and check we got it?
|
||||
'';
|
||||
testPasswordFile = pkgs.writeText "anki-password" "passfilepassword";
|
||||
in
|
||||
{
|
||||
name = "anki-sync-server";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ martinetd ];
|
||||
};
|
||||
|
||||
nodes.machine = {
|
||||
services.anki-sync-server = {
|
||||
enable = true;
|
||||
users = [
|
||||
{
|
||||
username = "user";
|
||||
password = "password";
|
||||
}
|
||||
{
|
||||
username = "passfileuser";
|
||||
passwordFile = testPasswordFile;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
services.anki-sync-server = {
|
||||
enable = true;
|
||||
users = [
|
||||
{
|
||||
username = "user";
|
||||
password = "password";
|
||||
}
|
||||
{
|
||||
username = "passfileuser";
|
||||
passwordFile = testPasswordFile;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
with subtest("Server starts successfully"):
|
||||
# service won't start without users
|
||||
machine.wait_for_unit("anki-sync-server.service")
|
||||
machine.wait_for_open_port(27701)
|
||||
|
||||
with subtest("Server starts successfully"):
|
||||
# service won't start without users
|
||||
machine.wait_for_unit("anki-sync-server.service")
|
||||
machine.wait_for_open_port(27701)
|
||||
|
||||
with subtest("Can sync"):
|
||||
machine.succeed("${ankiSyncTest}")
|
||||
'';
|
||||
}
|
||||
)
|
||||
with subtest("Can sync"):
|
||||
machine.succeed("${ankiSyncTest}")
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
import ./make-test-python.nix (
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
name = "anuko-time-tracker";
|
||||
meta = {
|
||||
maintainers = with pkgs.lib.maintainers; [ michaelshmitty ];
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
name = "anuko-time-tracker";
|
||||
meta = {
|
||||
maintainers = with pkgs.lib.maintainers; [ michaelshmitty ];
|
||||
};
|
||||
nodes = {
|
||||
machine = {
|
||||
services.anuko-time-tracker.enable = true;
|
||||
};
|
||||
nodes = {
|
||||
machine = {
|
||||
services.anuko-time-tracker.enable = true;
|
||||
};
|
||||
};
|
||||
testScript = ''
|
||||
start_all()
|
||||
machine.wait_for_unit("phpfpm-anuko-time-tracker")
|
||||
machine.wait_for_open_port(80);
|
||||
machine.wait_until_succeeds("curl -s --fail -L http://localhost/time.php | grep 'Anuko Time Tracker'")
|
||||
'';
|
||||
}
|
||||
)
|
||||
};
|
||||
testScript = ''
|
||||
start_all()
|
||||
machine.wait_for_unit("phpfpm-anuko-time-tracker")
|
||||
machine.wait_for_open_port(80);
|
||||
machine.wait_until_succeeds("curl -s --fail -L http://localhost/time.php | grep 'Anuko Time Tracker'")
|
||||
'';
|
||||
}
|
||||
|
||||
+36
-38
@@ -2,45 +2,43 @@ let
|
||||
# arbitrary address
|
||||
ipAddr = "192.168.42.42";
|
||||
in
|
||||
import ./make-test-python.nix (
|
||||
{ lib, pkgs, ... }:
|
||||
{
|
||||
name = "apcupsd";
|
||||
meta.maintainers = with lib.maintainers; [ bjornfor ];
|
||||
{ lib, ... }:
|
||||
{
|
||||
name = "apcupsd";
|
||||
meta.maintainers = with lib.maintainers; [ bjornfor ];
|
||||
|
||||
nodes = {
|
||||
machine = {
|
||||
services.apcupsd = {
|
||||
enable = true;
|
||||
configText = ''
|
||||
UPSTYPE usb
|
||||
BATTERYLEVEL 42
|
||||
# Configure NISIP so that the only way apcaccess can work is to read
|
||||
# this config.
|
||||
NISIP ${ipAddr}
|
||||
'';
|
||||
};
|
||||
networking.interfaces.eth1 = {
|
||||
ipv4.addresses = [
|
||||
{
|
||||
address = ipAddr;
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
};
|
||||
nodes = {
|
||||
machine = {
|
||||
services.apcupsd = {
|
||||
enable = true;
|
||||
configText = ''
|
||||
UPSTYPE usb
|
||||
BATTERYLEVEL 42
|
||||
# Configure NISIP so that the only way apcaccess can work is to read
|
||||
# this config.
|
||||
NISIP ${ipAddr}
|
||||
'';
|
||||
};
|
||||
networking.interfaces.eth1 = {
|
||||
ipv4.addresses = [
|
||||
{
|
||||
address = ipAddr;
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Check that the service starts, that the CLI (apcaccess) works and that it
|
||||
# uses the config (ipAddr) defined in the service config.
|
||||
testScript = ''
|
||||
start_all()
|
||||
machine.wait_for_unit("apcupsd.service")
|
||||
machine.wait_for_open_port(3551, "${ipAddr}")
|
||||
res = machine.succeed("apcaccess")
|
||||
expect_line="MBATTCHG : 42 Percent"
|
||||
assert "MBATTCHG : 42 Percent" in res, f"expected apcaccess output to contain '{expect_line}' but got '{res}'"
|
||||
machine.shutdown()
|
||||
'';
|
||||
}
|
||||
)
|
||||
# Check that the service starts, that the CLI (apcaccess) works and that it
|
||||
# uses the config (ipAddr) defined in the service config.
|
||||
testScript = ''
|
||||
start_all()
|
||||
machine.wait_for_unit("apcupsd.service")
|
||||
machine.wait_for_open_port(3551, "${ipAddr}")
|
||||
res = machine.succeed("apcaccess")
|
||||
expect_line="MBATTCHG : 42 Percent"
|
||||
assert "MBATTCHG : 42 Percent" in res, f"expected apcaccess output to contain '{expect_line}' but got '{res}'"
|
||||
machine.shutdown()
|
||||
'';
|
||||
}
|
||||
|
||||
+111
-115
@@ -1,130 +1,126 @@
|
||||
import ../make-test-python.nix (
|
||||
{ pkgs, lib, ... }:
|
||||
let
|
||||
helloProfileContents = ''
|
||||
abi <abi/4.0>,
|
||||
include <tunables/global>
|
||||
profile hello ${lib.getExe pkgs.hello} {
|
||||
include <abstractions/base>
|
||||
}
|
||||
'';
|
||||
in
|
||||
{
|
||||
name = "apparmor";
|
||||
meta.maintainers = with lib.maintainers; [
|
||||
julm
|
||||
grimmauld
|
||||
];
|
||||
{ pkgs, lib, ... }:
|
||||
let
|
||||
helloProfileContents = ''
|
||||
abi <abi/4.0>,
|
||||
include <tunables/global>
|
||||
profile hello ${lib.getExe pkgs.hello} {
|
||||
include <abstractions/base>
|
||||
}
|
||||
'';
|
||||
in
|
||||
{
|
||||
name = "apparmor";
|
||||
meta.maintainers = with lib.maintainers; [
|
||||
julm
|
||||
grimmauld
|
||||
];
|
||||
|
||||
nodes.machine =
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
security.apparmor = {
|
||||
enable = lib.mkDefault true;
|
||||
nodes.machine =
|
||||
{
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
security.apparmor = {
|
||||
enable = lib.mkDefault true;
|
||||
|
||||
policies.hello = {
|
||||
# test profile enforce and content definition
|
||||
state = "enforce";
|
||||
profile = helloProfileContents;
|
||||
};
|
||||
policies.hello = {
|
||||
# test profile enforce and content definition
|
||||
state = "enforce";
|
||||
profile = helloProfileContents;
|
||||
};
|
||||
|
||||
policies.sl = {
|
||||
# test profile complain and path definition
|
||||
state = "complain";
|
||||
path = ./sl_profile;
|
||||
};
|
||||
policies.sl = {
|
||||
# test profile complain and path definition
|
||||
state = "complain";
|
||||
path = ./sl_profile;
|
||||
};
|
||||
|
||||
policies.hexdump = {
|
||||
# test profile complain and path definition
|
||||
state = "enforce";
|
||||
profile = ''
|
||||
abi <abi/4.0>,
|
||||
include <tunables/global>
|
||||
profile hexdump /nix/store/*/bin/hexdump {
|
||||
include <abstractions/base>
|
||||
deny /tmp/** r,
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
includes."abstractions/base" = ''
|
||||
/nix/store/*/bin/** mr,
|
||||
/nix/store/*/lib/** mr,
|
||||
/nix/store/** r,
|
||||
policies.hexdump = {
|
||||
# test profile complain and path definition
|
||||
state = "enforce";
|
||||
profile = ''
|
||||
abi <abi/4.0>,
|
||||
include <tunables/global>
|
||||
profile hexdump /nix/store/*/bin/hexdump {
|
||||
include <abstractions/base>
|
||||
deny /tmp/** r,
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
includes."abstractions/base" = ''
|
||||
/nix/store/*/bin/** mr,
|
||||
/nix/store/*/lib/** mr,
|
||||
/nix/store/** r,
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
testScript =
|
||||
let
|
||||
inherit (lib) getExe getExe';
|
||||
in
|
||||
''
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
testScript =
|
||||
let
|
||||
inherit (lib) getExe getExe';
|
||||
in
|
||||
''
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
|
||||
with subtest("AppArmor profiles are loaded"):
|
||||
machine.succeed("systemctl status apparmor.service")
|
||||
with subtest("AppArmor profiles are loaded"):
|
||||
machine.succeed("systemctl status apparmor.service")
|
||||
|
||||
# AppArmor securityfs
|
||||
with subtest("AppArmor securityfs is mounted"):
|
||||
machine.succeed("mountpoint -q /sys/kernel/security")
|
||||
machine.succeed("cat /sys/kernel/security/apparmor/profiles")
|
||||
# AppArmor securityfs
|
||||
with subtest("AppArmor securityfs is mounted"):
|
||||
machine.succeed("mountpoint -q /sys/kernel/security")
|
||||
machine.succeed("cat /sys/kernel/security/apparmor/profiles")
|
||||
|
||||
# Test apparmorRulesFromClosure by:
|
||||
# 1. Prepending a string of the relevant packages' name and version on each line.
|
||||
# 2. Sorting according to those strings.
|
||||
# 3. Removing those prepended strings.
|
||||
# 4. Using `diff` against the expected output.
|
||||
with subtest("apparmorRulesFromClosure"):
|
||||
machine.succeed(
|
||||
"${getExe' pkgs.diffutils "diff"} -u ${
|
||||
pkgs.writeText "expected.rules" (import ./makeExpectedPolicies.nix { inherit pkgs; })
|
||||
} ${
|
||||
pkgs.runCommand "actual.rules" { preferLocalBuild = true; } ''
|
||||
${getExe pkgs.gnused} -e 's:^[^ ]* ${builtins.storeDir}/[^,/-]*-\([^/,]*\):\1 \0:' ${
|
||||
pkgs.apparmorRulesFromClosure {
|
||||
name = "ping";
|
||||
additionalRules = [ "x $path/foo/**" ];
|
||||
} [ pkgs.libcap ]
|
||||
} |
|
||||
${getExe' pkgs.coreutils "sort"} -n -k1 |
|
||||
${getExe pkgs.gnused} -e 's:^[^ ]* ::' >$out
|
||||
''
|
||||
}"
|
||||
)
|
||||
# Test apparmorRulesFromClosure by:
|
||||
# 1. Prepending a string of the relevant packages' name and version on each line.
|
||||
# 2. Sorting according to those strings.
|
||||
# 3. Removing those prepended strings.
|
||||
# 4. Using `diff` against the expected output.
|
||||
with subtest("apparmorRulesFromClosure"):
|
||||
machine.succeed(
|
||||
"${getExe' pkgs.diffutils "diff"} -u ${
|
||||
pkgs.writeText "expected.rules" (import ./makeExpectedPolicies.nix { inherit pkgs; })
|
||||
} ${
|
||||
pkgs.runCommand "actual.rules" { preferLocalBuild = true; } ''
|
||||
${getExe pkgs.gnused} -e 's:^[^ ]* ${builtins.storeDir}/[^,/-]*-\([^/,]*\):\1 \0:' ${
|
||||
pkgs.apparmorRulesFromClosure {
|
||||
name = "ping";
|
||||
additionalRules = [ "x $path/foo/**" ];
|
||||
} [ pkgs.libcap ]
|
||||
} |
|
||||
${getExe' pkgs.coreutils "sort"} -n -k1 |
|
||||
${getExe pkgs.gnused} -e 's:^[^ ]* ::' >$out
|
||||
''
|
||||
}"
|
||||
)
|
||||
|
||||
# Test apparmor profile states by using `diff` against `aa-status`
|
||||
with subtest("apparmorProfileStates"):
|
||||
machine.succeed("${getExe' pkgs.diffutils "diff"} -u \
|
||||
<(${getExe' pkgs.apparmor-bin-utils "aa-status"} --json | ${getExe pkgs.jq} --sort-keys . ) \
|
||||
<(${getExe pkgs.jq} --sort-keys . ${
|
||||
pkgs.writers.writeJSON "expectedStates.json" {
|
||||
version = "2";
|
||||
processes = { };
|
||||
profiles = {
|
||||
hexdump = "enforce";
|
||||
hello = "enforce";
|
||||
sl = "complain";
|
||||
};
|
||||
}
|
||||
})")
|
||||
# Test apparmor profile states by using `diff` against `aa-status`
|
||||
with subtest("apparmorProfileStates"):
|
||||
machine.succeed("${getExe' pkgs.diffutils "diff"} -u \
|
||||
<(${getExe' pkgs.apparmor-bin-utils "aa-status"} --json | ${getExe pkgs.jq} --sort-keys . ) \
|
||||
<(${getExe pkgs.jq} --sort-keys . ${
|
||||
pkgs.writers.writeJSON "expectedStates.json" {
|
||||
version = "2";
|
||||
processes = { };
|
||||
profiles = {
|
||||
hexdump = "enforce";
|
||||
hello = "enforce";
|
||||
sl = "complain";
|
||||
};
|
||||
}
|
||||
})")
|
||||
|
||||
# Test apparmor profile files in /etc/apparmor.d/<name> to be either a correct symlink (sl) or have the right file contents (hello)
|
||||
with subtest("apparmorProfileTargets"):
|
||||
machine.succeed("${getExe' pkgs.diffutils "diff"} -u <(${getExe pkgs.file} /etc/static/apparmor.d/sl) ${pkgs.writeText "expected.link" ''
|
||||
/etc/static/apparmor.d/sl: symbolic link to ${./sl_profile}
|
||||
''}")
|
||||
machine.succeed("${getExe' pkgs.diffutils "diff"} -u /etc/static/apparmor.d/hello ${pkgs.writeText "expected.content" helloProfileContents}")
|
||||
# Test apparmor profile files in /etc/apparmor.d/<name> to be either a correct symlink (sl) or have the right file contents (hello)
|
||||
with subtest("apparmorProfileTargets"):
|
||||
machine.succeed("${getExe' pkgs.diffutils "diff"} -u <(${getExe pkgs.file} /etc/static/apparmor.d/sl) ${pkgs.writeText "expected.link" ''
|
||||
/etc/static/apparmor.d/sl: symbolic link to ${./sl_profile}
|
||||
''}")
|
||||
machine.succeed("${getExe' pkgs.diffutils "diff"} -u /etc/static/apparmor.d/hello ${pkgs.writeText "expected.content" helloProfileContents}")
|
||||
|
||||
|
||||
with subtest("apparmorProfileEnforce"):
|
||||
machine.succeed("${getExe pkgs.hello} 1> /tmp/test-file")
|
||||
machine.fail("${lib.getExe' pkgs.util-linux "hexdump"} /tmp/test-file") # no access to /tmp/test-file granted by apparmor
|
||||
'';
|
||||
}
|
||||
)
|
||||
with subtest("apparmorProfileEnforce"):
|
||||
machine.succeed("${getExe pkgs.hello} 1> /tmp/test-file")
|
||||
machine.fail("${lib.getExe' pkgs.util-linux "hexdump"} /tmp/test-file") # no access to /tmp/test-file granted by apparmor
|
||||
'';
|
||||
}
|
||||
|
||||
+28
-30
@@ -1,38 +1,36 @@
|
||||
import ./make-test-python.nix (
|
||||
{ lib, ... }:
|
||||
{
|
||||
name = "archi";
|
||||
meta.maintainers = with lib.maintainers; [ paumr ];
|
||||
{ lib, ... }:
|
||||
{
|
||||
name = "archi";
|
||||
meta.maintainers = with lib.maintainers; [ paumr ];
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
imports = [
|
||||
./common/x11.nix
|
||||
];
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
imports = [
|
||||
./common/x11.nix
|
||||
];
|
||||
|
||||
environment.systemPackages = with pkgs; [ archi ];
|
||||
};
|
||||
environment.systemPackages = with pkgs; [ archi ];
|
||||
};
|
||||
|
||||
enableOCR = true;
|
||||
enableOCR = true;
|
||||
|
||||
testScript = ''
|
||||
machine.wait_for_x()
|
||||
testScript = ''
|
||||
machine.wait_for_x()
|
||||
|
||||
with subtest("createEmptyModel via CLI"):
|
||||
machine.succeed("Archi -application com.archimatetool.commandline.app -consoleLog -nosplash --createEmptyModel --saveModel smoke.archimate")
|
||||
machine.copy_from_vm("smoke.archimate", "")
|
||||
with subtest("createEmptyModel via CLI"):
|
||||
machine.succeed("Archi -application com.archimatetool.commandline.app -consoleLog -nosplash --createEmptyModel --saveModel smoke.archimate")
|
||||
machine.copy_from_vm("smoke.archimate", "")
|
||||
|
||||
with subtest("UI smoketest"):
|
||||
machine.succeed("DISPLAY=:0 Archi --createEmptyModel >&2 &")
|
||||
machine.wait_for_window("Archi")
|
||||
with subtest("UI smoketest"):
|
||||
machine.succeed("DISPLAY=:0 Archi --createEmptyModel >&2 &")
|
||||
machine.wait_for_window("Archi")
|
||||
|
||||
# wait till main UI is open
|
||||
# since OCR seems to be buggy wait_for_text was replaced by sleep, issue: #302965
|
||||
# machine.wait_for_text("Welcome to Archi")
|
||||
machine.sleep(20)
|
||||
# wait till main UI is open
|
||||
# since OCR seems to be buggy wait_for_text was replaced by sleep, issue: #302965
|
||||
# machine.wait_for_text("Welcome to Archi")
|
||||
machine.sleep(20)
|
||||
|
||||
machine.screenshot("welcome-screen")
|
||||
'';
|
||||
}
|
||||
)
|
||||
machine.screenshot("welcome-screen")
|
||||
'';
|
||||
}
|
||||
|
||||
+47
-49
@@ -1,54 +1,52 @@
|
||||
import ./make-test-python.nix (
|
||||
{ pkgs, ... }:
|
||||
let
|
||||
rpcSecret = "supersecret";
|
||||
rpc-listen-port = 6800;
|
||||
curlBody = {
|
||||
jsonrpc = 2.0;
|
||||
id = 1;
|
||||
method = "aria2.getVersion";
|
||||
params = [ "token:${rpcSecret}" ];
|
||||
};
|
||||
in
|
||||
rec {
|
||||
name = "aria2";
|
||||
{ pkgs, ... }:
|
||||
let
|
||||
rpcSecret = "supersecret";
|
||||
rpc-listen-port = 6800;
|
||||
curlBody = {
|
||||
jsonrpc = 2.0;
|
||||
id = 1;
|
||||
method = "aria2.getVersion";
|
||||
params = [ "token:${rpcSecret}" ];
|
||||
};
|
||||
in
|
||||
{
|
||||
name = "aria2";
|
||||
|
||||
nodes.machine = {
|
||||
environment.etc."aria2Rpc".text = rpcSecret;
|
||||
services.aria2 = {
|
||||
enable = true;
|
||||
rpcSecretFile = "/etc/aria2Rpc";
|
||||
settings = {
|
||||
inherit rpc-listen-port;
|
||||
allow-overwrite = false;
|
||||
check-integrity = true;
|
||||
console-log-level = "warn";
|
||||
listen-port = [
|
||||
{
|
||||
from = 20000;
|
||||
to = 20010;
|
||||
}
|
||||
{
|
||||
from = 22222;
|
||||
to = 22222;
|
||||
}
|
||||
];
|
||||
max-concurrent-downloads = 50;
|
||||
seed-ratio = 1.2;
|
||||
summary-interval = 0;
|
||||
};
|
||||
nodes.machine = {
|
||||
environment.etc."aria2Rpc".text = rpcSecret;
|
||||
services.aria2 = {
|
||||
enable = true;
|
||||
rpcSecretFile = "/etc/aria2Rpc";
|
||||
settings = {
|
||||
inherit rpc-listen-port;
|
||||
allow-overwrite = false;
|
||||
check-integrity = true;
|
||||
console-log-level = "warn";
|
||||
listen-port = [
|
||||
{
|
||||
from = 20000;
|
||||
to = 20010;
|
||||
}
|
||||
{
|
||||
from = 22222;
|
||||
to = 22222;
|
||||
}
|
||||
];
|
||||
max-concurrent-downloads = 50;
|
||||
seed-ratio = 1.2;
|
||||
summary-interval = 0;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
machine.start()
|
||||
machine.wait_for_unit("aria2.service")
|
||||
curl_cmd = 'curl --fail-with-body -X POST -H "Content-Type: application/json" \
|
||||
-d \'${builtins.toJSON curlBody}\' http://localhost:${toString rpc-listen-port}/jsonrpc'
|
||||
print(machine.wait_until_succeeds(curl_cmd, timeout=10))
|
||||
machine.shutdown()
|
||||
'';
|
||||
testScript = ''
|
||||
machine.start()
|
||||
machine.wait_for_unit("aria2.service")
|
||||
curl_cmd = 'curl --fail-with-body -X POST -H "Content-Type: application/json" \
|
||||
-d \'${builtins.toJSON curlBody}\' http://localhost:${toString rpc-listen-port}/jsonrpc'
|
||||
print(machine.wait_until_succeeds(curl_cmd, timeout=10))
|
||||
machine.shutdown()
|
||||
'';
|
||||
|
||||
meta.maintainers = [ pkgs.lib.maintainers.timhae ];
|
||||
}
|
||||
)
|
||||
meta.maintainers = [ pkgs.lib.maintainers.timhae ];
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
{
|
||||
system ? builtins.currentSystem,
|
||||
config ? { },
|
||||
pkgs ? import ../.. { inherit system config; },
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with import ../lib/testing-python.nix { inherit system pkgs; };
|
||||
|
||||
let
|
||||
user = "alice";
|
||||
|
||||
@@ -27,9 +24,9 @@ let
|
||||
};
|
||||
|
||||
in
|
||||
makeTest {
|
||||
{
|
||||
name = "armagetronad";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
meta = with lib.maintainers; {
|
||||
maintainers = [ numinit ];
|
||||
};
|
||||
|
||||
|
||||
+27
-29
@@ -1,36 +1,34 @@
|
||||
import ./make-test-python.nix (
|
||||
{ pkgs, ... }:
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
name = "atd";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ bjornfor ];
|
||||
{
|
||||
name = "atd";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ bjornfor ];
|
||||
};
|
||||
|
||||
nodes.machine =
|
||||
{ ... }:
|
||||
{
|
||||
services.atd.enable = true;
|
||||
users.users.alice = {
|
||||
isNormalUser = true;
|
||||
};
|
||||
};
|
||||
|
||||
nodes.machine =
|
||||
{ ... }:
|
||||
{
|
||||
services.atd.enable = true;
|
||||
users.users.alice = {
|
||||
isNormalUser = true;
|
||||
};
|
||||
};
|
||||
# "at" has a resolution of 1 minute
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
# "at" has a resolution of 1 minute
|
||||
testScript = ''
|
||||
start_all()
|
||||
machine.wait_for_unit("atd.service") # wait for atd to start
|
||||
machine.fail("test -f ~root/at-1")
|
||||
machine.fail("test -f ~alice/at-1")
|
||||
|
||||
machine.wait_for_unit("atd.service") # wait for atd to start
|
||||
machine.fail("test -f ~root/at-1")
|
||||
machine.fail("test -f ~alice/at-1")
|
||||
machine.succeed("echo 'touch ~root/at-1' | at now+1min")
|
||||
machine.succeed("su - alice -c \"echo 'touch at-1' | at now+1min\"")
|
||||
|
||||
machine.succeed("echo 'touch ~root/at-1' | at now+1min")
|
||||
machine.succeed("su - alice -c \"echo 'touch at-1' | at now+1min\"")
|
||||
machine.succeed("sleep 1.5m")
|
||||
|
||||
machine.succeed("sleep 1.5m")
|
||||
|
||||
machine.succeed("test -f ~root/at-1")
|
||||
machine.succeed("test -f ~alice/at-1")
|
||||
'';
|
||||
}
|
||||
)
|
||||
machine.succeed("test -f ~root/at-1")
|
||||
machine.succeed("test -f ~alice/at-1")
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
import ./make-test-python.nix (
|
||||
{ lib, ... }:
|
||||
{
|
||||
name = "audiobookshelf";
|
||||
meta.maintainers = with lib.maintainers; [ wietsedv ];
|
||||
{ lib, ... }:
|
||||
{
|
||||
name = "audiobookshelf";
|
||||
meta.maintainers = with lib.maintainers; [ wietsedv ];
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
services.audiobookshelf = {
|
||||
enable = true;
|
||||
port = 1234;
|
||||
};
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
services.audiobookshelf = {
|
||||
enable = true;
|
||||
port = 1234;
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
machine.wait_for_unit("audiobookshelf.service")
|
||||
machine.wait_for_open_port(1234)
|
||||
machine.succeed("curl --fail http://localhost:1234/")
|
||||
'';
|
||||
}
|
||||
)
|
||||
testScript = ''
|
||||
machine.wait_for_unit("audiobookshelf.service")
|
||||
machine.wait_for_open_port(1234)
|
||||
machine.succeed("curl --fail http://localhost:1234/")
|
||||
'';
|
||||
}
|
||||
|
||||
+156
-158
@@ -1,180 +1,178 @@
|
||||
import ./make-test-python.nix (
|
||||
{ pkgs, lib, ... }:
|
||||
{ pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
dbUser = "nixos_auth";
|
||||
dbPassword = "topsecret123";
|
||||
dbName = "auth";
|
||||
let
|
||||
dbUser = "nixos_auth";
|
||||
dbPassword = "topsecret123";
|
||||
dbName = "auth";
|
||||
|
||||
mysqlUsername = "mysqltest";
|
||||
mysqlPassword = "topsecretmysqluserpassword123";
|
||||
mysqlGroup = "mysqlusers";
|
||||
mysqlUsername = "mysqltest";
|
||||
mysqlPassword = "topsecretmysqluserpassword123";
|
||||
mysqlGroup = "mysqlusers";
|
||||
|
||||
localUsername = "localtest";
|
||||
localPassword = "topsecretlocaluserpassword123";
|
||||
localUsername = "localtest";
|
||||
localPassword = "topsecretlocaluserpassword123";
|
||||
|
||||
mysqlInit = pkgs.writeText "mysqlInit" ''
|
||||
CREATE USER '${dbUser}'@'localhost' IDENTIFIED BY '${dbPassword}';
|
||||
CREATE DATABASE ${dbName};
|
||||
GRANT ALL PRIVILEGES ON ${dbName}.* TO '${dbUser}'@'localhost';
|
||||
FLUSH PRIVILEGES;
|
||||
mysqlInit = pkgs.writeText "mysqlInit" ''
|
||||
CREATE USER '${dbUser}'@'localhost' IDENTIFIED BY '${dbPassword}';
|
||||
CREATE DATABASE ${dbName};
|
||||
GRANT ALL PRIVILEGES ON ${dbName}.* TO '${dbUser}'@'localhost';
|
||||
FLUSH PRIVILEGES;
|
||||
|
||||
USE ${dbName};
|
||||
CREATE TABLE `groups` (
|
||||
rowid int(11) NOT NULL auto_increment,
|
||||
gid int(11) NOT NULL,
|
||||
name char(255) NOT NULL,
|
||||
PRIMARY KEY (rowid)
|
||||
);
|
||||
USE ${dbName};
|
||||
CREATE TABLE `groups` (
|
||||
rowid int(11) NOT NULL auto_increment,
|
||||
gid int(11) NOT NULL,
|
||||
name char(255) NOT NULL,
|
||||
PRIMARY KEY (rowid)
|
||||
);
|
||||
|
||||
CREATE TABLE `users` (
|
||||
name varchar(255) NOT NULL,
|
||||
uid int(11) NOT NULL auto_increment,
|
||||
gid int(11) NOT NULL,
|
||||
password varchar(255) NOT NULL,
|
||||
PRIMARY KEY (uid),
|
||||
UNIQUE (name)
|
||||
) AUTO_INCREMENT=5000;
|
||||
CREATE TABLE `users` (
|
||||
name varchar(255) NOT NULL,
|
||||
uid int(11) NOT NULL auto_increment,
|
||||
gid int(11) NOT NULL,
|
||||
password varchar(255) NOT NULL,
|
||||
PRIMARY KEY (uid),
|
||||
UNIQUE (name)
|
||||
) AUTO_INCREMENT=5000;
|
||||
|
||||
INSERT INTO `users` (name, uid, gid, password) VALUES
|
||||
('${mysqlUsername}', 5000, 5000, SHA2('${mysqlPassword}', 256));
|
||||
INSERT INTO `groups` (name, gid) VALUES ('${mysqlGroup}', 5000);
|
||||
'';
|
||||
in
|
||||
{
|
||||
name = "auth-mysql";
|
||||
meta.maintainers = with lib.maintainers; [ netali ];
|
||||
INSERT INTO `users` (name, uid, gid, password) VALUES
|
||||
('${mysqlUsername}', 5000, 5000, SHA2('${mysqlPassword}', 256));
|
||||
INSERT INTO `groups` (name, gid) VALUES ('${mysqlGroup}', 5000);
|
||||
'';
|
||||
in
|
||||
{
|
||||
name = "auth-mysql";
|
||||
meta.maintainers = with lib.maintainers; [ netali ];
|
||||
|
||||
nodes.machine =
|
||||
{ ... }:
|
||||
{
|
||||
services.mysql = {
|
||||
enable = true;
|
||||
package = pkgs.mariadb;
|
||||
settings.mysqld.bind-address = "127.0.0.1";
|
||||
initialScript = mysqlInit;
|
||||
};
|
||||
|
||||
users.users.${localUsername} = {
|
||||
isNormalUser = true;
|
||||
password = localPassword;
|
||||
};
|
||||
|
||||
security.pam.services.login.makeHomeDir = true;
|
||||
|
||||
users.mysql = {
|
||||
enable = true;
|
||||
host = "127.0.0.1";
|
||||
user = dbUser;
|
||||
database = dbName;
|
||||
passwordFile = "${builtins.toFile "dbPassword" dbPassword}";
|
||||
pam = {
|
||||
table = "users";
|
||||
userColumn = "name";
|
||||
passwordColumn = "password";
|
||||
passwordCrypt = "sha256";
|
||||
disconnectEveryOperation = true;
|
||||
};
|
||||
nss = {
|
||||
getpwnam = ''
|
||||
SELECT name, 'x', uid, gid, name, CONCAT('/home/', name), "/run/current-system/sw/bin/bash" \
|
||||
FROM users \
|
||||
WHERE name='%1$s' \
|
||||
LIMIT 1
|
||||
'';
|
||||
getpwuid = ''
|
||||
SELECT name, 'x', uid, gid, name, CONCAT('/home/', name), "/run/current-system/sw/bin/bash" \
|
||||
FROM users \
|
||||
WHERE uid=%1$u \
|
||||
LIMIT 1
|
||||
'';
|
||||
getspnam = ''
|
||||
SELECT name, password, 1, 0, 99999, 7, 0, -1, 0 \
|
||||
FROM users \
|
||||
WHERE name='%1$s' \
|
||||
LIMIT 1
|
||||
'';
|
||||
getpwent = ''
|
||||
SELECT name, 'x', uid, gid, name, CONCAT('/home/', name), "/run/current-system/sw/bin/bash" \
|
||||
FROM users
|
||||
'';
|
||||
getspent = ''
|
||||
SELECT name, password, 1, 0, 99999, 7, 0, -1, 0 \
|
||||
FROM users
|
||||
'';
|
||||
getgrnam = ''
|
||||
SELECT name, 'x', gid FROM groups WHERE name='%1$s' LIMIT 1
|
||||
'';
|
||||
getgrgid = ''
|
||||
SELECT name, 'x', gid FROM groups WHERE gid='%1$u' LIMIT 1
|
||||
'';
|
||||
getgrent = ''
|
||||
SELECT name, 'x', gid FROM groups
|
||||
'';
|
||||
memsbygid = ''
|
||||
SELECT name FROM users WHERE gid=%1$u
|
||||
'';
|
||||
gidsbymem = ''
|
||||
SELECT gid FROM users WHERE name='%1$s'
|
||||
'';
|
||||
};
|
||||
};
|
||||
nodes.machine =
|
||||
{ ... }:
|
||||
{
|
||||
services.mysql = {
|
||||
enable = true;
|
||||
package = pkgs.mariadb;
|
||||
settings.mysqld.bind-address = "127.0.0.1";
|
||||
initialScript = mysqlInit;
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
def switch_to_tty(tty_number):
|
||||
machine.fail(f"pgrep -f 'agetty.*tty{tty_number}'")
|
||||
machine.send_key(f"alt-f{tty_number}")
|
||||
machine.wait_until_succeeds(f"[ $(fgconsole) = {tty_number} ]")
|
||||
machine.wait_for_unit(f"getty@tty{tty_number}.service")
|
||||
machine.wait_until_succeeds(f"pgrep -f 'agetty.*tty{tty_number}'")
|
||||
users.users.${localUsername} = {
|
||||
isNormalUser = true;
|
||||
password = localPassword;
|
||||
};
|
||||
|
||||
security.pam.services.login.makeHomeDir = true;
|
||||
|
||||
users.mysql = {
|
||||
enable = true;
|
||||
host = "127.0.0.1";
|
||||
user = dbUser;
|
||||
database = dbName;
|
||||
passwordFile = "${builtins.toFile "dbPassword" dbPassword}";
|
||||
pam = {
|
||||
table = "users";
|
||||
userColumn = "name";
|
||||
passwordColumn = "password";
|
||||
passwordCrypt = "sha256";
|
||||
disconnectEveryOperation = true;
|
||||
};
|
||||
nss = {
|
||||
getpwnam = ''
|
||||
SELECT name, 'x', uid, gid, name, CONCAT('/home/', name), "/run/current-system/sw/bin/bash" \
|
||||
FROM users \
|
||||
WHERE name='%1$s' \
|
||||
LIMIT 1
|
||||
'';
|
||||
getpwuid = ''
|
||||
SELECT name, 'x', uid, gid, name, CONCAT('/home/', name), "/run/current-system/sw/bin/bash" \
|
||||
FROM users \
|
||||
WHERE uid=%1$u \
|
||||
LIMIT 1
|
||||
'';
|
||||
getspnam = ''
|
||||
SELECT name, password, 1, 0, 99999, 7, 0, -1, 0 \
|
||||
FROM users \
|
||||
WHERE name='%1$s' \
|
||||
LIMIT 1
|
||||
'';
|
||||
getpwent = ''
|
||||
SELECT name, 'x', uid, gid, name, CONCAT('/home/', name), "/run/current-system/sw/bin/bash" \
|
||||
FROM users
|
||||
'';
|
||||
getspent = ''
|
||||
SELECT name, password, 1, 0, 99999, 7, 0, -1, 0 \
|
||||
FROM users
|
||||
'';
|
||||
getgrnam = ''
|
||||
SELECT name, 'x', gid FROM groups WHERE name='%1$s' LIMIT 1
|
||||
'';
|
||||
getgrgid = ''
|
||||
SELECT name, 'x', gid FROM groups WHERE gid='%1$u' LIMIT 1
|
||||
'';
|
||||
getgrent = ''
|
||||
SELECT name, 'x', gid FROM groups
|
||||
'';
|
||||
memsbygid = ''
|
||||
SELECT name FROM users WHERE gid=%1$u
|
||||
'';
|
||||
gidsbymem = ''
|
||||
SELECT gid FROM users WHERE name='%1$s'
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
def switch_to_tty(tty_number):
|
||||
machine.fail(f"pgrep -f 'agetty.*tty{tty_number}'")
|
||||
machine.send_key(f"alt-f{tty_number}")
|
||||
machine.wait_until_succeeds(f"[ $(fgconsole) = {tty_number} ]")
|
||||
machine.wait_for_unit(f"getty@tty{tty_number}.service")
|
||||
machine.wait_until_succeeds(f"pgrep -f 'agetty.*tty{tty_number}'")
|
||||
|
||||
|
||||
def try_login(tty_number, username, password):
|
||||
machine.wait_until_tty_matches(tty_number, "login: ")
|
||||
machine.send_chars(f"{username}\n")
|
||||
machine.wait_until_tty_matches(tty_number, f"login: {username}")
|
||||
machine.wait_until_succeeds("pgrep login")
|
||||
machine.wait_until_tty_matches(tty_number, "Password: ")
|
||||
machine.send_chars(f"{password}\n")
|
||||
def try_login(tty_number, username, password):
|
||||
machine.wait_until_tty_matches(tty_number, "login: ")
|
||||
machine.send_chars(f"{username}\n")
|
||||
machine.wait_until_tty_matches(tty_number, f"login: {username}")
|
||||
machine.wait_until_succeeds("pgrep login")
|
||||
machine.wait_until_tty_matches(tty_number, "Password: ")
|
||||
machine.send_chars(f"{password}\n")
|
||||
|
||||
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
machine.wait_for_unit("mysql.service")
|
||||
machine.wait_until_succeeds("cat /etc/security/pam_mysql.conf | grep users.db_passwd")
|
||||
machine.wait_until_succeeds("pgrep -f 'agetty.*tty1'")
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
machine.wait_for_unit("mysql.service")
|
||||
machine.wait_until_succeeds("cat /etc/security/pam_mysql.conf | grep users.db_passwd")
|
||||
machine.wait_until_succeeds("pgrep -f 'agetty.*tty1'")
|
||||
|
||||
with subtest("Local login"):
|
||||
switch_to_tty("2")
|
||||
try_login("2", "${localUsername}", "${localPassword}")
|
||||
with subtest("Local login"):
|
||||
switch_to_tty("2")
|
||||
try_login("2", "${localUsername}", "${localPassword}")
|
||||
|
||||
machine.wait_until_succeeds("pgrep -u ${localUsername} bash")
|
||||
machine.send_chars("id > local_id.txt\n")
|
||||
machine.wait_for_file("/home/${localUsername}/local_id.txt")
|
||||
machine.succeed("cat /home/${localUsername}/local_id.txt | grep 'uid=1000(${localUsername}) gid=100(users) groups=100(users)'")
|
||||
machine.wait_until_succeeds("pgrep -u ${localUsername} bash")
|
||||
machine.send_chars("id > local_id.txt\n")
|
||||
machine.wait_for_file("/home/${localUsername}/local_id.txt")
|
||||
machine.succeed("cat /home/${localUsername}/local_id.txt | grep 'uid=1000(${localUsername}) gid=100(users) groups=100(users)'")
|
||||
|
||||
with subtest("Local incorrect login"):
|
||||
switch_to_tty("3")
|
||||
try_login("3", "${localUsername}", "wrongpassword")
|
||||
with subtest("Local incorrect login"):
|
||||
switch_to_tty("3")
|
||||
try_login("3", "${localUsername}", "wrongpassword")
|
||||
|
||||
machine.wait_until_tty_matches("3", "Login incorrect")
|
||||
machine.wait_until_tty_matches("3", "login:")
|
||||
machine.wait_until_tty_matches("3", "Login incorrect")
|
||||
machine.wait_until_tty_matches("3", "login:")
|
||||
|
||||
with subtest("MySQL login"):
|
||||
switch_to_tty("4")
|
||||
try_login("4", "${mysqlUsername}", "${mysqlPassword}")
|
||||
with subtest("MySQL login"):
|
||||
switch_to_tty("4")
|
||||
try_login("4", "${mysqlUsername}", "${mysqlPassword}")
|
||||
|
||||
machine.wait_until_succeeds("pgrep -u ${mysqlUsername} bash")
|
||||
machine.send_chars("id > mysql_id.txt\n")
|
||||
machine.wait_for_file("/home/${mysqlUsername}/mysql_id.txt")
|
||||
machine.succeed("cat /home/${mysqlUsername}/mysql_id.txt | grep 'uid=5000(${mysqlUsername}) gid=5000(${mysqlGroup}) groups=5000(${mysqlGroup})'")
|
||||
machine.wait_until_succeeds("pgrep -u ${mysqlUsername} bash")
|
||||
machine.send_chars("id > mysql_id.txt\n")
|
||||
machine.wait_for_file("/home/${mysqlUsername}/mysql_id.txt")
|
||||
machine.succeed("cat /home/${mysqlUsername}/mysql_id.txt | grep 'uid=5000(${mysqlUsername}) gid=5000(${mysqlGroup}) groups=5000(${mysqlGroup})'")
|
||||
|
||||
with subtest("MySQL incorrect login"):
|
||||
switch_to_tty("5")
|
||||
try_login("5", "${mysqlUsername}", "wrongpassword")
|
||||
with subtest("MySQL incorrect login"):
|
||||
switch_to_tty("5")
|
||||
try_login("5", "${mysqlUsername}", "wrongpassword")
|
||||
|
||||
machine.wait_until_tty_matches("5", "Login incorrect")
|
||||
machine.wait_until_tty_matches("5", "login:")
|
||||
'';
|
||||
}
|
||||
)
|
||||
machine.wait_until_tty_matches("5", "Login incorrect")
|
||||
machine.wait_until_tty_matches("5", "login:")
|
||||
'';
|
||||
}
|
||||
|
||||
+174
-178
@@ -1,187 +1,183 @@
|
||||
# Test Authelia as an auth server for Traefik as a reverse proxy of a local web service
|
||||
import ./make-test-python.nix (
|
||||
{ lib, ... }:
|
||||
{
|
||||
name = "authelia";
|
||||
meta.maintainers = with lib.maintainers; [ jk ];
|
||||
{ lib, ... }:
|
||||
{
|
||||
name = "authelia";
|
||||
meta.maintainers = with lib.maintainers; [ jk ];
|
||||
|
||||
nodes = {
|
||||
authelia =
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
services.authelia.instances.testing = {
|
||||
enable = true;
|
||||
secrets.storageEncryptionKeyFile = "/etc/authelia/storageEncryptionKeyFile";
|
||||
secrets.jwtSecretFile = "/etc/authelia/jwtSecretFile";
|
||||
settings = {
|
||||
authentication_backend.file.path = "/etc/authelia/users_database.yml";
|
||||
access_control.default_policy = "one_factor";
|
||||
session.domain = "example.com";
|
||||
storage.local.path = "/tmp/db.sqlite3";
|
||||
notifier.filesystem.filename = "/tmp/notifications.txt";
|
||||
};
|
||||
nodes = {
|
||||
authelia =
|
||||
{
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
services.authelia.instances.testing = {
|
||||
enable = true;
|
||||
secrets.storageEncryptionKeyFile = "/etc/authelia/storageEncryptionKeyFile";
|
||||
secrets.jwtSecretFile = "/etc/authelia/jwtSecretFile";
|
||||
settings = {
|
||||
authentication_backend.file.path = "/etc/authelia/users_database.yml";
|
||||
access_control.default_policy = "one_factor";
|
||||
session.domain = "example.com";
|
||||
storage.local.path = "/tmp/db.sqlite3";
|
||||
notifier.filesystem.filename = "/tmp/notifications.txt";
|
||||
};
|
||||
|
||||
# These should not be set from nix but through other means to not leak the secret!
|
||||
# This is purely for testing purposes!
|
||||
environment.etc."authelia/storageEncryptionKeyFile" = {
|
||||
mode = "0400";
|
||||
user = "authelia-testing";
|
||||
text = "you_must_generate_a_random_string_of_more_than_twenty_chars_and_configure_this";
|
||||
};
|
||||
environment.etc."authelia/jwtSecretFile" = {
|
||||
mode = "0400";
|
||||
user = "authelia-testing";
|
||||
text = "a_very_important_secret";
|
||||
};
|
||||
environment.etc."authelia/users_database.yml" = {
|
||||
mode = "0400";
|
||||
user = "authelia-testing";
|
||||
text = ''
|
||||
users:
|
||||
bob:
|
||||
disabled: false
|
||||
displayname: bob
|
||||
# password of password
|
||||
password: $argon2id$v=19$m=65536,t=3,p=4$2ohUAfh9yetl+utr4tLcCQ$AsXx0VlwjvNnCsa70u4HKZvFkC8Gwajr2pHGKcND/xs
|
||||
email: bob@jim.com
|
||||
groups:
|
||||
- admin
|
||||
- dev
|
||||
'';
|
||||
};
|
||||
|
||||
services.traefik = {
|
||||
enable = true;
|
||||
|
||||
dynamicConfigOptions = {
|
||||
tls.certificates =
|
||||
let
|
||||
certDir = pkgs.runCommand "selfSignedCerts" { buildInputs = [ pkgs.openssl ]; } ''
|
||||
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -nodes -subj '/CN=example.com/CN=auth.example.com/CN=static.example.com' -days 36500
|
||||
mkdir -p $out
|
||||
cp key.pem cert.pem $out
|
||||
'';
|
||||
in
|
||||
[
|
||||
{
|
||||
certFile = "${certDir}/cert.pem";
|
||||
keyFile = "${certDir}/key.pem";
|
||||
}
|
||||
];
|
||||
http.middlewares.authelia.forwardAuth = {
|
||||
address = "http://localhost:9091/api/verify?rd=https%3A%2F%2Fauth.example.com%2F";
|
||||
trustForwardHeader = true;
|
||||
authResponseHeaders = [
|
||||
"Remote-User"
|
||||
"Remote-Groups"
|
||||
"Remote-Email"
|
||||
"Remote-Name"
|
||||
];
|
||||
};
|
||||
http.middlewares.authelia-basic.forwardAuth = {
|
||||
address = "http://localhost:9091/api/verify?auth=basic";
|
||||
trustForwardHeader = true;
|
||||
authResponseHeaders = [
|
||||
"Remote-User"
|
||||
"Remote-Groups"
|
||||
"Remote-Email"
|
||||
"Remote-Name"
|
||||
];
|
||||
};
|
||||
|
||||
http.routers.simplehttp = {
|
||||
rule = "Host(`static.example.com`)";
|
||||
tls = true;
|
||||
entryPoints = "web";
|
||||
service = "simplehttp";
|
||||
};
|
||||
http.routers.simplehttp-basic-auth = {
|
||||
rule = "Host(`static-basic-auth.example.com`)";
|
||||
tls = true;
|
||||
entryPoints = "web";
|
||||
service = "simplehttp";
|
||||
middlewares = [ "authelia-basic@file" ];
|
||||
};
|
||||
|
||||
http.services.simplehttp = {
|
||||
loadBalancer.servers = [
|
||||
{
|
||||
url = "http://localhost:8000";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
http.routers.authelia = {
|
||||
rule = "Host(`auth.example.com`)";
|
||||
tls = true;
|
||||
entryPoints = "web";
|
||||
service = "authelia@file";
|
||||
};
|
||||
|
||||
http.services.authelia = {
|
||||
loadBalancer.servers = [
|
||||
{
|
||||
url = "http://localhost:9091";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
staticConfigOptions = {
|
||||
global = {
|
||||
checkNewVersion = false;
|
||||
sendAnonymousUsage = false;
|
||||
};
|
||||
|
||||
entryPoints.web.address = ":443";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.simplehttp =
|
||||
let
|
||||
fakeWebPageDir = pkgs.writeTextDir "index.html" "hello";
|
||||
in
|
||||
{
|
||||
script = "${pkgs.python3}/bin/python -m http.server --directory ${fakeWebPageDir} 8000";
|
||||
serviceConfig.Type = "simple";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
# These should not be set from nix but through other means to not leak the secret!
|
||||
# This is purely for testing purposes!
|
||||
environment.etc."authelia/storageEncryptionKeyFile" = {
|
||||
mode = "0400";
|
||||
user = "authelia-testing";
|
||||
text = "you_must_generate_a_random_string_of_more_than_twenty_chars_and_configure_this";
|
||||
};
|
||||
environment.etc."authelia/jwtSecretFile" = {
|
||||
mode = "0400";
|
||||
user = "authelia-testing";
|
||||
text = "a_very_important_secret";
|
||||
};
|
||||
environment.etc."authelia/users_database.yml" = {
|
||||
mode = "0400";
|
||||
user = "authelia-testing";
|
||||
text = ''
|
||||
users:
|
||||
bob:
|
||||
disabled: false
|
||||
displayname: bob
|
||||
# password of password
|
||||
password: $argon2id$v=19$m=65536,t=3,p=4$2ohUAfh9yetl+utr4tLcCQ$AsXx0VlwjvNnCsa70u4HKZvFkC8Gwajr2pHGKcND/xs
|
||||
email: bob@jim.com
|
||||
groups:
|
||||
- admin
|
||||
- dev
|
||||
'';
|
||||
};
|
||||
|
||||
authelia.wait_for_unit("simplehttp.service")
|
||||
authelia.wait_for_unit("traefik.service")
|
||||
authelia.wait_for_unit("authelia-testing.service")
|
||||
authelia.wait_for_open_port(443)
|
||||
authelia.wait_for_unit("multi-user.target")
|
||||
services.traefik = {
|
||||
enable = true;
|
||||
|
||||
with subtest("Check for authelia"):
|
||||
# expect the login page
|
||||
assert "Login - Authelia", "could not reach authelia" in \
|
||||
authelia.succeed("curl --insecure -sSf -H Host:auth.example.com https://authelia:443/")
|
||||
dynamicConfigOptions = {
|
||||
tls.certificates =
|
||||
let
|
||||
certDir = pkgs.runCommand "selfSignedCerts" { buildInputs = [ pkgs.openssl ]; } ''
|
||||
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -nodes -subj '/CN=example.com/CN=auth.example.com/CN=static.example.com' -days 36500
|
||||
mkdir -p $out
|
||||
cp key.pem cert.pem $out
|
||||
'';
|
||||
in
|
||||
[
|
||||
{
|
||||
certFile = "${certDir}/cert.pem";
|
||||
keyFile = "${certDir}/key.pem";
|
||||
}
|
||||
];
|
||||
http.middlewares.authelia.forwardAuth = {
|
||||
address = "http://localhost:9091/api/verify?rd=https%3A%2F%2Fauth.example.com%2F";
|
||||
trustForwardHeader = true;
|
||||
authResponseHeaders = [
|
||||
"Remote-User"
|
||||
"Remote-Groups"
|
||||
"Remote-Email"
|
||||
"Remote-Name"
|
||||
];
|
||||
};
|
||||
http.middlewares.authelia-basic.forwardAuth = {
|
||||
address = "http://localhost:9091/api/verify?auth=basic";
|
||||
trustForwardHeader = true;
|
||||
authResponseHeaders = [
|
||||
"Remote-User"
|
||||
"Remote-Groups"
|
||||
"Remote-Email"
|
||||
"Remote-Name"
|
||||
];
|
||||
};
|
||||
|
||||
with subtest("Check contacting basic http server via traefik with https works"):
|
||||
assert "hello", "could not reach raw static site" in \
|
||||
authelia.succeed("curl --insecure -sSf -H Host:static.example.com https://authelia:443/")
|
||||
http.routers.simplehttp = {
|
||||
rule = "Host(`static.example.com`)";
|
||||
tls = true;
|
||||
entryPoints = "web";
|
||||
service = "simplehttp";
|
||||
};
|
||||
http.routers.simplehttp-basic-auth = {
|
||||
rule = "Host(`static-basic-auth.example.com`)";
|
||||
tls = true;
|
||||
entryPoints = "web";
|
||||
service = "simplehttp";
|
||||
middlewares = [ "authelia-basic@file" ];
|
||||
};
|
||||
|
||||
with subtest("Test traefik and authelia"):
|
||||
with subtest("No details fail"):
|
||||
authelia.fail("curl --insecure -sSf -H Host:static-basic-auth.example.com https://authelia:443/")
|
||||
with subtest("Incorrect details fail"):
|
||||
authelia.fail("curl --insecure -sSf -u 'bob:wordpass' -H Host:static-basic-auth.example.com https://authelia:443/")
|
||||
authelia.fail("curl --insecure -sSf -u 'alice:password' -H Host:static-basic-auth.example.com https://authelia:443/")
|
||||
with subtest("Correct details pass"):
|
||||
assert "hello", "could not reach authed static site with valid credentials" in \
|
||||
authelia.succeed("curl --insecure -sSf -u 'bob:password' -H Host:static-basic-auth.example.com https://authelia:443/")
|
||||
'';
|
||||
}
|
||||
)
|
||||
http.services.simplehttp = {
|
||||
loadBalancer.servers = [
|
||||
{
|
||||
url = "http://localhost:8000";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
http.routers.authelia = {
|
||||
rule = "Host(`auth.example.com`)";
|
||||
tls = true;
|
||||
entryPoints = "web";
|
||||
service = "authelia@file";
|
||||
};
|
||||
|
||||
http.services.authelia = {
|
||||
loadBalancer.servers = [
|
||||
{
|
||||
url = "http://localhost:9091";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
staticConfigOptions = {
|
||||
global = {
|
||||
checkNewVersion = false;
|
||||
sendAnonymousUsage = false;
|
||||
};
|
||||
|
||||
entryPoints.web.address = ":443";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.simplehttp =
|
||||
let
|
||||
fakeWebPageDir = pkgs.writeTextDir "index.html" "hello";
|
||||
in
|
||||
{
|
||||
script = "${pkgs.python3}/bin/python -m http.server --directory ${fakeWebPageDir} 8000";
|
||||
serviceConfig.Type = "simple";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
authelia.wait_for_unit("simplehttp.service")
|
||||
authelia.wait_for_unit("traefik.service")
|
||||
authelia.wait_for_unit("authelia-testing.service")
|
||||
authelia.wait_for_open_port(443)
|
||||
authelia.wait_for_unit("multi-user.target")
|
||||
|
||||
with subtest("Check for authelia"):
|
||||
# expect the login page
|
||||
assert "Login - Authelia", "could not reach authelia" in \
|
||||
authelia.succeed("curl --insecure -sSf -H Host:auth.example.com https://authelia:443/")
|
||||
|
||||
with subtest("Check contacting basic http server via traefik with https works"):
|
||||
assert "hello", "could not reach raw static site" in \
|
||||
authelia.succeed("curl --insecure -sSf -H Host:static.example.com https://authelia:443/")
|
||||
|
||||
with subtest("Test traefik and authelia"):
|
||||
with subtest("No details fail"):
|
||||
authelia.fail("curl --insecure -sSf -H Host:static-basic-auth.example.com https://authelia:443/")
|
||||
with subtest("Incorrect details fail"):
|
||||
authelia.fail("curl --insecure -sSf -u 'bob:wordpass' -H Host:static-basic-auth.example.com https://authelia:443/")
|
||||
authelia.fail("curl --insecure -sSf -u 'alice:password' -H Host:static-basic-auth.example.com https://authelia:443/")
|
||||
with subtest("Correct details pass"):
|
||||
assert "hello", "could not reach authed static site with valid credentials" in \
|
||||
authelia.succeed("curl --insecure -sSf -u 'bob:password' -H Host:static-basic-auth.example.com https://authelia:443/")
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -1,33 +1,27 @@
|
||||
import ./make-test-python.nix (
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
name = "auto-cpufreq-server";
|
||||
|
||||
{
|
||||
name = "auto-cpufreq-server";
|
||||
|
||||
nodes = {
|
||||
machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
# service will still start but since vm inside qemu cpufreq adjustments
|
||||
# cannot be made. This will resource in the following error but the service
|
||||
# remains up:
|
||||
# ERROR:
|
||||
# Couldn't find any of the necessary scaling governors.
|
||||
services.auto-cpufreq = {
|
||||
enable = true;
|
||||
settings = {
|
||||
charger = {
|
||||
turbo = "auto";
|
||||
};
|
||||
};
|
||||
nodes = {
|
||||
machine = {
|
||||
# service will still start but since vm inside qemu cpufreq adjustments
|
||||
# cannot be made. This will resource in the following error but the service
|
||||
# remains up:
|
||||
# ERROR:
|
||||
# Couldn't find any of the necessary scaling governors.
|
||||
services.auto-cpufreq = {
|
||||
enable = true;
|
||||
settings = {
|
||||
charger = {
|
||||
turbo = "auto";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
machine.start()
|
||||
machine.wait_for_unit("auto-cpufreq.service")
|
||||
machine.succeed("auto-cpufreq --force reset")
|
||||
'';
|
||||
}
|
||||
)
|
||||
testScript = ''
|
||||
machine.start()
|
||||
machine.wait_for_unit("auto-cpufreq.service")
|
||||
machine.succeed("auto-cpufreq --force reset")
|
||||
'';
|
||||
}
|
||||
|
||||
+19
-21
@@ -1,25 +1,23 @@
|
||||
import ./make-test-python.nix (
|
||||
{ lib, ... }:
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
name = "autobrr";
|
||||
meta.maintainers = with lib.maintainers; [ av-gal ];
|
||||
{
|
||||
name = "autobrr";
|
||||
meta.maintainers = with lib.maintainers; [ av-gal ];
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
services.autobrr = {
|
||||
enable = true;
|
||||
# We create this secret in the Nix store (making it readable by everyone).
|
||||
# DO NOT DO THIS OUTSIDE OF TESTS!!
|
||||
secretFile = pkgs.writeText "session_secret" "not-secret";
|
||||
};
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
services.autobrr = {
|
||||
enable = true;
|
||||
# We create this secret in the Nix store (making it readable by everyone).
|
||||
# DO NOT DO THIS OUTSIDE OF TESTS!!
|
||||
secretFile = pkgs.writeText "session_secret" "not-secret";
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
machine.wait_for_unit("autobrr.service")
|
||||
machine.wait_for_open_port(7474)
|
||||
machine.succeed("curl --fail http://localhost:7474/")
|
||||
'';
|
||||
}
|
||||
)
|
||||
testScript = ''
|
||||
machine.wait_for_unit("autobrr.service")
|
||||
machine.wait_for_open_port(7474)
|
||||
machine.succeed("curl --fail http://localhost:7474/")
|
||||
'';
|
||||
}
|
||||
|
||||
+7
-10
@@ -1,17 +1,14 @@
|
||||
{
|
||||
system ? builtins.currentSystem,
|
||||
config ? { },
|
||||
pkgs ? import ../.. { inherit system config; },
|
||||
pkgs,
|
||||
# bool: whether to use networkd in the tests
|
||||
networkd ? false,
|
||||
}@args:
|
||||
...
|
||||
}:
|
||||
|
||||
# Test whether `avahi-daemon' and `libnss-mdns' work as expected.
|
||||
import ./make-test-python.nix {
|
||||
{
|
||||
name = "avahi";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ ];
|
||||
};
|
||||
meta.maintainers = [ ];
|
||||
|
||||
nodes =
|
||||
let
|
||||
@@ -29,7 +26,7 @@ import ./make-test-python.nix {
|
||||
extraServiceFiles.ssh = "${pkgs.avahi}/etc/avahi/services/ssh.service";
|
||||
};
|
||||
}
|
||||
// pkgs.lib.optionalAttrs (networkd) {
|
||||
// pkgs.lib.optionalAttrs networkd {
|
||||
networking = {
|
||||
useNetworkd = true;
|
||||
useDHCP = false;
|
||||
@@ -84,4 +81,4 @@ import ./make-test-python.nix {
|
||||
|
||||
one.log(one.execute("systemd-analyze security avahi-daemon.service | grep -v ✓")[1])
|
||||
'';
|
||||
} args
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user