diff --git a/nixos/doc/manual/release-notes/rl-1709.xml b/nixos/doc/manual/release-notes/rl-1709.xml
index f271451970a2..55b39209f0d5 100644
--- a/nixos/doc/manual/release-notes/rl-1709.xml
+++ b/nixos/doc/manual/release-notes/rl-1709.xml
@@ -107,7 +107,7 @@ rmdir /var/lib/ipfs/.ipfs
The mysql default dataDir has changed from /var/mysql to /var/lib/mysql.
- Radicale's default package has changed from 1.x to 2.x. Instructions to migrate can be found here . It is also possible to use the newer version by setting the package to radicale2, which is done automatically when stateVersion is 17.09 or higher.
+ Radicale's default package has changed from 1.x to 2.x. Instructions to migrate can be found here . It is also possible to use the newer version by setting the package to radicale2, which is done automatically when stateVersion is 17.09 or higher. The extraArgs option has been added to allow passing the data migration arguments specified in the instructions; see the radicale.nix NixOS test for an example migration.
diff --git a/nixos/modules/services/networking/radicale.nix b/nixos/modules/services/networking/radicale.nix
index f1b8edf43713..56f2e976cff5 100644
--- a/nixos/modules/services/networking/radicale.nix
+++ b/nixos/modules/services/networking/radicale.nix
@@ -48,6 +48,12 @@ in
configuration file.
'';
};
+
+ services.radicale.extraArgs = mkOption {
+ type = types.listOf types.string;
+ default = [];
+ description = "Extra arguments passed to the Radicale daemon.";
+ };
};
config = mkIf cfg.enable {
@@ -71,7 +77,11 @@ in
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
- ExecStart = "${cfg.package}/bin/radicale -C ${confFile} -f";
+ ExecStart = concatStringsSep " " ([
+ "${cfg.package}/bin/radicale" "-C" confFile
+ ] ++ (
+ map escapeShellArg cfg.extraArgs
+ ));
User = "radicale";
Group = "radicale";
};
diff --git a/nixos/tests/radicale.nix b/nixos/tests/radicale.nix
index bec86d2cb284..2c888469d0a4 100644
--- a/nixos/tests/radicale.nix
+++ b/nixos/tests/radicale.nix
@@ -2,12 +2,8 @@ let
user = "someuser";
password = "some_password";
port = builtins.toString 5232;
-in
- import ./make-test.nix ({ pkgs, lib, ... }: {
- name = "radicale";
- meta.maintainers = with lib.maintainers; [ aneeshusa infinisil ];
- machine = {
+ common = { pkgs, ... }: {
services.radicale = {
enable = true;
config = ''
@@ -29,11 +25,81 @@ in
${pkgs.apacheHttpd}/bin/htpasswd -bcB "$out" ${user} ${password}
'';
};
-
- # This tests whether the web interface is accessible to an authenticated user
- testScript = ''
- $machine->waitForUnit('radicale.service');
- $machine->waitForOpenPort(${port});
- $machine->succeed('curl --fail http://${user}:${password}@localhost:${port}/.web/');
- '';
+
+in
+
+ import ./make-test.nix ({ pkgs, lib, ... }@args: {
+ 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 ];
+ });
+ })
+ ];
+ };
+ radicale1_export = lib.recursiveUpdate radicale1 {
+ services.radicale.extraArgs = [
+ "--export-storage" "/tmp/collections-new"
+ ];
+ };
+ radicale2_verify = lib.recursiveUpdate radicale2 {
+ services.radicale.extraArgs = [ "--verify-storage" ];
+ };
+ radicale2 = lib.recursiveUpdate (common args) {
+ system.stateVersion = "17.09";
+ };
+ };
+
+ # 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 ''
+ # Check Radicale 1 functionality
+ $radicale->succeed('${switchToConfig "radicale1"} >&2');
+ $radicale->waitForUnit('radicale.service');
+ $radicale->waitForOpenPort(${port});
+ $radicale->succeed('curl --fail http://${user}:${password}@localhost:${port}/someuser/calendar.ics/');
+
+ # Export data in Radicale 2 format
+ $radicale->succeed('systemctl stop radicale');
+ $radicale->succeed('ls -al /tmp/collections');
+ $radicale->fail('ls -al /tmp/collections-new');
+ # Radicale exits immediately after exporting storage
+ $radicale->succeed('${switchToConfig "radicale1_export"} >&2');
+ $radicale->waitUntilFails('systemctl status radicale');
+ $radicale->succeed('ls -al /tmp/collections');
+ $radicale->succeed('ls -al /tmp/collections-new');
+
+ # 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->waitUntilFails('systemctl status radicale');
+ my ($retcode, $logs) = $radicale->execute('journalctl -u radicale -n 5');
+ if ($retcode != 0 || index($logs, 'Verifying storage') == -1) {
+ die "Radicale 2 didn't verify storage"
+ }
+ if (index($logs, 'failed') != -1 || index($logs, 'exception') != -1) {
+ die "storage verification failed"
+ }
+
+ # Check Radicale 2 functionality
+ $radicale->succeed('${switchToConfig "radicale2"} >&2');
+ $radicale->waitForUnit('radicale.service');
+ $radicale->waitForOpenPort(${port});
+ my ($retcode, $output) = $radicale->execute('curl --fail http://${user}:${password}@localhost:${port}/someuser/calendar.ics/');
+ if ($retcode != 0 || index($output, 'VCALENDAR') == -1) {
+ die "Could not read calendar from Radicale 2"
+ }
+ $radicale->succeed('curl --fail http://${user}:${password}@localhost:${port}/.web/');
+ '';
})
diff --git a/pkgs/servers/radicale/default.nix b/pkgs/servers/radicale/default.nix
index ee38783a899e..9c8ad94f61cb 100644
--- a/pkgs/servers/radicale/default.nix
+++ b/pkgs/servers/radicale/default.nix
@@ -1,8 +1,8 @@
{ stdenv, fetchFromGitHub, python3Packages }:
let
- version = "2.1.2";
- sha256 = "0gmbnvm17j0ilcnci1k2jh0vkbz5g8xlk9lgia5mlx790048hlm8";
+ version = "2.1.6";
+ sha256 = "1x76nvxjhjpagniyh075hqia4sl06972alnhi7628cjrq3pr4v9i";
in
python3Packages.buildPythonApplication {