Serverless REST API
With Pulumi, you can combine infrastructure definitions and application code in one program. The @pulumi/cloud library is a set of Pulumi components that provide a higher-level abstraction over AWS. So, instead of provisioning an API Gateway instance, Lambda functions, and setting up IAM roles, you can use cloud.API and define application code at the same time as the infrastructure it depends on.
In this tutorial, we’ll show how to create a simple REST API that counts the number of times a route has been hit. To implement this API, we need a key-value store, an API endpoint, and a Lambda function.
Prerequisites
Create a simple REST API
Run
pulumi new
:$ mkdir hello-http && cd hello-http $ pulumi new aws-javascript
Replace the contents of
index.js
with the following:const cloud = require("@pulumi/cloud-aws"); // Create a mapping from 'route' to a count let counterTable = new cloud.Table("counterTable", "route"); // Create an API endpoint let endpoint = new cloud.API("hello-world"); endpoint.get("/{route+}", (req, res) => { let route = req.params["route"]; console.log(`Getting count for '${route}'`); // get previous value and increment // reference outer `counterTable` object counterTable.get({ route }).then(value => { let count = (value && value.count) || 0; counterTable.insert({ route, count: ++count }).then(() => { res.status(200).json({ route, count }); console.log(`Got count ${count} for '${route}'`); }); }); }); exports.endpoint = endpoint.publish().url;
The definition for
counterTable
stores a counter for each route, using cloud.Table. On AWS, this provisions a DynamoDB instance. To create a new API Gateway instance, we create an instance of cloud.API. New routes can be added to this endpoint using methods likeget
,post
,put
etc.The function passed to
get
is the interesting part: this becomes the body of a new AWS Lambda function that is called on a GET request to the API Gateway. The body of this function can use variables defined in the main program, such ascounterTable
. This is translated to a lookup on the provisioned DynamoDB instance; there is no need to store its ARN in an environment variable.Add and install the NPM dependencies:
$ npm install --save @pulumi/cloud @pulumi/cloud-aws
Preview and deploy changes via
pulumi up
:$ pulumi up Previewing update of stack 'hello-http' ... Updating stack 'hello-http' ... info: 14 changes performed: + 14 resources created
View the endpoint URL and curl a few routes:
$ pulumi stack output Current stack outputs (1): OUTPUT VALUE endpoint https://5e8xrktey3.execute-api.us-west-2.amazonaws.com/stage/ $ curl $(pulumi stack output endpoint)/hello {"route":"hello","count":1} $ curl $(pulumi stack output endpoint)/woohoo {"route":"woohoo","count":1}
To view the runtime logs of the Lambda function, use the
pulumi logs
command. To get a log stream, usepulumi logs --follow
.$ pulumi logs --follow Collecting logs since 2018-05-01T21:22:59.000-07:00. 2018-05-01T22:25:05.040-07:00[ hello-world4fcc7b60] Getting count for 'hello' 2018-05-01T22:25:05.188-07:00[ hello-world4fcc7b60] Got count 1 for 'hello' 2018-05-01T22:25:13.562-07:00[ hello-world4fcc7b60] Getting count for 'woohoo' 2018-05-01T22:25:13.704-07:00[ hello-world4fcc7b60] Got count 1 for 'woohoo'
Clean up
Before moving on, tear down the resources that are part of your stack to avoid incurring any charges.
- Run
pulumi destroy
to tear down all resources. You'll be prompted to make sure you really want to delete these resources. A destroy operation may take some time, since Pulumi waits for the resources to finish shutting down before it considers the destroy operation to be complete. - To delete the stack itself, run
pulumi stack rm
. Note that this command deletes all deployment history from the Pulumi Service.
Next steps
For an end-to-end application with a frontend, see the URL shortener sample.
Thank you for your feedback!
If you have a question about how to use Pulumi, reach out in Community Slack.
Open an issue on GitHub to report a problem or suggest an improvement.