Schritt 4: Eine API verwenden: CDK-Beispiel - AWS AppSync

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Schritt 4: Eine API verwenden: CDK-Beispiel

Tipp

Bevor Sie das CDK verwenden, empfehlen wir, die CDKs zu lesenoffizielle Dokumentationzusammen mitAWS AppSyncistCDK-Referenz.

Wir empfehlen außerdem sicherzustellen, dass IhreAWSCLIundNPMInstallationen funktionieren auf Ihrem System.

In diesem Abschnitt werden wir eine einfache CDK-App erstellen, die Elemente aus einer DynamoDB-Tabelle hinzufügen und aus ihr abrufen kann. Dies soll ein Schnellstartbeispiel sein, das einen Teil des Codes aus demEntwerfen Sie Ihr Schema,Eine Datenquelle anhängen, undResolver konfigurieren (JavaScript)Abschnitte.

Einrichtung eines CDK-Projekts

Warnung

Diese Schritte sind je nach Umgebung möglicherweise nicht ganz korrekt. Wir gehen davon aus, dass auf Ihrem System die erforderlichen Dienstprogramme installiert sind, eine Möglichkeit, mitAWSDienste und die richtigen Konfigurationen sind vorhanden.

Der erste Schritt ist die Installation vonAWSCDK. In Ihrer CLI können Sie den folgenden Befehl eingeben:

npm install -g aws-cdk

Als Nächstes müssen Sie ein Projektverzeichnis erstellen und dann dorthin navigieren. Ein Beispiel für einen Befehlssatz zum Erstellen und Navigieren zu einem Verzeichnis ist:

mkdir example-cdk-app cd example-cdk-app

Als Nächstes müssen Sie eine App erstellen. Unser Service verwendet hauptsächlichTypeScript. Geben Sie in Ihrem Projektverzeichnis den folgenden Befehl ein:

cdk init app --language typescript

Wenn Sie dies tun, wird eine CDK-App zusammen mit ihren Initialisierungsdateien installiert:

Ihre Projektstruktur könnte so aussehen:

Sie werden feststellen, dass wir mehrere wichtige Verzeichnisse haben:

  • bin: Die erste BIN-Datei erstellt die App. Wir werden das in diesem Handbuch nicht behandeln.

  • lib: Das Verzeichnis lib enthält Ihre Stack-Dateien. Sie können sich Stack-Dateien als einzelne Ausführungseinheiten vorstellen. Konstrukte werden in unseren Stack-Dateien enthalten sein. Im Grunde genommen handelt es sich dabei um Ressourcen für einen Dienst, der inAWS CloudFormationwenn die App bereitgestellt wird. Hier wird der Großteil unserer Codierung stattfinden.

  • node_modules: Dieses Verzeichnis wurde von NPM erstellt und enthält alle Paketabhängigkeiten, die Sie mit dem installiert habennpmBefehl.

Unsere anfängliche Stack-Datei könnte etwa Folgendes enthalten:

import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; // import * as sqs from 'aws-cdk-lib/aws-sqs'; export class ExampleCdkAppStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // The code that defines your stack goes here // example resource // const queue = new sqs.Queue(this, 'ExampleCdkAppQueue', { // visibilityTimeout: cdk.Duration.seconds(300) // }); } }

Dies ist der Boilerplate-Code zum Erstellen eines Stacks in unserer App. Der größte Teil unseres Codes in diesem Beispiel wird in den Geltungsbereich dieser Klasse fallen.

Um zu überprüfen, ob sich Ihre Stack-Datei in der App im Verzeichnis Ihrer App befindet, führen Sie den folgenden Befehl im Terminal aus:

cdk ls

Eine Liste deiner Stacks sollte erscheinen. Ist dies nicht der Fall, musst du die Schritte möglicherweise erneut ausführen oder in der offiziellen Dokumentation nach Hilfe suchen.

Wenn Sie Ihre Codeänderungen vor der Bereitstellung erstellen möchten, können Sie jederzeit den folgenden Befehl im Terminal ausführen:

npm run build

Und um die Änderungen vor der Bereitstellung zu sehen:

cdk diff

Bevor wir unseren Code zur Stack-Datei hinzufügen, führen wir einen Bootstrap durch. Bootstrapping ermöglicht es uns, Ressourcen für das CDK bereitzustellen, bevor die App bereitgestellt wird. Weitere Informationen zu diesem Prozess finden Siehier. Um einen Bootstrap zu erstellen, lautet der Befehl:

