【AWS】Boto3で攻略！ EC2のすべて

### はじめに
Boto3を使ってAWSコンソールのEC2一覧に表示されている情報取得をやっていく。
EC2の情報がほしい時の参考に。

Boto3とは、PythonでAWSの各種サービスを簡単に扱えるようにするライブラリ。
今回はこちら:point_down:のBoto3 EC2を参照します。

https://boto3.amazonaws.com/v1/documentation/api/1.9.42/reference/services/ec2.html

### 構成
構成はこちら。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288944/7b778ebe-4048-ae8b-f5a0-05306df100b5.png)

API Gatewayを使ったのは、Lambdaを実行する際にアクセス制限をしたかったからです。
下図は、API GatewayのリソースポリシーでIPアドレス制限を入れた例です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288944/75ac5e16-fe38-2d75-5a33-09d08695cb8b.png)

LambdaでBoto3を使います。
Boto3を使うためにLambdaの先頭でimportします。

```python:lambda_function.py
import boto3

ec2_client = boto3.client('ec2')
```

また、Lambdaのアクセス権限で付与されているロールに「AmazonEC2ReadOnlyAccess」を追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288944/408c6e0d-c8f9-2cde-9ae5-7912e5b515ab.png)

それではやっていきましょう！

### EC2のすべて

AWSコンソールのEC2一覧です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288944/3334295d-2e20-2088-4d6b-a9ad0b18d6e7.png)

EC2一覧の右上の :gear: マークをクリックすると一覧の表示項目がわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288944/43a39706-1458-5d03-1121-87943e81e4ee.png)

それぞれの項目の値を取得していきます。

#### :o: Name

* 「Name」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「Tags」
つまり、EC2インスタンスのタグNameの値
* タグのキーがNameの値を取得

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
    jsonObj['Name'] = ""
        for tag in instance['Tags']:
            if tag.get('Key') and tag['Key'] == 'Name':
                jsonObj['Name'] = tag['Value']
```

#### :o: インスタンスID

* 「インスタンスID」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「InstanceId」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['インスタンスID'] = instance['InstanceId']
```

#### :o: インスタンスの状態

* 「インスタンスの状態」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「State」

```python:lambda_function.py
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['インスタンスの状態'] = instance['State']['Name']
```

#### :o: インスタンスタイプ

* 「インスタンスタイプ」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「InstanceType」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['インスタンスタイプ'] = instance['InstanceType']
```

#### :o: ステータスチェック

* 「ステータスチェック」はBoto3のメソッド「describe_instance_status」で取得した「SystemStatus」の「Status」と「describe_instance_status」で取得した「InstanceStatuses」の「Status」
* InstanceIdsに「describe_instances」で取得した「InstanceId」を指定
* SystemStatusは、物理ホストの問題などAWSの関与が必要な問題のチェック
* InstanceStatusesは、メモリ枯渇などユーザの関与が必要な問題のチェック
* EC2起動後は、どちらのStatusもOKになるまで待つ

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['ステータスチェック'] = []
        instancestatuses = ec2_client.describe_instance_status(InstanceIds=[instance['InstanceId']])
        for instancestatuse in instancestatuses['InstanceStatuses']:
            jsonObj['ステータスチェック'].append(instancestatuse['SystemStatus']['Status'])
            jsonObj['ステータスチェック'].append(instancestatuse['InstanceStatus']['Status'])
```

#### :o: アラームの状態（未確認）

* CloudWatchのアラームから取得
* EC2一覧からCloudWatchアラームの設定が可能

#### :o: アベイラビリティゾーン

* 「アベイラビリティゾーン」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「Placement」の「AvailabilityZone」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['アベイラビリティーゾーン'] = instance['Placement']['AvailabilityZone']
```

#### :o: パブリックIPV4 DNS

* 「パブリックIPV4 DNS」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「PublicDnsName」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['パブリックIPv4 DNS'] = instance['PublicDnsName']
```

#### :o: パブリックIPv4 アドレス

