ようへいの日々精進XP

よかろうもん

俺は AWS について何も解っていなかった 〜 ec2 describe instances の Filters オプションでタグによる検索をしたい場合 〜

やりたかった事

EC2 タグ Key = foo と Value = true が付与されているインスタンス ID を取得したかった。

+------------+-----+-------+
| INSTANCEID | KEY | VALUE |
+------------+-----+-------+
| i-a7fe057c | foo | true  |
+------------+-----+       +
| i-45ada37f | bar |       |
+------------+-----+-------+
| i-831bccdb | foo | false |
+------------+-----+-------+

これらのインスタンス ID はフィクションです。

解っていなかった事

知ったかぶりをして

ドキュメントを読まずに知ったかぶりをして以下のように書いた。

>>> import boto3
>>> ec2 = boto3.client('ec2', endpoint_url='http://127.0.0.1:5000')
>>>
>>> response = ec2.describe_instances(Filters=[{'Name':'tag-key','Values':['foo']},{'Name':'tag-value','Values':['true']}])
>>> [instance['InstanceId'] for r in response['Reservations'] for instance in r['Instances']]
['i-a7fe057c']

一応、意図した通りのインスタンス ID が取得出来ている。

ところが、ドキュメントを読むと…

Filters で指定出来るオプションにて、タグに関するオプションは以下のように書かれている。

  • tag :key =value - The key/value combination of a tag assigned to the resource. Specify the key of the tag in the filter name and the value of the tag in the filter value. For example, for the tag Purpose=X, specify tag:Purpose for the filter name and X for the filter value.
  • tag-key - The key of a tag assigned to the resource. This filter is independent of the tag-value filter. For example, if you use both the filter “tag-key=Purpose” and the filter “tag-value=X”, you get any resources assigned both the tag key Purpose (regardless of what the tag’s value is), and the tag value X (regardless of what the tag’s key is). If you want to list only resources where Purpose is X, see the tag :key =value filter.
  • tag-value - The value of a tag assigned to the resource. This filter is independent of the tag-key filter.

今回のように EC2 タグからフィルタして一意のインスタンス ID が欲しい場合、tag-keytag-value を併用するのでは無く、tag:foo = true と指定するべきらしい。

こんな感じ

>>> response = ec2.describe_instances(Filters=[{'Name':'tag:foo','Values':['true']}])
>>> [instance['InstanceId'] for r in response['Reservations'] for instance in r['Instances']]
['i-a7fe057c']

先程と同様に意図した通りのインスタンス ID が取得出来ている。

ということで

このメモを書くきっかけ

とあるお仕事で tag-keytag-value を使った状態でフィルタした場合、意図した結果が返って来なくてドキュメントをよく読んでみたら…というのがきっかけ。

検証した結果だと、tag-keytag-value の併用と tag:Name = value で結果が変わらなかった(意図した挙動になった)ので「アレレ」という状態なのだが、ドキュメントに書かれていることを信じて、今後は tag:Name = value を使っていこうと思う。

Python のリスト内包表記

ついつい、以下のように書いてしまうけど…

>>> for r in response['Reservations']:
...     for instance in r['Instances']:
...         instance_ids.append(instance['InstanceId'])

リスト内包表記だと以下のようにシンプルに書けたのが気持ち良かった。

[instance['InstanceId'] for r in response['Reservations'] for instance in r['Instances']]