Skip to content

Commit

Permalink
Stop backup.info errors from breaking barman-cloud-backup-list (#363)
Browse files Browse the repository at this point in the history
Catches exceptions encountered when reading backup.info files
during backup list operations. A warning is logged and we continue
iterating through backup files.

This fixes a problem where a single unreadable backup.info file
would break barman-cloud-backup-list entirely, preventing users
from finding any backups in cloud storage. The specific example
reported was when a backup.info file has the AWS S3 Glacier
storage class however there are other reasons why a backup.info
file might not be readable. In these scenarios we would still
want to list the backup.info files that were readable, so we
therefore catch `Exception`s rather than anything more specific.

Closes #332
  • Loading branch information
mikewallace1979 authored Jul 23, 2021
1 parent 889830e commit d433355
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 2 deletions.
8 changes: 7 additions & 1 deletion barman/cloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -1496,7 +1496,13 @@ def get_backup_list(self):
if backup_dir[-1] != "/":
continue
backup_id = os.path.basename(backup_dir.rstrip("/"))
backup_info = self.get_backup_info(backup_id)
try:
backup_info = self.get_backup_info(backup_id)
except Exception as exc:
logging.warning(
"Unable to open backup.info file for %s: %s" % (backup_id, exc)
)
continue

if backup_info:
backup_list[backup_id] = backup_info
Expand Down
63 changes: 62 additions & 1 deletion tests/test_cloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@
from azure.core.exceptions import ServiceRequestError

import mock
from mock.mock import MagicMock
import pytest
from boto3.exceptions import Boto3Error
from botocore.exceptions import ClientError, EndpointConnectionError

from barman.cloud import CloudUploadingError, FileUploadStatistics
from barman.cloud import CloudBackupCatalog, CloudUploadingError, FileUploadStatistics
from barman.cloud_providers.aws_s3 import S3CloudInterface
from barman.cloud_providers.azure_blob_storage import AzureCloudInterface

Expand Down Expand Up @@ -1057,3 +1058,63 @@ def test_abort_multipart_upload_with_encryption_scope(self, blob_service_mock):
[], encryption_scope=encryption_scope
)
blob_client_mock.delete_blob.assert_called_once_with()


class TestCloudBackupCatalog(object):
"""
Tests which verify we can list backups stored in a cloud provider
"""

def get_backup_info_file_object(self):
"""Minimal backup info"""
return BytesIO(
b"""
backup_label=None
end_time=2014-12-22 09:25:27.410470+01:00
"""
)

def raise_exception(self):
raise Exception("something went wrong reading backup.info")

def mock_remote_open(self, _):
"""
Helper function which alternates between successful and unsuccessful
remote_open responses.
"""
try:
if self.remote_open_should_succeed:
return self.get_backup_info_file_object()
else:
raise Exception("something went wrong reading backup.info")
finally:
self.remote_open_should_succeed = not self.remote_open_should_succeed

def test_can_list_single_backup(self):
mock_cloud_interface = MagicMock()
mock_cloud_interface.list_bucket.return_value = [
"mt-backups/test-server/base/20210723T133818/",
]
mock_cloud_interface.remote_open.return_value = (
self.get_backup_info_file_object()
)
catalog = CloudBackupCatalog(mock_cloud_interface, "test-server")
backups = catalog.get_backup_list()
assert len(backups) == 1
assert "20210723T133818" in backups

def test_backups_can_be_listed_if_one_is_unreadable(self):
self.remote_open_should_succeed = True
mock_cloud_interface = MagicMock()
mock_cloud_interface.list_bucket.return_value = [
"mt-backups/test-server/base/20210723T133818/",
"mt-backups/test-server/base/20210723T154445/",
"mt-backups/test-server/base/20210723T154554/",
]
mock_cloud_interface.remote_open.side_effect = self.mock_remote_open
catalog = CloudBackupCatalog(mock_cloud_interface, "test-server")
backups = catalog.get_backup_list()
assert len(backups) == 2
assert "20210723T133818" in backups
assert "20210723T154445" not in backups
assert "20210723T154554" in backups

0 comments on commit d433355

Please sign in to comment.