Skip to content

Commit

Permalink
Merge pull request #4 from open-craft/artur/aws-region
Browse files Browse the repository at this point in the history
feat: support for specifying AWS region
  • Loading branch information
ArturGaspar authored Dec 27, 2023
2 parents 89ca1ea + 55f46d2 commit 97b5985
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 5 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ Change Log
Unreleased
**********

Added
=====

* feat: support for specifying AWS region

3.4.1
*****

Expand Down
13 changes: 10 additions & 3 deletions djpyfs/djpyfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,16 @@ def get_s3fs(namespace):
"""
key_id = DJFS_SETTINGS.get('aws_access_key_id', None)
key_secret = DJFS_SETTINGS.get('aws_secret_access_key', None)
region = DJFS_SETTINGS.get('region', None)

fullpath = namespace

if 'prefix' in DJFS_SETTINGS:
fullpath = os.path.join(DJFS_SETTINGS['prefix'], fullpath)

s3fs = S3FS(DJFS_SETTINGS['bucket'], fullpath, aws_access_key_id=key_id, aws_secret_access_key=key_secret)
s3fs = S3FS(DJFS_SETTINGS['bucket'], fullpath,
aws_access_key_id=key_id, aws_secret_access_key=key_secret,
region=region)

def get_s3_url(self, filename, timeout=60): # pylint: disable=unused-argument
"""
Expand All @@ -154,7 +157,9 @@ def get_s3_url(self, filename, timeout=60): # pylint: disable=unused-argument

try:
if not S3CONN:
S3CONN = boto3.client('s3', aws_access_key_id=key_id, aws_secret_access_key=key_secret)
S3CONN = boto3.client('s3', aws_access_key_id=key_id,
aws_secret_access_key=key_secret,
region_name=region)

return S3CONN.generate_presigned_url(
"get_object",
Expand All @@ -168,7 +173,9 @@ def get_s3_url(self, filename, timeout=60): # pylint: disable=unused-argument
except Exception: # pylint: disable=broad-except
# Retry on error; typically, if the connection has timed out, but
# the broad except covers all errors.
S3CONN = boto3.client('s3', aws_access_key_id=key_id, aws_secret_access_key=key_secret)
S3CONN = boto3.client('s3', aws_access_key_id=key_id,
aws_secret_access_key=key_secret,
region_name=region)

return S3CONN.generate_presigned_url(
"get_object",
Expand Down
35 changes: 33 additions & 2 deletions djpyfs/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,8 @@ def setUp(self):
def _setUpS3(self):
"""setup class"""

djpyfs.S3CONN = None

# Start mocking S3
self.mock_s3 = mock_s3()
self.mock_s3.start()
Expand All @@ -320,19 +322,23 @@ def _setUpS3(self):
self.conn = boto3.resource('s3')
self.conn.create_bucket(Bucket=djpyfs.DJFS_SETTINGS['bucket'])

def test_aws_credentials(self):
def test_aws_options(self):
fs = djpyfs.get_filesystem(self.namespace)
self.assertEqual(fs.aws_access_key_id, 'foo')
self.assertEqual(fs.aws_secret_access_key, 'bar')
self.assertEqual(fs.region, djpyfs.DJFS_SETTINGS.get('region', None))

# This test is only relevant for S3. Generate some fake errors to make
# sure we cover the retry code.
def test_get_url_retry(self):
fs = djpyfs.get_filesystem(self.namespace)
# Call get_url() once to initialise global S3CONN so we can patch its
# generate_presigned_url() method below.
fs.get_url(self.relative_path_to_test_file)
with patch('boto3.client') as mock_client:
mock_client.side_effect = AttributeError("Some attribute error occurred")
with patch.object(djpyfs.S3CONN, "generate_presigned_url") as mock_client:
mock_client.side_effect = AttributeError("Some attribute error occurred")
fs = djpyfs.get_filesystem(self.namespace)
with self.assertRaises(AttributeError):
fs.get_url(self.relative_path_to_test_file).startswith(self.expected_url_prefix)

Expand Down Expand Up @@ -364,3 +370,28 @@ def setUp(self):
f"{djpyfs.DJFS_SETTINGS['prefix']}/{self.namespace}/"
f"{self.relative_path_to_test_file}")
self._setUpS3()


# pylint: disable=test-inherits-tests
class S3TestRegion(S3Test):
"""
Same as S3Test above, but specifies AWS region.
"""

djfs_settings = {
'type': 's3fs',
'directory_root': 'django-pyfs/static/django-pyfs-test',
'url_root': '/static/django-pyfs-test',
'aws_access_key_id': 'foo',
'aws_secret_access_key': 'bar',
'bucket': 'test_bucket',
'region': 'me-south-1'
}

def setUp(self):
super().setUp()

self.expected_url_prefix = (f"https://s3.{djpyfs.DJFS_SETTINGS['region']}.amazonaws.com/"
f"{djpyfs.DJFS_SETTINGS['bucket']}/{self.namespace}/"
f"{self.relative_path_to_test_file}")
self._setUpS3()

0 comments on commit 97b5985

Please sign in to comment.