How To Create a VPC In AWS Using Pulumi And Golang
Tags: go, devops
Published: 2020-01-18 01:37:46

---
title: How To Create a VPC In AWS Using Pulumi And Golang
published: true
date: 2020-01-07 00:00:00 UTC
tags: Go,DevOps
canonical_url: https://retgits.com/2020/01/how-to-create-a-vpc-in-aws-using-pulumi-and-golang/
---

The source code you write as a developer is important, but it is only one part of the entire application that goes into production. To deploy an app, you’ll need resources like API gateways, S3 buckets, or VPCs as well. Configuring those resources is a task you don’t want to do manually. How about building your infrastructure as code using the same language you’ve built your app in. That is what [Pulumi](https://pulumi.com) allows you to do!

Most of the resources deployed to any of the major cloud providers need to be deployed inside a VPC. So let’s walk through the steps to create a VPC using the Pulumi Go SDK. The complete project is available on [GitHub](https://github.com/retgits/pulumi-blogs/tree/vpc-blog).

## A new project

If you haven’t done so already, you might want to take a quick second and head over to the [Pulumi website](https://app.pulumi.com/signin) to create a new account. It’s free forever for personal use! Once you’ve done that and installed the [CLI](https://www.pulumi.com/docs/get-started/aws/install-pulumi/) you’re ready to start. To get going, you’ll need to create a new Pulumi project. On the command line you can specify which template you want to use (`go` in this case). You’ll be able to specify the project name (with the `--name` flag), the description (with the `--description` flag), and the stack name (with the `--stack` flag).

```bash
pulumi new go \
--name builder \
--description "An awesome Pulumi infrastructure-as-code Stack" \
--stack retgits/builderstack
```

In the above example, I’ve used the project name `builder` and the stack is called `retgits/builderstack`.

## Using Go modules

The current Go template still relies on `dep` for dependency management, but with the introduction of Go modules you probably want to use that to manage dependencies. Luckily, switching from `dep` to `Go modules` only requires three commands.

```bash
go mod init github.com/retgits/builder
go mod tidy
rm Gopkg.*
```

The first command creates a new Go module in the directory where you run the command. The module needs a name and in this example the name of the module is `github.com/retgits/builder`. The second command takes the input from `Gopkg.toml` and creates entries in `go.mod` for each entry. The third command removes the `Gopkg` files.

## Default configuration variables

To ultimate deploy to AWS, Pulumi needs to know how to connect to AWS. To connect, Pulumi uses a _provider_ (more on that later). The configuration for that provider can be set through the command line: `pulumi config set aws:<option>`.

```yaml
pulumi config set aws:profile default
pulumi config set aws:region us-east-1
```

The example above, has the required parameter `aws:region` which tells Pulumi which region to deploy to (in this case `us-east-1`) and the optional parameter `aws:profile` which tells Pulumi the profile to use (in this case `default`). The profiles you can choose are the ones you created using `aws configure`.

## Adding more configuration variables

As a [best practice](https://aws.amazon.com/answers/account-management/aws-tagging-strategies/), AWS suggests that you add tags to each resource you create (at least the ones that support tags). Tags are simple key/value pairs that can make it easier to manage, search for, and filter resources. The tags that I use when I deploy code to AWS, and the ones that are in the sample are _version_ (because infrastructure-as-code makes it easy to version your infrastructure too), _author_ (so you can see who did the deployment), _team_ (so you can see which team did a deployment), and _feature_ (resources are generally part of a larger app so with this you can filter all resources for an app you’re looking for). If you want to change the tags, feel free to do so in the source code. To create a VPC, you’ll need two parameters. Firstly, the name of the VPC and secondly you’ll need to specify the CIDR block.

```yaml
tags:version: "0.1.0"
tags:author: <your name>
tags:team: <your team>
tags:feature: myFirstVPCWithPulumi
vpc:name: myPulumiVPC
vpc:cidr-block: "172.32.0.0/16"
```

There are two ways you can add configuration variables to your Pulumi config. You can either use the command line, like `pulumi config set tags:version "0.1.0"`, or you can add them directly into the yaml file. The yaml file with all the configuration is called `Pulumi.<name of your project>.yaml`.

## Using configuration variables in your code

The configuration variables that you’ve added to the YAML file are accessible through the `pulumi.Context` object. You can use the `GetConfig()` method to search for your key and you’ll get a string and a boolean in return. The boolean tells whether the context could find the key you’re looking for. To make that process a little easier and provide the option to have default values, you can add a method like the one below.

```go
// getEnv searches for the requested key in the pulumi context and provides either the value of the key or the fallback.
func getEnv(ctx *pulumi.Context, key string, fallback string) string {
	if value, ok := ctx.GetConfig(key); ok {
		return value
	}
	return fallback
}
```

## Making it all work

Now that most of the code is ready, it’s time to create a VPC. In the code below you can see a `map[string]interface{}` called _tags_ which is used to tag all the resources created with for this project. Pulumi creates the VPC by executing `ec2.NewVpc()`. As you likely want to know the ID of the newly created VPC, Pulumi makes it easy to take output from the AWS and _export_ it as outputs so you can see them in the [Pulumi console](https://app.pulumi.com/).

```go
func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		// Prepare the tags that are used for each individual resource so they can be found
		// using the Resource Groups service in the AWS Console
		tags := make(map[string]interface{})
		tags["version"] = getEnv(ctx, "tags:version", "unknown")
		tags["author"] = getEnv(ctx, "tags:author", "unknown")
		tags["team"] = getEnv(ctx, "tags:team", "unknown")
		tags["feature"] = getEnv(ctx, "tags:feature", "unknown")
		tags["region"] = getEnv(ctx, "aws:region", "unknown")

		// Create a VPC for the EKS cluster
		cidrBlock := getEnv(ctx, "vpc:cidr-block", "unknown")

		vpcArgs := &ec2.VpcArgs{
			CidrBlock: cidrBlock,
			Tags: tags,
		}

		vpcName := getEnv(ctx, "vpc:name", "unknown")

		vpc, err := ec2.NewVpc(ctx, vpcName, vpcArgs)
		if err != nil {
			fmt.Println(err.Error())
			return err
		}

		// Export IDs of the created resources to the Pulumi stack
		ctx.Export("VPC-ID", vpc.ID())
		return nil
	})
}
```

## Running the code

While most other languages rely on the package manager of the language to install Pulumi plugins (also called _providers_), Go does not. In order to deploy to AWS, you’ll need to manually install the AWS provider. To install the latest version (as of writing this blog) of the AWS provider, you can run the below command.

```bash
pulumi plugin install resource aws v1.17.0
```

The last thing to do is run `pulumi up` to tell Pulumi to go create your VPC!

```bash
$ pulumi up
Previewing update (builderstack):

     Type Name Plan       
 + pulumi:pulumi:Stack builder-builderstack create     
 + └─ aws:ec2:Vpc myPulumiVPC create     
 
Resources:
    + 2 to create

Do you want to perform this update? yes
Updating (builderstack):

     Type Name Status      
 + pulumi:pulumi:Stack builder-builderstack created     
 + └─ aws:ec2:Vpc myPulumiVPC created     
 
Outputs:
    VPC-ID: "vpc-<id>"

Resources:
    + 2 created

Duration: 11s

Permalink: https://app.pulumi.com/retgits/builder/builderstack/updates/1
```

The permalink at the bottom of the output takes you to the Pulumi console where you can see all the details of the execution of your app and the resources that were created.

![The Pulumi console also has really useful links to the AWS console to see the resources.](https://retgits.com/images/how-to-create-a-vpc-in-aws-using-pulumi-and-golang-1.png) <figcaption>
            <p>The Pulumi console also has really useful links to the AWS console to see the resources.</p>
        </figcaption>