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

Fix restoring Metabase backups

See merge request !1383
parents e8faa79f 9b6a294a
[instance-profile]
filename = instance.cfg.in
md5sum = 0e74c862401f266111552b7a3611f7bf
md5sum = 685e7b371768f6977896d7214fd379f1
......@@ -130,7 +130,7 @@ recipe = slapos.cookbook:generate.password
[postgresql]
recipe = slapos.cookbook:postgres
bin = ${postgresql10:location}/bin/
bin = ${postgresql10:location}/bin
services = $${directory:service}
dbname = metabase_db
superuser = metabase-psql
......@@ -190,7 +190,16 @@ wrapper-path = $${directory:bin}/$${:_buildout_section_name_}
command-line =
sh -e -c "\
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 \
--exit-on-error \
-h $${postgresql:pgdata-directory} \
......
......@@ -25,23 +25,32 @@
#
##############################################################################
import contextlib
import os
import json
from urllib import parse
import shutil
import subprocess
import time
import requests
from slapos.testing.testcase import makeModuleSetUpAndTestCaseClass
from slapos.testing.utils import CrontabMixin
setUpModule, MetabaseTestCase = makeModuleSetUpAndTestCaseClass(
setUpModule, BaseTestCase = makeModuleSetUpAndTestCaseClass(
os.path.abspath(
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
# instance can take time, /api/session/properties timeout at the beginning.
instance_max_retry = 30
class TestMetabaseSetup(MetabaseTestCase):
def test_setup(self):
url = self.computer_partition.getConnectionParameterDict()['url']
resp = requests.get(parse.urljoin(url, '/setup'), verify=False)
......@@ -94,3 +103,62 @@ class TestMetabaseSetup(MetabaseTestCase):
"password": password
}).json()
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