SNSトピックへのメッセージをGoランタイムのLambdaでSlack通知する
前置き
AWSのリソースに関するイベントをSlackに通知したい欲があり 少し前にLamdaのGo言語サポートが実装されたことを思い出したので Goランタイムで動くLambda関数を作成しました。
実装コード
package main import ( "bytes" "context" "fmt" "net/http" "os" "github.com/antonholmquist/jason" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" ) type Slack struct { WebhookURL string Channel string Name string Emoji string Message string } func send(s Slack) { jsonStr := `{"channel":"` + s.Channel + `","username":"` + s.Name + `","icon_emoji":"` + s.Emoji + `","text":"` + s.Message + `"}` req, err := http.NewRequest( "POST", s.WebhookURL, bytes.NewBuffer([]byte(jsonStr)), ) if err != nil { fmt.Print(err) } req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Print(err) } fmt.Print(resp) defer resp.Body.Close() } func createMessage(message string) string { json, err := jason.NewObjectFromBytes([]byte(message)) if err != nil { panic(err) } text := "<!channel>\n```\n" for k, v := range json.Map() { s, sErr := v.String() if sErr == nil { text += fmt.Sprintf("%s\t:%s\n", k, s) } else { text += fmt.Sprintf("%s\t:%s\n", k, sErr) } } text += "```" return text } func slackNotice(ctx context.Context, snsEvent events.SNSEvent) { for _, record := range snsEvent.Records { snsRecord := record.SNS var s = Slack{os.Getenv("WEBHOOK_URL"), os.Getenv("SLACK_CHANNEL"), os.Getenv("SLACK_NAME"), os.Getenv("SLACK_EMOJI"), createMessage(snsRecord.Message)} send(s) } } func main() { lambda.Start(slackNotice) }
Slackに通知するためのPost処理の部分は、
crossbridge-lab.hatenablog.com
こちらの記事を参考にさせていただきました。
SNSのイベント情報を取得する
今回の本命処理は、以下の部分です。 (本命と言うほどでもない)
func slackNotice(ctx context.Context, snsEvent events.SNSEvent) { for _, record := range snsEvent.Records { snsRecord := record.SNS var s = Slack{os.Getenv("WEBHOOK_URL"), os.Getenv("SLACK_CHANNEL"), os.Getenv("SLACK_NAME"), os.Getenv("SLACK_EMOJI"), createMessage(snsRecord.Message)} send(s) } }
今回は、SNSトピックに色々なイベントを集約して同一のSlackチャンネルに通知する方針です。
そのため、snsEvent events.SNSEvent
でトリガーとなったSNSのイベント情報を取得しています。
また、Slack通知関係の定数(WebhookURLなど)は、Lambda関数の環境変数をos.Getenv
で取ってくるようにしているため、別のアカウントでも流用できる形となっています。
まとめ
Go言語は初学者中の初学者なのですが、割と直感的に書けていい感じの言語だと思いました。 また、フォーマッティングまで言語がサポートしてくれるのはとても嬉しいですね。
もっと複雑な処理もサーバーレスに処理できるようにLambdaGoの知見を貯めて行きたいと思います。