Skip to main content
How To Create a VPC In AWS Using Pulumi And Golang
  1. Blog/

How To Create a VPC In AWS Using Pulumi And Golang

·4 mins·
Infrastructure as Code with Pulumi and Go - This article is part of a series.
Part 1: This Article

Your source code is only one piece of what goes into production. You also need API gateways, S3 buckets, VPCs, and other infrastructure. Configuring those by hand is tedious and error-prone. Pulumi lets you define all of that in the same language you build your app in.

Most resources on the major cloud providers need to live inside a VPC, so that’s a natural starting point. This post walks through creating one with the Pulumi Go SDK. The complete project is available on GitHub.

A new project
#

If you haven’t already, head over to the Pulumi website to create an account (free for personal use). Once you’ve installed the CLI, you can create a new project. The go template gives you a starting point, and you can set the project name, description, and stack name via flags:

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

In this example, the project name is builder and the stack is retgits/builderstack.

Using Go modules
#

The default Go template still uses dep for dependency management, but Go modules are the way to go now. Switching over takes three commands:

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

The first creates a new Go module. The second pulls dependencies from Gopkg.toml into go.mod. The third cleans up the old Gopkg files.

Default configuration variables
#

Pulumi needs to know how to connect to AWS. You configure the AWS provider through the command line with pulumi config set aws:<option>:

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

The aws:region parameter is required and tells Pulumi where to deploy. The aws:profile parameter is optional and maps to the profiles you created with aws configure.

Adding more configuration variables
#

AWS recommends tagging your resources so they’re easier to manage, search, and filter. The tags used here are version, author, team, and feature. Feel free to adjust them in the source code. You’ll also need a VPC name and CIDR block:

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"

You can add these with the command line (e.g., pulumi config set tags:version "0.1.0") or edit the YAML file directly. The file is named Pulumi.<name of your project>.yaml.

Using configuration variables in your code
#

Configuration variables from the YAML file are accessible through the pulumi.Context object. The GetConfig() method returns a string and a boolean indicating whether the key was found. A small helper function makes this cleaner:

// 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
#

With the helper in place, here’s the code that creates the VPC. It builds a tag map, sets up the VPC arguments, and exports the VPC ID so it shows up in the Pulumi console:

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
#

Go doesn’t use a package manager to install Pulumi plugins like other languages do, so you need to install the AWS provider manually:

pulumi plugin install resource aws v1.17.0

Then run pulumi up to create the VPC:

$ 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 takes you to the Pulumi console where you can see all the details of the execution and the resources that were created.

Cover image by Free-Photos from Pixabay

Infrastructure as Code with Pulumi and Go - This article is part of a series.
Part 1: This Article

Related

Serverless - From Microservice to Functions

·1 min
Using serverless requires us to change our mindset on how we build apps and requires us to unlearn things we learned building apps in the past. At AWS re:Invent I got a chance to do a VMware Code session and talk about how we took part of our ACME Fitness Shop and transformed it into serverless functions with AWS Lambda.

Serverless - The Wrath of Containers

·1 min
Containers were this awesome technology that ushered in the Cloud era and with a lot of new FaaS tools coming along, companies are wondering if they should jump the container ship altogether. As it turns out, containers definitely have value in Serverless. In this session we will take an existing containerized app and move it into AWS Fargate, look at the cost of running it, and how we can monitor it.

Trusting Your Ingredients @DevOpsDays Columbus

·1 min
As a developer, I always thought that security, like documentation, would be done by someone else. While that might have been true in the past, in today’s world that model no longer works. As a developer you’re responsible for the security of your app. Security in this case should be seen in the broadest sense of the word, ranging from licenses to software packages. A chef creating cheesecake has similar challenges. The ingredients of a cheesecake are similar to the software packages a developer uses. The preparation is similar to the DevOps pipeline, and recipe is similar to the licenses for developers. Messing up any of those means you have a messy kitchen, or a data breach!