LoginSignup
1

More than 3 years have passed since last update.

【AWS】NextTokenの有無を判断して値を全部取る【boto3】

Posted at

おはようアンダーソン君
これは私の備忘録だ。取っておきたまえ

事の発端

AWS Lambda上でEC2のインスタンス情報(describe_instances)で掘り堀りする某スクリプトがありました。
instanceIDがすべて取れてないことに気づきました。
そう、boto3にはNextTokenという1度に取得に上限値が設定されているAPIがあるのです。

なんだそれ

boto3のドキュメント読んでくだちい…だと何にもならないので…
例としてこちらをご覧くだしい
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ec2.html#EC2.Client.describe_instances

EC2のdescribe_instancesというAPI
ReturnのResponce Syntaxに
'NextToken': 'string'
という値があるはずです。

1度に取れる値が何件なのか?気になりますよね
たぶん50件くらい? APIによるのかな。MaxResultsの値が上限ならdescribe_instancesは1000件までってことになるけど。
とにかくNextTokenがとかいうキーが「次はここから取りまっせ」の記号になります。

とりあえず全件取れるスクリプトをゴニョりました。
まぁ細かいことはサポートに聞くかドキュメント読んでくだちい(ひどい)

何!?この横着もの!とっとと結果をよこせだと!?
わかる。

スクリプトサンプル例

NextToken = None
while True:
    if NextToken is None:
        ec2_var = ec2_cli.describe_instances()
    else:
        ec2_var = ec2_cli.describe_instances(NextToken=NextToken)

    #EC2の戻り値(JSON)から必要な値を取得します。
    for Reservations in ec2_var['Reservations']:
        for instances in Reservations['Instances']:
            #ホスト名(タグ/Name)抽出
            ec2_list_nametag.append(instances['Tags'][0]['Value'])
            #ホストのインスタンスID抽出
            ec2_list_id.append(str(instances['InstanceId']))
            #ホストの配置AZ情報抽出
            ec2_list_az.append(instances['Placement']['AvailabilityZone'])
            #ホストのステータス抽出
            ec2_list_status.append(instances['State']['Name'])

    if not 'NextToken' in ec2_var:
        break
    NextToken = ec2_var['NextToken']
else:
    print(NextToken)

#抽出したEC2のリストの値を合体
ec2_list = [ec2_list_nametag,ec2_list_id,ec2_list_az,ec2_list_status]

#(例)AZ-Aにいるおめあてのホストを取得する。
for i in ec2_list[0]:
    if 'hoge' in i:
        num =ec2_list[0].index(i)
        if ec2_list[2][num] == 'ap-northeast-1a':
            hostname = str(i)

#(例)おめあてのステータス確認。
if hostname in != '': #お目当てがいたらじっこうしましょう
    for i in ec2_list[0]:
        if hostname in i:
            num =ec2_list[0].index(i)
                host_status = str(ec2_list[3][num])
else:
    print('おめあてが居なかったっぽい?')

結果

上記のスクリプトを使用することで全件のインスタンス情報を変数に格納することができました。
ついでに内部のforで必要な値を掘り堀りしてリストにします。
EMRとかいうとんでもないオモチャのせいでEC2がハンパない数起動していても、サクッと取れるようになります。

補足

しれっと多次元配列つかってますが、これを使うことで1個の全体量から色々と掘り堀りすることができるようになります。
何が言いたいかっつーとイチイチAPI叩いてご機嫌うかがってるとスロットリング起こしたり処理が遅くなったりするので
リトライ処理だなんだかんだを加えるなら、1発どかんで最初に取ったほうが楽じゃね?という理屈です。うわーこえー
で、そのリストは同じ戻り値を上からforでなぞれば順番同じじゃね?という理屈です。うわーこえー
内包型表記にしなかったのは見やすさ?誰が見てもわかってくれ~という私なりの気遣いです。
変数のメモリ使用量を考えろとか言われそうですが、AWS Lambdaなんかで実行する場合は多少気にしたほうがいいかもですね。メモリ量。

おしまい。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1