Usare un AWS AppSync API con AWS CDK - AWS AppSync

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Usare un AWS AppSync API con AWS CDK

Suggerimento

Prima di utilizzare ilCDK, ti consigliamo CDK di consultare la documentazione ufficiale insieme AWS AppSync ai CDKriferimenti.

Ti consigliamo inoltre di assicurarti che AWS CLIle tue NPMinstallazioni funzionino correttamente sul tuo sistema.

In questa sezione, creeremo una semplice CDK applicazione in grado di aggiungere e recuperare elementi da una tabella DynamoDB. Questo vuole essere un esempio di avvio rapido che utilizza parte del codice delle sezioni Progettazione dello schema, Collegamento di una fonte di dati e Configurazione dei resolvers (). JavaScript

Configurazione di un progetto CDK

avvertimento

Questi passaggi potrebbero non essere completamente accurati a seconda dell'ambiente. Partiamo dal presupposto che sul sistema siano installate le utilità necessarie, un modo per interfacciarsi con AWS i servizi e configurazioni corrette.

Il primo passo è l'installazione di. AWS CDK Nel tuoCLI, puoi inserire il seguente comando:

npm install -g aws-cdk

Successivamente, è necessario creare una directory di progetto, quindi accedervi. Un esempio di set di comandi per creare e navigare in una directory è:

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

Successivamente, devi creare un'app. Il nostro servizio utilizza principalmente TypeScript. Nella directory del progetto, inserisci il seguente comando:

cdk init app --language typescript

Quando esegui questa operazione, verrà installata un'CDKapp con i relativi file di inizializzazione:

Terminal output showing Git repository initialization and npm install completion.

La struttura del tuo progetto potrebbe essere simile a questa:

Project directory structure showing folders and files for an example CDK app.

Noterai che abbiamo diverse directory importanti:

  • bin: Il file bin iniziale creerà l'app. Non lo tratteremo in questa guida.

  • lib: La directory lib contiene i tuoi file stack. Potete pensare ai file stack come a singole unità di esecuzione. I costrutti saranno all'interno dei nostri file stack. Fondamentalmente, si tratta di risorse per un servizio che verrà attivato AWS CloudFormation quando l'app verrà distribuita. È qui che avverrà la maggior parte della nostra codifica.

  • node_modules: Questa directory è creata NPM e contiene tutte le dipendenze dei pacchetti che sono state installate utilizzando il npm comando.

Il nostro file stack iniziale può contenere qualcosa del genere:

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

Questo è il codice standard per creare uno stack nella nostra app. La maggior parte del nostro codice in questo esempio rientrerà nell'ambito di questa classe.

Per verificare che il file stack si trovi nell'app, nella directory dell'app, esegui il seguente comando nel terminale:

cdk ls

Dovrebbe apparire un elenco dei tuoi stack. In caso contrario, potrebbe essere necessario ripetere i passaggi o consultare la documentazione ufficiale per ricevere assistenza.

Se desideri creare le modifiche al codice prima della distribuzione, puoi sempre eseguire il seguente comando nel terminale:

npm run build

Inoltre, per vedere le modifiche prima della distribuzione:

cdk diff

Prima di aggiungere il codice al file stack, eseguiremo un bootstrap. Il bootstrap ci consente di fornire le risorse necessarie CDK prima della distribuzione dell'app. Ulteriori informazioni su questo processo sono disponibili qui. Per creare un bootstrap, il comando è:

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

Questo passaggio richiede diverse IAM autorizzazioni nel tuo account. Il tuo bootstrap verrà negato se non li hai. In tal caso, potrebbe essere necessario eliminare le risorse incomplete causate dal bootstrap, ad esempio il bucket S3 che genera.

Bootstrap genererà diverse risorse. Il messaggio finale sarà simile al seguente:

Terminal output showing successful bootstrapping of an AWS environment.

Questa operazione viene eseguita una volta per account per regione, quindi non dovrai farlo spesso. Le risorse principali del bootstrap sono lo AWS CloudFormation stack e il bucket Amazon S3.

Il bucket Amazon S3 viene utilizzato per archiviare file e IAM ruoli che concedono le autorizzazioni necessarie per eseguire le distribuzioni. Le risorse richieste sono definite in uno AWS CloudFormation stack, chiamato stack bootstrap, che di solito viene denominato. CDKToolkit Come ogni AWS CloudFormation stack, appare nella AWS CloudFormation console una volta distribuito:

CDKToolkit stack with CREATE_COMPLETE status in AWS CloudFormation console.

Lo stesso si può dire per il bucket:

S3 bucket details showing name, region, access settings, and creation date.

Per importare i servizi di cui abbiamo bisogno nel nostro file stack, possiamo usare il seguente comando:

npm install aws-cdk-lib # V2 command
Suggerimento

Se hai problemi con la V2, puoi installare le singole librerie usando i comandi V1:

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

Non lo consigliamo perché la V1 è obsoleta.

Implementazione di un progetto - Schema CDK

Ora possiamo iniziare a implementare il nostro codice. Innanzitutto, dobbiamo creare il nostro schema. Puoi semplicemente creare un .graphql file nella tua app:

mkdir schema touch schema.graphql

Nel nostro esempio, abbiamo incluso una directory di primo livello chiamata schema contenente il nostroschema.graphql:

File structure showing a schema folder containing schema.graphql file.

All'interno del nostro schema, includiamo un semplice esempio:

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

Tornando al nostro file stack, dobbiamo assicurarci che siano definite le seguenti direttive di importazione:

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

All'interno della classe, aggiungeremo il codice per creare il nostro GraphQL API e collegarlo al nostro schema.graphql file:

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

