【AWS】AWSCLIの「filter」と「query」の使い方について(備忘録)

# はじめに
AWSCLIの確認コマンドでよく用いられる`filter`と`query`の使い方について備忘録を書きたいと思います。

:::note warn
全てのパターンは網羅できておりませんので、ご了承下さい。
:::

# 前提
今回はサブネット一覧を確認するコマンド`aws ec2 describe-subnets`の使用を通して、`filter`と`query`の使い方をご紹介していければと思います。

# filterとは？
filterとは、**出力結果の絞り込み**で使用するオプションになります。

## filterの使用例

### 1つの項目から出力結果を絞る
複数あるサブネットからサブネットID「subnet-0e4fe7412ac22561f」に該当するサブネットのみに出力結果を絞ります。

```zsh:コマンド
aws ec2 describe-subnets \
--filter "Name=subnet-id,Values=subnet-0e4fe7412ac22561f"
```

フィルターする内容は、以下になります。

|  Name  |  Values  |  備考  |
| ---- | ---- | ---- |
|  subnet-id  | subnet-0e4fe7412ac22561f   |  `SubnetID`は`subnet-id`と入力  |


```zsh:実行例
% aws ec2 describe-subnets --filter "Name=subnet-id,Values=subnet-0e4fe7412ac22561f"
{
    "Subnets": [
        {
            "AvailabilityZone": "ap-northeast-1c",
            "AvailabilityZoneId": "apne1-az1",
            "AvailableIpAddressCount": 4091,
            "CidrBlock": "192.168.16.0/20",
            "DefaultForAz": false,
            "MapPublicIpOnLaunch": false,
            "MapCustomerOwnedIpOnLaunch": false,
            "State": "available",
            "SubnetId": "subnet-0e4fe7412ac22561f",
〜〜〜〜続く〜〜〜〜
```

:::note warn
コマンドを入力する際のNameの部分は、「SubnetId」→「subnet-id」とします。
※表示名と入力するNameの値は違うので、必要に応じて確認が必要です。
:::

### タグの情報から出力結果を絞る

```zsh:コマンド
aws ec2 describe-subnets \
--filter "Name=tag-key,Values=Name" \
 "Name=tag-value,Values=TestVPC-subnet-private2-ap-northeast-1c"
```

フィルターする内容は、以下になります。

|  Name  |  Values  |  備考  |
| ---- | ---- | ---- |
|  tag-key  | Name  | Tagsの中のKeyを指定   |
|  tag-value  | TestVPC-subnet-private2-ap-northeast-1c  | Tagsの中のValueを指定 |

```zsh:実行例
% aws ec2 describe-subnets \
--filter "Name=tag-key,Values=Name" \
 "Name=tag-value,Values=TestVPC-subnet-private2-ap-northeast-1c"
{
    "Subnets": [
        {
            "AvailabilityZone": "ap-northeast-1c",
            "AvailabilityZoneId": "apne1-az1",
〜〜〜〜省略〜〜〜〜
            "Ipv6CidrBlockAssociationSet": [],
            "Tags": [
                {
                    "Key": "Name",
                    "Value": "TestVPC-subnet-private2-ap-northeast-1c"
                }
            ],
            "SubnetArn": "arn:aws:ec2:ap-northeast-1:555246305565:subnet/subnet-01a0789d880d1fd7f",
〜〜〜〜省略〜〜〜〜
```


# queryとは？
queryとは、**出力項目の絞り込み**で用いられるオプションになります。

## queryの使用例

### 全てのサブネットから1つの項目(`SubnetId`)のみ抽出して出力

```zsh:コマンド
aws ec2 describe-subnets \
--query "Subnets[*].SubnetId"
```

queryする内容は以下になります。

|  大項目  |  小項目  |  備考  |
| ---- | ---- | ---- |
|  Subnets[*]  | SubnetId  | ・大項目を入力する場合は語尾に`[*]`を付ける。<br>・filterとは異なりqueryは小項目をそのまま指定(例:SubnetId)  |

```zsh:実行例
% aws ec2 describe-subnets --query "Subnets[*].AvailabilityZone"
[
    "ap-northeast-1c",
    "ap-northeast-1a",
    "ap-northeast-1a",
    "ap-northeast-1a",
    "ap-northeast-1c"
]
%
```

:::note info
queryの場合は、そのまま`SubnetId`と記載します。
※filterの場合は、`subnet-id`になります。
:::


### 全てのサブネットから複数項目(`AvailabilityZone`,`SubnetId`　)を出力

```zsh:コマンド
aws ec2 describe-subnets \
--query "Subnets[*].[AvailabilityZone,SubnetId]"
```