* 「パブリックIPv4 アドレス」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「PublicIpAddress」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['パブリックIPv4アドレス'] = '-'
        if instance.get('PublicIpAddress'):
            jsonObj['パブリックIPv4アドレス'] = instance['PublicIpAddress']
```

#### :o: Elastic IP

* 「Elastic IP」はBoto3のメソッド「describe_addresses」で取得した「Addresses」
* describe_addressesのFilterにVPCを指定
* Elastic IPは、EC2を停止起動してもIPアドレスを固定にする

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        jsonObj['Elastic IP'] = '-'
        filters = [{'Name': 'domain', 'Values': ['vpc']}]
        if len(ec2_client.describe_addresses(Filters=filters)['Addresses']) != 0:
            jsonObj['Elastic IP'] = ec2_client.describe_addresses(Filters=filters)['Addresses'][0]
```

#### :o: IPv6

* 「IPv6」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「NetworkInterfaces」の「Ipv6Addresses」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['IPv6 IP'] = []
        for networkinterface in instance['NetworkInterfaces']:
            jsonObj['IPv6 IP'].append(networkinterface['Ipv6Addresses'])
```

#### :o: プライベートDNS名

* 「プライベートDNS名」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「PrivateDnsName」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['プライベートDNS名'] = instance['PrivateDnsName']
```

#### :o: プライベートIPアドレス

* 「プライベートIPアドレス」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「PrivateIpAddress」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['プライベートIPアドレス'] = instance['PrivateIpAddress']
```

#### :o: モニタリング

* 「モニタリング」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「Monitoring」
* モニタリングは、CloudWatchエージェントによるモニタリングの有無

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['モニタリング'] = instance['Monitoring']['State']
```

#### :o: セキュリティグループ名、セキュリティグループID

* 「セキュリティグループ名」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「SecurityGroups」の「GroupName」
* 「セキュリティグループID」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「SecurityGroups」の「GroupId」
* 複数指定できるためfor文で取得

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['セキュリティグループ名'] = []
        jsonObj['セキュリティグループID'] = []
        for securitygroup in instance['SecurityGroups']:
            jsonObj['セキュリティグループ名'].append(securitygroup['GroupName'])
            jsonObj['セキュリティグループID'].append(securitygroup['GroupId'])
```

#### :o: キー名

* 「キー名」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「KeyName」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['キー名'] = '-'
        if instance.get('KeyName'):
            jsonObj['キー名'] = instance['KeyName']
```

#### :o: 所有者ID

* 「所有者ID」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「NetworkInterfaces」の「OwnerId」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['所有者ID'] = []
        for networkinterface in instance['NetworkInterfaces']:
            jsonObj['所有者ID'].append(networkinterface['OwnerId'])
```

#### :o: ボリュームID

* 「ボリュームID」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「BlockDeviceMappings」の「Ebs」の「VolumeId」
* EC2に追加したEBSのボリュームID

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['ボリュームID'] = []
        for blockdevicemapping in instance['BlockDeviceMappings']:
            jsonObj['ボリュームID'] = blockdevicemapping['Ebs']['VolumeId']
```

#### :o: ルートデバイス名

* 「ルートデバイス名」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「RootDeviceName」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['ルートデバイス名'] = instance['RootDeviceName']
```

#### :o: ルートデバイスタイプ

* 「ルートデバイスタイプ」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「RootDeviceType」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['ルートデバイスタイプ'] = instance['RootDeviceType']
```

#### :o: EBSに最適化

* 「EBSに最適化」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「EbsOptimized」
* EBSの最適化オプションで、有効にするとEBSのパフォーマンスが向上

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['EBSに最適化'] = instance['EbsOptimized']
```

#### :o: イメージID

* 「イメージID」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「ImageId」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['イメージID'] = instance['ImageId']
```

#### :o: カーネルID

* 「カーネルID」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「KernelId」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj[i]['カーネルID'] = '-'
        if instance.get('KernelId'):
            jsonObj['カーネルID'] = instance['KernelId']
