dempti
dempti

Reputation: 346

using for each with terraform version upgrade from 0.12 to 0.13

I am working on version upgrade of terraform from 0.12 to 0.13. So far I am able to create the necessary pieces by changing providers as well as my modules.

Current Status of service.tf

module "services" {
  source   = "../../modules/aws-ecs-servicev2"
  for_each = var.applications

  container_name               = each.value.container_name
  container_cpu                = each.value.container_cpu
  container_image              = each.value.container_image
  container_memory_total       = each.value.container_memory_total
  container_memory_reservation = each.value.container_memory_reservation
  deployment_max_percent       = each.value.deployment_max_percent
  deployment_min_healthy       = each.value.deployment_min_healthy
  container_host_port          = each.value.container_host_port
  container_port               = each.value.container_port
  command                      = each.value.command
  replica_count                = each.value.replica_count
  stage                        = each.value.stage
  alb_enabled                  = each.value.alb_enabled
  alb_subnets                  = module.vpc.public_subnets
  alb_https_enabled            = each.value.alb_https_enabled
  alb_ssl_arn                  = each.value.alb_ssl_arn
  health_check_path            = each.value.health_check_path
  internal_lb                  = each.value.health_check_path
  vault_key                    = each.value.vault_key
  vault_backend                = each.value.vault_backend
  cpu_based_autoscaling        = each.value.cpu_based_autoscaling
  target_cpu_value             = each.value.target_cpu_value
  max_capacity                 = each.value.max_capacity
  min_capacity                 = each.value.min_capacity
  scale_out_adjustment         = each.value.scale_out_adjustment
  scale_out_cooldown           = each.value.scale_out_cooldown
  scale_in_adjustment          = each.value.scale_in_adjustment
  scale_in_cooldown            = each.value.scale_in_cooldown
  disable_scale_in             = each.value.disable_scale_in
  ecs_arn                      = module.ecs.arn
  namespace                    = var.namespace
  sd_namespace_id              = aws_service_discovery_private_dns_namespace.default.id
  vpc_id                       = module.vpc.vpc_id
  health_check_response        = "200"
  alb_sgs                      = [aws_security_group.ecs_sg.id]
}

and application.tf

variable "applications" {
  description = "Map for the services to be deployed"
  type        = any
  default = {
    service-a = {
      container_cpu                = 512
      container_image              = service-a-image:latest
      container_memory_total       = 2048
      container_memory_reservation = 1024
      container_name               = "service-a"
      command                      = null
      deployment_max_percent       = 200
      deployment_min_healthy       = 50
      container_host_port          = [0]
      container_port               = [80]
      replica_count                = 1
      stage                        = "dev"
      health_check_path            = null
      internal_lb                  = false
      vault_key                    = null
      vault_backend                = null
      alb_enabled                  = false
      alb_ssl_arn                  = null
      alb_https_enabled            = false
      cpu_based_autoscaling        = false
      target_cpu_value             = null
      max_capacity                 = null
      min_capacity                 = null
      scale_out_adjustment         = null
      scale_out_cooldown           = null
      scale_in_adjustment          = null
      scale_in_cooldown            = null
      disable_scale_in             = false
    }
  }
}

What I want to achieve?

Is it possible to pass somehow default values to few of the variables such as health_check_path= null so that I do not have to worry about the not including this in services which do not require these values. There are also some services which does require such values which I will then provide from the same variables. Example

    service-b = {
      container_name               = "service-b-container"
      container_cpu                = 1024
      container_image              = "service-b-image:latest"
      container_memory_total       = 1024
      container_memory_reservation = 1024
      deployment_max_percent       = 200
      deployment_min_healthy       = 50
      container_host_port          = [0]
      container_port               = [80]
      command                      = null
      replica_count                = 1
      stage                        = "dev"
      alb_enabled                  = true
      alb_https_enabled            = true
      alb_ssl_arn                  = "ssl-arn"
      health_check_response        = 200
      health_check_path            = "/status"
      internal_lb                  = false
      vault_key                    = "servia-b"
      vault_backend                = "service"
      cpu_based_autoscaling        = true
      target_cpu_value             = 40
      max_capacity                 = 8
      min_capacity                 = 1
      scale_out_adjustment         = 2
      scale_out_cooldown           = 60
      scale_in_adjustment          = 1
      scale_in_cooldown            = 300
      disable_scale_in             = false
    },

