terraform-aws-modules/terraform-aws-alb

Changing to weighted-forward listener rule (to add stickiness) results in error determining target group arn

barnabyibis opened this issue · 3 comments

Description

I have been using the module with success for a while now. A change in our target solution now requires sticky sessions to some target groups. When I attempt to modify from action.type == "forward" to action.type == "weighted-forward" returns an error

Error: Error in function call

│ on ....\modules\alb\main.tf line 346, in resource "aws_lb_listener_rule" "this":
│ 346: arn = try(target_group.value.arn, aws_lb_target_group.this[target_group.value.target_group_key].arn)
│ ├────────────────
│ │ aws_lb_target_group.this is object with 2 attributes
│ │ target_group.value is "ecs-ctnr-nz-ecomm-nz-devtest"

│ Call to function "try" failed: no expression succeeded:
│ - Unsupported attribute (at ....\modules\alb\main.tf:346,44-48)
│ Can't access attributes on a primitive-typed value (string).
│ - Unsupported attribute (at ....\modules\alb\main.tf:346,93-110)
│ Can't access attributes on a primitive-typed value (string).

│ At least one expression must produce a successful result.

Even though I have an aws_lb_target_group that should match, the 'try' declaration fails

terraform state show module.eos_ecs-alb.module.alb.aws_lb_target_group.this[\"ecs-ctnr-nz-ecomm-nz-devtest\"]
# module.eos_ecs-alb.module.alb.aws_lb_target_group.this["ecs-ctnr-nz-ecomm-nz-devtest"]:
resource "aws_lb_target_group" "this" {
    arn                                = "arn:aws:elasticloadbalancing:ap-southeast-2...

Versions

  • Module version [Required]: 9.9.0

  • Terraform version:

  • Provider version(s):

Terraform v1.8.1
on windows_amd64

  • provider registry.terraform.io/hashicorp/archive v2.4.2
  • provider registry.terraform.io/hashicorp/aws v5.46.0
  • provider registry.terraform.io/hashicorp/local v2.5.1

Reproduction Code [Required]

listeners = merge(
	{for container_name, urls in var.container_URLs : 
                  container_name => {
                    ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06"
                    certificate_arn = var.cert_arn
                    additional_certificate_arns = [for domain, arn in var.customer_certs : arn if contains(concat(urls, local.wildcard_URLs), domain)]
                    # If there are no URLs, I'm expecting the default rule to kick in. This may need to be revisited...
                    rules = [for url in urls : {
                      # priority = 100 <- unsure how to provide an incrementing value for these (not sure it is important, module creates nulls if missing)
                      actions = [{
                        type = "weighted-forward"
						target_groups = {
							target_group_key = container_name # Associates by name to matching target_groups resource (created next, below)
						}
						stickiness = {
							enabled = strcontains(container_name, "-ecomm-") ? true : false
							duration = 600
						}
                      }]
                      conditions = [{
                        host_header = {
                          values = [url]
                        }
                      }]
                    }]
                    fixed_response = { #default_action
                      content_type = "text/plain"
                      message_body = "Invalid URL - please contact Ibis support"
                      status_code  = "403"
                    }
                  }
                },
				{
					HTTP_redirect = {
						port 	 = 80
						protocol = "HTTP"
						redirect = {
						  port        = "443"
						  protocol    = "HTTPS"
						  status_code = "HTTP_301"
						}
					}
				}
			 )

Steps to reproduce the behavior:

No workspaces

Cache not cleared - I'm relying on the stored state to validate the requested ALB change

Created a standard ALB with simple target groups using the following successful code, then tried to introduce sticky sessions to the listener

listeners = merge(
	{for container_name, urls in var.container_URLs : 
                  container_name => {
                    ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06"
                    certificate_arn = var.cert_arn
                    additional_certificate_arns = [for domain, arn in var.customer_certs : arn if contains(concat(urls, local.wildcard_URLs), domain)]
                    # If there are no URLs, I'm expecting the default rule to kick in. This may need to be revisited...
                    rules = [for url in urls : {
                      # priority = 100 <- unsure how to provide an incrementing value for these (not sure it is important, module creates nulls if missing)
                      actions = [{
                        type = "forward"
                        target_group_key = container_name # Associates by name to matching target_groups resource (created next, below)
                      }]
                      conditions = [{
                        host_header = {
                          values = [url]
                        }
                      }]
                    }]
                    fixed_response = { #default_action
                      content_type = "text/plain"
                      message_body = "Invalid URL - please contact Ibis support"
                      status_code  = "403"
                    }
                  }
                },
				{
					HTTP_redirect = {
						port 	 = 80
						protocol = "HTTP"
						redirect = {
						  port        = "443"
						  protocol    = "HTTPS"
						  status_code = "HTTP_301"
						}
					}
				}
			 )

Expected behavior

ALB changes by changing some target groups to use sticky sessions

Actual behavior

Error as described prevents apply

Terminal Output Screenshot(s)

Additional context

The crux of the issue is that I don't understand the result in the error report

target_group.value is "ecs-ctnr-nz-ecomm-nz-devtest"

when the code says

type = "weighted-forward"
	target_groups = {
		target_group_key = container_name

In other words, I expect target_group.value to be a map(string), not just a string

I found the issue by review a sample:
The target groups can be multiple so are expected to be provided as a List.
This works:

                      actions = [{
                        type = "weighted-forward"
						target_groups = [
							{
								target_group_key = container_name # Associates by name to matching target_groups resource (created next, below)
							}
						]
						stickiness = {
							enabled = strcontains(container_name, "-ecomm-") ? true : false
							duration = 600
						}
                      }]

(There is only one 'stickiness' declaration, and it is cast to a list in the module, now I look more closely)

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.