In a recent investigation, we found an interesting difference between AWS command line tools (based on Boto library) and AWS Web interface. Apparently, command line tools are case sensitive while AWS Web interface is not. This can potentially lead to automated scaling issues. Tooling may not get ‘the full picture’ if tags are mixed-case and software does not account for that.
Lets start with simple example …
We have the following EC2 instances in AWS Account:
Search for the term ‘TEST-NODE’ yields the same results as searching for ‘test-node’ in the AWS Web interface.
… it behaves the same way. It is case-insensitive.
However, commend line tools will produce totally different output.
Searching for ‘TEST-NODE':
1 2 3 |
:~> aws ec2 describe-instances --filters "Name=tag:Name,Values=*TEST-NODE*" --query 'Reservations[*].Instances[*].Tags[?Key==`Name`].Value[]' --output text TEST-NODE-1 :~> |
Searching for ‘test-node':
1 2 3 |
:~> aws ec2 describe-instances --filters "Name=tag:Name,Values=*test-node*" --query 'Reservations[*].Instances[*].Tags[?Key==`Name`].Value[]' --output text test-node-5 :~> |
Python + Boto shows the same behavior (not surprisingly, AWS CLI uses Boto):
Searching for ‘TEST-NODE':
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
:~> python Python 2.7.5 (default, Mar 9 2014, 22:15:05) [GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import boto >>> import boto.ec2 >>> conn = boto.ec2.connect_to_region('us-east-1', aws_access_key_id='', aws_secret_access_key='') >>> reservations = conn.get_all_instances(filters = {'instance-state-name' : 'running', "tag:Name": "*" + 'TEST-NODE' + "*"}) >>> for r in reservations: ... for i in r.instances: ... print i.tags['Name'] ... TEST-NODE-1 >>> ^D :~> |
Searching for ‘test-node':
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
:~> python Python 2.7.5 (default, Mar 9 2014, 22:15:05) [GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import boto >>> import boto.ec2 >>> conn = boto.ec2.connect_to_region('us-east-1', aws_access_key_id='', aws_secret_access_key='') >>> reservations = conn.get_all_instances(filters = {'instance-state-name' : 'running', "tag:Name": "*" + 'test-node' + "*"}) >>> for r in reservations: ... for i in r.instances: ... print i.tags['Name'] ... test-node-5 >>> ^D :~> |
Moral of the story: ALWAYS VERIFY/ENFORCE THAT DATA IS PROPERLY FORMATTED!
There are multiple possible solutions to this issue. With the cost of few extra cycles one can make sure proper comparison is implemented:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
:~> python Python 2.7.5 (default, Mar 9 2014, 22:15:05) [GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import boto >>> import boto.ec2 >>> conn = boto.ec2.connect_to_region('us-east-1', aws_access_key_id='', aws_secret_access_key='') >>> reservations = conn.get_all_instances(filters = {'instance-state-name' : 'running'}) >>> for r in reservations: ... for i in r.instances: ... if 'test-node'.upper() in i.tags['Name'].upper(): ... print i.tags['Name'] ... TEST-NODE-1 TEST-Node-2 TEST-node-3 test-node-5 >>> ^D :~> |
References
Related Posts
- Small Tip: How to use AWS CLI ‘–filter’ parameter
- Small Tip: How to use –block-device-mappings to manage instance volumes with AWS CLI
- Small Tip: How to use AWS CLI to start Spot instances with UserData
- Small Tip: AWS announces T2 instance types
- Small Tip: EBS volume allocation time is linear to the size and unrelated to the instance type