Commit 63331d51 authored by Jérome Perrin's avatar Jérome Perrin

Fix restoring Metabase backups

See merge request nexedi/slapos!1383
parents e8faa79f 9b6a294a
[instance-profile] [instance-profile]
filename = instance.cfg.in filename = instance.cfg.in
md5sum = 0e74c862401f266111552b7a3611f7bf md5sum = 685e7b371768f6977896d7214fd379f1
...@@ -130,7 +130,7 @@ recipe = slapos.cookbook:generate.password ...@@ -130,7 +130,7 @@ recipe = slapos.cookbook:generate.password
[postgresql] [postgresql]
recipe = slapos.cookbook:postgres recipe = slapos.cookbook:postgres
bin = ${postgresql10:location}/bin/ bin = ${postgresql10:location}/bin
services = $${directory:service} services = $${directory:service}
dbname = metabase_db dbname = metabase_db
superuser = metabase-psql superuser = metabase-psql
...@@ -190,7 +190,16 @@ wrapper-path = $${directory:bin}/$${:_buildout_section_name_} ...@@ -190,7 +190,16 @@ wrapper-path = $${directory:bin}/$${:_buildout_section_name_}
command-line = command-line =
sh -e -c "\ sh -e -c "\
echo 'This will replace current database with latest backup. Hit Ctrl+C to cancel'; echo 'This will replace current database with latest backup. Hit Ctrl+C to cancel';
sleep 30; sleep 10;
$${postgresql:bin}/dropdb \
-h $${postgresql:pgdata-directory} \
-U $${postgresql:superuser} \
--if-exists \
$${postgresql:dbname};
$${postgresql:bin}/createdb \
-h $${postgresql:pgdata-directory} \
-U $${postgresql:superuser} \
$${postgresql:dbname};
$${postgresql:bin}/pg_restore \ $${postgresql:bin}/pg_restore \
--exit-on-error \ --exit-on-error \
-h $${postgresql:pgdata-directory} \ -h $${postgresql:pgdata-directory} \
......
...@@ -25,23 +25,32 @@ ...@@ -25,23 +25,32 @@
# #
############################################################################## ##############################################################################
import contextlib
import os import os
import json import json
from urllib import parse from urllib import parse
import shutil
import subprocess
import time
import requests import requests
from slapos.testing.testcase import makeModuleSetUpAndTestCaseClass from slapos.testing.testcase import makeModuleSetUpAndTestCaseClass
from slapos.testing.utils import CrontabMixin
setUpModule, MetabaseTestCase = makeModuleSetUpAndTestCaseClass( setUpModule, BaseTestCase = makeModuleSetUpAndTestCaseClass(
os.path.abspath( os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', 'software.cfg'))) os.path.join(os.path.dirname(__file__), '..', 'software.cfg')))
class TestMetabaseSetup(MetabaseTestCase): class MetabaseTestCase(BaseTestCase):
__partition_reference__ = 'S' # postgresql use a socket in data dir __partition_reference__ = 'S' # postgresql use a socket in data dir
# instance can take time, /api/session/properties timeout at the beginning. # instance can take time, /api/session/properties timeout at the beginning.
instance_max_retry = 30 instance_max_retry = 30
class TestMetabaseSetup(MetabaseTestCase):
def test_setup(self): def test_setup(self):
url = self.computer_partition.getConnectionParameterDict()['url'] url = self.computer_partition.getConnectionParameterDict()['url']
resp = requests.get(parse.urljoin(url, '/setup'), verify=False) resp = requests.get(parse.urljoin(url, '/setup'), verify=False)
...@@ -94,3 +103,62 @@ class TestMetabaseSetup(MetabaseTestCase): ...@@ -94,3 +103,62 @@ class TestMetabaseSetup(MetabaseTestCase):
"password": password "password": password
}).json() }).json()
self.assertTrue(session.get('id')) self.assertTrue(session.get('id'))
class TestMetabaseBackup(MetabaseTestCase, CrontabMixin):
def test_backup(self):
self._executeCrontabAtDate('postgresql-backup-crontab-entry', '2100-01-01')
with open(
os.path.join(
self.computer_partition_root_path, 'srv', 'backup', 'backup.pg_dump'),
'rb') as f:
self.assertIn(b'CREATE DATABASE metabase_db', f.read())
def test_restore(self):
# restore a "known good" backup and check we can login with the
# user from the backup.
url = self.computer_partition.getConnectionParameterDict()['url']
shutil.copyfile(
os.path.join(os.path.dirname(__file__), 'testdata', 'backup.pg_dump'),
os.path.join(
self.computer_partition_root_path, 'srv', 'backup', 'backup.pg_dump')
)
with self.slap.instance_supervisor_rpc as supervisor:
# stop metabase, so that it does not interfere with restoring the backup
info, = [i for i in
supervisor.getAllProcessInfo() if 'metabase-instance' in i['name']]
metabase_process_name = f"{info['group']}:{info['name']}"
supervisor.stopProcess(metabase_process_name)
# restart postgres, to terminate all current connections
info, = [i for i in
supervisor.getAllProcessInfo() if 'postgres' in i['name']]
postresql_process_name = f"{info['group']}:{info['name']}"
supervisor.stopProcess(postresql_process_name)
supervisor.startProcess(postresql_process_name)
subprocess.check_output(
os.path.join(
self.computer_partition_root_path, 'bin', 'postgresql-restore-backup'))
with self.slap.instance_supervisor_rpc as supervisor:
supervisor.startProcess(metabase_process_name)
for _ in range(30):
with contextlib.suppress(requests.exceptions.RequestException):
time.sleep(1)
resp = requests.post(
parse.urljoin(url, '/api/session'),
verify=False,
json={
"username": "youlooknicetoday@email.com",
"password": "passwordformbackup123"
}, timeout=5)
if resp.ok:
session = resp.json()
break
else:
resp.raise_for_status()
self.assertTrue(session.get('id'))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment