AWS S3 (Object Storage)
S3 Buckets
Stelvio supports creating and managing S3 buckets using the Bucket component.
Create an S3 bucket and link it to an API Gateway handler:
@app.run
def run() -> None:
bucket = Bucket("todo-bucket")
api = Api("todo-api")
api.route("GET", "/write", handler="functions/write.get", links=[bucket])
api.route("GET", "/read", handler="functions/read.get", links=[bucket])
Using the linking mechanism, you can easily access the S3 bucket in your Lambda functions using the regular boto3 library:
import boto3
from stlv_resources import Resources
def get(event, context):
s3_client = boto3.client("s3")
bucket_name = Resources.todo_bucket.bucket_name
s3_client.put_object(Bucket=bucket_name, Key="hello.txt", Body="Hello, World!")
return {"statusCode": 200, "body": "Hello, World!"}
Public Access
By default, all public access is blocked for S3 buckets created with the Bucket component.
You can change that behaviour by setting the access argument to 'public':
How access is implemented
Internally, access to S3 buckets is handled by the BucketPublicAccessBlock resource.
It is created with the followign parameters:
block_public_acls=<Value>,
block_public_policy=<Value>,
ignore_public_acls=<Value>,
restrict_public_buckets=<Value>,
<Value> is set to either False for public access or True for private access (default).
| Parameter | Description |
|---|---|
block_public_acls |
Whether to block public ACLs. |
block_public_policy |
Whether to block public policies. |
ignore_public_acls |
Whether to ignore public ACLs. |
restrict_public_buckets |
Whether to restrict public buckets. |
Additionally, a policy for s3:GetObject is created to allow public read access to the objects in the bucket if access is set to 'public'.
See the Pulumi Documentation for more information.
Parameters
| Parameter | Description |
|---|---|
versioning |
The versioning configuration for the S3 bucket. Boolean. Default is False. |
access |
The access configuration for the S3 bucket. Either None (default) or 'public'. |
Resources
| Resource | Description |
|---|---|
bucket |
The S3 bucket created by the Bucket component. |
public_access_block |
The BucketPublicAccessBlock resource created by the Bucket component. |
bucket_policy |
The BucketPolicy resource created by the Bucket component if access is set to 'public'. |
Static Websites
Stelvio can create and manage S3 buckets for static website hosting using the S3StaticWebsite component.
Create a static website from a directory using the S3StaticWebsite component:
@app.run
def run() -> None:
config = mkdocs.config.load_config("mkdocs.yml")
mkdocs.commands.build.build(config)
_ = S3StaticWebsite(
"s3-static-mkdocs",
custom_domain="s3-2." + CUSTOM_DOMAIN_NAME,
directory="site"
)
- Creates an S3 bucket for static website hosting
- Creates a CloudFront distribution for the S3 bucket, so that it is compatible with 3rd party DNS providers
- Attaching a domain name to a S3 bucket (without CloudFront) only works with AWS Route 53, because you'd need to create a CNAME pointing to the S3 bucket name. This is not possible with other DNS providers as they don't have access to the S3 bucket name in AWS.
- Creates an S3 object for each file in the static website directory
- Automatically creates a DNS record for the CloudFront distribution if a DNS provider is configured
Handling files (assets) of a static website
The S3StaticWebsite component automatically uploads all files in the specified directory to the S3 bucket.
The directory parameter is optional, though. If omitted, an empty S3 bucket is created and you are responsible for uploading the files (assets) to the bucket.
The custom_domain parameter is also optional. If omitted, no DNS record is created for the CloudFront distribution and you can access the static website using the CloudFront domain name (<distribution_id>.cloudfront.net).
In the following example, we use the mkdocs library to build a static website from Markdown files and upload the generated files to the S3 bucket:
@app.run
def run() -> None:
config = mkdocs.config.load_config("mkdocs.yml")
mkdocs.commands.build.build(config)
website = S3StaticWebsite(
"s3-static-mkdocs",
custom_domain="s3-2." + CUSTOM_DOMAIN_NAME,
)
# Upload files to the bucket
s3_bucket = website.bucket
boto3_client = boto3.client("s3")
boto3_client.put_object(
Bucket=s3_bucket.bucket_name, Key="index.html", Body="<h1>Hello, World!</h1>"
)
In both cases, the files uploaded to your static website are considered part of your infrastructure. Thus, the files would be automatically deployed whenever you run stlv deploy. However, in the latter case, uploaded files are not part of your (Pulumi) state and thus not tracked.
Using the stlv_resources module, you can access the S3 bucket and manage the files (assets) in your static website, should you decide that part should not be part of your deployment. Note that at the moment, you can get the arn of the bucket via stvl_resources only from within a Lambda function.
Note
If you decide to upload your file assets manually, you must also take care of removing the files from the bucket before running stlv destroy, as the AWS API does not allow deleting a non-empty S3 bucket.
!! note
The S3StaticWebsite component is designed for most use cases of static websites. The error handler for 404 is by default set to `error.html`. This will be exposed to the user as a parameter in the future.
Exposing a bucket along with other resources
If you want to expose a bucket along with other resources, such as an API Gateway, you can use the Router component.
Parameters
| Parameter | Description |
|---|---|
custom_domain |
The custom domain name for the static website. Optional. If provided, a DNS record will be created for the CloudFront distribution. Optional. A str. |
directory |
The directory containing the static website files to be uploaded to the S3 bucket. Optional. Either a Path like object or a str. |
Resources
| Resource | Description |
|---|---|
bucket |
The S3 bucket created for the static website. |
files |
The files uploaded to the S3 bucket for the static website. |
cloudfront_distribution |
The CloudFront distribution created for the static website. |