AWSのLambdaからLambdaを呼んで、Slackにメッセージを送信する

# 今回のお題
機能単位でLambdaを作成し、Lambda内からLambdaを実行する。
また、Requestで必要なデータを送信し、Responseで結果を得る。
本来はAWSのサービスのStep FunctionsやSNS使うことを考える必要があるのだろうけど、
チュートリアルなので次の課題とさせていただきます。

# Requestで受けた情報を元にSlackへメッセージを送信するLambdaの作成
[LambdaからWebHookを使用してSlackにメッセージを送信してみる
](https://qiita.com/seisyu1985/items/c59dbb8164b5332d5c9e)
こちらを元に、下記のように定義しました。
少しずつ最終形に近づいています。

```slack.py
# 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, # アイコン
    }))
```
## ポイント
1. eventの中にはRequest内のパラメータが入っていますので、そこからSlackに使用する情報を取得しました。
    1. user_id : メンションするユーザID(**Slackで自動で振られるMemberIDを使用**)
    2. message : 本文
    3. channel : 送信先のチャンネル
2. WebhookのURLを環境変数に入れて暗号化しました。使用する際に複合化してます。
    3. [Lambdaの環境変数をKMSで暗号化して、Pythonで複合化する
](https://qiita.com/seisyu1985/items/880c5e49e8c8677bc9e3)を元に実施しました。定数にしたり、DynamoDBに入れたりとかが正かもしれませんが、今回は環境変数にしました。

## テスト実行。
テストイベントで、Requestパラメータを下記のように設定します。
<img width="821" alt="スクリーンショット 2017-11-21 0.08.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/204329/af27c41d-6c8d-e86e-5427-e53fe681d9d6.png">

この状態でテストを実行します。
<img width="592" alt="スクリーンショット 2017-11-21 0.14.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/204329/a53f9f90-3201-499b-a96d-0f1bfbb38287.png">
チャンネルやちゃんとした名前はボカしてますが、無事にRequestから取得した内容でSlack通信できました。
(テストデータにゴミが入ってますね・・・失礼しました・・・)

# 別のLambdaから実行する
[AWSでPythonを使用したLambdaを作ってみる](https://qiita.com/seisyu1985/items/c5560c5eaea5b5ff9098)
を元に、新規で１つLambdaを作成し、下記のようなソースを記載します。

```lambda.py
# -*- 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"])
```

## ポイント
1. boto3.client("lambda")を使用して、lambdaをソースから実行できるようにしてます。
2. RequestパラメータはJSON形式をエンコードして渡します。
3. Response情報は、clientLambda.invokeでの結果を受け取り、Payloadの中に入ります。そちらを読み取り、JSON形式に変換してます。

## テスト実行するとエラーに・・・
こちらで一度実行して見ました。
するとエラーになり、下記の文言が出てきました。

```
 is not authorized to perform
```
どうやら、デフォルトで用意されているロールの「lambda_basic_execution」を設定している場合は、他のLambdaを実行する権限が無いようです。

# ロールを作成する

IAM>ロール>ロールの作成ボタンを押下します。
<img width="248" alt="スクリーンショット 2017-11-21 0.25.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/204329/b8b921de-9982-df83-5e39-4ac0cd7dbb6c.png">

## ロールの作成
1. AWSを選択します。
<img width="808" alt="スクリーンショット 2017-11-21 0.26.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/204329/e570cb65-2a20-dce6-7b4f-3697e6b9d9a4.png">
2. Lambdaを選択し、次のステップへ
<img width="959" alt="スクリーンショット 2017-11-21 0.27.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/204329/2aff6f60-c21d-d8b5-7b9a-6da8c0dc1ec9.png">

## ポリシーの選択
画面上部でlambdaと入力し、必要なものを絞り込みます。
<img width="966" alt="スクリーンショット 2017-11-21 0.27.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/204329/075b70eb-9336-8e07-cb66-a1ecacd51999.png">

1. Lambdaでは、Cloud Watchが必要なようなので、「AWSLambdaBasicExecutionRole」を選択します。
<img width="960" alt="スクリーンショット 2017-11-21 0.28.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/204329/f69ecfbe-06a0-99f3-88eb-1a801077d679.png">
2. 他のLambdaを呼ぶために、「AWSLambdaRole」も追加します。
<img width="954" alt="スクリーンショット 2017-11-21 0.29.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/204329/7c8026c3-20ca-0529-b207-9d40eb620d0b.png">
**おそらく、Resourceも指定して設定するのが本来の用途だと思いますが、今回は割愛します**
他にも必要に応じて、DynamoDBやRDSなど、必要なものを追加します。

## ロール名と説明を入力して、完了
<img width="422" alt="スクリーンショット 2017-11-21 0.32.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/204329/4ea870ae-c856-af34-9b5d-ff3d2b895afe.png">
説明は空でも構いません。

## 作成が完了すると、一覧に表示されます。
<img width="1059" alt="スクリーンショット 2017-11-21 0.33.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/204329/b1f99df0-a61c-80f9-7f9e-a63cbe4e3261.png">

# Lambdaに戻って、ロールの設定をする。
先ほどのエラーになったLambdaに戻り、ロールを選択して保存します。
<img width="438" alt="スクリーンショット 2017-11-21 0.34.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/204329/6437de70-cc16-0181-050e-f24dfe0eed59.png">

## テスト実行
テスト成功(returnを書いてないためnullになっている)
<img width="939" alt="スクリーンショット 2017-11-21 0.35.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/204329/ac5ba2c7-d7b1-ce36-b061-cd5519a89ab7.png">

ログにも、retの値のTrueが出る
<img width="575" alt="スクリーンショット 2017-11-21 0.35.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/204329/fe36f187-6b2a-faf3-63e1-cffebe0420e1.png">

Slackにも送信結果が出力される。
<img width="578" alt="スクリーンショット 2017-11-21 0.38.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/204329/2c6bc70b-9b5b-1aac-63e0-229692deddc1.png">

### 以上で、LambdaからLambdaを呼ぶことができました。
boto3については下記を参照願います。
http://boto3.readthedocs.io/en/latest/reference/services/lambda.html