Terraform if statement with true or false - terraform

I need to prepare if statement. I am wondering what is the best solution for this?
locals {
prod_ingress_certyficate = "${prod_ingress_certyficate == "true" ? var.prod_cert : var.test_cert}"
}
Is it the correct way? If the variable is true then user prod_cert and if false then use test_cert.

You can't reference prod_ingress_certyficate before it is defined. But, you could create a variable called prod_ingress_certyficate which then you use in locals in your condition:
variable "prod_cert" {
default = "prod_cert"
}
variable "test_cert" {
default = "test_cert"
}
variable "prod_ingress_certyficate" {
default = true
}
locals {
prod_ingress_certyficate = var.prod_ingress_certyficate == true ? var.prod_cert : var.test_cert
}
output "test" {
value = local.prod_ingress_certyficate
}

Related

How can I split out an 'any' variable in terraform?

I'm trying to get multiple values out of an 'any' type variable. I'm new to terraform and open to recommendations. Specifically for this example, I'd like to know how I can output the 'bucket_name' value in my outputs.
variable "replica_config" {
type = any
default = {
role = "role_name"
rules = [
{
id = "full-s3-replication"
status = true
priority = 10
delete_marker_replication = false
destination = {
bucket = "bucket_name"
storage_class = "STANDARD"
replica_kms_key_id = "key_id"
account_id = "account_id"
replication_time = {
status = "Enabled"
minutes = 15
}
}
}
]
}
}
Current Output:
output "output4" {
value = flatten(var.replica_config["rules"])
}
Since you you have a list for rules, you can use a splat expression as such:
output "output4" {
value = var.replica_config.rules[*].destination.bucket
}
Keep in mind, the output of this expression will also be a list. If you want a single item instead of a list, you can use an index.
For example:
output "output4" {
value = var.replica_config.rules[0].destination.bucket
}

dynamic block in module parameters

