mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-12 20:55:31 +03:00
nixos/nextcloud: refactor tests
The tests had very much duplication and some if it was even wrong! For instance, `withRcloneEnv` in the MySQL test didn't have the `"$@"` at the bottom to execute commands passed to it. Because of that, the MySQL testcase never checked whether files can be uploaded. Since tests are just another module-system I decided to abstract away common things by using it: * Define a base module with * an empty `client` node and a `nextcloud` node with defaults shared among all tests. * rclone scripts that are used by all tests. * a `testScript` checking upload/download. Additional checks can be added via `test-helpers.extraTests`. * Make common information such as admin user & password shared via options. Also, changed the following things: * The `name` of the final derivation also includes the Nextcloud major it was tested against. * Improved the objecstore test by making sure the file was actually uploaded into the bucket.
This commit is contained in:
parent
6ecafb1c38
commit
0b31ada92b
5 changed files with 232 additions and 280 deletions
|
@ -1,27 +1,27 @@
|
||||||
args@{ pkgs, nextcloudVersion ? 22, ... }:
|
{ name, pkgs, testBase, system,... }:
|
||||||
|
|
||||||
(import ../make-test-python.nix ({ pkgs, ...}: let
|
with import ../../lib/testing-python.nix { inherit system pkgs; };
|
||||||
adminpass = "notproduction";
|
runTest ({ config, ... }: {
|
||||||
adminuser = "root";
|
inherit name;
|
||||||
in {
|
|
||||||
name = "nextcloud-basic";
|
|
||||||
meta = with pkgs.lib.maintainers; {
|
meta = with pkgs.lib.maintainers; {
|
||||||
maintainers = [ globin eqyiel ];
|
maintainers = [ globin eqyiel ma27 ];
|
||||||
};
|
};
|
||||||
|
|
||||||
nodes = rec {
|
imports = [ testBase ];
|
||||||
|
|
||||||
|
nodes = {
|
||||||
# The only thing the client needs to do is download a file.
|
# The only thing the client needs to do is download a file.
|
||||||
client = { ... }: {
|
client = { ... }: {
|
||||||
services.davfs2.enable = true;
|
services.davfs2.enable = true;
|
||||||
systemd.tmpfiles.settings.nextcloud = {
|
systemd.tmpfiles.settings.nextcloud = {
|
||||||
"/tmp/davfs2-secrets"."f+" = {
|
"/tmp/davfs2-secrets"."f+" = {
|
||||||
mode = "0600";
|
mode = "0600";
|
||||||
argument = "http://nextcloud/remote.php/dav/files/${adminuser} ${adminuser} ${adminpass}";
|
argument = "http://nextcloud/remote.php/dav/files/${config.adminuser} ${config.adminuser} ${config.adminpass}";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
virtualisation.fileSystems = {
|
virtualisation.fileSystems = {
|
||||||
"/mnt/dav" = {
|
"/mnt/dav" = {
|
||||||
device = "http://nextcloud/remote.php/dav/files/${adminuser}";
|
device = "http://nextcloud/remote.php/dav/files/${config.adminuser}";
|
||||||
fsType = "davfs";
|
fsType = "davfs";
|
||||||
options = let
|
options = let
|
||||||
davfs2Conf = (pkgs.writeText "davfs2.conf" "secrets /tmp/davfs2-secrets");
|
davfs2Conf = (pkgs.writeText "davfs2.conf" "secrets /tmp/davfs2-secrets");
|
||||||
|
@ -30,11 +30,7 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
nextcloud = { config, pkgs, ... }: let
|
nextcloud = { config, pkgs, ... }: {
|
||||||
cfg = config;
|
|
||||||
in {
|
|
||||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
|
||||||
|
|
||||||
systemd.tmpfiles.rules = [
|
systemd.tmpfiles.rules = [
|
||||||
"d /var/lib/nextcloud-data 0750 nextcloud nginx - -"
|
"d /var/lib/nextcloud-data 0750 nextcloud nginx - -"
|
||||||
];
|
];
|
||||||
|
@ -42,14 +38,7 @@ in {
|
||||||
services.nextcloud = {
|
services.nextcloud = {
|
||||||
enable = true;
|
enable = true;
|
||||||
datadir = "/var/lib/nextcloud-data";
|
datadir = "/var/lib/nextcloud-data";
|
||||||
hostName = "nextcloud";
|
config.dbtableprefix = "nixos_";
|
||||||
database.createLocally = true;
|
|
||||||
config = {
|
|
||||||
# Don't inherit adminuser since "root" is supposed to be the default
|
|
||||||
adminpassFile = "${pkgs.writeText "adminpass" adminpass}"; # Don't try this at home!
|
|
||||||
dbtableprefix = "nixos_";
|
|
||||||
};
|
|
||||||
package = pkgs.${"nextcloud" + (toString nextcloudVersion)};
|
|
||||||
autoUpdateApps = {
|
autoUpdateApps = {
|
||||||
enable = true;
|
enable = true;
|
||||||
startAt = "20:00";
|
startAt = "20:00";
|
||||||
|
@ -57,64 +46,31 @@ in {
|
||||||
phpExtraExtensions = all: [ all.bz2 ];
|
phpExtraExtensions = all: [ all.bz2 ];
|
||||||
};
|
};
|
||||||
|
|
||||||
environment.systemPackages = [ cfg.services.nextcloud.occ ];
|
specialisation.withoutMagick.configuration = {
|
||||||
|
services.nextcloud.enableImagemagick = false;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
nextcloudWithoutMagick = args@{ config, pkgs, lib, ... }:
|
|
||||||
lib.mkMerge
|
|
||||||
[ (nextcloud args)
|
|
||||||
{ services.nextcloud.enableImagemagick = false; } ];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = { nodes, ... }: let
|
test-helpers.extraTests = { nodes, ... }: let
|
||||||
withRcloneEnv = pkgs.writeScript "with-rclone-env" ''
|
|
||||||
#!${pkgs.runtimeShell}
|
|
||||||
export RCLONE_CONFIG_NEXTCLOUD_TYPE=webdav
|
|
||||||
export RCLONE_CONFIG_NEXTCLOUD_URL="http://nextcloud/remote.php/dav/files/${adminuser}"
|
|
||||||
export RCLONE_CONFIG_NEXTCLOUD_VENDOR="nextcloud"
|
|
||||||
export RCLONE_CONFIG_NEXTCLOUD_USER="${adminuser}"
|
|
||||||
export RCLONE_CONFIG_NEXTCLOUD_PASS="$(${pkgs.rclone}/bin/rclone obscure ${adminpass})"
|
|
||||||
"''${@}"
|
|
||||||
'';
|
|
||||||
copySharedFile = pkgs.writeScript "copy-shared-file" ''
|
|
||||||
#!${pkgs.runtimeShell}
|
|
||||||
echo 'hi' | ${withRcloneEnv} ${pkgs.rclone}/bin/rclone rcat nextcloud:test-shared-file
|
|
||||||
'';
|
|
||||||
|
|
||||||
diffSharedFile = pkgs.writeScript "diff-shared-file" ''
|
|
||||||
#!${pkgs.runtimeShell}
|
|
||||||
diff <(echo 'hi') <(${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file)
|
|
||||||
'';
|
|
||||||
|
|
||||||
findInClosure = what: drv: pkgs.runCommand "find-in-closure" { exportReferencesGraph = [ "graph" drv ]; inherit what; } ''
|
findInClosure = what: drv: pkgs.runCommand "find-in-closure" { exportReferencesGraph = [ "graph" drv ]; inherit what; } ''
|
||||||
test -e graph
|
test -e graph
|
||||||
grep "$what" graph >$out || true
|
grep "$what" graph >$out || true
|
||||||
'';
|
'';
|
||||||
nextcloudUsesImagick = findInClosure "imagick" nodes.nextcloud.system.build.vm;
|
nexcloudWithImagick = findInClosure "imagick" nodes.nextcloud.system.build.vm;
|
||||||
nextcloudWithoutDoesntUseIt = findInClosure "imagick" nodes.nextcloudWithoutMagick.system.build.vm;
|
nextcloudWithoutImagick = findInClosure "imagick" nodes.nextcloud.specialisation.withoutMagick.configuration.system.build.vm;
|
||||||
in ''
|
in ''
|
||||||
assert open("${nextcloudUsesImagick}").read() != ""
|
with subtest("File is in proper nextcloud home"):
|
||||||
assert open("${nextcloudWithoutDoesntUseIt}").read() == ""
|
nextcloud.succeed("test -f ${nodes.nextcloud.services.nextcloud.datadir}/data/root/files/test-shared-file")
|
||||||
|
|
||||||
nextcloud.start()
|
with subtest("Closure checks"):
|
||||||
client.start()
|
assert open("${nexcloudWithImagick}").read() != ""
|
||||||
nextcloud.wait_for_unit("multi-user.target")
|
assert open("${nextcloudWithoutImagick}").read() == ""
|
||||||
# This is just to ensure the nextcloud-occ program is working
|
|
||||||
nextcloud.succeed("nextcloud-occ status")
|
with subtest("Davfs2"):
|
||||||
nextcloud.succeed("curl -sSf http://nextcloud/login")
|
assert "hi" in client.succeed("cat /mnt/dav/test-shared-file")
|
||||||
# Ensure that no OpenSSL 1.1 is used.
|
|
||||||
nextcloud.succeed(
|
with subtest("Ensure SSE is disabled by default"):
|
||||||
"${nodes.nextcloud.services.phpfpm.pools.nextcloud.phpPackage}/bin/php -i | grep 'OpenSSL Library Version' | awk -F'=>' '{ print $2 }' | awk '{ print $2 }' | grep -v 1.1"
|
nextcloud.succeed("grep -vE '^HBEGIN:oc_encryption_module' /var/lib/nextcloud-data/data/root/files/test-shared-file")
|
||||||
)
|
|
||||||
nextcloud.succeed(
|
|
||||||
"${withRcloneEnv} ${copySharedFile}"
|
|
||||||
)
|
|
||||||
client.wait_for_unit("multi-user.target")
|
|
||||||
nextcloud.succeed("test -f /var/lib/nextcloud-data/data/root/files/test-shared-file")
|
|
||||||
client.succeed(
|
|
||||||
"${withRcloneEnv} ${diffSharedFile}"
|
|
||||||
)
|
|
||||||
assert "hi" in client.succeed("cat /mnt/dav/test-shared-file")
|
|
||||||
nextcloud.succeed("grep -vE '^HBEGIN:oc_encryption_module' /var/lib/nextcloud-data/data/root/files/test-shared-file")
|
|
||||||
'';
|
'';
|
||||||
})) args
|
})
|
||||||
|
|
|
@ -5,25 +5,108 @@
|
||||||
|
|
||||||
with pkgs.lib;
|
with pkgs.lib;
|
||||||
|
|
||||||
foldl
|
let
|
||||||
(matrix: ver: matrix // {
|
baseModule = { config, ... }: {
|
||||||
"basic${toString ver}" = import ./basic.nix { inherit system pkgs; nextcloudVersion = ver; };
|
imports = [
|
||||||
"with-postgresql-and-redis${toString ver}" = import ./with-postgresql-and-redis.nix {
|
{
|
||||||
inherit system pkgs;
|
options.test-helpers = {
|
||||||
nextcloudVersion = ver;
|
rclone = mkOption { type = types.str; };
|
||||||
|
upload-sample = mkOption { type = types.str; };
|
||||||
|
check-sample = mkOption { type = types.str; };
|
||||||
|
init = mkOption { type = types.str; default = ""; };
|
||||||
|
extraTests = mkOption { type = types.either types.str (types.functionTo types.str); default = ""; };
|
||||||
|
};
|
||||||
|
options.adminuser = mkOption { type = types.str; };
|
||||||
|
options.adminpass = mkOption { type = types.str; };
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
adminuser = "root";
|
||||||
|
adminpass = "hunter2";
|
||||||
|
|
||||||
|
test-helpers.rclone = "${pkgs.writeShellScript "rclone" ''
|
||||||
|
set -euo pipefail
|
||||||
|
export PATH="${pkgs.rclone}/bin:$PATH"
|
||||||
|
export RCLONE_CONFIG_NEXTCLOUD_TYPE=webdav
|
||||||
|
export RCLONE_CONFIG_NEXTCLOUD_URL="http://nextcloud/remote.php/dav/files/${config.adminuser}"
|
||||||
|
export RCLONE_CONFIG_NEXTCLOUD_VENDOR="nextcloud"
|
||||||
|
export RCLONE_CONFIG_NEXTCLOUD_USER="${config.adminuser}"
|
||||||
|
export RCLONE_CONFIG_NEXTCLOUD_PASS="$(rclone obscure ${config.adminpass})"
|
||||||
|
exec "$@"
|
||||||
|
''}";
|
||||||
|
test-helpers.upload-sample = "${pkgs.writeShellScript "rclone-upload" ''
|
||||||
|
<<<'hi' rclone rcat nextcloud:test-shared-file
|
||||||
|
''}";
|
||||||
|
test-helpers.check-sample = "${pkgs.writeShellScript "check-sample" ''
|
||||||
|
set -e
|
||||||
|
diff <(echo 'hi') <(rclone cat nextcloud:test-shared-file)
|
||||||
|
''}";
|
||||||
|
|
||||||
|
nodes = {
|
||||||
|
client = { ... }: {};
|
||||||
|
nextcloud = {
|
||||||
|
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||||
|
services.nextcloud = {
|
||||||
|
enable = true;
|
||||||
|
hostName = "nextcloud";
|
||||||
|
https = false;
|
||||||
|
database.createLocally = true;
|
||||||
|
config = {
|
||||||
|
adminpassFile = "${pkgs.writeText "adminpass" config.adminpass}"; # Don't try this at home!
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
"with-mysql-and-memcached${toString ver}" = import ./with-mysql-and-memcached.nix {
|
|
||||||
inherit system pkgs;
|
testScript = args@{ nodes, ... }: let
|
||||||
nextcloudVersion = ver;
|
inherit (config) test-helpers;
|
||||||
};
|
in mkBefore ''
|
||||||
"with-declarative-redis-and-secrets${toString ver}" = import ./with-declarative-redis-and-secrets.nix {
|
nextcloud.start()
|
||||||
inherit system pkgs;
|
client.start()
|
||||||
nextcloudVersion = ver;
|
nextcloud.wait_for_unit("multi-user.target")
|
||||||
};
|
|
||||||
"with-objectstore${toString ver}" = import ./with-objectstore.nix {
|
${test-helpers.init}
|
||||||
inherit system pkgs;
|
|
||||||
nextcloudVersion = ver;
|
with subtest("Ensure nextcloud-occ is working"):
|
||||||
};
|
nextcloud.succeed("nextcloud-occ status")
|
||||||
})
|
nextcloud.succeed("curl -sSf http://nextcloud/login")
|
||||||
{ }
|
|
||||||
[ 27 28 29 ]
|
with subtest("Upload/Download test"):
|
||||||
|
nextcloud.succeed(
|
||||||
|
"${test-helpers.rclone} ${test-helpers.upload-sample}"
|
||||||
|
)
|
||||||
|
client.wait_for_unit("multi-user.target")
|
||||||
|
client.succeed(
|
||||||
|
"${test-helpers.rclone} ${test-helpers.check-sample}"
|
||||||
|
)
|
||||||
|
|
||||||
|
${if builtins.isFunction test-helpers.extraTests then test-helpers.extraTests args else test-helpers.extraTests}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
genTests = version:
|
||||||
|
let
|
||||||
|
testBase.imports = [
|
||||||
|
baseModule
|
||||||
|
{
|
||||||
|
nodes.nextcloud = { pkgs, ... }: {
|
||||||
|
services.nextcloud.package = pkgs.${"nextcloud${toString version}"};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
callNextcloudTest = path:
|
||||||
|
let
|
||||||
|
name = "${removeSuffix ".nix" (baseNameOf path)}${toString version}";
|
||||||
|
in nameValuePair name (import path {
|
||||||
|
inherit system pkgs testBase;
|
||||||
|
name = "nextcloud-${name}";
|
||||||
|
});
|
||||||
|
in map callNextcloudTest [
|
||||||
|
./basic.nix
|
||||||
|
./with-mysql-and-memcached.nix
|
||||||
|
./with-postgresql-and-redis.nix
|
||||||
|
./with-objectstore.nix
|
||||||
|
];
|
||||||
|
in
|
||||||
|
listToAttrs (concatMap genTests [ 27 28 29 ])
|
||||||
|
|
|
@ -1,79 +1,37 @@
|
||||||
args@{ pkgs, nextcloudVersion ? 22, ... }:
|
{ pkgs, testBase, system, ... }:
|
||||||
|
|
||||||
(import ../make-test-python.nix ({ pkgs, ...}: let
|
with import ../../lib/testing-python.nix { inherit system pkgs; };
|
||||||
adminpass = "hunter2";
|
runTest ({ config, ... }: {
|
||||||
adminuser = "root";
|
|
||||||
in {
|
|
||||||
name = "nextcloud-with-mysql-and-memcached";
|
name = "nextcloud-with-mysql-and-memcached";
|
||||||
meta = with pkgs.lib.maintainers; {
|
meta = with pkgs.lib.maintainers; {
|
||||||
maintainers = [ eqyiel ];
|
maintainers = [ eqyiel ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
imports = [ testBase ];
|
||||||
|
|
||||||
nodes = {
|
nodes = {
|
||||||
# The only thing the client needs to do is download a file.
|
|
||||||
client = { ... }: {};
|
|
||||||
|
|
||||||
nextcloud = { config, pkgs, ... }: {
|
nextcloud = { config, pkgs, ... }: {
|
||||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
|
||||||
|
|
||||||
services.nextcloud = {
|
services.nextcloud = {
|
||||||
enable = true;
|
|
||||||
hostName = "nextcloud";
|
|
||||||
https = true;
|
|
||||||
package = pkgs.${"nextcloud" + (toString nextcloudVersion)};
|
|
||||||
caching = {
|
caching = {
|
||||||
apcu = true;
|
apcu = true;
|
||||||
redis = false;
|
redis = false;
|
||||||
memcached = true;
|
memcached = true;
|
||||||
};
|
};
|
||||||
database.createLocally = true;
|
config.dbtype = "mysql";
|
||||||
config = {
|
|
||||||
dbtype = "mysql";
|
|
||||||
# Don't inherit adminuser since "root" is supposed to be the default
|
|
||||||
adminpassFile = "${pkgs.writeText "adminpass" adminpass}"; # Don't try this at home!
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
services.memcached.enable = true;
|
services.memcached.enable = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = let
|
test-helpers.init = let
|
||||||
configureMemcached = pkgs.writeScript "configure-memcached" ''
|
configureMemcached = pkgs.writeScript "configure-memcached" ''
|
||||||
#!${pkgs.runtimeShell}
|
|
||||||
nextcloud-occ config:system:set memcached_servers 0 0 --value 127.0.0.1 --type string
|
nextcloud-occ config:system:set memcached_servers 0 0 --value 127.0.0.1 --type string
|
||||||
nextcloud-occ config:system:set memcached_servers 0 1 --value 11211 --type integer
|
nextcloud-occ config:system:set memcached_servers 0 1 --value 11211 --type integer
|
||||||
nextcloud-occ config:system:set memcache.local --value '\OC\Memcache\APCu' --type string
|
nextcloud-occ config:system:set memcache.local --value '\OC\Memcache\APCu' --type string
|
||||||
nextcloud-occ config:system:set memcache.distributed --value '\OC\Memcache\Memcached' --type string
|
nextcloud-occ config:system:set memcache.distributed --value '\OC\Memcache\Memcached' --type string
|
||||||
'';
|
'';
|
||||||
withRcloneEnv = pkgs.writeScript "with-rclone-env" ''
|
|
||||||
#!${pkgs.runtimeShell}
|
|
||||||
export RCLONE_CONFIG_NEXTCLOUD_TYPE=webdav
|
|
||||||
export RCLONE_CONFIG_NEXTCLOUD_URL="http://nextcloud/remote.php/dav/files/${adminuser}"
|
|
||||||
export RCLONE_CONFIG_NEXTCLOUD_VENDOR="nextcloud"
|
|
||||||
export RCLONE_CONFIG_NEXTCLOUD_USER="${adminuser}"
|
|
||||||
export RCLONE_CONFIG_NEXTCLOUD_PASS="$(${pkgs.rclone}/bin/rclone obscure ${adminpass})"
|
|
||||||
'';
|
|
||||||
copySharedFile = pkgs.writeScript "copy-shared-file" ''
|
|
||||||
#!${pkgs.runtimeShell}
|
|
||||||
echo 'hi' | ${pkgs.rclone}/bin/rclone rcat nextcloud:test-shared-file
|
|
||||||
'';
|
|
||||||
|
|
||||||
diffSharedFile = pkgs.writeScript "diff-shared-file" ''
|
|
||||||
#!${pkgs.runtimeShell}
|
|
||||||
diff <(echo 'hi') <(${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file)
|
|
||||||
'';
|
|
||||||
in ''
|
in ''
|
||||||
start_all()
|
|
||||||
nextcloud.wait_for_unit("multi-user.target")
|
|
||||||
nextcloud.succeed("${configureMemcached}")
|
nextcloud.succeed("${configureMemcached}")
|
||||||
nextcloud.succeed("curl -sSf http://nextcloud/login")
|
|
||||||
nextcloud.succeed(
|
|
||||||
"${withRcloneEnv} ${copySharedFile}"
|
|
||||||
)
|
|
||||||
client.wait_for_unit("multi-user.target")
|
|
||||||
client.succeed(
|
|
||||||
"${withRcloneEnv} ${diffSharedFile}"
|
|
||||||
)
|
|
||||||
'';
|
'';
|
||||||
})) args
|
})
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
args@{ pkgs, nextcloudVersion ? 28, ... }:
|
{ name, pkgs, testBase, system, ... }:
|
||||||
|
|
||||||
(import ../make-test-python.nix ({ pkgs, ...}: let
|
|
||||||
adminpass = "hunter2";
|
|
||||||
adminuser = "root";
|
|
||||||
|
|
||||||
|
with import ../../lib/testing-python.nix { inherit system pkgs; };
|
||||||
|
runTest ({ config, lib, ... }: let
|
||||||
accessKey = "BKIKJAA5BMMU2RHO6IBB";
|
accessKey = "BKIKJAA5BMMU2RHO6IBB";
|
||||||
secretKey = "V7f1CwQqAcwo80UEIJEjc5gVQUSSx5ohQ9GSrr12";
|
secretKey = "V7f1CwQqAcwo80UEIJEjc5gVQUSSx5ohQ9GSrr12";
|
||||||
|
|
||||||
|
@ -11,40 +9,30 @@ args@{ pkgs, nextcloudVersion ? 28, ... }:
|
||||||
MINIO_ROOT_USER=${accessKey}
|
MINIO_ROOT_USER=${accessKey}
|
||||||
MINIO_ROOT_PASSWORD=${secretKey}
|
MINIO_ROOT_PASSWORD=${secretKey}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
in {
|
in {
|
||||||
name = "nextcloud-with-objectstore";
|
inherit name;
|
||||||
meta = with pkgs.lib.maintainers; {
|
meta = with pkgs.lib.maintainers; {
|
||||||
maintainers = [ onny ma27 ];
|
maintainers = [ onny ma27 ];
|
||||||
};
|
};
|
||||||
|
|
||||||
nodes = {
|
imports = [ testBase ];
|
||||||
# The only thing the client needs to do is download a file.
|
|
||||||
client = { ... }: {};
|
|
||||||
|
|
||||||
|
nodes = {
|
||||||
nextcloud = { config, pkgs, ... }: {
|
nextcloud = { config, pkgs, ... }: {
|
||||||
networking.firewall.allowedTCPPorts = [ 80 9000 ];
|
networking.firewall.allowedTCPPorts = [ 9000 ];
|
||||||
environment.systemPackages = [ pkgs.minio-client ];
|
environment.systemPackages = [ pkgs.minio-client ];
|
||||||
|
|
||||||
services.nextcloud = {
|
services.nextcloud.config.objectstore.s3 = {
|
||||||
enable = true;
|
enable = true;
|
||||||
hostName = "nextcloud";
|
bucket = "nextcloud";
|
||||||
package = pkgs.${"nextcloud" + (toString nextcloudVersion)};
|
autocreate = true;
|
||||||
database.createLocally = true;
|
key = accessKey;
|
||||||
# Don't try this at home!
|
secretFile = "${pkgs.writeText "secretKey" secretKey}";
|
||||||
config.adminpassFile = "${pkgs.writeText "adminpass" adminpass}";
|
hostname = "nextcloud";
|
||||||
config.objectstore.s3 = {
|
useSsl = false;
|
||||||
enable = true;
|
port = 9000;
|
||||||
bucket = "nextcloud";
|
usePathStyle = true;
|
||||||
autocreate = false;
|
region = "us-east-1";
|
||||||
key = accessKey;
|
|
||||||
secretFile = "${pkgs.writeText "secretKey" secretKey}";
|
|
||||||
hostname = "nextcloud";
|
|
||||||
useSsl = false;
|
|
||||||
port = 9000;
|
|
||||||
usePathStyle = true;
|
|
||||||
region = "us-east-1";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
services.minio = {
|
services.minio = {
|
||||||
|
@ -53,51 +41,56 @@ in {
|
||||||
consoleAddress = "0.0.0.0:9001";
|
consoleAddress = "0.0.0.0:9001";
|
||||||
inherit rootCredentialsFile;
|
inherit rootCredentialsFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = let
|
test-helpers.init = ''
|
||||||
withRcloneEnv = pkgs.writeScript "with-rclone-env" ''
|
|
||||||
#!${pkgs.runtimeShell}
|
|
||||||
export RCLONE_CONFIG_NEXTCLOUD_TYPE=webdav
|
|
||||||
export RCLONE_CONFIG_NEXTCLOUD_URL="http://nextcloud/remote.php/dav/files/${adminuser}"
|
|
||||||
export RCLONE_CONFIG_NEXTCLOUD_VENDOR="nextcloud"
|
|
||||||
export RCLONE_CONFIG_NEXTCLOUD_USER="${adminuser}"
|
|
||||||
export RCLONE_CONFIG_NEXTCLOUD_PASS="$(${pkgs.rclone}/bin/rclone obscure ${adminpass})"
|
|
||||||
"''${@}"
|
|
||||||
'';
|
|
||||||
copySharedFile = pkgs.writeScript "copy-shared-file" ''
|
|
||||||
#!${pkgs.runtimeShell}
|
|
||||||
set -euxo pipefail
|
|
||||||
echo 'hello world' | ${pkgs.rclone}/bin/rclone rcat nextcloud:test-shared-file
|
|
||||||
'';
|
|
||||||
|
|
||||||
diffSharedFile = pkgs.writeScript "diff-shared-file" ''
|
|
||||||
#!${pkgs.runtimeShell}
|
|
||||||
set -euxo pipefail
|
|
||||||
diff <(echo 'hello world') <(${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file)
|
|
||||||
'';
|
|
||||||
in ''
|
|
||||||
start_all()
|
|
||||||
nextcloud.wait_for_unit("multi-user.target")
|
|
||||||
nextcloud.wait_for_unit("minio.service")
|
|
||||||
nextcloud.wait_for_open_port(9000)
|
nextcloud.wait_for_open_port(9000)
|
||||||
nextcloud.succeed(
|
|
||||||
"mc config host add minio http://localhost:9000 ${accessKey} ${secretKey} --api s3v4"
|
|
||||||
)
|
|
||||||
nextcloud.succeed("mc mb minio/nextcloud")
|
|
||||||
nextcloud.succeed("curl -sSf http://nextcloud/login")
|
|
||||||
|
|
||||||
client.wait_for_unit("multi-user.target")
|
|
||||||
client.succeed(
|
|
||||||
"${withRcloneEnv} ${copySharedFile}"
|
|
||||||
)
|
|
||||||
nextcloud.succeed("${withRcloneEnv} ${diffSharedFile}")
|
|
||||||
client.wait_until_succeeds(
|
|
||||||
"${withRcloneEnv} ${diffSharedFile}"
|
|
||||||
)
|
|
||||||
|
|
||||||
nextcloud.succeed("mc ls --recursive minio >&2")
|
|
||||||
'';
|
'';
|
||||||
})) args
|
|
||||||
|
test-helpers.extraTests = { nodes, ... }: ''
|
||||||
|
with subtest("File is not on the filesystem"):
|
||||||
|
nextcloud.succeed("test ! -e ${nodes.nextcloud.services.nextcloud.home}/data/root/files/test-shared-file")
|
||||||
|
|
||||||
|
with subtest("Check if file is in S3"):
|
||||||
|
nextcloud.succeed(
|
||||||
|
"mc config host add minio http://localhost:9000 ${accessKey} ${secretKey} --api s3v4"
|
||||||
|
)
|
||||||
|
files = nextcloud.succeed('mc ls minio/nextcloud|sort').strip().split('\n')
|
||||||
|
|
||||||
|
# Cannot assert an exact number here, nc27 writes more stuff initially into S3.
|
||||||
|
# For now let's assume it's always the most recently added file.
|
||||||
|
assert len(files) > 0, f"""
|
||||||
|
Expected to have at least one object in minio/nextcloud. But `mc ls` gave output:
|
||||||
|
|
||||||
|
'{files}'
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
ptrn = re.compile("^\[[A-Z0-9 :-]+\] +(?P<details>[A-Za-z0-9 :]+)$")
|
||||||
|
match = ptrn.match(files[-1].strip())
|
||||||
|
assert match, "Cannot match mc client output!"
|
||||||
|
size, type_, file = tuple(match.group('details').split(' '))
|
||||||
|
|
||||||
|
assert size == "3B", f"""
|
||||||
|
Expected size of uploaded file to be 3 bytes, got {size}
|
||||||
|
"""
|
||||||
|
|
||||||
|
assert type_ == 'STANDARD', f"""
|
||||||
|
Expected type of bucket entry to be a file, i.e. 'STANDARD'. Got {type_}
|
||||||
|
"""
|
||||||
|
|
||||||
|
assert file.startswith('urn:oid'), """
|
||||||
|
Expected filename to start with 'urn:oid', instead got '{file}.
|
||||||
|
"""
|
||||||
|
|
||||||
|
with subtest("Test download from S3"):
|
||||||
|
client.succeed(
|
||||||
|
"env AWS_ACCESS_KEY_ID=${accessKey} AWS_SECRET_ACCESS_KEY=${secretKey} "
|
||||||
|
+ f"${lib.getExe pkgs.awscli2} s3 cp s3://nextcloud/{file} test --endpoint-url http://nextcloud:9000 "
|
||||||
|
+ "--region us-east-1"
|
||||||
|
)
|
||||||
|
|
||||||
|
client.succeed("test hi = $(cat test)")
|
||||||
|
'';
|
||||||
|
})
|
||||||
|
|
|
@ -1,45 +1,30 @@
|
||||||
args@{ pkgs, nextcloudVersion ? 22, ... }:
|
{ name, pkgs, testBase, system, ... }:
|
||||||
|
|
||||||
(import ../make-test-python.nix ({ pkgs, ...}: let
|
with import ../../lib/testing-python.nix { inherit system pkgs; };
|
||||||
adminpass = "hunter2";
|
runTest ({ config, ... }: {
|
||||||
adminuser = "custom-admin-username";
|
inherit name;
|
||||||
in {
|
|
||||||
name = "nextcloud-with-postgresql-and-redis";
|
|
||||||
meta = with pkgs.lib.maintainers; {
|
meta = with pkgs.lib.maintainers; {
|
||||||
maintainers = [ eqyiel ];
|
maintainers = [ eqyiel ma27 ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
imports = [ testBase ];
|
||||||
|
|
||||||
nodes = {
|
nodes = {
|
||||||
# The only thing the client needs to do is download a file.
|
|
||||||
client = { ... }: {};
|
|
||||||
|
|
||||||
nextcloud = { config, pkgs, lib, ... }: {
|
nextcloud = { config, pkgs, lib, ... }: {
|
||||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
|
||||||
|
|
||||||
services.nextcloud = {
|
services.nextcloud = {
|
||||||
enable = true;
|
|
||||||
hostName = "nextcloud";
|
|
||||||
package = pkgs.${"nextcloud" + (toString nextcloudVersion)};
|
|
||||||
caching = {
|
caching = {
|
||||||
apcu = false;
|
apcu = false;
|
||||||
redis = true;
|
redis = true;
|
||||||
memcached = false;
|
memcached = false;
|
||||||
};
|
};
|
||||||
database.createLocally = true;
|
config.dbtype = "pgsql";
|
||||||
config = {
|
|
||||||
dbtype = "pgsql";
|
|
||||||
inherit adminuser;
|
|
||||||
adminpassFile = toString (pkgs.writeText "admin-pass-file" ''
|
|
||||||
${adminpass}
|
|
||||||
'');
|
|
||||||
};
|
|
||||||
notify_push = {
|
notify_push = {
|
||||||
enable = true;
|
enable = true;
|
||||||
logLevel = "debug";
|
logLevel = "debug";
|
||||||
};
|
};
|
||||||
extraAppsEnable = true;
|
extraAppsEnable = true;
|
||||||
extraApps = {
|
extraApps = with config.services.nextcloud.package.packages.apps; {
|
||||||
inherit (pkgs."nextcloud${lib.versions.major config.services.nextcloud.package.version}Packages".apps) notify_push notes;
|
inherit notify_push notes;
|
||||||
};
|
};
|
||||||
settings.trusted_proxies = [ "::1" ];
|
settings.trusted_proxies = [ "::1" ];
|
||||||
};
|
};
|
||||||
|
@ -49,50 +34,27 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = let
|
test-helpers.init = let
|
||||||
configureRedis = pkgs.writeScript "configure-redis" ''
|
configureRedis = pkgs.writeScript "configure-redis" ''
|
||||||
#!${pkgs.runtimeShell}
|
|
||||||
nextcloud-occ config:system:set redis 'host' --value 'localhost' --type string
|
nextcloud-occ config:system:set redis 'host' --value 'localhost' --type string
|
||||||
nextcloud-occ config:system:set redis 'port' --value 6379 --type integer
|
nextcloud-occ config:system:set redis 'port' --value 6379 --type integer
|
||||||
nextcloud-occ config:system:set memcache.local --value '\OC\Memcache\Redis' --type string
|
nextcloud-occ config:system:set memcache.local --value '\OC\Memcache\Redis' --type string
|
||||||
nextcloud-occ config:system:set memcache.locking --value '\OC\Memcache\Redis' --type string
|
nextcloud-occ config:system:set memcache.locking --value '\OC\Memcache\Redis' --type string
|
||||||
'';
|
'';
|
||||||
withRcloneEnv = pkgs.writeScript "with-rclone-env" ''
|
|
||||||
#!${pkgs.runtimeShell}
|
|
||||||
export RCLONE_CONFIG_NEXTCLOUD_TYPE=webdav
|
|
||||||
export RCLONE_CONFIG_NEXTCLOUD_URL="http://nextcloud/remote.php/dav/files/${adminuser}"
|
|
||||||
export RCLONE_CONFIG_NEXTCLOUD_VENDOR="nextcloud"
|
|
||||||
export RCLONE_CONFIG_NEXTCLOUD_USER="${adminuser}"
|
|
||||||
export RCLONE_CONFIG_NEXTCLOUD_PASS="$(${pkgs.rclone}/bin/rclone obscure ${adminpass})"
|
|
||||||
"''${@}"
|
|
||||||
'';
|
|
||||||
copySharedFile = pkgs.writeScript "copy-shared-file" ''
|
|
||||||
#!${pkgs.runtimeShell}
|
|
||||||
echo 'hi' | ${pkgs.rclone}/bin/rclone rcat nextcloud:test-shared-file
|
|
||||||
'';
|
|
||||||
|
|
||||||
diffSharedFile = pkgs.writeScript "diff-shared-file" ''
|
|
||||||
#!${pkgs.runtimeShell}
|
|
||||||
diff <(echo 'hi') <(${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file)
|
|
||||||
'';
|
|
||||||
in ''
|
in ''
|
||||||
start_all()
|
|
||||||
nextcloud.wait_for_unit("multi-user.target")
|
|
||||||
nextcloud.succeed("${configureRedis}")
|
nextcloud.succeed("${configureRedis}")
|
||||||
nextcloud.succeed("curl -sSf http://nextcloud/login")
|
|
||||||
nextcloud.succeed(
|
|
||||||
"${withRcloneEnv} ${copySharedFile}"
|
|
||||||
)
|
|
||||||
client.wait_for_unit("multi-user.target")
|
|
||||||
client.execute("${pkgs.lib.getExe pkgs.nextcloud-notify_push.passthru.test_client} http://nextcloud ${adminuser} ${adminpass} >&2 &")
|
|
||||||
client.succeed(
|
|
||||||
"${withRcloneEnv} ${diffSharedFile}"
|
|
||||||
)
|
|
||||||
nextcloud.wait_until_succeeds("journalctl -u nextcloud-notify_push | grep -q \"Sending ping to ${adminuser}\"")
|
|
||||||
|
|
||||||
# redis cache should not be empty
|
|
||||||
nextcloud.fail('test "[]" = "$(redis-cli --json KEYS "*")"')
|
|
||||||
|
|
||||||
nextcloud.fail("curl -f http://nextcloud/nix-apps/notes/lib/AppInfo/Application.php")
|
|
||||||
'';
|
'';
|
||||||
})) args
|
|
||||||
|
test-helpers.extraTests = ''
|
||||||
|
with subtest("notify-push"):
|
||||||
|
client.execute("${pkgs.lib.getExe pkgs.nextcloud-notify_push.passthru.test_client} http://nextcloud ${config.adminuser} ${config.adminpass} >&2 &")
|
||||||
|
nextcloud.wait_until_succeeds("journalctl -u nextcloud-notify_push | grep -q \"Sending ping to ${config.adminuser}\"")
|
||||||
|
|
||||||
|
with subtest("Redis is used for caching"):
|
||||||
|
# redis cache should not be empty
|
||||||
|
nextcloud.fail('test "[]" = "$(redis-cli --json KEYS "*")"')
|
||||||
|
|
||||||
|
with subtest("No code is returned when requesting PHP files (regression test)"):
|
||||||
|
nextcloud.fail("curl -f http://nextcloud/nix-apps/notes/lib/AppInfo/Application.php")
|
||||||
|
'';
|
||||||
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue