Bulk tagging all instances in an Auto Scaling Group (ASG) using AWS CLI and JMESPath Expressions – sathyasays.com
This page looks best with JavaScript enabled

Bulk tagging all instances in an Auto Scaling Group (ASG) using AWS CLI and JMESPath Expressions

 ·   ·  ☕ 4 min read  ·  ✍️ Sathyajith Bhat · 👀... views

Thumbnail image generated by Stable Diffusion Online with the prompt: applying name tags to a server in a data center.

Why?

I wanted to tag all the instances in an AWS Auto Scaling Group (ASG) with some tags that would be used for reporting. The first order of business was to update the ASG with the relevant tags. This was done by applying the tag to the ASG using Infrastructure as Code (Terraform, in this case) so that all new instances launched would get the tag. However, the existing nodes would not inherit the tags.

While I could recycle the nodes, instance refresh makes it that much easier. Still, I figured bulk tagging the instances in the ASG was a simpler way to set the tags.

Filtering with AWS CLI

Since I wanted to tag instances of a specific ASG, I tried to use jq on the output of the aws ec2 describe-auto-scaling-groups command and further slice and dice the data. This was getting too painful, so I started to dig into AWS CLI’s docs and found out that the AWS CLI can apply client-side filtering using the --query option and server-side filtering using the --filter option.

Querying Auto Scaling Group Instances

The aws autoscaling describe-auto-scaling-groups command has a response structure as shown below:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
[
    {
        "AutoScalingGroupName": "name",
        "AutoScalingGroupARN": "arn",
        "LaunchConfigurationName": "lc-name",
        "MinSize": 1,
        "MaxSize": 1,
        "DesiredCapacity": 1,
        "DefaultCooldown": 300,
        "AvailabilityZones": [
            "ap-southeast-1a",
            "ap-southeast-1c"
        ],
        "LoadBalancerNames": [],
        "TargetGroupARNs": [],
        "HealthCheckType": "EC2",
        "HealthCheckGracePeriod": 0,
        "Instances": [
            {
                "InstanceId": "",
                "InstanceType": "",
                "AvailabilityZone": "",
                "LifecycleState": "",
                "HealthStatus": "",
                "LaunchConfigurationName": "",
                "ProtectedFromScaleIn": false
            }
        ],
        "CreatedTime": "",
        "SuspendedProcesses": [],
        "VPCZoneIdentifier": "",
        "EnabledMetrics": [],
        "Tags": [],
        "TerminationPolicies": [
            "Default"
        ],
        "NewInstancesProtectedFromScaleIn": false,
        "ServiceLinkedRoleARN": "arn",
        "TrafficSources": []
    }
]

To query, the AWS CLI uses expressions created using JMESPath Syntax. From the response above, we want to select the instance IDs of a specific Auto Scaling Group. In JMESPath query, the question mark ? is used to filter and select elements. Thus, to filter based on AutoScaling Group name, the JMESPath Expression would be as shown below, replacing asg-name with the actual name of the Auto Scaling Group:

AutoScalingGroups[?AutoScalingGroupName==`asg-name`]

Filtering Instances Based on Auto Scaling Group

Since I further want to select only the instance IDs, the JMESPath expression of the instance ID .Instances[*].InstanceId can be chained to the above query condition. Thus, the command to fetch the instance IDs from a specific Auto Scaling Group becomes as shown below, taking care to replace region and asg-name with the region name and the ASG name, respectively.

1
aws autoscaling describe-auto-scaling-groups --region region --query 'AutoScalingGroups[?AutoScalingGroupName==`asg-name`].Instances[*].InstanceId'

Now that there’s a list of instance IDs, these IDs can be passed over to the aws ec2 create-tags command to apply the tag to all the instances.

1
aws ec2 create-tags --region ap-southeast-1 --tags Key=tagKey,Value=tagValue --resources $(aws autoscaling describe-auto-scaling-groups --region region --query 'AutoScalingGroups[?AutoScalingGroupName==`asg-name`].Instances[*].InstanceId' --output text)

Verifying the results

Applying what I learned above, I verified that all the instances have been correctly tagged by using the below command, taking care to replace region and asg-name with the region name and the ASG name, respectively.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
aws ec2 describe-instances --region ap-southeast-1 --filters "Name=tag:aws:autoscaling:groupName,Values='asg-name'" --query "Reservations[].Instances[].{Instance:InstanceId,Name:Tags[?Key=='Name']|[0].Value}" --output table

-------------------------------------------
|            DescribeInstances            |
+----------------------+------------------+
|       Instance       |      Name        |
+----------------------+------------------+
|  i-0xdeadbeef456242  |  asg-nme-1234    |
|  i-0xdeadbeef454142  |  asg-nme-1235    |
-------------------------------------------

In the above command, the --filter option applies server-side filtering and fetches the instances that have the tag, tag:aws:autoscaling:groupName as the tag key and asg-name as the tag value. This is then chained with the client-side filter --query to display the instance ID and the name of the instance by fetching the tag with key Name.

Share on

Sathyajith Bhat
WRITTEN BY
Sathyajith Bhat
Author, AWS Container Hero and DevOps Specialist

What's on this Page