A cloud file storage API backed by S3 and a sample client based on FilePond.
- AWS: API Gateway, Lambda, DynamoDB, S3, CloudWatch
- SAM + Swagger (OpenAPI)
- Python 3.7
- REST API, Security: API KEY
- FilePond client
- AWS Account
- AWS CLI
- SAM CLI
- Python 3.7
- (Optional) jq
-
Create S3 bucket for deployment
BUCKET NAME
is where the deployment artefacts are placedREGION
is where your bucket is createdaws s3api create-bucket --bucket [BUCKET NAME] --create-bucket-configuration LocationConstraint=[REGION]
-
Upload Swagger (OpenAPI) file
aws s3 cp swagger.yaml s3://[BUCKET NAME]/
-
Build the project with SAM
sam build --template template.yaml --build-dir ./dist
-
Package the project with SAM
sam package --s3-bucket [BUCKET NAME] --template-file dist/template.yaml --output-template-file dist/packaged.yaml
-
Deploy the project with CloudFormation
aws cloudformation deploy --template-file dist/packaged.yaml\ --stack-name FilestoreAppStack --s3-bucket [BUCKET NAME] --capabilities CAPABILITY_NAMED_IAM\ --parameter-overrides "StorageBucketName=filestore-project"\ "SwaggerLocation=s3://[BUCKET NAME]/swagger.yaml"
Additional deployment parameters
-
EnvironmentParameter=dev|prod
- deployment environment (String) -
SignedUrlExpiration=3600
- signed URL-s (S3) expiration in seconds (Number) -
StoreOnLoad=False|True
- mode of operation for storing files after upload (String)True = files are immediately stored after upload.
False = files are temporarily stored after upload, use the "store" API to store them permanently
-
-
Get the output from the deployment
aws cloudformation describe-stacks --stack-name FilestoreAppStack | jq .Stacks[0].Outputs
This command uses
jq
to extract the outputs from the JSON reponse. -
Create an API key for authentication
Use a recognisable
API KEY NAME
aws apigateway create-api-key --enabled --name [API KEY NAME]
-
Add the key to the usage plan
PLAN ID
can be found in the deployment output, look for the object with"OutputKey": "UsagePlanId"
API KEY ID
look for the"id"
value in the reponse from creating the API keyaws apigateway create-usage-plan-key --key-type "API_KEY" --usage-plan-id [PLAN ID] --key-id [API KEY ID]
-
Run unit test
-
Need to adjust
PYTHONPATH
to include the source directory holding the function implementations.export PYTHONPATH=$PYTHONPATH:"`pwd`/source"
-
Run the test (there is only one for now)
python -m unittest tests.unit.file
-
-
Run integration tests
-
Install pytest and tavern
pip install pytest tavern
-
Set environment variables
export TEST_HOST="..." export TEST_API_KEY="..."
TEST_HOST
: Retrive the host from the CloudFormation output at the end of deployment.TEST_API_KEY
: Use the API key created during deployment. -
Run the integration tests one by one
tavern-ci tests/integration/test_upload_file.tavern.yaml tavern-ci tests/integration/test_store_file.tavern.yaml tavern-ci tests/integration/test_delete_file.tavern.yaml tavern-ci tests/integration/test_download_file.tavern.yaml
-
Remove the deployment (deleting stack) if the app is not needed anymore, or if something goes wrong during deployment that needs fixing before trying it again.
aws cloudformation delete-stack --stack-name FilestoreAppStack
There is an example web app client you can deploy for testing purposes.
-
Create S3 bucket for the static site
WEB BUCKET NAME
is the bucket where the the static site is deployedREGION
is where your bucket is createdaws s3api create-bucket --bucket [WEB BUCKET NAME] --create-bucket-configuration LocationConstraint=[REGION]
Note the response will include your S3 static website link, something like http://[WEB BUCKET NAME].s3.amazonaws.com/
-
Update the S3 bucket policy to allow public acces
aws s3api put-bucket-policy --bucket [WEB BUCKET NAME]\ --policy '{"Version": "2012-10-17", "Statement": [{ "Sid": "Allow Public Access to All Objects", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::[WEB BUCKET NAME]/*"}]}'
-
Update S3 bucket website hosting configuration
aws s3api put-bucket-website --bucket [WEB BUCKET NAME] --website-configuration '{"IndexDocument": {"Suffix": "index.html"},"ErrorDocument": {"Key": "error.html"},"RoutingRules": [{"Redirect": {"ReplaceKeyWith": "index.html"},"Condition": {"KeyPrefixEquals": "/"}}]}'
-
Update the Filestore app URL
Open the
static/web/index.html
file and replace the[YOUR_URL]/[YOUR ENVIRONMENT]
at the bottom with the Filestore app URL, which is theApiRootUrl
from the CloudFormation output.Use the environment from the deployment configuration, or use
dev
if you kept the default.The final URL will look like: https://xxxxxxxxx.execute-api.xxxxxx.amazonaws.com/dev
-
Upload static files
aws s3 cp static/web s3://[WEB BUCKET NAME] --recursive --acl public-read
-
Open the website at http://[WEB BUCKET NAME].s3.amazonaws.com/index.html
Find more details about the use of the API in the User Guide.