概要 †AWS SDK for Go を触ってみる。 目次 †
Go Lambda のハンドラ †基本形 †有効な関数ハンドラは以下のページに記載されている通り。 例) package main
import (
"github.com/aws/aws-lambda-go/lambda"
)
func hello() (string, error) {
return "Hello World!", nil
}
func main() {
lambda.Start(hello)
}
Lambdaプロキシ統合を使用する場合 †API Gateway用のLambdaで Lambdaプロキシ統合を使用する場合、 https://github.com/aws/aws-lambda-go/blob/master/events/apigw.go 上記URLを見る限り、各パラメータはそれぞれ以下の通り取得できると思われる。
sample.go package main
import (
"fmt"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
return events.APIGatewayProxyResponse{
Body: fmt.Sprintf("Hello %s!", request.QueryStringParameters["name"]),
StatusCode: 200,
}, nil
}
func main() {
lambda.Start(handler)
}
SAM CLI によるローカルでの動作確認 †ハンドラをビルドしておく †GOOS=linux GOARCH=amd64 go build -o sample sample.go template.yml の作成 †AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Resources:
SampleFunction:
Type: AWS::Serverless::Function
Properties:
Handler: sample
Runtime: go1.x
Tracing: Active
Events:
GetEvent:
Type: Api
Properties:
Path: /
Method: get
SAM CLI で Lambda をinvoke †sample_request.json {
"path": "/",
"httpMethod": "GET",
"queryStringParameters": {
"name": "Taro"
}
}
イベントJSONの内容を入力として invoke sam local invoke "SampleFunction" -e sample_request.json 標準入力からリクエストデータを渡す場合は -e に "-" を指定する。(JSONを作りたくない場合) echo '{"path": "/", "httpMethod": "GET", "queryStringParameters": {"name": "Taro"}}' | sam local invoke -e "-" "SampleFunction"
SAM CLI で API を起動 †ローカルでAPI Gatewayを起動 sam local start-api --template template.yml 動作確認 curl http://127.0.0.1:3000/?name=Taro Hello Taro! ビルド †GOPATHを通しておく export GOPATH=/usr/local/Cellar/go/1.13.5 必要なライブラリをgo getしておく go get github.com/aws/aws-lambda-go/lambda ビルド GOOS=linux GOARCH=amd64 go build -o main main.go パッケージングとデプロイ †TODO: aws cloudformation package と deploy を使用する場合はzip圧縮等も自動でやってくれる?(未確認)
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-go-how-to-create-deployment-package.html 実装メモ †JSONデータを返却する †package main
import (
"fmt"
"encoding/json"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
type response struct {
Name string `json:"name"`
Message string `json:message`
}
func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
res := &response{
Name: request.QueryStringParameters["name"],
Message: fmt.Sprintf("Hello %s!", request.QueryStringParameters["name"]),
}
body, err := json.Marshal(res)
fmt.Printf("%+v", string(body))
if err != nil {
return events.APIGatewayProxyResponse{}, err
}
return events.APIGatewayProxyResponse{
Headers: map[string]string{
"Content-Type": "application/json",
},
Body: string(body),
StatusCode: 200,
}, nil
}
func main() {
lambda.Start(handler)
}
S3へのアクセス †https://docs.aws.amazon.com/sdk-for-go/api/service/s3/ package main
import (
"fmt"
"encoding/json"
"strings"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/aws"
)
type response struct {
Objects []string `json:objects`
}
var svc *s3.S3
var mybucket = "bucket.example"
/**
* 初期処理
*/
func init() {
svc = s3.New(session.New())
}
/**
* Lambdaハンドラ
*/
func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
// バケットにオブジェクトを追加
putInput := &s3.PutObjectInput{
Body: aws.ReadSeekCloser(strings.NewReader("test1 text!")),
Bucket: aws.String(mybucket),
Key: aws.String("test1.txt"),
}
putResult, putErr := svc.PutObject(putInput)
if putErr != nil {
fmt.Printf("Put Error!\n")
fmt.Printf("%+v\n", putErr)
} else {
fmt.Printf("Put Success!\n")
fmt.Printf("%+v\n", putResult)
}
// バケット内のオブジェクトを取得
getInput := &s3.GetObjectInput{
Bucket: aws.String(mybucket),
Key: aws.String("test1.txt"),
}
getResult, getErr := svc.GetObject(getInput)
if getErr != nil {
fmt.Printf("Get Error!\n")
fmt.Printf("%+v\n", getErr)
} else {
fmt.Printf("Get Success!\n")
fmt.Printf("%+v\n", getResult)
}
// バケット内のオブジェクト一覧を取得
listInput := &s3.ListObjectsV2Input{Bucket: aws.String(mybucket)}
result, _ := svc.ListObjectsV2(listInput)
myObjects := result.Contents
objects := []string{}
for i := 0; i < len(myObjects); i++ {
objects = append(objects, *myObjects[i].Key)
}
// レスポンスデータの設定
body, err := json.Marshal(&response{Objects: objects})
if err != nil {
return events.APIGatewayProxyResponse{}, err
} else {
return events.APIGatewayProxyResponse{
Headers: map[string]string{
"Content-Type": "application/json",
},
Body: string(body),
StatusCode: 200,
}, nil
}
}
func main() {
lambda.Start(handler)
}
DynamoDBへのアクセス †テーブル名:SampleTable、パーティションキー: pkey、ソートキー: skey とした場合の、登録(PutItem)、検索(GetItem、Query)の例。 参考: https://docs.aws.amazon.com/sdk-for-go/api/service/dynamodb/ package main
import (
"fmt"
"encoding/json"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/dynamodb"
"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
"github.com/aws/aws-sdk-go/aws"
)
type response struct {
Items []Record `json:items`
}
type Record struct {
Pkey string `json:pkey`
Skey string `json:skey`
Value string `json:value`
}
var svc *dynamodb.DynamoDB
var mytable = "SampleTable"
/**
* 初期処理
*/
func init() {
svc = dynamodb.New(session.New())
}
/**
* Lambdaハンドラ
*/
func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
//-------------------------------
// PutItem
//-------------------------------
putInput := &dynamodb.PutItemInput{
Item: map[string]*dynamodb.AttributeValue{
"pkey": {S: aws.String("test1")},
"skey": {S: aws.String("101")},
"value": {S: aws.String("sample data!")},
},
ReturnConsumedCapacity: aws.String("TOTAL"),
TableName: aws.String(mytable),
}
putResult, putErr := svc.PutItem(putInput)
if putErr != nil {
fmt.Printf("Put Error!\n")
fmt.Printf("%+v\n", putErr)
} else {
fmt.Printf("Put Success!\n")
fmt.Printf("%+v\n", putResult)
}
//-------------------------------
// GetItem
//-------------------------------
getInput := &dynamodb.GetItemInput{
Key: map[string]*dynamodb.AttributeValue{
"pkey": {S: aws.String("test1")},
"skey": {S: aws.String("101")},
},
TableName: aws.String(mytable),
}
getResult, getErr := svc.GetItem(getInput)
if getErr != nil {
fmt.Printf("Get Error!\n")
fmt.Printf("%+v\n", getErr)
} else {
fmt.Printf("Get Success!\n")
fmt.Printf("%+v\n", getResult)
}
//-------------------------------
// Query
//-------------------------------
items := []Record{}
queryInput := &dynamodb.QueryInput{
ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{
":key": {S: aws.String("test1")},
},
KeyConditionExpression: aws.String("pkey = :key"),
TableName: aws.String(mytable),
}
queryResult, queryErr := svc.Query(queryInput)
if queryErr != nil {
fmt.Printf("Query Error!\n")
fmt.Printf("%+v\n", queryErr)
} else {
fmt.Printf("Query Success!\n")
fmt.Printf("%+v\n", queryResult)
// 取得結果の構造体への変換は dynamodbattribute を使用して行う事ができる
// https://docs.aws.amazon.com/sdk-for-go/api/service/dynamodb/dynamodbattribute/
err := dynamodbattribute.UnmarshalListOfMaps(queryResult.Items, &items)
if err != nil {
panic(fmt.Sprintf("failed to unmarshal Dynamodb Scan Items, %v", err))
}
}
//-------------------------------
// レスポンスデータの設定
//-------------------------------
body, err := json.Marshal(&response{Items: items})
if err != nil {
return events.APIGatewayProxyResponse{}, err
} else {
return events.APIGatewayProxyResponse{
Headers: map[string]string{
"Content-Type": "application/json",
},
Body: string(body),
StatusCode: 200,
}, nil
}
}
func main() {
lambda.Start(handler)
}
Credentialの取得 †任意の Credential を指定する場合は credentials.NewChainCredentials などが利用できる。 ec2metrics.go package main
import (
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awsutil"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/cloudwatch"
)
func main() {
region := "ap-northeast-1"
accessKeyId := "XXXXXXXXXXXXXXXXXXXXXX"
secretAccessKey := "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
value, err := getAllMetrics(region, accessKeyId, secretAccessKey)
fmt.Printf("%+v", value)
if err != nil{
fmt.Printf("Error!")
}
}
/**
* メトリクスの一覧を取得する.
*/
func getAllMetrics(region string, accessKeyId string, secretAccessKey string) (cloudwatch.ListMetricsOutput, error) {
namespace := "AWS/EC2"
//metric := "CPUUtilization"
creds, err := GetCredentials(accessKeyId, secretAccessKey)
if err != nil {
return cloudwatch.ListMetricsOutput{}, err
}
cfg := &aws.Config{
Region: aws.String(region),
Credentials: creds,
}
sess, err := session.NewSession(cfg)
if err != nil {
return cloudwatch.ListMetricsOutput{}, err
}
svc := cloudwatch.New(sess, cfg)
params := &cloudwatch.ListMetricsInput{
Namespace: aws.String(namespace),
//MetricName: aws.String(metric),
}
var resp cloudwatch.ListMetricsOutput
err = svc.ListMetricsPages(params,
func(page *cloudwatch.ListMetricsOutput, lastPage bool) bool {
metrics, _ := awsutil.ValuesAtPath(page, "Metrics")
for _, metric := range metrics {
resp.Metrics = append(resp.Metrics, metric.(*cloudwatch.Metric))
}
return !lastPage
})
if err != nil {
return resp, err
}
return resp, err
}
/**
* クレデンシャル取得.
*/
func GetCredentials(accessKeyId string, secretAccessKey string) (*credentials.Credentials, error) {
creds := credentials.NewChainCredentials(
[]credentials.Provider{
&credentials.StaticProvider{Value: credentials.Value{
AccessKeyID: accessKeyId,
SecretAccessKey: secretAccessKey,
}},
//&credentials.EnvProvider{}, // 環境変数から取得?
})
return creds, nil
}
|