skip to Main Content

While creating auto_scaling_group with terraform, error showing:

omkar@kws MINGW64 ~/repo/kiwi-infra (main)
$ terraform validate
╷
│ Error: Unsupported attribute
│
│   on main.tf line 46, in module "asg":
│   46:   tg = "${module.alb.tg}"
│     ├────────────────
│     │ module.alb is a list of object
│
│ Can't access attributes on a list of objects. Did you mean to access attribute "tg" for a specific element of the list, or across all elements of the list?

and my code goes as below:

alb module:

resource "aws_lb_target_group" "kiwi-dev-tg" {
  health_check {
    interval            = 10
    path                = "/"
    protocol            = "HTTP"
    timeout             = 5
    healthy_threshold   = 3
    unhealthy_threshold = 2
  }

  name        = "${var.project}-dev-tg"
  port        = 80
  protocol    = "HTTP"
  target_type = "instance"
  vpc_id      = "${var.vpc-id}"
}

asg module:

resource "aws_autoscaling_group" "asg" {
  launch_configuration = "${aws_launch_configuration.launch-conf.name}"
  vpc_zone_identifier  = ["${var.sn1}","${var.sn2 }"]
  target_group_arns    = "${var.tg}"
  health_check_type    = "ELB"

asg variables:

variable "tg" {}

alb output file:

output "tg" {
  value = aws_lb_target_group.kiwi-dev-tg.arn
}

main.tf

module "asg" {
  source = "./modules/asg"
  project = "${var.project}"
  app-sg = "${module.vpc.app-sg}"
  sn1 = "${module.vpc.sn1}"
  sn2 = "${module.vpc.sn2}"
  tg = "${module.alb.tg}"
}

ALB

module "alb" {
  source    = "./modules/alb"
  project = "${var.project}"
  vpc-id = "${module.vpc.vpc-id}"
  count = "${length(module.ec2.app)}"
  app = "${element(module.ec2.app, count.index)}" 
  #app01 = "${module.ec2.app01}"
  #app02 = "${module.ec2.app02}"
  alb-sg = "${module.vpc.alb-sg}"
  sn1 = "${module.vpc.sn1}"
  sn2 = "${module.vpc.sn2}"
}

2

Answers


  1. You are trying to pass a string interpolated version of the output as a variable that is to be read as a list in module.asg. So the output is fine, but you need to change how it is passed to then used in module.asg. The main issues are that your are not referencing the specific instance of module.alb (implemented with count) and you are passing a single string for target_group_arns where a list is expected.

    The module implementation in main.tf should look like:

    module "asg" {
      source  = "./modules/asg"
      project = var.project
      app-sg  = module.vpc.app-sg
      sn1     = module.vpc.sn1
      sn2     = module.vpc.sn2
      tg      = module.alb[*].tg
    }
    

    Then the resource in modules/asg/asgmod.tf should look like:

    resource "aws_autoscaling_group" "asg" {
      launch_configuration = aws_launch_configuration.launch-conf.name
      vpc_zone_identifier  = [var.sn1, var.sn2]
      target_group_arns    = var.tg # or [var.tf] if you pass single
      health_check_type    = "ELB"
    
      min_size = 2
      max_size = 4
    
      tag {
        key                 = "name"
        value               = "${var.project}-dev-asg"
        propagate_at_launch = true
      }
    }
    

    Notice the [var.tg] because aws_autoscaling_group target_group_arns expects a list. So if you choose module.alb[0].tg for example [var.tg] will be needed, but if you use module.alb[*].tg, then var.tg will work.


    In addition, I think it would be a bit more clear to have in module/alb/outputs.tf:

    output "target_group_arn" {
      value = aws_lb_target_group.kiwi-dev-tg.arn
    }
    

    Then in modules/asg/vars.tf:

    variable "target_group_arns" {
      type    = list(string)
      default = []
    }
    

    In modules/asg/asgmod.tf:

    resource "aws_autoscaling_group" "asg" {
      launch_configuration = aws_launch_configuration.launch-conf.name
      vpc_zone_identifier  = [var.sn1, var.sn2]
      target_group_arns    = var.target_group_arns
      health_check_type    = "ELB"
    
      min_size = 2
      max_size = 4
    
      tag {
        key                 = "name"
        value               = "${var.project}-dev-asg"
        propagate_at_launch = true
      }
    }
    

    And lastly, in main.tf:

    module "asg" {
      source            = "./modules/asg"
      project           = var.project
      app-sg            = module.vpc.app-sg
      sn1               = module.vpc.sn1
      sn2               = module.vpc.sn2
      target_group_arns = module.alb[*].target_group_arn
    }
    

    That seems more clear to me.

    Login or Signup to reply.
  2. Since you have a module call to the ALB which is using the count meta-argument, that means you will have to either reference a specific index of the module (because it becomes a list) or you will need to use the same count meta-argument in the module call for ASG. For example:

    module "asg" {
      source = "./modules/asg"
      project = "${var.project}"
      app-sg = "${module.vpc.app-sg}"
      sn1 = "${module.vpc.sn1}"
      sn2 = "${module.vpc.sn2}"
      tg = "${module.alb[0].tg}" # or any other index that falls into [0, length(module.ec2.app) - 1]
    }
    

    If you need a separate ASG for every TG and app, then you need this:

    module "asg" {
      count = "${length(module.ec2.app)}"
      source = "./modules/asg"
      project = "${var.project}"
      app-sg = "${module.vpc.app-sg}"
      sn1 = "${module.vpc.sn1}"
      sn2 = "${module.vpc.sn2}"
      tg = "${module.alb[count.index].tg}"
    }
    

    As a side note, you are using the old terraform interpolation syntax, which should be changed to:

    module "asg" {
      count = length(module.ec2.app)
      source = "./modules/asg"
      project = var.project
      app-sg = module.vpc.app-sg
      sn1 = module.vpc.sn1
      sn2 = module.vpc.sn2
      tg = module.alb[count.index].tg
    }
    

    Additionally, the target_group_arns argument is supposed to be a list, so you would have to update the ASG module as well to take that into account:

    resource "aws_autoscaling_group" "asg" {
      launch_configuration = "${aws_launch_configuration.launch-conf.name}"
      vpc_zone_identifier  = ["${var.sn1}","${var.sn2 }"]
      target_group_arns     = ["${var.tg}"]
      health_check_type    = "ELB"
    
      min_size = 2
      max_size = 4
    
      tag {
        key                 = "name"
        value               = "${var.project}-dev-asg"
        propagate_at_launch = true
      }
    }
    

    If you would want to have more than one TG assigned to the ASG, then you would need to update the variable so it can accept a list:

    variable "tg" {
      description = "List of TG to attach to the ASG."
      type = list(string)
    }
    

    Then, in the module call, the following would change:

    module "asg" {
      source = "./modules/asg"
      project = "${var.project}"
      app-sg = "${module.vpc.app-sg}"
      sn1 = "${module.vpc.sn1}"
      sn2 = "${module.vpc.sn2}"
      tg = "${module.alb[*].tg}"
    }
    

    With the same general comment about the terraform syntax:

    module "asg" {
      source = "./modules/asg"
      project = var.project
      app-sg  = module.vpc.app-sg
      sn1     = module.vpc.sn1
      sn2     = module.vpc.sn2
      tg      = module.alb[*].tg
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search