Skip to content

Commit a30b87a

Browse files
author
Bolyki György
committed
fix(nix): support configured database credentials in maintenance tools
1 parent 29b1711 commit a30b87a

7 files changed

Lines changed: 415 additions & 35 deletions

File tree

lib/teslamate/log.ex

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,13 @@ defmodule TeslaMate.Log do
240240
|> Repo.insert()
241241
end
242242

243+
def delete_drive(id) when is_integer(id) do
244+
case Repo.get(Drive, id) do
245+
nil -> :not_found
246+
drive -> delete(drive)
247+
end
248+
end
249+
243250
def close_drive(%Drive{id: id} = drive, opts \\ []) do
244251
drive = Repo.preload(drive, [:car])
245252

@@ -407,6 +414,13 @@ defmodule TeslaMate.Log do
407414
|> Repo.update()
408415
end
409416

417+
def delete_charging_process(id) when is_integer(id) do
418+
case Repo.get(ChargingProcess, id) do
419+
nil -> :not_found
420+
charging_process -> delete(charging_process)
421+
end
422+
end
423+
410424
def start_charging_process(%Car{id: id}, %{latitude: _, longitude: _} = attrs, opts \\ []) do
411425
lookup_address = Keyword.get(opts, :lookup_address, true)
412426
position = Map.put(attrs, :car_id, id)
@@ -708,4 +722,11 @@ defmodule TeslaMate.Log do
708722
|> Update.changeset(%{start_date: date, end_date: date, version: version})
709723
|> Repo.insert()
710724
end
725+
726+
defp delete(struct) do
727+
case Repo.delete(struct) do
728+
{:ok, _struct} -> :ok
729+
{:error, _changeset} = error -> error
730+
end
731+
end
711732
end

nix/backup_and_restore.nix

Lines changed: 96 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,118 @@
11
{
22
stdenv,
33
lib,
4-
pkgs,
4+
coreutils,
5+
gnused,
6+
postgresql,
7+
systemd,
58
writeShellScript,
69
databaseUser,
710
databaseName,
11+
databaseHost,
12+
databasePort,
13+
environmentFilePath,
814
...
915
}:
1016
let
17+
pgDump = lib.getExe' postgresql "pg_dump";
18+
psql = lib.getExe' postgresql "psql";
19+
sed = lib.getExe gnused;
20+
systemctl = lib.getExe' systemd "systemctl";
21+
tail = lib.getExe' coreutils "tail";
22+
databaseArgs = lib.escapeShellArgs [
23+
"--host=${databaseHost}"
24+
"--port=${toString databasePort}"
25+
"--username=${databaseUser}"
26+
"--dbname=${databaseName}"
27+
"--no-password"
28+
];
29+
loadDatabasePassword = ''
30+
load_database_password() {
31+
if [ ! -r ${lib.escapeShellArg environmentFilePath} ]; then
32+
printf '%s\n' ${lib.escapeShellArg "Environment file ${environmentFilePath} not found or not readable."} >&2
33+
return 1
34+
fi
35+
36+
database_password="$(
37+
${sed} -n 's/^DATABASE_PASS=//p' ${lib.escapeShellArg environmentFilePath} |
38+
${tail} -n 1
39+
)"
40+
41+
case "$database_password" in
42+
\"*\")
43+
database_password="''${database_password#\"}"
44+
database_password="''${database_password%\"}"
45+
;;
46+
esac
47+
48+
if [ -z "$database_password" ]; then
49+
printf '%s\n' ${lib.escapeShellArg "DATABASE_PASS must be set in ${environmentFilePath} (services.teslamate.secretsFile)."} >&2
50+
return 1
51+
fi
52+
}
53+
54+
run_with_database_password() {
55+
PGPASSWORD="$database_password" "$@"
56+
}
57+
'';
1158
backup = writeShellScript "teslamate-backup" ''
1259
set -euo pipefail
13-
: ''${1?' Please specify a file to save backup'}
14-
sudo -u teslamate pg_dump -U ${databaseUser} ${databaseName} > "$1"
60+
: "''${1:?'Please specify a file to save backup'}"
61+
62+
${loadDatabasePassword}
63+
load_database_password
64+
run_with_database_password ${pgDump} ${databaseArgs} > "$1"
1565
'';
1666
restore = writeShellScript "teslamate-restore" ''
1767
set -euo pipefail
18-
: ''${1?' Please specify a file to restore from'}
68+
: "''${1:?'Please specify a file to restore from'}"
69+
70+
if [ ! -f "$1" ]; then
71+
printf 'Restore file %q does not exist, is not a regular file, or is not readable.\n' "$1" >&2
72+
exit 1
73+
fi
74+
if ! exec 3< "$1"; then
75+
printf 'Restore file %q does not exist, is not a regular file, or is not readable.\n' "$1" >&2
76+
exit 1
77+
fi
1978
20-
# Stop the teslamate service to avoid write conflicts
21-
systemctl stop teslamate.service
79+
${loadDatabasePassword}
80+
load_database_password
81+
82+
restart_teslamate() {
83+
original_status="$?"
84+
trap - EXIT
85+
86+
if ${systemctl} start teslamate.service 3<&-; then
87+
restart_status=0
88+
else
89+
restart_status="$?"
90+
fi
91+
92+
if [ "$original_status" -ne 0 ]; then
93+
exit "$original_status"
94+
fi
95+
96+
exit "$restart_status"
97+
}
98+
99+
# Restart TeslaMate on every exit after this point. If reset or restore
100+
# fails, preserve that original status even when restarting also fails.
101+
trap restart_teslamate EXIT
102+
103+
${systemctl} stop teslamate.service 3<&-
22104
23105
# Drop existing data and reinitialize
24-
sudo -u teslamate psql -U ${databaseUser} -d ${databaseName} << .
25-
DROP SCHEMA IF EXISTS public cascade;
26-
DROP SCHEMA IF EXISTS private CASCADE;
27-
CREATE SCHEMA public;
28-
CREATE EXTENSION cube WITH SCHEMA public;
29-
CREATE EXTENSION earthdistance WITH SCHEMA public;
30-
.
106+
run_with_database_password ${psql} ${databaseArgs} --set=ON_ERROR_STOP=1 <<'SQL'
107+
DROP SCHEMA IF EXISTS public CASCADE;
108+
DROP SCHEMA IF EXISTS private CASCADE;
109+
CREATE SCHEMA public;
110+
CREATE EXTENSION cube WITH SCHEMA public;
111+
CREATE EXTENSION earthdistance WITH SCHEMA public;
112+
SQL
31113
32114
# Restore
33-
sudo -u teslamate psql -U ${databaseUser} -d ${databaseName} < "$1"
34-
35-
# Restart the teslamate container
36-
systemctl start teslamate.service
115+
run_with_database_password ${psql} ${databaseArgs} --set=ON_ERROR_STOP=1 <&3
37116
'';
38117
in
39118
stdenv.mkDerivation {

0 commit comments

Comments
 (0)