AWS：EC2インスタンスの情報を取得したいとき

EC2インスタンスの情報を取得したいとき、GUIでワンオペワンショットで画面キャプチャもではなく、コマンドで一括でCSV取得する方法。


# 前提条件
・CloudShellを利用する。
・タグNameでEC2インスタンスを識別している

# 全インスタンス情報を標準出力
```shell-session:CloudShell
$ aws ec2 describe-instances --query 'Reservations[].Instances[].{Name:Tags[?Key==`Name`].Value|[0],ImageId:ImageId,PlatformDetails:PlatformDetails,InstanceType:InstanceType,KeyName:KeyName,ENI01VpcId:NetworkInterfaces[].VpcId|[0],ENI01SubnetId:NetworkInterfaces[].SubnetId|[0],ENI01SecurityGroup:NetworkInterfaces[].Groups[].GroupName|[0],ENI01NetworkInterfaceId:NetworkInterfaces[].NetworkInterfaceId|[0],ENI01PuclicIpAddress:NetworkInterfaces[].Association.PublicIp|[0],ENI01PrivateIpAddress:NetworkInterfaces[].PrivateIpAddress|[0],ENI01SourceDestCheck:NetworkInterfaces[].SourceDestCheck|[0], ENI02VpcId:NetworkInterfaces[].VpcId|[1], ENI02SubnetId:NetworkInterfaces[].SubnetId|[1], ENI02SecurityGroup:NetworkInterfaces[].Groups[].GroupName|[1], ENI02NetworkInterfaceId:NetworkInterfaces[].NetworkInterfaceId|[1], ENI02PuclicIpAddress:NetworkInterfaces[].Association.PublicIp|[1], ENI02PrivateIpAddress:NetworkInterfaces[].PrivateIpAddress|[1], ENI02SourceDestCheck:NetworkInterfaces[].SourceDestCheck|[1], ENI03VpcId:NetworkInterfaces[].VpcId|[2], ENI03SubnetId:NetworkInterfaces[].SubnetId|[2], ENI03SecurityGroup:NetworkInterfaces[].Groups[].GroupName|[2], ENI03NetworkInterfaceId:NetworkInterfaces[].NetworkInterfaceId|[2], ENI03PuclicIpAddress:NetworkInterfaces[].Association.PublicIp|[2], ENI03PrivateIpAddress:NetworkInterfaces[].PrivateIpAddress|[2], ENI03SourceDestCheck:NetworkInterfaces[].SourceDestCheck|[2],ENI04VpcId:NetworkInterfaces[].VpcId|[3], ENI04SubnetId:NetworkInterfaces[].SubnetId|[3], ENI04SecurityGroup:NetworkInterfaces[].Groups[].GroupName|[3], ENI04NetworkInterfaceId:NetworkInterfaces[].NetworkInterfaceId|[3], ENI04PuclicIpAddress:NetworkInterfaces[].Association.PublicIp|[3], ENI04PrivateIpAddress:NetworkInterfaces[].PrivateIpAddress|[3], ENI04SourceDestCheck:NetworkInterfaces[].SourceDestCheck|[3],  RootDeviceType:RootDeviceType, RootDeviceName:RootDeviceName, RootVolDeleteOnTermination:BlockDeviceMappings|[0].Ebs.DeleteOnTermination, SecondDeviceName:BlockDeviceMappings|[1].DeviceName, SecondVolDeleteOnTermination:BlockDeviceMappings|[1].Ebs.DeleteOnTermination, ThirdDeviceName:BlockDeviceMappings|[2].DeviceName, ThirdVolDeleteOnTermination:BlockDeviceMappings|[2].Ebs.DeleteOnTermination, FourthDeviceName:BlockDeviceMappings|[3].DeviceName, FourthVolDeleteOnTermination:BlockDeviceMappings|[3].Ebs.DeleteOnTermination, IAMPolicy:IamInstanceProfile.Arn, DetailMonitoring:Monitoring.State}'
```

