5
2

More than 1 year has passed since last update.

AWS Appsync Lambdaの練習(チュートリアル)

Last updated at Posted at 2022-12-09

こんにちは。
SARAH FoodDataBankの沈(シム)です。
弊社のFoodDataBankはAWSのAppsync + Lambdaの組み合わせてサービスを提供しているので、勉強のため、改めてAppsync + Lambdaの組み合わせを実施してみました。

役に立つ対象

既存のREST APIまたはAPI Gatewayを用いてAPIを実装していた方
AppsyncでAPIを実装したい方

システム図

スクリーンショット 2022-12-08 14.02.47.png

必要なAWSリソース

  • Appsync
  • Lambda
  • DynamoDB
  • IAM Role(Lambda用、AppSync用)
  • SAM

AppSync作成

まず、AppSyncを作成します。
AWS Consoleで「API 作成」ボタンを押下し、「一から構築」を選択し、「開始」ボタンをクリック
スクリーンショット 2022-12-08 14.16.34.png

API 名には適切な名前を入力し、「作成」ボタンをクリク
スクリーンショット 2022-12-08 14.17.42.png

AppSync APIが作成できると、左メニューの「スキーマ」をクリックし、スキーマの中身を以下のように設定します。
その後、「スキーマ保存」ボタンをクリック
スクリーンショット 2022-12-08 14.19.29.png

スキーマ

type Mutation {
    putPost(
        field: String!,
        pk: String!,
        sk: String!,
        title: String!
    ): Post
}

type Post {
    field: String!
    pk: String!
    sk: String!
    title: String
}

type Query {
    singlePost(field: String!, pk: String!, sk: String!): Post
}

schema {
    query: Query
    mutation: Mutation
}

DynamoDB作成

AWS consoleにてDynamoDBへ移動し、テーブル作成ボタンをクリックします。
練習用のため、簡単に作ります。
テーブル名は適切な名で入力し、パーティションキーはpk、ソートキーはsk入力し、「テーブル作成」ボタンをクリック
スクリーンショット 2022-12-08 14.23.36.png

Lambda

ディレクトリ構成
スクリーンショット 2022-12-08 14.35.43.png

// src/main.go
package main

import (
	"fmt"

	"github.com/aws/aws-lambda-go/lambda"
	"github.com/aws/aws-sdk-go/aws"
	"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"
)

type Post struct {
	Field string `json:"field"`
	Pk    string `json:"pk"`
	Sk    string `json:"sk"`
	Title string `json:"title"`
}

type Response struct {
	Pk    string `json:"pk"`
	Sk    string `json:"sk"`
	Title string `json:"title"`
}

func hander(arg Post) (Response, error) {

	response := Response{}

	fmt.Println("arg: ", arg)
	fmt.Println("[DEBUG]Start create session.")
	session, err := session.NewSession(
		&aws.Config{Region: aws.String("ap-northeast-1")},
	)
	if err != nil {
		return Response{}, err
	}
	svc := dynamodb.New(session)

	switch arg.Field {
	case "putPost":
		input := &dynamodb.PutItemInput{
			Item: map[string]*dynamodb.AttributeValue{
				"pk": {
					S: aws.String(arg.Pk),
				},
				"sk": {
					S: aws.String(arg.Sk),
				},
				"title": {
					S: aws.String(arg.Title),
				},
			},
			TableName: aws.String("fdb-sim-test-dynamodb"),
		}

		_, err = svc.PutItem(input)
		if err != nil {
			return Response{}, err
		}

		response.Pk = arg.Pk
		response.Sk = arg.Sk
		response.Title = arg.Title

	case "singlePost":
		input := &dynamodb.GetItemInput{
			Key: map[string]*dynamodb.AttributeValue{
				"pk": {
					S: aws.String(arg.Pk),
				},
				"sk": {
					S: aws.String(arg.Sk),
				},
			},
			TableName: aws.String("fdb-sim-test-dynamodb"),
		}

		result, err := svc.GetItem(input)
		if err != nil {
			return Response{}, err
		}

		resultData := &Response{}
		if err := dynamodbattribute.UnmarshalMap(result.Item, resultData); err != nil {
			return Response{}, err
		}
		response.Pk = resultData.Pk
		response.Sk = resultData.Sk
		response.Title = resultData.Title
	}

	return response, nil
}

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

// src/go.mod
module example.com/main

go 1.18

require (
	github.com/aws/aws-lambda-go v1.36.0 // indirect
	github.com/aws/aws-sdk-go v1.44.154 // indirect
	github.com/jmespath/go-jmespath v0.4.0 // indirect
)

## samconfig.toml
version = 0.1

### Sandbox ###

