terraform-aws-modules / terraform-aws-autoscaling

Terraform module to create AWS Auto Scaling resources 🇺🇦
https://registry.terraform.io/modules/terraform-aws-modules/autoscaling/aws
Apache License 2.0
289 stars 553 forks source link

feat!: Use `launch_template_id` instead of `launch_template_name`, raise MSV of AWS provider and Terraform to 5.0 and 1.0 respectively #204

Closed dhoppe closed 9 months ago

dhoppe commented 1 year ago

Description

In case the value of launch_template_name changes, a new launch template will be created but the auto scaling group still points to the old launch template.

If you execute terraform apply a second time, the auto scaling group tries to change the name of the launch template, but keeps the id of the old launch template which is not valid anymore.

Using the launch_template_id instead of launch_template_name everything is working as expected.

Motivation and Context

Breaking Changes

How Has This Been Tested?

dhoppe commented 1 year ago

@antonbabenko What do you think about this fix?

antonbabenko commented 1 year ago

@bryantbiggs WDYT?

bryantbiggs commented 1 year ago

it seems valid - I haven't had a chance to test before/after change to see if that introduces any interruption to current launch templates (i.e. - breaking change)

dhoppe commented 1 year ago

I am back from vacation and ran a few tests.

Create Auto Scaling Group based on version 6.5.2:

...
  # aws_autoscaling_group.this[0] will be created
  + resource "aws_autoscaling_group" "this" {
      + arn                       = (known after apply)
      + availability_zones        = (known after apply)
      + default_cooldown          = (known after apply)
      + desired_capacity          = 1
      + enabled_metrics           = [
          + "GroupDesiredCapacity",
          + "GroupInServiceInstances",
          + "GroupMaxSize",
          + "GroupMinSize",
          + "GroupPendingInstances",
          + "GroupStandbyInstances",
          + "GroupTerminatingInstances",
          + "GroupTotalInstances",
        ]
      + force_delete              = false
      + force_delete_warm_pool    = false
      + health_check_grace_period = 300
      + health_check_type         = (known after apply)
      + id                        = (known after apply)
      + max_size                  = 2
      + metrics_granularity       = "1Minute"
      + min_size                  = 1
      + name                      = "example-dev"
      + name_prefix               = (known after apply)
      + protect_from_scale_in     = false
      + service_linked_role_arn   = (known after apply)
      + termination_policies      = [
          + "OldestInstance",
          + "OldestLaunchTemplate",
        ]
      + vpc_zone_identifier       = [
          + "subnet-010d8727ed0731858",
          + "subnet-0277536173302342b",
          + "subnet-061b8068f8143f3cd",
        ]
      + wait_for_capacity_timeout = "10m"

      + instance_refresh {
          + strategy = "Rolling"
          + triggers = [
              + "tag",
            ]

          + preferences {
              + min_healthy_percentage = 90
              + skip_matching          = false
            }
        }

      + launch_template {
          + id      = (known after apply)
          + name    = "1st-example-dev"
          + version = "$Latest"
        }

      + tag {
          + key                 = "Contact"
          + propagate_at_launch = true
          + value               = "Dennis Hoppe"
        }
      + tag {
          + key                 = "Environment"
          + propagate_at_launch = true
          + value               = "dev"
        }
      + tag {
          + key                 = "Name"
          + propagate_at_launch = true
          + value               = "example-dev"
        }
      + tag {
          + key                 = "Project"
          + propagate_at_launch = true
          + value               = "Atlassian"
        }

      + timeouts {}
    }
