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/builderstackIn 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-1The 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.0Then 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/1The 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