-
Notifications
You must be signed in to change notification settings - Fork 63
Expand file tree
/
Copy pathsetup-script.nix
More file actions
143 lines (134 loc) · 4.62 KB
/
setup-script.nix
File metadata and controls
143 lines (134 loc) · 4.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
{ config, pkgs, lib }:
let
setupInitialSchema = dbName: schema: ''
echo "Applying database schema on ${dbName}"
if [ -f "${schema}" ]
then
echo "Running file ${schema}"
awk 'NF' "${schema}" | psql_with_args -d ${dbName}
elif [ -d "${schema}" ]
then
# Read sql files in version order. Apply one file
# at a time to handle files where the last statement
# doesn't end in a ;.
find "${schema}"/*.sql | while read -r f ; do
echo "Applying sql file: $f"
awk 'NF' "$f" | psql_with_args -d ${dbName}
done
else
echo "ERROR: Could not determine how to apply schema with ${schema}"
exit 1
fi
'';
setupInitialDatabases =
if config.initialDatabases != [ ] then
(lib.concatMapStrings
(database: ''
echo "Checking presence of database: ${database.name}"
# Create initial databases
dbAlreadyExists=$(
echo "SELECT 1 as exists FROM pg_database WHERE datname = '${database.name}';" | \
psql_with_args -d postgres | \
grep -c 'exists = "1"' || true
)
echo "$dbAlreadyExists"
if [ 1 -ne "$dbAlreadyExists" ]; then
echo "Creating database: ${database.name}"
echo 'create database "${database.name}";' | psql_with_args -d postgres
${lib.optionalString (database.schemas != null)
(lib.concatMapStrings (schema: setupInitialSchema (database.name) schema) database.schemas)}
fi
'')
config.initialDatabases)
else
lib.optionalString config.createDatabase ''
echo "CREATE DATABASE ''${USER:-$(id -nu)};" | psql_with_args -d postgres '';
runInitialScript =
let
scriptCmd = sqlScript: ''
echo "${sqlScript}" | psql_with_args -d postgres
'';
in
{
before = with config.initialScript;
lib.optionalString (before != null) (scriptCmd before);
after = with config.initialScript;
lib.optionalString (after != null) (scriptCmd after);
};
toStr = value:
if true == value then
"yes"
else if false == value then
"no"
else if lib.isString value then
"'${lib.replaceStrings [ "'" ] [ "''" ] value}'"
else
toString value;
configFile = pkgs.writeText "postgresql.conf" (lib.concatStringsSep "\n"
(lib.mapAttrsToList (n: v: "${n} = ${toStr v}") (config.defaultSettings // config.settings)));
initdbArgs =
config.initdbArgs
++ (lib.optionals (config.superuser != null) [ "-U" config.superuser ])
++ [ "-D" config.dataDir ];
in
(pkgs.writeShellApplication {
name = "setup-postgres";
runtimeInputs = with pkgs; [ config.package coreutils gnugrep gawk ];
text = ''
set -x
# Execute the `psql` command with default arguments
function psql_with_args() {
psql ${lib.optionalString (config.superuser != null) "-U ${config.superuser}"} -v "ON_ERROR_STOP=1" "$@"
}
# Setup postgres ENVs
export PGDATA="${config.dataDir}"
export PGPORT="${toString config.port}"
POSTGRES_RUN_INITIAL_SCRIPT="false"
if [[ ! -d "$PGDATA" ]]; then
initdb ${lib.concatStringsSep " " initdbArgs}
POSTGRES_RUN_INITIAL_SCRIPT="true"
echo
echo "PostgreSQL initdb process complete."
echo
fi
# Setup config
echo "Setting up postgresql.conf"
cp ${configFile} "$PGDATA/postgresql.conf"
# Create socketDir if it doesn't exist and it is not empty
${lib.optionalString (config.socketDir != "") ''
if [ ! -d "${config.socketDir}" ]; then
echo "Creating socket directory"
mkdir -p "${config.socketDir}"
fi
''}
if [[ "$POSTGRES_RUN_INITIAL_SCRIPT" = "true" ]]; then
echo
echo "PostgreSQL is setting up the initial database."
echo
${ if config.socketDir != "" then ''
PGHOST=$(mktemp -d "$(readlink -f "${config.socketDir}")/pg-init-XXXXXX")
'' else ''
PGHOST=$(mktemp -d /tmp/pg-init-XXXXXX)
''
}
export PGHOST
function remove_tmp_pg_init_sock_dir() {
if [[ -d "$1" ]]; then
rm -rf "$1"
fi
}
trap 'remove_tmp_pg_init_sock_dir "$PGHOST"' EXIT
pg_ctl -D "$PGDATA" -w start -o "-c unix_socket_directories=$PGHOST -c listen_addresses= -p ${toString config.port}"
${runInitialScript.before}
${setupInitialDatabases}
${runInitialScript.after}
pg_ctl -D "$PGDATA" -m fast -w stop
remove_tmp_pg_init_sock_dir "$PGHOST"
else
echo
echo "PostgreSQL database directory appears to contain a database; Skipping initialization"
echo
fi
unset POSTGRES_RUN_INITIAL_SCRIPT
'';
})