2017-02-02 22:59:39 +00:00
|
|
|
let
|
2017-07-25 08:01:08 +01:00
|
|
|
user = "someuser";
|
|
|
|
password = "some_password";
|
|
|
|
port = builtins.toString 5232;
|
|
|
|
|
2017-09-18 09:46:07 +01:00
|
|
|
common = { pkgs, ... }: {
|
2017-02-02 22:59:39 +00:00
|
|
|
services.radicale = {
|
|
|
|
enable = true;
|
2017-07-25 08:01:08 +01:00
|
|
|
config = ''
|
2017-02-02 22:59:39 +00:00
|
|
|
[auth]
|
|
|
|
type = htpasswd
|
|
|
|
htpasswd_filename = /etc/radicale/htpasswd
|
|
|
|
htpasswd_encryption = bcrypt
|
2017-07-25 08:01:08 +01:00
|
|
|
|
2017-02-02 22:59:39 +00:00
|
|
|
[storage]
|
2017-07-25 08:01:08 +01:00
|
|
|
filesystem_folder = /tmp/collections
|
2017-02-02 22:59:39 +00:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
# WARNING: DON'T DO THIS IN PRODUCTION!
|
2017-12-11 22:09:23 +00:00
|
|
|
# This puts unhashed secrets directly into the Nix store for ease of testing.
|
2017-07-25 08:01:08 +01:00
|
|
|
environment.etc."radicale/htpasswd".source = pkgs.runCommand "htpasswd" {} ''
|
|
|
|
${pkgs.apacheHttpd}/bin/htpasswd -bcB "$out" ${user} ${password}
|
2017-02-02 22:59:39 +00:00
|
|
|
'';
|
|
|
|
};
|
2017-09-18 09:46:07 +01:00
|
|
|
|
|
|
|
in
|
|
|
|
|
2019-12-01 02:05:39 +00:00
|
|
|
import ./make-test-python.nix ({ lib, ... }@args: {
|
2017-09-18 09:46:07 +01:00
|
|
|
name = "radicale";
|
|
|
|
meta.maintainers = with lib.maintainers; [ aneeshusa infinisil ];
|
|
|
|
|
|
|
|
nodes = rec {
|
|
|
|
radicale = radicale1; # Make the test script read more nicely
|
|
|
|
radicale1 = lib.recursiveUpdate (common args) {
|
|
|
|
nixpkgs.overlays = [
|
|
|
|
(self: super: {
|
|
|
|
radicale1 = super.radicale1.overrideAttrs (oldAttrs: {
|
|
|
|
propagatedBuildInputs = with self.pythonPackages;
|
|
|
|
(oldAttrs.propagatedBuildInputs or []) ++ [ passlib ];
|
|
|
|
});
|
|
|
|
})
|
|
|
|
];
|
2018-07-25 21:22:54 +01:00
|
|
|
system.stateVersion = "17.03";
|
2017-09-18 09:46:07 +01:00
|
|
|
};
|
|
|
|
radicale1_export = lib.recursiveUpdate radicale1 {
|
|
|
|
services.radicale.extraArgs = [
|
|
|
|
"--export-storage" "/tmp/collections-new"
|
|
|
|
];
|
2020-06-20 13:30:33 +01:00
|
|
|
system.stateVersion = "17.03";
|
2017-09-18 09:46:07 +01:00
|
|
|
};
|
|
|
|
radicale2_verify = lib.recursiveUpdate radicale2 {
|
2020-06-20 13:30:33 +01:00
|
|
|
services.radicale.extraArgs = [ "--debug" "--verify-storage" ];
|
|
|
|
system.stateVersion = "17.09";
|
2017-09-18 09:46:07 +01:00
|
|
|
};
|
|
|
|
radicale2 = lib.recursiveUpdate (common args) {
|
2018-07-25 21:22:54 +01:00
|
|
|
system.stateVersion = "17.09";
|
2017-09-18 09:46:07 +01:00
|
|
|
};
|
2020-06-20 13:30:33 +01:00
|
|
|
radicale3 = lib.recursiveUpdate (common args) {
|
|
|
|
system.stateVersion = "20.09";
|
|
|
|
};
|
2017-09-18 09:46:07 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
# This tests whether the web interface is accessible to an authenticated user
|
|
|
|
testScript = { nodes }: let
|
|
|
|
switchToConfig = nodeName: let
|
|
|
|
newSystem = nodes.${nodeName}.config.system.build.toplevel;
|
|
|
|
in "${newSystem}/bin/switch-to-configuration test";
|
|
|
|
in ''
|
2019-12-01 02:05:39 +00:00
|
|
|
with subtest("Check Radicale 1 functionality"):
|
|
|
|
radicale.succeed(
|
|
|
|
"${switchToConfig "radicale1"} >&2"
|
|
|
|
)
|
|
|
|
radicale.wait_for_unit("radicale.service")
|
|
|
|
radicale.wait_for_open_port(${port})
|
|
|
|
radicale.succeed(
|
|
|
|
"curl --fail http://${user}:${password}@localhost:${port}/someuser/calendar.ics/"
|
|
|
|
)
|
2017-09-18 09:46:07 +01:00
|
|
|
|
2019-12-01 02:05:39 +00:00
|
|
|
with subtest("Export data in Radicale 2 format"):
|
|
|
|
radicale.succeed("systemctl stop radicale")
|
|
|
|
radicale.succeed("ls -al /tmp/collections")
|
|
|
|
radicale.fail("ls -al /tmp/collections-new")
|
2017-09-18 09:46:07 +01:00
|
|
|
|
2019-12-01 02:05:39 +00:00
|
|
|
with subtest("Radicale exits immediately after exporting storage"):
|
|
|
|
radicale.succeed(
|
|
|
|
"${switchToConfig "radicale1_export"} >&2"
|
|
|
|
)
|
|
|
|
radicale.wait_until_fails("systemctl status radicale")
|
|
|
|
radicale.succeed("ls -al /tmp/collections")
|
|
|
|
radicale.succeed("ls -al /tmp/collections-new")
|
2017-09-18 09:46:07 +01:00
|
|
|
|
2019-12-01 02:05:39 +00:00
|
|
|
with subtest("Verify data in Radicale 2 format"):
|
|
|
|
radicale.succeed("rm -r /tmp/collections/${user}")
|
|
|
|
radicale.succeed("mv /tmp/collections-new/collection-root /tmp/collections")
|
|
|
|
radicale.succeed(
|
|
|
|
"${switchToConfig "radicale2_verify"} >&2"
|
|
|
|
)
|
|
|
|
radicale.wait_until_fails("systemctl status radicale")
|
|
|
|
|
|
|
|
(retcode, logs) = radicale.execute("journalctl -u radicale -n 10")
|
|
|
|
assert (
|
|
|
|
retcode == 0 and "Verifying storage" in logs
|
|
|
|
), "Radicale 2 didn't verify storage"
|
|
|
|
assert (
|
|
|
|
"failed" not in logs and "exception" not in logs
|
|
|
|
), "storage verification failed"
|
|
|
|
|
|
|
|
with subtest("Check Radicale 2 functionality"):
|
|
|
|
radicale.succeed(
|
|
|
|
"${switchToConfig "radicale2"} >&2"
|
|
|
|
)
|
|
|
|
radicale.wait_for_unit("radicale.service")
|
|
|
|
radicale.wait_for_open_port(${port})
|
|
|
|
|
|
|
|
(retcode, output) = radicale.execute(
|
|
|
|
"curl --fail http://${user}:${password}@localhost:${port}/someuser/calendar.ics/"
|
|
|
|
)
|
|
|
|
assert (
|
|
|
|
retcode == 0 and "VCALENDAR" in output
|
|
|
|
), "Could not read calendar from Radicale 2"
|
|
|
|
|
2020-06-20 13:30:33 +01:00
|
|
|
radicale.succeed("curl --fail http://${user}:${password}@localhost:${port}/.web/")
|
|
|
|
|
|
|
|
with subtest("Check Radicale 3 functionality"):
|
|
|
|
radicale.succeed(
|
|
|
|
"${switchToConfig "radicale3"} >&2"
|
|
|
|
)
|
|
|
|
radicale.wait_for_unit("radicale.service")
|
|
|
|
radicale.wait_for_open_port(${port})
|
|
|
|
|
|
|
|
(retcode, output) = radicale.execute(
|
|
|
|
"curl --fail http://${user}:${password}@localhost:${port}/someuser/calendar.ics/"
|
|
|
|
)
|
|
|
|
assert (
|
|
|
|
retcode == 0 and "VCALENDAR" in output
|
|
|
|
), "Could not read calendar from Radicale 3"
|
|
|
|
|
|
|
|
radicale.succeed("curl --fail http://${user}:${password}@localhost:${port}/.web/")
|
2017-09-18 09:46:07 +01:00
|
|
|
'';
|
2017-03-20 16:13:27 +00:00
|
|
|
})
|