1
votes

In AWS using terraform, have to create a load balancer resource only when the LB does not exist. For this, I can have a variable defined like "lb_exists=true" and based on this "true" value, the resource has to be created otherwise, terraform should skip the LB creation.

To achieve this, I am planning to have depends_on. If "lb_exists=false", then depends_on should be an empty list or set to no resource name.

locals {
  lb_exists = "true"
}

resource "aws_lb" "test" {
  name               = var.alb_name
  internal           = false
  load_balancer_type = "application"
  #...
}

data "aws_lb" "test" {
  lb_exists = "${local.lb_exists}"
  depends_on    = ["aws_lb.test"]
}

What is the right way to achieve this and how? is there any workaround for this. I do not want to recreate the LB if exists in the AWS. Please suggest.

[EDIT] copying the full code

provider "aws" {
  region = var.aws_region
}

resource "aws_lb" "test" {
  count = local.lb_exists == "true" ? 1 : 0
  name               = var.alb_name
  internal           = false
  load_balancer_type = "application"
  security_groups    = var.alb_security_groups
  subnets            = var.alb_subnets


  enable_deletion_protection = true

  access_logs {
    #bucket  = aws_s3_bucket.lb_logs.bucket
    bucket = "aws-lab-demo"
    prefix  = "test-lb-logs"
    enabled = false
  }

  tags = {
    Environment = var.env
    Name = var.vpc_id
  }
}

data "aws_lb" "test" {
 # count = local.lb_exists == "true" ? 1 : 0
  arn  = "${aws_lb.test.arn}"
  name = "${aws_lb.test.name}"
}

resource "aws_lb_target_group" "test" {
  name     = var.alb_name
  port     = 8080
  protocol = "HTTP"
  vpc_id   = var.vpc_id
  stickiness {
    type            = "lb_cookie"
    cookie_duration = 1800
    enabled         = false
  }
  health_check {
    healthy_threshold   = 3
    unhealthy_threshold = 10
    timeout             = 5
    interval            = 10
    path                = "/"
    port                = "8081"
  }
}

data "aws_lb_target_group" "test" {
  arn  = "${aws_lb_target_group.test.arn}"
  name = "${aws_lb_target_group.test.name}"
}

resource "aws_lb_listener" "front_end" {
  load_balancer_arn = data.aws_lb.test.arn
  port              = "80"
  protocol          = "HTTP"
  default_action {
    type             = "forward"
    target_group_arn = data.aws_lb_target_group.test.arn
  }
}
1

1 Answers

3
votes

There are two ways to achieve it:

  1. You can use count meta argument to tell terraform how many instances of resource or data source should be created. This could be a recommended way for your case.
resource "aws_lb" "test" {
  count = local.lb_exists == "true" ? 1 : 0
 ...
}

If you use count, then terraform creates list of resources and you should access them like this: aws_lb.test[0]

  1. Second option might be to use for_each. The difference is that if you use this option, you have to provide either set or map to for_each. This approach is useful when you need to control what kind of resources you are creating. For example, if you have something like this:
locals {
  load_balancers = ["app1", "app2"]
}

resource "aws_lb" "test" {
  # you can also make it conditional and provide an empty map
  for_each = { for item in local.load_balanecers: item => item }
 ...
}

In this case, terraform creates a map of resources that can be accessed by the key provided to for_each: aws_lb.test["app1"]