diff --git a/src/backups.py b/src/backups.py index f661458467..4d905f8e21 100644 --- a/src/backups.py +++ b/src/backups.py @@ -284,13 +284,28 @@ def _create_bucket_if_not_exists(self) -> None: except ClientError: logger.warning("Bucket %s doesn't exist or you don't have access to it.", bucket_name) exists = False - if not exists: - try: - bucket.create(CreateBucketConfiguration={"LocationConstraint": region}) + if exists: + return - bucket.wait_until_exists() - logger.info("Created bucket '%s' in region=%s", bucket_name, region) - except ClientError as error: + try: + bucket.create(CreateBucketConfiguration={"LocationConstraint": region}) + + bucket.wait_until_exists() + logger.info("Created bucket '%s' in region=%s", bucket_name, region) + except ClientError as error: + if error.response["Error"]["Code"] == "InvalidLocationConstraint": + logger.info("Specified location-constraint is not valid, trying create without it") + try: + bucket.create() + + bucket.wait_until_exists() + logger.info("Created bucket '%s', ignored region=%s", bucket_name, region) + except ClientError as error: + logger.exception( + "Couldn't create bucket named '%s' in region=%s.", bucket_name, region + ) + raise error + else: logger.exception( "Couldn't create bucket named '%s' in region=%s.", bucket_name, region ) diff --git a/tests/unit/test_backups.py b/tests/unit/test_backups.py index 509f391cf4..f1d6e55972 100644 --- a/tests/unit/test_backups.py +++ b/tests/unit/test_backups.py @@ -368,7 +368,7 @@ def test_create_bucket_if_not_exists(harness, tls_ca_chain_filename): # Test when the bucket doesn't exist. head_bucket.reset_mock() head_bucket.side_effect = ClientError( - error_response={"Error": {"Code": 1, "message": "fake error"}}, + error_response={"Error": {"Code": "SomeFakeException", "message": "fake error"}}, operation_name="fake operation name", ) harness.charm.backup._create_bucket_if_not_exists() @@ -381,7 +381,7 @@ def test_create_bucket_if_not_exists(harness, tls_ca_chain_filename): create.reset_mock() wait_until_exists.reset_mock() create.side_effect = ClientError( - error_response={"Error": {"Code": 1, "message": "fake error"}}, + error_response={"Error": {"Code": "SomeFakeException", "message": "fake error"}}, operation_name="fake operation name", ) with pytest.raises(ClientError): @@ -391,9 +391,32 @@ def test_create_bucket_if_not_exists(harness, tls_ca_chain_filename): create.assert_called_once() wait_until_exists.assert_not_called() + # Test when the bucket creation fails with InvalidLocationConstraint. + head_bucket.reset_mock() + create.reset_mock() + wait_until_exists.reset_mock() + create.side_effect = ClientError( + error_response={ + "Error": {"Code": "InvalidLocationConstraint", "message": "fake error"} + }, + operation_name="fake operation name", + ) + with pytest.raises(ClientError): + harness.charm.backup._create_bucket_if_not_exists() + assert False + head_bucket.assert_called_once() + want = [ + call(CreateBucketConfiguration={"LocationConstraint": "test-region"}), + call(), + ] + create.assert_has_calls(want) + wait_until_exists.assert_not_called() + wait_until_exists.assert_has_calls([call(), call()]) + # Test when the bucket creation fails due to a timeout error. head_bucket.reset_mock() create.reset_mock() + wait_until_exists.reset_mock() head_bucket.side_effect = botocore.exceptions.ConnectTimeoutError( endpoint_url="fake endpoint URL" )