Skip to content

Commit f051755

Browse files
committed
draft start for the plugin Testgres.probackup
1 parent 934f540 commit f051755

File tree

4 files changed

+145
-34
lines changed

4 files changed

+145
-34
lines changed

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from distutils.core import setup
77

88
# Basic dependencies
9-
install_requires = ["pg8000", "port-for>=0.4", "six>=1.9.0", "psutil"]
9+
install_requires = ["pg8000", "port-for>=0.4", "six>=1.9.0", "psutil", "tox", "termcolor"]
1010

1111
# Add compatibility enum class
1212
if sys.version_info < (3, 4):
@@ -21,7 +21,7 @@
2121
readme = f.read()
2222

2323
setup(
24-
version='1.8.5',
24+
version='1.9.0',
2525
name='testgres',
2626
packages=['testgres'],
2727
description='Testing utility for PostgreSQL and its extensions',

testgres/node.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,41 @@ def promote(self, dbname=None, username=None):
772772

773773
return self
774774

775+
def slow_start(self, replica=False):
776+
777+
# wait for https://github.com/postgrespro/testgres/pull/50
778+
# self.start()
779+
# self.poll_query_until(
780+
# "postgres",
781+
# "SELECT not pg_is_in_recovery()",
782+
# suppress={testgres.NodeConnection})
783+
784+
if replica:
785+
query = 'SELECT pg_is_in_recovery()'
786+
else:
787+
query = 'SELECT not pg_is_in_recovery()'
788+
789+
self.start()
790+
while True:
791+
try:
792+
output = self.safe_psql('template1', query).decode("utf-8").rstrip()
793+
794+
if output == 't':
795+
break
796+
797+
except testgres.QueryException as e:
798+
if 'database system is starting up' in e.message:
799+
pass
800+
elif 'FATAL: the database system is not accepting connections' in e.message:
801+
pass
802+
elif replica and 'Hot standby mode is disabled' in e.message:
803+
raise e
804+
else:
805+
raise e
806+
807+
sleep(0.5)
808+
809+
775810
def pg_ctl(self, params):
776811
"""
777812
Invoke pg_ctl with params.

testgres/probackup.py

Lines changed: 99 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,23 @@
1212
import re
1313
import json
1414

15+
import errno
16+
import unittest
17+
from termcolor import colored
18+
19+
1520
from time import sleep
1621
from sys import exit, argv, version_info
1722

1823
#from testgres.utils import get_pg_edition
1924
from testgres.utils import is_enterprise, is_nls_enabled
2025

21-
class ProbackupException(Exception):
26+
27+
# move to the settings.py with other global configurations
28+
TEST_DIR = 'tmp_dirs'
29+
30+
31+
class PGProbackupException(Exception):
2232
def __init__(self, message, cmd):
2333
self.message = message
2434
self.cmd = cmd
@@ -27,21 +37,60 @@ def __str__(self):
2737
return '\n ERROR: {0}\n CMD: {1}'.format(repr(self.message), self.cmd)
2838

2939

40+
class PGProbackupApp(object):
41+
IS_ENTERPRISE = False
42+
43+
settings = dict()
44+
host = 'localhost'
45+
tests_full_path = TEST_DIR # tmp_test_dirs
46+
47+
48+
#def __new__(self, *args, **kwargs):
49+
# pass
50+
51+
def __init__(
52+
self, tests_path='.', test_dir=TEST_DIR,
53+
*args, **kwargs):
54+
pass
3055

3156

32-
class ProbackupTest(object):
57+
class PGProbackupTestCaseMixin(unittest.TestCase):
58+
def setUp(self):
59+
pass
60+
61+
def tearDown(self):
62+
pass
63+
64+
65+
66+
class PGProbackupPackageCompTestCaseMixin(PGProbackupTestCaseMixin):
67+
current_version = None
68+
previous_version = None
69+
70+
def setUp(self):
71+
pass
72+
73+
def tearDown(self):
74+
pass
75+
76+
77+
78+
79+
class ProbackupTest(object):
3380
# Class attributes
3481
enterprise = is_enterprise()
3582
enable_nls = is_nls_enabled()
3683

3784
def __init__(self, *args, **kwargs):
3885
super(ProbackupTest, self).__init__(*args, **kwargs)
86+
87+
self.verbose = False
3988
if '-v' in argv or '--verbose' in argv:
4089
self.verbose = True
41-
else:
42-
self.verbose = False
90+
4391

4492
self.test_env = os.environ.copy()
93+
4594
envs_list = [
4695
'LANGUAGE',
4796
'LC_ALL',
@@ -75,28 +124,32 @@ def __init__(self, *args, **kwargs):
75124
self.archive_compress = 'ARCHIVE_COMPRESSION' in self.test_env and \
76125
self.test_env['ARCHIVE_COMPRESSION'] == 'ON'
77126

78-
try:
79-
testgres.configure_testgres(
80-
cache_initdb=False,
81-
cached_initdb_dir=False,
82-
cache_pg_config=False,
83-
node_cleanup_full=False)
84-
except:
85-
pass
86-
87-
self.helpers_path = os.path.dirname(os.path.realpath(__file__))
88-
self.dir_path = os.path.abspath(
89-
os.path.join(self.helpers_path, os.pardir)
90-
)
91-
self.tmp_path = os.path.abspath(
92-
os.path.join(self.dir_path, 'tmp_dirs')
93-
)
94-
try:
95-
os.makedirs(os.path.join(self.dir_path, 'tmp_dirs'))
96-
except:
97-
pass
98127

128+
testgres.configure_testgres(
129+
cache_initdb=False,
130+
cached_initdb_dir=False,
131+
cache_pg_config=False,
132+
node_cleanup_full=False)
133+
134+
135+
# Choose path for the tests artifacts
136+
self.tests_path =os.path.join(os.path.abspath('.'), TEST_DIR)
137+
try:
138+
os.makedirs(os.path.join(self.tests_path))
139+
log.info('Artefacts from the tests are stored in the direcotry: %s'%self.tests_path)
140+
except OSError as e:
141+
if e.errno == errno.EEXIST:
142+
pass
143+
else:
144+
# print(
145+
# colored('Please choose directory for the tests artefacts with 777 chmod. [%s]'%self.tests_path, 'red'))
146+
raise
147+
148+
149+
# XXX dont work with
99150
self.user = self.get_username()
151+
152+
100153
self.probackup_path = None
101154
if 'PGPROBACKUPBIN' in self.test_env:
102155
if (
@@ -108,6 +161,7 @@ def __init__(self, *args, **kwargs):
108161
if self.verbose:
109162
print('PGPROBACKUPBIN is not an executable file')
110163

164+
# XXX
111165
print('@@@', self.probackup_path)
112166

113167
if not self.probackup_path:
@@ -162,18 +216,22 @@ def __init__(self, *args, **kwargs):
162216
self.old_probackup_version = None
163217

164218
try:
219+
165220
self.probackup_version_output = subprocess.check_output(
166221
[self.probackup_path, "--version"],
167222
stderr=subprocess.STDOUT,
168223
).decode('utf-8')
224+
169225
except subprocess.CalledProcessError as e:
170-
raise ProbackupException(e.output.decode('utf-8'))
226+
raise PGProbackupException(e.output.decode('utf-8'))
171227

172228
if self.probackup_old_path:
229+
173230
old_probackup_version_output = subprocess.check_output(
174231
[self.probackup_old_path, "--version"],
175232
stderr=subprocess.STDOUT,
176233
).decode('utf-8')
234+
177235
self.old_probackup_version = re.search(
178236
r"\d+\.\d+\.\d+",
179237
subprocess.check_output(
@@ -224,19 +282,26 @@ def pg_config_version(self):
224282
# print('PGPROBACKUP_SSH_USER is not set')
225283
# exit(1)
226284

285+
286+
# XXX move to the node.PostgresNode
227287
def make_empty_node(
228288
self,
229289
base_dir=None):
230-
real_base_dir = os.path.join(self.tmp_path, base_dir)
290+
291+
real_base_dir = os.path.join(self.tests_path, base_dir)
231292
shutil.rmtree(real_base_dir, ignore_errors=True)
232293
os.makedirs(real_base_dir)
233294

234295
node = testgres.get_new_node('test', base_dir=real_base_dir)
296+
235297
# bound method slow_start() to 'node' class instance
236-
node.slow_start = slow_start.__get__(node)
298+
#node.slow_start = slow_start.__get__(node)
299+
237300
node.should_rm_dirs = True
238301
return node
239302

303+
304+
# XXX preconfigured Node for the pg_probackup app
240305
def make_simple_node(
241306
self,
242307
base_dir=None,
@@ -254,6 +319,8 @@ def make_simple_node(
254319
node.major_version_str = str(f.read().rstrip())
255320
node.major_version = float(node.major_version_str)
256321

322+
# XXX move it to the ProbackupTestCaseMixin class setUp
323+
257324
# Sane default parameters
258325
options = {}
259326
options['max_connections'] = 100
@@ -405,7 +472,7 @@ def get_md5_per_page_for_fork(self, file, size_in_pages):
405472

406473
size = size_in_pages
407474
for segment_number in range(nsegments):
408-
if size - 131072 > 0:
475+
if size - 131072 > 0: # XXX make global static config PARAM
409476
pages_per_segment[segment_number] = 131072
410477
else:
411478
pages_per_segment[segment_number] = size
@@ -427,7 +494,7 @@ def get_md5_per_page_for_fork(self, file, size_in_pages):
427494
for page in range(start_page, end_page):
428495
md5_per_page[page] = hashlib.md5(
429496
os.read(file_desc, 8192)).hexdigest()
430-
offset += 8192
497+
offset += 8192 # XXX make global static config PARAM
431498
os.lseek(file_desc, offset, 0)
432499
os.close(file_desc)
433500

@@ -683,7 +750,7 @@ def run_pb(self, command, asynchronous=False, gdb=False, old_binary=False, retur
683750
else:
684751
return self.output
685752
except subprocess.CalledProcessError as e:
686-
raise ProbackupException(e.output.decode('utf-8'), self.cmd)
753+
raise PGProbackupException(e.output.decode('utf-8'), self.cmd)
687754

688755
def run_binary(self, command, asynchronous=False, env=None):
689756

@@ -709,7 +776,7 @@ def run_binary(self, command, asynchronous=False, env=None):
709776
).decode('utf-8')
710777
return self.output
711778
except subprocess.CalledProcessError as e:
712-
raise ProbackupException(e.output.decode('utf-8'), command)
779+
raise PGProbackupException(e.output.decode('utf-8'), command)
713780

714781
def init_pb(self, backup_dir, options=[], old_binary=False):
715782

@@ -1455,7 +1522,7 @@ def del_test_dir(self, module_name, fname):
14551522

14561523
shutil.rmtree(
14571524
os.path.join(
1458-
self.tmp_path,
1525+
self.tests_path,
14591526
module_name,
14601527
fname
14611528
),

tox.ini

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[tox]
2+
envlist = py27,py36
3+
4+
[testenv]
5+
# install pytest in the virtualenv where commands will be executed
6+
deps = pytest
7+
commands =
8+
# NOTE: you can run any command line tool here - not just tests
9+
make

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy