Create main vars with nested vars

38 Views Asked by At

I'm configuring a terraform module with lambda and VPC endpoint deployment, and currently, I would like to use more cleaner way of defining and accessing the vars in the code

S3 vars are used for creating lambda function aws resource and vpc endpoint vars for creating aws_vpc_endpoint resource

Below are my local vars which have the same conditions

Is it possible to somehow create one var for s3 and a second one for vpc endpoint where I can apply only one condition to the entire var without duplicating?

 s3_bucket         = var.s3_existing_package != null ? try(var.s3_existing_package.bucket, null) : null
 s3_key            = var.s3_existing_package != null ? try(var.s3_existing_package.key, null) : null
 s3_object_version = var.s3_existing_package != null ? try(data.aws_s3_object.this.version_id, null) : null

 ## VPC endpoint
 vpc_id                                     = var.enable_api_gw && var.api_gw_endpoint_type == "PRIVATE" ? try(var.vpc_id, null) : null
 vpc_endpoint_subnet_ids                    = var.enable_api_gw && var.api_gw_endpoint_type == "PRIVATE" ? try(var.vpc_endpoint_subnet_ids, null) : null
 vpc_endpoint_default_sg_allowed_cidrs      = var.enable_api_gw && var.api_gw_endpoint_type == "PRIVATE" ? try(var.vpc_endpoint_default_sg_allowed_cidrs, null) : null
 vpc_endpoint_additional_security_group_ids = var.enable_api_gw && var.api_gw_endpoint_type == "PRIVATE" ? try(var.vpc_endpoint_additional_security_group_ids, []) : []
2

There are 2 best solutions below

0
Helder Sepulveda On

https://developer.hashicorp.com/terraform/language/values/locals#declaring-a-local-value

The expressions in local values are not limited to literal constants; they can also reference other values in the module in order to transform or combine them, including variables, resource attributes, or other local values:

Here is one example using your code

variable "existing" {
  default = true
}

locals {
  s3 = var.existing != null ? {
    bucket         = "foo"
    key            = "x"
    object_version = "123"
  } : null
}

output "s3" {
  value = local.s3
}

and a terraform plan on that will show


Changes to Outputs:
  + s3 = {
      + bucket         = "foo"
      + key            = "x"
      + object_version = "123"
    }

My recommendation, start simple like that one variable one local and output, complicate that local as much as you want to test then bring it to your project and integrate with the rest of your resources, the same try as you have should be no problem

0
itshagunrathore On

In this case you can define local blocks for your s3 and vpc endpoints.

locals {
   s3_vars = var.existing != null ? {
   bucket         =  try(var.s3_existing_package.bucket, null)
   key            =  try(var.s3_existing_package.key, null)
   object_version =  try(var.s3_existing_package.key, null)
  } : {
   bucket         = null
   key            = null
   object_version = null
   }
}

And your resource block would be like :

resource "aws_lambda_function" "example" {
  s3_bucket         = local.s3_vars.bucket
  s3_key            = local.s3_vars.key
  s3_object_version = local.s3_vars.object_version
}