alfalfa

package module
v0.0.0-...-2ebb6ce Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 18, 2021 License: MIT Imports: 6 Imported by: 0

README

Build Status Coverage Status Contributors GitHub pull requests GitHub closed pull requests GitHub stars

alfalfa (ALexA Lambda Fun Aws)

Demo alexa skill using a go lambda function, deployed with cloudformation

Purpose

  • show how to use cloudformation to deploy everything in one run (Alexa, Lambda, IAM roles and policies)
  • demonstrate golang lambda structure with localization support
  • build skill from code (generate JSON required for the Alexa skill from the code)
  • demonstrate good code design: keeping it simple and separated
  • demonstrate good integration with travis and coveralls

How to use it

See Usage

For l10n, see README.md

code structure

commands
  • /cmd/alfalfa -> ./deploy/app is the default command (for lambda)
  • app make --skill is the command to generate the Alexa skill json file
  • app make --models is the command to generate the Alexa model json files
  • app just runs the lambda function, waiting for a request

what goes where?

  • link to markdown file, explaining code structure, separation of concerns, interfaces, ...

golang context

  • don't "misuse" context to pass logger etc. instead make the application satisfy the required interfaces

Setup/Tools

Install ask cli on macOS

requires Homebrew

brew install ask-cli
# alternatively via npm:
brew install npm
npm install -g ask-cli

Setup ask-cli

ask init
# follow instructions, link ask to an aws account (required for cloudformation Alexa skill to assume S3 role)
# visit https://developer.amazon.com/settings/console/securityprofile/web-settings/view.html for the `ASKClientId` and `ASKClientSecret`

ask util generate-lwa-tokens --no-browser
# redirects you to the browser to authenticate, will output `access_token` and `refresh_token`
# take the `refresh_token` for `ASKRefreshToken` below

Test lambda locally

Why?

  • Run tests (alexa requests) against your code before you commit or merge with master.
  • Add tests to build pipeline to ensure correct functionality.
Run tests
# will build for linux/amd64 and run multiple requests using lambci/lambda:go1.x docker image
./test/tests.sh
Using aws cli tools (OBSOLETE)

Install prerequisites:

pip install --user --upgrade awscli # aws-sam-cli : did not work for me, see below
docker pull lambci/lambda:go1.x

sam requires a zip file

(cd deploy; zip deploy.zip app)
sed -e 's#../deploy#./deploy.zip#' cloudformation/cloudformation.yml > deploy/template.yml
# now we have a template that points to our zip file
# did not work for me, but apparently should (some problem launching the docker?):
#sam local invoke --debug -t deploy/template.yml "LambdaFunction"

# this works:
(GOARCH=amd64 GOOS=linux go build -a -ldflags "-s -X main.version=$(git describe --tags --always)" -o ./deploy/app ./cmd/alfalfa)
(cd deploy; 
cat ../test/lambda_intent-slot_request.json |
docker run --platform linux/amd64 --rm -i -v "$PWD":/var/task -e DOCKER_LAMBDA_USE_STDIN=1 lambci/lambda:go1.x app
)

Test cloudformation locally

Why?

  • run the cloudformation template regularly while you develop and add to it
  • run the cloudformation template from your local machine to test
  • ensure that the aws user has all the permissions needed to create the resources in the stack

What you need:

  • setup AWS credentials which can be used to execute cloudformation (see ~/.aws/credentials)
  • this cloudformation user needs permissions for
    • cloudformation
    • lambda
    • IAM roles and policies
    • S3