I'm trying to create terraform that calls a module and I need to be able to include a dynamic block in the parameters of the module call
this is the sort of thing i'm trying to do
main.tf
module "eks" {
source = "../../modules/eks"
node_groups = [
{
name = "gp1"
gp_instance_count = 4
},
{
name = "gp2"
gp_instance_count = 2
}
]
}
variables.tf
variable "node_groups" {
type = list(object({
name = string
gp_instance_count = number
}))
}
eks.tf
module "eks" {
source = "terraform-aws-modules/eks/aws"
dynamic self_managed_node_groups {
for_each = var.node_groups
content {
self_managed_node_groups.value["name"] = {
capacity_rebalance = true
use_mixed_instances_policy = true
desired_size = self_managed_node_groups.value[".gp_instance_count"]
}
}
}
What I'm hoping for here is to iterate around var.node_groups and create a "self_managed_node_groups" section.
This would pass the following to the module
gp1 = {
capacity_rebalance = true
use_mixed_instances_policy = true
desired_size = 4
} ,
gp2 = {
capacity_rebalance = true
use_mixed_instances_policy = true
desired_size = 2
}
I'm getting the error
87: self_managed_node_groups.value["name"] = {
An argument or block definition is required here. To set an argument, use the
equals sign "=" to introduce the argument value.```
if I hardcode the self_managed_node_groups.value["name"] value then I get the error
Blocks of type "dynamic" are not expected here.
It feels like what I'm trying to do is quite straightforward and i'm just missing something simple.
I'd appreciate any help at all on this!

For_each loop with for expression based on value in map

Since the title is not descriptive enough let me introduce my problem.
I'm creating DRY module code for CDN that contains profile/endpoint/custom_domain.
Variable cdn_config would hold all necessary/optional parameters and these are created based on the for_each loop.
Variable looks like this:
variable "cdn_config" {
profiles = {
"profile_1" = {}
}
endpoints = {
"endpoint_1" = {
custom_domain = {
}
}
}
}
Core of this module is working - in the means that it would create cdn_profile "profile_1" then cdn_endpoint "endpoint_1" will be created and assigned to this profile then cdn_custom_domain will be created and assigned to "endpoint_1" since it's the part of "endpoint_1" map.
Then I realize, what in case I want to create "cdn_custom_domain" only and specify resource ID manually?
I was thinking that adding the optional parameter "standalone" could help, so it would look like this:
variable "cdn_config" {
profiles = {
"profile_1" = {}
}
endpoints = {
"endpoint_1" = {
custom_domain = {
}
}
"endpoint_standalone" = {
custom_domain = {
standalone = true
cdn_endpoint_id = "xxxxx"
}
}
}
}
Having this "standalone" parameter eq true "endpoint_standalone" map should be totally ignored from looping in the azurerm_cdn_endpoint resource creation.
So far this direction is my only guess, clearly, it's not working - if I add "endpoint_standalone" it complains that not all required parameters are specified so it's surely finding it.
resource "azurerm_cdn_endpoint" "this" {
for_each = {for k in keys(var.cdn_config.endpoints) : k => var.cdn_config.endpoints[k] if lookup(var.cdn_config.endpoints[k],"standalone",null) != "true"}
I would be grateful if you have a solution for this problem.
You are comparing a bool type to a string type, so the logical comparison will always return false:
for_each = {for k in keys(var.cdn_config.endpoints) : k => var.cdn_config.endpoints[k] if lookup(var.cdn_config.endpoints[k],"standalone",null) != true }
While we are here, we can also improve this for expression:
for_each = { for endpoint, params in var.cdn_config.endpoints : endpoint => params if lookup(params.custom_domain, "standalone", null) != true }

Terraform - override a single value in a map

I would like to know if it is possible to merge two map of maps without replacing the main map object.
My map object is defined as follows:
variable "apps" {
type = map(object({
is_enabled = bool
cost_center = string
}))
default = {}
}
locals {
default_apps = {
"api-1" = {
is_enabled = false
cost_center = "1234"
},
"api-2" = {
is_enabled = false
cost_center = "1235"
},
}
apps = merge(
local.default_apps,
var.apps
)
}
If define my tfars as follows, to override the value of api-1['s_enabled']
apps = {
"api-1" = {
is_enabled = true
}
}
I get the following error:
Error: Invalid value for input variable
The environment variable TF_VAR_apps does not contain a valid value for
variable "apps": element "api-1": attribute "cost_center" is required.
It works if I define my tfvars like so:
apps = {
"api-1" = {
is_enabled = true
cost_center = "1234"
}
}
My goal is to override a single value of one of the pre defined local variables under default_apps (e.x is_enabled) in tfvars.
Edit: requirements
The error is not about your merge but about your tfars. The following variable is invalid in your case:
apps = {
"api-1" = {
is_enabled = true
}
}
as you explicitly defined it as:
type = map(object({
is_enabled = bool
cost_center = string
}))
Your apps is missing cost_center which is required. If you use object type, everything that you specify in type definition must be provided:
Values that match the object type must contain all of the specified keys, and the value for each key must match its specified type.

terraform how to describe variable type with changing keys in object

I've got an ever changing list of objects as variable and wanted to know how to properly describe its type
variable "lifecycle_rules" {
type = set(object({
# set(object({
# action = map(string)
# condition = map(string)
# }))
}))
default = [
{
first = [
{
condition = {
age = "1"
}
action = {
type = "Delete"
}
},
{
condition = {
age = "2"
}
action = {
type = "Delete"
}
}
]},
{
second = [
{
condition = {
age = "3"
}
action = {
type = "Delete"
}
},
{
condition = {
age = "4"
}
action = {
type = "Delete"
}
}
]
}
]
}
Here should be line with smth like this string = set(object({...
the first and second are always changing, so key value should be
string but can't really set it - any other thoguhts, how to write
type for the default below ?
You are almost there. I think the correct one is:
type = set(
map(
set(
object({condition = map(string),
action = map(string)})
)
)
)
In the map you don't specify attributes, as they can be different. In the most inner one you have object as condition and action are constant.

Resources