PythonのBoto3で特定サービスが対応しているリージョン一覧を少し工夫して取得する

Boto3で特定サービスが対応しているリージョン一覧を少しだけ工夫して取得してみましょう。
2022.03.31

こんにちは。サービスグループの武田です。

Boto3はPython用のAWS SDKですが、これを使用してAWSの全リージョンに対して何らかの操作をしたいというニーズはよくあります。DevelopersIOでも次のようなエントリが書かれています。

この2つの方法のメリットを書き出してみると次のようになります。

  • ec2.describe_regions()のメリット
    • 常に最新のリージョンリストが返ってくる
    • アカウントのリージョンオプトインに対応した結果が返ってくる
  • Session#get_available_regions()のメリット
    • 指定したサービスが有効なリージョンのみ返ってくる

さて、たとえば 利用できる全リージョンでAmazon Detectiveを有効化したい のような要件の場合どちらの方法を使えばいいでしょうか。それぞれの結果を確認してみます。

>>> import boto3
>>> ec2 = boto3.client("ec2")
>>> sorted(r["RegionName"] for r in ec2.describe_regions()["Regions"])
['ap-northeast-1', 'ap-northeast-2', 'ap-northeast-3', 'ap-south-1', 'ap-southeast-1', 'ap-southeast-2', 'ca-central-1', 'eu-central-1', 'eu-north-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'sa-east-1', 'us-east-1', 'us-east-2', 'us-west-1', 'us-west-2']

>>> session = boto3.session.Session()
>>> sorted(session.get_available_regions("detective"))
['af-south-1', 'ap-east-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-south-1', 'ap-southeast-1', 'ap-southeast-2', 'ca-central-1', 'eu-central-1', 'eu-north-1', 'eu-south-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'me-south-1', 'sa-east-1', 'us-east-1', 'us-east-2', 'us-west-1', 'us-west-2']

ec2.describe_regions()ではDetectiveが利用できない大阪(ap-northeast-3)リージョンが含まれています。一方でSession#get_available_regions()ではこのアカウントでは有効化していないケープタウン(af-south-1)リージョンなどが含まれています。そうするとどちらでリージョン一覧を取得しても、必ず有効化に失敗するリージョンが出てくることになります。例外処理をして、ダメなリージョンはスルーするのも手ですが、ちょっと工夫をしてみましょう。

サービスが利用できるリージョンかつアカウントが利用できるリージョンの一覧を取得する

要は先ほど取得した2つの一覧の積集合(共通部分)を取れば解決します。Pythonでは集合を扱うset型があり、これを使用することで簡単に積集合を取れます。

>>> regions1 = {r["RegionName"] for r in ec2.describe_regions()["Regions"]}
>>> regions2 = set(session.get_available_regions("detective"))

>>> regions1 & regions2
{'eu-west-2', 'eu-central-1', 'ap-northeast-2', 'eu-west-3', 'sa-east-1', 'ca-central-1', 'ap-south-1', 'ap-southeast-1', 'ap-northeast-1', 'eu-west-1', 'ap-southeast-2', 'us-west-1', 'us-west-2', 'us-east-1', 'eu-north-1', 'us-east-2'}

>>> sorted(regions1 & regions2)
['ap-northeast-1', 'ap-northeast-2', 'ap-south-1', 'ap-southeast-1', 'ap-southeast-2', 'ca-central-1', 'eu-central-1', 'eu-north-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'sa-east-1', 'us-east-1', 'us-east-2', 'us-west-1', 'us-west-2']

あとはこのリストを使ってやりたい処理をすればスマートに実装できますね!

注意点

Session#get_available_regions()が返すリストはbotocoreが内部的に持っているファイルが元になっています。そのためAWSが新しくリージョンサポートをしても、ライブラリをアップデートするまでは返されるリストも更新されません。そのため、用件としてライブラリアップデートなどをしなくても最新リージョンに追従する、などがあるのであればこの方法は使えません。

まとめ

リージョナルなリソースを有効化しようとすると、リージョン一覧を取得してループ処理をするのが定番となってきます。そのリージョン一覧の取得も考慮すべき点があることはぜひ忘れないようにしましょう。