webフォームからの問い合わせをRedmineに自動登録して対応状況を管理する(API Gateway + Lambda)
先日、検証目的で作成したRedmineの冗長化の一機能として、webフォームから問い合わせがあった場合に、Redmineのチケットを自動登録して対応状況を管理出来るようにしてみました。
- webフォームはS3で静的ホスティングを使っています。
- CloudFrontでS3をオリジンにしてwebフォームを配信しています。
- ACMでSSL証明書を無料で取得しています。
- webフォームから送信された情報はAmazon API Gateway、AWS Lambdaを経由してDynamoDBテーブルへ格納されます。
- DynamoDBテーブルに格納されたデータはDynamoDB StreamからLambdaが実行されてSQSへキューを送信します。
- SQSからキューを受信したLambdaがRedmine APIをコールしてチケットを作成します。
※ DynamoDBを介しているのは、Redmineへ送る必要のないデータも含めて記録しておくためです。
※ SQSを介しているのはRedmine APIがコール出来ない場合に再処理を容易にするためと、再処理回数をSQSのデッドレターキュー機能で制限したいためです。
※ 4で6の処理をするAWS Lambdaを実行してもいいですが、Redmine APIがコール出来ない場合の再処理などを考慮する必要があると思います。
Lambdaは全部Python3.6です。
目次
webフォームからのポストを受けてDynamoDBへ送信するLambda
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import logging import boto3 import traceback from datetime import datetime logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): logger.info(event) try: dynamodb = boto3.resource('dynamodb') table = dynamodb.Table('contact') event['submit_datetime'] = datetime.now().strftime('%Y%m%d%H%M%S') table.put_item(Item=event) except: logger.error(traceback.format_exc()) raise Exception(traceback.format_exc()) |
- DynamoDBテーブルではsubmit_datetimeをパーティションキーに、フォームから送信されるメールアドレスをソートキーにしています。
DynamoDB Streamから実行されてSQSへキューを送信するLambda
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
import logging import boto3 import json import traceback logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): logger.info(event) try: sqs_url = os.environ['SQS_URL'] if not ('Records' in event): return event sqs = boto3.client('sqs') records = event['Records'] for record in records: if not ('dynamodb' in record): continue if not ('NewImage' in record['dynamodb']): continue contact = record['dynamodb']['NewImage'] response = sqs.send_message( QueueUrl=sqs_url, MessageBody=json.dumps( { 'contact_name': contact['contact_name']['S'], 'mail_address': contact['mail_address']['S'], 'contact_detail': contact['contact_detail']['S'] } ) ) logger.info(response) except: logger.error(traceback.format_exc()) raise Exception(traceback.format_exc()) |
- sqsのurlはLambdaの環境変数に入力しておきます。
SQSからキューを受信してRedmine APIをコールしてチケットを作成するLambda
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# coding:utf-8 import logging import boto3 import json import os import traceback from redminelib import Redmine from base64 import b64decode logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): try: redmine_url = os.environ['REDMINE_URL'] enc_key = os.environ['REDMINE_KEY'] redmine_key = boto3.client('kms').decrypt(CiphertextBlob=b64decode(enc_key))['Plaintext'] sqs_url = os.environ['SQS_URL'] sqs = boto3.client('sqs') message = sqs.receive_message( QueueUrl=sqs_url, MaxNumberOfMessages=1 ) logger.info(message) if not('Messages' in message): return message_body = json.loads(message['Messages'][0]['Body']) logger.info(message_body) redmine = Redmine( redmine_url, key=redmine_key ) issue = redmine.issue.new() issue.project_id = 'contact' issue.subject = u'{name}様から問い合わせ'.format( name=message_body['contact_name'] ) issue.description = '{body}\n{mail}'.format( body=message_body['contact_detail'].replace( 'newline', '\n' ), mail=message_body['mail_address'] ) issue.save() response = sqs.delete_message( QueueUrl=sqs_url, ReceiptHandle=message['Messages'][0]['ReceiptHandle'] ) logger.info(response) except: logger.error(traceback.format_exc()) raise Exception(traceback.format_exc()) |
- sqsのurlはLambdaの環境変数に入力しておきます。
- RedmineのurlはLambdaの環境変数に入力しておきます。
- redmineのAPIキーは登録するプロジェクトにチケットを作成する権限を持っているユーザーのAPIキーを使用します。
- redmineのAPIキーは環境変数に入力してKMSで暗号化します。
最後までお読みいただきましてありがとうございました!
「AWS認定資格試験テキスト&問題集 AWS認定ソリューションアーキテクト - プロフェッショナル 改訂第2版」という本を書きました。
「AWS認定資格試験テキスト AWS認定クラウドプラクティショナー 改訂第3版」という本を書きました。
「AWS認定資格試験テキスト AWS認定AIプラクティショナー」という本を書きました。
「ポケットスタディ AWS認定 デベロッパーアソシエイト [DVA-C02対応] 」という本を書きました。
「要点整理から攻略するAWS認定ソリューションアーキテクト-アソシエイト」という本を書きました。
「AWSではじめるLinux入門ガイド」という本を書きました。
開発ベンダー5年、ユーザ企業システム部門通算9年、ITインストラクター5年目でプロトタイプビルダーもやりだしたSoftware Engineerです。
質問はコメントかSNSなどからお気軽にどうぞ。
出来る限りなるべく答えます。
このブログの内容/発言の一切は個人の見解であり、所属する組織とは関係ありません。
このブログは経験したことなどの共有を目的としており、手順や結果などを保証するものではありません。
ご参考にされる際は、読者様自身のご判断にてご対応をお願いいたします。
また、勉強会やイベントのレポートは自分が気になったことをメモしたり、聞いて思ったことを書いていますので、登壇者の意見や発表内容ではありません。
関連記事
-
-
Amazon SNSサブスクリプションフィルターを設定してPython(boto3)からPublish
上記のような構成でRocketChatを使うとき使わないときがあります。 都度都 …
-
-
AWS EC2 インスタンスステータスのチェックで失敗 原因はPHP-FPMのOOM-KILLER
先週に引き続きEC2のインスタンスステータスチェックで失敗 再起動するも失敗する …
-
-
S3バケットポリシーですべてDenyにしてしまったらルートユーザーの出番
特定のConditionsを指定して、それ以外はすべて拒否するS3バケットポリシ …
-
-
EC2 Global Viewで不要なインスタンスを見つけて4つほど終了しました
EC2 Global Viewという機能がリリースされました。 EC2コンソール …
-
-
Amazon Auroraのスナップショットの暗号化とリージョン間コピーを改めて試しました
Amazon Auroraデータベースを暗号化して、スナップショットを作成、クロ …
-
-
AWS CodeCommitのリポジトリをiPhoneのWorkingCopyアプリから使う
iPhoneからも執筆できるようにしておこうと思いまして、iOSアプリのGitク …
-
-
AWS Cost Explorerの設定で「EC2リソースの推奨事項を受け取る」を有効にしました
「EC2リソースの推奨事項を受け取る」という機能がAWS Cost Explor …
-
-
JAWS-UG関西IoT専門支部 ✕ SORACOM UG 関西「Wio LTE + 絶対圧センサーで遊ぼう!」ワークショップにいってきた
JAWS-UG関西IoT専門支部 ✕ SORACOM UG 関西「Wio LTE …
-
-
AWS Transit Gatewayピアリング接続確認
AWS Transit Gatewayのピアリング接続を使用して、異なるリージョ …
-
-
Amazon EC2(Amazon Linux 2)にRedmine3.4をインストール
久しぶりに新しい環境でRedmineを構築したくなり、せっかくなのでAmazon …