cdk bootstrap aws://ACCOUNT-NUMBER/REGION
Tipp

Für diesen Schritt sind mehrere IAM-Berechtigungen in Ihrem Konto erforderlich. Ihr Bootstrap wird verweigert, wenn Sie sie nicht haben. In diesem Fall müssen Sie möglicherweise unvollständige Ressourcen löschen, die durch den Bootstrap verursacht wurden, z. B. den von ihm generierten S3-Bucket.

Bootstrap wird mehrere Ressourcen hochfahren. Die endgültige Nachricht wird so aussehen:

Dies erfolgt einmal pro Konto pro Region, sodass Sie dies nicht oft tun müssen. Die Hauptressourcen des Bootstrap sindAWS CloudFormationStack und der Amazon S3-Bucket.

Der Amazon S3-Bucket wird zum Speichern von Dateien und IAM-Rollen verwendet, die die für die Durchführung von Bereitstellungen erforderlichen Berechtigungen gewähren. Die erforderlichen Ressourcen sind in einem definiertAWS CloudFormationStack, der so genannte Bootstrap-Stack, der normalerweise so genannt wirdCDKToolkit. Wie jederAWS CloudFormationStapel, es erscheint imAWS CloudFormationKonsole, sobald sie bereitgestellt wurde:

Das Gleiche gilt für den Bucket:

Um die Dienste, die wir benötigen, in unsere Stack-Datei zu importieren, können wir den folgenden Befehl verwenden:

npm install aws-cdk-lib # V2 command
Tipp

Wenn Sie Probleme mit V2 haben, können Sie die einzelnen Bibliotheken mit V1-Befehlen installieren:

npm install @aws-cdk/aws-appsync @aws-cdk/aws-dynamodb

Wir empfehlen dies nicht, da V1 veraltet ist.

Implementierung eines CDK-Projekts — Schema

Wir können jetzt mit der Implementierung unseres Codes beginnen. Zuerst müssen wir unser Schema erstellen. Sie können einfach eine erstellen.graphqlDatei in deiner App:

mkdir schema touch schema.graphql

In unserem Beispiel haben wir ein Verzeichnis auf oberster Ebene mit dem Namen hinzugefügtschemadas unsere enthältschema.graphql:

Lassen Sie uns in unser Schema ein einfaches Beispiel aufnehmen:

input CreatePostInput { title: String content: String } type Post { id: ID! title: String content: String } type Mutation { createPost(input: CreatePostInput!): Post } type Query { getPost: [Post] }

Zurück in unserer Stack-Datei müssen wir sicherstellen, dass die folgenden Importdirektiven definiert sind:

import * as cdk from 'aws-cdk-lib'; import * as appsync from 'aws-cdk-lib/aws-appsync'; import * as dynamodb from 'aws-cdk-lib/aws-dynamodb'; import { Construct } from 'constructs';

Innerhalb der Klasse fügen wir Code hinzu, um unsere GraphQL-API zu erstellen und sie mit unserer zu verbindenschema.graphqldatei:

export class ExampleCdkAppStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // makes a GraphQL API const api = new appsync.GraphqlApi(this, 'post-apis', { name: 'api-to-process-posts', schema: appsync.SchemaFile.fromAsset('schema/schema.graphql'), }); } }

Wir werden auch etwas Code hinzufügen, um die GraphQL-URL, den API-Schlüssel und die Region auszudrucken:

export class ExampleCdkAppStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // Makes a GraphQL API construct const api = new appsync.GraphqlApi(this, 'post-apis', { name: 'api-to-process-posts', schema: appsync.SchemaFile.fromAsset('schema/schema.graphql'), }); // Prints out URL new cdk.CfnOutput(this, "GraphQLAPIURL", { value: api.graphqlUrl }); // Prints out the AppSync GraphQL API key to the terminal new cdk.CfnOutput(this, "GraphQLAPIKey", { value: api.apiKey || '' }); // Prints out the stack region to the terminal new cdk.CfnOutput(this, "Stack Region", { value: this.region }); } }

An dieser Stelle werden wir unsere App erneut bereitstellen verwenden:

cdk deploy

Das ist das Ergebnis:

Es scheint, dass unser Beispiel erfolgreich war, aber lassen Sie uns das überprüfenAWS AppSyncKonsole nur zur Bestätigung:

