Skip to content

ordered_placement_strategy uses map instead of list, breaking strategy order #369

@jworks-mwb

Description

@jworks-mwb

Description

The ordered_placement_strategy variable in the ECS service module is defined as a map(object({...})) type, which is problematic because maps are not ordered collections in Terraform. According to AWS ECS documentation, placement strategies are evaluated in order from top to bottom, and the ordering is significant for determining how tasks are placed.

Using a map for this variable means that:

  1. The order of placement strategies cannot be guaranteed
  2. This contradicts the variable's own description which states "List from top to bottom in order of precedence"
  3. Users cannot reliably control the order in which placement strategies are applied
  • I have searched the open/closed issues and my issue is not listed.

Versions

  • Module version: Latest (main branch)
  • Terraform version: N/A - This is a module design issue
  • Provider version(s): N/A - This is a module design issue

Reproduction Code

The issue exists in the module variable definitions:

Root module (variables.tf:321-324):

ordered_placement_strategy = optional(map(object({
  field = optional(string)
  type  = string
})))

Service module (modules/service/variables.tf:218-225):

variable "ordered_placement_strategy" {
  description = "Service level strategy rules that are taken into consideration during task placement. List from top to bottom in order of precedence"
  type = map(object({
    field = optional(string)
    type  = string
  }))
  default = null
}

Service module usage (modules/service/main.tf:153-160):

dynamic "ordered_placement_strategy" {
  for_each = var.ordered_placement_strategy != null ? var.ordered_placement_strategy : {}

  content {
    field = ordered_placement_strategy.value.field
    type  = ordered_placement_strategy.value.type
  }
}

Example demonstrating the issue

When using this Terraform configuration:

ordered_placement_strategy = {
  spread = {
    type  = "spread"
    field = "attribute:ecs.availability-zone"
  },
  binpack = {
    type  = "binpack"
    field = "memory"
  }
}

The resulting task placement strategy in AWS is:

binpack (MEMORY), spread (attribute:ecs.availability-zone)

Note how the order is reversed from what was specified in the Terraform code. This is because maps in Terraform do not preserve insertion order, and the keys are sorted alphabetically (binpack comes before spread alphabetically), leading to unpredictable and incorrect task placement behavior.

Expected behavior

The ordered_placement_strategy variable should be defined as a list(object({...})) to preserve the order of placement strategies. For example:

variable "ordered_placement_strategy" {
  description = "Service level strategy rules that are taken into consideration during task placement. List from top to bottom in order of precedence"
  type = list(object({
    field = optional(string)
    type  = string
  }))
  default = null
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions