これは、なにをしたくて書いたもの?
PythonのAWSクライアントライブラリといえば、Boto 3というものだそうです。
GitHub - boto/boto3: AWS SDK for Python
ドキュメントは、こちら。
Boto 3 Documentation — Boto 3 Docs 1.9.134 documentation
AWSの代わりにLocalStackを使っていろいろと遊びたいのですが、LocalStackに接続する際にはエンドポイントを変えたり
しないといけないわけで、そのあたりを調べてみました。
お題
Boto 3を使って、LocalStack上のS3にアクセスしてみたいと思います。
Boto 3には高レベルAPI(Resource)と低レベルAPI(Client)があるようなので、その両方でやってみます。
環境とライブラリのインストール
LocalStackは、Docker Composeで起動。LocalStackは、「192.168.0.3」というホストで動作しているものとします。
docker-compose.yml
version: "3" services: localstack: image: localstack/localstack:0.9.1 ports: - "4567-4593:4567-4593" - "8080:8080" environment: - SERVICES=${SERVICES- } - DEBUG=${DEBUG- } - DATA_DIR=${DATA_DIR- } - PORT_WEB_UI=${PORT_WEB_UI- } - LAMBDA_EXECUTOR=docker-reuse - KINESIS_ERROR_PROBABILITY=${KINESIS_ERROR_PROBABILITY- } - DOCKER_HOST=unix:///var/run/docker.sock volumes: - "/var/run/docker.sock:/var/run/docker.sock"
今回の環境は、こちら。
$ python -V Python 3.6.7
仮想環境の作成。
$ python3 -m venv venv $ . venv/bin/activate
Boto 3のインストール。
$ pip3 install boto3
バージョン。
$ pip3 freeze boto3==1.9.134 ...
これで、準備は完了です。
サンプルプログラム
Bucketの作成、削除、オブジェクトのPut/Getを行う簡単なプログラムを作成。
app.py
import boto3.session from botocore.config import Config session = boto3.session.Session( aws_access_key_id = 'my-access-key', aws_secret_access_key = 'my-secret-access-key' ) ### for Client s3client = session.client( 's3', endpoint_url = 'http://192.168.0.3:4572', config = Config() ) print(s3client.list_buckets()) bucket = s3client.create_bucket(Bucket = 'my-bucket1') print(s3client.list_buckets()) s3client.put_object(Bucket = 'my-bucket1', Key = 'sample-object1', Body = b'Hello LocalStack S3!! from Client') print('body = ' + s3client.get_object(Bucket = 'my-bucket1', Key = 'sample-object1')['Body'].read().decode()) s3client.delete_object(Bucket = 'my-bucket1', Key = 'sample-object1') s3client.delete_bucket(Bucket = 'my-bucket1') #### for Resource s3resource = session.resource( 's3', endpoint_url = 'http://192.168.0.3:4572', config = Config() ) bucket = s3resource.Bucket('my-bucket2') bucket.create() my_object = bucket.Object('sample-object2') my_object.put(Body = b'Hello LocalStack S3!! from Resource') print('body = ' + my_object.get()['Body'].read().decode()) my_object.delete() bucket.delete()
サンプルは、Exampleを参考にしつつ
Amazon S3 Examples — Boto 3 Docs 1.9.134 documentation
S3用のAPIリファレンスを眺めながら作成。
アクセスキーやシークレットアクセスキーは、AWS CLIで設定してもいいのですが、今回はプログラム内で指定。
session = boto3.session.Session( aws_access_key_id = 'my-access-key', aws_secret_access_key = 'my-secret-access-key' )
デフォルトの情報以外でClientやResourceを作成するには、Sessionというものをカスタマイズすることになる、と。
Session — Boto 3 Docs 1.9.134 documentation
低レベルAPI(Client)を使った場合。
### for Client s3client = session.client( 's3', endpoint_url = 'http://192.168.0.3:4572', config = Config() ) print(s3client.list_buckets()) bucket = s3client.create_bucket(Bucket = 'my-bucket1') print(s3client.list_buckets()) s3client.put_object(Bucket = 'my-bucket1', Key = 'sample-object1', Body = b'Hello LocalStack S3!! from Client') print('body = ' + s3client.get_object(Bucket = 'my-bucket1', Key = 'sample-object1')['Body'].read().decode()) s3client.delete_object(Bucket = 'my-bucket1', Key = 'sample-object1') s3client.delete_bucket(Bucket = 'my-bucket1')
Sessionから、Clientを作成します。この時、エンドポイントを指定したりできます。
s3client = session.client( 's3', endpoint_url = 'http://192.168.0.3:4572', config = Config() )
リファレンスは、こちら。
ここで指定しているConfigというのは、Boto 3より更に低レベルなライブラリである、Botocoreというライブラリの設定です。
今回は特になにも指定していませんが、カスタマイズする場合は以下を参照しましょう。
Config Reference — botocore 1.12.134 documentation
続いて、高レベルAPI(Resource)の場合。
#### for Resource s3resource = session.resource( 's3', endpoint_url = 'http://192.168.0.3:4572', config = Config() ) bucket = s3resource.Bucket('my-bucket2') bucket.create() my_object = bucket.Object('sample-object2') my_object.put(Body = b'Hello LocalStack S3!! from Resource') print('body = ' + my_object.get()['Body'].read().decode()) my_object.delete() bucket.delete()
Resourceも、やはりSessionから作成します。
s3resource = session.resource( 's3', endpoint_url = 'http://192.168.0.3:4572', config = Config() )
リファレンスは、こちら。
Clientの時と同様、ConfigというのはBotocoreの設定になります。
確認
最後に、実行して確認です。
$ python3 app.py {'ResponseMetadata': {'HTTPStatusCode': 200, 'HTTPHeaders': {'server': 'BaseHTTP/0.3 Python/2.7.15', 'date': 'Sat, 20 Apr 2019 13:20:59 GMT', 'content-type': 'application/xml; charset=utf-8', 'content-length': '205', 'access-control-allow-origin': '*', 'access-control-allow-methods': 'HEAD,GET,PUT,POST,DELETE,OPTIONS,PATCH', 'access-control-allow-headers': 'authorization,content-type,content-md5,cache-control,x-amz-content-sha256,x-amz-date,x-amz-security-token,x-amz-user-agent'}, 'RetryAttempts': 0}, 'Buckets': [], 'Owner': {'DisplayName': 'webfile', 'ID': 'bcaf1ffd86f41161ca5fb16fd081034f'}} {'ResponseMetadata': {'HTTPStatusCode': 200, 'HTTPHeaders': {'server': 'BaseHTTP/0.3 Python/2.7.15', 'date': 'Sat, 20 Apr 2019 13:20:59 GMT', 'content-type': 'application/xml; charset=utf-8', 'content-length': '298', 'access-control-allow-origin': '*', 'access-control-allow-methods': 'HEAD,GET,PUT,POST,DELETE,OPTIONS,PATCH', 'access-control-allow-headers': 'authorization,content-type,content-md5,cache-control,x-amz-content-sha256,x-amz-date,x-amz-security-token,x-amz-user-agent'}, 'RetryAttempts': 0}, 'Buckets': [{'Name': 'my-bucket1', 'CreationDate': datetime.datetime(2006, 2, 3, 16, 45, 9, tzinfo=tzutc())}], 'Owner': {'DisplayName': 'webfile', 'ID': 'bcaf1ffd86f41161ca5fb16fd081034f'}} body = Hello LocalStack S3!! from Client body = Hello LocalStack S3!! from Resource