Guys,
I have been troubles in use my AWS S3 module, when I set a variable policy turns mandatory. Someone with more experience using Terraform module know a way to do this var optional again?
I have been try use some feature like:
main.tf
- jsonencode(var.policy),
- lookup(var.policy, “policy”, null),
- file(var.policy)
and
var.tf
- without declare type
- with
type = string
- without declare default value
- with
default = ""
- with
default = null
- with
default = { }
And when I try run terraform apply
doesn’t work. I got errors like:
- Error: Error putting S3 policy: MalformedPolicy: Missing required field Statement
- Error: Error putting S3 policy: MalformedPolicy: Policies must be valid JSON and the first byte must be ‘{’
- Error: No value for required variable
-
Error: Invalid function argument
on main.tf line 3, in resource “aws_s3_bucket_policy” “sbp”:
3: policy = file(var.policy)
|----------------
| var.policy is “”
Invalid value for “path” parameter: failed to read …
Hi @weyderfs,
If I’m understanding correctly what you’ve reported here, it sounds like Terraform isn’t considering the variable to be mandatory but your module isn’t correctly handling the case where it isn’t set. If you declare a variable as optional then you must take care each time you use that value elsewhere in the configuration to explain what the behavior should be when the caller doesn’t set the value.
In this context I’m guessing that your goal is to only declare an aws_s3_bucket_policy
object when var.policy
is set, and otherwise to not create any policy at all. Here’s one way to declare that:
variable "policy_file" {
type = string
default = null
}
resource "aws_s3_bucket_policy" "sbp" {
count = var.policy_file != null ? 1 : 0
policy = file(var.policy_file)
# ...
}
This declares that if var.policy
is null
(its default value) then there should be zero policy objects.
Another design I’d consider here is to let the caller pass in a policy document directly, rather than a file containing one, and let the caller be the one to decide where that policy JSON comes from. The caller could then write it inline if desired, or request it from a remote API, or generate it using the aws_iam_policy_document
data source.
variable "policy_json" {
type = string
default = null
}
resource "aws_s3_bucket_policy" "sbp" {
count = var.policy_json != null ? 1 : 0
policy = var.policy_json
# ...
}
From the perspective of the calling module, then:
module "example" {
source = "./modules/example"
policy_json = file("${path.module}/policy.json")
}
1 Like
@apparentlymart thanks for share you knowledge you example of use count solve my case and now I know how handle this scenario.
1 Like