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:
[
{
"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.
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.
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.
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.