Affects:
The current behavior of aws_lambda_function is to require that either the "filename" parameter is specified or the s3_-prefixed options (s3_bucket, s3_key, s3_version). It raises errors like the following if both are specified:
Error: aws_lambda_function.hello: "filename": conflicts with s3_bucket ("")
Error: aws_lambda_function.hello: "s3_bucket": conflicts with filename ("lambda.zip")
Error: aws_lambda_function.hello: "s3_key": conflicts with filename ("lambda.zip")
Error: aws_lambda_function.hello: "s3_object_version": conflicts with filename ("lambda.zip")
This makes it very difficult to create a module that creates lambda, yet wants to leave the possibility that the caller could still choose between a local or s3 file.
I propose that aws_lambda_function allow all of the parameters, but check that only one set of them has non-empty values. Thus, this would be acceptable:
resource "aws_lambda_function" "hello" {
filename = "lambda.zip"
s3_bucket = ""
s3_key = ""
s3_object_version = ""
* * *
Naturally, this would look like this in actual use:
resource "aws_lambda_function" "hello" {
filename = "${var.lambda_zip_file}"
s3_bucket = "${var.lambda_s3_bucket}"
s3_key = "${var.lambda_s3_key}"
s3_object_version = "${var.lambda_s3_object_version}"
* * *
If file name is non-empty and any of the S3-prefixed variables are non-empty, that would still be a clear violation that would generate an error.
Please do the above!
Voting for having this feature. It is very hard to create a module.
Hi folks ๐ This issue is resolved in Terraform 0.12, which supports new functionality in the configuration language aimed at solving this issue. The new null value can be used to omit arguments as if they were not defined in the configuration at all. For doing similar with configuration blocks, please see the new dynamic block syntax.
For example, given this configuration:
terraform {
required_providers {
aws = "2.20.0"
}
required_version = "0.12.5"
}
provider "aws" {
region = "us-east-1"
}
variable "filename" {
type = string
default = "test.zip"
}
variable "s3_bucket" {
type = string
default = null
}
variable "s3_key" {
type = string
default = null
}
resource "aws_iam_role" "test" {
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Principal = {
Service = "lambda.amazonaws.com"
}
Effect = "Allow"
Sid = ""
}]
})
}
resource "aws_iam_role_policy_attachment" "test" {
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
role = aws_iam_role.test.name
}
resource "aws_lambda_function" "test" {
depends_on = [aws_iam_role_policy_attachment.test]
filename = var.filename
function_name = "test"
role = aws_iam_role.test.arn
handler = "exports.example"
runtime = "nodejs8.10"
s3_bucket = var.s3_bucket
s3_key = var.s3_key
}
Produces the following plan output:
$ terraform apply
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_iam_role.test will be created
+ resource "aws_iam_role" "test" {
+ arn = (known after apply)
+ assume_role_policy = jsonencode(
{
+ Statement = [
+ {
+ Action = "sts:AssumeRole"
+ Effect = "Allow"
+ Principal = {
+ Service = "lambda.amazonaws.com"
}
+ Sid = ""
},
]
+ Version = "2012-10-17"
}
)
+ create_date = (known after apply)
+ force_detach_policies = false
+ id = (known after apply)
+ max_session_duration = 3600
+ name = (known after apply)
+ path = "/"
+ unique_id = (known after apply)
}
# aws_iam_role_policy_attachment.test will be created
+ resource "aws_iam_role_policy_attachment" "test" {
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
+ role = (known after apply)
}
# aws_lambda_function.test will be created
+ resource "aws_lambda_function" "test" {
+ arn = (known after apply)
+ filename = "test.zip"
+ function_name = "test"
+ handler = "exports.example"
+ id = (known after apply)
+ invoke_arn = (known after apply)
+ last_modified = (known after apply)
+ memory_size = 128
+ publish = false
+ qualified_arn = (known after apply)
+ reserved_concurrent_executions = -1
+ role = (known after apply)
+ runtime = "nodejs8.10"
+ source_code_hash = (known after apply)
+ source_code_size = (known after apply)
+ timeout = 3
+ version = (known after apply)
+ tracing_config {
+ mode = (known after apply)
}
}
Plan: 3 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_iam_role.test: Creating...
aws_iam_role.test: Creation complete after 1s [id=terraform-20190724063139347300000001]
aws_iam_role_policy_attachment.test: Creating...
aws_iam_role_policy_attachment.test: Creation complete after 0s [id=terraform-20190724063139347300000001-20190724063139783700000002]
aws_lambda_function.test: Creating...
aws_lambda_function.test: Creation complete after 8s [id=test]
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
Enjoy! ๐
I'm going to lock this issue because it has been closed for _30 days_ โณ. This helps our maintainers find and focus on the active issues.
If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. Thanks!
Most helpful comment
Hi folks ๐ This issue is resolved in Terraform 0.12, which supports new functionality in the configuration language aimed at solving this issue. The new
nullvalue can be used to omit arguments as if they were not defined in the configuration at all. For doing similar with configuration blocks, please see the newdynamicblock syntax.For example, given this configuration:
Produces the following plan output:
Enjoy! ๐