Étape 4 : Utilisation d'un AWS AppSync API avec AWS CDK - AWS AppSync

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Étape 4 : Utilisation d'un AWS AppSync API avec AWS CDK

Astuce

Avant de l'utiliserCDK, nous vous recommandons CDK de consulter la documentation officielle ainsi que AWS AppSync les CDKréférences.

Nous vous recommandons également de vous assurer que votre NPMinstallation AWS CLIet celle de votre système fonctionnent correctement.

Dans cette section, nous allons créer une CDK application simple capable d'ajouter et de récupérer des éléments à partir d'une table DynamoDB. Il s'agit d'un exemple de démarrage rapide utilisant une partie du code des sections Conception de votre schéma, Attachement d'une source de données et Configuration des résolveurs (JavaScript).

Configuration d'un CDK projet

Avertissement

Ces étapes peuvent ne pas être totalement précises en fonction de votre environnement. Nous supposons que les utilitaires nécessaires sont installés sur votre système, qu'il existe un moyen d'interfacer avec les AWS services et que les configurations appropriées sont en place.

La première étape consiste à installer le AWS CDK. Dans votreCLI, vous pouvez saisir la commande suivante :

npm install -g aws-cdk

Ensuite, vous devez créer un répertoire de projet, puis y accéder. Voici un exemple d'ensemble de commandes permettant de créer un répertoire et d'y accéder :

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

Ensuite, vous devez créer une application. Notre service utilise principalement TypeScript. Dans le répertoire de votre projet, entrez la commande suivante :

cdk init app --language typescript

Dans ce cas, une CDK application ainsi que ses fichiers d'initialisation seront installés :

Terminal output showing Git initialization messages. (AI generated)

La structure de votre projet peut ressembler à ceci :

Project directory structure with folders and files. (AI generated)

Vous remarquerez que nous avons plusieurs annuaires importants :

  • bin: Le fichier bin initial créera l'application. Nous n'en parlerons pas dans ce guide.

  • lib: Le répertoire lib contient vos fichiers de pile. Vous pouvez considérer les fichiers de pile comme des unités d'exécution individuelles. Les constructions se trouveront dans nos fichiers de pile. Il s'agit essentiellement de ressources pour un service qui sera intégré AWS CloudFormation lors du déploiement de l'application. C'est là que se déroulera la majeure partie de notre codage.

  • node_modules: Ce répertoire est créé par NPM et contient toutes les dépendances du package que vous avez installées à l'aide de la npm commande.

Notre fichier de pile initial peut contenir quelque chose comme ceci :

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) // }); } }

Il s'agit du code standard pour créer une pile dans notre application. Dans cet exemple, la majeure partie de notre code entrera dans le champ d'application de cette classe.

Pour vérifier que votre fichier de pile se trouve dans l'application, dans le répertoire de votre application, exécutez la commande suivante dans le terminal :

cdk ls

Une liste de vos piles devrait apparaître. Si ce n'est pas le cas, vous devrez peut-être recommencer les étapes ou consulter la documentation officielle pour obtenir de l'aide.

Si vous souhaitez créer vos modifications de code avant le déploiement, vous pouvez toujours exécuter la commande suivante dans le terminal :

npm run build

Et pour voir les modifications avant le déploiement :

cdk diff

Avant d'ajouter notre code au fichier de pile, nous allons effectuer un bootstrap. Le bootstrapping nous permet de fournir des ressources CDK avant le déploiement de l'application. Vous trouverez plus d'informations sur ce processus ici. Pour créer un bootstrap, la commande est la suivante :

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

Cette étape nécessite plusieurs IAM autorisations dans votre compte. Votre bootstrap sera refusé si vous ne les avez pas. Dans ce cas, vous devrez peut-être supprimer les ressources incomplètes causées par le bootstrap, telles que le compartiment S3 qu'il génère.

Bootstrap lancera plusieurs ressources. Le message final ressemblera à ceci :

Terminal output showing bootstrapping environment. (AI generated)

Cela se fait une fois par compte et par région, vous n'aurez donc pas à le faire souvent. Les principales ressources du bootstrap sont la AWS CloudFormation pile et le compartiment Amazon S3.

Le compartiment Amazon S3 est utilisé pour stocker les fichiers et les IAM rôles qui accordent les autorisations nécessaires pour effectuer des déploiements. Les ressources requises sont définies dans une AWS CloudFormation pile, appelée pile bootstrap, qui est généralement nomméeCDKToolkit. Comme toute AWS CloudFormation pile, elle apparaît dans la AWS CloudFormation console une fois déployée :

AWS CloudFormation stack list with CDKToolkit stack details. (AI generated)

Il en va de même pour le bucket :

AWS S3 bucket details showing name, region, access level, and creation date. (AI generated)

Pour importer les services dont nous avons besoin dans notre fichier de pile, nous pouvons utiliser la commande suivante :

npm install aws-cdk-lib # V2 command
Astuce

Si vous rencontrez des problèmes avec la V2, vous pouvez installer les bibliothèques individuelles à l'aide des commandes V1 :

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

Nous ne le recommandons pas car la V1 est obsolète.

Implémentation d'un CDK projet - Schéma

Nous pouvons maintenant commencer à implémenter notre code. Nous devons d'abord créer notre schéma. Vous pouvez simplement créer un .graphql fichier dans votre application :

mkdir schema touch schema.graphql

Dans notre exemple, nous avons inclus un répertoire de premier niveau appelé schema contenant : schema.graphql

Directory structure showing a schema.graphql file. (AI generated)

Dans notre schéma, incluons un exemple simple :

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

De retour dans notre fichier de pile, nous devons nous assurer que les directives d'importation suivantes sont définies :

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';

