A First Look at Pulumi
Tags: pulumi, iac, aws, lambda
Published: 2021-09-28 00:03:15

---
canonical_url: "https://ajcwebdev.com/first-look-pulumi/"
description: "Pulumi provides open source infrastructure as code SDKs for creating, deploying, and managing infrastructure on multiple clouds in multiple languages."
---

## Outline

- [Introduction](#introduction)
- [Setup](#setup)
  - [Install Pulumi CLI](#install-pulumi-cli)
  - [Configure AWS Credentials](#configure-aws-credentials)
  - [Login to Pulumi](#login-to-pulumi)
- [Create a New Pulumi Project](#create-a-new-pulumi-project)
  - [Pulumi Yaml Files](#pulumi-yaml-files)
  - [Index File](#index-file)
  - [HTML Index File](#html-index-file)
- [Deploy to Pulumi Cloud](#deploy-to-pulumi-cloud)
  - [Update HTML File](#update-html-file)

> ___All of this project's code can be found in the [First Look monorepo](https://github.com/ajcwebdev/a-first-look/tree/main/deployment/pulumi/) on my GitHub.___

## Introduction

[Pulumi](https://www.pulumi.com) provides open source infrastructure as code SDKs that enable you to create, deploy, and manage infrastructure on numerous popular clouds in multiple programming languages.

## Setup

In this tutorial, we’ll show you how to write a Pulumi program that creates a serverless app serving static content with dynamic routes in AWS Lambda.

### Install Pulumi CLI

Instructions for downloading the CLI will [vary depending on your operating system](https://www.pulumi.com/docs/get-started/install/#installing-pulumi). This tutorial will use [Homebrew](https://brew.sh/) on MacOS.

```bash
brew install pulumi
```

Subsequent updates can be installed with `brew upgrade`.

```bash
brew upgrade pulumi
```

### Configure AWS Credentials

Make sure you have the [AWS CLI](https://aws.amazon.com/cli/) installed and an [AWS account](https://aws.amazon.com/). For general use, [`aws configure`](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html) is recommended as the fastest way to set up your AWS CLI installation.

```bash
aws configure
```

When you enter this command, the AWS CLI prompts you for four pieces of information:
* Access key ID
* Secret access key
* AWS Region
* Output format

Go to [My Security Credentials](https://console.aws.amazon.com/iam/home?#/security_credentials) to find your Access Key ID, Secret Access Key, and default region. You can leave the output format blank.

```
AWS Access Key ID: <YOUR_ACCESS_KEY_ID>
AWS Secret Access Key: <YOUR_SECRET_ACCESS_KEY>
Default region name: <YOUR_REGION_NAME>
Default output format [None]: 
```

### Login to Pulumi

```bash
pulumi login
```

You will be asked to hit `<ENTER>` to log in with your browser.

```
Manage your Pulumi stacks by logging in.

Run `pulumi login --help` for alternative login options.

Enter your access token from https://app.pulumi.com/account/tokens
    or hit <ENTER> to log in using your browser
```

## Create a New Pulumi Project

We'll use the [pulumi new](https://www.pulumi.com/docs/reference/cli/pulumi_new/) command and generate a new project with the `hello-aws-javascript` template. It will be named `ajcwebdev-pulumi` with the `--name` flag.

```bash
mkdir ajcwebdev-pulumi
cd ajcwebdev-pulumi
pulumi new hello-aws-javascript --name ajcwebdev-pulumi
```

You will be asked to provide a description, stack name, and AWS region. I selected the default option for each.

### Pulumi Yaml Files

A Pulumi project is any folder which contains a `Pulumi.yaml` file specifying metadata about your project. The project file must begin with a capitalized P and can use either `.yml` or `.yaml` extensions.

```yaml
# Pulumi.yaml

name: ajcwebdev-pulumi
runtime: nodejs
description: A simple AWS serverless JavaScript Pulumi program
```

The key-value pairs for any given stack are stored in your project’s stack settings file, which is automatically named `Pulumi.<stack-name>.yaml`.

```yaml
# Pulumi.dev.yaml

config:
  aws:region: us-west-1
```

### Index File

Import the [pulumi/aws](https://pulumi.io/reference/pkg/nodejs/@pulumi/aws/index.html) package. Create a public HTTP endpoint using AWS API Gateway that serves static files from the `www` folder using AWS S3 with a REST API served on `GET /name` with AWS Lambda. Finally, export the public URL for the HTTP service with `exports.url = endpoint.url`.

```js
// index.js

const pulumi = require("@pulumi/pulumi")
const aws = require("@pulumi/aws")
const awsx = require("@pulumi/awsx")

const endpoint = new awsx.apigateway.API("hello", {
  routes: [
    {
      path: "/",
      localPath: "www",
    },
    {
      path: "/source",
      method: "GET",
      eventHandler: (req, ctx, cb) => {
        cb(undefined, {
          statusCode: 200,
          body: Buffer.from(JSON.stringify({ name: "AWS" }), "utf8").toString("base64"),
          isBase64Encoded: true,
          headers: { "content-type": "application/json" },
        })
      },
    },
  ],
})

exports.url = endpoint.url
```

### HTML Index File

The project comes with a hello world example in the `index.html` file.

```html
<!-- www/index.html -->

<!DOCTYPE html>

<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Hello Pulumi</title>
    <link rel="shortcut icon" href="favicon.png" type="image/png">
  </head>

  <body>
    <p>Hello, world!</p>
    <p>Made with ❤️ using <a href="https://pulumi.com">Pulumi</a></p>
    <p>Served from: <span id="source"></span></p>
  </body>

  <script>
    fetch("source")
      .then(response => response.json())
      .then(json => {
        document.getElementById("source").innerText = json.name;
      });
  </script>
</html>
```

## Deploy to Pulumi Cloud

Create or update the resources in a stack with `pulumi up`.

```bash
pulumi up
```

```
Do you want to perform this update?  [Use arrows to move, enter to select, type to filter]
> yes
  no
  details
```

Select yes.

```
Outputs:
    url: "https://2inuue6w0a.execute-api.us-west-1.amazonaws.com/stage/"

Resources:
    + 22 created

Duration: 26s
```

Open [2inuue6w0a.execute-api.us-west-1.amazonaws.com/stage/](https://2inuue6w0a.execute-api.us-west-1.amazonaws.com/stage/).

![01-pulumi-boilerplate](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2f3qi23p9307ig3t0bqc.png)

### Update HTML File

Change stuff.

```html
<!-- www/index.html -->

<!DOCTYPE html>

<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>ajcwebdev-pulumi</title>
    <link rel="shortcut icon" href="favicon.png" type="image/png">
  </head>

  <body>
    <h2>ajcwebdev-pulumi</h2>
    <p>Served from: <span id="source"></span></p>
  </body>

  <script>
    fetch("source")
      .then(response => response.json())
      .then(json => {
        document.getElementById("source").innerText = json.name;
      });
  </script>
</html>
```

Run `pulumi up` again to deploy your changes.

```bash
pulumi up
```

Check back to [2inuue6w0a.execute-api.us-west-1.amazonaws.com/stage/](https://2inuue6w0a.execute-api.us-west-1.amazonaws.com/stage/).

![02-ajcwebdev-pulumi](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2puhpc364ba4uhxmffyu.png)