1.はじめに
1.1目的
golangと、lambdaを使ってアレクサスキルと作りたくなったのでやってみる。
1.2環境
Windows(GitBash)
Go Version 1.22.0
1.3前提条件
- Amazon 開発者アカウントの作成を事前に行う。下記リンクより、Amazon開発者アカウントの作成を元に準備してください
2.Golangでソースを書き、Lambdaにデプロイしよう
アプリ名naviQiita(ナビキータ)で作成をしていきます。
以下の解説でアプリ名やリソース名などは自身が作成するものに適宜合わせてください。
2.1 コーディング
公式ドキュメントを参考に作成してみる
- goプロジェクトの準備を行います
適当な作業ディレクトリを作成しそのディレクトリ配下で下記コマンドを叩き、Go.modを作成しますmodule-pathは適宜自身の物に合わせてください(僕は、module-pathを"githun.com/keny-N/NaviQiita"にします)$ go mod init [module-path] go: creating new go.mod: module [module-path]
- AWS Lambda go ADKのインストール
$ go get github.com/aws/aws-lambda-go/lambda go: downloading github.com/aws/aws-lambda-go v1.46.0 go: added github.com/aws/aws-lambda-go v1.46.0
- ファイルを作成していく
- /cmd/alexa-skill/main.go
package main
import (
"context"
"githun.com/keny-N/NaviQiita/internal/qiita"
"githun.com/keny-N/NaviQiita/pkg/response"
"github.com/aws/aws-lambda-go/lambda"
)
func Handler(ctx context.Context) (response.AlexaResponse, error) {
items, err := qiita.FetchQiitaItems()
if err != nil {
return response.AlexaResponse{}, err
}
message := "最新のQiitaの記事を5つ紹介します。。: "
for _, item := range items {
message += item.Title + ", URL: " + item.URL + ". "
}
return response.CreateResponse(message), nil
}
func main() {
lambda.Start(Handler)
}
- /internal/qiita/qiita.go
package qiita
import (
"encoding/json"
"net/http"
)
type QiitaItem struct {
Title string `json:"title"`
URL string `json:"url"`
}
func FetchQiitaItems() ([]QiitaItem, error) {
resp, err := http.Get("https://qiita.com/api/v2/items?page=1&per_page=5")
if err != nil {
return nil, err
}
defer resp.Body.Close()
var items []QiitaItem
if err := json.NewDecoder(resp.Body).Decode(&items); err != nil {
return nil, err
}
return items, nil
}
- /pkg/response/response.go
package response
type AlexaResponse struct {
Version string `json:"version"`
SessionAttributes struct{} `json:"sessionAttributes"`
Response struct {
OutputSpeech struct {
Type string `json:"type"`
Text string `json:"text"`
} `json:"outputSpeech"`
} `json:"response"`
}
func CreateResponse(message string) AlexaResponse {
return AlexaResponse{
Version: "1.0",
Response: struct {
OutputSpeech struct {
Type string `json:"type"`
Text string `json:"text"`
} `json:"outputSpeech"`
}{
OutputSpeech: struct {
Type string `json:"type"`
Text string `json:"text"`
}{
Type: "PlainText",
Text: message,
},
},
}
}
module githun.com/keny-N/NaviQiita
go 1.22.0
require github.com/aws/aws-lambda-go v1.46.0 // indirect
github.com/aws/aws-lambda-go v1.46.0 h1:UWVnvh2h2gecOlFhHQfIPQcD8pL/f7pVCutmFl+oXU8=
github.com/aws/aws-lambda-go v1.46.0/go.mod h1:dpMpZgvWx5vuQJfBt0zqBha60q7Dd7RfgJv23DymV8A=
4.以下のコマンドを実行して、Linux向けの実行可能ファイルをビルドします
"main"という名前の実行ファイルが生成されます
```
$ GOOS=linux GOARCH=amd64 go build -o bootstrap cmd/naviQiita/main.go
```
5.mainファイルをzip形式に圧縮する
(注意)ここが一番ハマッタ
windows環境で圧縮する場合は、公式の手順通り行ってください。
WindowsでそのままZIPを作成したらパーミッションエラーで怒られます。
go install github.com/aws/aws-lambda-go/cmd/build-lambda-zip@latest
# このコマンドだけpowershellでたたきました(他はGitbash)
$ $env:GOOS = "linux"
$ $env:GOARCH = "arm64"
$ $env:CGO_ENABLED = "0"
$ go build -tags lambda.norpc -o bootstrap cmd\naviQiita\main.go
$ ~\Go\Bin\build-lambda-zip.exe -o myFunction.zip bootstrap
6.最終的なフォルダ構成
githubにソースコードを挙げているので参考にしてください
└─NaviQiita
│ bootstrap
│ go.mod
│ go.sum
│ myFunction.zip
│
├─cmd
│ └─naviQiita
│ main.go
│
├─internal
│ └─qiita
│ qiita.go
│
└─pkg
└─response
response.go
2.2 Lambdaの準備
東京リージョンにリソースを作成します(AWSCLIの設定であらかじめ東京リージョンにデフォルトで繋がるようにしています)
- Lambdaのロールを作成
$ aws iam create-role --role-name navi-qiita --assume-role-policy-document '{"Version": "2012-10-17","Statement": [{ "Effect": "Allow", "Principal": {"Service": "lambda.amazonaws.com"}, "Action": "sts:AssumeRole"}]}' { "Role": { "Path": "/", "RoleName": "navi-qiita", "RoleId": "AROA4MTWKLOMIZOLHCBGP", "Arn": "{ここに作成したロールのArnが記載される}", "CreateDate": "2024-03-29T17:43:18+00:00", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } } }
- Lambda関数を作成する
Arnにはロールを作成したときに返ってきたArnを入力する$ aws lambda create-function --function-name "NaviQiita" --runtime provided.al2023 --handler bootstrap --zip-file fileb://myFunction.zip --role arn:aws:iam::xxxxxxxx --architectures arm64
- 作成されたことを確認する
AWSのLambdaの画面を開き、リソースが作成されていることを確認する
3.アレクサスキルを作成しよう
Alexa公式ページの第1回: 初めてのスキル開発を参考にアレクサスキルを作成していきましょう
※記事が古いので一部UIが違う部分もあるので注意
参考 ↓
3.1 アレクサスキルの作成
-
トップメニューよりAlexaを押下する
-
Alexa開発者コンソールが開かれるので、スキルの作成を押下する
作成したスキルはこの画面で後ほど確認することもできます
-
各項目を入力し、次へを押下する
スキル名:Alexaスキルの名前(好きなものを入力しよう)
プライマリロケール:僕は日本語しかできないので日本語を選択
-
各項目を選択し次へを押下する
エクスペリエンスタイプ:ニュース(作るスキルに合わせて好きに選択してください)
モデル:カスタム
ホスティングサービス:独自のプロビジョニング
-
スキルの呼び出し名を変更する
今回はアレクサスキル名と同じにしていますが、呼び出し名の要件や、実際にアレクサにスキルを起動してもらうときに言いやすい、覚えやすい呼び出し名にすることをおすすめします。
呼び出し名を変更後、画面右上のスキルをビルドを押下してください。
-
Lambdaと紐づけ
Lambda側でトリガーの追加
作成したLambda関数の詳細画面に移動し、トリガー -> トリガーを追加を押下する
AlexaのAlexaSkillsKitを選択し、スキルIDには作成しアレクサスキルのIDを入力する。入力後追加を押下する
SkillIDはAlexaスキルのエンドポイントの画面より確認できる(後述)
トリガーが追加されたことを確認する。
次の手順で関数のARNが必要になるのでコピーしておく
エンドポイントを押下し、デフォルトの地域の欄に先ほど作成したLambdaのARNを入力します。
この画面で、スキルIDを取得できます
保存ボタンを押下し、画面右下に緑のメッセージが表示されればOK
3.2 スキルのテスト
-
開発者コンソール画面上部のテストを押下する
4.感想
アレクサスキルをLambda,golangを混ぜて作成してみて楽しかった。
Qiitaの記事タイトルとURLを返すようにしているがここらへんをもう少し工夫してアレクサスキルで実用的になるようにできればいいなと思った。
記事の中身をよみあげるなどなど。
ハマッタポイント
Lambdaにファイルをアップしたらパーミッションエラーで怒られた
Windows環境で、ファイルに適切なパーミッションをつけて圧縮しても効果がないらしい。(詳しい人おしえてください)
なので、公式が案内している方法でzipファイルを作成する必要があった
#### エラー内容
Error: fork/exec /var/task/bootstrap: permission denied
解決策
Windows での .zip ファイルの作成の手順通り圧縮すればいけた
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/golang-package.html#golang-package-windows