Skip to content

EC2 update_auto_scaling_group Does Not Update Version when New Version Is Submitted #9374

@cloudwitch

Description

@cloudwitch

I'm trying to use update_auto_scaling_group to update my ASGs when there is a new AMI published to the SSM Parameter. However, when writing the unit tests for this I discovered the version does not update on the ASG when using update_auto_scaling_group in moto. When run against AWS, it updates no problem. I am using a mixed instance policy, but it fails just the same using a regular launch template.

I've included a test script and my output to help with reproduction of the bug.

Package Version
moto 5.1.14
boto3 1.40.52
Python 3.11

Thank you!

Test script

Run using python -m unittest test.py.

"""Tests for moto github issue"""

import os
import unittest
import json

import boto3
from moto import mock_aws


def promote_launch_template_on_asg(asg_client, asg_name: str, launch_template: dict) -> dict:
    """Update mixed instance policy launch template to latest version."""
    asg_client.update_auto_scaling_group(
        AutoScalingGroupName=asg_name,
        MixedInstancesPolicy={
            "LaunchTemplate": {
                "LaunchTemplateSpecification": {
                    "LaunchTemplateName": launch_template["LaunchTemplateName"],
                    "Version": str(launch_template["VersionNumber"]),
                }
            }
        },
    )
    return asg_client.describe_auto_scaling_groups(AutoScalingGroupNames=[asg_name])["AutoScalingGroups"][0]


@mock_aws
class TestMain(unittest.TestCase):
    def setUp(self):
        os.environ["AWS_REGION"] = "us-east-1"
        os.environ["AWS_ACCESS_KEY_ID"] = "testing"
        os.environ["AWS_SECRET_ACCESS_KEY"] = "testing"
        os.environ["AWS_SECURITY_TOKEN"] = "testing"
        os.environ["AWS_SESSION_TOKEN"] = "testing"
        os.environ["AWS_DEFAULT_REGION"] = "us-east-1"
        os.environ["ACCOUNT_NUMBER"] = "123456789012"
        os.environ["ACCOUNT_ID"] = "123456789012"
        self.mock_ec2_client_east = boto3.client("ec2", region_name="us-east-1")
        self.mock_asg_client_east = boto3.client("autoscaling", region_name="us-east-1")
        self.mock_cfn_client_east = boto3.client("cloudformation", region_name="us-east-1")

        # Create VPC for ASG
        vpc = self.mock_ec2_client_east.create_vpc(CidrBlock="10.0.0.0/16")
        vpc_id = vpc["Vpc"]["VpcId"]
        # create Subnet for ASG
        subnet = self.mock_ec2_client_east.create_subnet(
            CidrBlock="10.0.0.0/24",
            AvailabilityZone="us-east-1a",
            VpcId=vpc_id,
        )
        subnet_id = subnet["Subnet"]["SubnetId"]
        # Create Launch Template
        self.mock_ec2_client_east.create_launch_template(
            LaunchTemplateName="test-lt",
            LaunchTemplateData={"ImageId": "ami-67890abcdeEXAMPLE"},
        )
        # Create ASG CFN Stack
        self.mock_cfn_client_east.create_stack(
            StackName="asg_stack",
            TemplateBody=json.dumps(
                {
                    "AWSTemplateFormatVersion": "2010-09-09",
                    "Resources": {
                        "SomeASG": {
                            "Type": "AWS::AutoScaling::AutoScalingGroup",
                            "Properties": {
                                "AutoScalingGroupName": "test-asg",
                                "MinSize": "1",
                                "MaxSize": "1",
                                "VPCZoneIdentifier": [subnet_id],
                                "MixedInstancesPolicy": {
                                    "LaunchTemplate": {
                                        "LaunchTemplateSpecification": {
                                            "LaunchTemplateName": "test-lt",
                                            "Version": "1",
                                        }
                                    }
                                },
                            },
                        }
                    },
                }
            ),
        )

    def test_promote_launch_template_on_asg(self):
        """Test promote_launch_template_on_asg()."""
        # Describe our launch template
        launch_template = self.mock_ec2_client_east.describe_launch_templates(LaunchTemplateNames=["test-lt"])[
            "LaunchTemplates"
        ][0]
        # Create a new launch template version with our new AMI ID
        new_launch_template = self.mock_ec2_client_east.create_launch_template_version(
            LaunchTemplateId=launch_template["LaunchTemplateId"],
            SourceVersion=str(launch_template["LatestVersionNumber"]),
            LaunchTemplateData={
                "ImageId": "ami-12345abcdeEXAMPLE",
            },
        )["LaunchTemplateVersion"]
        # New launch template version is 2.
        self.assertEqual(new_launch_template["VersionNumber"], 2)
        # Update ASG to use the new launch template version.
        asg = promote_launch_template_on_asg(self.mock_asg_client_east, "test-asg", new_launch_template)
        # Print the version number to STDOUT. It shows version is 1 even though we updated it to 2.
        print(asg["MixedInstancesPolicy"]["LaunchTemplate"]["LaunchTemplateSpecification"])
        self.assertEqual(asg["MixedInstancesPolicy"]["LaunchTemplate"]["LaunchTemplateSpecification"]["Version"], "2")

Test output

{'LaunchTemplateId': 'lt-e6d7775a8af1b891c', 'LaunchTemplateName': 'test-lt', 'Version': '1'}
F
======================================================================
FAIL: test_promote_launch_template_on_asg (test.TestMain.test_promote_launch_template_on_asg)
Test promote_launch_template_on_asg().
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/snip/testing/venv/lib/python3.11/site-packages/moto/core/models.py", line 122, in wrapper
    result = func(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^
  File "/snip/testing/tests/test.py", line 106, in test_promote_launch_template_on_asg
    self.assertEqual(asg["MixedInstancesPolicy"]["LaunchTemplate"]["LaunchTemplateSpecification"]["Version"], "2")
AssertionError: '1' != '2'
- 1
+ 2


----------------------------------------------------------------------
Ran 1 test in 0.714s

FAILED (failures=1)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions