12
3

More than 3 years have passed since last update.

boto3はどのようにしてAWSへリクエストを送っているか

Last updated at Posted at 2020-12-10

この記事は ABEJA Advent Calendar 2020 11日目の記事です。

この記事ではPythonのAWS SDKであるboto3が、どのような仕組みでAWSへリクエストを送っているかを説明します。

boto3とは

boto3とはPythonのAWS SDKです。PythonでAWSのリソースを操作する場合には(多くの場合)boto3を使う事となります。boto3でAWSのリソースを操作する場合には、以下のようにサービス毎にclientのインスタンスを作成して操作を行います。

import boto3
client = boto3.client('kinesisvideo')
client.list_streams()

AWSに新しいサービスが追加された際にはリリース直後にCLIやSDKで追加サービスの操作が可能となります。その際、boto3ではAWSのAPIの各オペレーションはclientのインスタンスメソッドとして提供され、リクエスト・パラメータはメソッドの引数として渡す事ができます。boto3はどのようにしてSDKを迅速に提供しているのでしょうか?
boto3はbotocoreというコアライブラリを参照する事で、SDKとしての機能を動的に提供しています。
なお、awscliは内部でbotocoreが使われているため、boto3と同じ仕組みでコマンドの提供が行われています。

boto3がAWSのAPIをclientに反映する仕組み

boto3.client()botocore.session.create_client()を返しています。
botocore.session.create_client()はbotocore.client.ClientCreator._create_client_classで作られるservice_clientインスタンスを返しています。このservice_clientインスタンスのクラスは組み込み関数のtypeを使ってサービス毎に動的に生成されています。

cls = type(str(class_name), tuple(bases), class_attributes)

サービス毎のクラスを生成する際に必要となる、class_nameclass_attributesbotocore.client.ClientCreator._load_service_model()で作られるServiceModelから生成されます。

このServiceModelはbotocore.loaders.Loader.load_service_model()で、各サービスのサービスモデルの定義ファイルを参照しています。定義ファイルには、サービスの各オペレーション毎のAPIエンドポイント、リクエストパラメータ、レスポンスパラメータ、エラーの定義が含まれています。

botocore/botocore/data/kinesisvideo/2017-09-30/service-2.json
{
  "version":"2.0",
  "metadata":{
     ...
  },
  "operations":{
    "CreateSignalingChannel":{
      "name":"CreateSignalingChannel",
      "http":{
        "method":"POST",
        "requestUri":"/createSignalingChannel"
      },
      "input":{"shape":"CreateSignalingChannelInput"},
      "output":{"shape":"CreateSignalingChannelOutput"},
      "errors":[
        {"shape":"InvalidArgumentException"},
        {"shape":"ClientLimitExceededException"},
        {"shape":"AccountChannelLimitExceededException"},
        {"shape":"ResourceInUseException"},
        {"shape":"AccessDeniedException"},
        {"shape":"TagsPerResourceExceededLimitException"}
      ],
....

つまり、boto3のclientはbotocoreに含まれるサービスの定義ファイルをPythonのクラスに変換する事で、AWSの各サービスのSDKとして機能しています。変換途中でオペレーション名をsnake_caseに変換する等の細かい処理も入っています。

AWSの新規サービスが追加された場合には、サービスモデルの定義ファイルをbotocoreに追加する事でboto3から利用可能になります。

実際にboto3.client()を見てみると以下のようにservice_modelは定義ファイルからオペレーション名やエラーの定義をロードしています。

>>> import boto3
>>> client = boto3.client("kinesisvideo")
>>> client
<botocore.client.KinesisVideo object at 0x10c689210>
>>> client._service_model
ServiceModel(kinesisvideo)
>>> client._service_model.operation_names
['CreateSignalingChannel', 'CreateStream', 'DeleteSignalingChannel', 'DeleteStream', 'DescribeSignalingChannel', 'DescribeStream', 'GetDataEndpoint', 'GetSignalingChannelEndpoint', 'ListSignalingChannels', 'ListStreams', 'ListTagsForResource', 'ListTagsForStream', 'TagResource', 'TagStream', 'UntagResource', 'UntagStream', 'UpdateDataRetention', 'UpdateSignalingChannel', 'UpdateStream']
>>> client._service_model.error_shapes
[<StructureShape(AccessDeniedException)>, <StructureShape(AccountChannelLimitExceededException)>, <StructureShape(AccountStreamLimitExceededException)>, <StructureShape(ClientLimitExceededException)>, <StructureShape(DeviceStreamLimitExceededException)>, <StructureShape(InvalidArgumentException)>, <StructureShape(InvalidDeviceException)>, <StructureShape(InvalidResourceFormatException)>, <StructureShape(NotAuthorizedException)>, <StructureShape(ResourceInUseException)>, <StructureShape(ResourceNotFoundException)>, <StructureShape(TagsPerResourceExceededLimitException)>, <StructureShape(VersionMismatchException)>]

まとめ

boto3やawscliはbotocoreに含まれる各サービスの定義ファイルを参照してSDK/CLIを提供しています。SDKが想定外の挙動をした場合や、AWSのmockを書く場合などは役にたつかもしれません。

12
3
0

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
12
3