```

#### :o: RAMディスクID

* 「RAMディスクID」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「RamdiskId」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['RAMディスクID'] = '-'
        if instance.get('RamdiskId'):
            jsonObj['RAMディスクID'] = instance['RamdiskId']
```

#### :o: AMI起動インデックス

* 「AMI起動インデックス」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「AmiLaunchIndex」
* AMI起動インデックスは、同時に複数のインスタンスを起動する場合の順番

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['AMI起動インデックス'] = instance['AmiLaunchIndex']
```

#### :o: 起動時刻

* 「起動時刻」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「LaunchTime」
* 日本時間で表示するためtimedeltaで+9時間

```python:lambda_function.py
    from datetime import timedelta

    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['起動時刻'] = str((instance['LaunchTime'] + timedelta(hours=9)).strftime('%Y/%m/%d %H:%M:%S'))
```

#### :o: 予約ID

* 「予約ID」はBoto3のメソッド「describe_instances」で取得した「Reservations」の「ReservationId」
* 予約IDは、起動したインスタンスを特定するもの

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        jsonObj['予約ID'] = r['ReservationId']
```

#### :o: VPC ID

* 「VPC ID」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「VpcId」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['VPC ID'] = instance['VpcId']
```

#### :o: サブネットID

* 「サブネットID」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「SubnetId」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['サブネットID'] = instance['SubnetId']
```

#### :o: インスタンスのライフサイクル

* 「インスタンスのライフサイクル」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「InstanceLifecycle」
* EC2のAuto Scalingでインスタンスの状態を示す？

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['インスタンスのライフサイクル'] = '-'
        if instance.get('InstanceLifecycle'):
            jsonObj['インスタンスのライフサイクル'] = instance['InstanceLifecycle']
```

#### :o: アーキテクチャ

* 「アーキテクチャ」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「Architecture」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['アーキテクチャ'] = instance['Architecture']
```

#### :o: 仮想化タイプ

* 「仮想化タイプ」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「VirtualizationType」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['仮想化タイプ'] = instance['VirtualizationType']
```

#### :o: プラットフォーム

* 「プラットフォーム」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「Platform」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['プラットフォーム'] = '-'
        if instance.get('Platform'):
            jsonObj['プラットフォーム'] = instance['Platform']
```

#### :o: プラットフォームの詳細

* 「プラットフォームの詳細」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「PlatformDetails」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['プラットフォームの詳細'] = instance['PlatformDetails']
```

#### :o: IAMインスタンスプロファイルARN

* 「IAMインスタンスプロファイルARN」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「IamInstanceProfile」の「Arn」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['IAMインスタンスプロファイルARN'] = instance['IamInstanceProfile']['Arn']
```

#### :o: テナンシー

* 「テナンシー」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「Placement」の「Tenancy」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['テナンシー'] = instance['Placement']['Tenancy']
```

#### :o: アフィニティ

* 「アフィニティ」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「Placement」の「Affinity」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['アフィニティ'] = '-'
        if instance['Placement'].get('Affinity'):
            jsonObj['アフィニティ'] = instance['Placement']['Affinity']
```

#### :o: ホストID

* 「ホストID」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「Placement」の「HostId」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['ホストID'] = '-'
        if instance['Placement'].get('HostId'):
            jsonObj['ホストID'] = instance['Placement']['HostId']
```

#### :o: プレイスメントグループ

* 「プレイスメントグループ」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「Placement」の「GroupName」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['プレイスメントグループ'] = instance['Placement']['GroupName']
```

#### :o: パーティション番号（未確認）

* （未確認）

#### :o: キャパシティーの予約ID

* 「キャパシティーの予約ID」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「CapacityReservationId」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['キャパシティーの予約ID'] = '-'
        if instance.get('CapacityReservationId'):
            jsonObj['キャパシティーの予約ID'] = instance['CapacityReservationId']
```

#### :o: 状態遷移の理由コード

* 「状態遷移の理由コード」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「StateReason」の「Code」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['状態遷移の理由コード'] = instance['StateReason']['Code']
```

