DBのスナップショットを手で作成するときや,CloudFormationでインスタンスを作成するときに,EBSにタグを付け忘れることがある.
そんなときのために,アタッチされているインスタンスに対して自動でタグを付けられるスクリプトを書いた.
import boto3
import os
def handler(event, context):
synced_tag_keys = os.environ['SYNCED_TAG_KEYS'].split(',')
client = boto3.client('ec2')
ebs_messages = ''
instance_tags_dict = get_instance_tags(client)
response = client.describe_volumes()
for volume in response['Volumes']:
volume_id = volume['VolumeId']
if not volume_id in instance_tags_dict:
continue
instance_tags = instance_tags_dict[volume_id]
volume_tags = tags_array_to_dict(volume.get('Tags'))
tags_to_notify = {}
for synced_tag in synced_tag_keys:
instance_tag_value = instance_tags.get(synced_tag)
if instance_tag_value is None:
continue
if volume_tags.get(synced_tag) != instance_tag_value:
create_tags(client, volume_id, synced_tag, instance_tag_value)
tags_to_notify[synced_tag] = instance_tag_value
if tags_to_notify != {}:
ebs_messages += volume_id + '(' + str(instance_tags.get('Name')) + '): ' + str(tags_to_notify) + '\n'
message = '(' + context.function_name + ') ' + '同期するタグ: ' + str(synced_tag_keys) + '\n'
if ebs_messages != '':
message += '以下にあるボリュームのタグを同期しました\n' + ebs_messages
else:
message += 'タグの同期が必要なボリュームはありません'
print(message)
def get_instance_tags(client):
response = client.describe_instances()
instance_tags = {}
for res in response['Reservations']:
for instance in res['Instances']:
for mapping in instance['BlockDeviceMappings']:
volume_id = mapping['Ebs']['VolumeId']
tags_dict = tags_array_to_dict(instance.get('Tags'))
instance_tags[volume_id] = tags_dict
return instance_tags
def tags_array_to_dict(tags_array):
if tags_array is None:
return {}
tags_dict = {}
for tag in tags_array:
tags_dict[tag['Key']] = tag['Value']
return tags_dict
def create_tags(client, volume_id, tag_key, tag_value):
client.create_tags(
Resources=[
volume_id,
],
Tags=[{
'Key': tag_key,
'Value': tag_value,
}]
)
EBSボリュームのidからアタッチされているインスタンスを検索して,環境変数SYNCED_TAG_KEYS
で指定したタグを同期させる.
Lambdaでの実行を想定しているので,CloudWatch などで定期実行すれば,自動的に同期することができる.