Es scheint, dass unsere API erstellt wurde. Jetzt überprüfen wir das an die API angehängte Schema:

Dies scheint mit unserem Schemacode übereinzustimmen, es war also erfolgreich. Eine andere Möglichkeit, dies aus Sicht der Metadaten zu bestätigen, ist der Blick aufAWS CloudFormationStapel:

Wenn wir unsere CDK-App bereitstellen, geht sie durchAWS CloudFormationum Ressourcen wie den Bootstrap hochzufahren. Jeder Stapel in unserer App wird 1:1 zugeordnet mit einemAWS CloudFormationStapel. Wenn Sie zum Stack-Code zurückkehren, wurde der Stack-Name aus dem Klassennamen übernommenExampleCdkAppStack. Sie können die erstellten Ressourcen, die auch unseren Namenskonventionen entsprechen, in unserem GraphQL-API-Konstrukt sehen:

Implementierung eines CDK-Projekts — Datenquelle

Als Nächstes müssen wir unsere Datenquelle hinzufügen. In unserem Beispiel wird eine DynamoDB-Tabelle verwendet. Innerhalb der Stack-Klasse fügen wir etwas Code hinzu, um eine neue Tabelle zu erstellen:

export class ExampleCdkAppStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // Makes a GraphQL API construct const api = new appsync.GraphqlApi(this, 'post-apis', { name: 'api-to-process-posts', schema: appsync.SchemaFile.fromAsset('schema/schema.graphql'), }); //creates a DDB table const add_ddb_table = new dynamodb.Table(this, 'posts-table', { partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING, }, }); // Prints out URL new cdk.CfnOutput(this, "GraphQLAPIURL", { value: api.graphqlUrl }); // Prints out the AppSync GraphQL API key to the terminal new cdk.CfnOutput(this, "GraphQLAPIKey", { value: api.apiKey || '' }); // Prints out the stack region to the terminal new cdk.CfnOutput(this, "Stack Region", { value: this.region }); } }

Lassen Sie uns an dieser Stelle erneut bereitstellen:

cdk deploy

Wir sollten in der DynamoDB-Konsole nach unserer neuen Tabelle suchen:

Unser Stack-Name ist korrekt und der Tabellenname entspricht unserem Code. Wenn wir unsere überprüfenAWS CloudFormationNochmals stapeln, wir sehen jetzt die neue Tabelle:

Implementierung eines CDK-Projekts - Resolver

In diesem Beispiel werden zwei Resolver verwendet: einer zum Abfragen der Tabelle und einer zum Hinzufügen. Da wir Pipeline-Resolver verwenden, müssen wir zwei Pipeline-Resolver mit jeweils einer Funktion deklarieren. In der Abfrage fügen wir den folgenden Code hinzu:

export class ExampleCdkAppStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // Makes a GraphQL API construct const api = new appsync.GraphqlApi(this, 'post-apis', { name: 'api-to-process-posts', schema: appsync.SchemaFile.fromAsset('schema/schema.graphql'), }); //creates a DDB table const add_ddb_table = new dynamodb.Table(this, 'posts-table', { partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING, }, }); // Creates a function for query const add_func = new appsync.AppsyncFunction(this, 'func-get-post', { name: 'get_posts_func_1', api, dataSource: api.addDynamoDbDataSource('table-for-posts', add_ddb_table), code: appsync.Code.fromInline(` export function request(ctx) { return { operation: 'Scan' }; } export function response(ctx) { return ctx.result.items; } `), runtime: appsync.FunctionRuntime.JS_1_0_0, }); // Creates a function for mutation const add_func_2 = new appsync.AppsyncFunction(this, 'func-add-post', { name: 'add_posts_func_1', api, dataSource: api.addDynamoDbDataSource('table-for-posts-2', add_ddb_table), code: appsync.Code.fromInline(` export function request(ctx) { return { operation: 'PutItem', key: util.dynamodb.toMapValues({id: util.autoId()}), attributeValues: util.dynamodb.toMapValues(ctx.args.input), }; } export function response(ctx) { return ctx.result; } `), runtime: appsync.FunctionRuntime.JS_1_0_0, }); // Adds a pipeline resolver with the get function new appsync.Resolver(this, 'pipeline-resolver-get-posts', { api, typeName: 'Query', fieldName: 'getPost', code: appsync.Code.fromInline(` export function request(ctx) { return {}; } export function response(ctx) { return ctx.prev.result; } `), runtime: appsync.FunctionRuntime.JS_1_0_0, pipelineConfig: [add_func], }); // Adds a pipeline resolver with the create function new appsync.Resolver(this, 'pipeline-resolver-create-posts', { api, typeName: 'Mutation', fieldName: 'createPost', code: appsync.Code.fromInline(` export function request(ctx) { return {}; } export function response(ctx) { return ctx.prev.result; } `), runtime: appsync.FunctionRuntime.JS_1_0_0, pipelineConfig: [add_func_2], }); // Prints out URL new cdk.CfnOutput(this, "GraphQLAPIURL", { value: api.graphqlUrl }); // Prints out the AppSync GraphQL API key to the terminal new cdk.CfnOutput(this, "GraphQLAPIKey", { value: api.apiKey || '' }); // Prints out the stack region to the terminal new cdk.CfnOutput(this, "Stack Region", { value: this.region }); } }

