Lambdaで実行したい外部コマンドがある場合、通常バイナリをパッケージに含めることになりデプロイに時間がかかってしまう。
package main
import (
"fmt"
"os/exec"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
cmd := exec.Command("git", "clone", "https://github.com/sambaiz/foobar.git", "/tmp/repo")
output, err := cmd.CombinedOutput()
if err != nil {
return events.APIGatewayProxyResponse{
Body: fmt.Sprintf("%s %s", string(output), err.Error()),
StatusCode: 500,
}, nil
}
return events.APIGatewayProxyResponse{
Body: string(output),
StatusCode: 200,
}, nil
}
func main() {
lambda.Start(handler)
}
exec: "git": executable file not found in $PATH
Lambda Layerを使うと
ライブラリやバイナリを切り出すことができ、複数Functionで共有することもできる。
ディレクトリをzipにしてLayerに指定すると中身が/opt
に展開され、/opt/bin
にはPATHが、/opt/lib
にはLD_LIBRARY_PATHが通るほか、
言語ごとのパッケージ置き場がある。
$ tree layer/
layer/
└── bin
└── some-command
zipはS3に上げておくこともできるが、
SAMではAWS::Lambda::LayerVersionのContentUriでローカルのパスを指定することもでき、
sam local
でも適用される。
そうする場合packageするのにAWS CLIのバージョンが1.16.67以降である
必要がある。
AWS SAMでLambdaの関数をデプロイしServerless Application Repositoryに公開する - sambaiz-net
$ cat template.yaml
...
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello-world/
Handler: hello-world
Runtime: go1.x
Layers:
- !Ref ExampleLayer
Events:
CatchAll:
Type: Api
Properties:
Path: /hello
Method: GET
ExampleLayer:
Type: AWS::Serverless::LayerVersion
Properties:
LayerName: SomeCommandLayer
Description: some-command binary is included
ContentUri: './layer'
CompatibleRuntimes:
- go1.x
RetentionPolicy: Delete
というこどでlambci/git-lambda-layerを入れてgitを使えるようにしようと思ったが、 調べているうちにsrc-d/go-gitを見つけたのでこちらを使うことにした。
_, err := git.PlainClone("/tmp/repo", false, &git.CloneOptions{
URL: "https://github.com/sambaiz/foobar.git",
Progress: os.Stdout,
})