AWS SAM でGolangのデバッグができるようになったので試してみた

RSSのフィードにAWS SAM CLIGolangデバッグができるようになったというニュースが流れてきました。

AWS SAM CLI Now Supports Debugging Go Functions and Testing with 50+ Events

確かにリリースノートにも書いてある。

Release 🐛 Debug your Lambda Functions written in Go, and generate sample payloads for 50+ events · awslabs/aws-sam-cli · GitHub

とういことでやってみました。

SAM CLI更新

$ pip install --upgrade aws-sam-cli

$ pip show aws-sam-cli Name: aws-sam-cli Version: 0.6.0 Summary: AWS SAM CLI is a CLI tool for local development and testing of Serverless applications Home-page: https://github.com/awslabs/aws-sam-cli Author: Amazon Web Services Author-email: aws-sam-developers@amazon.com License:

$ sam --version SAM CLI, version 0.6.0

$ sam local start-api --help
#----省略
  --debugger-path TEXT            Host path to a debugger that will be mounted
                                  into the Lambda container. 
#----省略

テスト用のSAM定義の準備

簡単なSAMの定義と、

$ cat template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
  MyApiFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: .
      Handler: debugtest
      Runtime: go1.x
      Events:
        TestApi:
          Type: Api
          Properties:
            Path: '/test'
            Method: get

API Gatewayトリガで動くLambdaを準備しました。

$ cat main.go 
package main

import (
        "context"
        "fmt"

        "github.com/aws/aws-lambda-go/events"
        "github.com/aws/aws-lambda-go/lambda"
)

func handleRequest(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
        fmt.Printf("Processing request data for request %s.\n", request.RequestContext.RequestID)
        fmt.Printf("Body size = %d.\n", len(request.Body))

        fmt.Println("Headers:")
        for key, value := range request.Headers {
                fmt.Printf("    %s: %s\n", key, value)
        }

        return events.APIGatewayProxyResponse{Body: "OK!", StatusCode: 200}, nil
}

func main() {
        lambda.Start(handleRequest)
}

delve(デバッガ)の準備

delveをデバッガーとして利用するのですが、これをsam localで起動するDockerにマウントするため、特定のディレクトリを準備して、そこにdlvというファイル名でビルドします。

$ GOARCH=amd64 GOOS=linux go build -o debug/dlv github.com/derekparker/delve/cmd/dlv
$ ls debug/
dlv

Goの実行ファイルをビルド

debugtestという実行ファイル名でビルドします。 この際に -gcflags='-N -l' をオプションとして渡します。

$ GOARCH=amd64 GOOS=linux go build -gcflags='-N -l' -o debugtest

VSCodeの設定

VSCode使っているので、以下のデバッグ設定を入れます。

$ cat .vscode/launch.json 
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Connect to Lambda container",
      "type": "go",
      "request": "launch",
      "mode": "remote",
      "remotePath": "",
      "port": 5986,
      "host": "127.0.0.1",
      "program": "${workspaceRoot}",
      "env": {},
      "args": []
    }
  ]
}

sam local 起動

以下のように、delveの実行ファイルを置いたパスと、デバッグポートを指定sam localを起動します。

$ sam local start-api -d 5986 --debugger-path debug

一つリクエストを送るとDockerが起動します。

$ curl http://127.0.0.1:3000/test
Fetching lambci/lambda:go1.x Docker container image......
2018-09-01 09:19:07 Mounting /path/to/gopath/go/src/github.com/yomon8/debugtest as /var/task:ro inside runtime container

VSCodeから繋がてみると、デバッグができるようになりました!

f:id:yomon8:20180901092807p:plain

参考URL

https://github.com/awslabs/aws-sam-cli/blob/develop/docs/usage.rst#debugging-golang-functions