#はじめに
AWS Lambda(Python3)を構築する際、直接Lambda関数の画面で作業してもいいのですが、デバッグしづらいし、エディタは使いづらい。
その為、ローカル環境で一度作成してから、AWS Lambdaへアップする方法を記載します。
→2017/12/02追記
AWSアップデートされCould9なんてものが追加されたし、AWS Lambdaエディタ機能も追加されたので、今後はブラウザ上だけで充分かもね(´・ω・`)
##環境
各インストール方法はぐぐってね。
OSはWindows10 Proにて確認。
- Python3(https://www.python.org/downloads/)
- AWS CLI(https://aws.amazon.com/jp/cli/)
- Boto3(https://aws.amazon.com/jp/sdk-for-python/)
- ATOMエディタ(https://atom.io/)
事前にAWS AMIアカウントから「アクセスキー」、「シークレットアクセスキー」を発行後
コマンドプロンプト「aws configure」で登録してね。
$ aws configure
aws_access_key_id = アクセスキー
aws_secret_access_key = シークレットアクセスキー
region = ap-northeast-1
output = json
###ATOMアドオン
- atom-beautify スクリプト整形用※
- atom-runner Python実行用★必須
- autocomplete-python Python補完用※
- file-icons アイコンが変わるよ
- highlight-selected 選択文字列ハイライト表示※
- japanese-menu ATOM日本語化※
- minimap スクロールバー※
- python-autopep8 Python補完用
- show-ideographic-space 全角スペース表示用※
- symbols-tree-view 関数、変数一覧表示
- web-search ATOMからWeb検索用
atom-runnerはATOM上でPythonを実行するのに必須。※印はお勧めアドオンです。
##動作確認(Python3コード)
以下コードをコピーし、適当なファイル名+拡張子(.py)で作成後、「ALT+R」でPythonを実行。
稼働中のEC2インスタンスIDとTag名(サーバー名)を取得します。
import boto3
import json
ec2c = boto3.client('ec2')
##############################################
#起動しているインスタンスID取得
##############################################
def func_GetInstanceId():
instanceid_List = []
retec2c = ec2c.describe_instances(
Filters=[
{'Name':'instance-state-name','Values': ['running']}
]
)
for reservation in retec2c['Reservations']:
for instanceid in reservation['Instances']:
instanceid_List.append(instanceid['InstanceId'])
return instanceid_List
##############################################
#インスタンスIDからタグ名取得
#引数:インスタンスID(i-1234567890ABCDEFG)
#戻り値:タグ名 Win2016_SV、未設定の場合は「サーバー名未設定」
##############################################
def func_RET_ServerTagName(SET_InstanceId):
TagName = ec2c.describe_tags(
Filters=[
{'Name': 'resource-id', 'Values': [SET_InstanceId]}
,{'Name': 'tag-key', 'Values': ['Name']}
])
try:
RET_ServerTagName=TagName['Tags'][0]['Value']
except Exception as e:
RET_ServerTagName="サーバー名未設定"
return RET_ServerTagName
################################
# MAIN
################################
#def lambda_handler(event, context):
if __name__ == "__main__":
#起動中のEC2インスタンスIDを取得
insid_list=func_GetInstanceId()
for insid in insid_list:
#インスタンスIDからTag名(サーバー名)を取得
ins_name=func_RET_ServerTagName(insid)
print(ins_name + "(" + insid + ")")
##出力例
以下インスタンスIDは適当に書き換えています
Win2016SV1(i-123456789ABCDEFG)
サーバー名未設定(i-123456789)
Windows2012SV2(i-0123456789abcd)
##AWS Lambdaにアップする際に修正する箇所
if __name__ == "__main__":
をコメントアウトし
def lambda_handler(event, context):
を有効にしましょう。
#def lambda_handler(event, context):
if __name__ == "__main__":
↓
def lambda_handler(event, context):
#if __name__ == "__main__":
あとはAWS Lambdaにコピペして動作を確認。
#時刻取得その1
時刻を取得する際、ローカル環境ではOSの時刻を取得する為、JSTで取得できますが
Lambda上はGMTで取得する為、+9時間する必要がありますよ。
import datetime
#Lambda上で実行する場合
#def lambda_handler(event, context):
#ローカルで実行する場合
if __name__ == "__main__":
#ローカルで実行する場合
d = datetime.datetime.now()
#Lambda上で実行する場合
#d = datetime.datetime.now() + datetime.timedelta(hours=9)
print("d時間:" + str(d))
#時刻取得その2
もしくは環境変数キー名「TZ」値「Asia/Tokyo」を追加すればJSTで取得する為、上記の様に+9時間しなくても大丈夫。
##グローバル変数で時刻を取得すると・・・だれかが死ぬ
日付時刻を取得する際、関数内で取得せず、グローバル変数として取得した場合、
AWS Lambda上2回目の動作以降に同じ時間を取得するはめになりますので注意。
※障害例
時刻取得処理をトリガーにて9:00開始、10分毎に実行した際、
9:00に実行した場合は、初回に実行する為「9:00」と正確に取得しますが、次回9:10に実行した際にも「9:00」と取得される。9:20以降もずーっと「9:00」で取得されてしまう。
またこれがLambdaテスト実行時には再利用されないため障害は発生せず、トリガーで定期的に実行すると発生するやっかいなヤツ。
・2回目以降のLambdaを再利用している為発生する模様。
http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-introduction.html
#時刻取得(正)
import datetime
def lambda_handler(event, context):
d = datetime.datetime.now() + datetime.timedelta(hours=9) # ◎関数内の為毎回取得します。
print("d時間:" + str(d))
#時刻取得(誤)
import datetime
d = datetime.datetime.now() + datetime.timedelta(hours=9) # ×グローバル変数で取得しちゃダメ
def lambda_handler(event, context):
print("d時間:" + str(d))
以上