A Terraform equivalent to CloudFormations AWS::NoValue ?
Sometimes, when using an infrastructure as code tool like Terraform or CloudFormation,
you only want to include a property on a resource under certain
conditions, while always including the resource itself. In AWS CloudFormation there are a few
CloudFormation Conditional Patterns
that let you do this, but and this is the central point of this post,
what’s the Terraform equivalent of using AWS::NoValue
to remove a property?
Here’s an example of doing this in CloudFormation. If InProd
is false
the Iops
property is completely removed from the resource. Not set to undef, no
NULLs, simply not included at all.
"MySQL" : {
"Type" : "AWS::RDS::DBInstance",
"DeletionPolicy" : "Snapshot",
"Properties" : {
... snip ...
"Iops" : {
"Fn::If" : [ "InProd",
"1000",
{ "Ref" : "AWS::NoValue" }
]
}
... snip ...
}
}
While Terraform allows you to use the, um, ‘inventive’, count
meta-parameter
to control if an entire resource is present or not -
resource "aws_security_group_rule" "example" {
count = "${var.create_rule}"
... snip ...
}
It doesn’t seem to have anything more fine grained.
One example of when I’d want to use this is writing an RDS module. I want
nearly all the resource properties to be present every time I use
the module, but not all of them. I’d only want replicate_source_db
or
snapshot_identifier
to be present when a certain variable
was passed in.
Here’s a horrific example of what I mean
resource "aws_db_instance" "default" {
... snip ...
# these properties are always present
storage_type = "gp2"
parameter_group_name = "default.mysql5.6"
# and then the optional one
replicate_source_db = "${var.replication_primary | absent_if_null}"
... snip ...
}
But with a nice syntax rather than that horrible made up one above. Does
anyone know how to do this? Do I need to write either two nearly
identical modules, with one param different or slightly better, have two
database resources, one with the extra parameter present and use a
count
to choose one of those? Help me Obi-internet! Is these a better way to
do this?