Home > Software design >  Terraform : The "count" object can only be used in "module", "resource"
Terraform : The "count" object can only be used in "module", "resource"

Time:09-09

I'm trying to access s3 bucket from load balancer access logs. There is a count set on the s3 bucket creation.

resource aws_s3_bucket lb_logging {
  count         = var.enable_lb_logging ? 1 : 0
  bucket        = "${var.environment_id}-account-lb-logging"
  acl           = "private"
  force_destroy = true
  lifecycle_rule {
    id      = "${var.environment_id}-account-lb-logging"
    enabled = true

    expiration {
      days = var.lb_logging_s3_expiration_period
    }
  }
}

When var.enable_lb_logging is true, it creates the s3 bucket and the need is to use the bucket to store load balancer access logs. My load balancer access logs looks like -

resource aws_lb alb {
  internal        = var.alb_is_public ? false : true
  security_groups = compact(concat(aws_security_group.additional_security_groups.*.id, list(aws_security_group.main.id), list(aws_security_group.account_inbound_rules_arm.id)))
  subnets         = local.alb_subnets
  tags            = var.tags
  access_logs {
    count   = length(aws_s3_bucket.lb_logging)
    bucket  = "${aws_s3_bucket.lb_logging[count.index].bucket}"
    enabled = var.enable_lb_logging ? true : false
  }  
}

During deployment I'm getting the below error

2022-09-08T16:08:46.5043258Z ##[error][1m[31mError: [0m[0m[1mReference to "count" in non-counted context[0m
2022-09-08T16:08:46.5063266Z ##[error][0m  on modules\load-balancers.tf line 16, in resource "aws_lb" "alb":
2022-09-08T16:08:46.5110603Z ##[error]  16:     bucket  = "${aws_s3_bucket.lb_logging[[4mcount.index[0m].bucket}"
2022-09-08T16:08:46.5116983Z ##[error][0m
2022-09-08T16:08:46.5119949Z ##[error]The "count" object can only be used in "module", "resource", and "data"
2022-09-08T16:08:46.5122470Z ##[error]blocks, and only when the "count" argument is set.

Can someone help me on this? how to use count in load balancer?

CodePudding user response:

The error is pretty clear. You cannot use the count meta-argument anywhere, i.e., in your case, you cannot use it in a block that you want to:

access_logs {
  count   = length(aws_s3_bucket.lb_logging) # <----- This cannot be done
  bucket  = "${aws_s3_bucket.lb_logging[count.index].bucket}"
  enabled = var.enable_lb_logging ? true : false
}  

However, similarly to what you have done for the bucket, you could do something like:

resource aws_lb alb {
  count           = var.enable_lb_logging ? 1 : 0
  internal        = var.alb_is_public ? false : true
  security_groups = compact(concat(aws_security_group.additional_security_groups.*.id, list(aws_security_group.main.id), list(aws_security_group.account_inbound_rules_arm.id)))
  subnets         = local.alb_subnets
  tags            = var.tags
  access_logs {
    bucket  = aws_s3_bucket.lb_logging[count.index].bucket
    enabled = var.enable_lb_logging ? true : false
  }  
}

The question remains if you want to have ALB depend on the bucket or another variable. In that case, you can use a different variable, but then you would have to figure out how to fetch the bucket index. If you are sure there will ever be only one bucket, you can even hardcode the index:

resource aws_lb alb {
  internal        = var.alb_is_public ? false : true
  security_groups = compact(concat(aws_security_group.additional_security_groups.*.id, list(aws_security_group.main.id), list(aws_security_group.account_inbound_rules_arm.id)))
  subnets         = local.alb_subnets
  tags            = var.tags
  access_logs {
    bucket  = aws_s3_bucket.lb_logging[0].bucket
    enabled = var.enable_lb_logging ? true : false
  }  
}

However, since the bucket is a required argument, you could use the dynamic block depending on the value of var.enable_lb_logging, e.g.:

resource aws_lb alb {
  internal        = var.alb_is_public ? false : true
  security_groups = compact(concat(aws_security_group.additional_security_groups.*.id, list(aws_security_group.main.id), list(aws_security_group.account_inbound_rules_arm.id)))
  subnets         = local.alb_subnets
  tags            = var.tags
  dynamic "access_logs" {
    for_each = var.enable_lb_logging ? [1] : []
    content {
      bucket   = aws_s3_bucket.lb_logging[0].bucket
      enabled  = var.enable_lb_logging
    }
  }  
}
  • Related