AWS CLIのフィルターとクエリーの使い方についてまとめてみた

AWS

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは植木和樹です。本日はaws-cliの機能「フィルター」と「クエリー」について調べてみました。業務上運用簡易化のためのシェルスクリプトを書く機会が多く、必然的にaws-cliを頻繁に利用するのですが、ようやく最近になってフィルターとクエリーを思い通りに書けるようになってきました。

ネットで aws-cli と検索してもJava版のコマンドラインツール(ec2- で始まるコマンドの方)が引っかかったり、公式ドキュメントにも目的に合致するサンプルが掲載されていなかったりと苦労しました。今回は自分の備忘録を兼ねてまとめておきたいと思います。

参考にした資料

環境

  • aws-cli/1.2.5 Python/2.7.6 Darwin/13.0.0

フィルター:出力結果の絞り込み(--filters)

基本的な使い方

フィルター指定は "Name=キー,Values=値" と指定します。

$ aws ec2 describe-tags --filters "Name=resource-type,Values=instance"

{
    "Tags": [
        {
            "ResourceType": "instance",
            "ResourceId": "i-0b3c0a0e",
            "Value": "sophos",
            "Key": "Name"
        },
        :
        :
}

間違って--filters "ResourceType=instance" と指定しないようにしましょう。

最も引っかかりやすい点はフィルターに指定するNameの値が結果に表示される項目名とは異なるということです。上記の例では絞り込みをResourceTypeキーで行うためにresource-typeと指定しています。結果に表示されるキャメルケースで表記されたキーをそのままフィルターに指定できないのでよく混乱します。どうやらAWS APIのフィルター仕様に沿っているようですね。

基本的にはキャメルケースを「すべて小文字にして、単語間をハイフンで区切った」文字列をフィルターに指定すれば良いでしょう。フィルターに指定できる文字列はサブコマンド名に続けてhelpコマンドで確認できます。

$ aws ec2 describe-tags help

FILTERS
   key
       The tag key.

   resource-id
       The resource ID.

   resource-type
       The resource type.

       Valid    Values:    customer-gateway|dhcp-options|image|instance|inter-
       net-gateway|network-acl|network-interface|reserved-instances|route-ta-
       ble|security-group|snapshot|spot-instances-request|subnet|vol-
       ume|vpc|vpn-connection|vpn-gateway

   value
       The tag value.

EC2インスタンスをタグ検索する際の特殊なフィルター

EC2インスタンス一覧を出力するaws ec2 describe-instancesコマンドにはタグで検索するために、tag-key, tag-value, tag:という特殊なフィルター指定があります。次の2つのコマンドは同じ結果を返します。

$ aws ec2 describe-instances \
    --filters "Name=tag-key,Values=Name" \
              "Name=tag-value,Values=cacti"

$ aws ec2 describe-instances --filters "Name=tag:Name,Values=cacti"

AND検索

次の例はEC2インスタンス(i-298a992c)に紐付いたタグを出力します。リソースタイプ(ResourceType)が"instance"かつリソースID(ResourceId)が"i-298a992c"のAND検索をしています。AND検索は--filtersに続けて複数フィルター条件をスペースで並べます。

希望するフィルターを作るために試行錯誤する際には、出力をテーブル形式(--output table)にすると、Excelのオートフィルターっぽく考えられて作業が進めやすいと思います。

$ aws ec2 describe-tags \
    --filters \
      "Name=resource-type,Values=instance" \
      "Name=resource-id,Values=i-298a992c" \
    --output table

---------------------------------------------------
|                  DescribeTags                   |
+-------------------------------------------------+
||                     Tags                      ||
|+------+--------------+----------------+--------+|
||  Key | ResourceId   | ResourceType   | Value  ||
|+------+--------------+----------------+--------+|
||  Name|  i-298a992c  |  instance      |  cacti ||
|+------+--------------+----------------+--------+|

(↑ResourceTypeとResourceIdでフィルターされていることがわかります)

OR検索(キーが同じ)

OR検索をしてみましょう。複数のインスタンスIDを出力してみます。フィルターするキー(ResourceId)は同じなので、Valuesにカンマ区切りでインスタンスIDを指定すればOR検索になります。

$ aws ec2 describe-tags \
    --filters \
      "Name=resource-type,Values=instance" \
      "Name=resource-id,Values=i-0b3c0a0e,i-298a992c" \
    --output table

----------------------------------------------------
|                   DescribeTags                   |
+--------------------------------------------------+
||                      Tags                      ||
|+------+--------------+----------------+---------+|
||  Key | ResourceId   | ResourceType   |  Value  ||
|+------+--------------+----------------+---------+|
||  Name|  i-0b3c0a0e  |  instance      |  sophos ||
||  Name|  i-298a992c  |  instance      |  cacti  ||
|+------+--------------+----------------+---------+|

(↑ResourceTypeとResourceIdでフィルターされていることがわかります)

もう一例。複数のEC2インスタンスをNameタグでOR検索してみます。

  • リソースタイプが "instance"
  • かつ タグのキー名が "Name"
  • かつ タグの値が "cacti" または "sophos"
$ aws ec2 describe-tags \
    --filters \
      "Name=resource-type,Values=instance" \
      "Name=key,Values=Name" \
      "Name=value,Values=sophos,cacti" \
    --output table

----------------------------------------------------
|                   DescribeTags                   |
+--------------------------------------------------+
||                      Tags                      ||
|+------+--------------+----------------+---------+|
||  Key | ResourceId   | ResourceType   |  Value  ||
|+------+--------------+----------------+---------+|
||  Name|  i-0b3c0a0e  |  instance      |  sophos ||
||  Name|  i-298a992c  |  instance      |  cacti  ||
|+------+--------------+----------------+---------+|

(↑ResourceType、Key、Valueでフィルターされていることがわかります)

OR検索(キーが異なる)

キーが異なる場合にOR検索するやり方はないようです。例えば「インスタンスIDが i-XXXXXXXX または NameタグにXXXX がついたEC2インスタンスのみを表示したい」という場合は、それぞれ実行して出力結果をマージしてください。

フィルターの使い方はここまでです。AND検索とOR検索、あとはキー指定時のコツ(APIにならう)さえつかめれば思い通りに使えるようになるかと思います。

クエリー:出力項目の絞り込み(--query)

クエリー機能はaws-cli 1.2で追加されました。

[AWS] AWC CLI 1.2 の queryオプションを試してみた | Developers.IO

条件に合致した結果だけを出力するのがフィルターの役割なら、出力する項目を絞り込むのがクエリーです。SQLでいうと「フィルター=WHERE句」「クエリー=SELECT句」です。たとえばaws ec2 describe-instancesでEC2インスタンス一覧を出力する際に「インスタンスIDのみ」を出力することができます。

クエリーの指定はJMESPath(ジェームズパス)という記法を使います(boto/jmespath)。

1項目のみ出力する

以下の例ではNameタグが設定されているEC2インスタンスについて、インスタンスIDのみを表示しています。クエリーは出力したい項目のパス(Tags - ResourceId)を指定します。Tagsは子要素が複数ある配列なので[*]ですべての子要素を対象にしています。フィルターと違い結果に表示された項目から出力したい項目名を指定すれば良いだけので分かりやすいかと思います。

(クエリー未指定)
$ aws ec2 describe-tags \                                                                  [~]
    --filters \
      "Name=resource-type,Values=instance" \
      "Name=key,Values=Name" \
    --output table
----------------------------------------------------------------
|                         DescribeTags                         |
+--------------------------------------------------------------+
||                            Tags                            ||
|+------+-------------+----------------+----------------------+|
||  Key | ResourceId  | ResourceType   |        Value         ||
|+------+-------------+----------------+----------------------+|
||  Name|  i-0b3c0a0e |  instance      |  sophos              ||
||  Name|  i-298a992c |  instance      |  cacti               ||
:
:
|+------+-------------+----------------+----------------------+|



(クエリー指定)
$ aws ec2 describe-tags \
    --filters \
      "Name=resource-type,Values=instance" \
      "Name=key,Values=Name" \
    --query "Tags[*].ResourceId" \
    --output table

----------------
| DescribeTags |
+--------------+
|  i-0b3c0a0e  |
|  i-298a992c  |
:
:
+--------------+

(↑ ResourceId)

複数項目を出力する

インスタンスID(ResourceID)だけでなく、Nameタグの値(Value)も指定する場合は項目をカンマ区切りで並べ[](ブラケット)で括ります。

$ aws ec2 describe-tags \
    --filters \
      "Name=resource-type,Values=instance" \
      "Name=key,Values=Name" \
    --query "Tags[*].[ResourceId,Value]" \
    --output table

--------------------------------------
|            DescribeTags            |
+-------------+----------------------+
|  i-0b3c0a0e |  sophos              |
|  i-298a992c |  cacti               |
:
:
+-------------+----------------------+

複数項目を項目名付きで出力する

このままだと出力結果に項目名(ResourceId,Value)がつきません。JSON形式で出力する場合は項目名も出力された方が良いでしょう。その場合は出力する項目「識別子:項目名」のペアをカンマ区切りで並べ{}(ブレイス)で括ります。

$ aws ec2 describe-tags \
    --filters \
      "Name=resource-type,Values=instance" \
      "Name=key,Values=Name" \
    --query "Tags[*].{InstanceId:ResourceId, Hostname:Value}" \
    --output table

--------------------------------------
|            DescribeTags            |
+---------------------+--------------+
|      Hostname       | InstanceId   |
+---------------------+--------------+
|  sophos             |  i-0b3c0a0e  |
|  cacti              |  i-298a992c  |
:
:
+---------------------+--------------+

(JSON形式だとこんな感じ)

$ aws ec2 describe-tags \
    --filters \
      "Name=resource-type,Values=instance" \
      "Name=key,Values=Name" \
    --query "Tags[*].{InstanceId:ResourceId, Hostname:Value}" \
    --output json

[
    {
        "InstanceId": "i-0b3c0a0e",
        "Hostname": "sophos"
    },
    {
        "InstanceId": "i-298a992c",
        "Hostname": "cacti"
    },
:
:
]

まとめ

本日は自分用備忘録としてaws-cliのフィルターとクエリーの使用方法をまとめてみました。以前はこの辺の使い方がよく分からずフィルターもクエリーもjqに頼っていた部分が多々あるのですが、最近はaws-cli単体で処理できるのであれば、なるべくaws-cliだけで済ませようとしています。

今回のエントリがみなさんのaws-cli活用の参考になれば幸いです。