I tried using local or any other such variables inside the variable section like follwing


variable "cpu" {
  type = number
  default = 1024
  description = "cpu to associate"
}

variable "applications" {
  description = "Map for the services to be deployed"
  type        = any
  default = {
  service-b = {
      container_name               = "service-b-container"
      container_cpu                = var.cpu
      container_image              = "service-b-image:latest"
      container_memory_total       = 1024
      container_memory_reservation = 1024
  },
  service-a = {
      container_name               = "service-a-container"
      container_cpu                = var.cpu
      container_image              = "service-b-image:latest"
      container_memory_total       = 1024
  }
 }
}

but turns out terraform does not allow that. To elaborate on this, let me add it's log here

Error: Variables not allowed

  on application.tf line 56, in variable "applications":
  56:       container_cpu        = var.cpu

Variables may not be used here.

If I try by not including the variables which are present in my services.tf then I get the followiing error

Acquiring state lock. This may take a few moments...                                                                                                                                                                                                                                                                                       
Refreshing Terraform state in-memory prior to plan...                                                                                                                                                                                                                                                                                      
The refreshed state will be used to calculate this plan, but will not be                                                                                                                                                                                                                                                                   
persisted to local or remote state storage.                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                           
module.services["service-a"].module.ecs_alb_service_task.data.aws_iam_policy_document.ecs_exec[0]: Refreshing state...                                                                                                                                                                                                            
module.services["service-a"].module.ecs_alb_service_task.data.aws_iam_policy_document.ecs_service_policy[0]: Refreshing state...                                                                                                                                                                                                  
module.services["service-a"].module.ecs_alb_service_task.data.aws_iam_policy_document.ecs_task_exec[0]: Refreshing state...                                                                                                                                                                                                       
module.services["service-a"].module.ecs_alb_service_task.data.aws_iam_policy_document.ecs_task[0]: Refreshing state...                                                                                                                                                                                                            
module.services["service-a"].module.ecs_alb_service_task.data.aws_iam_policy_document.ecs_service[0]: Refreshing state...                                                                                                                                                                                                         
module.vpc.aws_vpc.this[0]: Refreshing state... [id=vpc-0641c1d3435df195a]                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
aws_service_discovery_private_dns_namespace.default: Refreshing state... [id=ns-vyggm2ltoxjufhfa]                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                           
Error: Unsupported attribute                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                                           
  on Service.tf line 22, in module "services":                                                                                                                                                                                                                                                                                             
  22:   alb_enabled                  = each.value.alb_enabled                                                                                                                                                                                                                                                                              
    |----------------                                                                                                                                                                                                                                                                                                                      
    | each.value is object with 12 attributes                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                           
This object does not have an attribute named "alb_enabled".                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                                                           
Error: Unsupported attribute                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                                           
  on Service.tf line 25, in module "services":                                                                                                                                                                                                                                                                                             
  25:   alb_https_enabled            = each.value.alb_https_enabled                                                                                                                                                                                                                                                                        
    |----------------                                                                                                                                                                                                                                                                                                                      
    | each.value is object with 12 attributes                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                           
This object does not have an attribute named "alb_https_enabled".                                                                                                                                                                                                                                                                          
                                                                      

Is there anyway I can achieve this, since there are more than 10 services which needs to be deployed in this way, also some services lack the variable while the other requires.

Upvotes: 0

Views: 547

Answers (1)

Encho Solakov
Encho Solakov

Reputation: 151

Option 1. Based on the documentation this could help - declaring some special object type and there you could set default values: https://www.terraform.io/docs/configuration/variables.html#declaring-an-input-variable

Option 2Also may be this could help (have not tried it) - using lookup with default value https://www.terraform.io/docs/configuration/functions/lookup.html

Simple example for option 2:

child module:

main.tf

resource "local_file" "simple_file" {
  filename = "file/${var.file_name}"
  content     = "foo!"
}

variables.tf

variable "file_name" {
  description = "file name"
}

root module: main.tf

module "file" {
  source = "./child_module"
  for_each = var.applications
  file_name = lookup(each.value, "Not_existing_key", "default_value" )
}

default_value is used in this case in the child module

terraform version 0.14.3

Upvotes: 3

Related Questions