search
LoginSignup
2

More than 1 year has passed since last update.

posted at

updated at

Organization

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

この記事は 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を書く場合などは役にたつかもしれません。

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
What you can do with signing up
2