queryする内容は以下になります。

|  大項目  |  小項目  |  備考  |
| ---- | ---- | ---- |
|  Subnets[*]  | AvailabilityZone,SubnetId  | 小項目と小項目の間は`,`で絞る  |

```zsh:実行例
% aws ec2 describe-subnets \
--query "Subnets[*].[AvailabilityZone,SubnetId]"
[
    [
        "ap-northeast-1c",
        "subnet-0e4fe7412ac22561f"
    ],
    [
        "ap-northeast-1a",
        "subnet-08fcf6ceed48d1a2c"
    ],
    [
        "ap-northeast-1a",
        "subnet-00dcd4caf121aac0a"
    ],
    [
        "ap-northeast-1a",
        "subnet-09484b8e38ec7a527"
    ],
    [
        "ap-northeast-1c",
        "subnet-01a0789d880d1fd7f"
    ]
]
%
```

### 全てのサブネットから複数項目(`AvailabilityZone`,`SubnetId`　)を項目名付きで出力

```zsh:実行コマンド
aws ec2 describe-subnets \
--query "Subnets[*].{AZ:AvailabilityZone,ID:SubnetId}"
```

```zsh:実行例
% aws ec2 describe-subnets \
--query "Subnets[*].{AZ:AvailabilityZone,ID:SubnetId}"
[
    {
        "AZ": "ap-northeast-1c",
        "ID": "subnet-0e4fe7412ac22561f"
    },
    {
        "AZ": "ap-northeast-1a",
        "ID": "subnet-08fcf6ceed48d1a2c"
    },
    {
        "AZ": "ap-northeast-1a",
        "ID": "subnet-00dcd4caf121aac0a"
    },
    {
        "AZ": "ap-northeast-1a",
        "ID": "subnet-09484b8e38ec7a527"
    },
    {
        "AZ": "ap-northeast-1c",
        "ID": "subnet-01a0789d880d1fd7f"
    }
]
%
```

項目無しと項目有りに違いは以下になります。

|  項目  |  コマンド  |  備考  |
| ---- | ---- | ---- |
|  項目無し | "Subnets[*].[AvailabilityZone,SubnetId]"  | `AvailabilityZone,SubnetId`を`[]`で囲う |
|  項目無し | "Subnets[*].{AZ:AvailabilityZone,ID:SubnetId}"  | ・`{任意の項目名:項目,任意の項目名:項目}`という形にする。<br>・`AZ:AvailabilityZone,ID:SubnetId`を`{}`で囲う |

# その他

## filterとqueryの組み合わせ
filterとqueryの組み合わせで以下のようにすることも可能。

```zsh:コマンド
aws ec2 describe-subnets \
--filter "Name=subnet-id,Values=subnet-0e4fe7412ac22561f" \
--query "Subnets[*].{AZ:AvailabilityZone,ID:SubnetId}"
```

上記コマンドの意味は、以下になります。

|  オプション  |  意味  |
| ---- | ---- |
|  --filter  |  全てのサブネット一覧からサブネットIDが`subnet-0e4fe7412ac22561f`であるものを検索  |
|  --query  |  出力を`AvailabilityZone`と`SubnetId`に限定し、項目名を付与する。  |

```zsh:実行例
% aws ec2 describe-subnets \
--filter "Name=subnet-id,Values=subnet-0e4fe7412ac22561f" \
--query "Subnets[*].{AZ:AvailabilityZone,ID:SubnetId}"
[
    {
        "AZ": "ap-northeast-1c",
        "ID": "subnet-0e4fe7412ac22561f"
    }
]
%
```

## テーブル形式での表示
`--output table`のオプションを付与すると、以下のような表示も可能です。

```zsh:実行例
% aws ec2 describe-subnets \
--query "Subnets[*].{AZ:AvailabilityZone,CIDR:CidrBlock}" \
--output table
-----------------------------------------
|            DescribeSubnets            |
+------------------+--------------------+
|        AZ        |       CIDR         |
+------------------+--------------------+
|  ap-northeast-1c |  192.168.16.0/20   |
|  ap-northeast-1a |  192.168.128.0/20  |
|  ap-northeast-1a |  172.31.0.0/24     |
|  ap-northeast-1a |  192.168.0.0/20    |
|  ap-northeast-1c |  192.168.144.0/20  |
+------------------+--------------------+
%
```


# まとめ
`filter`と`query`の違いは、以下になります。

|  オプション  |  意味  |
| ---- | ---- |
|  --filter  |  出力結果の絞り込み  |
|  --query  |  出力項目の絞り込み  |

# 参考
https://dev.classmethod.jp/articles/aws-cli-filter-and-query-howto/