/ #lambda #appsync 

【CDK/Python】ゼロから作るAppSync!データソースはLambda

もくじ

最近お仕事でGraphQLに触れる機会がありまして、typescriptでインフラを作ったりしてました。

今回は自分用のメモでPythonで実装したらどんな感じだったのかな?を、 コマンドを順に叩くと作れるチュートリアル方式で残します。


今回つくるのはこんな感じです

前提

  • 自由にできるAWSのアカウントがある
  • Python3
  • CDK 1.128.0
  • 動作確認でGraphQL Playgroundを使います
  • バックエンドにストレージ的なものがないので、APIの返答はダミーデータです(笑)

では 作っていきましょう👻

プロジェクト用意

まず雛形になるプロジェクトを用意します

$ mkdir cdk-appsync-lambda && cd $_
$ cdk init --language python

次に依存関係を書きます。今回は自動生成されたsetup.pyを編集して行います。

#...略
setuptools.setup(
	#...略
    install_requires=[
        "aws-cdk.core==1.128.0",
		"aws-cdk.aws-lambda==1.128.0",
		"aws-cdk.aws-appsync==1.128.0",
    ],
#...略

インストール

$ pip install -r requirements.txt

スキーマを作る

ここはダミーでこんなスキーマを用意しました!程度です(笑)

type Query {
  getUsers: [User!]!
}

type Mutation {
  addUser(id: ID!, name: String): User
}

type User {
  id: ID!
  name: String
}

Userのオブジェクトがあり、一覧を見たり追加したりすることができます。

スタックを実装する

下記な感じです

from aws_cdk import core as cdk
import aws_cdk.aws_appsync as appsync
from aws_cdk.aws_lambda import Runtime
from aws_cdk.aws_lambda_python import PythonFunction


class CdkAppsyncLambdaStack(cdk.Stack):
    def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        lambda_ = PythonFunction(self, f"HogeLambda", entry="src", runtime=Runtime.PYTHON_3_9)

        api = appsync.GraphqlApi(
            self, "HogeApi", name="HogeApi", schema=appsync.Schema.from_asset("./schema/schema.graphql"),
        )

        lambda_datasource = api.add_lambda_data_source("HogeLambdaSource", lambda_)
        lambda_datasource.create_resolver(type_name="Query", field_name="getUsers")
        lambda_datasource.create_resolver(
            type_name="Mutation", field_name="addUser",
        )

名前解決的なことをするLambdaを1つ作って、それをデータソースとして登録。そこにgetUsersaddUserをマッピングします。

Lambdaを実装する

名前解決をしてデータをいい感じに処理するLambdaを実装します。

ただし、今回はLambdaはダミーデータを返すだけで、DBにアクセスはしません。

def getUsers(arguments):
    return [{"id": "hogehoge", "name": "ししぃ"}]  # ダミー

def addUser(arguments):
    return dict(**arguments)  # ダミー

def handler(event, context):
    return globals()[event["info"]["fieldName"]](event["arguments"])

ふるまいは

addUserが来た場合は、受け取ったパラメーターをそのまま返すだけ、

getUsersが来たら固定されたユーザーを返すだけ、です(笑)

デプロイ!

$ cdk deploy

動作確認

では動作確認です。

DBに何のアクセスもしないので、何が動作確認なのだ!という感じですが、一応動きを確認しときます!

まずAPIの情報を色々とってきます。

$ aws appsync list-graphql-apis --output table --query 'graphqlApis[?contains(name,`HogeApi`)]'

上記のコマンドを叩くと下記のようなテーブルが出力されます

GRAPHQLはエンドポイントのURLなのでGraphQL-Playgroundのリクエスト先に設定します。

次にapiIdから認証キーを取得します。

コマンドは下記

# ↓`hogehoge`のところに`apiId`を貼り付ける
$ aws appsync list-api-keys --api-id hogehoge --query 'apiKeys[*].id' --output text
> XXXXXXXXXXXXXXXXXXXXXXXXX

上記認証キーをコピーしてきて、GraphQL-PlaygroundHTTP HEADERSの項目に下記な感じで設定します。

{
  "x-api-key":"xxxxxxxxxxxxxxxxxxx"
}

これで準備完了

Queryの動作確認する

下記のようなクエリーを作って投げてみます

query {
  getUsers {
    id
    name
  }
}

# ↓ 結果 ↓ #

{
  "data": {
    "getUsers": [
      {
        "id": "hogehoge",
        "name": "ししぃ"
      }
    ]
  }
}

##################################

query {
  getUsers {
    name
  }
}

# ↓ 結果 ↓ #

{
  "data": {
    "getUsers": [
      {
        "name": "ししぃ"
      }
    ]
  }
}

Mutationの動作を確認する

下記のようなクエリーを作って投げてみます

mutation MyMutation {
  addUser(id: "fuga", name: "fuugaaa") {
    id
    name
  }
}

# ↓ 結果 ↓ #

{
  "data": {
    "addUser": {
      "id": "fuga",
      "name": "fuugaaa"
    }
  }
}

##################################

mutation MyMutation {
  addUser(id: "fuga") {
    name
  }
}

# ↓ 結果 ↓ #

{
  "data": {
    "addUser": {
      "name": null
    }
  }
}

##################################

mutation MyMutation {
  addUser(name: "fuga") {
    id
  }
}

# ↓ 結果 ↓ #

{
  "data": null,
  "errors": [
    {
      "path": null,
      "locations": [
        {
          "line": 2,
          "column": 3,
          "sourceName": null
        }
      ],
      "message": "Validation error of type MissingFieldArgument: Missing field argument id @ 'addUser'"
    }
  ]
}

いい感じ!

はい。lambdaで実装した通りの返答を受け取ることができました!

今回のリポジトリはこちら

https://github.com/sisi100/cdk-appsync-lambda/tree/2021/10%2F18

Author

Sisii

インフラが好きなエンジニアぶってるなにか