LoginSignup
2
2

More than 5 years have passed since last update.

AlexaスキルでGo

Last updated at Posted at 2019-03-02

前回(Alexa-hostedスキルを使用してAlexaスキルを作ってみる)、Go言語でAlexaスキルで作ろうと思って始めたものの、途中から脱線してAlexa-hostedスキルの方に流れてしまいました。
改めてGo言語で。前回作ったやつのバックエンド部分は捨てる想定です。
なので作るスキルは一緒。

Go言語をLambdaにデプロイする

しかし、やはりというかなんというか、すでにやっている方おられますね。
AlexaスキルをGoとServerlessで書いてみた

このままやったらだいたいできるんじゃないかしら。
進めていて詰まる所があったら記します。なければこの記事には公開の意義ないかもしれん。

まずはこちらを参考に進める

$ serverless create -u https://github.com/serverless/serverless-golang/ -p alexa-kamefood-go
$ cd alexa-kamefood-go
$ vi serverless.yml
$ diff serverless.yml serverless.yml.orig 
25,26c25,26
<   stage: dev
<   region: ap-northeast-1
---
> #  stage: dev
> #  region: us-east-1
57,59d56
<     memorySize: 128
<     events:
<       - alexaSkill
$ go get github.com/aws/aws-lambda-go/lambda

で、おおよそこちらのレポジトリの内容でdeployしたらうまくいきました。

$ sls deploy
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Warning! You are using an old syntax for alexaSkill which doesn't restrict the invocation solely to your skill. Please refer to the documentation for additional information.
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
.....
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service alexa-kamefood-go.zip file to S3 (10.04 MB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
...................
Serverless: Stack update finished...
Service Information
service: alexa-kamefood-go
stage: dev
region: ap-northeast-1
stack: alexa-kamefood-go-dev
resources: 6
api keys:
  None
endpoints:
  None
functions:
  hello: alexa-kamefood-go-dev-hello
layers:
  None

で、alexa-kamefood-go-dev-hello というfunctionができております。(functionの名称どうでも良かったのでhelloのままです。。)

image.png

テストしても普通に使える。
結局、すんなりといきました。

コードを書く

その後、こちらをインスパイアしつつ、コードを仕上げていきます。
なお、json読みこむようにしたのでserverless.yml 少し変えました

serverless.yml
package:
 exclude:
   - ./**
 include:
   - ./bin/**
   - ./jsons/**

jsonのあたりのコードはこんな感じです。

main.go
var (
        // ErrInvalidIntent is error-object
        ErrInvalidIntent = errors.New("Invalid intent")
        FoodJsonFile string = "./jsons/foods.json"
)

.....

        // JSONファイル読み込み
        foods := make(map[string]string)
        bytes, err := ioutil.ReadFile(FoodJsonFile)
        if err != nil {
            log.Fatal(err)
        }
        // JSONデコード
        if err := json.Unmarshal(bytes, &foods); err != nil {
            log.Fatal(err)
        }

        if food, ok := intent.Slots["foodSlot"]; ok {
            if speech, ok := foods[food.Value]; ok {
                speechOutput = speech
            }else{
                speechOutput = "すみません。" + food.Value + "についてはわかりませんでした。他の食べ物の名前を聞いてみてくださいね。ではまた。"
            }
        } else {
            speechOutput = "すみません。わかりませんでした。他の食べ物の名前を聞いてみてくださいね。ではまた。"
        }

encoding/json を使っています。
なお、コードについては参照元のライセンス表記がなく、ちょっと公開するのがグレーなので公開は控えておきます。

申請

実はAlexa-hostedのままで申請をしていたのですが、取り下げつつ、Goのlambda functionのものと差し替えてみました。

で、切り替え後のテスト

82.png

うん、大丈夫そう。
Go言語の方のLambda functionで申請してみます。

おまけ

で、これで終わったらちょっとつまんないので少し遊ぶ。
git hubに上げたら勝手にdeployするようにしたいです。
aws codestarを使ってみます。

開いてロール作成

83.png

Go言語を選択し、GitHubアカウントに連携します

84.png

buildspec.ymlとtemplate.yml編集

けっこう適当なので余計な部分とかあるかもですが。

buildspec.yml
version: 0.2

phases:

  install:
    commands:

      # AWS Codebuild Go images use /go for the $GOPATH so let's symlink our
      # application source code into that directory structure.
      #- ln -s "${CODEBUILD_SRC_DIR}" "/go/src/handler"

  pre_build:
    commands:

      # Make sure we're in the project directory within our GOPATH
      #- cd "/go/src/handler"

      # Fetch all dependencies
      - go get github.com/aws/aws-lambda-go/lambda
      - go get encoding/json
      - go get io/ioutil

  build:
    commands:
      # Build our go application
      - go build -o bin/main main.go
      #- serverless deploy -v
      # Copy static assets to S3, and package application with AWS CloudFormation/SAM
      - aws cloudformation package --template template.yml --s3-bucket $S3_BUCKET --output-template template-export.yml

  post_build:
    commands:
      # Do not remove this statement. This command is required for AWS CodeStar projects.
      # Update the AWS Partition, AWS Region, account ID and project ID in the project ARN on template-configuration.json file so AWS CloudFormation can tag project resources.
      - sed -i.bak 's/\$PARTITION\$/'${PARTITION}'/g;s/\$AWS_REGION\$/'${AWS_REGION}'/g;s/\$ACCOUNT_ID\$/'${ACCOUNT_ID}'/g;s/\$PROJECT_ID\$/'${PROJECT_ID}'/g' template-configuration.json

artifacts:
  type: zip
  files:
    - template-export.yml
    - template-configuration.json
template.yml
AWSTemplateFormatVersion: 2010-09-09
Transform:
- AWS::Serverless-2016-10-31
- AWS::CodeStar

Parameters:
  ProjectId:
    Type: String
    Description: AWS CodeStar projectID used to associate new resources to team members
  CodeDeployRole:
    Type: String
    Description: IAM role to allow AWS CodeDeploy to manage deployment of AWS Lambda functions
  Stage:
    Type: String
    Description: The name for a project pipeline stage, such as Staging or Prod, for which resources are provisioned and deployed.
    Default: ''

Globals:
  Function:
    AutoPublishAlias: live
    DeploymentPreference:
      Enabled: true
      Type: Canary10Percent5Minutes
      Role: !Ref CodeDeployRole

Resources:
  hello:
    Type: AWS::Serverless::Function
    Properties:
      Handler: bin/main
      Runtime: go1.x
      Role:
        Fn::GetAtt:
        - LambdaExecutionRole
        - Arn
      Events:
        AlexaSkillEvent:
          Type: AlexaSkill
  LambdaExecutionRole:
    Description: Creating service role in IAM for AWS Lambda
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub 'CodeStar-${ProjectId}-Execution${Stage}'
      AssumeRolePolicyDocument:
        Statement:
        - Effect: Allow
          Principal:
            Service: [lambda.amazonaws.com]
          Action: sts:AssumeRole
      Path: /
      ManagedPolicyArns:
        -  arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      PermissionsBoundary: !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/CodeStar_${ProjectId}_PermissionsBoundary'

いらないファイルを削ったり、ソースを置いたり

publicとか、main-test.goとか消しました。
あとはソースを上書き。

githubにpush

で勝手にlambda関数が作られます。
ちゃんと動きました。

85.png

CodeStar使って、Codepipelineの一式(CodeCommit or GitHub, CodeBuild, CodeDeploy)がまるっと作られた感じです。
あら、便利。

というか、CodeBuild内でSeverless FrameWorkのコマンド書いちゃえばCode Buildだけでもできそう。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2