...
  # aws_launch_template.this[0] will be created
  + resource "aws_launch_template" "this" {
      + arn                    = (known after apply)
      + default_version        = (known after apply)
      + id                     = (known after apply)
      + image_id               = "ami-096800910c1b781ba"
      + instance_type          = "t3.medium"
      + key_name               = "atlassian-dev"
      + latest_version         = (known after apply)
      + name                   = "1st-example-dev"
      + name_prefix            = (known after apply)
      + tags                   = {
          + "Contact"     = "Dennis Hoppe"
          + "Environment" = "dev"
          + "Project"     = "Atlassian"
        }
      + tags_all               = {
          + "Contact"     = "Dennis Hoppe"
          + "Environment" = "dev"
          + "Project"     = "Atlassian"
        }
      + update_default_version = true
      + user_data              = "IyEvdXNyL2Jpbi9lbnYgYmFzaAphcHQgdXBkYXRlCmFwdCBpbnN0YWxsIC15IG5naW54CgpJTlNUQU5DRV9JRD1gY3VybCBodHRwOi8vMTY5LjI1NC4xNjkuMjU0L2xhdGVzdC9tZXRhLWRhdGEvaW5zdGFuY2UtaWRgCnNlZCAtaSAicy9uZ2lueFwhL25naW54XCEgKCRJTlNUQU5DRV9JRCkvZyIgL3Zhci93d3cvaHRtbC9pbmRleC5uZ2lueC1kZWJpYW4uaHRtbAoKc3lzdGVtY3RsIGVuYWJsZSBuZ2lueApzeXN0ZW1jdGwgc3RhcnQgbmdpbngK"
      + vpc_security_group_ids = [
          + "sg-0b0a601122357afe3",
        ]

      + block_device_mappings {
          + device_name = "/dev/sda1"
          + no_device   = "0"

          + ebs {
              + delete_on_termination = "true"
              + encrypted             = "true"
              + iops                  = (known after apply)
              + throughput            = (known after apply)
              + volume_size           = 80
              + volume_type           = "gp3"
            }
        }
      + block_device_mappings {
          + device_name = "/dev/xvdf"
          + no_device   = "1"

          + ebs {
              + delete_on_termination = "true"
              + encrypted             = "true"
              + iops                  = (known after apply)
              + throughput            = (known after apply)
              + volume_size           = 200
              + volume_type           = "gp3"
            }
        }

      + iam_instance_profile {
          + arn  = (known after apply)
          + name = (known after apply)
        }

      + metadata_options {
          + http_endpoint               = (known after apply)
          + http_protocol_ipv6          = (known after apply)
          + http_put_response_hop_limit = (known after apply)
          + http_tokens                 = (known after apply)
          + instance_metadata_tags      = (known after apply)
        }

      + monitoring {
          + enabled = true
        }
    }
...
1st_asg 1st_lt

Change name of Launch Template based on version 6.5.2:

...
  # aws_autoscaling_group.this[0] will be updated in-place
  ~ resource "aws_autoscaling_group" "this" {
        id                        = "example-dev"
        name                      = "example-dev"
        # (23 unchanged attributes hidden)

      ~ launch_template {
            id      = "lt-08331c40be1bda486"
          ~ name    = "1st-example-dev" -> "2nd-example-dev"
            # (1 unchanged attribute hidden)
        }

        # (6 unchanged blocks hidden)
    }
...
  # aws_launch_template.this[0] must be replaced
+/- resource "aws_launch_template" "this" {
      ~ arn                     = "arn:aws:ec2:eu-west-1:590606209411:launch-template/lt-08331c40be1bda486" -> (known after apply)
      ~ default_version         = 1 -> (known after apply)
      - disable_api_stop        = false -> null
      - disable_api_termination = false -> null
      ~ id                      = "lt-08331c40be1bda486" -> (known after apply)
      ~ latest_version          = 1 -> (known after apply)
      ~ name                    = "1st-example-dev" -> "2nd-example-dev" # forces replacement
      + name_prefix             = (known after apply)
      - security_group_names    = [] -> null
        tags                    = {
            "Contact"     = "Dennis Hoppe"
            "Environment" = "dev"
            "Project"     = "Atlassian"
        }
        # (7 unchanged attributes hidden)

      ~ block_device_mappings {
            # (2 unchanged attributes hidden)

          ~ ebs {
              ~ iops                  = 0 -> (known after apply)
              ~ throughput            = 0 -> (known after apply)
                # (4 unchanged attributes hidden)
            }
        }
      ~ block_device_mappings {
            # (2 unchanged attributes hidden)

          ~ ebs {
              ~ iops                  = 0 -> (known after apply)
              ~ throughput            = 0 -> (known after apply)
                # (4 unchanged attributes hidden)
            }
        }

      ~ iam_instance_profile {
            # (1 unchanged attribute hidden)
        }

      + metadata_options {
          + http_endpoint               = (known after apply)
          + http_protocol_ipv6          = (known after apply)
          + http_put_response_hop_limit = (known after apply)
          + http_tokens                 = (known after apply)
          + instance_metadata_tags      = (known after apply)
        }

        # (1 unchanged block hidden)
    }
...
2nd_asg 2nd_asg_activity 2nd_lt

