Files
process-compose-wrapper/lib.nix

197 lines
5.8 KiB
Nix

{ pkgs }:
let
inherit (pkgs) lib;
runtime = ".compose";
in
{
mkWrapper =
{
config,
name,
enableTui ? false,
modules ? [ ],
}:
let
merged_config = lib.foldl' (acc: elem: lib.recursiveUpdate acc elem) config modules;
# checks = lib.concatStringsSep "\n" (
# lib.concatMap (
# attrs:
# lib.mapAttrsToList (k: v: ''
# echo "Running ${k}"
# ${v}/bin/check
# echo "Passed ${k}"
# '') attrs.checks
# ) modules
# );
removeNullAndEmptyAttrs =
attrs:
let
f = lib.filterAttrsRecursive (key: value: value != null && value != { });
in
# filterAttrsRecursive doesn't delete the *resulting* empty attrs, so we must
# evaluate it again and to get rid of it.
lib.pipe attrs [
f
f
];
toPCJson =
name: attrs:
pkgs.writeTextFile {
name = "process-compose-${name}.json";
text = builtins.toJSON attrs;
};
configFile = toPCJson name (
removeNullAndEmptyAttrs (
merged_config
// {
is_tui_disabled = !enableTui;
}
)
);
in
# {
# inherit configFile merged_config;
# };
pkgs.writeShellApplication {
inherit name;
text = ''
PC_CONFIG_FILES=${configFile} RUNTIME_PATH=$(pwd)/${runtime} ${pkgs.process-compose}/bin/process-compose "$@"
'';
};
mkPostgres =
{
name,
default_config ? true,
config ? { },
extra_config ? '''',
package ? pkgs.postgresql,
port ? 5432,
listen_addresses ? "localhost",
initialDatabases ? [ ],
...
}:
let
merged_config =
(
if default_config then
{
listen_addresses = "localhost";
port = 5432;
shared_buffers = "128MB";
work_mem = "4MB";
logging_collector = false;
}
else
{ }
)
// config
// {
unix_socket_directories = ".";
inherit port listen_addresses;
};
toStr =
value:
if true == value then
"yes"
else if false == value then
"no"
else if lib.isString value then
"'${lib.replaceStrings [ "'" ] [ "''" ] value}'"
else
builtins.toString value;
configFile = pkgs.writeTextFile {
name = "postgresql.conf";
text = lib.concatStringsSep "\n" (
lib.mapAttrsToList (n: v: "${n} = ${toStr v}") (
lib.filterAttrs (lib.const (x: x != null)) merged_config
)
);
};
setupInitialDatabases =
if initialDatabases != [ ] then
(lib.concatMapStrings (db: ''
echo "Checking presence of database ${db.name}"
dbAlreadyExists="$(echo "SELECT 1 AS result FROM pg_database WHERE datname='${db.name}';" | psql --dbname postgres | ${pkgs.gnugrep}/bin/grep -c 'exists = "1"' || true)"
echo "$dbAlreadyExists"
if [ 1 -ne "$dbAlreadyExists" ]; then
echo "Creating database ${db.name}"
echo 'CREATE DATABASE "${db.name}";' | psql --dbname postgres
${lib.optionalString (db.user != null && db.password != null) ''
echo "Creating user ${db.user}"
psql --dbname postgres <<'EOF'
DO $$
BEGIN
CREATE ROLE "${db.user}" WITH LOGIN PASSWORD '${db.password}';
EXCEPTION WHEN duplicate_object THEN RAISE NOTICE '%, skipping', SQLERRM USING ERRCODE = SQLSTATE;
END
$$;
GRANT ALL PRIVILEGES ON DATABASE "${db.name}" TO "${db.user}";
\c ${db.name}
GRANT ALL PRIVILEGES ON SCHEMA public TO "${db.user}";
EOF
''}
else
echo "Database ${db.name} already exists"
fi
'') initialDatabases)
else
"";
setupScript = pkgs.writeShellApplication {
name = "setup-postgres";
runtimeInputs = [
package
pkgs.coreutils
];
text = ''
POSTGRES_RUN_INITIAL_SCRIPT="false"
if [[ ! -d "$PGDATA" ]]; then
initdb --no-instructions
POSTGRES_RUN_INITIAL_SCRIPT="true"
echo
echo "PostgreSQL initdb process completed"
echo
fi
cp ${configFile} "$PGDATA"/postgresql.conf
if [[ "$POSTGRES_RUN_INITIAL_SCRIPT" == "true" ]]; then
echo
echo "PostgreSQL is setting up the initial database"
echo
pg_ctl -w start -o "-c listen_addresses= -p ${builtins.toString port}"
${setupInitialDatabases}
pg_ctl -m fast -w stop
else
echo
echo "Database directory exists. Skipping initialization"
echo
fi
unset POSTGRES_RUN_INITIAL_SCRIPT
'';
};
script = pkgs.writeShellApplication {
name = "run-postgres";
text = ''
set -euo pipefail
PGDATA=$RUNTIME_PATH/${name}
PGHOST=$RUNTIME_PATH/${name}
PGPORT=${builtins.toString port}
echo "Starting postgres with PGDATA=''${PGDATA} PGHOST=''${PGHOST} PGPORT=''${PGPORT}"
export PGDATA PGHOST PGPORT
${setupScript}/bin/setup-postgres
${package}/bin/postgres
'';
};
in
# configFileCheck = pkgs.runCommand {} ''
# ${package}/bin/postgres -D${configFile} -C config_file
# touch $out
# '';
{
processes."${name}" = {
command = "${script}/bin/run-postgres";
};
};
}