In diesem Snippet haben wir einen Pipeline-Resolver namens hinzugefügtpipeline-resolver-create-postsmit einer Funktion namensfunc-add-postdaran befestigt. Dies ist der Code, der hinzugefügt wirdPostszum Tisch. Der andere Pipeline-Resolver wurde aufgerufenpipeline-resolver-get-postsmit einer Funktion namensfunc-get-postdas ruft abPostszur Tabelle hinzugefügt.

Wir werden das bereitstellen, um es zurAWS AppSyncDienst:

cdk deploy

Schauen wir uns das anAWS AppSyncKonsole, um zu sehen, ob sie an unsere GraphQL-API angehängt waren:

Es scheint richtig zu sein. Im Code waren diese beiden Resolver an die von uns erstellte GraphQL-API angehängt (bezeichnet mitapiDer Wert von Requisiten ist sowohl in den Resolvern als auch in den Funktionen vorhanden). In der GraphQL-API wurden die Felder, an die wir unsere Resolver angehängt haben, auch in den Requisiten angegeben (definiert durchtypenameundfieldnameRequisiten in jedem Resolver).

Mal sehen, ob der Inhalt der Resolver korrekt ist, beginnend mitpipeline-resolver-get-posts:

Die Vorher- und Nachher-Handler stimmen mit unseren übereincodeWert der Requisiten. Wir können auch sehen, dass eine Funktion aufgerufen wirdadd_posts_func_1, was dem Namen der Funktion entspricht, die wir an den Resolver angehängt haben.

Schauen wir uns den Codeinhalt dieser Funktion an:

Das stimmt mit dem übereincodeRequisiten deradd_posts_func_1Funktion. Unsere Anfrage wurde erfolgreich hochgeladen, also schauen wir uns die Anfrage an:

Diese stimmen auch mit dem Code überein. Wenn wir uns ansehenget_posts_func_1:

Alles scheint an seinem Platz zu sein. Um dies aus Sicht der Metadaten zu bestätigen, können wir unseren Stack eincheckenAWS CloudFormationnochmal:

Jetzt müssen wir diesen Code testen, indem wir einige Anfragen ausführen.

Implementierung eines CDK-Projekts — Anfragen

Um unsere App zu testen in derAWS AppSyncIn der Konsole haben wir eine Abfrage und eine Mutation gemacht:

MyMutationenthält eincreatePostOperation mit den Argumenten1970-01-01T12:30:00.000Zundfirst post. Es gibt die zurückdateundtitledie wir übergeben haben, sowie die automatisch generiertenidWert. Das Ausführen der Mutation ergibt das Ergebnis:

{ "data": { "createPost": { "date": "1970-01-01T12:30:00.000Z", "id": "4dc1c2dd-0aa3-4055-9eca-7c140062ada2", "title": "first post" } } }

Wenn wir die DynamoDB-Tabelle schnell überprüfen, können wir unseren Eintrag in der Tabelle sehen, wenn wir sie scannen:

Zurück in derAWS AppSyncKonsole, wenn wir die Abfrage ausführen, um das abzurufenPost, wir erhalten das folgende Ergebnis:

{ "data": { "getPost": [ { "id": "9f62c4dd-49d5-48d5-b835-143284c72fe0", "date": "1970-01-01T12:30:00.000Z", "title": "first post" } ] } }