testgres-pg-probackup2 0.0.1__tar.gz → 0.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {testgres_pg_probackup2-0.0.1 → testgres_pg_probackup2-0.0.3}/PKG-INFO +1 -1
- {testgres_pg_probackup2-0.0.1 → testgres_pg_probackup2-0.0.3}/README.md +6 -14
- {testgres_pg_probackup2-0.0.1 → testgres_pg_probackup2-0.0.3}/pg_probackup2/app.py +66 -26
- {testgres_pg_probackup2-0.0.1 → testgres_pg_probackup2-0.0.3}/pg_probackup2/init_helpers.py +19 -9
- {testgres_pg_probackup2-0.0.1 → testgres_pg_probackup2-0.0.3}/pg_probackup2/storage/fs_backup.py +4 -1
- {testgres_pg_probackup2-0.0.1 → testgres_pg_probackup2-0.0.3}/setup.py +1 -1
- {testgres_pg_probackup2-0.0.1 → testgres_pg_probackup2-0.0.3}/testgres_pg_probackup2.egg-info/PKG-INFO +1 -1
- {testgres_pg_probackup2-0.0.1 → testgres_pg_probackup2-0.0.3}/testgres_pg_probackup2.egg-info/SOURCES.txt +0 -1
- testgres_pg_probackup2-0.0.1/pg_probackup2/storage/s3_backup.py +0 -134
- {testgres_pg_probackup2-0.0.1 → testgres_pg_probackup2-0.0.3}/pg_probackup2/__init__.py +0 -0
- {testgres_pg_probackup2-0.0.1 → testgres_pg_probackup2-0.0.3}/pg_probackup2/gdb.py +0 -0
- {testgres_pg_probackup2-0.0.1 → testgres_pg_probackup2-0.0.3}/pg_probackup2/storage/__init__.py +0 -0
- {testgres_pg_probackup2-0.0.1 → testgres_pg_probackup2-0.0.3}/setup.cfg +0 -0
- {testgres_pg_probackup2-0.0.1 → testgres_pg_probackup2-0.0.3}/testgres_pg_probackup2.egg-info/dependency_links.txt +0 -0
- {testgres_pg_probackup2-0.0.1 → testgres_pg_probackup2-0.0.3}/testgres_pg_probackup2.egg-info/requires.txt +0 -0
- {testgres_pg_probackup2-0.0.1 → testgres_pg_probackup2-0.0.3}/testgres_pg_probackup2.egg-info/top_level.txt +0 -0
|
@@ -16,22 +16,14 @@ The package requires testgres~=1.9.3.
|
|
|
16
16
|
|
|
17
17
|
## Usage
|
|
18
18
|
|
|
19
|
-
### Environment
|
|
19
|
+
### Environment variables
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
* export `PG_CONFIG` environment variable pointing to the `pg_config` executable;
|
|
26
|
-
* export `PG_BIN` environment variable pointing to the directory with executable files.
|
|
27
|
-
|
|
28
|
-
Example:
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
export PG_BIN=$HOME/pg/bin
|
|
32
|
-
python my_tests.py
|
|
33
|
-
```
|
|
21
|
+
| Variable | Required | Default value | Description |
|
|
22
|
+
| - | - | - | - |
|
|
23
|
+
| PGPROBACKUP_TMP_DIR | No | tests/tmp_dirs | The root of the temporary directory hierarchy where tests store data and logs. Relative paths start from the current working directory. |
|
|
24
|
+
| PG_PROBACKUP_TEST_BACKUP_DIR_PREFIX | No | Temporary test hierarchy | Prefix of the test backup directories. Must be an absolute path. Use this variable to store test backups in a location other than the temporary test hierarchy. |
|
|
34
25
|
|
|
26
|
+
See [Testgres](https://github.com/postgrespro/testgres/tree/master#environment) on how to configure a custom Postgres installation using `PG_CONFIG` and `PG_BIN` environment variables.
|
|
35
27
|
|
|
36
28
|
### Examples
|
|
37
29
|
|
|
@@ -4,7 +4,6 @@ import json
|
|
|
4
4
|
import os
|
|
5
5
|
import re
|
|
6
6
|
import subprocess
|
|
7
|
-
import sys
|
|
8
7
|
import threading
|
|
9
8
|
import time
|
|
10
9
|
import unittest
|
|
@@ -37,6 +36,10 @@ class ProbackupException(Exception):
|
|
|
37
36
|
return '\n ERROR: {0}\n CMD: {1}'.format(repr(self.message), self.cmd)
|
|
38
37
|
|
|
39
38
|
|
|
39
|
+
# Local backup control
|
|
40
|
+
fs_backup_class = FSTestBackupDir
|
|
41
|
+
|
|
42
|
+
|
|
40
43
|
class ProbackupApp:
|
|
41
44
|
|
|
42
45
|
def __init__(self, test_class: unittest.TestCase,
|
|
@@ -53,6 +56,7 @@ class ProbackupApp:
|
|
|
53
56
|
self.verbose = init_params.verbose
|
|
54
57
|
self.archive_compress = init_params.archive_compress
|
|
55
58
|
self.test_class.output = None
|
|
59
|
+
self.execution_time = None
|
|
56
60
|
|
|
57
61
|
def run(self, command, gdb=False, old_binary=False, return_id=True, env=None,
|
|
58
62
|
skip_log_directory=False, expect_error=False, use_backup_dir=True):
|
|
@@ -110,16 +114,17 @@ class ProbackupApp:
|
|
|
110
114
|
cmdline = ['gdbserver'] + ['localhost:' + str(gdb_port)] + cmdline
|
|
111
115
|
print("pg_probackup gdb suspended, waiting gdb connection on localhost:{0}".format(gdb_port))
|
|
112
116
|
|
|
117
|
+
start_time = time.time()
|
|
113
118
|
self.test_class.output = subprocess.check_output(
|
|
114
119
|
cmdline,
|
|
115
120
|
stderr=subprocess.STDOUT,
|
|
116
121
|
env=env
|
|
117
122
|
).decode('utf-8', errors='replace')
|
|
123
|
+
end_time = time.time()
|
|
124
|
+
self.execution_time = end_time - start_time
|
|
125
|
+
|
|
118
126
|
if command[0] == 'backup' and return_id:
|
|
119
|
-
|
|
120
|
-
for line in self.test_class.output.splitlines():
|
|
121
|
-
if 'INFO: Backup' and 'completed' in line:
|
|
122
|
-
result = line.split()[2]
|
|
127
|
+
result = self.get_backup_id()
|
|
123
128
|
else:
|
|
124
129
|
result = self.test_class.output
|
|
125
130
|
if expect_error is True:
|
|
@@ -136,6 +141,19 @@ class ProbackupApp:
|
|
|
136
141
|
else:
|
|
137
142
|
raise ProbackupException(self.test_class.output, self.test_class.cmd)
|
|
138
143
|
|
|
144
|
+
def get_backup_id(self):
|
|
145
|
+
if init_params.major_version > 2:
|
|
146
|
+
pattern = re.compile(r"Backup (.*) completed successfully.")
|
|
147
|
+
for line in self.test_class.output.splitlines():
|
|
148
|
+
match = pattern.search(line)
|
|
149
|
+
if match:
|
|
150
|
+
return match.group(1)
|
|
151
|
+
else:
|
|
152
|
+
for line in self.test_class.output.splitlines():
|
|
153
|
+
if 'INFO: Backup' and 'completed' in line:
|
|
154
|
+
return line.split()[2]
|
|
155
|
+
return None
|
|
156
|
+
|
|
139
157
|
def init(self, options=None, old_binary=False, skip_log_directory=False, expect_error=False, use_backup_dir=True):
|
|
140
158
|
if options is None:
|
|
141
159
|
options = []
|
|
@@ -146,13 +164,19 @@ class ProbackupApp:
|
|
|
146
164
|
use_backup_dir=use_backup_dir
|
|
147
165
|
)
|
|
148
166
|
|
|
149
|
-
def add_instance(self, instance, node, old_binary=False, options=None, expect_error=False):
|
|
167
|
+
def add_instance(self, instance, node, old_binary=False, options=None, expect_error=False, datname=False):
|
|
150
168
|
if options is None:
|
|
151
169
|
options = []
|
|
170
|
+
|
|
171
|
+
if not datname:
|
|
172
|
+
datname = 'postgres'
|
|
173
|
+
|
|
152
174
|
cmd = [
|
|
153
175
|
'add-instance',
|
|
154
176
|
'--instance={0}'.format(instance),
|
|
155
|
-
'-D', node.data_dir
|
|
177
|
+
'-D', node.data_dir,
|
|
178
|
+
'--pgport', '%i' % node.port,
|
|
179
|
+
'--pgdatabase', datname
|
|
156
180
|
]
|
|
157
181
|
|
|
158
182
|
# don`t forget to kill old_binary after remote ssh release
|
|
@@ -189,15 +213,13 @@ class ProbackupApp:
|
|
|
189
213
|
|
|
190
214
|
return self.run(cmd + options, old_binary=old_binary, expect_error=expect_error)
|
|
191
215
|
|
|
192
|
-
def del_instance(self, instance, old_binary=False, expect_error=False):
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
expect_error=expect_error
|
|
200
|
-
)
|
|
216
|
+
def del_instance(self, instance, options=None, old_binary=False, expect_error=False):
|
|
217
|
+
if options is None:
|
|
218
|
+
options = []
|
|
219
|
+
cmd = ['del-instance', '--instance={0}'.format(instance)] + options
|
|
220
|
+
return self.run(cmd,
|
|
221
|
+
old_binary=old_binary,
|
|
222
|
+
expect_error=expect_error)
|
|
201
223
|
|
|
202
224
|
def backup_node(
|
|
203
225
|
self, instance, node, data_dir=False,
|
|
@@ -662,7 +684,11 @@ class ProbackupApp:
|
|
|
662
684
|
if custom_archive_command is None:
|
|
663
685
|
archive_command = " ".join([f'"{init_params.probackup_path}"',
|
|
664
686
|
'archive-push', *self.backup_dir.pb_args])
|
|
665
|
-
if os.name ==
|
|
687
|
+
if os.name == 'posix':
|
|
688
|
+
# Dash produces a core dump when it gets a SIGQUIT from its
|
|
689
|
+
# child process so replace the shell with pg_probackup
|
|
690
|
+
archive_command = 'exec ' + archive_command
|
|
691
|
+
elif os.name == "nt":
|
|
666
692
|
archive_command = archive_command.replace("\\", "\\\\")
|
|
667
693
|
archive_command += f' --instance={instance}'
|
|
668
694
|
|
|
@@ -747,16 +773,30 @@ class ProbackupApp:
|
|
|
747
773
|
|
|
748
774
|
return getattr(module, class_name)
|
|
749
775
|
|
|
776
|
+
def archive_push(self, instance, node, wal_file_name, wal_file_path=None, options=None, expect_error=False):
|
|
777
|
+
if options is None:
|
|
778
|
+
options = []
|
|
779
|
+
cmd = [
|
|
780
|
+
'archive-push',
|
|
781
|
+
'--instance={0}'.format(instance),
|
|
782
|
+
'--wal-file-name={0}'.format(wal_file_name),
|
|
783
|
+
]
|
|
784
|
+
if wal_file_path is None:
|
|
785
|
+
cmd = cmd + ['--wal-file-path={0}'.format(os.path.join(node.data_dir, 'pg_wal'))]
|
|
786
|
+
else:
|
|
787
|
+
cmd = cmd + ['--wal-file-path={0}'.format(wal_file_path)]
|
|
788
|
+
return self.run(cmd + options, expect_error=expect_error)
|
|
750
789
|
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
790
|
+
def archive_get(self, instance, wal_file_name, wal_file_path, options=None, expect_error=False):
|
|
791
|
+
if options is None:
|
|
792
|
+
options = []
|
|
793
|
+
cmd = [
|
|
794
|
+
'archive-get',
|
|
795
|
+
'--instance={0}'.format(instance),
|
|
796
|
+
'--wal-file-name={0}'.format(wal_file_name),
|
|
797
|
+
'--wal-file-path={0}'.format(wal_file_path),
|
|
798
|
+
]
|
|
799
|
+
return self.run(cmd + options, expect_error=expect_error)
|
|
760
800
|
|
|
761
801
|
def build_backup_dir(self, backup='backup'):
|
|
762
802
|
return fs_backup_class(rel_path=self.rel_path, backup=backup)
|
|
@@ -52,6 +52,7 @@ class Init(object):
|
|
|
52
52
|
parts[0] = re.match(r'\d+', parts[0]).group()
|
|
53
53
|
self.pg_config_version = reduce(lambda v, x: v * 100 + int(x), parts, 0)
|
|
54
54
|
|
|
55
|
+
os.environ['LANGUAGE'] = 'en' # set default locale language to en. All messages will use this locale
|
|
55
56
|
test_env = os.environ.copy()
|
|
56
57
|
envs_list = [
|
|
57
58
|
'LANGUAGE',
|
|
@@ -147,21 +148,24 @@ class Init(object):
|
|
|
147
148
|
[self.probackup_path, "--version"],
|
|
148
149
|
stderr=subprocess.STDOUT,
|
|
149
150
|
).decode('utf-8')
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
151
|
+
match = re.search(r"\d+\.\d+\.\d+",
|
|
152
|
+
probackup_version_output)
|
|
153
|
+
self.probackup_version = match.group(0) if match else None
|
|
154
|
+
match = re.search(r"\(compressions: ([^)]*)\)", probackup_version_output)
|
|
155
|
+
compressions = match.group(1) if match else None
|
|
156
|
+
if compressions:
|
|
157
|
+
self.probackup_compressions = {s.strip() for s in compressions.split(',')}
|
|
158
|
+
else:
|
|
159
|
+
self.probackup_compressions = []
|
|
156
160
|
|
|
157
161
|
if self.probackup_old_path:
|
|
158
162
|
old_probackup_version_output = subprocess.check_output(
|
|
159
163
|
[self.probackup_old_path, "--version"],
|
|
160
164
|
stderr=subprocess.STDOUT,
|
|
161
165
|
).decode('utf-8')
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
166
|
+
match = re.search(r"\d+\.\d+\.\d+",
|
|
167
|
+
old_probackup_version_output)
|
|
168
|
+
self.old_probackup_version = match.group(0) if match else None
|
|
165
169
|
|
|
166
170
|
self.remote = test_env.get('PGPROBACKUP_SSH_REMOTE', None) == 'ON'
|
|
167
171
|
self.ptrack = test_env.get('PG_PROBACKUP_PTRACK', None) == 'ON' and self.pg_config_version >= 110000
|
|
@@ -200,6 +204,12 @@ class Init(object):
|
|
|
200
204
|
os.environ["PGAPPNAME"] = "pg_probackup"
|
|
201
205
|
self.delete_logs = delete_logs
|
|
202
206
|
|
|
207
|
+
if self.probackup_version.split('.')[0].isdigit():
|
|
208
|
+
self.major_version = int(self.probackup_version.split('.')[0])
|
|
209
|
+
else:
|
|
210
|
+
print('Can\'t process pg_probackup version \"{}\": the major version is expected to be a number'.format(self.probackup_version))
|
|
211
|
+
sys.exit(1)
|
|
212
|
+
|
|
203
213
|
def test_env(self):
|
|
204
214
|
return self._test_env.copy()
|
|
205
215
|
|
{testgres_pg_probackup2-0.0.1 → testgres_pg_probackup2-0.0.3}/pg_probackup2/storage/fs_backup.py
RENAMED
|
@@ -43,7 +43,10 @@ class FSTestBackupDir(TestBackupDir):
|
|
|
43
43
|
""" Backup directory. Usually created by running pg_probackup init -B <path>"""
|
|
44
44
|
|
|
45
45
|
def __init__(self, *, rel_path, backup):
|
|
46
|
-
|
|
46
|
+
backup_prefix = os.environ.get('PG_PROBACKUP_TEST_BACKUP_DIR_PREFIX')
|
|
47
|
+
if backup_prefix and not os.path.isabs(backup_prefix):
|
|
48
|
+
raise Exception(f"PG_PROBACKUP_TEST_BACKUP_DIR_PREFIX must be an absolute path, current value: {backup_prefix}")
|
|
49
|
+
self.path = os.path.join(backup_prefix or init_params.tmp_path, rel_path, backup)
|
|
47
50
|
self.pb_args = ('-B', self.path)
|
|
48
51
|
|
|
49
52
|
def list_instance_backups(self, instance):
|
|
@@ -6,7 +6,6 @@ pg_probackup2/gdb.py
|
|
|
6
6
|
pg_probackup2/init_helpers.py
|
|
7
7
|
pg_probackup2/storage/__init__.py
|
|
8
8
|
pg_probackup2/storage/fs_backup.py
|
|
9
|
-
pg_probackup2/storage/s3_backup.py
|
|
10
9
|
testgres_pg_probackup2.egg-info/PKG-INFO
|
|
11
10
|
testgres_pg_probackup2.egg-info/SOURCES.txt
|
|
12
11
|
testgres_pg_probackup2.egg-info/dependency_links.txt
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import io
|
|
3
|
-
import sys
|
|
4
|
-
|
|
5
|
-
import minio
|
|
6
|
-
from minio import Minio
|
|
7
|
-
from minio.deleteobjects import DeleteObject
|
|
8
|
-
import urllib3
|
|
9
|
-
from .fs_backup import TestBackupDir
|
|
10
|
-
|
|
11
|
-
root = os.path.realpath(os.path.join(os.path.dirname(__file__), '../..'))
|
|
12
|
-
if root not in sys.path:
|
|
13
|
-
sys.path.append(root)
|
|
14
|
-
|
|
15
|
-
# Should fail if either of env vars does not exist
|
|
16
|
-
host = os.environ['PG_PROBACKUP_S3_HOST']
|
|
17
|
-
port = os.environ['PG_PROBACKUP_S3_PORT']
|
|
18
|
-
access = os.environ['PG_PROBACKUP_S3_ACCESS_KEY']
|
|
19
|
-
secret = os.environ['PG_PROBACKUP_S3_SECRET_ACCESS_KEY']
|
|
20
|
-
bucket = os.environ['PG_PROBACKUP_S3_BUCKET_NAME']
|
|
21
|
-
path_suffix = os.environ.get("PG_PROBACKUP_TEST_TMP_SUFFIX")
|
|
22
|
-
https = os.environ.get("PG_PROBACKUP_S3_HTTPS")
|
|
23
|
-
|
|
24
|
-
s3_type = os.environ.get('PG_PROBACKUP_S3_TEST', os.environ.get('PROBACKUP_S3_TYPE_FULL_TEST'))
|
|
25
|
-
tmp_path = os.environ.get('PGPROBACKUP_TMP_DIR', default='')
|
|
26
|
-
|
|
27
|
-
status_forcelist = [413, # RequestBodyTooLarge
|
|
28
|
-
429, # TooManyRequests
|
|
29
|
-
500, # InternalError
|
|
30
|
-
503, # ServerBusy
|
|
31
|
-
]
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
class S3TestBackupDir(TestBackupDir):
|
|
35
|
-
is_file_based = False
|
|
36
|
-
|
|
37
|
-
def __init__(self, *, rel_path, backup):
|
|
38
|
-
path = "pg_probackup"
|
|
39
|
-
if path_suffix:
|
|
40
|
-
path += "_" + path_suffix
|
|
41
|
-
if tmp_path == '' or os.path.isabs(tmp_path):
|
|
42
|
-
self.path = f"{path}{tmp_path}/{rel_path}/{backup}"
|
|
43
|
-
else:
|
|
44
|
-
self.path = f"{path}/{tmp_path}/{rel_path}/{backup}"
|
|
45
|
-
|
|
46
|
-
secure: bool = False
|
|
47
|
-
if https in ['ON', 'HTTPS']:
|
|
48
|
-
secure = True
|
|
49
|
-
self.conn = Minio(host + ":" + port, secure=secure, access_key=access,
|
|
50
|
-
secret_key=secret, http_client=urllib3.PoolManager(retries=urllib3.Retry(total=5,
|
|
51
|
-
backoff_factor=1,
|
|
52
|
-
status_forcelist=status_forcelist)))
|
|
53
|
-
if not self.conn.bucket_exists(bucket):
|
|
54
|
-
raise Exception(f"Test bucket {bucket} does not exist.")
|
|
55
|
-
self.pb_args = ('-B', '/' + self.path, f'--s3={s3_type}')
|
|
56
|
-
return
|
|
57
|
-
|
|
58
|
-
def list_instance_backups(self, instance):
|
|
59
|
-
full_path = os.path.join(self.path, 'backups', instance)
|
|
60
|
-
candidates = self.conn.list_objects(bucket, prefix=full_path, recursive=True)
|
|
61
|
-
return [os.path.basename(os.path.dirname(x.object_name))
|
|
62
|
-
for x in candidates if x.object_name.endswith('backup.control')]
|
|
63
|
-
|
|
64
|
-
def list_files(self, sub_dir, recursive=False):
|
|
65
|
-
full_path = os.path.join(self.path, sub_dir)
|
|
66
|
-
# Need '/' in the end to find inside the folder
|
|
67
|
-
full_path_dir = full_path if full_path[-1] == '/' else full_path + '/'
|
|
68
|
-
object_list = self.conn.list_objects(bucket, prefix=full_path_dir, recursive=recursive)
|
|
69
|
-
return [obj.object_name.replace(full_path_dir, '', 1)
|
|
70
|
-
for obj in object_list
|
|
71
|
-
if not obj.is_dir]
|
|
72
|
-
|
|
73
|
-
def list_dirs(self, sub_dir):
|
|
74
|
-
full_path = os.path.join(self.path, sub_dir)
|
|
75
|
-
# Need '/' in the end to find inside the folder
|
|
76
|
-
full_path_dir = full_path if full_path[-1] == '/' else full_path + '/'
|
|
77
|
-
object_list = self.conn.list_objects(bucket, prefix=full_path_dir, recursive=False)
|
|
78
|
-
return [obj.object_name.replace(full_path_dir, '', 1).rstrip('\\/')
|
|
79
|
-
for obj in object_list
|
|
80
|
-
if obj.is_dir]
|
|
81
|
-
|
|
82
|
-
def read_file(self, sub_path, *, text=True):
|
|
83
|
-
full_path = os.path.join(self.path, sub_path)
|
|
84
|
-
bytes = self.conn.get_object(bucket, full_path).read()
|
|
85
|
-
if not text:
|
|
86
|
-
return bytes
|
|
87
|
-
return bytes.decode('utf-8')
|
|
88
|
-
|
|
89
|
-
def write_file(self, sub_path, data, *, text=True):
|
|
90
|
-
full_path = os.path.join(self.path, sub_path)
|
|
91
|
-
if text:
|
|
92
|
-
data = data.encode('utf-8')
|
|
93
|
-
self.conn.put_object(bucket, full_path, io.BytesIO(data), length=len(data))
|
|
94
|
-
|
|
95
|
-
def cleanup(self):
|
|
96
|
-
self.remove_dir('')
|
|
97
|
-
|
|
98
|
-
def remove_file(self, sub_path):
|
|
99
|
-
full_path = os.path.join(self.path, sub_path)
|
|
100
|
-
self.conn.remove_object(bucket, full_path)
|
|
101
|
-
|
|
102
|
-
def remove_dir(self, sub_path):
|
|
103
|
-
if sub_path:
|
|
104
|
-
full_path = os.path.join(self.path, sub_path)
|
|
105
|
-
else:
|
|
106
|
-
full_path = self.path
|
|
107
|
-
objs = self.conn.list_objects(bucket, prefix=full_path, recursive=True,
|
|
108
|
-
include_version=True)
|
|
109
|
-
delobjs = (DeleteObject(o.object_name, o.version_id) for o in objs)
|
|
110
|
-
errs = list(self.conn.remove_objects(bucket, delobjs))
|
|
111
|
-
if errs:
|
|
112
|
-
strerrs = "; ".join(str(err) for err in errs)
|
|
113
|
-
raise Exception("There were errors: {0}".format(strerrs))
|
|
114
|
-
|
|
115
|
-
def exists(self, sub_path):
|
|
116
|
-
full_path = os.path.join(self.path, sub_path)
|
|
117
|
-
try:
|
|
118
|
-
self.conn.stat_object(bucket, full_path)
|
|
119
|
-
return True
|
|
120
|
-
except minio.error.S3Error as s3err:
|
|
121
|
-
if s3err.code == 'NoSuchKey':
|
|
122
|
-
return False
|
|
123
|
-
raise s3err
|
|
124
|
-
except Exception as err:
|
|
125
|
-
raise err
|
|
126
|
-
|
|
127
|
-
def __str__(self):
|
|
128
|
-
return '/' + self.path
|
|
129
|
-
|
|
130
|
-
def __repr__(self):
|
|
131
|
-
return "S3TestBackupDir" + str(self.path)
|
|
132
|
-
|
|
133
|
-
def __fspath__(self):
|
|
134
|
-
return self.path
|
|
File without changes
|
|
File without changes
|
{testgres_pg_probackup2-0.0.1 → testgres_pg_probackup2-0.0.3}/pg_probackup2/storage/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|