Pulumi Platypus And The Very GRAND Stack

Deploying A Serverless GraphQL API Using Infrastructure As Code

--

We are going to explore the Infrastructure-as-Code world today with the help of Pulumi, creating a newly minted interpretation of the GRANDStack architecture in an easily deploy-able construct that will allow us to build and experiment.

If you are like me and would generally rather just read and tweak code. Here is a repo. 🐠

Get over there, fork it, tweak it, tell me what I did wrong, come back here if you feel like reading more. 🍒

Pulumi Platypus the Intern
Pulumi Platypus

We don’t need to run through a bunch of sales copy here. Pulumi has their messaging on lock, but it’s nice to take a moment to realize that their choice of mascot is extremely appropriate. The oddly cobbled together feel of cloud services, choice of programming languages and operating procedures flows smoothly and with a bit of trial and error can lead to a nice, contextually relevant amalgamation that provides both flexibility and stability.

There are a lot of examples to start your project, but before digging into the toy chest you’ll need to make some decisions about clouds and run through Pulumi’s get started flow. We are going to leverage GCP for our cloud choice, if you’d like to follow along, make sure you’ve created a google project and installed the CLI.

Versioning is important, so let me break out from the collective voice momentarily and say that I am currently using Pulumi CLI: v2.11.2 and running all of this on a linux box from System 76. For the sake of argument, I’m also using vscode: 1.50.0-insider.

Lets Talk Command Line

There are a lot of different commands that you can use with pulumi CLI, but like with docker-compose and kubectl there are a couple commands that you are going to run again and again.

pulumi up — This is your standard start and push

…it creates or updates resources in a stack. This command records a full transactional snapshot of the stack’s new state afterwards so that the stack may be updated incrementally again later on.

pulumi destroy— this is a great command to remember because it cleans up all of the various cloud systems that you have leveraged to create your current Pulumi stack. Pulumi warns you that it as a fairly aggressive and destructive action:

This command deletes an entire existing stack by name.

…this command is generally irreversible and should be used with great care.

Personally I’m a bit paranoid about finding random charges on the credit card attached to my account so I run this at the end of every dev session. Do as you will 😺.

pulumi logs -f — these give you the logs from pulumi, good to run in a different terminal. They are in preview state and sometimes are a bit hit or miss but can be helpful.

Boilerplate

We are going to run some Typescript today. It’s a toss up between Go and Typescript but the cool kids use Typescript and we want to be cool 😎. We’ll start with the most basic example that fits our use case. Many thanks to leezen. He’s got some vids over on youtube, go check them out sometime.

If you’d like to clone Lee Zen’s repo and run the gcp function configuration skip ahead to the gist right before Making a Database (we need to tweak a few things) ➡️, if you’d like to attack the skeleton, turn to page 4 💀, if instead you are going with ground up you will need to create a project folder and leverage pulumi cli to bootstrap a new Google Cloud/Typescript project.

This command will install a minimal file set and attach to your google project that you created earlier. At this point if you like, you should be able to run pulumi up. It will create a bucket and deploy it to your project. Let’s riff on that with Apollo Server Cloud Functions.

Once we have those two packages we can edit our entry file and add a few lines for our typeDefs and resolvers:

This is stolen wholeheartedly from Zen’s repo 🙌 which wrapped a factory function around apollo server’s base lambda example. We are going to add in an endpoint to our Apollo Server config so we can leverage the playground.

This is a good spot to update you stack and check it out. You might run into an error that looks something like this:

For now you can just follow the link and apply the Cloud Build API manually then pulumi up. If all goes well you should be able to go to the url output of your Pulumi stack and checkout the playground.

GraphQL playground with simple query
Basic GraphQL query that returns a string

Next we’ll loop in Neo4j and use a few more libraries to setup our schema.

Making a Database

Head on over to Neo4J and spin up a new blank sandbox to hold your data. You are going to need something in there, but lets not over-complicate things. Open the sandbox browser and run this command:

Now we have a single node, that is a Person type with a field, name that should return the string ‘Andy’. Our database knows this, but our Pulumi stack is blissfully ignorant of this advance, Andy is trapped in the database! Let’s add in some schema linking and attach the Neo4J driver to make it aware of what’s going on in the database and save Andy.

First we’ll install some npm packages. neo4j-driver is going to allow us to connect to Apollo server so they can communicate effectively. neo4j-graphql-js will generate a GraphQL API based on our typedefs and without writing resolvers.

We are just scratching this surface here, take a minute sometime to check out the Neo4j GraphQL docs and dig deeper.

Our driver needs some credentials. Head over to Neo4j Sandbox to pick those up from the Connection details tab in your instance to connect the driver.

Neo4j sandbox credentials
Connection details tab

Then we’ll update our entry file with our new Neo4j libraries. Our credentials from the sandbox connect up our driver and with only a single line of code we have all our database queries. That one right there: makeAugmentedSchema. makeAgumentedSchema takes that string of the typedefs and builds out all the needed resolvers.

Cool. Should be good. Run pulumi up and let’s see what is…

Sweet that is one unique bonbon. Let’s test a query in our playground.

There is Andy. We’ve missed you friend 😍 😿 and a quick look at the Docs and the Schema tab gives us a window into all the useful elements the neo4j-graphql-js provided for us.

From here on out you can delve into the world of Neo4j through their official docs to build out your schema or check out their Twitch Streams. Using Pulumi as your API/Stack build tool gives you a bridge into the cloud that doesn’t involve the confusion of GUI’s and multiple IAM nightmares and allows you to easily diff your prior builds.

Next it would be pretty sweet to get your React/Vue/Flutter frontend attached to another gcp instance. Take a swing at it and if you are looking for some inspiration head over to GRANDStack Starter

Oh and last but not least: pulumi destroy. Don’t forget to destroy 😈

Prologue — In which AWS is given it’s due

My first choice was AWS with APIGateway. To set this up you need an IAM user for Pulumi to create resources. There were some positives about this at the beginning and after a few hiccups, most notably a mismatched context type to which I found a solution here, I got through to the “hello world” string coming back from the playground or a curl request.

At this point it was time to attach the driver. I got a fairly obtuse timeout error without a useful way to debug it.

The Error of Doom

After fiddling around with cloudwatch logs and trying several different side paths to debug and or circumvent this problem I decided it was time to pivot to GCP. I would however like to include my failure as it might be informative and or interesting to other people: AWS fail.

--

--