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 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.
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 to create a new account. It’s free forever for personal use! Once you’ve done that and installed the CLI 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).
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.
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>
.
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, 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.
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.
// 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.
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.
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!
$ 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.
Top comments (0)