Set variables manually
export GO111MODULE=on
# required for lambda
export GOARCH=amd64
export GOOS=linux
export AWS_ACCESS_KEY_ID=<AccessKeyId>
export AWS_SECRET_ACCESS_KEY=<SecretAccessKey>
export AWS_DEFAULT_REGION=<AWSRegion>
export CF_STACK_NAME=<StackName>
export ASKS3Bucket=<S3Bucket>
export ASKS3Key=<S3File>
export ASKClientId=<ClientId>
export ASKClientSecret=<ClientSecret>
export ASKRefreshToken=<RefreshToken>
export ASKVendorId=<VendorId>
Using .env file
  • write plain variable assignements into .env file (do NOT commit, it's also in .gitignore)
  • make sure you escape the | in the ASKRefreshToken like this: Atzr\|...
  • export the variables:

export $(grep -v '^#' .env | xargs)

Lint and test
go mod download
go get github.com/tj/mmake/cmd/mmake
go get golang.org/x/lint/golint
go get github.com/mattn/goveralls
alias make=mmake

export GOARCH=amd64

golint ./...
go vet ./...
go test -gcflags=-l -covermode=count -coverprofile=profile.cov ./...
./test/tests.sh
Build the lambda function
  • build for GOOS=Linux and GOARCH=amd64 (see above)
  • save it as ./deploy/app (referenced in the cloudformation template)
make build
mkdir deploy
mv ./alfalfa ./deploy/app
Run deploy.sh

(same as in .travis.yml)

  • make deploy directory
  • build lambda for cloudformation
  • run deploy.sh
    • generates skill.json and <locale>.json files for Alexa and uploads to S3
    • deploys via cloudformation (branch master -> production, else staging)
      • staging: append -staging to cloudformation stack name
      • packages Alexa skill and uploads it to S3
      • cloudformation packages deploy/app and uploads it to S3
    • if staging: (branch != master)
      • deletes the cloudformation stack 10 seconds after deploy (unless you set KEEP_STACK=1)
      • you can set a different CF_STACK_NAME, but deploy.sh will still append -staging...
mkdir deploy
go build -a -ldflags "-s -X main.version=$(git describe --tags --always)" -o ./deploy/app ./cmd/alfalfa
bash ./cloudformation/deploy.sh
Validate the Skill witk ask
ask validate -s amzn1.ask.skill.xxx -l en-US > result_en-US.json
# output is long, search for "FAIL"

TODOs

Before first "release"

  • simplify skill and models definition with helper functions -> gen package
    • basic structure refactoring + documentation
  • Integrate intent definition and locale with lambda (simplify app/lambda) Issue #36
  • add documentation and examples
    • use case examples (see Usage)
    • simple app example explanation in docs
  • add test cases for lambda (request/response)
  • Add staging deploy (validation) Issue #30
    • decide: staging deploy -> review+fix or try to validate as much as possible before deploying (see Issue #17)
  • implement and integrate l10n package
  • complete (defined portions) of alexa package (enums, consts, ...)
    • test coverage of package
    • externalize and make package public

Cloudformation

Alexa schemas

Further reading

Documentation

Overview

Package alfalfa contains base elements of the skill project (app, skill).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CreateSkillModels

func CreateSkillModels(s *skill.SkillBuilder) (map[string]*skill.Model, error)

CreateSkillModels generates and returns a list of Models.

func NewSkill

func NewSkill() *skill.SkillBuilder

NewSkill returns a configured SkillBuilder.

Types

type Application

type Application struct {
	// contains filtered or unexported fields
}

Application defines the base application.

func NewApplication

func NewApplication(l log.Logger, s stats.Statter) *Application

NewApplication returns an Application with the logger and statter.

func (*Application) AWSStatus

func (a *Application) AWSStatus(loc l10n.LocaleInstance, area, region string) (alexa.Response, error)

AWSStatus responds with messages containing 2 slots.

func (*Application) AWSStatusAreaElicit

func (a *Application) AWSStatusAreaElicit(l l10n.LocaleInstance, area string) (alexa.Response, error)

AWSStatusAreaElicit will ask for the Area value.

func (*Application) AWSStatusRegionElicit

func (a *Application) AWSStatusRegionElicit(l l10n.LocaleInstance, region string) (alexa.Response, error)

AWSStatusRegionElicit will ask for the Region value.

func (*Application) Demo

func (a *Application) Demo(l l10n.LocaleInstance) (alexa.Response, error)

Demo is a simple demo response.

func (*Application) Help

func (a *Application) Help(l l10n.LocaleInstance) (alexa.Response, error)

Help is the response to a help request.

func (*Application) Launch

func (a *Application) Launch(l l10n.LocaleInstance) (alexa.Response, error)

Launch is the response to the launch request.

func (*Application) Logger

func (a *Application) Logger() log.Logger

Logger returns the application logger.

func (*Application) SSMLDemo

func (a *Application) SSMLDemo(l l10n.LocaleInstance) (alexa.Response, error)

SSMLDemo is the intent to demonstrate SSML output with Alexa.

func (*Application) SaySomething

func (a *Application) SaySomething(loc l10n.LocaleInstance, opts ...ResponseFunc) (alexa.Response, error)

SaySomething handles simple title + text response.

func (*Application) Statter

func (a *Application) Statter() stats.Statter

Statter returns the application statter.

func (*Application) Stop

func (a *Application) Stop(l l10n.LocaleInstance) (alexa.Response, error)

Stop is the response to stop the skill.

type Config

type Config struct {
	User string
}

Config defines additional data that can be provided and used in requests.

type ResponseFunc

type ResponseFunc func(cfg *Config)

ResponseFunc defines the function that can optionally be passed to responses.

func WithUser

func WithUser(user string) ResponseFunc

WithUser returns a ResponseFunc that sets the user.

Directories

Path Synopsis
cmd
Package lambda defines intents, handles requests and calls Application functions accordingly.
Package lambda defines intents, handles requests and calls Application functions accordingly.
middleware
Package middleware for lambda requests Package middleware for lambda requests
Package middleware for lambda requests Package middleware for lambda requests
Package loca contains all localization for the skill.
Package loca contains all localization for the skill.
pkg
alexa
Package alexa enables parsing request and building responses.
Package alexa enables parsing request and building responses.
alexa/l10n
Package l10n provides locale helpers (LocaleRegistry) and predefined standard keys for Alexa skills
Package l10n provides locale helpers (LocaleRegistry) and predefined standard keys for Alexa skills
alexa/skill
Package skill serves generating the skill and model.
Package skill serves generating the skill and model.
alexa/ssml
Package ssml provides functions to simplify working with SSML speech.
Package ssml provides functions to simplify working with SSML speech.
Package server is a standalone http server (as replacement for lambda)
Package server is a standalone http server (as replacement for lambda)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL