Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ci/vale/dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1048,6 +1048,7 @@ psycop2
pty
pubkey
publickey
pulumi
puppetd
puppetlabs
puppetmaster
Expand Down Expand Up @@ -1193,6 +1194,7 @@ sendmail
seo
serv
server1
serverless
servername
serverpassword
serverspec
Expand Down
3 changes: 3 additions & 0 deletions ci/vale/styles/Linode/Terms.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,7 @@ swap:
uris: URIs
Cuda: CUDA
gpu: GPU
stackscript: StackScript
typescript: TypeScript
pulumi: Pulumi
markdown: Markdown
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressing a merge conflict in Terms.yml

Original file line number Diff line number Diff line change
@@ -0,0 +1,315 @@
---
author:
name: Linode
email: docs@linode.com
description: 'Learn how to install Pulumi, import the Linode module for Pulumi, and write your first Pulumi programs.'
keywords: ["pulumi", "configuration management", "infrastructure as code", "iac", "javascript", "python"]
license: '[CC BY-ND 4.0](https://creativecommons.org/licenses/by-nd/4.0)'
modified_by:
name: Linode
published: 2019-06-26
title: Getting Started with Pulumi
external_resources:
- '[Pulumi Documentation](https://pulumi.io/reference/)'
- '[Pulumi API reference](https://pulumi.io/reference/pkg/)'
- '[Why Pulumi](https://www.pulumi.com/why-pulumi/)'
---

## What is Pulumi?

[*Pulumi*](https://www.pulumi.com/) is a development tool that allows you to write computer programs which deploy cloud resources--a practice referred to as *infrastructure as code (IaC)*. Pulumi integrates with multiple cloud platforms, and Pulumi programs can be authored in a number of common programming languages.

With Pulumi's Linode integration, you can manage your Linode resources as you would with our [API](https://developers.linode.com/api/v4/) or [CLI](/docs/platform/api/using-the-linode-cli/), but in a language you may already be familiar with. This guide will present examples written in JavaScript, but Pulumi is also compatible with Go, Python, and TypeScript.

Pulumi also comes with a CLI interface for running the cloud infrastructure programs that you write. Once you've written a program, you can create your cloud resources with a single command:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inserted this paragraph and CLI example so that we could get in an example of code/commands early on, which could hopefully help with reader engagement


pulumi up

In this guide you will learn how to:

* [Install and set up Pulumi](#before-you-begin) on Debian 9
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Distros should be "Distro_name distro_version" (space in between)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also added links to the respective sections

* [Create a single Linode instance](#create-a-linode) using Pulumi and JavaScript
* [Create a NodeBalancer](#create-and-configure-a-nodebalancer) with two NGINX webserver backends using Pulumi and JavaScript

## Before You Begin

1. If you haven't yet, [create a Linode API token](/docs/platform/api/getting-started-with-the-linode-api/#create-an-api-token).

1. [Create a free Pulumi account](https://app.pulumi.com/signup).

1. Create a new Debian 9 Linode. Follow our [Getting Started](/docs/getting-started/) guide to deploy the Linode, and then follow the [Securing Your Server](/docs/security/securing-your-server/) guide. Be sure to create a [limited Linux user with sudo privileges](/docs/security/securing-your-server/#add-a-limited-user-account) on your server. All commands in this guide are to be run from a sudo user.

1. Install Pulumi on your Linode using their installation script:

curl -fsSL https://get.pulumi.com | sh

1. To start using the Pulumi CLI:

- Restart your shell session, or

- Add `/home/username/.pulumi/bin` to your `$PATH` variable in your current session. Replace `username` with the name of your limited Linux user:

PATH=$PATH:/home/username/.pulumi/bin

1. Install [Node.js](https://nodejs.org/en/) and [npm](https://www.npmjs.com/):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vale fix


sudo apt-get install curl software-properties-common
curl -sL https://deb.nodesource.com/setup_12.x | sudo bash -
sudo apt-get install -y nodejs

## Generate a Pulumi Access Token

Once you have a Pulumi account, you will need to create an *access token* to use later.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name of the Access Token page is capitalized in the title for that page on Pulumi's site, but they don't capitalize it in their body text


{{< disclosure-note "Why do I need a Pulumi access token?" >}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding some context around why you would need an access token, which may be a natural question for some readers. For example, Terraform does not require any access token with their organization's website to use the tool, as state is stored on your filesystem by default, so it may not be obvious that Pulumi is doing this.

When Pulumi interprets the infrastructure programs that you write, it determines what cloud resources it needs to create in order to satisfy your program. Every time you run your program, [Pulumi stores the state](https://pulumi.io/reference/state/#state-and-backends) of these resources in a persistent backend. In subsequent updates to your infrastructure, Pulumi will compare your program with the recorded state so that it can determine which changes need to be made.

By default, Pulumi securely stores this state information on a web backend hosted at [https://app.pulumi.com](https://app.pulumi.com). This service is free to start and offers paid tiers for teams and enterprises.

It is possible to opt-out of using the default web backend and use a filesystem-based backend instead. Review [Pulumi's documentation](https://pulumi.io/reference/state/#to-the-filesystem-backend) for instructions.
{{< /disclosure-note >}}

1. [Log into your Pulumi account](https://app.pulumi.com/signin). After you've logged in, click on the avatar graphic to the top right of the Pulumi dashboard, then click on the **Settings** option in the dropdown menu that appears:

[![Location of Pulumi Settings option](pulumi-settings.png "Location of Pulumi Settings option")](pulumi-settings.png)

1. Select the **Access Tokens** item in the sidebar to the left of the page that appears:

[![Location of Pulumi Access Token page](pulumi-token.png "Location of Pulumi Access Token page")](pulumi-token.png)

1. Click on the **New Access Token** button towards the top right of the following page and follow the prompts to create your new token. Make sure you save this in a secure location, similar to your Linode API token.

## Create a Linode
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename H2 from Default Configuration to Create a Linode, to make it more consistent with the next H2 section. Also added extra H3s to break up the content of this section (including one called "Inspect the Default Configuration")


### Set up your Pulumi Project

Now that you have everything you need to begin using Pulumi, you can create a new Pulumi *project*.

{{< note >}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a short definition of what a Pulumi project is

A Pulumi [project](https://pulumi.io/reference/project/) is the folder structure which contains your Pulumi programs. Specifically, a project is any folder which contains a `Pulumi.yaml` metadata file.
{{< /note >}}

1. Pulumi requires an empty directory for each new project, so first you'll need to create one and make it your working directory:

cd ~/ && mkdir pulumi && cd pulumi

1. Now that you're inside of your new empty working directory, create a new project:

pulumi new

1. From here, you'll see several prompts:

- Enter your Pulumi access token if prompted. If you've already entered it at any point following the installation of Pulumi, you will not be prompted again and can skip this step.
- Use your arrow keys to highlight the `linode-javascript` option.
- Enter a project name of your choice, or leave blank to use the default option.

- Enter a project description, or leave blank to use the default option.
- Enter a *stack* name of your choice, or leave blank to use the default option.

{{< disclosure-note "What's a stack?" >}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding short, collapsible definition of what a stack is

Multiple instances of your Pulumi programs can be created. For example, you may want to have separate instances for the development, staging, and production environments of your service. Or, you may create multiple instances of your service if you're offering it to different business clients. In Pulumi, these instances are referred to as [stacks](https://pulumi.io/tour/programs-stacks/).
{{< /disclosure-note >}}

- Enter your Linode API token.

1. Once the installation is successful, you will see a `Your new project is ready to go!` message. The `pulumi new` command scaffolds a collection of default configuration files in your project's directory. The default configuration will give you everything you need to get started. Enter the `ls` command to ensure that the files are present:

ls

{{< output >}}
index.js package.json Pulumi.pulumi.yaml
node_modules package-lock.json Pulumi.yaml
{{< /output >}}

The contents of these files were defined according to our responses to each prompt after entering `pulumi new`. In particular:

- `index.js` contains the JavaScript Pulumi will run
- `package.json` defines the dependencies we can use and the file path Pulumi will be reading our code from.

### Inspect the Default Configuration

Let's take a look at the contents of our `index.js` file:

{{< file "index.js" javascript >}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can add the kind of language for the snippet and the syntax highlighting will change

"use strict";
const pulumi = require("@pulumi/pulumi");
const linode = require("@pulumi/linode");

// Create a Linode resource (Linode Instance)
const instance = new linode.Instance("my-instance", {
type: "g6-nanode-1",
region: "us-east",
image: "linode/ubuntu18.04",
});

// Export the Instance label of the instance
exports.instanceLabel = instance.label;
{{< /file >}}

The file requires two JavaScript modules unique to Pulumi: Pulumi's SDK, and Pulumi's Linode integration. [Pulumi's API Reference Documentation](https://pulumi.io/reference/pkg/nodejs/pulumi/linode/) serves as a reference for the JavaScript you'll see here. It also includes a library of several additional options that enable you to create configurations more specific to your use case.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverting previous package<->module change


In this case, your file is only creating a single Nanode instance in the Newark data center running Ubuntu 18.04.

### Create and Destroy Resources
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed the section and framed it in a bulleted list to add some structure


- Use [Pulumi's `preview` command](https://pulumi.io/reference/cli/pulumi_preview/) to test your code and make sure it's successfully able to create resources under your account.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test your code and make sure it's successfully able to create resources under your account description I think more accurately corresponds to Pulumi's preview command, so I added that to the guide

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also inserted links to the Pulumi docs for each command (preview, up, destroy)


pulumi preview

The output of the command will list the operations Pulumi will perform once you deploy your program:

Previewing update (dev):

Type Name Plan
+ pulumi:pulumi:Stack my-pulumi-project-dev create
+ └─ linode:index:Instance my-instance create

Resources:
+ 2 to create

- Use [Pulumi's `up` command](https://pulumi.io/reference/cli/pulumi_up/) to deploy your code to your Linode account:

pulumi up

{{< note >}}
This will create a new billable resource on your account.
{{< /note >}}

From here, you will be prompted to confirm the resource creation. Use your arrow keys to choose the `yes` option, hit `enter`, and you will see your resources being created. Once the process is completed, the Linode Label of your new Linode will be displayed. If you check your account manually through the [Cloud Manager](https://cloud.linode.com/), you can confirm that this Linode has been successfully created.

- Since this Linode was only created as a test, you can safely delete it by entering [Pulumi's `destroy` command](https://pulumi.io/reference/cli/pulumi_destroy/):

pulumi destroy

Follow the prompts, and you'll be able to see the resources being removed, similar to how we could see them being created.

{{< note >}}
Many Pulumi commands will be logged on your Pulumi account. You can see this under the **Activity** tab of your project's stack in [Pulumi's Application Page](https://app.pulumi.com/).
{{< /note >}}

## Create and Configure a NodeBalancer

To better demonstrate the power of Pulumi code, we'll create a new `index.js` file. This will define everything we need to create a functioning NodeBalancer which is pre-configured with two backend Linodes running NGINX.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pre-configured + pre-installed in one sentence was loading up on the pre- suffix a bit much, reworded the pre-installed part


1. Replace the contents of your `index.js` file with the following:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added line numbering for the instructions


{{< file "index.js" javascript >}}
const pulumi = require("@pulumi/pulumi");
const linode = require("@pulumi/linode");

// Create two new Nanodes using a StackScript to configure them internally.
// The StackScript referenced will install and enable NGINX.

// "linode1" (the first argument passed to the Linode instance constructor function) is the Pulumi-allocated Unique Resource Name (URN) for this resource
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding some context with regard to URNs vs Linode labels

const linode1 = new linode.Instance("linode1", {
// "PulumiNode1" is the Linode's label that appears in the Cloud Manager. Linode labels must be unique on your Linode account
label: "PulumiNode1",
region: "us-east",
image: "linode/debian9",
privateIp: true,
stackscriptData: {
hostname: "PulumiNode1",
},
stackscriptId: 526246,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the StackScript so that the web page served says "Hello from " instead of the default NGINX . page

type:"g6-nanode-1",
});

const linode2 = new linode.Instance("linode2", {
label: "PulumiNode2",
region: "us-east",
image: "linode/debian9",
privateIp: true,
stackscriptData: {
hostname: "PulumiNode2",
},
stackscriptId: 526246,
type:"g6-nanode-1",
});

// Create and configure your NodeBalancer

const nodeBalancer = new linode.NodeBalancer("nodeBalancer", {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

made variable names more verbose to hopefully increase legibility

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also made javascript variable names and Pulumi URNs all in camelCase (some were in snake_case, some were in all lower case)

Made Linode labels all in TitleCase

clientConnThrottle: 20,
label: "PulumiNodeBalancer",
region: "us-east",
});

const nodeBalancerConfig = new linode.NodeBalancerConfig("nodeBalancerConfig", {
algorithm: "source",
check: "http",
checkAttempts: 3,
checkTimeout: 30,
checkInterval: 40,
checkPath: "/",
nodebalancerId: nodeBalancer.id,
port: 8088,
protocol: "http",
stickiness: "http_cookie",
});

// Assign your Linodes to the NodeBalancer

const balancerNode1 = new linode.NodeBalancerNode("balancerNode1", {
address: pulumi.concat(linode1.privateIpAddress, ":80"),
configId: nodeBalancerConfig.id,
label: "PulumiBalancerNode1",
nodebalancerId: nodeBalancer.id,
weight: 50,
});

const balancerNode2 = new linode.NodeBalancerNode("balancerNode2", {
address: pulumi.concat(linode2.privateIpAddress, ":80"),
configId: nodeBalancerConfig.id,
label: "PulumiBalancerNode2",
nodebalancerId: nodeBalancer.id,
weight: 50,
});

//Output your NodeBalancer's Public IPV4 address and the port we configured to access it
exports.nodeBalancerIP = nodeBalancer.ipv4;
exports.nodeBalancerPort = nodeBalancerConfig.port;
{{< /file >}}

{{< note >}}
In our `index.js` file we've created and configured two Linodes using an existing [StackScript](/docs/platform/stackscripts/) which installs NGINX. Pulumi's Linode integration allows for the creation of entirely [new StackScripts](https://pulumi.io/reference/pkg/nodejs/pulumi/linode/#StackScript) directly in code, which can help you to automate your deployments even further.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't need to replace module with integration--I only have wish-washy reasons for doing that, and we could revert it if we wanted.

I switched pre-configured StackScript to existing StackScript. We were using pre-configured to refer to NodeBalancers earlier, and the NodeBalancer nodes are configured via StackScript, so using the word again in this context got a little confusing in my head.


If you're interested in seeing how this StackScript works, you can view it [here](https://www.linode.com/stackscripts/view/526246).
{{< /note >}}

1. Now that you've successfully prepared your JavaScript code, let's bring up our configuration:

pulumi up

As before, select `yes` when prompted and wait for a few moments as your resources are created, configured, and brought online.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using backticks when referring to terminal output


1. Once the process is completed, you'll see your NodeBalancer's IP address and the port you configured earlier displayed as part of the output:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Showing the Pulumi variable exports the reader should look for in the output, and giving an example of the response via cURL


Outputs:
+ nodeBalancerIP : "192.0.2.3"
+ nodeBalancerPort: 8088

Enter this IP address and port into your web browser, and you will see the *Hello World*-style page that the StackScript configured:

curl http://192.0.2.3:8088/

{{< output >}}
Hello from PulumiNode1
{{< /output >}}

{{< note >}}
If you do not see this page right away, you should wait a few additional moments. NodeBalancers can sometimes require a little extra time to fully apply a new configuration.
{{< /note >}}

1. Once you're finished with your NodeBalancer, you can remove and delete everything you added by entering `pulumi destroy` as before.

## Next Steps

Pulumi is a powerful tool with a vast number of possible configurations that can be applied. From here you can:

* Look at Pulumi's [examples](https://github.com/pulumi/examples) for more ideas regarding the things you can do with Pulumi.

* Try using Pulumi with different languages like [Python](https://pulumi.io/reference/python/) or [TypeScript](https://pulumi.io/reference/javascript/#typescript)

* Import Node.js tools like [Express](https://expressjs.com/) for even more elasticity with your code.

* Use Pulumi for [Serverless Computing](https://www.pulumi.com/serverless/)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/platform/stackscripts-classic-manager/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ The UDF tags are explained in the table below:
|manyof | A comma separated list of values| Optional


Below is an example implementation of the UDF variables. Note that the UDF tags are commented out to prevent execution errors, as the stackscript system parses the tags without removing them:
Below is an example implementation of the UDF variables. Note that the UDF tags are commented out to prevent execution errors, as the StackScript system parses the tags without removing them:

{{< file "StackScript" bash >}}
# [...]
Expand Down
2 changes: 1 addition & 1 deletion docs/platform/stackscripts/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ The UDF tags are explained in the table below:
|manyof | A comma separated list of values| Optional


Below is an example implementation of the UDF variables. Note that the UDF tags are commented out to prevent execution errors, as the stackscript system parses the tags without removing them:
Below is an example implementation of the UDF variables. Note that the UDF tags are commented out to prevent execution errors, as the StackScript system parses the tags without removing them:

{{< file "StackScript" bash >}}
# [...]
Expand Down