Aggiungeremo anche del codice per stampare GraphQLURL, la API chiave e la regione:

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

A questo punto, utilizzeremo nuovamente la distribuzione della nostra app:

cdk deploy

Questo è il risultato:

Deployment output showing ExampleCdkAppStack details, including GraphQL API URL and stack region.

Sembra che il nostro esempio abbia avuto successo, ma controlliamo la AWS AppSync console solo per confermare:

GraphQL interface showing successful API request with response data displayed.

Sembra che il nostro API sia stato creato. Ora controlleremo lo schema allegato aAPI:

GraphQL schema defining CreatePostInput, Post type, Mutation, and Query operations.

Questo sembra corrispondere al nostro codice dello schema, quindi ha avuto successo. Un altro modo per confermarlo dal punto di vista dei metadati è guardare lo AWS CloudFormation stack:

AWS CloudFormation stack showing ExampleCdkAppStack update complete and CDKToolkit creation complete.

Quando distribuiamo la nostra CDK app, questa attiva risorse AWS CloudFormation come il bootstrap. Ogni stack all'interno della nostra app viene mappato 1:1 con uno stack. AWS CloudFormation Se torni al codice dello stack, il nome dello stack è stato preso dal nome della classe. ExampleCdkAppStack Puoi vedere le risorse che ha creato, che corrispondono anche alle nostre convenzioni di denominazione, nel nostro costrutto GraphQL: API

Expanded view of post-apis resource showing Schema, DefaultApiKey, and CDKMetadata.

Implementazione di un CDK progetto - Fonte dei dati

Successivamente, dobbiamo aggiungere la nostra fonte di dati. Il nostro esempio utilizzerà una tabella DynamoDB. All'interno della classe stack, aggiungeremo del codice per creare una nuova tabella:

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

A questo punto, eseguiamo nuovamente l'implementazione:

cdk deploy

Dovremmo controllare la console DynamoDB per la nostra nuova tabella:

DynamoDB console showing ExampleCdkAppStack-poststable as Active with Provisioned capacity.

Il nome del nostro stack è corretto e il nome della tabella corrisponde al nostro codice. Se controlliamo nuovamente il nostro AWS CloudFormation stack, ora vedremo la nuova tabella:

Expanded view of a logical ID in AWS CloudFormation showing post-apis, posts-table, and CDKMetadata.

Implementazione di un CDK progetto - Resolver

Questo esempio utilizzerà due resolver: uno per interrogare la tabella e uno per aggiungervi. Poiché utilizziamo resolver di pipeline, dovremo dichiarare due resolver di pipeline con una funzione ciascuno. Nella query, aggiungeremo il seguente codice:

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 questo frammento, abbiamo aggiunto un risolutore di pipeline chiamato pipeline-resolver-create-posts con una funzione chiamata attached. func-add-post Questo è il codice che verrà aggiunto alla tabella. Posts L'altro risolutore di pipeline è stato chiamato pipeline-resolver-get-posts con una funzione chiamata func-get-post che recupera i dati Posts aggiunti alla tabella.

Lo implementeremo per aggiungerlo al servizio: AWS AppSync

cdk deploy

Controlliamo la AWS AppSync console per vedere se erano collegate al nostro GraphQLAPI:

GraphQL API schema showing mutation and query fields with Pipeline resolvers.

Sembra essere corretto. Nel codice, entrambi questi resolver erano collegati al GraphQL che API abbiamo creato (indicato dal valore api props presente sia nei resolver che nelle funzioni). In GraphQLAPI, i campi a cui abbiamo collegato i nostri resolver sono stati specificati anche negli oggetti di scena (definiti da typename e fieldname props in ogni resolver).

Vediamo se il contenuto dei resolver è corretto a partire da: pipeline-resolver-get-posts

Code snippet showing request and response functions in a resolver, with an arrow pointing to them.

I gestori prima e dopo corrispondono al nostro valore props. code Possiamo anche vedere una funzione chiamataadd_posts_func_1, che corrisponde al nome della funzione che abbiamo inserito nel resolver.

Diamo un'occhiata al contenuto del codice di quella funzione:

Function code showing request and response methods for a PutItem operation.

Questo corrisponde agli code oggetti di scena della add_posts_func_1 funzione. La nostra query è stata caricata correttamente, quindi controlliamo la query:

Resolver code with request and response functions, and a get_posts_func_1 function listed below.

Anche questi corrispondono al codice. Se osserviamoget_posts_func_1:

Code snippet showing two exported functions: request returning 'Scan' operation and response returning items.

Sembra che tutto sia a posto. Per confermarlo dal punto di vista dei metadati, possiamo ricontrollare il nostro stack: AWS CloudFormation

List of logical IDs for AWS resources including API, table, functions, and pipelines.

Ora, dobbiamo testare questo codice eseguendo alcune richieste.

Implementazione di un CDK progetto - Richieste

Per testare la nostra app nella AWS AppSync console, abbiamo effettuato una query e una mutazione:

GraphQL code snippet showing a query to get post details and a mutation to create a post.

MyMutationcontiene un'createPostoperazione con gli argomenti 1970-01-01T12:30:00.000Z efirst post. Restituisce l'dateand title che abbiamo passato e il id valore generato automaticamente. L'esecuzione della mutazione produce il risultato:

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

Se controlliamo rapidamente la tabella DynamoDB, possiamo vedere la nostra voce nella tabella quando la scansioniamo:

DynamoDB table entry showing id, date, and title fields for a single item.

Tornando alla AWS AppSync console, se eseguiamo la query per recuperarloPost, otteniamo il seguente risultato:

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