Skip to content
This repository was archived by the owner on Jun 8, 2022. It is now read-only.

Commit f581401

Browse files
Rafael Felix Correarafaelfelix
authored andcommitted
Support for lambda source from S3
this patch enables the module to allow defining the lambda function code from an s3_bucket and key, instead of locally.
1 parent b65918e commit f581401

File tree

7 files changed

+110
-8
lines changed

7 files changed

+110
-8
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,10 @@ function name unique per region, for example by setting
8585
| publish | Whether to publish creation/change as new Lambda Function Version | string | `"false"` | no |
8686
| reserved\_concurrent\_executions | The amount of reserved concurrent executions for this Lambda function | string | `"0"` | no |
8787
| runtime | The runtime environment for the Lambda function | string | n/a | yes |
88-
| source\_path | The source file or directory containing your Lambda source code | string | n/a | yes |
88+
| s3\_bucket | The S3 bucket location containing the function's deployment package. Required when `source_from_s3` = `true`. This bucket must reside in the same AWS region where you are creating the Lambda function. | string | - | no |
89+
| s3\_key | The S3 key of an object containing the function's deployment package. Required when `source_from_s3` = `true` | string | - | no |
90+
| source\_from\_s3 | Set this to true if fetching the Lambda source code from S3. | string | `false` | no |
91+
| source\_path | The source file or directory containing your Lambda source code. Ignored when `source_from_s3` = `true` | string | `` | no |
8992
| tags | A mapping of tags | map | `<map>` | no |
9093
| timeout | The amount of time your Lambda function had to run in seconds | string | `"10"` | no |
9194
| vpc\_config | VPC configuration for the Lambda function | map | `<map>` | no |

