やりたいこと
AWS S3 には定期的にバケット内のファイル一覧を出力する Storage Inventory という機能がある。
この機能の出力は マニフェストファイル + データファイル(複数件) という構成になっている。
このままでは扱いが少々面倒なので、一つのファイルにまとめて出力させたい。
コード
言語は Python 3。boto3が必要。
# download_inventory.py
import sys
import json
import gzip
import shutil
import boto3
s3 = boto3.client('s3')
def download_inventory(manifest_bucket, manifest_prefix, outfile):
checksum_key = manifest_prefix + '/manifest.checksum'
manifest_key = manifest_prefix + '/manifest.json'
print('Manifest: s3://{}/{}'.format(manifest_bucket, manifest_key))
print('Manifest checksum: s3://{}/{}'.format(manifest_bucket, checksum_key))
checksum_res = s3.get_object(
Bucket=manifest_bucket,
Key=checksum_key)
checksum = checksum_res['Body'].read().decode('utf-8').strip()
manifest_res = s3.get_object(
Bucket=manifest_bucket,
Key=manifest_key,
IfMatch=checksum)
manifest_body = manifest_res['Body'].read()
manifest = json.loads(manifest_body.decode('utf-8'))
outfile.write((manifest['fileSchema'] + '\n').encode('utf-8'))
for entry in manifest['files']:
destbucket = manifest['destinationBucket'].replace('arn:aws:s3:::', '', 1)
print('Inventory: s3://{}/{}'.format(destbucket, entry['key']))
inventory_res = s3.get_object(
Bucket=destbucket,
Key=entry['key'],
IfMatch=entry['MD5checksum'])
with gzip.open(inventory_res['Body']) as f:
shutil.copyfileobj(f, outfile)
if __name__ == '__main__':
if len(sys.argv) != 4:
sys.exit('Usage: python download_inventory.py <output> <manifest bucket> <manifest prefix>')
with open(sys.argv[1], 'wb') as outfile:
download_inventory(sys.argv[2], sys.argv[3], outfile)
print('Saved: ' + sys.argv[1])
使い方
python download_inventory.py 出力先ファイル名 バケット名 マニフェストファイルが存在するバケット名 マニフェストファイルのキープレフィックス
例: マニフェストファイルが s3://mybucket/someprefix/2017-06-22T00-02Z/manifest.json に存在する場合は次の通り。
python download_inventory.py output mybucket someprefix/2017-06-22T00-02Z
インベントリの内容は output に出力される。