hashicorp / terraform-provider-aws

The AWS Provider enables Terraform to manage AWS resources.
https://registry.terraform.io/providers/hashicorp/aws
Mozilla Public License 2.0
9.83k stars 9.18k forks source link

lb_listener_rule target group support in 2.65 #13636

Closed jmgreg31 closed 1 year ago

jmgreg31 commented 4 years ago

Community Note

Terraform Version

Terraform v0.12.26
provider.aws: version = "~> 2.65"

Affected Resource(s)

Terraform Configuration Files

resource "aws_lb_target_group" "my-albtg" {
  count    = length(var.autoscaling_group_name)
  name     = format("${var.name}%01d-alb-tg", count.index +1)
  ...
}

resource "aws_lb_listener_rule" "my-alb-listener-rule" {
  listener_arn = aws_lb_listener.my-alb-listener.arn
  priority     = 100
  action {
      type  = "forward"
      forward {
        dynamic "target_group" {
          for_each = var.autoscaling_group_name
          content {
            arn = aws_lb_target_group.my-albtg[target_group.key].arn
          }
        } 
      }
    }

Debug Output

Error: action.0.forward.0.target_group: attribute supports 2 item as a minimum, config has 1 declared

Expected Behavior

This pattern works fine if you are using multiple target groups blocks. Per the documentation, I would expect this to work with a single target group block as well

Actual Behavior

error

Steps to Reproduce

  1. terraform apply

Important Factoids

Found a workaround, however, if you re-apply a listener rule with fewer target groups it will throw an error

Error: Error deleting Target Group: ResourceInUse: Target group 'arn:aws:elasticloadbalancing:us-east-1:.......' is currently in use by a listener or a rule

Attempted workaround:

action {
    type             = "forward"
    target_group_arn = length(var.autoscaling_group_name) == 1 ? aws_lb_target_group.my-albtg[0].arn : null
    dynamic "forward" {
      for_each = length(var.autoscaling_group_name) == 1 ? [] : [aws_lb_target_group.my-albtg[0].arn]
      content {
        dynamic "target_group" {
          for_each = var.autoscaling_group_name
          content {
            arn = aws_lb_target_group.my-albtg[target_group.key].arn
          }
        } 
      }
    }
  }

Wondering if the use case of dynamic number of target groups is just not yet supported?

bflad commented 4 years ago

Hi @jmgreg31 👋 What version of Terraform CLI are you using (terraform version)? There were similar reports in earlier 0.12 versions of the Terraform CLI.

jmgreg31 commented 4 years ago

@bflad I am using the latest version - apologies I updated the original comment

Terraform v0.12.26
jmgreg31 commented 4 years ago

I believe the attempted working around is facing this issue: https://github.com/terraform-providers/terraform-provider-aws/issues/636

However none of the solutions mentioned with random naming would solve for this use case as we would in fact need to destroy the resource.

SpComb commented 4 years ago

https://github.com/terraform-providers/terraform-provider-aws/pull/12574#issuecomment-639642524 explains that this is an API issue with type = "forward" + target_group_arn = ... vs multiple target_group { arn = ... } blocks...

Hi @jmgreg31, I think you're correct. I make a mistake in the documentation. To route to a single target group you must use the "target_group_arn" attribute outside the forward block, and to route to two or more target groups, the "forward" block with "target_group" blocks.

This is because of an API limitation in the AWS upstream, but I'll make my best to work around this behavior and/or update the documentation this weekend.

I suppose the terraform provider would need to special-case the single-target_group case for this to work?

SpComb commented 4 years ago

Best workaround might be to use separate resources for the two structural cases:

resource "aws_lb_listener_rule" "http-forward" {
  count = (var.second_target_group_arn == null) ? 1 : 0

  listener_arn = var.alb_listener_arn
  priority     = var.alb_priority

  condition {
    host_header {
      values = [var.server_name]
    }
  }

  action {
    type             = "forward"
    target_group_arn = var.first_target_group_arn
  }
}

resource "aws_lb_listener_rule" "http-forward-weighted" {
  count = (var.second_target_group_arn == null) ? 0 : 1

  listener_arn = var.alb_listener_arn
  priority     = var.alb_priority

  condition {
    host_header {
      values = [var.server_name]
    }
  }

  action {
    type             = "forward"

    forward {
      target_group {
        arn    = var.first_target_group_arn
        weight = var.first_target_group_weight
      }
      target_group {
        arn    = var.second_target_group_arn
        weight = var.second_target_group_weight
      }
    }
  }
}
ctacka commented 4 years ago

Having same issue in v0.12.29

resource "aws_lb_listener_rule" "https" {
  listener_arn = data.aws_lb_listener.https.arn
  action {
    type = "forward"
    target_group_arn = aws_lb_target_group.tg.arn
    forward {
      target_group {
        arn    = aws_lb_target_group.tg.arn
      }

      stickiness {
        enabled  = true
        duration = 600
      }
    }
  }

  condition {
    host_header {
      values = [aws_route53_record.db.fqdn]
    }
  }
}

Error: List shorter than MinItems

on main.tf line 151, in resource "aws_lb_listener_rule" "https": 151: target_group {

Attribute supports 2 item minimum, config has 1 declared

nicon89 commented 3 years ago

Same issue on TF 0.14.4.

kiddom-kq commented 3 years ago

I hit this exact error while trying trying out a dynamic block inside of the default_action block on the aws_lb_listener resource. I know that aws_lb_listener is not the same as the resource that the ticket was opened for: aws_lb_listener_rule but this behavior seems too bizarre to not document and seems to be related and might possibly be a work around.

resource "aws_lb_listener" "this" {
  load_balancer_arn = module.alb.arn
  port     = "443"
  protocol = "HTTPS"

  ssl_policy = "ELBSecurityPolicy-FS-1-2-Res-2020-10"
  certificate_arn = var.lb_certificate_arn

  default_action {
    type = "forward"
    # WORKS, even though length(aws_lb_target_group.this) is 1
    # forward {
    #   # Create a TG block for each of the TGs we created from user input
    #   dynamic "target_group" {
    #     for_each = aws_lb_target_group.this
    #     content {
    #       arn = target_group.value["arn"]
    #     }
    #   }
    # }

    # WORKS
    # forward {
    #   target_group {
    #     arn    = "Foo"
    #     weight = 80
    #   }
    #   target_group {
    #     arn    = "Bar"
    #     weight = 80
    #   }
    # }

    # DOES NOT WORK!
    # Returns: Attribute supports 2 item minimum, config has 1 declared
    forward {
      target_group {
        arn    = "Foo"
        weight = 80
      }
    }
  }
}

When the last forward block is enabled/un-commented, i get the same error OP reported:

❯ tf apply

Error: List shorter than MinItems

  on .terraform/modules/mo-module/main.tf line 173, in resource "aws_lb_listener" "this":
 173:       target_group {

Attribute supports 2 item minimum, config has 1 declared

But when the forward block with two 'dummy' target_groups is enabled/uncommented:

  # module.my-module.aws_lb_listener.this will be created
  + resource "aws_lb_listener" "this" {
      + arn               = (known after apply)
      + certificate_arn   = "arn:aws:acm:..."
      <...>
      + ssl_policy        = "ELBSecurityPolicy-FS-1-2-Res-2020-10"

      + default_action {
          + order = (known after apply)
          + type  = "forward"

          + forward {

              + target_group {
                  + arn    = "Bar"
                  + weight = 80
                }
              + target_group {
                  + arn    = "Foo"
                  + weight = 80
                }
            }
        }
    }

And when the first forward block is enabled:

  # module.my-module.aws_lb_listener.this will be created
  + resource "aws_lb_listener" "this" {
      + arn               = (known after apply)
      <...>
      + ssl_policy        = "ELBSecurityPolicy-FS-1-2-Res-2020-10"

      + default_action {
          + order = (known after apply)
          + type  = "forward"

          + forward {

              + target_group {
                  + arn    = (known after apply)
                  + weight = 1
                }
            }
        }
    }

So you can get around the "need a minimum of two" error if you do it dynamically...

I am UTD:

❯ tf -version
Terraform v0.14.5
+ provider registry.terraform.io/hashicorp/aws v3.25.0

And it looks like i spoke too soon! The error, when using dynamic does not show up during the initial phase of plan... it only shows up after agreeing to the proposed changes!


  # module.my-module.aws_lb_listener.this will be created
  + resource "aws_lb_listener" "this" {
      + arn               = (known after apply)
      <...>

      + default_action {
          + order = (known after apply)
          + type  = "forward"

          + forward {

              + target_group {
                  + arn    = (known after apply)
                  + weight = 1
                }
            }
        }
    }

<...>

Plan: 10 to add, 2 to change, 2 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

<...>

module.bastion.aws_instance.bastion: Still creating... [1m10s elapsed]
module.bastion.aws_instance.bastion: Creation complete after 1m11s [id=i-DeadBeefBabe12345]

Error: List shorter than MinItems

  on .terraform/modules/my-module/main.tf line 153, in resource "aws_lb_listener" "this":
 153:     forward {

Attribute supports 2 item minimum,  config has 1 declared

So no. No work around :(.

DanGardnerr commented 3 years ago

Also experiencing this issue in terraform verison 0.14.5

resource "aws_alb_listener_rule" "host_based_routing" {
  listener_arn = "arn"
  priority     = 99

  action {
    type = "forward"
    forward {
      target_group {
        arn    = aws_alb_target_group.nginx-service-tg.arn
        weight = 80
      }

      stickiness {
        enabled  = true
        duration = 600
      }
    }
  }

  condition {
    path_pattern {
      values = ["/ng/"]
    }
  }
}

Getting the error

Error: Error creating LB Listener Rule: ValidationError: You cannot specify the same target group multiple times in the target group list
        status code: 400, request id: 
mnazir23 commented 3 years ago

Facing the same issue. Terraform Version is 0.13.5

I am trying to create the default ALB listener rule.

resource "aws_lb_listener" "my-alb-httpslistener" { load_balancer_arn = ALB_ARN port = 443 protocol = "HTTPS" ssl_policy = var.AlbSslPolicy certificate_arn = var.AlbCertificateArn default_action { type = "forward" forward { target_group { arn = <Target Group ARN> } stickiness { enabled = true duration = 3600 } } } }

Getting the same error attribute supports 2 item minimum, config has 1 declared

trentondyck commented 3 years ago

Why should I have two target groups in my ALB listener rule? I just don't get it. All I'm trying to do is add stickiness to a single target group in ALB listener, If I add it elsewhere in that block it's not supported

resource "aws_lb_listener_rule" "prod-platform-tf" {
  listener_arn = aws_lb_listener.prod-https-tf.arn
  priority     = 100
  action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.prod-platform-tf.arn
   forward {
      target_group {
        arn = aws_lb_target_group.prod-platform-tf.arn
      }
      stickiness {
        enabled  = true
        duration = 86400
      }
    }
  }
  condition {
    path_pattern {
      values = ["/foo*"]
    }
  }
}
daniloalves commented 3 years ago

In this comment I got a explanation: https://github.com/hashicorp/terraform-provider-aws/pull/12574#issuecomment-639642524 When route to a single target group you must use the "target_group_arn" attribute outside the forward block.

bereket42 commented 3 years ago

In this comment I got a explanation: #12574 (comment) When route to a single target group you must use the "target_group_arn" attribute outside the forward block.

But what if you need to create a stickiness block? Or if the existing default has an invalid duration? See https://github.com/hashicorp/terraform-provider-aws/issues/15144

suneshgovind commented 2 years ago

Trying to do the same operation as @trentondyck is doing. How do you add stickiness block for a listener rule with a single target group?

forward {
  target_group {
    arn = var.target_group_arn
  }

  dynamic "stickiness" {
    for_each = var.stickiness_enabled == false ? [] : [1]
    content {
      enabled  = true
      duration = var.stickiness_duration
    }
  }
}
kartvep commented 2 years ago

The same issue.

Terraform v1.0.7
on darwin_amd64
+ provider registry.terraform.io/hashicorp/aws v3.75.1

Interestingly, the aws_lb_listener works smoothly with the single target group. So the limitation on the API side is gone?

engineertdog commented 2 years ago

This is still an issue, and not an AWS API limitation as this point.

Yukititit commented 1 year ago

Same issue with version:

Terraform v1.3.5
on windows_amd64

i am able to route to a single target group with target_group_arn but how should i add a stickiness block?

autotune commented 1 year ago

I am working on this as part of my 100 days of terraform contributions challenge. PR arriving soon.

github-actions[bot] commented 1 year ago

This functionality has been released in v5.24.0 of the Terraform AWS Provider. Please see the Terraform documentation on provider versioning or reach out if you need any assistance upgrading.

For further feature requests or bug reports with this functionality, please create a new GitHub issue following the template. Thank you!

github-actions[bot] commented 11 months ago

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.