5
5

More than 1 year has passed since last update.

【AWS】S3に格納したExcelファイルをLambdaで読み込んでEC2にタグ付けする

Last updated at Posted at 2022-10-05

はじめに

久しぶりにコードを書く機会があったのでそこで使用したコードの一部をテンプレートっぽく記事として残そうと思います。
エクセルファイルを読み込んで、その他のサービス(SystemsManagerやEventBridgeなど)に対して処理を行う場合のコードとかも
別のタイミングで記事として残そうと思っていますので興味がある方は読んでみてください。

今回の検証では以下のサービスを使用します。

  • S3
  • EC2
  • Lambda(python3.9)

目次

  1. 処理の概要
  2. インプットデータを作成する
  3. IAMロールを作成する
  4. Lambda関数を作成する
  5. Iamロールを作成する
  6. Lambdaを実行する
  7. タグの確認
  8. さいごに

処理の概要

S3に格納したエクセルファイルをLambdaで読み込んで、対象のインスタンスにタグを付与します。
言語はPython3.9でモジュールはOpenpyxlを使用します。

インプットデータを作成する

画像のようなイメージでインプットデータを作成します。
InstanceNameの列は存在するインスタンス名を記載してください。(今回の検証ではあらかじめ3台用意してあります。)
シート名は今回はデフォルトのまま変更せず、「Sheet1」としてます。
image.png

  • S3にアップロードする
    「qiita-test」というフォルダを作成し、その中にエクセルファイルをアップロードします。
    image.png
  • 対象インスタンスのタグを確認します
    image.png
    image.png
    image.png

IAMロールを作成する

信頼されたエンティティでLambdaを指定してロールを作成します。
image.png

  • 以下の通り作成します
    ロール名

    • Create-EC2-Tag-for-Lambda

    ポリシー

    • AmazonS3FullAccess
    • AmazonEC2FullAccess
      image.png

Lambda関数を作成する

先ほど作成したIAMロールを指定してください。
image.png

ソースコード
※1行ずつに対して処理を実行するので大量のインスタンスに対して実行する場合はいい感じに書き換えて使ってください(笑)
(APIの書き方サンプルだと思っていただければ)

create_tag.py
import json
import boto3
import openpyxl
from io import BytesIO

s3_client = boto3.client('s3')
ec2_client = boto3.client('ec2')
bucket_name = "バケット名"

#指定したインスタンスIDにタグを付与
def create_tags(instance_id,tag_key,tag_value):
    response = ec2_client.create_tags(
        Resources = [
            instance_id
            ],
        Tags=[
            {
                'Key': tag_key,
                'Value': tag_value
            },
        ]
    )

#インスタンス名からインスタンスIDを取得
def get_instanceid(instance_name):
    response = ec2_client.describe_instances(Filters=[{'Name':'tag:Name','Values':[instance_name]}])
    for reservation in response['Reservations']:
      for instance in reservation['Instances']:
        # インスタンスIDを取得
        instance_id = instance.get('InstanceId')
        return instance_id

#エクセルファイルを1行ずつ読み込んで処理
#インスタンス名からインスタンスIDを取得し、対象のインスタンスにタグを付与
def lambda_handler(event, context):
    object_key = event["excel-file"]
    s3_resp = s3_client.get_object(Bucket=bucket_name, Key=object_key)
    wb = openpyxl.load_workbook(BytesIO(s3_resp['Body'].read()),data_only=True)
    main_ws = wb["Sheet1"]

    #エクセルファイルを読み込む
    for row in main_ws.rows:
        if row[0].row == 1:
            # 1行目
            header_cells = row
        else:
            # 2行目以降
            row_dic = {}
            # セルの値を「key-value」で登録
            for k, v in zip(header_cells, row):
                row_dic[k.value] = v.value
    
            print("エクセルファイルから1行ずつ読み込んだ結果:{}".format(row_dic))
            
            #インスタンス名からインスタンスIDを取得
            instance_id = get_instanceid(row_dic["InstanceName"])
            
            #取得したインスタンスIDにタグを付与
            tag_key = row_dic["TagKey"]
            tag_value = row_dic["TagValue"]
            create_tags(instance_id,tag_key,tag_value)
            
    print("タグ付けが完了しました")

レイヤーにOpenpyxlモジュールを追加します
image.png

Lambdaを実行する

テストイベントを定義し保存します。
image.png

テストを実行します
image.png

成功しました
image.png

タグの確認

対象インスタンス3台に対してエクセルファイル内で指定したタグが付与されていることが確認できました!
image.png
image.png
image.png

さいごに

今回はLambdaを使ってEC2にタグを付与してみました。
Openpyxlのモジュールの使い方の勉強にもなったので検証できてよかったです。

とりあえず動くものをと思って作ったので見返すと無駄が多いコードになってしまっていますが。。。。
基本的なboto3を使ったAPIの呼び出しのサンプルとして誰かの役に立てれば幸いです。
(大量のインスタンスに対して処理する際はインスタンスIDをリスト化したり、エラー処理を挟んだほうがいいと思うので、いい感じに書き換えて使ってください笑)

最後まで読んでいただきありがとうございました。

5
5
0

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
  3. You can use dark theme
What you can do with signing up
5
5