```json:実行結果
[
{
        "Name": "test-instance",
        "ImageId": "ami-XXXXXXXXXXXXXXX",
        "PlatformDetails": "Linux/UNIX",
        "InstanceType": "t2.micro",
        "KeyName": null,
        "ENI01VpcId": "vpc-XXXXXXXXXXXXXXX,
        "ENI01SubnetId": "subnet-XXXXXXXXXXXXXXX",
        "ENI01SecurityGroup": "TESTSecurityGroup",
        "ENI01NetworkInterfaceId": "eni-XXXXXXXXXXXXXXX",
        "ENI01PuclicIpAddress": null,
        "ENI01PrivateIpAddress": "1.1.1.1",
        "ENI01SourceDestCheck": true,
        "ENI02VpcId": null,
        "ENI02SubnetId": null,
        "ENI02SecurityGroup": null,
        "ENI02NetworkInterfaceId": null,
        "ENI02PuclicIpAddress": null,
        "ENI02PrivateIpAddress": null,
        "ENI02SourceDestCheck": null,
        "ENI03VpcId": null,
        "ENI03SubnetId": null,
        "ENI03SecurityGroup": null,
        "ENI03NetworkInterfaceId": null,
        "ENI03PuclicIpAddress": null,
        "ENI03PrivateIpAddress": null,
        "ENI03SourceDestCheck": null,
        "ENI04VpcId": null,
        "ENI04SubnetId": null,
        "ENI04SecurityGroup": null,
        "ENI04NetworkInterfaceId": null,
        "ENI04PuclicIpAddress": null,
        "ENI04PrivateIpAddress": null,
        "ENI04SourceDestCheck": null,
        "RootDeviceType": "ebs",
        "RootDeviceName": "/dev/xvda",
        "RootVolDeleteOnTermination": true,
        "SecondDeviceName": null,
        "SecondVolDeleteOnTermination": null,
        "ThirdDeviceName": null,
        "ThirdVolDeleteOnTermination": null,
        "FourthDeviceName": null,
        "FourthVolDeleteOnTermination": null,
        "IAMPolicy": "arn:aws:iam::XXXXXXXXXXXXXXX:instance-profile/TEST",
        "DetailMonitoring": "disabled"
    },
・・・（続く）
```

コマンド1行が異常に長いが、これがJMESPathの癖。

（以下、アンミカ風）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229539/51f79357-017c-72d6-ae64-5cc0b1af9b02.png)

> ふつう円マーク（\）で改行できるやん？
Linuxコマンドやと\で改行できるやん？jqもできるやん？
でもJMESPathはできへんの！だから1行がものすっごい長なるん。
だからこの一行の文字数って900あんねん。

（アンミカ風終わり）

1インスタンスにぶら下がる、ENIとEBSは4つまで取得できるようにしている。
で、これだと意味不明なJSON情報だけなので、これをキレイに加工していく。


# 全インスタンス情報を標準出力（CSV形式に加工して、CSV出力）
```shell-session:CloudShell
$ aws ec2 describe-instances --query 'Reservations[].Instances[].{Name:Tags[?Key==`Name`].Value|[0],ImageId:ImageId,PlatformDetails:PlatformDetails,InstanceType:InstanceType,KeyName:KeyName,ENI01VpcId:NetworkInterfaces[].VpcId|[0],ENI01SubnetId:NetworkInterfaces[].SubnetId|[0],ENI01SecurityGroup:NetworkInterfaces[].Groups[].GroupName|[0],ENI01NetworkInterfaceId:NetworkInterfaces[].NetworkInterfaceId|[0],ENI01PuclicIpAddress:NetworkInterfaces[].Association.PublicIp|[0],ENI01PrivateIpAddress:NetworkInterfaces[].PrivateIpAddress|[0],ENI01SourceDestCheck:NetworkInterfaces[].SourceDestCheck|[0], ENI02VpcId:NetworkInterfaces[].VpcId|[1], ENI02SubnetId:NetworkInterfaces[].SubnetId|[1], ENI02SecurityGroup:NetworkInterfaces[].Groups[].GroupName|[1], ENI02NetworkInterfaceId:NetworkInterfaces[].NetworkInterfaceId|[1], ENI02PuclicIpAddress:NetworkInterfaces[].Association.PublicIp|[1], ENI02PrivateIpAddress:NetworkInterfaces[].PrivateIpAddress|[1], ENI02SourceDestCheck:NetworkInterfaces[].SourceDestCheck|[1], ENI03VpcId:NetworkInterfaces[].VpcId|[2], ENI03SubnetId:NetworkInterfaces[].SubnetId|[2], ENI03SecurityGroup:NetworkInterfaces[].Groups[].GroupName|[2], ENI03NetworkInterfaceId:NetworkInterfaces[].NetworkInterfaceId|[2], ENI03PuclicIpAddress:NetworkInterfaces[].Association.PublicIp|[2], ENI03PrivateIpAddress:NetworkInterfaces[].PrivateIpAddress|[2], ENI03SourceDestCheck:NetworkInterfaces[].SourceDestCheck|[2],ENI04VpcId:NetworkInterfaces[].VpcId|[3], ENI04SubnetId:NetworkInterfaces[].SubnetId|[3], ENI04SecurityGroup:NetworkInterfaces[].Groups[].GroupName|[3], ENI04NetworkInterfaceId:NetworkInterfaces[].NetworkInterfaceId|[3], ENI04PuclicIpAddress:NetworkInterfaces[].Association.PublicIp|[3], ENI04PrivateIpAddress:NetworkInterfaces[].PrivateIpAddress|[3], ENI04SourceDestCheck:NetworkInterfaces[].SourceDestCheck|[3],  RootDeviceType:RootDeviceType, RootDeviceName:RootDeviceName, RootVolDeleteOnTermination:BlockDeviceMappings|[0].Ebs.DeleteOnTermination, SecondDeviceName:BlockDeviceMappings|[1].DeviceName, SecondVolDeleteOnTermination:BlockDeviceMappings|[1].Ebs.DeleteOnTermination, ThirdDeviceName:BlockDeviceMappings|[2].DeviceName, ThirdVolDeleteOnTermination:BlockDeviceMappings|[2].Ebs.DeleteOnTermination, FourthDeviceName:BlockDeviceMappings|[3].DeviceName, FourthVolDeleteOnTermination:BlockDeviceMappings|[3].Ebs.DeleteOnTermination, IAMPolicy:IamInstanceProfile.Arn, DetailMonitoring:Monitoring.State}' \
 | jq '.[]' | jq -rs '(.[0]|keys_unsorted),map([.[]])[]|@csv' > ec2-all.csv
```

