I really love Serverless for their ease of use--but a lot of enterprises are already integrated with Terraform. So, this Terraform module was designed to be as simple to use as Serverless by mirroring the structure of serverless.yml
.
Supported languages:
- Go
- Python
- Javascript
Supported Events:
- S3
- HTTP (API Gateway)
- Schedule (Cloudwatch Cron)
Similar to the serverless.yml
spec, functions are first class citizens. Then you define what triggers the function (http, schedule, etc.). The serverless.yml
structure is flattened at the events
name has been omitted. Look at the examples below for more clarity.
As seen in Example: Hello World Go
module "serverless" {
source = "rms1000watt/serverless-tf/aws"
functions = [
{
file = "main.go"
},
]
}
As seen in Example: Hello World Py
module "serverless" {
source = "rms1000watt/serverless-tf/aws"
functions = [
{
file = "main.py"
},
]
}
As seen in Example: Hello World JS
module "serverless" {
source = "rms1000watt/serverless-tf/aws"
functions = [
{
file = "main.js"
},
]
}
As seen in Example: HTTP Go
module "serverless" {
source = "rms1000watt/serverless-tf/aws"
functions = [
{
file = "main.go"
http_path = "hello-world"
},
]
}
Then test by running:
curl https://$API_DEPLOYMENT_ID.execute-api.$REGION.amazonaws.com/dev/hello-world
As seen in Example: Schedule Go
module "serverless" {
source = "rms1000watt/serverless-tf/aws"
functions = [
{
file = "main.go"
schedule_rate = "rate(1 minute)"
},
]
}
As seen in Example: S3 Go
module "serverless" {
source = "../.."
functions = [
{
file = "main.go"
s3_bucket = "org-x-super-cool-bucket"
},
]
}
As seen in Example: Regions Go
provider "aws" {
region = "us-west-2"
}
module "serverless" {
source = "../.."
functions = [
{
region = "us-east-1"
file = "../http-go/main.go"
schedule_rate = "rate(1 hour)"
http_path = "hello-world"
},
{
region = "us-east-2"
file = "../http-go/main.go"
schedule_rate = "rate(1 hour)"
http_path = "hello-world"
},
]
}
module "serverless" {
source = "rms1000watt/serverless-tf/aws"
functions = [
{
file = "main.go"
},
{
file = "main.go"
http_path = "hello-world"
schedule_rate = "rate(2 hours)"
},
{
file = "main.go"
schedule_rate = "rate(1 minute)"
},
{
file = "main.go"
http_path = "hello-world-again"
},
]
}
See Example: HTTP S3 Go for an example to override Lambda Role/Policy allowing it to connect to an S3 bucket.
As seen in Example: HTTP Authorizer Go
module "serverless" {
source = "../.."
functions = [
{
file = "main.go"
name = "authorizer-1"
vendor_cmd = "dep ensure"
},
{
file = "../hello-world-go/main.go"
http_path = "hello-world"
http_authorizer = "authorizer-1"
},
]
}
As seen in Example: HTTP Authorizer S3 Go to override authorizer with a custom policy.
Here are the options that each function supports.
module "serverless" {
source = "rms1000watt/serverless-tf/aws"
service = "" // optional (default: folder name)
stage = "" // optional (default: dev)
http_policy = "" // optional (default: "") (usage: Global API Gateway policy to restrict access)
functions = [
{
file = "main.go" // required (usage: relative path to file: main.go, ../main.go, path/to/main.go)
vendor_cmd = "dep ensure" // optional (default: "")
test_cmd = "go test ./..." // optional (default: "")
name = "" // optional (default: folder name + basename(file) + list_index, only required if this will be authorizer)
runtime = "" // optional (default: go1.x for *.go, python3.6 for *.py, nodejs8.10 for *.js)
handler = "" // optional (default: ${basename(file)})
rebuild = "" // optional (default: never)
role_arn = "" // optional (default: default role with cloudwatch access: role-lambda.json)
env_keys = "" // optional (default: "") (usage: space delimited list: "KEY1 KEY2 KEY3")
env_vals = "" // optional (default: "") (usage: space delimited list: "value1 value2 value3")
region = "" // optional (default: "") (usage: define a different region to deploy the function + events within)
http = "" // optional (default: "" unless any http_OPTS are defined)
http_path = "" // optional (default: lambda_name when http = true)
http_method = "" // optional (default: GET when http = true)
http_metrics = "" // optional (default: "" when http = true)
http_logging = "" // optional (default: "" when http = true)
http_authorizer = "" // optional (default: "" specify function name you want to use as CUSTOM REQUEST authorizer)
http_authorizer_policy_arn = "" // optional (default: "" specify policy arn if you need additional permissions)
schedule = "" // optional (default: "" unless any schedule_OPTS are defined)
schedule_rate = "" // optional (default: rate(1 hour))
s3_bucket = "" // optional (default: "") (usage: bucket must exist with this name)
s3_events = "" // optional (default: "s3:ObjectRemoved:* s3:ObjectCreated:* s3:ReducedRedundancyLostObject" when s3_bucket != "") (usage: space delimited list)
s3_prefix = "" // optional (default: "")
s3_suffix = "" // optional (default: "")
cloudwatch_event_pattern = "" // optional (default: "") (usage: a cloudwatch event pattern in a file or HEREDOC style)
},
]
}
Since this is a module, the ouput needs to be mapped from the module to your implementation. Many outputs have been stubbed out. Look at the outputs
directory for some stubs.
- Up to 5 functions per module (configurable.. update
generator.sh
then submit a PR) - No duplicate event-type per function (ie. only 1
http_path
per function) - Depth of 1 API Gateway path
- No dynamic path parameters in API Gateway
(Please contribute if you need this functionality)
An alternative approach for full Serverless functionality would be to create a Golang binary with file-packed templates that accepts and parses serverless.yml
as input and generates all the Terraform files as output. The trade-off is between limited functionality without changing your Terraform toolset or getting full functionality but changing your toolset/pipeline.
- SQS
- SNS
- Cloudwatch Event
- Cloudwatch Log
- Kinesis
- Dynamo
- Cognito