diff --git a/tests/providers/s3/test_provider.py b/tests/providers/s3/test_provider.py index ddee6756d..1b7498675 100644 --- a/tests/providers/s3/test_provider.py +++ b/tests/providers/s3/test_provider.py @@ -257,6 +257,21 @@ async def test_validate_v1_path_file(self, provider, file_header_metadata, mock_ assert wb_path_v1 == wb_path_v0 + @pytest.mark.asyncio + @pytest.mark.aiohttpretty + async def test_validate_v1_path_file_with_subfolder(self, provider, file_header_metadata, mock_time): + file_path = '/my-subfolder/foobah' + provider.settings['id'] = 'the-bucket:/my-subfolder/' + + good_metadata_url = provider.bucket.new_key(file_path).generate_url(100, 'HEAD') + aiohttpretty.register_uri('HEAD', good_metadata_url, headers=file_header_metadata) + + assert WaterButlerPath('/my-subfolder/') == await provider.validate_v1_path('/') + wb_path_v1 = await provider.validate_v1_path(file_path) + wb_path_v0 = await provider.validate_path(file_path) + + assert wb_path_v1 == wb_path_v0 + @pytest.mark.asyncio @pytest.mark.aiohttpretty async def test_validate_v1_path_folder(self, provider, folder_metadata, mock_time): @@ -408,6 +423,35 @@ async def test_download_folder_400s(self, provider, mock_time): await provider.download(WaterButlerPath('/cool/folder/mom/')) assert e.value.code == 400 + @pytest.mark.asyncio + @pytest.mark.aiohttpretty + async def test_upload_to_subfolder_as_root(self, + provider, + file_content, + file_stream, + file_header_metadata, + mock_time + ): + + provider.settings['id'] = 'the-bucket:/my-subfolder/' + path = WaterButlerPath('/my-subfolder/foobah') + + content_md5 = hashlib.md5(file_content).hexdigest() + + url = provider.bucket.new_key(path.path).generate_url(100, 'PUT') + metadata_url = provider.bucket.new_key(path.path).generate_url(100, 'HEAD') + aiohttpretty.register_uri('HEAD', metadata_url, headers=file_header_metadata) + header = {'ETag': f'"{content_md5}"'} + aiohttpretty.register_uri('PUT', url, status=201, headers=header) + + metadata, created = await provider.upload(file_stream, path) + + assert metadata.kind == 'file' + assert metadata.path == '/my-subfolder/foobah' + assert not created + assert aiohttpretty.has_call(method='PUT', uri=url) + assert aiohttpretty.has_call(method='HEAD', uri=metadata_url) + @pytest.mark.asyncio @pytest.mark.aiohttpretty async def test_upload_update(self, diff --git a/waterbutler/providers/s3/provider.py b/waterbutler/providers/s3/provider.py index a2419f7f1..dd3ac664f 100644 --- a/waterbutler/providers/s3/provider.py +++ b/waterbutler/providers/s3/provider.py @@ -688,7 +688,11 @@ async def _metadata_file(self, path, revision=None): async def _metadata_folder(self, path): await self._check_region() - params = {'prefix': path.path, 'delimiter': '/'} + # The user selected base folder, the root of the where that user's node is connected. + prefix = self.settings['id'].split(':/')[1] if path == '/' and self.settings.get('id') else path.path + + params = {'prefix': prefix, 'delimiter': '/'} + resp = await self.make_request( 'GET', functools.partial(self.bucket.generate_url, settings.TEMP_URL_SECS, 'GET', query_parameters=params), @@ -731,11 +735,11 @@ async def _metadata_folder(self, path): items = [ S3FolderMetadata(item) - for item in prefixes + for item in prefixes if item['Prefix'] != path.path ] for content in contents: - if content['Key'] == path.path: + if content['Key'] == params['prefix']: continue if content['Key'].endswith('/'):