実行すると、CloudShellのカレントディレクトリに「ec2-all.csv」が生成される。
```shell-session:ec2-all.csv
$ head ec2-all.csv 
"Name","ImageId","PlatformDetails","InstanceType","KeyName","ENI01VpcId","ENI01SubnetId","ENI01SecurityGroup","ENI01NetworkInterfaceId","ENI01PuclicIpAddress","ENI01PrivateIpAddress","ENI01SourceDestCheck","ENI02VpcId","ENI02SubnetId","ENI02SecurityGroup","ENI02NetworkInterfaceId","ENI02PuclicIpAddress","ENI02PrivateIpAddress","ENI02SourceDestCheck","ENI03VpcId","ENI03SubnetId","ENI03SecurityGroup","ENI03NetworkInterfaceId","ENI03PuclicIpAddress","ENI03PrivateIpAddress","ENI03SourceDestCheck","ENI04VpcId","ENI04SubnetId","ENI04SecurityGroup","ENI04NetworkInterfaceId","ENI04PuclicIpAddress","ENI04PrivateIpAddress","ENI04SourceDestCheck","RootDeviceType","RootDeviceName","RootVolDeleteOnTermination","SecondDeviceName","SecondVolDeleteOnTermination","ThirdDeviceName","ThirdVolDeleteOnTermination","FourthDeviceName","FourthVolDeleteOnTermination","IAMPolicy","DetailMonitoring"
"test-instance","ami-XXXXXXX","Windows","t2.micro","pemkey","vpc-XXXXXXXXXXXXXXX","subnet-XXXXXXXXXXXXXXX","test-secgrp","eni-XXXXXXXXXXXXXXX","1.1.1.1","2.2.2.2",true,,,,,,,,,,,,,,,,,,,,,,"ebs","/dev/sda1",true,,,,,,,,"disabled"

```

「ec2-all.csv」をダウンロードして、あとはよしなにExcelで設計書感あるように修正して、いい感じに見繕う。

ダウンロードするときはこんな感じ
```shell-session:CloudShell
$ ls -ld ${HOME}/* | grep ec2-all.csv
-rw-rw-r-- 1 cloudshell-user cloudshell-user    39686 Jan 27 08:27 /home/cloudshell-user/ec2-all.csv
```
これでCSVの絶対パスが出るので、CloudShellのGUIよりこの絶対パスを指定してダウンロードする。（/home/cloudshell-user/ec2-all.csv）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229539/0e9ce7f4-31d4-e323-7e51-d63ec35edc3a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229539/6bdebfd1-7de2-84d8-4d53-f326104ca23f.png)


# 参考URL
jq と JMESPath を同時に覚える
https://www.techscore.com/blog/2019/09/30/jq-%E3%81%A8-jmespath-%E3%82%92%E5%90%8C%E6%99%82%E3%81%AB%E8%A6%9A%E3%81%88%E3%82%8B/

↑jqに馴染みがなかった自分によって、非常にためになった記事。jqとJMESPathは微妙に違う。awscliは便利なんだけど、使いこなすにはこの2つを覚える必要があり、スキル習得の難易度があがってる感じ。AWSさん、ここなんとかしてれないっすかね。JMESPathはあんまり好きでない・・・。jqに統合してほしい。

AWS CLI でインスタンス情報を取得
https://qiita.com/m-chika/items/fd2505a565755a7827e3

EC2インスタンスの情報をCLIとjqをつかってcsvにする。
https://manatee-tech.com/posts/cli-jq-output-csv