[default]
[default.deploy]
[default.deploy.parameters]
stack_name = "fdb-sim-test-lambda-go" ## 自分のもので変更してください
s3_prefix = "fdb-sim-test-lambda-go" ## 自分のもので変更してください
region = "ap-northeast-1"
confirm_changeset = false
capabilities = "CAPABILITY_NAMED_IAM CAPABILITY_AUTO_EXPAND"

# template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Appsync Lambda test

Resources:
  TestFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: "fdb-sim-test-lambda"
      CodeUri: ./src/
      Handler: main
      Runtime: go1.x
      Timeout: 30
      MemorySize: 128
      Policies:
        - CloudWatchFullAccess
        - AmazonDynamoDBFullAccess

  TestFunctionLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub "/aws/lambda/fdb-sim-test-lambda"
      RetentionInDays: 30

注意点

main.goの中に記入されているDynamoDBの名前は自分のもので変更してください!

TableName: aws.String("fdb-sim-test-dynamodb"),

aws cliで以下のコマンドを入力します。

sam build
sam deploy --resolve-s3

Cloudfrontの新しいスタックが生成され、LambdaとCloudwatch Log、IAMロールが作成されます。

AppSync用IAMロール作成

AWS consoleにてIAMに移動し、ロール作成をクリックします。
「AWSのサービス」を選択し、「他のAWSのサービスのユースケース」でAppSyncを検索して選択します。
スクリーンショット 2022-12-08 14.48.17.png

許可ポリシーは後ほど追加するのでとりあえず、次ボタンを押下
スクリーンショット 2022-12-08 14.49.34.png

ロール名を適切なもので設定してください。
「Service」がappsync.amazonaws.comで設定されているのか確認後、作成ボタンを押下
スクリーンショット 2022-12-08 14.50.05.png

新しく作成できたロールにLambdaのポリシーを追加します。
※簡単にするため、Lambda_Fullaccessを追加しました。プロダクトには適切な権限を持ったポリシーを追加してください。
スクリーンショット 2022-12-08 14.58.50.png

AppSync設定

AppSyncに戻り、データセットとリゾルバーを設定します。
左メニューで「データソース」を選択し、新しいデータソースを追加します。
「データソース」名は適切な名を入力し、「データソースタイプ」を「AWS Lambda 関数」で選択します。
リージョンは作成したLambdaのリージョンを選択し、「関数のARN」にて先ほど作成したLambdaのARNを選択します。
ロール選択する時も「既存の役割」を選択して先ほど作成したAppSync用のロールを選択します。
スクリーンショット 2022-12-08 15.24.22.png

左メニューで「スキーマ」を選択し、右側の「Mutaion」下にあるputPostの「アタッチ」ボタンをクリックします。
スクリーンショット 2022-12-08 15.28.43.png

「アクション」ボタンで「ランタイムの更新」を選択します。
スクリーンショット 2022-12-08 15.29.58.png

「リゾルバータイプ」を「Unit Resolver(VTL only)」を選択し、Saveボタン押下
スクリーンショット 2022-12-08 15.30.53.png

「データソース名」で先ほど設定したデータソースを選択し、「マッピングテンプレートの設定」でrequest, responseのマッピングテンプレートをEnableにします。
各テンプレートは既にサンプルで提供されているものだけで良いので、
リクエストマッピングはInvoke and forward arguments
レスポンスマッピングはReturn Lambda resultで選択し、「リゾルバー保存」ボタンを押下
スクリーンショット 2022-12-08 15.32.22.png

テスト

AppSyncの左メニューで「クエリ」をクリックして実際にクエリを投げて疎通テストを行います。
クエリの入力欄に以下のクエリを入れて実行ボタンを押します。

mutation PutPost {
  putPost(field: "putPost", pk: "hoge", sk: "huga", title: "Hello! AppSync!!") {
    pk
    sk
    title
  }
}

画面の右側に入力したデータが返ってきたら成功です!
スクリーンショット 2022-12-08 15.36.12.png

実際にDynamoDBにデータが入っているのか確認してみましょう。
データはちゃんと入ってますね。
スクリーンショット 2022-12-08 15.39.23.png

まとめ

最近GraphQLでAPIを実装するのが当然ではあり、サーバーレス環境では結構使われているものなので、復習するために改めてAppSync + Lambdaで構築してみました。大体GraphQLのAPIがこんな感じで作られているのを認識できればと思います。
何か不明なものがありましたらコメントつけてください。
今回はAppSyncでリゾルバーを設定したやり方になってますが、AWS側ではダイレクトリゾルバーがあるので、次回はダイレクトリゾルバーを使ってAppSync + Lambdaをやってみようかと思います。

参照サイト

  • スキーマやLambdaのコードはこちらのサイトから参照

  • go.mod作成する方法

SARAH Tech Blog

5
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
5
2