はじめに
LambdaでS3オブジェクトを制御したかったので、オブジェクトに独自のメタデータ(ユーザ定義メタデータ)を追加・更新して対処した。
本文では、ユーザ定義メタデータについて、実際のソースと実行結果について記す。
ユーザ定義メタデータとは
Content-Lengthなどのオブジェクトの追加情報をメタデータ
という。
メタデータには2種類あり、主にAWSシステム上で制御されるシステムメタデータ
とユーザが独自で定義できるユーザ定義メタデータ
がある。
今回はファイルの上書き回数(メタデータ名をx-amz-meta-count
とする)をユーザ定義メタデータとして定義する。
Lambdaソース
下記LambdaをCloudWatchEventsなどをトリガーとして実行する。
指定したバケット、ディレクトリ配下のファイルを取得し、そのファイルのメタデータにx-amz-meta-count
がなければ追加する。
あれば、メタデータの値を+1する。
最後に追加更新した内容でファイルを上書き(copy_object())する。
import os
import json
import boto3
import pprint
import urllib.parse
if os.getenv("AWS_SAM_LOCAL"):
s3Client = boto3.client(
's3', endpoint_url='http://host.docker.internal:4572/'
)
s3Resource = boto3.resource(
's3', endpoint_url="http://host.docker.internal:4572/")
else:
s3Client = boto3.client('s3')
s3Resource = boto3.resource('s3')
def lambda_handler(event, context):
BUCKET_NAME = "test-ksatou-20200125"
PREFIX = "input/"
try:
# ディレクトリ下のオブジェクト一覧を取得
objs = s3Resource.Bucket(BUCKET_NAME).objects.filter(Prefix=PREFIX)
for obj in objs:
print("Key: " + obj.key)
# オブジェクトのメタデータを取得
headObj = s3Client.head_object(Bucket=BUCKET_NAME, Key=obj.key)
# 上記で取得したメタデータから、ユーザ定義メタデータ(x-amz-meta-count)を取得する
# ユーザ定義メタデータのキーの接頭辞は「x-amz-meta-」で始まる
httpHeaders = headObj["ResponseMetadata"]["HTTPHeaders"]
count = httpHeaders.get("x-amz-meta-count")
orgEtag = httpHeaders.get("etag")
contentType = headObj["ContentType"]
# ユーザ定義メタデータ(x-amz-meta-count)を追加・更新して、ファイルを上書く
# メタデータの追加・更新の際は、接頭辞「x-amz-meta-」は記述する必要はない
# valueはstring型でなければならない
metadata = headObj["Metadata"]
metadata["count"] = "0" if count == None else str(
int(count) + 1)
s3Client.copy_object(Key=obj.key, Bucket=BUCKET_NAME,
CopySource={
"Bucket": BUCKET_NAME, "Key": obj.key},
Metadata=metadata,
ContentType=contentType,
MetadataDirective="REPLACE",
CopySourceIfMatch=orgEtag)
except Exception as e:
print(e)
raise e