forked from jjhelmus/pyfive
-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mock s3fs testing framework #26
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
87a1980
add deps for mock s3 test
valeriupredoi c7058b6
add mock s3 test
valeriupredoi 7462033
add test reports to gitignore for now
valeriupredoi 0c8ffc5
add conftest
valeriupredoi 8cc2363
minimize conftest
valeriupredoi 3086211
make use of conftest and add minimal test for mock s3 fs
valeriupredoi ed0f117
upgrade actions versions
valeriupredoi 6843567
add flask dep
valeriupredoi 88752d1
restrict to python 3.10
valeriupredoi ddeb0ea
add flask-cors
valeriupredoi 522bf7a
add h5 modules
valeriupredoi 22476e8
mark test as xfailed
valeriupredoi f28c68d
add dosctrings
valeriupredoi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,3 +5,4 @@ __pycache__ | |
*.egg-info | ||
.idea | ||
.DS_Store | ||
test-reports/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import os | ||
import s3fs | ||
import pathlib | ||
import json | ||
import moto | ||
import pytest | ||
|
||
from moto.moto_server.threaded_moto_server import ThreadedMotoServer | ||
|
||
|
||
# some spoofy server parameters | ||
# test parameters; don't modify these | ||
port = 5555 | ||
endpoint_uri = "http://127.0.0.1:%s/" % port | ||
test_bucket_name = "test" | ||
versioned_bucket_name = "test-versioned" | ||
secure_bucket_name = "test-secure" | ||
|
||
def get_boto3_client(): | ||
from botocore.session import Session | ||
|
||
# NB: we use the sync botocore client for setup | ||
session = Session() | ||
return session.create_client("s3", endpoint_url=endpoint_uri) | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def s3_base(): | ||
# writable local S3 system | ||
|
||
# This fixture is module-scoped, meaning that we can re-use the MotoServer across all tests | ||
##### | ||
# lifted from https://github.com/fsspec/s3fs/blob/main/s3fs/tests/test_s3fs.py | ||
##### | ||
server = ThreadedMotoServer(ip_address="127.0.0.1", port=port) | ||
server.start() | ||
# the user ID and secret key are needed when accessing a public bucket | ||
# since our S3 FS and bucket are not actually on an AWS system, they can have | ||
# bogus values | ||
if "AWS_SECRET_ACCESS_KEY" not in os.environ: | ||
os.environ["AWS_SECRET_ACCESS_KEY"] = "foo" | ||
if "AWS_ACCESS_KEY_ID" not in os.environ: | ||
os.environ["AWS_ACCESS_KEY_ID"] = "foo" | ||
os.environ.pop("AWS_PROFILE", None) | ||
|
||
print("server up") | ||
yield | ||
print("moto done") | ||
server.stop() | ||
|
||
|
||
@pytest.fixture() | ||
def s3fs_s3(s3_base): | ||
""" | ||
Create a fully functional "virtual" S3 FileSystem compatible with fsspec/s3fs. | ||
Method inspired by https://github.com/fsspec/s3fs/blob/main/s3fs/tests/test_s3fs.py | ||
|
||
The S3 FS, being AWS-like but not actually physically deployed anywhere, still needs | ||
all the usual user IDs, secret keys, endpoint URLs etc; the setup makes use of the ACL=public | ||
configuration (public-read, or public-read-write). Public DOES NOT mean anon=True, but rather, | ||
All Users group – https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html | ||
Access permission to this group allows anyone with AWS credentials to access the resource. | ||
The requests need be signed (authenticated) or not. | ||
|
||
Also, keys are encrypted using AWS-KMS | ||
https://docs.aws.amazon.com/kms/latest/developerguide/overview.html | ||
""" | ||
client = get_boto3_client() | ||
|
||
# see not above about ACL=public-read | ||
client.create_bucket(Bucket=test_bucket_name, ACL="public-read") | ||
|
||
client.create_bucket(Bucket=versioned_bucket_name, ACL="public-read") | ||
client.put_bucket_versioning( | ||
Bucket=versioned_bucket_name, VersioningConfiguration={"Status": "Enabled"} | ||
) | ||
|
||
# initialize secure bucket | ||
client.create_bucket(Bucket=secure_bucket_name, ACL="public-read") | ||
policy = json.dumps( | ||
{ | ||
"Version": "2012-10-17", | ||
"Id": "PutObjPolicy", | ||
"Statement": [ | ||
{ | ||
"Sid": "DenyUnEncryptedObjectUploads", | ||
"Effect": "Deny", | ||
"Principal": "*", | ||
"Action": "s3:PutObject", | ||
"Resource": "arn:aws:s3:::{bucket_name}/*".format( | ||
bucket_name=secure_bucket_name | ||
), | ||
"Condition": { | ||
"StringNotEquals": { | ||
"s3:x-amz-server-side-encryption": "aws:kms" | ||
} | ||
}, | ||
} | ||
], | ||
} | ||
) | ||
|
||
client.put_bucket_policy(Bucket=secure_bucket_name, Policy=policy) | ||
s3fs.S3FileSystem.clear_instance_cache() | ||
s3 = s3fs.S3FileSystem(anon=False, client_kwargs={"endpoint_url": endpoint_uri}) | ||
s3.invalidate_cache() | ||
|
||
yield s3 | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import os | ||
import s3fs | ||
import pathlib | ||
import pyfive | ||
import pytest | ||
import h5netcdf | ||
|
||
|
||
# needed by the spoofed s3 filesystem | ||
port = 5555 | ||
endpoint_uri = "http://127.0.0.1:%s/" % port | ||
|
||
|
||
def test_s3fs_s3(s3fs_s3): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @bnlawrence here is a very little test that sets up the mock S3 FS via its fixture in conftest - the object |
||
"""Test mock S3 filesystem constructor.""" | ||
# this is an entire mock S3 FS | ||
mock_s3_filesystem = s3fs_s3 | ||
|
||
# explore its attributes and methods | ||
print(dir(mock_s3_filesystem)) | ||
|
||
assert not mock_s3_filesystem.anon | ||
assert not mock_s3_filesystem.version_aware | ||
assert mock_s3_filesystem.client_kwargs == {'endpoint_url': 'http://127.0.0.1:5555/'} | ||
|
||
|
||
def test_s3file_with_s3fs(s3fs_s3): | ||
""" | ||
This test spoofs a complete s3fs FileSystem via s3fs_s3, | ||
creates a mock bucket inside it, then puts a REAL netCDF4 file in it, | ||
then it loads it as if it was an S3 file. This is proper | ||
Wild Weasel stuff right here. | ||
""" | ||
# set up physical file and Path properties | ||
ncfile = "./tests/data/issue23_A.nc" | ||
file_path = pathlib.Path(ncfile) | ||
file_name = pathlib.Path(ncfile).name | ||
|
||
# use mocked s3fs | ||
bucket = "MY_BUCKET" | ||
s3fs_s3.mkdir(bucket) | ||
s3fs_s3.put(file_path, bucket) | ||
s3 = s3fs.S3FileSystem( | ||
anon=False, version_aware=True, client_kwargs={"endpoint_url": endpoint_uri} | ||
) | ||
|
||
# test load by h5netcdf | ||
with s3.open(os.path.join("MY_BUCKET", file_name), "rb") as f: | ||
print("File path", f.path) | ||
ncfile = h5netcdf.File(f, 'r', invalid_netcdf=True) | ||
print("File loaded from spoof S3 with h5netcdf:", ncfile) | ||
print(ncfile["q"]) | ||
assert "q" in ncfile | ||
|
||
# PyFive it | ||
with s3.open(os.path.join("MY_BUCKET", file_name), "rb") as f: | ||
pyfive_ds = pyfive.File(f) | ||
print(f"Dataset loaded from mock S3 with s3fs and Pyfive: ds") | ||
assert "q" in pyfive_ds |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
conftest now added, gents @bnlawrence and @davidhassell - these fixtures are now available out the box for testing right away