nixos/mattermost: add preferNixConfig option and tests

One use case for Mattermost configuration is doing a "mostly
mutable" configuration where NixOS module options take priority
over Mattermost's config JSON.

Add a preferNixConfig option that prefers configured Nix options
over what's configured in Mattermost config if mutableConfig is set.

Remove the reliance on readFile (it's flake incompatible) and use
jq instead.

Merge Mattermost configs together on Mattermost startup, depending
on configured module options.

Write tests for mutable, mostly mutable, and immutable configurations.
This commit is contained in:
Morgan Jones 2021-04-11 19:29:29 -06:00 committed by Raphael Megzari
parent f5901b85d1
commit 174b340406
3 changed files with 143 additions and 16 deletions

View File

@ -6,23 +6,18 @@ let
cfg = config.services.mattermost; cfg = config.services.mattermost;
defaultConfig = builtins.fromJSON (builtins.replaceStrings [ "\\u0026" ] [ "&" ]
(readFile "${pkgs.mattermost}/config/config.json")
);
database = "postgres://${cfg.localDatabaseUser}:${cfg.localDatabasePassword}@localhost:5432/${cfg.localDatabaseName}?sslmode=disable&connect_timeout=10"; database = "postgres://${cfg.localDatabaseUser}:${cfg.localDatabasePassword}@localhost:5432/${cfg.localDatabaseName}?sslmode=disable&connect_timeout=10";
mattermostConf = foldl recursiveUpdate defaultConfig mattermostConf = recursiveUpdate
[ { ServiceSettings.SiteURL = cfg.siteUrl; { ServiceSettings.SiteURL = cfg.siteUrl;
ServiceSettings.ListenAddress = cfg.listenAddress; ServiceSettings.ListenAddress = cfg.listenAddress;
TeamSettings.SiteName = cfg.siteName; TeamSettings.SiteName = cfg.siteName;
SqlSettings.DriverName = "postgres"; SqlSettings.DriverName = "postgres";
SqlSettings.DataSource = database; SqlSettings.DataSource = database;
} }
cfg.extraConfig cfg.extraConfig;
];
mattermostConfJSON = pkgs.writeText "mattermost-config-raw.json" (builtins.toJSON mattermostConf); mattermostConfJSON = pkgs.writeText "mattermost-config.json" (builtins.toJSON mattermostConf);
in in
@ -77,6 +72,16 @@ in
''; '';
}; };
preferNixConfig = mkOption {
type = types.bool;
default = false;
description = ''
If both mutableConfig and this option are set, the Nix configuration
will take precedence over any settings configured in the server
console.
'';
};
extraConfig = mkOption { extraConfig = mkOption {
type = types.attrs; type = types.attrs;
default = { }; default = { };
@ -180,14 +185,19 @@ in
ln -sf ${pkgs.mattermost}/{bin,fonts,i18n,templates,client} ${cfg.statePath} ln -sf ${pkgs.mattermost}/{bin,fonts,i18n,templates,client} ${cfg.statePath}
'' + lib.optionalString (!cfg.mutableConfig) '' '' + lib.optionalString (!cfg.mutableConfig) ''
rm -f ${cfg.statePath}/config/config.json rm -f ${cfg.statePath}/config/config.json
cp ${mattermostConfJSON} ${cfg.statePath}/config/config.json ${pkgs.jq}/bin/jq -s '.[0] * .[1]' ${pkgs.mattermost}/config/config.json ${mattermostConfJSON} > ${cfg.statePath}/config/config.json
${pkgs.mattermost}/bin/mattermost config migrate ${cfg.statePath}/config/config.json ${database} ${pkgs.mattermost}/bin/mattermost config migrate ${cfg.statePath}/config/config.json ${database}
'' + lib.optionalString cfg.mutableConfig '' '' + lib.optionalString cfg.mutableConfig ''
if ! test -e "${cfg.statePath}/config/.initial-created"; then if ! test -e "${cfg.statePath}/config/.initial-created"; then
rm -f ${cfg.statePath}/config/config.json rm -f ${cfg.statePath}/config/config.json
cp ${mattermostConfJSON} ${cfg.statePath}/config/config.json ${pkgs.jq}/bin/jq -s '.[0] * .[1]' ${pkgs.mattermost}/config/config.json ${mattermostConfJSON} > ${cfg.statePath}/config/config.json
touch ${cfg.statePath}/config/.initial-created touch ${cfg.statePath}/config/.initial-created
fi fi
'' + lib.optionalString (cfg.mutableConfig && cfg.preferNixConfig) ''
newConfig="$(${pkgs.jq}/bin/jq -s '.[0] * .[1]' ${cfg.statePath}/config/config.json ${mattermostConfJSON})"
rm -f ${cfg.statePath}/config/config.json
echo "$newConfig" > ${cfg.statePath}/config/config.json
'' + lib.optionalString cfg.localDatabaseCreate '' '' + lib.optionalString cfg.localDatabaseCreate ''
if ! test -e "${cfg.statePath}/.db-created"; then if ! test -e "${cfg.statePath}/.db-created"; then
${pkgs.sudo}/bin/sudo -u ${config.services.postgresql.superUser} \ ${pkgs.sudo}/bin/sudo -u ${config.services.postgresql.superUser} \

View File

@ -261,6 +261,7 @@ in
matomo = handleTest ./matomo.nix {}; matomo = handleTest ./matomo.nix {};
matrix-appservice-irc = handleTest ./matrix-appservice-irc.nix {}; matrix-appservice-irc = handleTest ./matrix-appservice-irc.nix {};
matrix-synapse = handleTest ./matrix-synapse.nix {}; matrix-synapse = handleTest ./matrix-synapse.nix {};
mattermost = handleTest ./mattermost.nix {};
mediawiki = handleTest ./mediawiki.nix {}; mediawiki = handleTest ./mediawiki.nix {};
meilisearch = handleTest ./meilisearch.nix {}; meilisearch = handleTest ./meilisearch.nix {};
memcached = handleTest ./memcached.nix {}; memcached = handleTest ./memcached.nix {};

116
nixos/tests/mattermost.nix Normal file
View File

@ -0,0 +1,116 @@
import ./make-test-python.nix ({ pkgs, lib, ... }:
let
host = "smoke.test";
port = "8065";
url = "http://${host}:${port}";
siteName = "NixOS Smoke Tests, Inc.";
makeMattermost = mattermostConfig:
{ config, ... }: {
environment.systemPackages = [
pkgs.mattermost
pkgs.curl
pkgs.jq
];
networking.hosts = {
"127.0.0.1" = [ host ];
};
services.mattermost = lib.recursiveUpdate {
enable = true;
inherit siteName;
listenAddress = "0.0.0.0:${port}";
siteUrl = url;
extraConfig = {
SupportSettings.AboutLink = "https://nixos.org";
};
} mattermostConfig;
};
in
{
name = "mattermost";
nodes = {
mutable = makeMattermost {
mutableConfig = true;
extraConfig.SupportSettings.HelpLink = "https://search.nixos.org";
};
mostlyMutable = makeMattermost {
mutableConfig = true;
preferNixConfig = true;
};
immutable = makeMattermost {
mutableConfig = false;
extraConfig.SupportSettings.HelpLink = "https://search.nixos.org";
};
};
testScript = let
expectConfig = jqExpression: pkgs.writeShellScript "expect-config" ''
set -euo pipefail
echo "Expecting config to match: "${lib.escapeShellArg jqExpression} >&2
curl ${lib.escapeShellArg url} >/dev/null
config="$(curl ${lib.escapeShellArg "${url}/api/v4/config/client?format=old"})"
echo "Config: $(echo "$config" | ${pkgs.jq}/bin/jq)" >&2
[[ "$(echo "$config" | ${pkgs.jq}/bin/jq -r ${lib.escapeShellArg ".SiteName == $siteName and .Version == ($mattermostName / $sep)[-1] and (${jqExpression})"} --arg siteName ${lib.escapeShellArg siteName} --arg mattermostName ${lib.escapeShellArg pkgs.mattermost.name} --arg sep '-')" = "true" ]]
'';
setConfig = jqExpression: pkgs.writeShellScript "set-config" ''
set -euo pipefail
mattermostConfig=/var/lib/mattermost/config/config.json
newConfig="$(${pkgs.jq}/bin/jq -r ${lib.escapeShellArg jqExpression} $mattermostConfig)"
rm -f $mattermostConfig
echo "$newConfig" > "$mattermostConfig"
'';
in
''
start_all()
## Mutable node tests ##
mutable.wait_for_unit("mattermost.service")
mutable.wait_for_open_port(8065)
# Get the initial config
mutable.succeed("${expectConfig ''.AboutLink == "https://nixos.org" and .HelpLink == "https://search.nixos.org"''}")
# Edit the config
mutable.succeed("${setConfig ''.SupportSettings.AboutLink = "https://mattermost.com"''}")
mutable.succeed("${setConfig ''.SupportSettings.HelpLink = "https://nixos.org/nixos/manual"''}")
mutable.systemctl("restart mattermost.service")
mutable.wait_for_open_port(8065)
# AboutLink and HelpLink should be changed
mutable.succeed("${expectConfig ''.AboutLink == "https://mattermost.com" and .HelpLink == "https://nixos.org/nixos/manual"''}")
## Mostly mutable node tests ##
mostlyMutable.wait_for_unit("mattermost.service")
mostlyMutable.wait_for_open_port(8065)
# Get the initial config
mostlyMutable.succeed("${expectConfig ''.AboutLink == "https://nixos.org"''}")
# Edit the config
mostlyMutable.succeed("${setConfig ''.SupportSettings.AboutLink = "https://mattermost.com"''}")
mostlyMutable.succeed("${setConfig ''.SupportSettings.HelpLink = "https://nixos.org/nixos/manual"''}")
mostlyMutable.systemctl("restart mattermost.service")
mostlyMutable.wait_for_open_port(8065)
# AboutLink should be overridden by NixOS configuration; HelpLink should be what we set above
mostlyMutable.succeed("${expectConfig ''.AboutLink == "https://nixos.org" and .HelpLink == "https://nixos.org/nixos/manual"''}")
## Immutable node tests ##
immutable.wait_for_unit("mattermost.service")
immutable.wait_for_open_port(8065)
# Get the initial config
immutable.succeed("${expectConfig ''.AboutLink == "https://nixos.org" and .HelpLink == "https://search.nixos.org"''}")
# Edit the config
immutable.succeed("${setConfig ''.SupportSettings.AboutLink = "https://mattermost.com"''}")
immutable.succeed("${setConfig ''.SupportSettings.HelpLink = "https://nixos.org/nixos/manual"''}")
immutable.systemctl("restart mattermost.service")
immutable.wait_for_open_port(8065)
# Our edits should be ignored on restart
immutable.succeed("${expectConfig ''.AboutLink == "https://nixos.org" and .HelpLink == "https://search.nixos.org"''}")
'';
})