Dans la classe, nous allons ajouter du code pour créer notre GraphQL API et le connecter à notre schema.graphql fichier :

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'), }); } }

Nous ajouterons également du code pour imprimer le GraphQLURL, la API clé et la région :

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 }); } }

À ce stade, nous allons à nouveau utiliser Deploy notre application :

cdk deploy

Voici le résultat :

Terminal output showing a successful CloudFormation deployment. (AI generated)

Il semble que notre exemple soit réussi, mais vérifions la AWS AppSync console juste pour confirmer :

AWS AppSync console showing the api-to-process-posts GraphQL API. (AI generated)

Il semblerait que le nôtre API ait été créé. Nous allons maintenant vérifier le schéma joint au API :

Schema showing input type, Post type, Mutation type with createPost, and Query type with getPost. (AI generated)

Cela semble correspondre à notre code de schéma, donc c'est réussi. Une autre façon de le confirmer du point de vue des métadonnées consiste à examiner la AWS CloudFormation pile :

AWS CloudFormation stack showing CREATE_COMPLETE and UPDATE_COMPLETE statuses. (AI generated)

Lorsque nous déployons notre CDK application, elle fait appel AWS CloudFormation à des ressources telles que le bootstrap. Chaque pile de notre application correspond à une AWS CloudFormation pile 1:1. Si vous revenez au code de la pile, le nom de la pile a été extrait du nom de la classeExampleCdkAppStack. Vous pouvez voir les ressources qu'il a créées, qui correspondent également à nos conventions de dénomination dans notre structure GraphQL API :

AWS CloudFormation stack resources and naming conventions. (AI generated)

Mise en œuvre d'un CDK projet - Source de données

Ensuite, nous devons ajouter notre source de données. Notre exemple utilisera une table DynamoDB. Dans la classe stack, nous allons ajouter du code pour créer une nouvelle table :

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 }); } }

À ce stade, déployons à nouveau :

cdk deploy

Nous devrions vérifier la console DynamoDB pour trouver notre nouvelle table :

DynamoDB console showing the ExampleCdkAppStack-poststabledbtable. (AI generated)

Le nom de notre pile est correct et le nom de la table correspond à notre code. Si nous vérifions à nouveau notre AWS CloudFormation pile, nous verrons maintenant le nouveau tableau :

AWS CloudFormation stack resources including posts-apis, posts-table, and poststableCCB5A2E6. (AI generated)

Implémentation d'un CDK projet - Resolver

Cet exemple utilisera deux résolveurs : l'un pour interroger la table et l'autre pour y ajouter des éléments. Puisque nous utilisons des résolveurs de pipeline, nous devrons déclarer deux résolveurs de pipeline avec une fonction dans chacun. Dans la requête, nous allons ajouter le code suivant :

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 }); } }

Dans cet extrait, nous avons ajouté un résolveur de pipeline appelé auquel est func-add-post attachée pipeline-resolver-create-posts une fonction appelée. Il s'agit du code qui sera ajouté Posts au tableau. L'autre résolveur de pipeline a été appelé pipeline-resolver-get-posts avec une fonction appelée func-get-post qui récupère les éléments Posts ajoutés à la table.

Nous allons le déployer pour l'ajouter au AWS AppSync service :

cdk deploy

Examinons la AWS AppSync console pour voir s'ils étaient attachés à notre GraphQL API :

Diagram showing mutation and query resolvers for a GraphQL API. (AI generated)

Cela semble correct. Dans le code, ces deux résolveurs étaient attachés au API GraphQL que nous avons créé (indiqué par la valeur props présente à api la fois dans les résolveurs et dans les fonctions). Dans GraphQLAPI, les champs auxquels nous avons attaché nos résolveurs étaient également spécifiés dans les accessoires (définis par les fieldname accessoires typename et de chaque résolveur).

Voyons si le contenu des résolveurs est correct en commençant par : pipeline-resolver-get-posts

Code editor showing two resolver functions for request and response. (AI generated)

Les gestionnaires avant et après correspondent à la valeur de nos code accessoires. Nous pouvons également voir qu'une fonction est appeléeadd_posts_func_1, ce qui correspond au nom de la fonction que nous avons attachée dans le résolveur.

Regardons le contenu du code de cette fonction :

Code snippet showing a request function that returns an operation and key/attribute values. (AI generated)

Cela correspond aux code accessoires de la add_posts_func_1 fonction. Notre requête a été chargée avec succès, alors vérifions-la :

Code editor showing two exported functions for request and response. (AI generated)

Ils correspondent également au code. Si nous examinons get_posts_func_1 :

Code snippet showing two functions: request and response. (AI generated)

Tout semble être en place. Pour confirmer cela du point de vue des métadonnées, nous pouvons AWS CloudFormation réexaminer notre pile :

AWS CloudFormation stack with logical IDs for resources. (AI generated)

Maintenant, nous devons tester ce code en effectuant quelques requêtes.

Mise en œuvre d'un CDK projet - Demandes

Pour tester notre application dans la AWS AppSync console, nous avons effectué une requête et une mutation :

Code snippet showing a GraphQL query and mutation. (AI generated)

MyMutationcontient une createPost opération avec les arguments 1970-01-01T12:30:00.000Z etfirst post. Il renvoie le date et title que nous avons transmis ainsi que la id valeur générée automatiquement. L'exécution de la mutation donne le résultat suivant :

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

Si nous vérifions rapidement la table DynamoDB, nous pouvons voir notre entrée dans la table lorsque nous la scannons :

DynamoDB table with id, date, and title columns showing an entry. (AI generated)

De retour dans la AWS AppSync console, si nous exécutons la requête pour le récupérerPost, nous obtenons le résultat suivant :

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