Blog

dranbleiben!

technology
Lorna Loncar

AWS Appsync Pipeline-Resolver mit Terraform

AWS AppSync bietet Anwendungsentwicklern 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:

  1. Definieren Sie ein Schema für die Query. Benutzer fordert Daten an. Der Resolver leitet die Abfrage an die erste Pipeline-Funktion weiter.
  2. Die erste Pipeline-Funktion ruft Daten aus DynamoDB ab und übergibt die Ergebnisse der DB-Abfrage an die nächste Pipeline-Funktion.
  3. In der zweiten Pipeline-Funktion, rufen wir die Lambda-Funktion auf, bei der die Daten entschlüsselt und im gleichen Format zurückgegeben werden.
  4. 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.

none
Conventic Icon

Standort Bonn

Burgstraße 69
53177 Bonn
Deutschland
+49 228 76 37 69 70
hello@conventic.com

Standort Braunschweig

Westbahnhof 11
38118 Braunschweig
Deutschland
+49 228 76 37 69 70
hello@conventic.com

Wir sind Mitglied bei

Grouplink Icon
Software Allianze Icon
Hubwerk Icon

Newsletter abonnieren

Twitter Icon
Facebook Icon
Instagram Icon
Xing Icon
LinkedIn Icon
Impressum, Haftungsausschluss und Datenschutzerklärung
© 2021 conventic GmbH · Alle Rechte vorbehalten.