#### :o: 状態遷移の理由メッセージ

* 「状態遷移の理由メッセージ」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「StateReason」の「Message」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['状態遷移の理由メッセージ'] = instance['StateReason']['Message']
```

#### :o: 停止-休止状態

* 「停止-休止状態」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「HibernationOptions」の「Configured」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['停止-休止動作'] = instance['HibernationOptions']['Configured']
```

#### :o: Outpost ARN

* 「Outpost ARN」はBoto3のメソッド「describe_snapshots」で取得した「Snapshots」の「OutpostArn」
* describe_snapshotsのFilterにボリュームIDを指定
* Outpost ARNは、EBSスナップショットのARN

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['Outpost ARN'] = []
        filters = [{'Name': 'volume-id', 'Values': [jsonObj['ボリュームID']]}]
        snapshots = ec2_client.describe_snapshots(Filters=filters)
        for snapshot in snapshots['Snapshots']:
            if snapshot.get('OutpostArn'):
                jsonObj['Outpost ARN'].append(snapshot['OutpostArn'])
```

#### :o: 製品コード

* 「製品コード」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「ProductCodes」

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['製品コード'] = []
        for productcode in instance['ProductCodes']:
            jsonObj['製品コード'].append(productcode)
```

#### :o: IMDSv2

* 「IMDSv2」はBoto3のメソッド「describe_instances」で取得した「Reservations」のうち、「Instances」の「MetadataOptions」の「HttpTokens」
* IMDSv2は、インスタンスのメタデータ

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    response = ec2_client.describe_instances()
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj['IMDSv2'] = instance['MetadataOptions']['HttpTokens']
```

仕上げとして
Lambdaで取得したIAMユーザの情報をjsonからhtmlに変換する。
htmlに変換するためpandasを利用。
pandasを利用するためのLambdaの設定方法はこちら:point_down:が参考になります。

https://qiita.com/polarbear08/items/202752d5ffcb65595bd9

jsonデータをhtmlに変換して返す。

```python:lambda_function.py
    # プログラムは必要な個所のみ記載
    df = pd.DataFrame(jsonObj)
    html_table = df.to_html(index=False, justify='center')
    with open('/tmp/table.html', 'w', encoding='utf-8') as file:
        file.write(html_table)
    print(html_table)

    return {
        'statusCode': 200,
        'headers': {
            'Content-Type': 'text/html; charset=UTF-8'
        },
        'body': html_table
    }
```

ブラウザで確認するとこんな感じ。（マスクしてるためほとんどわからない:sweat_smile:）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288944/c8947292-15c1-3094-457e-fad4e812ca10.png)

<details><summary>LambdaのPythonコード全文です。</summary>

```python:lambda_function.py
import json
import boto3
from datetime import datetime, timedelta, timezone
import pandas as pd

ec2_client = boto3.client('ec2')

