今回のお題
機能単位でLambdaを作成し、Lambda内からLambdaを実行する。
また、Requestで必要なデータを送信し、Responseで結果を得る。
本来はAWSのサービスのStep FunctionsやSNS使うことを考える必要があるのだろうけど、
チュートリアルなので次の課題とさせていただきます。
Requestで受けた情報を元にSlackへメッセージを送信するLambdaの作成
LambdaからWebHookを使用してSlackにメッセージを送信してみる
こちらを元に、下記のように定義しました。
少しずつ最終形に近づいています。
# coding: UTF-8
import requests
import json
import os
from base64 import b64decode
import boto3
from datetime import datetime
def lambda_handler(event, context):
# 時間を設定
now = datetime.now()
msg = now.strftime("%Y/%m/%d %H:%M:%S")
# メンションを設定
if event['user_id'] != None:
msg += "\r\n<@%s>" % event['user_id']
# メッセージを設定
msg += u"\r\n%s" % event["message"]
# 実行
send_slack(u'カイジ', u':kaiji:', event['channel'], msg)
return {"ret": True}
# slack送信、仮メソッド
def send_slack(user_name, icon, channel, msg):
# WEBHOOK URLを複合化
kms = boto3.client('kms')
webhook = kms.decrypt(CiphertextBlob=b64decode(os.environ['WEBHOOK_URL']))['Plaintext']
requests.post(webhook, data = json.dumps({
'text': msg, # 投稿するテキスト
'username': user_name, # 投稿のユーザー名
'link_names': 1, # メンションを有効にする
'channel': channel, # チャンネル
'icon_emoji': icon, # アイコン
}))
ポイント
- eventの中にはRequest内のパラメータが入っていますので、そこからSlackに使用する情報を取得しました。
- user_id : メンションするユーザID(Slackで自動で振られるMemberIDを使用)
- message : 本文
- channel : 送信先のチャンネル
- WebhookのURLを環境変数に入れて暗号化しました。使用する際に複合化してます。
3. Lambdaの環境変数をKMSで暗号化して、Pythonで複合化する
を元に実施しました。定数にしたり、DynamoDBに入れたりとかが正かもしれませんが、今回は環境変数にしました。
テスト実行。
テストイベントで、Requestパラメータを下記のように設定します。
この状態でテストを実行します。
チャンネルやちゃんとした名前はボカしてますが、無事にRequestから取得した内容でSlack通信できました。
(テストデータにゴミが入ってますね・・・失礼しました・・・)
別のLambdaから実行する
AWSでPythonを使用したLambdaを作ってみる
を元に、新規で1つLambdaを作成し、下記のようなソースを記載します。
# -*- coding: utf-8 -*-
import boto3
import json
def lambda_handler(event, context):
clientLambda = boto3.client("lambda")
# 引数
params = {
"user_id": "1234567890",
"message": "lambdaからlambdaを実行する",
"channel": "test"
}
res = clientLambda.invoke(
FunctionName="呼び出すLambdaの関数名",
InvocationType="RequestResponse",
Payload=json.dumps(params)
)
# ResponseをJson形式に変換
pay=json.loads(res['Payload'].read())
# 表示
print(pay["ret"])
ポイント
- boto3.client("lambda")を使用して、lambdaをソースから実行できるようにしてます。
- RequestパラメータはJSON形式をエンコードして渡します。
- Response情報は、clientLambda.invokeでの結果を受け取り、Payloadの中に入ります。そちらを読み取り、JSON形式に変換してます。
テスト実行するとエラーに・・・
こちらで一度実行して見ました。
するとエラーになり、下記の文言が出てきました。
is not authorized to perform
どうやら、デフォルトで用意されているロールの「lambda_basic_execution」を設定している場合は、他のLambdaを実行する権限が無いようです。
ロールを作成する
ロールの作成
- AWSを選択します。
ポリシーの選択
- Lambdaでは、Cloud Watchが必要なようなので、「AWSLambdaBasicExecutionRole」を選択します。
ロール名と説明を入力して、完了
説明は空でも構いません。作成が完了すると、一覧に表示されます。
Lambdaに戻って、ロールの設定をする。
先ほどのエラーになったLambdaに戻り、ロールを選択して保存します。
テスト実行
テスト成功(returnを書いてないためnullになっている)
以上で、LambdaからLambdaを呼ぶことができました。
boto3については下記を参照願います。
http://boto3.readthedocs.io/en/latest/reference/services/lambda.html