AWS Appsync Pipeline-Resolver mit Terraform
AWS AppSync bietet Softwareentwicklern eine robuste, skalierbare GraphQL-Oberfläche, mit der sie Daten aus mehreren Quellen kombinieren können, einschließlich Amazon DynamoDB, AWS Lambda und HTTP REST APIs.
AWS AppSync enthält eine Vielzahl von Funktionen, um das Erstellen von GraphQL zu einer optimierten Erfahrung zu machen:
- Leistungsstarke Bearbeitung von GraphQL-Schemas über die AWS AppSync-Konsole, einschließlich der automatischen Generierung von GraphQL-Schemas aus DynamoDB
- Optimiertes Daten-Caching
- Integration in Amazon Cognito-Benutzerpools für eine differenzierte Zugriffskontrolle auf Feldebene
Weitere Informationen zu AWS AppSync finden Sie hier.
Mit einem Pipeline-Resolver können Entwickler Operationen zusammenstellen (sog. Funktionen) und nacheinander ausführen. In der Vergangenheit war das nur durch die Implementierung einer Lambda-Funktion als Resolver möglich, was für viele Fälle kein idealer Workflow war.
Überblick
In diesem Blog erfahren Sie, wie Sie einen Pipeline Resolver erstellen, der Daten entschlüsselt, nachdem sie aus einer Dynamo Datenbank abgerufen wurden.
Um diese Abfrage durchzuführen, zeigen wir die folgenden Schritte:
- Definieren Sie ein Schema für die Query. Benutzer fordert Daten an. Der Resolver leitet die Abfrage an die erste Pipeline-Funktion weiter.
- Die erste Pipeline-Funktion ruft Daten aus DynamoDB ab und übergibt die Ergebnisse der DB-Abfrage an die nächste Pipeline-Funktion.
- In der zweiten Pipeline-Funktion, rufen wir die Lambda-Funktion auf, bei der die Daten entschlüsselt und im gleichen Format zurückgegeben werden.
- In der Antwort geben wir die entschlüsselte Liste der Bestellungen zurück.
Anfangen
Um diese Abfrage durchzuführen, definieren wir 2 Pipeline-Funktionen und 1 Datenquelle mithilfe von Terraform. Das Schema für die Query schreiben wir im GraphQL-Format.
Schema für "listOrders" Query erstellen
Zuerst erstellen wir die Ressourcen, die wir für unsere Query benötigen:
schema.gql
type OrdersList {
items: [OrderData]
nextToken: String
}
type OrderData {
applicant: Applicant
id: String
products: String
request_date: String
user_id: String
}
type Applicant {
title: String,
last_name: String,
first_name: String,
address: Address,
phone_number: String,
email: String,
}
type Address {
country: String,
city: String,
street: String,
street_number: String,
zip: String
}
Als Nächstes erstellen wir die Query “listOrders”, um die Argumente limit
und nextToken
zu erwarten. limit
ist die maximale Anzahl der auszuwertenden Elemente (nicht notwendigerweise die Anzahl der übereinstimmenden Elemente). Dies ist ein optionales Feld. nextToken
ist das Paginierungs-Token für die Fortsetzung einer früheren Abfrage. Dieses wäre von einer vorherigen Abfrage erhalten worden. Dies ist ein optionales Feld.
schema.gql
type Query {
listOrders(limit: Int, nextToken: String): OrdersList
}
schema {
query: Query
}
Datasource definieren
Mit der DataSource-Ressource werden Datenquellen erstellt, mit denen sich Resolver in AWS AppSync verbinden können, z. B. in unserem Fall Amazon DynamoDB und AWS Lambda. Resolver verwenden diese Datenquellen, um Daten abzurufen, wenn Clients GraphQL-Aufrufe senden.
Im ersten Schritt definieren wir DynamoDB, aus der wir Bestelldaten entnehmen.
appsync_datasources.tf
resource "aws_appsync_datasource" "ds_app_name_orders_projection" {
count = length(var.stages)
api_id = aws_appsync_graphql_api.app_name_api[count.index].id
name = "ds_app_namee_orders_projection_${element(var.stages, count.index)}"
service_role_arn = aws_iam_role.app_name_api_role.arn
type = "AMAZON_DYNAMODB"
dynamodb_config {
table_name = "OrdersProjection-${element(var.stages, count.index)}"
}
}
Im zweiten Schritt definieren wir die DataSource für Lambda, die die angegebene Projektion basierend auf dem JSON-Schema entschlüsselt.
appsync_datasources.tf
resource "aws_appsync_datasource" "ds_app_name_validate_projection" {
count = length(var.stages)
api_id = aws_appsync_graphql_api.app_name_api[count.index].id
name = "ds_app_name_validate_projection"
service_role_arn = aws_iam_role.app_name_api_role.arn
type = "AWS_LAMBDA"
lambda_config {
function_arn = local.validate_projection_aliases[element(var.stages, count.index)]
}
}
api_id
- (Erforderlich) Die API-ID für die GraphQL-API für die DataSource.
name
- (Erforderlich) Ein vom Benutzer angegebener Name für die DataSource.
service_role_arn
- (Optional) Die IAM-Servicerolle ARN für die Datenquelle.
type
- (Erforderlich) Der Typ der DataSource. Gültige Werte: AWS_LAMBDA, AMAZON_DYNAMODB, AMAZON_ELASTICSEARCH, HTTP, NONE
table_name
- (Erforderlich) Name der DynamoDB-Tabelle.
function_arn
- (Erforderlich) Die ARN für die Lambda-Funktion.
Pipeline resolver schreiben
Ein Pipeline-Resolver besteht aus Before mapping template, After mapping template und einer Liste von Funktionen. Jede Funktion verfügt über request und response mapping template, die sie für eine Datenquelle ausführt. Da ein Pipeline-Resolver die Ausführung an eine Liste von Funktionen delegiert, ist er daher nicht mit einer Datenquelle verknüpft.
appsync_resolvers.tf
resource "aws_appsync_resolver" "list_orders_resolver" {
count = length(var.stages)
api_id = aws_appsync_graphql_api.app_name_api[count.index].id
field = "listOrders"
type = "Query"
request_template = "{}"
response_template = "$util.toJson($ctx.result)"
kind = "PIPELINE"
pipeline_config {
functions = [
aws_appsync_function.fn_get_list_orders[count.index].function_id,
aws_appsync_function.fn_validate_projection[count.index].function_id
]
}
}
api_id
- (Erforderlich) Die API-ID für die GraphQL-API für die DataSource.
field
- (Erforderlich) Der Feldname aus dem in der GraphQL-API definierten Schema.
type
- (Erforderlich) Der Typname aus dem in der GraphQL-API definierten Schema.
request_template
- (Required) 'before mapping template'
response_template
- (Required) 'after mapping template'
kind
- (Optional) Der Resolvertyp. Gültige Werte sind UNIT und PIPELINE.
pipeline_config
- (Optional) Die PipelineConfig.
functions
- (Erforderlich) Die Liste der Funktions-ID.
Unser Resolver verwendet zwei Funktionen, von denen die erste verschlüsselte Daten von DynamoDB holt. Die zweite ruft die Lambda-Funktion auf, die die angegebenen Daten entschlüsselt. Im nächsten Schritt werden wir jede Funktion einzeln beschreiben.
Funktionen erstellen
Mit der Operation Scan erhalten wir alle Bestellungen aus der DynamoDB-Tabelle. Wir ordnen die Response dann so zu, wie wir sie an die nächste Funktion übergeben möchten. Zu diesem Zeitpunkt werden die Daten verschlüsselt und die nächste Funktion kümmert sich um die Entschlüsselung.