def lambda_handler(event, context):
    response = ec2_client.describe_instances()
    jsonObj = [''] * len(response['Reservations'])
    i = 0
    for r in response['Reservations']:
        instance = r['Instances'][0]
        jsonObj[i] = {}

        # Name
        jsonObj[i]['Name'] = ""
        for tag in instance['Tags']:
            if tag.get('Key') and tag['Key'] == 'Name':
                jsonObj[i]['Name'] = tag['Value']

        # インスタンスID
        jsonObj[i]['インスタンスID'] = instance['InstanceId']
        
        # インスタンスの状態
        jsonObj[i]['インスタンスの状態'] = instance['State']['Name']

        # インスタンスタイプ
        jsonObj[i]['インスタンスタイプ'] = instance['InstanceType']

        # ステータスチェック
        jsonObj[i]['ステータスチェック'] = []
        instancestatuses = ec2_client.describe_instance_status(InstanceIds=[instance['InstanceId']])
        for instancestatuse in instancestatuses['InstanceStatuses']:
            jsonObj[i]['ステータスチェック'].append(instancestatuse['SystemStatus']['Status'])
            jsonObj[i]['ステータスチェック'].append(instancestatuse['InstanceStatus']['Status'])
            
        # アラームの状態 CloudWatchのアラーム

        # アベイラビリティーゾーン
        jsonObj[i]['アベイラビリティーゾーン'] = instance['Placement']['AvailabilityZone']

        # パブリックIPv4 DNS
        jsonObj[i]['パブリックIPv4 DNS'] = instance['PublicDnsName']

        # パブリックIPv4アドレス
        jsonObj[i]['パブリックIPv4アドレス'] = '-'
        if instance.get('PublicIpAddress'):
            jsonObj[i]['パブリックIPv4アドレス'] = instance['PublicIpAddress']

        # Elastic IP
        jsonObj[i]['Elastic IP'] = '-'
        filters = [{'Name': 'domain', 'Values': ['vpc']}]
        if len(ec2_client.describe_addresses(Filters=filters)['Addresses']) != 0:
            jsonObj[i]['Elastic IP'] = ec2_client.describe_addresses(Filters=filters)['Addresses'][0]

        # IPv6 IP
        jsonObj[i]['IPv6 IP'] = []

        # プライベートDNS名
        jsonObj[i]['プライベートDNS名'] = instance['PrivateDnsName']

        # プライベートIPアドレス
        jsonObj[i]['プライベートIPアドレス'] = instance['PrivateIpAddress']

        # モニタリング
        jsonObj[i]['モニタリング'] = instance['Monitoring']['State']

        # セキュリティグループ名
        # セキュリティグループID
        jsonObj[i]['セキュリティグループ名'] = []
        jsonObj[i]['セキュリティグループID'] = []
        for securitygroup in instance['SecurityGroups']:
            jsonObj[i]['セキュリティグループ名'].append(securitygroup['GroupName'])
            jsonObj[i]['セキュリティグループID'].append(securitygroup['GroupId'])

        # キー名
        jsonObj[i]['キー名'] = '-'
        if instance.get('KeyName'):
            jsonObj[i]['キー名'] = instance['KeyName']

        # 所有者ID
        jsonObj[i]['所有者ID'] = []
        for networkinterface in instance['NetworkInterfaces']:
            jsonObj[i]['所有者ID'].append(networkinterface['OwnerId'])
            jsonObj[i]['IPv6 IP'].append(networkinterface['Ipv6Addresses'])

        # ボリュームID
        jsonObj[i]['ボリュームID'] = []
        for blockdevicemapping in instance['BlockDeviceMappings']:
            jsonObj[i]['ボリュームID'] = blockdevicemapping['Ebs']['VolumeId']

        # ルートデバイス名
        jsonObj[i]['ルートデバイス名'] = instance['RootDeviceName']

        # ルートデバイスタイプ
        jsonObj[i]['ルートデバイスタイプ'] = instance['RootDeviceType']

        # EBSに最適化
        jsonObj[i]['EBSに最適化'] = instance['EbsOptimized']

        # イメージID
        jsonObj[i]['イメージID'] = instance['ImageId']

        # カーネルID
        jsonObj[i]['カーネルID'] = '-'
        if instance.get('KernelId'):
            jsonObj[i]['カーネルID'] = instance['KernelId']

        # RAMディスクID
        jsonObj[i]['RAMディスクID'] = '-'
        if instance.get('RamdiskId'):
            jsonObj[i]['RAMディスクID'] = instance['RamdiskId']

        # AMI起動インデックス
        jsonObj[i]['AMI起動インデックス'] = instance['AmiLaunchIndex']

        # 起動時刻
        jsonObj[i]['起動時刻'] = str((instance['LaunchTime'] + timedelta(hours=9)).strftime('%Y/%m/%d %H:%M:%S'))

        # 予約ID
        jsonObj[i]['予約ID'] = r['ReservationId']

        # VPC ID
        jsonObj[i]['VPC ID'] = instance['VpcId']

        # サブネットID
        jsonObj[i]['サブネットID'] = instance['SubnetId']

        # インスタンスのライフサイクル
        jsonObj[i]['インスタンスのライフサイクル'] = '-'
        if instance.get('InstanceLifecycle'):
            jsonObj[i]['インスタンスのライフサイクル'] = instance['InstanceLifecycle']

        # アーキテクチャ
        jsonObj[i]['アーキテクチャ'] = instance['Architecture']

        # 仮想化タイプ
        jsonObj[i]['仮想化タイプ'] = instance['VirtualizationType']

        # プラットフォーム
        jsonObj[i]['プラットフォーム'] = '-'
        if instance.get('Platform'):
            jsonObj[i]['プラットフォーム'] = instance['Platform']

        # プラットフォームの詳細
        jsonObj[i]['プラットフォームの詳細'] = instance['PlatformDetails']

        # IAMインスタンスプロファイルARN
        jsonObj[i]['IAMインスタンスプロファイルARN'] = instance['IamInstanceProfile']['Arn']

        # テナンシー
        jsonObj[i]['テナンシー'] = instance['Placement']['Tenancy']

        # アフィニティ
        jsonObj[i]['アフィニティ'] = '-'
        if instance['Placement'].get('Affinity'):
            jsonObj[i]['アフィニティ'] = instance['Placement']['Affinity']

        # ホストID
        jsonObj[i]['ホストID'] = '-'
        if instance['Placement'].get('HostId'):
            jsonObj[i]['ホストID'] = instance['Placement']['HostId']

        # プレイスメントグループ
        jsonObj[i]['プレイスメントグループ'] = instance['Placement']['GroupName']

        # パーティション番号
        
        # キャパシティーの予約ID
        jsonObj[i]['キャパシティーの予約ID'] = '-'
        if instance.get('CapacityReservationId'):
            jsonObj[i]['キャパシティーの予約ID'] = instance['CapacityReservationId']

        # 状態遷移の理由コード
        jsonObj[i]['状態遷移の理由コード'] = instance['StateReason']['Code']

        # 状態遷移の理由メッセージ
        jsonObj[i]['状態遷移の理由メッセージ'] = instance['StateReason']['Message']

        # 停止-休止動作
        jsonObj[i]['停止-休止動作'] = instance['HibernationOptions']['Configured']

        # Outpost ARN スナップショットの保存場所
        jsonObj[i]['Outpost ARN'] = []
        filters = [{'Name': 'volume-id', 'Values': [jsonObj[i]['ボリュームID']]}]
        snapshots = ec2_client.describe_snapshots(Filters=filters)
        for snapshot in snapshots['Snapshots']:
            if snapshot.get('OutpostArn'):
                jsonObj[i]['Outpost ARN'].append(snapshot['OutpostArn'])

        # 製品コード
        jsonObj[i]['製品コード'] = []
        for productcode in instance['ProductCodes']:
            jsonObj[i]['製品コード'].append(productcode)

        # IMDSv2
        jsonObj[i]['IMDSv2'] = instance['MetadataOptions']['HttpTokens']

        i+=1
    
    scripts = """
            <style type="text/css">
            .design10 {
             width: 100%;
             text-align: center;
             border-collapse: collapse;
             border-spacing: 0;
            }
            .design10 th {
             padding: 10px;
             border-bottom: solid 4px #778ca3;
             color: #778ca3
            }
            .design10 td {
             padding: 10px;
             border-bottom: solid 1px #778ca3;
            }
            </style>
        """
            
    df = pd.DataFrame(jsonObj)
    html_table = scripts + df.to_html(index=False, justify='center', classes='design10')
    with open('/tmp/table.html', 'w', encoding='utf-8') as file:
        file.write(html_table)

    return {
        'statusCode': 200,
        'headers': {
            'Content-Type': 'text/html; charset=UTF-8'
        },
        'body': html_table
    }

```
</details>

### さいごに

* 今回はBoto3を使ってEC2の情報取得をしましたが、EC2の作成、更新、削除もできます。使い方はBoto3のマニュアルとにらめっこ。
* 他のサービスについてもやっていく予定です。
* 少しでもみなさんの参考になりますように！