Change name of Launch Template (Error) based on version 6.5.2:

...
  # aws_autoscaling_group.this[0] will be updated in-place
  ~ resource "aws_autoscaling_group" "this" {
        id                        = "example-dev"
        name                      = "example-dev"
        # (23 unchanged attributes hidden)

      ~ launch_template {
            id      = "lt-08331c40be1bda486"
          ~ name    = "1st-example-dev" -> "2nd-example-dev"
            # (1 unchanged attribute hidden)
        }

        # (6 unchanged blocks hidden)
    }
...
3rd_asg

Change name of Launch Template (Success) based on branch launch_template_name:

...
  # aws_autoscaling_group.this[0] will be updated in-place
  ~ resource "aws_autoscaling_group" "this" {
        id                        = "example-dev"
        name                      = "example-dev"
        # (23 unchanged attributes hidden)

      ~ launch_template {
          ~ id      = "lt-08331c40be1bda486" -> "lt-044be7e5004489352"
            name    = "1st-example-dev"
            # (1 unchanged attribute hidden)
        }

        # (6 unchanged blocks hidden)
    }
...
4th_asg 4th_lt

As you can see, the pull request works as expected. Even if the diff still shows the old name of the launch template, the output has been updated accordingly.

Outputs:

autoscaling_group_arn = "arn:aws:autoscaling:eu-west-1:590606209411:autoScalingGroup:b1f8d5a5-d5f1-4f5e-a2d9-666e9b355511:autoScalingGroupName/example-dev"
autoscaling_group_availability_zones = toset([
  "eu-west-1a",
  "eu-west-1b",
  "eu-west-1c",
])
autoscaling_group_default_cooldown = 300
autoscaling_group_desired_capacity = 1
autoscaling_group_enabled_metrics = toset([
  "GroupDesiredCapacity",
  "GroupInServiceInstances",
  "GroupMaxSize",
  "GroupMinSize",
  "GroupPendingInstances",
  "GroupStandbyInstances",
  "GroupTerminatingInstances",
  "GroupTotalInstances",
])
autoscaling_group_health_check_grace_period = 300
autoscaling_group_health_check_type = "EC2"
autoscaling_group_id = "example-dev"
autoscaling_group_load_balancers = toset([])
autoscaling_group_max_size = 2
autoscaling_group_min_size = 1
autoscaling_group_name = "example-dev"
autoscaling_group_target_group_arns = toset([])
autoscaling_group_vpc_zone_identifier = toset([
  "subnet-010d8727ed0731858",
  "subnet-0277536173302342b",
  "subnet-061b8068f8143f3cd",
])
autoscaling_policy_arns = {}
autoscaling_schedule_arns = {}
iam_instance_profile_arn = "arn:aws:iam::590606209411:instance-profile/ec2/example-dev"
iam_instance_profile_id = "example-dev"
iam_instance_profile_unique = "AIPAYTAW7SGBXFX47HQPG"
iam_role_arn = "arn:aws:iam::590606209411:role/ec2/example-dev"
iam_role_name = "example-dev"
iam_role_unique_id = "AROAYTAW7SGBZFQYKY3SJ"
launch_template_arn = "arn:aws:ec2:eu-west-1:590606209411:launch-template/lt-044be7e5004489352"
launch_template_default_version = 1
launch_template_id = "lt-044be7e5004489352"
launch_template_latest_version = 1
launch_template_name = "2nd-example-dev"
dhoppe commented 1 year ago

@antonbabenko I really tried to avoid introducing breaking changes, but right now I am out of ideas.

The resource aws_autoscaling_group only allows the argument launch_template_id or launch_template_name. In that case adding an additional local variable does not help.

I also tried to use the data source aws_launch_template, but there are examples which do not provide a value for var.launch_template which causes an error message.

I do not know how common it is for someone to change the name of a launch template or not manage the launch template with this Terraform module, but in the end this is a bug.

I wonder how long it will take for your kid to work on the first Issues / Pull Requests. I am pretty sure you can use all the help you can get ;)

github-actions[bot] commented 1 year ago

This PR has been automatically marked as stale because it has been open 30 days with no activity. Remove stale label or comment or this PR will be closed in 10 days

antonbabenko commented 9 months ago

This PR is included in version 7.0.0 :tada:

github-actions[bot] commented 8 months ago

I'm going to lock this pull request 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 related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.