Skip to content

!Rain::S3 and !Rain::S3Http

These directives upload a local file or directory to the artifact bucket and insert its location into the template.

Illustrative output

These directives upload to S3, so the tests cannot run them without AWS. The packaged output on this page is illustrative. Your bucket name and object keys will be different.

How uploads work

  • If the path is a directory, cfnrain zips it first. Zip: true also zips a single file.
  • The object key is the SHA-256 hash of the content that cfnrain uploads, as hex. If you set --s3-prefix, the key starts with that prefix. Extension adds a file extension.
  • A file that did not change gets the same key, so CloudFormation sees no change. A zip file also stores the modification time of each file. If a build or a fresh checkout touches the files, the zip gets a new key, and CloudFormation updates the resource.
  • Paths are relative to the template file.
  • cfnrain uploads each path only once per run, also when the template uses it many times.

!Rain::S3

The short form takes a path and inserts the S3 URI:

Resources:
  Job:
    Type: AWS::Glue::Job
    Properties:
      Command:
        Name: glueetl
        ScriptLocation: !Rain::S3 etl/job.py

The packaged template:

Resources:
  Job:
    Type: AWS::Glue::Job
    Properties:
      Command:
        Name: glueetl
        ScriptLocation: s3://rain-artifacts-123456789012-eu-west-1/9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08

!Rain::S3Http

!Rain::S3Http <path> uploads the same way and inserts the HTTPS URL of the object:

Resources:
  Api:
    Type: AWS::Serverless::Api
    Properties:
      StageName: prod
      DefinitionUri: !Rain::S3Http openapi.yaml

The packaged template:

Resources:
  Api:
    Type: AWS::Serverless::Api
    Properties:
      StageName: prod
      DefinitionUri: https://rain-artifacts-123456789012-eu-west-1.s3.eu-west-1.amazonaws.com/a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e

The object form

Give !Rain::S3 a map instead of a path to control the upload and the output:

Resources:
  Function:
    Type: AWS::Lambda::Function
    Properties:
      Runtime: python3.13
      Handler: index.main
      Role: !GetAtt FunctionRole.Arn
      Code: !Rain::S3
        Path: lambda-src
        Run: build.sh
        BucketProperty: S3Bucket
        KeyProperty: S3Key

The packaged template:

Resources:
  Function:
    Type: AWS::Lambda::Function
    Properties:
      Runtime: python3.13
      Handler: index.main
      Role: !GetAtt FunctionRole.Arn
      Code:
        S3Bucket: rain-artifacts-123456789012-eu-west-1
        S3Key: 1b4844dacc843f09941c11c94f80981d3be8ae7578952c71e875ef7add37b1a7

Options

Option Value What it does
Path A file or directory The content to upload. Required.
Zip true or false Zip the path even when it is a single file. The default is false. A directory is always zipped.
BucketProperty A property name With Format: Object, the name of the property that gets the bucket name
KeyProperty A property name With Format: Object, the name of the property that gets the object key
Format URI, Http or Object What to insert. See Format.
Run A script path A script that cfnrain runs before the upload. See Run.
Extension For example zip or sh Add .<Extension> to the object key

Format

Format Output
URI s3://<bucket>/<key>
Http https://<bucket>.s3.<region>.amazonaws.com/<key>
Object A map with the bucket in BucketProperty and the key in KeyProperty

If you do not set Format, the default depends on the other options. When you set both BucketProperty and KeyProperty, the default is Object. Otherwise the default is URI.

The values are case sensitive. Write URI, not Uri. With Format: Uri, packaging stops with unexpected S3 output format: Uri. The cfnrain pkg help text, inherited from Rain, still shows Uri, which is wrong. See Known issues.

Format: Object without both property names stops with missing BucketProperty or KeyProperty.

Run

Run names a script, relative to the template file. cfnrain runs it in the template's directory before the upload, with no arguments. Use it to build the content that Path points to:

#!/bin/sh
# build.sh
set -e
rm -rf lambda-src
mkdir lambda-src
cp src/*.py lambda-src/
pip install -r requirements.txt -t lambda-src

The script must be executable. If it fails, packaging stops. cfnrain shows the script output only with --debug.

Templates run code

Run executes a program from your computer when you package the template. See Templates can run code.

Extension

Some services need a file extension on the object key. Extension adds it:

Resources:
  Document:
    Type: AWS::SSM::Document
    Properties:
      DocumentType: Command
      Attachments:
        - Key: SourceUrl
          Values:
            - !Rain::S3
              Path: scripts/setup.sh
              Extension: sh

The packaged template:

Resources:
  Document:
    Type: AWS::SSM::Document
    Properties:
      DocumentType: Command
      Attachments:
        - Key: SourceUrl
          Values:
            - s3://rain-artifacts-123456789012-eu-west-1/5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03.sh