View a markdown version of this page

Utilizzo di un' AWS AppSync API con AWS CDK - AWS AppSync GraphQL

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à.

Utilizzo di un' AWS AppSync API con AWS CDK

Suggerimento

Prima di utilizzare il CDK, ti consigliamo di consultare la documentazione ufficiale del CDK insieme AWS AppSync al riferimento CDK.

Ti consigliamo inoltre di assicurarti che le installazioni AWS CLI e NPM funzionino sul tuo sistema.

In questa sezione, creeremo una semplice applicazione CDK 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 del CDK. AWS Nella tua CLI, 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, è necessario 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'app CDK con i relativi file di inizializzazione:

Output del terminale che mostra l'inizializzazione del repository Git con suggerimenti per la denominazione dei rami principali.

La struttura del tuo progetto potrebbe essere simile a questa:

Albero dei file che mostra il example-cdk-app progetto con bin, lib, node_modules, cartelle di test e file di configurazione.

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 CloudFormation quando l'app verrà distribuita. È qui che avverrà la maggior parte della nostra codifica.

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

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 nostro codice al file stack, eseguiremo un bootstrap. Il bootstrap ci consente di fornire risorse per il 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 autorizzazioni IAM 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:

Uscita del terminale che mostra il messaggio di avvio di Environment dopo la creazione del CloudFormation changeset.

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

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

CloudFormation console che mostra lo CDKToolkit stack con lo stato CREATE_COMPLETE.

Lo stesso si può dire per il bucket:

Riga del bucket S3 che mostra il nome, la regione dell'Oregon occidentale degli Stati Uniti, l'accesso privato e la data di creazione.

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 CDK - Schema

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:

Albero dei file che mostra la cartella dello schema espansa con il file schema.graphql evidenziato.

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 la nostra API GraphQL e collegarla 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 l'URL GraphQL, la chiave API 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:

CDK output di distribuzione che mostra la chiave API GraphQL, l'URL, la regione dello stack e i dettagli ARN.

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

Navigazione della console api-to-process-posts mostrata e API_KEY visualizzata con l'opzione GraphQL.

Sembra che la nostra API sia stata creata. Ora controlleremo lo schema allegato all'API:

Schema GraphQL che mostra le definizioni del tipo di post CreatePostInput, della mutazione e della query.

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

CloudFormation elenco degli stack visualizzato ExampleCdkAppStack con lo stato UPDATE_COMPLETE e con lo stato CREATE_COMPLETE. CDKToolkit

Quando distribuiamo la nostra app CDK, questa attiva risorse come il bootstrap. CloudFormation Ogni stack all'interno della nostra app viene mappato 1:1 con uno stack. 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 API GraphQL:

Vista ad albero compressa che mostra le post-api con Schema e e gli elementi. DefaultApiKey CDKMetadata

Implementazione di un progetto CDK - 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 riga della tabella che mostra ExampleCdkAppStack -postable con stato attivo e classe Standard.

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

Gerarchia di ID logici che mostra post-apis, posts-table, postStableC6B5A2E6 e. CDKMetadata

Implementazione di un progetto CDK - 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 alla nostra API GraphQL:

Campi Mutation e Query che mostrano i resolver CreatePost e GetPost collegati a Pipeline.

Sembra essere corretto. Nel codice, entrambi questi resolver erano collegati all'API GraphQL che abbiamo creato (indicata dal valore api props presente sia nei resolver che nelle funzioni). Nell'API GraphQL, i campi a cui abbiamo collegato i nostri resolver sono stati specificati anche nelle proprietà (definite da typename e fieldname props in ogni resolver).

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

Codice del resolver che mostra le funzioni di richiesta e risposta con la freccia che punta alla funzione di risposta.

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 collegato nel resolver.

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

Frammento di codice che mostra le funzioni di richiesta e risposta con operation, key e attributeValues.

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

Codice del resolver che mostra la funzione di risposta con la freccia che punta alla funzione get_posts_func_1 di seguito.

Anche questi corrispondono al codice. Se osserviamoget_posts_func_1:

Codice funzionale che mostra l'operazione di restituzione della funzione di richiesta Funzione di scansione e risposta che restituisce ctx.result.items.

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

Elenco di elementi logici IDs tra cui post-api, posts-table, funzioni, risolutori di pipeline e. CDKMetadata

Ora, dobbiamo testare questo codice eseguendo alcune richieste.

Implementazione di un progetto CDK - Richieste

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

Visualizzazione del codice GraphQL con i campi MyQuery getPost e MyMutation con l'operazione CreatePost.

MyMutationcontiene un'createPostoperazione con gli argomenti e. 1970-01-01T12:30:00.000Z first 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 voce della tabella che mostra id, data del 01/01/1970 e titolo del primo post.

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" } ] } }