この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
Amazon Connectでは、事前に用意された処理を組み合わせることで、自由に電話応対フロー(Contact Flow)を作成することができます。 例えば、通話中にユーザがプッシュした番号によって案内の内容を変えたり、ユーザの電話番号によってどのオペレータにつながるか指定することができます。 事前に用意された処理はブロックと呼ばれていますが、その中にはAWS Lambdaを実行するブロックも含まれています。 なので、電話でAWSリソースの参照や操作ができます。 今回はAmazon ConnectをつかってEC2インスタンスを再起動する仕組みを作りました。
概要
電話をかけると次のようなやりとりが発生します。 (Amazon Connect)
You have 3 instances. Which one do you want to reboot? i-xxxxxx is number 0. i-yyyyyyy is number 1. i-zzzzzzz is number 2.
(ユーザ) "1#"と押す
(Amazon Connect) 指定されたi-yyyyyyyの再起動を開始した後
i-yyyyyyy is rebooting now.
電話切れる。
今回作ったContact Flowです。 下記のような処理を行っています。
処理の単位であるブロックの一覧はこちらをご覧ください。 現時点で30個近いブロックが用意されていますが、今回利用するのは次の5つです。
- Check contact attributes: 電話番号等ユーザ情報を元に処理を分岐させる
- Play prompt: ユーザにメッセージを返す
- Store customer input: ユーザにメッセージを返した後、ユーザから入力(プッシュ番号)を受け取り、保存する
- Invoke AWS Lambda function: Lambdaファンクションを実行する
- Disconnect / hang up: 電話を切る
Contact Flowの作成
Contact Flowの作成はVirtual contact center instanceの管理ページから行います。 https://{エンドポイント}/connect/contact-flows Virtual contact center instanceの作成方法はこちらのエントリーを参照ください。 AWSのコールセンターサービス Amazon Connectの試し方
画面右上にある「Create contact flow」から作成を開始します。
発信元チェック
「Check contact attributes」ブロックで電話の発信元をチェックしています。 知らない人が僕のサーバを再起動するのは避けたいからです。
僕の電話番号以外から電話がかけられた場合、「Play prompt」ブロックでメッセージを流して「Disconnect / hang up」ブロックで電話を切ります。
EC2インスタンスリストの取得
発信元の電話番号に問題がない場合、「Invoke AWS Lambda function」ブロックでAWS Lambdaファンクションを呼び出し、インスタンスIDのリストを受け取ります。 このブロックで指定するのはLambdaファンクションのARNとLambdaに渡すパラメータです。ここでは"Action: List"というパラメータを渡しています。 注意が必要なのはTimeoutの最大値が8秒と短い点です。なので、時間がかかる処理には向きません。
AWS Lambdaファンクション側のコードです。
import boto3
def lambda_handler(event, context):
ec2 = boto3.client("ec2")
resultMap = {}
action = event['Details']['Parameters']['Action']
if action == 'List':
instances = ec2.describe_instances()
if len(instances['Reservations']) == 0:
resultMap['NumInstances'] = '0'
else:
instance_ids = [i['InstanceId'] for r in instances['Reservations'] for i in r['Instances']]
resultMap['NumInstances'] = str(len(instance_ids))
resultMap['InstanceIds'] = ','.join(instance_ids)
resultMap['InstanceIdList'] = '<speak>You have %s instances. Which one do you want to reboot?' % len(instance_ids)
for i, instance_id in enumerate(instance_ids):
resultMap['InstanceIdList'] += '<say-as interpret-as="characters">%s</say-as> is number %s.' % (instance_id, i)
resultMap['InstanceIdList'] += '</speak>'
elif action == 'Reboot':
instance_ids = event['Details']['Parameters']['InstanceIds'].split(',')
instance_id = instance_ids[int(event['Details']['Parameters']['InstanceIndex'])]
ec2.reboot_instances(InstanceIds=[instance_id])
resultMap['RebootInstance'] = '<speak><say-as interpret-as="characters">%s</say-as> is rebooting now.</speak>' % (instance_id)
return resultMap
「Invoke AWS Lambda function」ブロックから渡されたパラメータは"event['Details']['Parameters']"で受け取ります。 また、Lambdaからの返り値はAWS Connectで利用できます。 Lambdaファンクションには必要な権限を持ったIAMロールを割り当ててください。
LambdaがAWS Connectから受け取る値や返り値の制限等、詳しい説明は下記ページを参照ください。 Granting Amazon Connect Access to AWS Lambda Functions AWS ConnectからLambdaを呼び出すために、リソースポリシーの設定も必要です。その設定方法もこのページに記載されています。
ユーザによるインスタンスの選択
Lambdaから返されたEC2インスタンスのリストをユーザに提示し、リブートするインスタンスを選択させましょう。 「Store customer input」ブロックを使います。 先ほどのLambdaファンクションのレスポンスはこんな感じなので、InstanceIdListの内容をユーザに伝えます。
{
'InstanceIdList': '<speak>You have 3 instances.Which one do you want to reboot?<say-as interpret-as="characters">i-xxxx</say-as> is number 0.<say-as interpret-as="characters">i-yyyy</say-as> is number 1.<say-as interpret-as="characters">i-zzzz</say-as> is number 2.</speak>',
'InstanceIds': 'i-xxxx,i-yyyy,i-zzzz'
}
ここでユーザが入力した数字はシステムに保存されます。
インスタンス再起動
リブートするインスタンスが選択されたので、「Invoke AWS Lambda function」ブロックで指定のインスタンスを再起動します。 今回は3つのパラメータを送っています。
- Action: Reboot
- InstanceIds: (先ほどLambdaからかえされたInstanceId)
- InstanceIndex: (ユーザの入力した番号)
画像からは見切れていますが、ARNは先ほどのLambdaファンクションと同じにしています。 なので、先ほどのLambdaファンクションが上記パラメータを受け取り、指定されたインスタンスをリブートします。
終了
リブート開始後、LambdaからAmazon Connectに
{
'RebootInstance': u'<speak><say-as interpret-as="characters">i-zzzz</say-as> is rebooting now.</speak>'
}
のような値が返されるので「Play prompt」ブロックでユーザに伝えます。
電話を切るために「Disconnect / hang up」ブロックにつなげて終了です。
最後に
Amazon Connectを使って電話からEC2を再起動する仕組みを作りました。 読み上げのリプレイやユーザ選択の確認、エラー処理等、実際はもっと作り込みが必要ですが基本的なフローであればあっという間に作ることができます。 Amazon Connectはコールセンター以外の用途としても便利なのでぜひ使って見てください。