archive.tf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ locals {
55
# Generates a filename for the zip archive based on the contents of the files
66
# in source_path. The filename will change when the source code changes.
77
data "external" "archive" {
8+
count = "${var.source_from_s3 ? 0 : 1}"
89
program = ["python", "${path.module}/hash.py"]
910

1011
query = {
@@ -18,6 +19,7 @@ data "external" "archive" {
1819

1920
# Build the zip archive whenever the filename changes.
2021
resource "null_resource" "archive" {
22+
count = "${var.source_from_s3 ? 0 : 1}"
2123
triggers {
2224
filename = "${lookup(data.external.archive.result, "filename")}"
2325
}
@@ -34,7 +36,12 @@ resource "null_resource" "archive" {
3436
# deletes the Lambda function. If the file is rebuilt here, the build
3537
# output is unfortunately invisible.
3638
data "external" "built" {
39+
<<<<<<< HEAD
3740
program = ["python", "${path.module}/built.py"]
41+
=======
42+
count = "${var.source_from_s3 ? 0 : 1}"
43+
program = ["${path.module}/built.py"]
44+
>>>>>>> Support for lambda source from S3
3845
3946
query = {
4047
build_command = "${lookup(data.external.archive.result, "build_command")}"

lambda.tf

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
resource "aws_lambda_function" "lambda" {
2-
count = "${! var.attach_vpc_config && ! var.attach_dead_letter_config ? 1 : 0}"
2+
count = "${! var.attach_vpc_config && ! var.attach_dead_letter_config && ! var.source_from_s3 ? 1 : 0}"
33

44
# ----------------------------------------------------------------------------
55
# IMPORTANT:
@@ -33,13 +33,40 @@ resource "aws_lambda_function" "lambda" {
3333
environment = ["${slice( list(var.environment), 0, length(var.environment) == 0 ? 0 : 1 )}"]
3434
}
3535

36+
resource "aws_lambda_function" "lambda_s3" {
37+
count = "${var.source_from_s3 && ! var.attach_vpc_config && ! var.attach_dead_letter_config ? 1 : 0}"
38+
39+
function_name = "${var.function_name}"
40+
description = "${var.description}"
41+
role = "${aws_iam_role.lambda.arn}"
42+
handler = "${var.handler}"
43+
memory_size = "${var.memory_size}"
44+
reserved_concurrent_executions = "${var.reserved_concurrent_executions}"
45+
runtime = "${var.runtime}"
46+
timeout = "${var.timeout}"
47+
tags = "${var.tags}"
48+
49+
s3_bucket = "${var.s3_bucket}"
50+
s3_key = "${var.s3_key}"
51+
52+
# The aws_lambda_function resource has a schema for the environment
53+
# variable, where the only acceptable values are:
54+
# a. Undefined
55+
# b. An empty list
56+
# c. A list containing 1 element: a map with a specific schema
57+
# Use slice to get option "b" or "c" depending on whether a non-empty
58+
# value was passed into this module.
59+
60+
environment = ["${slice( list(var.environment), 0, length(var.environment) == 0 ? 0 : 1 )}"]
61+
}
62+
3663
# The vpc_config and dead_letter_config variables are lists of maps which,
3764
# due to a bug or missing feature of Terraform, do not work with computed
3865
# values. So here is a copy and paste of of the above resource for every
3966
# combination of these variables.
4067

4168
resource "aws_lambda_function" "lambda_with_dl" {
42-
count = "${var.attach_dead_letter_config && ! var.attach_vpc_config ? 1 : 0}"
69+
count = "${var.attach_dead_letter_config && ! var.attach_vpc_config && ! var.source_from_s3 ? 1 : 0}"
4370

4471
dead_letter_config {
4572
target_arn = "${var.dead_letter_config["target_arn"]}"
@@ -66,7 +93,7 @@ resource "aws_lambda_function" "lambda_with_dl" {
6693
}
6794

6895
resource "aws_lambda_function" "lambda_with_vpc" {
69-
count = "${var.attach_vpc_config && ! var.attach_dead_letter_config ? 1 : 0}"
96+
count = "${var.attach_vpc_config && ! var.attach_dead_letter_config && ! var.source_from_s3 ? 1 : 0}"
7097

7198
vpc_config {
7299
security_group_ids = ["${var.vpc_config["security_group_ids"]}"]
@@ -94,7 +121,7 @@ resource "aws_lambda_function" "lambda_with_vpc" {
94121
}
95122

96123
resource "aws_lambda_function" "lambda_with_dl_and_vpc" {
97-
count = "${var.attach_dead_letter_config && var.attach_vpc_config ? 1 : 0}"
124+
count = "${var.attach_dead_letter_config && var.attach_vpc_config && ! var.source_from_s3 ? 1 : 0}"
98125

99126
dead_letter_config {
100127
target_arn = "${var.dead_letter_config["target_arn"]}"

outputs.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
output "function_arn" {
22
description = "The ARN of the Lambda function"
3-
value = "${element(concat(aws_lambda_function.lambda.*.arn, aws_lambda_function.lambda_with_dl.*.arn, aws_lambda_function.lambda_with_vpc.*.arn, aws_lambda_function.lambda_with_dl_and_vpc.*.arn), 0)}"
3+
value = "${element(concat(aws_lambda_function.lambda.*.arn, aws_lambda_function.lambda_s3.*.arn, aws_lambda_function.lambda_with_dl.*.arn, aws_lambda_function.lambda_with_vpc.*.arn, aws_lambda_function.lambda_with_dl_and_vpc.*.arn), 0)}"
44
}
55

66
output "function_name" {
77
description = "The name of the Lambda function"
8-
value = "${element(concat(aws_lambda_function.lambda.*.function_name, aws_lambda_function.lambda_with_dl.*.function_name, aws_lambda_function.lambda_with_vpc.*.function_name, aws_lambda_function.lambda_with_dl_and_vpc.*.function_name), 0)}"
8+
value = "${element(concat(aws_lambda_function.lambda.*.function_name, aws_lambda_function.lambda_s3.*.arn, aws_lambda_function.lambda_with_dl.*.function_name, aws_lambda_function.lambda_with_vpc.*.function_name, aws_lambda_function.lambda_with_dl_and_vpc.*.function_name), 0)}"
99
}
1010

1111
output "function_qualified_arn" {

tests/s3-bucket-key/lambda.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
def lambda_handler(event, context):
2+
return 'test passed'

tests/s3-bucket-key/main.tf

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
terraform {
2+
backend "local" {
3+
path = "terraform.tfstate"
4+
}
5+
}
6+
7+
provider "aws" {
8+
region = "eu-west-1"
9+
}
10+
11+
resource "random_id" "name" {
12+
byte_length = 6
13+
prefix = "terraform-aws-lambda-s3-"
14+
}
15+
16+
resource "aws_s3_bucket" "b" {
17+
bucket = "${random_id.name.hex}"
18+
acl = "private"
19+
}
20+
data "archive_file" "l" {
21+
type = "zip"
22+
source_file = "${path.module}/lambda.py"
23+
output_path = "${path.module}/lambda.zip"
24+
}
25+
26+
resource "aws_s3_bucket_object" "o" {
27+
bucket = "${aws_s3_bucket.b.id}"
28+
key = "lambda.zip"
29+
source = "${path.module}/lambda.zip"
30+
}
31+
32+
module "lambda" {
33+
source = "../../"
34+
35+
function_name = "terraform-aws-lambda-test-s3-bucket-key"
36+
description = "Test S3 bucket and key in terraform-aws-lambda"
37+
handler = "lambda.lambda_handler"
38+
memory_size = 128
39+
reserved_concurrent_executions = 3
40+
runtime = "python3.6"
41+
timeout = 30
42+
43+
source_from_s3 = true
44+
s3_bucket = "${aws_s3_bucket.b.id}"
45+
s3_key = "${aws_s3_bucket_object.o.id}"
46+
}

variables.tf

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ variable "timeout" {
3232
}
3333

3434
variable "source_path" {
35-
description = "The source file or directory containing your Lambda source code"
35+
description = "The source file or directory containing your Lambda source code. Ignored when `source_from_s3` = `true`"
3636
type = "string"
37+
default = ""
3738
}
3839

3940
variable "build_command" {
@@ -84,6 +85,22 @@ variable "attach_vpc_config" {
8485
default = false
8586
}
8687

88+
variable "source_from_s3" {
89+
description = "Set this to true if fetching the Lambda source code from S3."
90+
type = "string"
91+
default = false
92+
}
93+
94+
variable "s3_bucket" {
95+
description = "The S3 bucket location containing the function's deployment package. Required when `source_from_s3` = `true`. This bucket must reside in the same AWS region where you are creating the Lambda function."
96+
type = "string"
97+
}
98+
99+
variable "s3_key" {
100+
description = "The S3 key of an object containing the function's deployment package. Required when `source_from_s3` = `true`"
101+
type = "string"
102+
}
103+
87104
variable "tags" {
88105
description = "A mapping of tags"
89106
type = "map"

0 commit comments

Comments
 (0)